Forráskód Böngészése

callback from C to HL working

Nicolas Cannasse 10 éve
szülő
commit
e933185d97
7 módosított fájl, 193 hozzáadás és 64 törlés
  1. 1 0
      hl.vcxproj
  2. 0 17
      src/alloc.c
  3. 61 0
      src/callback.c
  4. 6 2
      src/hl.h
  5. 119 41
      src/jit.c
  6. 1 1
      src/main.c
  7. 5 3
      src/module.c

+ 1 - 0
hl.vcxproj

@@ -140,6 +140,7 @@
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClCompile Include="src\alloc.c" />
+    <ClCompile Include="src\callback.c" />
     <ClCompile Include="src\code.c" />
     <ClCompile Include="src\jit.c" />
     <ClCompile Include="src\main.c" />

+ 0 - 17
src/alloc.c

@@ -173,20 +173,3 @@ vclosure *hl_alloc_closure_i64( hl_module *m, int_val fid, int_val v64 ) {
 	c->v64 = v64;
 	return c;
 }
-
-void hl_call( void *f ) {
-#	if !defined(HL_64) && defined(HL_VCC)
-	int old_esp;
-	__asm {
-		mov old_esp, esp
-		mov eax, esp
-		and eax, 15
-		sub esp, eax
-		call f
-		mov esp, old_esp
-	}
-#	else
-	((fptr)f)();
-#	endif
-}
-

+ 61 - 0
src/callback.c

@@ -0,0 +1,61 @@
+#include "hl.h"
+
+#define MAX_ARGS	16
+
+static void *hl_callback_entry = NULL;
+
+void hl_callback_init( void *e ) {
+	hl_callback_entry = e;
+}
+
+void *hl_callback( void *f, int nargs, vdynamic **args ) {
+	union {
+		unsigned char b[MAX_ARGS * HL_WSIZE];
+		double d[MAX_ARGS];
+		int i[MAX_ARGS];
+	} stack;
+	/*
+		Same as jit(prepare_call_args) but writes values to the stack var
+	*/
+	int i, size = 0, pad = 0, pos = 0;
+	for(i=0;i<nargs;i++) {
+		vdynamic *d = args[i];
+		hl_type *dt = (*d->t)->t;
+		size += hl_pad_size(size,dt);
+		size += hl_type_size(dt);
+	}
+	if( size & 15 )
+		pad = 16 - (size&15);
+	size = pos = pad;
+	for(i=0;i<nargs;i++) {
+		// RTL
+		vdynamic *d = args[i];
+		hl_type *dt = (*d->t)->t;
+		int pad;
+		int tsize = hl_type_size(dt);
+		size += tsize;
+		pad = hl_pad_size(size,dt);
+		if( pad ) {
+			pos += pad;
+			size += pad;
+		}
+		switch( tsize ) {
+		case 0:
+			continue;
+		case 1:
+			stack.b[pos] = d->v.b;
+			break;
+		case 4:
+			stack.i[pos>>2] = d->v.i;
+			break;
+		case 8:
+			stack.d[pos>>3] = d->v.d;
+			break;
+		default:
+			printf("Invalid callback arg\n");
+			return NULL;
+		}
+		pos += tsize;
+	}
+	return ((void *(*)(void *, void *, int))hl_callback_entry)(f, &stack, (IS_64?pos>>3:pos>>2));
+}

+ 6 - 2
src/hl.h

@@ -217,6 +217,7 @@ 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 );
 void hl_jit_init( jit_ctx *ctx, hl_module *m );
+int hl_jit_init_callback( jit_ctx *ctx );
 int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f );
 void *hl_jit_code( jit_ctx *ctx, hl_module *m );
 
