Przeglądaj źródła

partial OO support

Nicolas Cannasse 10 lat temu
rodzic
commit
049db45174
6 zmienionych plików z 185 dodań i 26 usunięć
  1. 26 3
      src/alloc.c
  2. 2 0
      src/code.c
  3. 45 12
      src/hl.h
  4. 49 8
      src/jit.c
  5. 1 1
      src/main.c
  6. 62 2
      src/module.c

+ 26 - 3
src/alloc.c

@@ -117,6 +117,15 @@ void *hl_alloc_executable_memory( int size ) {
 #endif
 }
 
+void hl_free_executable_memory( void *c ) {
+#ifdef HL_WIN
+	VirtualFree(c,0,MEM_RELEASE);
+#else
+	printf("NOT IMPLEMENTED\n");
+	return NULL;
+#endif
+}
+
 vdynamic *hl_alloc_dynamic( hl_type *t ) {
 	vdynamic *d = (vdynamic*)malloc(sizeof(vdynamic));
 	d->t = t;
@@ -124,9 +133,23 @@ vdynamic *hl_alloc_dynamic( hl_type *t ) {
 	return d;
 }
 
-vobj *hl_alloc_obj( hl_module *m, hl_type_obj *t ) {
-	printf("TODO");
-	return NULL;
+vobj *hl_alloc_obj( hl_module *m, hl_type *t ) {
+	vobj *o;
+	int size;
+	hl_runtime_obj *rt = t->obj->rt;
+	if( rt == NULL || rt->proto == NULL ) rt = hl_get_obj_proto(m,t);
+	size = rt->size;
+	if( size & (HL_WSIZE-1) ) size += HL_WSIZE - (size & (HL_WSIZE-1));
+	o = (vobj*)malloc(size);
+	memset(o,0,size);
+	o->proto = rt->proto;
+	return o;
+}
+
+vclosure *hl_alloc_closure_void( hl_module *m, int_val fid ) {
+	vclosure *c = (vclosure*)malloc(sizeof(vclosure));
+	c->fun = m->functions_ptrs[fid];
+	return c;
 }
 
 void hl_call( void *f ) {

+ 2 - 0
src/code.c

@@ -173,6 +173,7 @@ static void hl_read_type( hl_reader *r, hl_type *t ) {
 			t->obj->nproto = nproto;
 			t->obj->fields = (hl_obj_field*)hl_malloc(&r->code->alloc,sizeof(hl_obj_field)*nfields);
 			t->obj->proto = (hl_obj_proto*)hl_malloc(&r->code->alloc,sizeof(hl_obj_proto)*nproto);
+			t->obj->rt = NULL;
 			for(i=0;i<nfields;i++) {
 				hl_obj_field *f = t->obj->fields + i;
 				f->name = hl_get_string(r);
@@ -182,6 +183,7 @@ static void hl_read_type( hl_reader *r, hl_type *t ) {
 				hl_obj_proto *p = t->obj->proto + i;
 				p->name = hl_get_string(r);
 				p->findex = UINDEX();
+				p->pindex = INDEX();
 			}
 		}
 	default:

+ 45 - 12
src/hl.h

@@ -93,6 +93,7 @@ typedef enum {
 } hl_type_kind;
 
 typedef struct hl_type hl_type;
+typedef struct hl_runtime_obj hl_runtime_obj;
 
 typedef struct {
 	int nargs;
@@ -108,6 +109,7 @@ typedef struct {
 typedef struct {
 	const char *name;
 	int findex;
+	int pindex;
 } hl_obj_proto;
 
 typedef struct {
@@ -117,6 +119,7 @@ typedef struct {
 	hl_type *super;
 	hl_obj_field *fields;
 	hl_obj_proto *proto;
+	hl_runtime_obj *rt;
 } hl_type_obj;
 
 struct hl_type {
@@ -202,6 +205,8 @@ const char* hl_op_name( int op );
 hl_module *hl_module_alloc( hl_code *code );
 int hl_module_init( hl_module *m );
 void hl_module_free( hl_module *m );
+hl_runtime_obj *hl_get_obj_rt( hl_module *m, hl_type *ot );
+hl_runtime_obj *hl_get_obj_proto( hl_module *m, hl_type *ot );
 
 jit_ctx *hl_jit_alloc();
 void hl_jit_free( jit_ctx *ctx );
@@ -210,31 +215,59 @@ void *hl_jit_code( jit_ctx *ctx, hl_module *m );
 
 /* -------------------- RUNTIME ------------------------------ */
 
+typedef struct vobj vobj;
+typedef struct vclosure vclosure;
+
+typedef union {
+	int i;
+	float f;
+	double d;
+	vobj *o;
+	vclosure *c;
+	void *ptr;
+} value;
+
 typedef struct {
 	hl_type *t;
 #	ifndef HL_64
 	int __pad; // force align
 #	endif
-	union {
-		double d;
-		float f;
-		int i;
-		void *ptr;
-	} v;
+	value v;
 } vdynamic;
 
-typedef struct vobj_proto vobj_proto;
-
-struct vobj_proto {
+typedef struct {
 	hl_type *t;
+} vobj_proto;
+
+struct vobj {
+	vobj_proto *proto;
 };
 
-typedef struct {
+struct vclosure {
+	void *fun;
+};
+
+struct hl_runtime_obj {
+	int nfields; // absolute
+	int nproto;  // absolute
+	int size;
+	int *fields_indexes;
 	vobj_proto *proto;
-} vobj;
+};
+
+void *hl_alloc_executable_memory( int size );
+void hl_free_executable_memory( void *ptr );
 
 void hl_call( void *f );
 vdynamic *hl_alloc_dynamic( hl_type *t );
-vobj *hl_alloc_obj( hl_module *m, hl_type_obj *o );
+vobj *hl_alloc_obj( hl_module *m, hl_type *t );
+
+vclosure *hl_alloc_closure_void( hl_module *m, int_val f );
+/*
+vclosure *hl_alloc_closure_int( hl_module *m, int_val f, int param );
+vclosure *hl_alloc_closure_double( hl_module *m, int_val f, double param );
+vclosure *hl_alloc_closure_float( hl_module *m, int_val f, float param );
+vclosure *hl_alloc_closure_ptr( hl_module *m, int_val f, void *param );
+*/
 
 #endif

+ 49 - 8
src/jit.c

@@ -875,7 +875,7 @@ static int prepare_call_args( jit_ctx *ctx, int count, int *args, bool isNative
 				else {
 					// pseudo push32 (not available)
 					op64(ctx,SUB,PESP,pconst(&p,4));
-					op32(ctx,MOV,pmem(&p,Esp,0,0),fetch(r));
+					op32(ctx,MOV,pmem(&p,Esp,0,0),alloc_cpu(ctx,r,true));
 				}
 				break;
 			case 8:
@@ -911,14 +911,15 @@ static void call_native( jit_ctx *ctx, void *nativeFun, int size ) {
 }
 
 static void op_call_fun( jit_ctx *ctx, vreg *dst, int findex, int count, int *args ) {
-	int fid = ctx->functionReindex[findex];
+	int fid = findex < 0 ? -1 : ctx->functionReindex[findex];
 	int isNative = fid >= ctx->m->code->nfunctions;
 	int i = 0, size = prepare_call_args(ctx,count,args,isNative);
 	preg p;
 	if( fid < 0 ) {
-		// not a static function or native, load it at runtime
-		op64(ctx,MOV,PEAX,paddr(&p,ctx->m->functions_ptrs + findex));
-		op64(ctx,CALL,PEAX,NULL);
+		// closure
+		preg *r = alloc_cpu(ctx, R(-findex), true);
+		op64(ctx,MOV,PEAX,pmem(&p,(CpuReg)r->id,0,0));
+		op64(ctx,CALL,PEAX,UNUSED);
 		discard_regs(ctx, 1);
 	} else if( isNative ) {
 		call_native(ctx,ctx->m->functions_ptrs[findex],size);
@@ -1326,12 +1327,54 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 		case ONew:
 			{
 				vreg *r = R(o->p1);
-				int_val args[2] = { (int_val)m, (int_val)r->t->obj }; 
+				int_val args[2] = { (int_val)m, (int_val)r->t }; 
 				if( r->t->kind != HOBJ ) ASSERT(r->t->kind);
 				call_native_consts(ctx, hl_alloc_obj, args, 2);
 				store(ctx, r, PEAX, true);
 			}
 			break;
+		case OGetFunction:
+			{
+				vreg *r = R(o->p1);
+				int_val args[2] = { (int_val)m, (int_val)o->p2 };
+				call_native_consts(ctx, hl_alloc_closure_void, args, 2);
+				store(ctx, r, PEAX, true);
+			}
+			break;
+		case OCallClosure:
+			// TODO : if closure has value ?
+			// TODO : if closure is native ?
+			// TODO : how to apply first value ?
+			// requires dynamic branching ?
+			op_call_fun(ctx,R(o->p1),-o->p2,o->p3,o->extra);
+			break;
+		case OGetThis:
+			{
+				vreg *r = R(0);
+				hl_runtime_obj *rt = hl_get_obj_rt(m, r->t);
+				preg *rr = alloc_cpu(ctx,r, true);
+				preg *rv;
+				if( rr->lock < i ) rr->lock = i;
+				rv = alloc_reg(ctx,RCPU);
+				if( rr == rv ) ASSERT(0);
+				// TODO : copy data
+				op32(ctx, MOV, rv, pmem(&p, (CpuReg)rr->id, rt->fields_indexes[o->p2], 0));
+				store(ctx, R(o->p1), rv, true);
+			}
+			break;
+		case OSetThis:
+			{
+				vreg *r = R(0);
+				hl_runtime_obj *rt = hl_get_obj_rt(m, r->t);
+				preg *rr = alloc_cpu(ctx, r, true);
+				preg *rv;
+				if( rr->lock < i ) rr->lock = i;
+				rv = alloc_cpu(ctx, R(o->p2), true);
+				if( rr == rv ) ASSERT(0);
+				// TODO : copy data
+				op32(ctx, MOV, pmem(&p, (CpuReg)rr->id, rt->fields_indexes[o->p1], 0), rv);
+			}
+			break;
 		default:
 			printf("Don't know how to jit %s\n",hl_op_name(o->op));
 			break;
@@ -1364,8 +1407,6 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 	return codePos;
 }
 
-void *hl_alloc_executable_memory( int size );
-
 void *hl_jit_code( jit_ctx *ctx, hl_module *m ) {
 	jlist *c;
 	int size = BUF_POS();

+ 1 - 1
src/main.c

@@ -68,7 +68,7 @@ int main( int argc, char *argv[] ) {
 			return 4;
 		if( !hl_module_init(m) )
 			return 5;
-		hl_call(*(fptr*)(m->globals_data + m->globals_indexes[m->code->entrypoint]));
+		hl_call(m->functions_ptrs[m->code->entrypoint]);
 		hl_module_free(m);
 		hl_free(&code->alloc);
 	}

+ 62 - 2
src/module.c

@@ -21,6 +21,65 @@
  */
 #include "hl.h"
 
+hl_runtime_obj *hl_get_obj_rt( hl_module *m, hl_type *ot ) {
+	hl_alloc *alloc = &m->code->alloc;
+	hl_type_obj *o = ot->obj;
+	hl_runtime_obj *p = NULL, *t;
+	int i, size, start;
+	if( o->rt ) return o->rt;
+	if( o->super ) p = hl_get_obj_rt(m, o->super);
+	t = (hl_runtime_obj*)hl_malloc(alloc,sizeof(hl_runtime_obj));
+	t->nfields = o->nfields + (p ? p->nfields : 0);
+	t->fields_indexes = (int*)hl_malloc(alloc,sizeof(int)*t->nfields);
+	
+	// fields indexes
+	start = 0;
+	if( p ) {
+		start = p->nfields;
+		memcpy(t->fields_indexes, p->fields_indexes, sizeof(int)*p->nfields);
+	}
+	size = p ? p->size : HL_WSIZE; // hl_type*
+	for(i=0;i<o->nfields;i++) {
+		hl_type *ft = o->fields[i].t;
+		size += hl_pad_size(size,ft);
+		t->fields_indexes[i+start] = size;
+		size += hl_type_size(ft);
+	}
+	t->size = size;
+	t->proto = NULL;
+	o->rt = t;
+	return t;
+}
+
+hl_runtime_obj *hl_get_obj_proto( hl_module *m, hl_type *ot ) {
+	hl_alloc *alloc = &m->code->alloc;
+	hl_type_obj *o = ot->obj;
+	hl_runtime_obj *p = NULL, *t = hl_get_obj_rt(m, ot);
+	int i;
+	if( t->proto ) return t;
+	if( o->super ) p = hl_get_obj_proto(m,o->super);
+	if( p )
+		t->nproto = p->nproto;
+	else
+		t->nproto = 0;
+	for(i=0;i<o->nproto;i++) {
+		hl_obj_proto *p = o->proto + i;
+		if( p->pindex >= t->nproto ) t->nproto = p->pindex + 1;
+	}
+	t->proto = (vobj_proto*)hl_malloc(alloc, sizeof(vobj_proto) + t->nproto * sizeof(void*));
+	t->proto->t = ot;
+	if( t->nproto ) {
+		void **fptr = (void**)((unsigned char*)t->proto + sizeof(vobj_proto));
+		if( p )
+			memcpy(fptr, (unsigned char*)p->proto + sizeof(vobj_proto), p->nproto * sizeof(void*));
+		for(i=0;i<o->nproto;i++) {
+			hl_obj_proto *p = o->proto + i;
+			if( p->pindex >= 0 ) fptr[p->pindex] = m->functions_ptrs[p->findex];
+		}
+	}
+	return t;
+}
+
 hl_module *hl_module_alloc( hl_code *c ) {
 	int i;
 	int gsize = 0;
@@ -45,12 +104,12 @@ hl_module *hl_module_alloc( hl_code *c ) {
 		return NULL;
 	}
 	memset(m->globals_data,0,gsize);
-	m->functions_ptrs = (void**)malloc(sizeof(void*)*c->nfunctions);
+	m->functions_ptrs = (void**)malloc(sizeof(void*)*(c->nfunctions + c->nnatives));
 	if( m->functions_ptrs == NULL ) {
 		hl_module_free(m);
 		return NULL;
 	}
-	memset(m->functions_ptrs,0,sizeof(void*)*c->nfunctions);
+	memset(m->functions_ptrs,0,sizeof(void*)*(c->nfunctions + c->nnatives));
 	return m;
 }
 
@@ -112,6 +171,7 @@ int hl_module_init( hl_module *m ) {
 }
 
 void hl_module_free( hl_module *m ) {
+	hl_free_executable_memory(m->code);
 	free(m->functions_ptrs);
 	free(m->globals_indexes);
 	free(m->globals_data);