Pārlūkot izejas kodu

call virtual dynamic ok, started special comparisons

Nicolas Cannasse 9 gadi atpakaļ
vecāks
revīzija
04da334022
2 mainītis faili ar 142 papildinājumiem un 35 dzēšanām
  1. 3 2
      src/callback.c
  2. 139 33
      src/jit.c

+ 3 - 2
src/callback.c

@@ -47,8 +47,9 @@ void *hl_callback( void *f, hl_type *t, void **args, vdynamic *ret ) {
 	size = pos = pad;
 	for(i=0;i<t->fun->nargs;i++) {
 		// RTL
-		hl_type *at = t->fun->args[i];
-		void *v = args[i];
+		int j = t->fun->nargs - 1 - i;
+		hl_type *at = t->fun->args[j];
+		void *v = args[j];
 		int pad;
 		int tsize = hl_type_size(at);
 		size += tsize;

+ 139 - 33
src/jit.c

@@ -50,6 +50,7 @@ typedef enum {
 
 typedef enum {
 	MOV,
+	LEA,
 	PUSH,
 	ADD,
 	SUB,
@@ -86,6 +87,7 @@ typedef enum {
 	CVTPD2PS,
 	// 8 bits
 	MOV8,
+	CMP8,
 	TEST8,
 	// --
 	_CPU_LAST
@@ -336,6 +338,7 @@ typedef struct {
 
 static opform OP_FORMS[_CPU_LAST] = {
 	{ "MOV", 0x8B, 0x89, 0xB8, 0, RM(0xC7,0) },
+	{ "LEA", 0x8D },
 	{ "PUSH", 0x50, RM(0xFF,6), 0x68, 0x6A },
 	{ "ADD", 0x03, 0x01, RM(0x81,0), RM(0x83,0) },
 	{ "SUB", 0x2B, 0x29, RM(0x81,5), RM(0x83,5) },
@@ -372,6 +375,7 @@ static opform OP_FORMS[_CPU_LAST] = {
 	{ "CVTPD2PS", 0x660F5A },
 	// 8 bits,
 	{ "MOV8", 0x8A, 0x88, 0, 0xB0, RM(0xC6,0) },
+	{ "CMP", 0x3A, 0x38, RM(0x80,7), 0 },
 	{ "TEST8", 0x84, 0x84, RM(0xF6,0) },
 };
 
@@ -1224,6 +1228,36 @@ static void op_ret( jit_ctx *ctx, vreg *r ) {
 	op64(ctx, RET, UNUSED, UNUSED);
 }
 
+static void call_native_consts( jit_ctx *ctx, void *nativeFun, int_val *args, int nargs ) {
+	int size = pad_stack(ctx, IS_64 ? 0 : HL_WSIZE*nargs);
+	preg p;
+	int i;
+#	ifdef HL_64
+	for(i=0;i<nargs;i++)
+		op64(ctx, MOV, REG_AT(CALL_REGS[i]), pconst64(&p, args[i]));
+#	else
+	for(i=nargs-1;i>=0;i--)
+		op32(ctx, PUSH, pconst64(&p, args[i]), UNUSED);
+#	endif
+	call_native(ctx, nativeFun, size);
+}
+
+static void on_jit_error( const char *msg, int_val line ) {
+	char buf[256];
+	int iline = (int)line;
+	sprintf(buf,"%s (line %d)",msg,iline);
+#ifdef HL_WIN
+	MessageBoxA(NULL,buf,"JIT ERROR",MB_OK);
+#else
+	printf("%s\n",buf);
+#endif
+	hl_debug_break();
+}
+
+static void _jit_error( jit_ctx *ctx, const char *msg, int line ) {
+	int_val args[2] = { (int_val)msg, (int_val)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;
@@ -1302,7 +1336,51 @@ static preg *op_binop( jit_ctx *ctx, vreg *dst, vreg *a, vreg *b, hl_opcode *op
 		case OJUGte:
 		case OJEq:
 		case OJNotEq:
-			o = CMP;
+			if( a->t->kind == HDYN || b->t->kind == HDYN ) {
+				jit_error("TODO");
+				return PEAX;
+			}
+			switch( a->t->kind ) {
+			case HI8:
+			case HBOOL:
+				o = CMP8;
+				break;
+			case HI16:
+				jit_error("TODO");
+				return PEAX;
+			case HTYPE:
+				jit_error("TODO");
+				return PEAX;
+			case HNULL:
+				jit_error("TODO");
+				return PEAX;
+			case HVIRTUAL:
+				if( b->t->kind == HOBJ ) {
+					jit_error("TODO");
+					return PEAX;
+				}
+			case HI32:
+			case HENUM:
+			case HDYNOBJ:
+			case HFUN:
+				o = CMP;
+				break;
+			case HOBJ:
+				if( b->t->kind == HVIRTUAL ) {
+					jit_error("TODO");
+					return PEAX;
+				}
+				if( hl_get_obj_rt(a->t)->compareFun ) {
+					jit_error("TODO");
+					return PEAX;
+				} else {
+					o = CMP;
+					break;
+				}
+			default:
+				o = CMP;
+				break;
+			}
 			break;
 		default:
 			printf("%s\n", hl_op_name(op->op));
@@ -1458,37 +1536,6 @@ static void register_jump( jit_ctx *ctx, int pos, int target ) {
 		ctx->opsPos[target] = -1;
 }
 
-static void call_native_consts( jit_ctx *ctx, void *nativeFun, int_val *args, int nargs ) {
-	int size = pad_stack(ctx, IS_64 ? 0 : HL_WSIZE*nargs);
-	preg p;
-	int i;
-#	ifdef HL_64
-	for(i=0;i<nargs;i++)
-		op64(ctx, MOV, REG_AT(CALL_REGS[i]), pconst64(&p, args[i]));
-#	else
-	for(i=nargs-1;i>=0;i--)
-		op32(ctx, PUSH, pconst64(&p, args[i]), UNUSED);
-#	endif
-	call_native(ctx, nativeFun, size);
-}
-
-static void on_jit_error( const char *msg, int_val line ) {
-	char buf[256];
-	int iline = (int)line;
-	sprintf(buf,"%s (line %d)",msg,iline);
-#ifdef HL_WIN
-	MessageBoxA(NULL,buf,"JIT ERROR",MB_OK);
-#else
-	printf("%s\n",buf);
-#endif
-	hl_debug_break();
-}
-
-static void _jit_error( jit_ctx *ctx, const char *msg, int line ) {
-	int_val args[2] = { (int_val)msg, (int_val)line };
-	call_native_consts(ctx,on_jit_error,args,2);
-}
-
 jit_ctx *hl_jit_alloc() {
 	int i;
 	jit_ctx *ctx = (jit_ctx*)malloc(sizeof(jit_ctx));
@@ -2163,7 +2210,66 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				break;
 			}
 			case HVIRTUAL:
-				jit_error("todo");
+				// ASM for --> if( hl_vfields(o)[f] ) dst = *hl_vfields(o)[f](o,args...); else dst = hl_dyn_call_obj(o->value,field,args,&ret)
+				{
+					int size;
+					int paramsSize;
+					int jhasfield, jend;
+					vreg *obj = R(o->extra[0]);
+					preg *v = alloc_cpu(ctx,obj, true);
+					preg *r = alloc_reg(ctx,RCPU);
+					op64(ctx,MOV,r,pmem(&p,v->id,sizeof(vvirtual)+HL_WSIZE*o->p2));
+					op64(ctx,TEST,r,r);
+					XJump_small(JNotZero,jhasfield);
+
+					paramsSize = (o->p3 - 1) * HL_WSIZE;
+					if( paramsSize & 15 ) paramsSize += 16 - (paramsSize&15);
+					op64(ctx,SUB,PESP,pconst(&p,paramsSize));
+					op64(ctx,MOV,r,PESP);
+
+					for(i=0;i<o->p3-1;i++) {
+						vreg *a = R(o->extra[i+1]);
+						if( hl_is_ptr(a->t) ) {
+							op64(ctx,MOV,pmem(&p,r->id,i*HL_WSIZE),alloc_cpu(ctx,a,true));
+							if( a->current != v ) RUNLOCK(a->current);
+						} else {
+							preg *r2 = alloc_reg(ctx,RCPU);
+							op64(ctx,LEA,r2,&a->stack);
+							op64(ctx,MOV,pmem(&p,r->id,i*HL_WSIZE),r2);
+							if( r2 != v ) RUNLOCK(r2);
+						}
+					}
+
+					size = pad_stack(ctx,HL_WSIZE*4);
+
+					if( hl_is_ptr(dst->t) || dst->t->kind == HVOID )
+						op64(ctx,PUSH,pconst(&p,0),UNUSED);
+					else 
+						jit_error("TODO");
+
+					op64(ctx,PUSH,r,UNUSED);
+					op64(ctx,PUSH,pconst(&p,obj->t->virt->fields[o->p2].hashed_name),UNUSED); // fid
+					op64(ctx,PUSH,pconst64(&p,(int_val)obj->t->virt->fields[o->p2].t),UNUSED); // ftype
+					op64(ctx,PUSH,pmem(&p,v->id,HL_WSIZE),UNUSED); // o->value
+
+					op64(ctx,MOV,PEAX,pconst64(&p,(int_val)hl_dyn_call_obj));
+
+					op64(ctx,CALL,PEAX,UNUSED);
+					discard_regs(ctx,true);
+
+					op64(ctx,ADD,PESP,pconst(&p,size + paramsSize));
+
+					BREAK();
+					
+					XJump_small(JAlways,jend);
+					patch_jump(ctx,jhasfield);
+					size = prepare_call_args(ctx,o->p3,o->extra,ctx->vregs,false,0);
+					op64(ctx,CALL,r,UNUSED);
+					discard_regs(ctx, false);
+					op64(ctx,ADD,PESP,pconst(&p,size));
+					store(ctx, dst, IS_FLOAT(dst) ? PXMM(0) : PEAX, true);
+					patch_jump(ctx,jend);
+				}				
 				break;
 			}
 			break;