瀏覽代碼

added OCallClosure(dyn) support

Nicolas Cannasse 9 年之前
父節點
當前提交
f47c663d91
共有 3 個文件被更改,包括 74 次插入32 次删除
  1. 4 0
      src/alloc.c
  2. 66 31
      src/jit.c
  3. 4 1
      src/std/fun.c

+ 4 - 0
src/alloc.c

@@ -865,6 +865,10 @@ vdynamic *hl_alloc_dynamic( hl_type *t ) {
 	vdynamic *d = (vdynamic*) (hl_is_ptr(t) ? hl_gc_alloc(sizeof(vdynamic)) : hl_gc_alloc_noptr(sizeof(vdynamic)));
 	d->t = t;
 	d->v.ptr = NULL;
+#	ifdef HL_DEBUG
+	if( t->kind == HVOID )
+		hl_error("alloc_dynamic(VOID)");
+#	endif
 	return d;
 }
 

+ 66 - 31
src/jit.c

@@ -1326,6 +1326,7 @@ static void _jit_error( jit_ctx *ctx, const char *msg, int line ) {
 	call_native_consts(ctx,on_jit_error,args,2);
 }
 
+
 static preg *op_binop( jit_ctx *ctx, vreg *dst, vreg *a, vreg *b, hl_opcode *op ) {
 	preg *pa = fetch(a), *pb = fetch(b), *out = NULL;
 	CpuOp o;
@@ -1347,7 +1348,9 @@ static preg *op_binop( jit_ctx *ctx, vreg *dst, vreg *a, vreg *b, hl_opcode *op
 			{
 				int args[] = { a->stack.id, b->stack.id };
 				int size = prepare_call_args(ctx,2,args,ctx->vregs,true,0);
-				call_native(ctx,a->t->kind == HF32 ? (void*)fmodf : (void*)fmod,size);
+				void *mod_fun;
+				if( a->t->kind == HF32 ) mod_fun = fmodf; else mod_fun = fmod; 
+				call_native(ctx,mod_fun,size);
 				store_native_result(ctx,dst);
 				return fetch(dst);
 			}
@@ -1888,6 +1891,37 @@ static void *get_dynget( hl_type *t ) {
 	}
 }
 
+static void make_dyn_cast( jit_ctx *ctx, vreg *dst, vreg *v ) {
+	int size;
+	preg p;
+#ifdef HL_64
+	jit_error("TODO");
+#else
+	switch( dst->t->kind ) {
+	case HF32:
+	case HF64:
+		size = pad_before_call(ctx, HL_WSIZE*2);
+		op32(ctx,PUSH,pconst64(&p,(int_val)v->t),UNUSED);
+		op32(ctx,MOV,PEAX,REG_AT(Ebp));
+		op32(ctx,ADD,PEAX,pconst(&p,v->stackPos));
+		op32(ctx,PUSH,PEAX,UNUSED);
+		call_native(ctx,get_dyncast(dst->t),size);
+		store_native_result(ctx, dst);
+		break;
+	default:
+		size = pad_before_call(ctx, HL_WSIZE*3);
+		op32(ctx,PUSH,pconst64(&p,(int_val)dst->t),UNUSED);
+		op32(ctx,PUSH,pconst64(&p,(int_val)v->t),UNUSED);
+		op32(ctx,MOV,PEAX,REG_AT(Ebp));
+		op32(ctx,ADD,PEAX,pconst(&p,v->stackPos));
+		op32(ctx,PUSH,PEAX,UNUSED);
+		call_native(ctx,get_dyncast(dst->t),size);
+		store(ctx, dst, PEAX, true);
+		break;
+	}
+#endif
+}
+
 int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 	int i, size = 0, opCount;
 	int codePos = BUF_POS();
@@ -2250,7 +2284,36 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 			break;
 		case OCallClosure:
 			if( ra->t->kind == HDYN ) {
-				jit_error("TODO");
+				// ASM for {
+				//	vdynamic *args[] = {args};
+				//  vdynamic *ret = hl_dyn_call(closure,args,nargs);
+				//  dst = hl_dyncast(ret,t_dynamic,t_dst);
+				// }
+				int size;
+				int offset = o->p3 * HL_WSIZE;
+				preg *r = alloc_reg(ctx, RCPU);
+				if( offset & 15 ) offset += 16 - (offset & 15);
+				op64(ctx,SUB,PESP,pconst(&p,offset));
+				op64(ctx,MOV,r,PESP);
+				for(i=0;i<o->p3;i++) {
+					vreg *a = R(o->extra[i]);
+					if( hl_is_dynamic(a->t) ) {
+						preg *v = alloc_cpu(ctx,a,true);
+						op64(ctx,MOV,pmem(&p,r->id,i * HL_WSIZE),v);
+						RUNLOCK(v);
+					} else {
+						jit_error("TODO");
+					}
+				}
+				size = pad_before_call(ctx,HL_WSIZE*2 + sizeof(int) + offset);
+				op64(ctx,PUSH,pconst(&p,o->p3),UNUSED);
+				op64(ctx,PUSH,r,UNUSED);
+				op64(ctx,PUSH,alloc_cpu(ctx,ra,true),UNUSED);
+				call_native(ctx,hl_dyn_call,size);
+				if( dst->t->kind != HVOID ) {
+					store(ctx,dst,PEAX,true);
+					make_dyn_cast(ctx,dst,dst);
+				}
 			} else {
 				int jhasvalue, jend, size;
 				// ASM for  if( c->hasValue ) c->fun(value,args) else c->fun(args)
@@ -2729,35 +2792,7 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 			}
 			break;
 		case OSafeCast:
-			{
-				int size;
-#				ifdef HL_64
-				jit_error("TODO");
-#				else
-				switch( dst->t->kind ) {
-				case HF32:
-				case HF64:
-					size = pad_before_call(ctx, HL_WSIZE*2);
-					op32(ctx,PUSH,pconst64(&p,(int_val)ra->t),UNUSED);
-					op32(ctx,MOV,PEAX,REG_AT(Ebp));
-					op32(ctx,ADD,PEAX,pconst(&p,ra->stackPos));
-					op32(ctx,PUSH,PEAX,UNUSED);
-					call_native(ctx,get_dyncast(dst->t),size);
-					store_native_result(ctx, dst);
-					break;
-				default:
-					size = pad_before_call(ctx, HL_WSIZE*3);
-					op32(ctx,PUSH,pconst64(&p,(int_val)dst->t),UNUSED);
-					op32(ctx,PUSH,pconst64(&p,(int_val)ra->t),UNUSED);
-					op32(ctx,MOV,PEAX,REG_AT(Ebp));
-					op32(ctx,ADD,PEAX,pconst(&p,ra->stackPos));
-					op32(ctx,PUSH,PEAX,UNUSED);
-					call_native(ctx,get_dyncast(dst->t),size);
-					store(ctx, dst, PEAX, true);
-					break;
-				}
-#				endif
-			}
+			make_dyn_cast(ctx, dst, ra);
 			break;
 		case ODynGet:
 			{

+ 4 - 1
src/std/fun.c

@@ -163,7 +163,10 @@ HL_PRIM vdynamic* hl_call_method( vdynamic *c, varray *args ) {
 	ret = hlc_static_call(cl->fun,cl->t,pargs,&out);
 	tret = cl->t->fun->ret;
 	if( !hl_is_ptr(tret) ) {
-		vdynamic *r = hl_alloc_dynamic(tret);
+		vdynamic *r;
+		if( tret->kind == HVOID )
+			return NULL;
+		r = hl_alloc_dynamic(tret);
 		r->t = tret;
 		r->v.d = out.v.d; // copy
 		return r;