Tuesday, June 1, 2010

Types

The is a scandalously wasteful manner of representing primitive values like constants, but it works for the moment. Every constant is preceded with a header, describing the size, a record tag, a type tag, and a series of bits describing the value. On Intel 64 architectures, it wastes memory like hell.

/** 
 *  COPYRIGHT 2008, M.C.A. Devillers
 *
 *  THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
 *  EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 *
 *  Internally used types and conversions from them to native C types.
 *
 *  A number of these routines are added at the moment pure for 
 *  debugging purposes. It is expected the compiler compiles static 
 *  values to C static values.
 *
 *  A Hi value is either a constant, a record, or a thunk. They are
 *  tagged with record and type tags.
 *
 *  A type tag is a size bounded series of bits.
 *  
 *  t[0]    size of the tag (number of native_ints)
 *  t[1]    0
 *  t[2..]  bits which make up the tag
 *
 *  A constant is a size bounded, record and type tagged, series of
 *  bits.
 *
 *  c[0]    size of the constant (number of native_ints)
 *  c[1]    0
 *  c[2]    constant record field pointer
 *  c[3]    constant type field pointer
 *  c[4..]  bits which make up the constant (with unused extra bits)
 *
 *  A record is a size bounded, record and type tagged, series of
 *  pointers.
 *
 *  r[0]    size of the record (number of native_ints)
 *  r[1]    1
 *  r[2]    record record field pointer
 *  r[3]    record type field pointer
 *  r[4..]  pointers which make up the record
 *
 *  This encoding is pretty portable but uses a lot of bits. 
 *  For example, any simple integer value is encoded with 5 * 64 is 
 *  320 bytes on an Intel 64 bit system, not counting tags.
 *
 *  Bit packing, and using a seperate info record for rtti is for 
 *  later.
 *
 *  Assuming that most tags are shared, some of that burden is 
 *  aleviated. 
 */

#ifndef TYPES_H
#define TYPES_H

#include <stdlib.h>
#include <stdint.h>

 typedef uintptr_t native_int;

#define HI_SIZE(t) \
    ((sizeof(t) + sizeof(native_int) - 1)/(sizeof(native_int)))

typedef void                hi_void;

#if SCHAR_MAX == 127
typedef unsigned char       hi_uint8;
typedef signed char         hi_sint8;
#else
 #error "int8 size not supported"
#endif
#if SHRT_MAX == 32767
typedef unsigned short      hi_uint16;
typedef signed short        hi_sint16;
#elif INT_MAX == 32767
typedef unsigned int        hi_uint16;
typedef signed int          hi_sint16;
#else
 #error "int16 size not supported"
#endif
#if INT_MAX == 2147483647
typedef unsigned int        hi_uint32;
typedef signed int          hi_sint32;
#elif SHRT_MAX == 2147483647
typedef unsigned short      hi_uint32;
typedef signed short        hi_sint32;
#elif LONG_MAX == 2147483647
typedef unsigned long       hi_uint32;
typedef signed long         hi_sint32;
#else
 #error "int32 size not supported"
#endif
#if INT_MAX == 9223372036854775807
typedef unsigned int        hi_uint64;
typedef signed int          hi_sint64;
#elif LONG_MAX == 9223372036854775807
typedef unsigned long       hi_uint64;
typedef signed long         hi_sint64;
#else
 #error "int64 size not supported"
#endif
typedef float      hi_float;
typedef double     hi_double;
typedef void*      hi_pointer;


static native_int* system_bool_tag;
static native_int* system_char_tag;
static native_int* system_int_tag;
static native_int* system_float_tag;
static native_int* system_pointer_tag;
static native_int* system_false_tag;
static native_int* system_true_tag;


 native_int* convert_from_tag(char* v);
char*       convert_to_tag(native_int* v);