@@ -231,6 +232,7 @@ typedef struct {
 	int __pad; // force align
 #	endif
 	union {
+		unsigned char b;
 		int i;
 		float f;
 		double d;
@@ -267,16 +269,18 @@ struct hl_runtime_obj {
 	int size;
 	int *fields_indexes;
 	vobj_proto *proto;
-	const char *(*toString)( vobj * );
+	void *toString;
 };
 
 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 *t );
 
+void hl_callback_init( void *e );
+void *hl_callback( void *f, int nargs, vdynamic **args );
+
 vclosure *hl_alloc_closure_void( hl_module *m, int_val f );
 vclosure *hl_alloc_closure_i32( hl_module *m, int_val f, int v32 );
 vclosure *hl_alloc_closure_i64( hl_module *m, int_val f, int_val v64 );

+ 119 - 41
src/jit.c

@@ -22,6 +22,7 @@
 #include "hl.h"
 
 //#define OP_LOG
+//#define JIT_DEBUG
 
 typedef enum {
 	Eax = 0,
@@ -57,6 +58,7 @@ typedef enum {
 	XOR,
 	CMP,
 	NOP,
+	SHL,
 	// SSE
 	MOVSD,
 	COMISD,
@@ -131,9 +133,9 @@ typedef enum {
 } preg_kind;
 
 typedef struct {
+	preg_kind kind;
 	int id;
 	int lock;
-	preg_kind kind;
 	vreg *holds;
 } preg;
 
@@ -154,7 +156,7 @@ struct vreg {
 #	define RFPU_SCRATCH_COUNT	6
 static int RCPU_SCRATCH_REGS[] = { Eax, Ecx, Edx, R8, R9, R10, R11 };
 #else
-#	define RCPU_COUNT	6
+#	define RCPU_COUNT	8
 #	define RFPU_COUNT	8
 #	define RCPU_SCRATCH_COUNT	3
 #	define RFPU_SCRATCH_COUNT	8
@@ -178,7 +180,7 @@ static int RCPU_SCRATCH_REGS[] = { Eax, Ecx, Edx };
 
 #define BREAK()		B(0xCC)
 
-static preg _unused = { 0, 0, RUNUSED, NULL };
+static preg _unused = { RUNUSED, 0, 0, NULL };
 static preg *UNUSED = &_unused;
 
 struct jit_ctx {
@@ -212,9 +214,9 @@ static void jit_exit() {
 	exit(-1);
 }
 
-static preg *pmem( preg *r, CpuReg reg, int regOrOffset, int mult ) {
+static preg *pmem( preg *r, CpuReg reg, int regOrOffset ) {
 	r->kind = RMEM;
-	r->id = mult | (reg << 4) | (regOrOffset << 8);
+	r->id = 0 | (reg << 4) | (regOrOffset << 8);
 	return r;
 }
 
@@ -273,12 +275,12 @@ static const char *KNAMES[] = { "cpu","fpu","stack","const","addr","mem","unused
 #define ERRIF(c)	if( c ) { printf("%s(%s,%s)\n",f?f->name:"???",KNAMES[a->kind], KNAMES[b->kind]); ASSERT(0); }
 
 typedef struct {
-	const char *name;
-	int r_mem;		// r32 / r/m32 
-	int mem_r;		// r/m32 / r32
-	int r_const;	// r32 / imm32
-	int r_i8;		// r32 / imm8
-	int mem_const;	// r/m32 / imm32
+	const char *name;						// single operand
+	int r_mem;		// r32 / r/m32				r32
+	int mem_r;		// r/m32 / r32				r/m32
+	int r_const;	// r32 / imm32				imm32
+	int r_i8;		// r32 / imm8				imm8
+	int mem_const;	// r/m32 / imm32			N/A
 } opform;
 
 #define RM(op,id) ((op) | (((id)+1)<<8))
@@ -292,11 +294,12 @@ static opform OP_FORMS[_CPU_LAST] = {
 	{ "SUB", 0x2B, 0x29, RM(0x81,5), RM(0x83,5) },
 	{ "POP", 0x58, RM(0x8F,0) },
 	{ "RET", 0xC3 },
-	{ "CALL", RM(0xFF,2), 0, 0xE8 },
-	{ "AND" },
+	{ "CALL", RM(0xFF,2), RM(0xFF,2), 0xE8 },
+	{ "AND", 0x23, 0x21, RM(0x81,4), RM(0x83,4) },
 	{ "XOR", 0x33, 0x31, RM(0x81,6), RM(0x83,6) },
 	{ "CMP", 0x3B, 0x39, RM(0x81,7), RM(0x83,7) },
 	{ "NOP", 0x90 },
+	{ "SHL", 0, 0, 0, RM(0xC1,4) },
 	// SSE
 	{ "MOVSD", 0xF20F10, 0xF20F11  },
 	{ "COMISD", 0x660F2F },
@@ -427,7 +430,7 @@ static void op( jit_ctx *ctx, CpuOp o, preg *a, preg *b, bool mode64 ) {
 		}
 		break;
 	case ID2(RCPU,RCONST):
-		ERRIF( f->r_const == 0 );
+		ERRIF( f->r_const == 0 && f->r_i8 == 0 );
 		if( a->id > 7 ) r64 |= 1;
 		{
 			int_val cval = b->holds ? (int_val)b->holds : b->id;
@@ -441,6 +444,7 @@ static void op( jit_ctx *ctx, CpuOp o, preg *a, preg *b, bool mode64 ) {
 				MOD_RM(3,GET_RM(f->r_const)-1,a->id);
 				if( mode64 && IS_64 ) W64(cval); else W((int)cval);
 			} else {
+				ERRIF( f->r_const == 0);
 				OP((f->r_const&0xFF) + (a->id&7));
 				if( mode64 && IS_64 ) W64(cval); else W((int)cval);
 			}
@@ -487,7 +491,7 @@ static void op( jit_ctx *ctx, CpuOp o, preg *a, preg *b, bool mode64 ) {
 		}
 		break;
 	case ID2(RMEM,RUNUSED):
-		ERRIF( f->r_mem == 0 );
+		ERRIF( f->mem_r == 0 );
 		{
 			int mult = a->id & 0xF;
 			int regOrOffs = mult == 15 ? a->id >> 4 : a->id >> 8;  
@@ -496,16 +500,16 @@ static void op( jit_ctx *ctx, CpuOp o, preg *a, preg *b, bool mode64 ) {
 				ERRIF(1);
 			} else if( mult == 0 ) {
 				if( reg > 7 ) r64 |= 1;
-				OP(f->r_mem);
+				OP(f->mem_r);
 				if( regOrOffs == 0 && (reg&7) != Ebp ) {
-					MOD_RM(0,GET_RM(f->r_mem)-1,reg);
+					MOD_RM(0,GET_RM(f->mem_r)-1,reg);
 					if( (reg&7) == Esp ) B(0x24);
 				} else if( IS_SBYTE(regOrOffs) ) {
-					MOD_RM(1,GET_RM(f->r_mem)-1,reg);
+					MOD_RM(1,GET_RM(f->mem_r)-1,reg);
 					if( (reg&7) == Esp ) B(0x24);
 					B(regOrOffs);
 				} else {
-					MOD_RM(2,GET_RM(f->r_mem)-1,reg);
+					MOD_RM(2,GET_RM(f->mem_r)-1,reg);
 					if( (reg&7) == Esp ) B(0x24);
 					W(regOrOffs);
 				}
@@ -645,6 +649,11 @@ static void patch_jump( jit_ctx *ctx, int p ) {
 	*(int*)(ctx->startBuf + p) = BUF_POS() - (p + 4);
 }
 
+static void patch_jump_to( jit_ctx *ctx, int p, int target ) {
+	if( p == 0 ) return;
+	*(int*)(ctx->startBuf + p) = target - (p + 4);
+}
+
 static preg *alloc_reg( jit_ctx *ctx, preg_kind k ) {
 	int i;
 	preg *p;
@@ -926,13 +935,13 @@ static int prepare_call_args( jit_ctx *ctx, int count, int *args, vreg *vregs, b
 			else {
 				// pseudo push32 (not available)
 				op64(ctx,SUB,PESP,pconst(&p,4));
-				op32(ctx,MOV,pmem(&p,Esp,0,0),alloc_cpu(ctx,r,true));
+				op32(ctx,MOV,pmem(&p,Esp,0),alloc_cpu(ctx,r,true));
 			}
 			break;
 		case 8:
 			if( fetch(r)->kind == RFPU ) {
 				op64(ctx,SUB,PESP,pconst(&p,8));
-				op64(ctx,MOVSD,pmem(&p,Esp,0,0),fetch(r));
+				op64(ctx,MOVSD,pmem(&p,Esp,0),fetch(r));
 			} else if( IS_64 )
 				op64(ctx,PUSH,fetch(r),UNUSED);
 			else
@@ -1007,13 +1016,13 @@ static void op_call_closure( jit_ctx *ctx, vreg *dst, vreg *f, int nargs, int *r
 	LOCK(r);
 	tmp = alloc_reg(ctx, RCPU);
 	// read bits
-	op32(ctx,MOV,tmp,pmem(&p,(CpuReg)r->id,HL_WSIZE*2,0));
+	op32(ctx,MOV,tmp,pmem(&p,(CpuReg)r->id,HL_WSIZE*2));
 	op32(ctx,CMP,tmp,pconst(&p,0));
 	XJump(JNeq,has_param);
 	{
 		// no argument call
 		int size = prepare_call_args(ctx,nargs,rargs,ctx->vregs,false);
-		op64(ctx,CALL,pmem(&p,(CpuReg)r->id,HL_WSIZE,0),UNUSED);
+		op64(ctx,CALL,pmem(&p,(CpuReg)r->id,HL_WSIZE),UNUSED);
 		if( size ) op64(ctx,ADD,PESP,pconst(&p,size));
 		XJump(JAlways,end1);
 	}
@@ -1034,7 +1043,7 @@ static void op_call_closure( jit_ctx *ctx, vreg *dst, vreg *f, int nargs, int *r
 		fake.t = &ti32;
 		fake.current = alloc_reg(ctx,RCPU);
 		LOCK(fake.current);
-		op32(ctx,MOV,fake.current,pmem(&p,(CpuReg)r->id,HL_WSIZE*3,0));
+		op32(ctx,MOV,fake.current,pmem(&p,(CpuReg)r->id,HL_WSIZE*3));
 
 		// prepare the args
 		vargs = (vreg*)hl_malloc(&ctx->falloc,sizeof(vreg)*(nargs+1));
@@ -1048,7 +1057,7 @@ static void op_call_closure( jit_ctx *ctx, vreg *dst, vreg *f, int nargs, int *r
 
 		// call
 		size = prepare_call_args(ctx,nargs+1,args,vargs,false);
-		op64(ctx,CALL,pmem(&p,(CpuReg)r->id,HL_WSIZE,0),UNUSED);
+		op64(ctx,CALL,pmem(&p,(CpuReg)r->id,HL_WSIZE),UNUSED);
 		op64(ctx,ADD,PESP,pconst(&p,size));
 		XJump(JAlways,end2);
 	}
@@ -1068,7 +1077,7 @@ static void op_call_closure( jit_ctx *ctx, vreg *dst, vreg *f, int nargs, int *r
 		fake.current = alloc_reg(ctx,RFPU);
 		LOCK(fake.current);
 
-		op64(ctx,MOVSD,fake.current,pmem(&p,(CpuReg)r->id,HL_WSIZE*3,0));
+		op64(ctx,MOVSD,fake.current,pmem(&p,(CpuReg)r->id,HL_WSIZE*3));
 
 		// prepare the args
 		vargs = (vreg*)hl_malloc(&ctx->falloc,sizeof(vreg)*(nargs+1));
@@ -1082,7 +1091,7 @@ static void op_call_closure( jit_ctx *ctx, vreg *dst, vreg *f, int nargs, int *r
 
 		// call
 		size = prepare_call_args(ctx,nargs+1,args,vargs,false);
-		op64(ctx,CALL,pmem(&p,(CpuReg)r->id,HL_WSIZE,0),UNUSED);
+		op64(ctx,CALL,pmem(&p,(CpuReg)r->id,HL_WSIZE),UNUSED);
 		op64(ctx,ADD,PESP,pconst(&p,size));
 	}
 	patch_jump(ctx,end1);
@@ -1292,6 +1301,68 @@ void hl_jit_init( jit_ctx *ctx, hl_module *m ) {
 		op32(ctx, NOP, UNUSED, UNUSED);
 }
 
+int hl_jit_init_callback( jit_ctx *ctx ) {
+	/*
+		create the function that will be called by hl_callback.
+		it will make sure to prepare the stack according to HL calling convention (cdecl)
+	*/
+#	ifndef HL_64
+	CpuReg R8 = Eax;
+#	endif
+	int pos = BUF_POS();
+	int jstart, jcall, jloop;
+	preg p;
+
+	jit_buf(ctx);
+	op64(ctx,PUSH,PEBP,UNUSED);
+	op64(ctx,MOV,PEBP,PESP);
+
+	// make sure the stack is aligned on 16 bytes
+	// the amount of push we will do afterwards is guaranteed to be a multiple of 16bytes by hl_callback
+	// in 64 bits, we already have EIP+EBP so it's aligned
+#	ifndef HL_64
+#		ifdef HL_VCC
+			// VCC does not guarantee us an aligned stack...
+			op64(ctx,MOV,PEAX,PESP);
+			op64(ctx,AND,PEAX,pconst(&p,15));
+			op64(ctx,SUB,PESP,PEAX);
+#		else
+			op64(ctx,SUB,PESP,pconst(&p,8));
+#		endif
+#	endif
+
+	if( !IS_64 ) {
+		// mov stack to regs (as x86_64)
+		op64(ctx,MOV,REG_AT(Ecx),pmem(&p,Ebp,HL_WSIZE*2));
+		op64(ctx,MOV,REG_AT(Edx),pmem(&p,Ebp,HL_WSIZE*3));
+		op64(ctx,MOV,REG_AT(R8),pmem(&p,Ebp,HL_WSIZE*4));
+	}
+
+
+	XJump(JAlways,jstart);
+	jloop = BUF_POS();
+	op64(ctx,PUSH,pmem(&p,Edx,0),UNUSED);
+	op64(ctx,ADD,REG_AT(Edx),pconst(&p,HL_WSIZE));
+	op64(ctx,SUB,REG_AT(R8),pconst(&p,1));
+	
+	patch_jump(ctx, jstart);
+	op64(ctx,CMP,REG_AT(R8),pconst(&p,0));
+	XJump(JNeq,jcall);
+	patch_jump_to(ctx, jcall, jloop);
+
+	op64(ctx,CALL,REG_AT(Ecx),UNUSED);
+
+	// cleanup and ret
+	op64(ctx,MOV,PESP,PEBP);
+	op64(ctx,POP,PEBP, UNUSED);
+	op64(ctx,RET,UNUSED,UNUSED);
+
+	jit_buf(ctx);
+	while( BUF_POS() & 15 )
+		op32(ctx, NOP, UNUSED, UNUSED);
+	return pos;
+}
+
 int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 	int i, size = 0, opCount;
 	int codePos = BUF_POS();
@@ -1350,6 +1421,13 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 		hl_opcode *o = f->ops + opCount;
 		ctx->currentPos = opCount;
 		jit_buf(ctx);
+#		ifdef JIT_DEBUG
+		{
+			int uid = opCount + (f->findex<<16);
+			op32(ctx, PUSH, pconst(&p,uid), UNUSED);
+			op64(ctx, ADD, PESP, pconst(&p,HL_WSIZE));
+		}
+#		endif
 		switch( o->op ) {
 		case OMov:
 			op_mov(ctx, R(o->p1), R(o->p2));
@@ -1369,7 +1447,7 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 					op64(ctx,MOVSD,r,paddr(&p,addr));
 				else if( IS_64 ) {
 					op64(ctx,MOV,r,pconst64(&p,(int_val)addr));
-					op32(ctx,MOV,r,pmem(&p,r->id,0,0));
+					op32(ctx,MOV,r,pmem(&p,r->id,0));
 				} else
 					op64(ctx,MOV,r,paddr(&p,addr));
 				store(ctx, to, r, false);
@@ -1386,7 +1464,7 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				else if( IS_64 ) {
 					preg *tmp = alloc_reg(ctx, RCPU);
 					op64(ctx,MOV,tmp,pconst64(&p,(int_val)addr));
-					op32(ctx,MOV,pmem(&p,(CpuReg)tmp->id,0,0),v);
+					op32(ctx,MOV,pmem(&p,(CpuReg)tmp->id,0),v);
 				} else
 					op32(ctx,MOV,paddr(&p,addr),v);
 			}
@@ -1444,15 +1522,15 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				if( IS_FLOAT(r) && !IS_64 ) {
 					preg *tmp = REG_AT(RCPU_SCRATCH_REGS[1]);
 					op64(ctx,MOV,tmp,&r->stack);
-					op64(ctx,MOV,pmem(&p,Eax,8,0),tmp);
+					op64(ctx,MOV,pmem(&p,Eax,8),tmp);
 					r->stackPos += 4;
 					op64(ctx,MOV,tmp,&r->stack);
-					op64(ctx,MOV,pmem(&p,Eax,12,0),tmp);
+					op64(ctx,MOV,pmem(&p,Eax,12),tmp);
 					r->stackPos -= 4;
 				} else {
 					preg *tmp = REG_AT(RCPU_SCRATCH_REGS[1]);
 					op64(ctx,MOV,tmp,&r->stack);
-					op64(ctx,MOV,pmem(&p,Eax,8,0),tmp);
+					op64(ctx,MOV,pmem(&p,Eax,8),tmp);
 				}
 				store(ctx, R(o->p1), PEAX, true);
 			}
@@ -1512,9 +1590,9 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				} else {
 					int size = pad_stack(ctx, 0);
 					if( arg->current && arg->current->kind == RFPU ) scratch(arg->current);
+					op64(ctx,MOV,REG_AT(CALL_REGS[2]),fetch(arg));
 					op64(ctx,MOV,REG_AT(CALL_REGS[0]),pconst64(&p,(int_val)m));
 					op64(ctx,MOV,REG_AT(CALL_REGS[1]),pconst64(&p,(int_val)o->p2));
-					op64(ctx,MOV,REG_AT(CALL_REGS[2]),fetch(arg));
 					call_native(ctx,hl_alloc_closure_i64,size);
 				}
 #				else
@@ -1545,7 +1623,7 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				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->p3], 0));
+				op32(ctx, MOV, rv, pmem(&p, (CpuReg)rr->id, rt->fields_indexes[o->p3]));
 				store(ctx, R(o->p1), rv, true);
 			}
 			break;
@@ -1559,7 +1637,7 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				rv = alloc_cpu(ctx, R(o->p3), true);
 				if( rr == rv ) ASSERT(0);
 				// TODO : copy data
-				op32(ctx, MOV, pmem(&p, (CpuReg)rr->id, rt->fields_indexes[o->p2], 0), rv);
+				op32(ctx, MOV, pmem(&p, (CpuReg)rr->id, rt->fields_indexes[o->p2]), rv);
 			}
 			break;
 		case OGetThis:
@@ -1572,7 +1650,7 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				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));
+				op32(ctx, MOV, rv, pmem(&p, (CpuReg)rr->id, rt->fields_indexes[o->p2]));
 				store(ctx, R(o->p1), rv, true);
 			}
 			break;
@@ -1586,7 +1664,7 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				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);
+				op32(ctx, MOV, pmem(&p, (CpuReg)rr->id, rt->fields_indexes[o->p1]), rv);
 			}
 			break;
 		case OCallThis:
@@ -1600,12 +1678,12 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				LOCK(r);
 				tmp = alloc_reg(ctx, RCPU);
 				LOCK(tmp);
-				op64(ctx,MOV,tmp,pmem(&p,r->id,0,0)); // read proto
+				op64(ctx,MOV,tmp,pmem(&p,r->id,0)); // read proto
 				args[0] = 0;
 				for(i=1;i<nargs;i++)
 					args[i] = o->extra[i-1];
 				size = prepare_call_args(ctx,nargs,args,ctx->vregs,false);
-				op64(ctx,CALL,pmem(&p,tmp->id,(o->p2 + 1)*HL_WSIZE,0),UNUSED);
+				op64(ctx,CALL,pmem(&p,tmp->id,(o->p2 + 1)*HL_WSIZE),UNUSED);
 				discard_regs(ctx, false);
 				op64(ctx,ADD,PESP,pconst(&p,size));
 				store(ctx, dst, IS_FLOAT(dst) ? PXMM(0) : PEAX, true);
@@ -1621,9 +1699,9 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				tmp = alloc_reg(ctx, RCPU);
 				LOCK(tmp);
 				// TODO : check r == NULL
-				op64(ctx,MOV,tmp,pmem(&p,r->id,0,0)); // read proto
+				op64(ctx,MOV,tmp,pmem(&p,r->id,0)); // read proto
 				size = prepare_call_args(ctx,o->p3,o->extra,ctx->vregs,false);
-				op64(ctx,CALL,pmem(&p,tmp->id,(o->p2 + 1)*HL_WSIZE,0),UNUSED);
+				op64(ctx,CALL,pmem(&p,tmp->id,(o->p2 + 1)*HL_WSIZE),UNUSED);
 				discard_regs(ctx, false);
 				op64(ctx,ADD,PESP,pconst(&p,size));
 				store(ctx, dst, IS_FLOAT(dst) ? PXMM(0) : PEAX, true);

+ 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(m->functions_ptrs[m->code->entrypoint]);
+		hl_callback(m->functions_ptrs[m->code->entrypoint],0,NULL);
 		hl_module_free(m);
 		hl_free(&code->alloc);
 	}

+ 5 - 3
src/module.c

@@ -114,7 +114,7 @@ hl_module *hl_module_alloc( hl_code *c ) {
 		return NULL;
 	}
 	memset(m->functions_ptrs,0,sizeof(void*)*(c->nfunctions + c->nnatives));
-	memset(m->functions_indexes,0xFF,sizeof(void*)*(c->nfunctions + c->nnatives));
+	memset(m->functions_indexes,0xFF,sizeof(int)*(c->nfunctions + c->nnatives));
 	return m;
 }
 
@@ -143,7 +143,7 @@ static void do_log( vdynamic *v ) {
 			if( o->rt == NULL || o->rt->toString == NULL )
 				printf("#%s\n",o->name);
 			else
-				printf("[%s]\n",o->rt->toString(v->v.o));
+				printf("[%s]\n",hl_callback(o->rt->toString,1,&v));
 		}
 		break;
 	default:
@@ -156,7 +156,7 @@ static void do_log( vdynamic *v ) {
 }
 
 int hl_module_init( hl_module *m ) {
-	int i;
+	int i, entry;
 	jit_ctx *ctx;
 	// RESET globals
 	for(i=0;i<m->code->nglobals;i++) {
@@ -182,6 +182,7 @@ int hl_module_init( hl_module *m ) {
 	if( ctx == NULL )
 		return 0;
 	hl_jit_init(ctx, m);
+	entry = hl_jit_init_callback(ctx);
 	for(i=0;i<m->code->nfunctions;i++) {
 		hl_function *f = m->code->functions + i;
 		int fpos = hl_jit_function(ctx, m, f);
@@ -196,6 +197,7 @@ int hl_module_init( hl_module *m ) {
 		hl_function *f = m->code->functions + i;
 		m->functions_ptrs[f->findex] = ((unsigned char*)m->jit_code) + ((int_val)m->functions_ptrs[f->findex]);
 	}
+	hl_callback_init(((unsigned char*)m->jit_code) + entry);
 	hl_jit_free(ctx);
 	return 1;
 }