1 /**************************************************************************/
2 /*                                                                        */
3 /*                                 OCaml                                  */
4 /*                                                                        */
5 /*          Xavier Leroy and Damien Doligez, INRIA Rocquencourt           */
6 /*                                                                        */
7 /*   Copyright 1996 Institut National de Recherche en Informatique et     */
8 /*     en Automatique.                                                    */
9 /*                                                                        */
10 /*   All rights reserved.  This file is distributed under the terms of    */
11 /*   the GNU Lesser General Public License version 2.1, with the          */
12 /*   special exception on linking described in the file LICENSE.          */
13 /*                                                                        */
14 /**************************************************************************/
15 
16 #ifndef CAML_MLVALUES_H
17 #define CAML_MLVALUES_H
18 
19 #ifndef CAML_NAME_SPACE
20 #include "compatibility.h"
21 #endif
22 #include "config.h"
23 #include "misc.h"
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 /* Definitions
30 
31   word: Four bytes on 32 and 16 bit architectures,
32         eight bytes on 64 bit architectures.
33   long: A C integer having the same number of bytes as a word.
34   val: The ML representation of something.  A long or a block or a pointer
35        outside the heap.  If it is a block, it is the (encoded) address
36        of an object.  If it is a long, it is encoded as well.
37   block: Something allocated.  It always has a header and some
38           fields or some number of bytes (a multiple of the word size).
39   field: A word-sized val which is part of a block.
40   bp: Pointer to the first byte of a block.  (a char *)
41   op: Pointer to the first field of a block.  (a value *)
42   hp: Pointer to the header of a block.  (a char *)
43   int32_t: Four bytes on all architectures.
44   int64_t: Eight bytes on all architectures.
45 
46   Remark: A block size is always a multiple of the word size, and at least
47           one word plus the header.
48 
49   bosize: Size (in bytes) of the "bytes" part.
50   wosize: Size (in words) of the "fields" part.
51   bhsize: Size (in bytes) of the block with its header.
52   whsize: Size (in words) of the block with its header.
53 
54   hd: A header.
55   tag: The value of the tag field of the header.
56   color: The value of the color field of the header.
57          This is for use only by the GC.
58 */
59 
60 typedef intnat value;
61 typedef uintnat header_t;
62 typedef uintnat mlsize_t;
63 typedef unsigned int tag_t;             /* Actually, an unsigned char */
64 typedef uintnat color_t;
65 typedef uintnat mark_t;
66 
67 /* Longs vs blocks. */
68 #define Is_long(x)   (((x) & 1) != 0)
69 #define Is_block(x)  (((x) & 1) == 0)
70 
71 /* Conversion macro names are always of the form  "to_from". */
72 /* Example: Val_long as in "Val from long" or "Val of long". */
73 #define Val_long(x)     ((intnat) (((uintnat)(x) << 1)) + 1)
74 #define Long_val(x)     ((x) >> 1)
75 #define Max_long (((intnat)1 << (8 * sizeof(value) - 2)) - 1)
76 #define Min_long (-((intnat)1 << (8 * sizeof(value) - 2)))
77 #define Val_int(x) Val_long(x)
78 #define Int_val(x) ((int) Long_val(x))
79 #define Unsigned_long_val(x) ((uintnat)(x) >> 1)
80 #define Unsigned_int_val(x)  ((int) Unsigned_long_val(x))
81 
82 /* Structure of the header:
83 
84 For 16-bit and 32-bit architectures:
85      +--------+-------+-----+
86      | wosize | color | tag |
87      +--------+-------+-----+
88 bits  31    10 9     8 7   0
89 
90 For 64-bit architectures:
91 
92      +--------+-------+-----+
93      | wosize | color | tag |
94      +--------+-------+-----+
95 bits  63    10 9     8 7   0
96 
97 For x86-64 with Spacetime profiling:
98   P = PROFINFO_WIDTH (as set by "configure", currently 26 bits, giving a
99     maximum block size of just under 4Gb)
100      +----------------+----------------+-------------+
101      | profiling info | wosize         | color | tag |
102      +----------------+----------------+-------------+
103 bits  63        (64-P) (63-P)        10 9     8 7   0
104 
105 */
106 
107 #define PROFINFO_SHIFT (64 - PROFINFO_WIDTH)
108 #define PROFINFO_MASK ((1ull << PROFINFO_WIDTH) - 1ull)
109 
110 #define Tag_hd(hd) ((tag_t) ((hd) & 0xFF))
111 #ifdef WITH_PROFINFO
112 #define Hd_no_profinfo(hd) ((hd) & ~(PROFINFO_MASK << PROFINFO_SHIFT))
113 #define Wosize_hd(hd) ((mlsize_t) ((Hd_no_profinfo(hd)) >> 10))
114 #else
115 #define Wosize_hd(hd) ((mlsize_t) ((hd) >> 10))
116 #endif /* WITH_PROFINFO */
117 #if defined(ARCH_SIXTYFOUR) && defined(WITH_PROFINFO)
118 /* [Profinfo_hd] is used when the compiler is not configured for Spacetime
119    (e.g. when decoding profiles). */
120 #define Profinfo_hd(hd) (((mlsize_t) ((hd) >> PROFINFO_SHIFT)) & PROFINFO_MASK)
121 #else
122 #define Profinfo_hd(hd) ((hd) & 0)
123 #endif /* ARCH_SIXTYFOUR && WITH_PROFINFO */
124 
125 #define Hd_val(val) (((header_t *) (val)) [-1])        /* Also an l-value. */
126 #define Hd_op(op) (Hd_val (op))                        /* Also an l-value. */
127 #define Hd_bp(bp) (Hd_val (bp))                        /* Also an l-value. */
128 #define Hd_hp(hp) (* ((header_t *) (hp)))              /* Also an l-value. */
129 #define Hp_val(val) (((header_t *) (val)) - 1)
130 #define Hp_op(op) (Hp_val (op))
131 #define Hp_bp(bp) (Hp_val (bp))
132 #define Val_op(op) ((value) (op))
133 #define Val_hp(hp) ((value) (((header_t *) (hp)) + 1))
134 #define Op_hp(hp) ((value *) Val_hp (hp))
135 #define Bp_hp(hp) ((char *) Val_hp (hp))
136 
137 #define Num_tags (1 << 8)
138 #ifdef ARCH_SIXTYFOUR
139 #define Max_wosize (((intnat)1 << (54-PROFINFO_WIDTH)) - 1)
140 #else
141 #define Max_wosize ((1 << 22) - 1)
142 #endif /* ARCH_SIXTYFOUR */
143 
144 #define Wosize_val(val) (Wosize_hd (Hd_val (val)))
145 #define Wosize_op(op) (Wosize_val (op))
146 #define Wosize_bp(bp) (Wosize_val (bp))
147 #define Wosize_hp(hp) (Wosize_hd (Hd_hp (hp)))
148 #define Whsize_wosize(sz) ((sz) + 1)
149 #define Wosize_whsize(sz) ((sz) - 1)
150 #define Wosize_bhsize(sz) ((sz) / sizeof (value) - 1)
151 #define Bsize_wsize(sz) ((sz) * sizeof (value))
152 #define Wsize_bsize(sz) ((sz) / sizeof (value))
153 #define Bhsize_wosize(sz) (Bsize_wsize (Whsize_wosize (sz)))
154 #define Bhsize_bosize(sz) ((sz) + sizeof (header_t))
155 #define Bosize_val(val) (Bsize_wsize (Wosize_val (val)))
156 #define Bosize_op(op) (Bosize_val (Val_op (op)))
157 #define Bosize_bp(bp) (Bosize_val (Val_bp (bp)))
158 #define Bosize_hd(hd) (Bsize_wsize (Wosize_hd (hd)))
159 #define Whsize_hp(hp) (Whsize_wosize (Wosize_hp (hp)))
160 #define Whsize_val(val) (Whsize_hp (Hp_val (val)))
161 #define Whsize_bp(bp) (Whsize_val (Val_bp (bp)))
162 #define Whsize_hd(hd) (Whsize_wosize (Wosize_hd (hd)))
163 #define Bhsize_hp(hp) (Bsize_wsize (Whsize_hp (hp)))
164 #define Bhsize_hd(hd) (Bsize_wsize (Whsize_hd (hd)))
165 
166 #define Profinfo_val(val) (Profinfo_hd (Hd_val (val)))
167 
168 #ifdef ARCH_BIG_ENDIAN
169 #define Tag_val(val) (((unsigned char *) (val)) [-1])
170                                                  /* Also an l-value. */
171 #define Tag_hp(hp) (((unsigned char *) (hp)) [sizeof(value)-1])
172                                                  /* Also an l-value. */
173 #else
174 #define Tag_val(val) (((unsigned char *) (val)) [-sizeof(value)])
175                                                  /* Also an l-value. */
176 #define Tag_hp(hp) (((unsigned char *) (hp)) [0])
177                                                  /* Also an l-value. */
178 #endif
179 
180 /* The lowest tag for blocks containing no value. */
181 #define No_scan_tag 251
182 
183 
184 /* 1- If tag < No_scan_tag : a tuple of fields.  */
185 
186 /* Pointer to the first field. */
187 #define Op_val(x) ((value *) (x))
188 /* Fields are numbered from 0. */
189 #define Field(x, i) (((value *)(x)) [i])           /* Also an l-value. */
190 
191 typedef int32_t opcode_t;
192 typedef opcode_t * code_t;
193 
194 /* NOTE: [Forward_tag] and [Infix_tag] must be just under
195    [No_scan_tag], with [Infix_tag] the lower one.
196    See [caml_oldify_one] in minor_gc.c for more details.
197 
198    NOTE: Update stdlib/obj.ml whenever you change the tags.
199  */
200 
201 /* Forward_tag: forwarding pointer that the GC may silently shortcut.
202    See stdlib/lazy.ml. */
203 #define Forward_tag 250
204 #define Forward_val(v) Field(v, 0)
205 
206 /* If tag == Infix_tag : an infix header inside a closure */
207 /* Infix_tag must be odd so that the infix header is scanned as an integer */
208 /* Infix_tag must be 1 modulo 4 and infix headers can only occur in blocks
209    with tag Closure_tag (see compact.c). */
210 
211 #define Infix_tag 249
212 #define Infix_offset_hd(hd) (Bosize_hd(hd))
213 #define Infix_offset_val(v) Infix_offset_hd(Hd_val(v))
214 
215 /* Another special case: objects */
216 #define Object_tag 248
217 #define Class_val(val) Field((val), 0)
218 #define Oid_val(val) Long_val(Field((val), 1))
219 CAMLextern value caml_get_public_method (value obj, value tag);
220 /* Called as:
221    caml_callback(caml_get_public_method(obj, caml_hash_variant(name)), obj) */
222 /* caml_get_public_method returns 0 if tag not in the table.
223    Note however that tags being hashed, same tag does not necessarily mean
224    same method name. */
225 
226 /* Special case of tuples of fields: closures */
227 #define Closure_tag 247
228 #define Code_val(val) (((code_t *) (val)) [0])     /* Also an l-value. */
229 
230 /* This tag is used (with Forward_tag) to implement lazy values.
231    See major_gc.c and stdlib/lazy.ml. */
232 #define Lazy_tag 246
233 
234 /* Another special case: variants */
235 CAMLextern value caml_hash_variant(char const * tag);
236 
237 /* 2- If tag >= No_scan_tag : a sequence of bytes. */
238 
239 /* Pointer to the first byte */
240 #define Bp_val(v) ((char *) (v))
241 #define Val_bp(p) ((value) (p))
242 /* Bytes are numbered from 0. */
243 #define Byte(x, i) (((char *) (x)) [i])            /* Also an l-value. */
244 #define Byte_u(x, i) (((unsigned char *) (x)) [i]) /* Also an l-value. */
245 
246 /* Abstract things.  Their contents is not traced by the GC; therefore they
247    must not contain any [value]. Must have odd number so that headers with
248    this tag cannot be mistaken for pointers (see caml_obj_truncate).
249 */
250 #define Abstract_tag 251
251 #define Data_abstract_val(v) ((void*) Op_val(v))
252 
253 /* Strings. */
254 #define String_tag 252
255 #define String_val(x) ((char *) Bp_val(x))
256 CAMLextern mlsize_t caml_string_length (value);   /* size in bytes */
257 CAMLextern int caml_string_is_c_safe (value);
258   /* true if string contains no '\0' null characters */
259 
260 /* Floating-point numbers. */
261 #define Double_tag 253
262 #define Double_wosize ((sizeof(double) / sizeof(value)))
263 #ifndef ARCH_ALIGN_DOUBLE
264 #define Double_val(v) (* (double *)(v))
265 #define Store_double_val(v,d) (* (double *)(v) = (d))
266 #else
267 CAMLextern double caml_Double_val (value);
268 CAMLextern void caml_Store_double_val (value,double);
269 #define Double_val(v) caml_Double_val(v)
270 #define Store_double_val(v,d) caml_Store_double_val(v,d)
271 #endif
272 
273 /* Arrays of floating-point numbers. */
274 #define Double_array_tag 254
275 #define Double_field(v,i) Double_val((value)((double *)(v) + (i)))
276 #define Store_double_field(v,i,d) do{ \
277   mlsize_t caml__temp_i = (i); \
278   double caml__temp_d = (d); \
279   Store_double_val((value)((double *) (v) + caml__temp_i), caml__temp_d); \
280 }while(0)
281 CAMLextern mlsize_t caml_array_length (value);   /* size in items */
282 CAMLextern int caml_is_double_array (value);   /* 0 is false, 1 is true */
283 
284 
285 /* Custom blocks.  They contain a pointer to a "method suite"
286    of functions (for finalization, comparison, hashing, etc)
287    followed by raw data.  The contents of custom blocks is not traced by
288    the GC; therefore, they must not contain any [value].
289    See [custom.h] for operations on method suites. */
290 #define Custom_tag 255
291 #define Data_custom_val(v) ((void *) &Field((v), 1))
292 struct custom_operations;       /* defined in [custom.h] */
293 
294 /* Int32.t, Int64.t and Nativeint.t are represented as custom blocks. */
295 
296 #define Int32_val(v) (*((int32_t *) Data_custom_val(v)))
297 #define Nativeint_val(v) (*((intnat *) Data_custom_val(v)))
298 #ifndef ARCH_ALIGN_INT64
299 #define Int64_val(v) (*((int64_t *) Data_custom_val(v)))
300 #else
301 CAMLextern int64_t caml_Int64_val(value v);
302 #define Int64_val(v) caml_Int64_val(v)
303 #endif
304 
305 /* 3- Atoms are 0-tuples.  They are statically allocated once and for all. */
306 
307 CAMLextern header_t caml_atom_table[];
308 #define Atom(tag) (Val_hp (&(caml_atom_table [(tag)])))
309 
310 /* Booleans are integers 0 or 1 */
311 
312 #define Val_bool(x) Val_int((x) != 0)
313 #define Bool_val(x) Int_val(x)
314 #define Val_false Val_int(0)
315 #define Val_true Val_int(1)
316 #define Val_not(x) (Val_false + Val_true - (x))
317 
318 /* The unit value is 0 (tagged) */
319 
320 #define Val_unit Val_int(0)
321 
322 /* List constructors */
323 #define Val_emptylist Val_int(0)
324 #define Tag_cons 0
325 
326 /* The table of global identifiers */
327 
328 extern value caml_global_data;
329 
330 CAMLextern value caml_set_oo_id(value obj);
331 
332 #ifdef __cplusplus
333 }
334 #endif
335 
336 #endif /* CAML_MLVALUES_H */
337