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