native_int* convert_from_uint8(hi_uint8 v);
native_int* convert_from_sint8(hi_sint8 v);
native_int* convert_from_uint16(hi_uint16 v);
native_int* convert_from_sint16(hi_sint16 v);
native_int* convert_from_uint32(hi_uint32 v);
native_int* convert_from_sint32(hi_sint32 v);
native_int* convert_from_uint64(hi_uint64 v);
native_int* convert_from_sint64(hi_sint64 v);
native_int* convert_from_float(hi_float v);
native_int* convert_from_double(hi_double v);
native_int* convert_from_pointer(hi_pointer v);
native_int* convert_from_string(char* v);

hi_uint8    convert_to_uint8(native_int* v);
hi_sint8    convert_to_sint8(native_int* v);
hi_uint16   convert_to_uint16(native_int* v);
hi_sint16   convert_to_sint16(native_int* v);
hi_uint32   convert_to_uint32(native_int* v);
hi_sint32   convert_to_sint32(native_int* v);
hi_uint64   convert_to_uint64(native_int* v);
hi_sint64   convert_to_sint64(native_int* v);
hi_float    convert_to_float(native_int* v);
hi_double   convert_to_double(native_int* v);
hi_pointer  convert_to_pointer(native_int* v);

char*       convert_to_string(native_int* v);
#endif // TYPES_H




/**
 *  COPYRIGHT 2008, M.C.A. Devillers
 *
 *  THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
 *  EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 *
 */
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "ffi.h"
#include "types.h"
static native_int system_bool[20] = {
    2 + (11 / sizeof(native_int)),
    0,
    (native_int) "system.bool"
};
static native_int* system_bool_tag = system_bool;
static native_int system_char[20] = {
    2 + (11 / sizeof(native_int)),
    0,
    (native_int) "system.char"
};
static native_int* system_char_tag = system_char;
static native_int system_int[20] = {
    2 + (10 / sizeof(native_int)),
    0,
    (native_int) "system.int"
};
static native_int* system_int_tag = system_int;
static native_int system_float[20] = {
    2 + (12 / sizeof(native_int)),
    20,
    0,
    (native_int) "system.float"
};
static native_int* system_float_tag = system_float;
static native_int system_string[20] = {
    2 + (12 / sizeof(native_int)),
    20,
    0,
    (native_int) "system.float"
};
static native_int* system_string_tag = system_string;
//////////////////////////////////////////////////////////////////////
native_int* convert_from_tag(char* v) {
    int v_len = strnlen(v, 2048);
    //v[v_len] = (char) 0;
    int sz = 2 + (v_len + sizeof(native_int))/sizeof(native_int);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = 0;
    char* p = (char*) &(n[2]);
    strcpy(p, v);
    return n;
}
char*       convert_to_tag(native_int* v) {
    char* p = (char*) (&(v[2]));
    return p;
}
//////////////////////////////////////////////////////////////////////
native_int* convert_from_uint8(hi_uint8 v) {
    int sz = 4 + HI_SIZE(hi_uint8);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = (native_int) system_int;
    n[3] = (native_int) system_int;
    n[4] = (native_int) v;
    return n;
}
native_int* convert_from_sint8(hi_sint8 v) {
    int sz = 4 + HI_SIZE(hi_sint8);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = (native_int) system_int;
    n[3] = (native_int) system_int;
    n[4] = (native_int) v;
    return n;
}
native_int* convert_from_uint16(hi_uint16 v) {
    int sz = 4 + HI_SIZE(hi_uint16);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = (native_int) system_int;
    n[3] = (native_int) system_int;
    n[4] = (native_int) v;
    return n;
}

native_int* convert_from_sint16(hi_sint16 v) {
    int sz = 4 + HI_SIZE(hi_sint16);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = (native_int) system_int;
    n[3] = (native_int) system_int;
    n[4] = (native_int) v;
    return n;
}

native_int* convert_from_uint32(hi_uint32 v) {
    int sz = 4 + HI_SIZE(hi_uint32);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = (native_int) system_int;
    n[3] = (native_int) system_int;
    n[4] = (native_int) v;
    return n;
}

