diff options
-rw-r--r-- | byterun/alloc.c | 21 | ||||
-rw-r--r-- | byterun/alloc.h | 7 | ||||
-rw-r--r-- | byterun/config.h | 32 | ||||
-rw-r--r-- | byterun/custom.c | 21 | ||||
-rw-r--r-- | byterun/custom.h | 10 | ||||
-rw-r--r-- | byterun/ints.c | 445 | ||||
-rw-r--r-- | byterun/major_gc.c | 2 | ||||
-rw-r--r-- | byterun/mlvalues.h | 18 | ||||
-rw-r--r-- | config/auto-aux/longlong.c | 32 | ||||
-rw-r--r-- | config/m-templ.h | 5 | ||||
-rwxr-xr-x | configure | 10 |
11 files changed, 503 insertions, 100 deletions
diff --git a/byterun/alloc.c b/byterun/alloc.c index 7a979f519..ebe9961d3 100644 --- a/byterun/alloc.c +++ b/byterun/alloc.c @@ -79,27 +79,6 @@ value alloc_string (mlsize_t len) return result; } -value alloc_custom(struct custom_operations * ops, - unsigned long size, - mlsize_t mem, - mlsize_t max) -{ - mlsize_t wosize; - value result; - - wosize = 1 + (size + sizeof(value) - 1) / sizeof(value); - if (ops->finalize == NULL && wosize <= Max_young_wosize) { - result = alloc_small(wosize, Custom_tag); - Custom_ops_val(result) = ops; - } else { - result = alloc_shr(wosize, Custom_tag); - Custom_ops_val(result) = ops; - adjust_gc_speed(mem, max); - result = check_urgent_gc(result); - } - return result; -} - value alloc_final (mlsize_t len, final_fun fun, mlsize_t mem, mlsize_t max) { return alloc_custom(final_custom_operations(fun), diff --git a/byterun/alloc.h b/byterun/alloc.h index 39a8797d5..e43af968b 100644 --- a/byterun/alloc.h +++ b/byterun/alloc.h @@ -26,13 +26,10 @@ value alloc_string (mlsize_t); value copy_string (char *); value copy_string_array (char **); value copy_double (double); +value copy_int32 (int32); /* defined in [ints.c] */ +value copy_int64 (int64); /* defined in [ints.c] */ value alloc_array (value (*funct) (char *), char ** array); -value alloc_custom(struct custom_operations * ops, - unsigned long size, /*size in bytes*/ - mlsize_t mem, /*resources consumed*/ - mlsize_t max /*max resources*/); - typedef void (*final_fun)(value); value alloc_final (mlsize_t /*size in words*/, final_fun, /*finalization function*/ diff --git a/byterun/config.h b/byterun/config.h index f8a60c1a5..8393a26be 100644 --- a/byterun/config.h +++ b/byterun/config.h @@ -23,6 +23,35 @@ #include "::config:sm-Mac.h" #endif +/* Types for signed chars, 32-bit integers, 64-bit integers */ + +typedef signed char schar; + +#if SIZEOF_INT == 4 +typedef int int32; +typedef unsigned int uint32; +#elif SIZEOF_LONG == 4 +typedef long int32; +typedef unsigned long uint32; +#elif SIZEOF_SHORT == 4 +typedef short int32; +typedef unsigned short uint32; +#endif + +#if SIZEOF_LONG == 8 +typedef long int64; +typedef unsigned long uint64; +#elif SIZEOF_LONG_LONG == 8 +typedef long long int64; +typedef unsigned long long uint64; +#else +/* Int64.t will not be supported, and operations over it are not defined, + but we must define the types int64 and uint64 as 64-bit placeholders. */ +typedef struct { uint32 a, b; } uint64; +typedef uint64 int64; +#endif + + /* Library dependencies */ #ifdef HAS_MEMMOVE @@ -48,9 +77,6 @@ #define THREADED_CODE #endif -/* Signed char type */ - -typedef signed char schar; /* Do not change this definition. */ #define Page_size (1 << Page_log) diff --git a/byterun/custom.c b/byterun/custom.c index 1c013ceab..3f36a9b66 100644 --- a/byterun/custom.c +++ b/byterun/custom.c @@ -18,6 +18,27 @@ #include "memory.h" #include "mlvalues.h" +value alloc_custom(struct custom_operations * ops, + unsigned long size, + mlsize_t mem, + mlsize_t max) +{ + mlsize_t wosize; + value result; + + wosize = 1 + (size + sizeof(value) - 1) / sizeof(value); + if (ops->finalize == NULL && wosize <= Max_young_wosize) { + result = alloc_small(wosize, Custom_tag); + Custom_ops_val(result) = ops; + } else { + result = alloc_shr(wosize, Custom_tag); + Custom_ops_val(result) = ops; + adjust_gc_speed(mem, max); + result = check_urgent_gc(result); + } + return result; +} + int custom_compare_default(value v1, value v2) { failwith("equal: abstract value"); diff --git a/byterun/custom.h b/byterun/custom.h index 6f1d7f324..72b9f884f 100644 --- a/byterun/custom.h +++ b/byterun/custom.h @@ -38,7 +38,13 @@ extern void custom_serialize_default(value v, unsigned long * wsize_32, #define Custom_ops_val(v) (*((struct custom_operations **) (v))) -extern void register_custom_operations(struct custom_operations * ops); -extern struct custom_operations * find_custom_operations(char * ident); +value alloc_custom(struct custom_operations * ops, + unsigned long size, /*size in bytes*/ + mlsize_t mem, /*resources consumed*/ + mlsize_t max /*max resources*/); + +void register_custom_operations(struct custom_operations * ops); +struct custom_operations * find_custom_operations(char * ident); +struct custom_operations * final_custom_operations(void (*fn)(value)); #endif diff --git a/byterun/ints.c b/byterun/ints.c index 6019fd01e..d6afe0976 100644 --- a/byterun/ints.c +++ b/byterun/ints.c @@ -15,66 +15,93 @@ #include <stdio.h> #include <string.h> #include "alloc.h" +#include "custom.h" #include "fail.h" +#include "intext.h" #include "memory.h" #include "misc.h" #include "mlvalues.h" -value int_of_string(value s) /* ML */ +static char * parse_sign_and_base(char * p, + /*out*/ int * base, + /*out*/ int * sign) { - long res; - int sign; - int base; - char * p; - int c, d; - - p = String_val(s); - if (*p == 0) failwith("int_of_string"); - sign = 1; + *sign = 1; if (*p == '-') { - sign = -1; + *sign = -1; p++; } - base = 10; + *base = 10; if (*p == '0') { switch (p[1]) { case 'x': case 'X': - base = 16; p += 2; break; + *base = 16; p += 2; break; case 'o': case 'O': - base = 8; p += 2; break; + *base = 8; p += 2; break; case 'b': case 'B': - base = 2; p += 2; break; + *base = 2; p += 2; break; } } - res = 0; - while (1) { - c = *p; - if (c >= '0' && c <= '9') - d = c - '0'; - else if (c >= 'A' && c <= 'F') - d = c - 'A' + 10; - else if (c >= 'a' && c <= 'f') - d = c - 'a' + 10; - else - break; - if (d >= base) break; + return p; +} + +static int parse_digit(char * p) +{ + int c = *p; + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else + return -1; +} + +static long parse_long(char * p) +{ + unsigned long res; + int sign, base, d; + + p = parse_sign_and_base(p, &base, &sign); + for (res = 0; /*nothing*/; p++) { + d = parse_digit(p); + if (d < 0) break; res = base * res + d; - p++; } - if (*p != 0) - failwith("int_of_string"); - return Val_long(sign < 0 ? -res : res); + if (*p != 0) failwith("int_of_string"); + return sign < 0 ? -((long) res) : (long) res; } -value format_int(value fmt, value arg) /* ML */ +value int_of_string(value s) /* ML */ { - char format_string[32], format_buffer[32]; - int prec; + return Val_long(parse_long(String_val(s))); +} + +#define FORMAT_BUFFER_SIZE 32 + +static char * parse_format(value fmt, + char * suffix, + char format_string[], + char default_format_buffer[]) +{ + int prec, lastletter; char * p; - char * dest; - mlsize_t len; - value res; + mlsize_t len, len_suffix; + /* Copy Caml format fmt to format_string, + adding the suffix before the last letter of the format */ + len = string_length(fmt); + len_suffix = strlen(suffix); + if (len + len_suffix + 1 >= FORMAT_BUFFER_SIZE) + invalid_argument("format_int: format too long"); + bcopy(String_val(fmt), format_string, len); + p = format_string + len - 1; + lastletter = *p; + bcopy(suffix, p, len_suffix); p += len_suffix; + *p++ = lastletter; + *p = 0; + /* Determine space needed for result and allocate it dynamically if needed */ prec = 32; for (p = String_val(fmt); *p != 0; p++) { if (*p >= '0' && *p <= '9') { @@ -82,22 +109,332 @@ value format_int(value fmt, value arg) /* ML */ break; } } - if (prec <= sizeof(format_buffer)) { - dest = format_buffer; - } else { - dest = stat_alloc(prec); - } - len = string_length(fmt); - if (len >= sizeof(format_string) - 1) - invalid_argument("format_int: format too long"); - bcopy(String_val(fmt), format_string, len); - format_string[len + 1] = 0; - format_string[len] = format_string[len - 1]; - format_string[len - 1] = 'l'; - sprintf(dest, format_string, Long_val(arg)); - res = copy_string(dest); - if (dest != format_buffer) { - stat_free(dest); - } + if (prec < FORMAT_BUFFER_SIZE) + return default_format_buffer; + else + return stat_alloc(prec + 1); +} + +value format_int(value fmt, value arg) /* ML */ +{ + char format_string[32], default_format_buffer[32]; + char * buffer; + value res; + + buffer = parse_format(fmt, "l", format_string, default_format_buffer); + sprintf(buffer, format_string, Long_val(arg)); + res = copy_string(buffer); + if (buffer != default_format_buffer) stat_free(buffer); + return res; +} + +/* 32-bit integers */ + +static int int32_compare(value v1, value v2) +{ + int32 i1 = Int32_val(v1); + int32 i2 = Int32_val(v2); + return i1 == i2 ? 0 : i1 < i2 ? -1 : 1; +} + +static long int32_hash(value v) +{ + return Int32_val(v); +} + +static void int32_serialize(value v, unsigned long * wsize_32, + unsigned long * wsize_64) +{ + serialize_int_4(Int32_val(v)); + *wsize_32 = *wsize_64 = 4; +} + +static unsigned long int32_deserialize(void * dst) +{ + *((int32 *) dst) = deserialize_sint_4(); + return 4; +} + +static struct custom_operations int32_ops = { + "_i", + custom_finalize_default, + int32_compare, + int32_hash, + int32_serialize, + int32_deserialize +}; + +value copy_int32(int32 i) +{ + value res = alloc_custom(&int32_ops, 4, 0, 1); + Int32_val(res) = i; + return res; +} + +value int32_neg(value v) /* ML */ +{ return copy_int32(- Int32_val(v)); } + +value int32_add(value v1, value v2) /* ML */ +{ return copy_int32(Int32_val(v1) + Int32_val(v2)); } + +value int32_sub(value v1, value v2) /* ML */ +{ return copy_int32(Int32_val(v1) - Int32_val(v2)); } + +value int32_mul(value v1, value v2) /* ML */ +{ return copy_int32(Int32_val(v1) * Int32_val(v2)); } + +value int32_div(value v1, value v2) /* ML */ +{ + int32 divisor = Int32_val(v2); + if (divisor == 0) raise_zero_divide(); + return copy_int32(Int32_val(v1) / divisor); +} + +value int32_mod(value v1, value v2) /* ML */ +{ + int32 divisor = Int32_val(v2); + if (divisor == 0) raise_zero_divide(); + return copy_int32(Int32_val(v1) % divisor); +} + +value int32_and(value v1, value v2) /* ML */ +{ return copy_int32(Int32_val(v1) & Int32_val(v2)); } + +value int32_or(value v1, value v2) /* ML */ +{ return copy_int32(Int32_val(v1) | Int32_val(v2)); } + +value int32_xor(value v1, value v2) /* ML */ +{ return copy_int32(Int32_val(v1) ^ Int32_val(v2)); } + +value int32_shift_left(value v1, value v2) /* ML */ +{ return copy_int32(Int32_val(v1) << Int_val(v2)); } + +value int32_shift_right(value v1, value v2) /* ML */ +{ return copy_int32(Int32_val(v1) >> Int_val(v2)); } + +value int32_shift_right_unsigned(value v1, value v2) /* ML */ +{ return copy_int32((uint32)Int32_val(v1) >> Int_val(v2)); } + +value int32_of_int(value v) /* ML */ +{ return copy_int32(Long_val(v)); } + +value int32_to_int(value v) /* ML */ +{ return Val_long(Int32_val(v)); } + +value format_int32(value fmt, value arg) /* ML */ +{ + char format_string[32], default_format_buffer[32]; + char * buffer; + value res; + + buffer = parse_format(fmt, "l", format_string, default_format_buffer); + sprintf(buffer, format_string, (long) Int32_val(arg)); + res = copy_string(buffer); + if (buffer != default_format_buffer) stat_free(buffer); + return res; +} + +value int32_of_string(value s) /* ML */ +{ + return copy_int32(parse_long(String_val(s))); +} + +/* 64-bit integers */ + +#if SIZEOF_LONG == 8 || SIZEOF_LONG_LONG == 8 + +static int int64_compare(value v1, value v2) +{ + int64 i1 = Int64_val(v1); + int64 i2 = Int64_val(v2); + return i1 == i2 ? 0 : i1 < i2 ? -1 : 1; +} + +static long int64_hash(value v) +{ + return (long) Int64_val(v); +} + +static void int64_serialize(value v, unsigned long * wsize_32, + unsigned long * wsize_64) +{ + serialize_int_8(Int64_val(v)); + *wsize_64 = *wsize_64 = 8; +} + +static unsigned long int64_deserialize(void * dst) +{ + *((int64 *) dst) = deserialize_sint_8(); + return 8; +} + +static struct custom_operations int64_ops = { + "_i", + custom_finalize_default, + int64_compare, + int64_hash, + int64_serialize, + int64_deserialize +}; + +value copy_int64(int64 i) +{ + value res = alloc_custom(&int64_ops, 4, 0, 1); + Int64_val(res) = i; + return res; +} + +value int64_neg(value v) /* ML */ +{ return copy_int64(- Int64_val(v)); } + +value int64_add(value v1, value v2) /* ML */ +{ return copy_int64(Int64_val(v1) + Int64_val(v2)); } + +value int64_sub(value v1, value v2) /* ML */ +{ return copy_int64(Int64_val(v1) - Int64_val(v2)); } + +value int64_mul(value v1, value v2) /* ML */ +{ return copy_int64(Int64_val(v1) * Int64_val(v2)); } + +value int64_div(value v1, value v2) /* ML */ +{ + int64 divisor = Int64_val(v2); + if (divisor == 0) raise_zero_divide(); + return copy_int64(Int64_val(v1) / divisor); +} + +value int64_mod(value v1, value v2) /* ML */ +{ + int64 divisor = Int64_val(v2); + if (divisor == 0) raise_zero_divide(); + return copy_int64(Int64_val(v1) % divisor); +} + +value int64_and(value v1, value v2) /* ML */ +{ return copy_int64(Int64_val(v1) & Int64_val(v2)); } + +value int64_or(value v1, value v2) /* ML */ +{ return copy_int64(Int64_val(v1) | Int64_val(v2)); } + +value int64_xor(value v1, value v2) /* ML */ +{ return copy_int64(Int64_val(v1) ^ Int64_val(v2)); } + +value int64_shift_left(value v1, value v2) /* ML */ +{ return copy_int64(Int64_val(v1) << Int_val(v2)); } + +value int64_shift_right(value v1, value v2) /* ML */ +{ return copy_int64(Int64_val(v1) >> Int_val(v2)); } + +value int64_shift_right_unsigned(value v1, value v2) /* ML */ +{ return copy_int64((uint64)Int64_val(v1) >> Int_val(v2)); } + +value int64_of_int(value v) /* ML */ +{ return copy_int64(Long_val(v)); } + +value int64_to_int(value v) /* ML */ +{ return Val_long((long) Int64_val(v)); } + +value int64_of_int32(value v) /* ML */ +{ return copy_int64(Int32_val(v)); } + +value int64_to_int32(value v) /* ML */ +{ return copy_int32((int32) Int64_val(v)); } + +value format_int64(value fmt, value arg) /* ML */ +{ + char format_string[64], default_format_buffer[64]; + char * buffer; + value res; + + buffer = parse_format(fmt, +#if SIZEOF_LONG == 8 + "l", +#else + "ll", +#endif + format_string, default_format_buffer); + sprintf(buffer, format_string, Int64_val(arg)); + res = copy_string(buffer); + if (buffer != default_format_buffer) stat_free(buffer); return res; } + +value int64_of_string(value s) /* ML */ +{ + char * p; + uint64 res; + int sign, base, d; + + p = parse_sign_and_base(String_val(s), &base, &sign); + for (res = 0; /*nothing*/; p++) { + d = parse_digit(p); + if (d < 0) break; + res = base * res + d; + } + if (*p != 0) failwith("Int64.of_string"); + return copy_int64(sign < 0 ? -((int64) res) : (int64) res); +} + +#else + +static char int64_error[] = + "The type Int64.t is not supported on this platform"; + +value copy_int64(int64 i) +{ invalid_arg(int64_error); } + +value int64_neg(value v) +{ invalid_arg(int64_error); } + +value int64_add(value v1, value v2) +{ invalid_arg(int64_error); } + +value int64_sub(value v1, value v2) +{ invalid_arg(int64_error); } + +value int64_mul(value v1, value v2) +{ invalid_arg(int64_error); } + +value int64_div(value v1, value v2) +{ invalid_arg(int64_error); } + +value int64_mod(value v1, value v2) +{ invalid_arg(int64_error); } + +value int64_and(value v1, value v2) +{ invalid_arg(int64_error); } + +value int64_or(value v1, value v2) +{ invalid_arg(int64_error); } + +value int64_xor(value v1, value v2) +{ invalid_arg(int64_error); } + +value int64_shift_left(value v1, value v2) +{ invalid_arg(int64_error); } + +value int64_shift_right(value v1, value v2) +{ invalid_arg(int64_error); } + +value int64_shift_right_unsigned(value v1, value v2) +{ invalid_arg(int64_error); } + +value int64_of_int(value v) +{ invalid_arg(int64_error); } + +value int64_to_int(value v) +{ invalid_arg(int64_error); } + +value int64_of_int32(value v) +{ invalid_arg(int64_error); } + +value int64_to_int32(value v) +{ invalid_arg(int64_error); } + +value format_int64(value fmt, value arg) +{ invalid_arg(int64_error); } + +value int64_of_string(value s) +{ invalid_arg(int64_error); } + +#endif diff --git a/byterun/major_gc.c b/byterun/major_gc.c index 8435d1645..0925eeba8 100644 --- a/byterun/major_gc.c +++ b/byterun/major_gc.c @@ -228,7 +228,7 @@ static void sweep_slice (long int work) switch (Color_hd (hd)){ case Caml_white: if (Tag_hd (hd) == Custom_tag){ - void (*final_fun)(value) = Custom_ops_val(Val_hp(hp)); + void (*final_fun)(value) = Custom_ops_val(Val_hp(hp))->finalize; if (final_fun != NULL) final_fun(Val_hp(hp)); } gc_sweep_hp = fl_merge_block (Bp_hp (hp)); diff --git a/byterun/mlvalues.h b/byterun/mlvalues.h index 6c66492cc..a45111341 100644 --- a/byterun/mlvalues.h +++ b/byterun/mlvalues.h @@ -57,20 +57,6 @@ typedef unsigned int tag_t; /* Actually, an unsigned char */ typedef unsigned long color_t; typedef unsigned long mark_t; -#if SIZEOF_INT == 4 -typedef int int32; -typedef unsigned int uint32; -#elif SIZEOF_LONG == 4 -typedef long int32; -typedef unsigned long uint32; -#elif SIZEOF_SHORT == 4 -typedef short int32; -typedef unsigned short uint32; -#endif - -typedef long int64; /* FIXME */ -typedef unsigned long uint64; /* FIXME */ - /* Longs vs blocks. */ #define Is_long(x) (((x) & 1) != 0) #define Is_block(x) (((x) & 1) == 0) @@ -235,6 +221,10 @@ void Store_double_val (value,double); #define Data_custom_val(v) ((void *) &Field(v, 1)) struct custom_operations; /* defined in [custom.h] */ +/* Int32.t and Int64.t are represented as custom blocks. */ + +#define Int32_val(v) (*((int32 *) Data_custom_val(v))) +#define Int64_val(v) (*((int64 *) Data_custom_val(v))) /* 3- Atoms are 0-tuples. They are statically allocated once and for all. */ diff --git a/config/auto-aux/longlong.c b/config/auto-aux/longlong.c new file mode 100644 index 000000000..92b4efdbf --- /dev/null +++ b/config/auto-aux/longlong.c @@ -0,0 +1,32 @@ +/***********************************************************************/ +/* */ +/* Objective Caml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. All rights reserved. This file is distributed */ +/* under the terms of the GNU Library General Public License. */ +/* */ +/***********************************************************************/ + +/* $Id$ */ + +#include <stdio.h> +#include <string.h> + +/* Check for the availability of "long long" type as per ISO C9X */ + +int main(int argc, char **argv) +{ + long long l; + unsigned long long u; + char buffer[64]; + + if (sizeof(long long) != 8) return 1; + l = 123456789123456789LL; + buffer[0] = 0; + sprintf(buffer, "%lld", l); + if (strcmp(buffer, "123456789123456789") != 0) return 1; + return 0; +} diff --git a/config/m-templ.h b/config/m-templ.h index c54dd1c4f..480bd952a 100644 --- a/config/m-templ.h +++ b/config/m-templ.h @@ -47,3 +47,8 @@ /* Define SIZEOF_INT, SIZEOF_LONG and SIZEOF_SHORT to the sizes in byte of the C types "int", "long" and "short", respectively. */ + +#define SIZEOF_LONG_LONG 8 + +/* Define SIZEOF_LONG_LONG to the size in byte of the C type "long long", + if supported by the C compiler. Otherwise, define SIZEOF_LONG_LONG as 0. */ @@ -261,6 +261,16 @@ echo "#define SIZEOF_INT $1" >> m.h echo "#define SIZEOF_LONG $2" >> m.h echo "#define SIZEOF_SHORT $4" >> m.h +if test $1 != 8; then + sh ./runtest longlong.c + case $? in + 0) echo "64-bit \"long long\" integer type found." + echo "#define SIZEOF_LONG_LONG 8" >> m.h;; + *) echo "No suitable 64-bit integer type found, Int64.t will not be supported." + echo "#define SIZEOF_LONG_LONG 0" >> m.h;; + esac +fi + # Determine endianness sh ./runtest endian.c |