/* l3lib.c * Library for the compilation of safe L3 * Author: Frank Pfenning, Fall 2007 */ extern void* calloc(unsigned int num_elts, unsigned int size); extern int raise(int sig); #define NULL 0L #define SIGSEGV 11 /* * Arithmetic operations that may be incorrectly optimized * by gcc with default optimizations enabled * For example: x/(-1) ==> -x or x/x ==> 1 or x<<32 ==> 0 */ int _idiv (int x, int y) { return x/y; } int _imod (int x, int y) { return x%y; } int _sal (int x, int y) { return x << y; } int _sar (int x, int y) { return x >> y; } /* * Replace lv /= e by _idiv_asn(&lv,e) and * similarly for %=, <<=, >>= */ void _idiv_asn (int* px, int y) { *px /= y; } void _imod_asn (int* px, int y) { *px %= y; } void _sal_asn (int* px, int y) { *px <<= y; } void _sar_asn (int* px, int y) { *px >>= y; } /* * compile e1[e2] to (tau)_sub(e1, e2, sizeof(tau)) * where e1 : tau[] */ void* _sub (int* A, int i, int elt_size) { if (i < 0 || i >= *A) raise(SIGSEGV); return (void *)(A+2+i*(elt_size/4)); } /* compile new(tau) to (tau*)_newptr(sizeof(tau)) */ void* _newptr (int elt_size) { int* p = calloc(1, elt_size); if (p == NULL) raise(SIGSEGV); return (void *)p; } /* compile new(tau[e]) to (int*)_newarray(e,sizeof(tau)) */ void* _newarray (int num, int elt_size) { if (num < 0 || num > (0x7FFFFFFF-8)/elt_size) raise(SIGSEGV); int* p = calloc(num*(elt_size/4)+2, sizeof(int)); if (p == NULL) raise(SIGSEGV); *p = num; /* initialize number of elements */ return (void *)p; } /* compile statement e; to _eval(0, e); to avoid gcc dead code elimination */ void _eval(int i, ...) { return; } /* * The remaining inequality and disequality functions are there to avoid * gcc optimization of, for example, *p == *p ==> 1 even if * p may be NULL */ int _eq_ptr (void* p, void* q) { return (p == q); } int _eq_int (int i, int j) { return (i == j); } int _noteq_ptr (void* p, void* q) { return (p != q); } int _noteq_int (int i, int j) { return (i != j); }