native_int* convert_from_sint32(hi_sint32 v) {
    int sz = 4 + HI_SIZE(hi_sint32);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = (native_int) system_int;
    n[3] = (native_int) system_int;
    n[4] = (native_int) v;
    return n;
}

native_int* convert_from_uint64(hi_uint64 v) {
    int sz = 4 + HI_SIZE(hi_uint64);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = (native_int) system_int;
    n[3] = (native_int) system_int;
    hi_uint64* p = (hi_uint64*) &(n[4]);
    *p = v;
    return n;
}

native_int* convert_from_sint64(hi_sint64 v) {
    int sz = 4 + HI_SIZE(hi_sint64);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = (native_int) system_int;
    n[3] = (native_int) system_int;
    hi_sint64* p = (hi_uint64*) &(n[4]);
    *p = v;
    return n;
}

native_int* convert_from_float(hi_float v) {
    int sz = 4 + HI_SIZE(hi_float);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = (native_int) system_int;
    n[3] = (native_int) system_int;
    hi_float* p = (hi_float*) &(n[4]);
    *p = v;
    return n;
}

native_int* convert_from_double(hi_double v) {
    int sz = 4 + HI_SIZE(hi_double);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = (native_int) system_int;
    n[3] = (native_int) system_int;
    hi_double* p = (hi_double*) &(n[4]);
    *p = v;
    return n;
}

native_int* convert_from_pointer(hi_pointer v) {
    int sz = 4 + HI_SIZE(hi_pointer);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = (native_int) system_int;
    n[3] = (native_int) system_int;
    hi_pointer* p = (hi_pointer*) &(n[4]);
    *p = v;
    return n;
}

native_int* convert_from_string(char* v) {
    int v_len = strnlen(v, 2048);
    //v[v_len] = (char) 0;
    int sz = 4 + (v_len + sizeof(native_int))/sizeof(native_int);
    native_int* n = (native_int*) malloc(sz * sizeof(native_int));
    n[0] = sz;
    n[1] = 0;
    n[2] = (native_int) system_string;
    n[3] = (native_int) system_string;
    char* p = (char*) &(n[4]);
    strcpy(p, v);
    return n;
}

//////////////////////////////////////////////////////////////////////

hi_uint8    convert_to_uint8(native_int* v) {
    hi_uint8* p = (hi_uint8*) (&(v[4]));
    return *p;
}

hi_sint8    convert_to_sint8(native_int* v) {
    hi_sint8* p = (hi_sint8*) (&(v[4]));
    return *p;
}

hi_uint16   convert_to_uint16(native_int* v) {
    hi_uint16* p = (hi_uint16*) (&(v[4]));
    return *p;
}

hi_sint16   convert_to_sint16(native_int* v) {
    hi_sint16* p = (hi_sint16*) (&(v[4]));
    return *p;
}

hi_uint32   convert_to_uint32(native_int* v) {
    hi_uint32* p = (hi_uint32*) (&(v[4]));
    return *p;
}

hi_sint32   convert_to_sint32(native_int* v) {
    hi_sint32* p = (hi_sint32*) (&(v[4]));
    return *p;
}

hi_uint64   convert_to_uint64(native_int* v) {
    hi_uint64* p = (hi_uint64*) (&(v[4]));
    return *p;
}

hi_sint64   convert_to_sint64(native_int* v) {
    hi_sint64* p = (hi_sint64*) (&(v[4]));
    return *p;
}

hi_float    convert_to_float(native_int* v) {
    hi_float* p = (hi_float*) (&(v[4]));
    return *p;
}

hi_double   convert_to_double(native_int* v) {
    hi_double* p = (hi_double*) (&(v[4]));
    return *p;
}

hi_pointer  convert_to_pointer(native_int* v) {
    hi_pointer* p = (hi_pointer*) (&(v[4]));
    return *p;
}

char*       convert_to_string(native_int* v) {
    char* p = (char*) (&(v[4]));
    return p;
}
//////////////////////////////////////////////////////////////////////


Note, this is fresh code. Spotted some bugs in the tags.

No comments:

Post a Comment