From 084eaaecbd26133891c6f1f78491efdc093aff68 Mon Sep 17 00:00:00 2001 From: dzaima Date: Sat, 25 Sep 2021 23:05:15 +0300 Subject: [PATCH] SETC --- src/jit/nvm_x86_64.c | 23 +++++++++++++++++------ src/vm.c | 22 ++++++++++++++++------ src/vm.h | 7 ++++--- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/jit/nvm_x86_64.c b/src/jit/nvm_x86_64.c index b9323f71..9538190c 100644 --- a/src/jit/nvm_x86_64.c +++ b/src/jit/nvm_x86_64.c @@ -127,6 +127,12 @@ INS B i_SETM(B s, B f, B x, Scope** pscs, u32* bc) { POS_UPD; v_set(pscs, s, r, true); dec(s); return r; } +INS B i_SETC(B s, B f, Scope** pscs, u32* bc) { POS_UPD; + B x = v_get(pscs, s); + B r = c1(f,x); dec(f); + v_set(pscs, s, r, true); dec(s); + return r; +} INS B i_SETH(B s, B x, Scope** pscs, u32* bc, Body* v1, Body* v2) { POS_UPD; bool ok = v_seth(pscs, s, x); dec(x); dec(s); if (ok) return bi_okHdr; @@ -143,9 +149,11 @@ INS B i_SETH(B s, B x, Scope** pscs, u32* bc, Body* v1, Body* v2) { POS_UPD; INS B i_SETNi( B x, Scope* sc, u32 p, u32* bc) { POS_UPD; v_setI(sc, p, inc(x), false); return x; } INS B i_SETUi( B x, Scope* sc, u32 p, u32* bc) { POS_UPD; v_setI(sc, p, inc(x), true ); return x; } INS B i_SETMi(B f, B x, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c2(f,v_getI(sc, p),x); dec(f); v_setI(sc, p, inc(r), true); return r; } +INS B i_SETCi(B f, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c1(f,v_getI(sc, p) ); dec(f); v_setI(sc, p, inc(r), true); return r; } INS void i_SETNv(B x, Scope* sc, u32 p, u32* bc) { POS_UPD; v_setI(sc, p, x, false); } INS void i_SETUv(B x, Scope* sc, u32 p, u32* bc) { POS_UPD; v_setI(sc, p, x, true ); } INS void i_SETMv(B f, B x, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c2(f,v_getI(sc, p),x); dec(f); v_setI(sc, p, r, true); } +INS void i_SETCv(B f, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c1(f,v_getI(sc, p) ); dec(f); v_setI(sc, p, r, true); } INS B i_FLDO(B ns, u32 p, Scope* sc) { if (!isNsp(ns)) thrM("Trying to read a field from non-namespace"); B r = inc(ns_getU(ns, sc->body->nsDesc->nameList, p)); @@ -297,7 +305,7 @@ static OptRes opt(u32* bc0) { stk[TSSIZE(stk)-1] = SREF(d, pos); break; } - case SETN: case SETU: case SETM: { S(s,0) + case SETN: case SETU: case SETM: case SETC: { S(s,0) if (!isVar(s.v)) goto defIns; cact = 2; RM(s.p); TSADD(data, s.v.u); @@ -356,15 +364,15 @@ static OptRes opt(u32* bc0) { u64 psz = TSSIZE(rbc); #define A64(X) { u64 a64=(X); TSADD(rbc, (u32)a64); TSADD(rbc, a64>>32); } switch (ctype) { default: UD; - case 2: { assert(v==SETN|v==SETU|v==SETM); - TSADD(rbc, v==SETN? SETNi : v==SETU? SETUi : SETMi); + case 2: { assert(v==SETN|v==SETU|v==SETM|v==SETC); + TSADD(rbc, v==SETN? SETNi : v==SETU? SETUi : v==SETC? SETCi : SETMi); u64 d = data[dpos++]; TSADD(rbc, (u16)(d>>32)); TSADD(rbc, (u32)d); break; } - case 7: { assert(v==SETN|v==SETU|v==SETM); - TSADD(rbc, v==SETN? SETNv : v==SETU? SETUv : SETMv); + case 7: { assert(v==SETN|v==SETU|v==SETM|v==SETC); + TSADD(rbc, v==SETN? SETNv : v==SETU? SETUv : v==SETC? SETCv : SETMv); u64 d = data[dpos++]; TSADD(rbc, (u16)(d>>32)); TSADD(rbc, (u32)d); @@ -597,13 +605,16 @@ Nvm_res m_nvm(Body* body) { case SETN: TOPp; GET(R_A1,1,1); LEAi(R_A2,R_SP,VAR(pscs,0)); IMM(R_A3,off); CCALL(i_SETN); break; // (B s, B x, Scope** pscs, u32* bc) case SETU: TOPp; GET(R_A1,1,1); LEAi(R_A2,R_SP,VAR(pscs,0)); IMM(R_A3,off); CCALL(i_SETU); break; // (B s, B x, Scope** pscs, u32* bc) case SETM: TOPp; GET(R_A1,1,1); GET(R_A2,2,1); LEAi(R_A3,R_SP,VAR(pscs,0)); IMM(R_A4,off); CCALL(i_SETM); break; // (B s, B f, B x, Scope** pscs, u32* bc) + case SETC: TOPp; GET(R_A1,1,1); LEAi(R_A2,R_SP,VAR(pscs,0)); IMM(R_A3,off); CCALL(i_SETC); break; // (B s, B f, Scope** pscs, u32* bc) // TODO SETNi doesn't really need to update gStack case SETNi:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,0,2); LSC(R_A1,d); IMM(R_A2,p); IMM(R_A3,off); CCALL(i_SETNi); break; } // ( B x, Scope* sc, u32 p, u32* bc) case SETUi:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,0,2); LSC(R_A1,d); IMM(R_A2,p); IMM(R_A3,off); CCALL(i_SETUi); break; } // ( B x, Scope* sc, u32 p, u32* bc) case SETMi:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,1,1); LSC(R_A2,d); IMM(R_A3,p); IMM(R_A4,off); CCALL(i_SETMi); break; } // (B f, B x, Scope* sc, u32 p, u32* bc) + case SETCi:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,0,2); LSC(R_A1,d); IMM(R_A2,p); IMM(R_A3,off); CCALL(i_SETCi); break; } // (B f, Scope* sc, u32 p, u32* bc) case SETNv:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,0,2); LSC(R_A1,d); IMM(R_A2,p); IMM(R_A3,off); CCALL(i_SETNv); NORES(1); break; } // ( B x, Scope* sc, u32 p, u32* bc) case SETUv:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,0,2); LSC(R_A1,d); IMM(R_A2,p); IMM(R_A3,off); CCALL(i_SETUv); NORES(1); break; } // ( B x, Scope* sc, u32 p, u32* bc) case SETMv:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,1,1); LSC(R_A2,d); IMM(R_A3,p); IMM(R_A4,off); CCALL(i_SETMv); NORES(2); break; } // (B f, B x, Scope* sc, u32 p, u32* bc) + case SETCv:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,0,2); LSC(R_A1,d); IMM(R_A2,p); IMM(R_A3,off); CCALL(i_SETCv); NORES(1); break; } // (B f, Scope* sc, u32 p, u32* bc) case FLDO: TOPp; GET(R_A1,0,2); IMM(R_A1,*bc++); MOV(R_A2,r_SC); CCALL(i_FLDO); break; // (B, u32 p, Scope* sc) case ALIM: TOPp; IMM(R_A1,*bc++); CCALL(i_ALIM); break; // (B, u32 l) case VFYM: TOPp; CCALL(i_VFYM); break; // (B) @@ -611,7 +622,7 @@ Nvm_res m_nvm(Body* body) { case RETD: if (lGPos!=0) GS_SET(r_CS); MOV(R_A0,r_SC); CCALL(i_RETD); ret=true; break; // (Scope* sc) case RETN: if (lGPos!=0) GS_SET(r_CS); ret=true; break; case FAIL: TOPs; IMM(R_A0,off); MOV(R_A1,r_SC); INV(2,0,i_FAIL); ret=true; break; - default: thrF("JIT: Unsupported bytecode %i/%S", *s, nameBC(s)); + default: thrF("JIT: Unsupported bytecode %i/%S", *s, bc_repr(s)); } #undef GET #undef GS_SET diff --git a/src/vm.c b/src/vm.c index f7a0fe4c..1c6a4565 100644 --- a/src/vm.c +++ b/src/vm.c @@ -11,10 +11,10 @@ #endif #define FOR_BC(F) F(PUSH) F(DYNO) F(DYNM) F(ARRO) F(ARRM) F(FN1C) F(FN2C) F(MD1C) F(MD2C) F(TR2D) \ - F(TR3D) F(SETN) F(SETU) F(SETM) F(POPS) F(DFND) F(FN1O) F(FN2O) F(CHKV) F(TR3O) \ + F(TR3D) F(SETN) F(SETU) F(SETM) F(SETC) F(POPS) F(DFND) F(FN1O) F(FN2O) F(CHKV) F(TR3O) \ F(MD2R) F(VARO) F(VARM) F(VFYM) F(SETH) F(RETN) F(FLDO) F(FLDM) F(ALIM) F(RETD) F(SYSV) F(VARU) \ F(EXTO) F(EXTM) F(EXTU) F(ADDI) F(ADDU) F(FN1Ci)F(FN1Oi)F(FN2Ci)F(FN2Oi) \ - F(SETNi)F(SETUi)F(SETMi)F(SETNv)F(SETUv)F(SETMv)F(FAIL) + F(SETNi)F(SETUi)F(SETMi)F(SETCi)F(SETNv)F(SETUv)F(SETMv)F(SETCv)F(FAIL) u32* nextBC(u32* p) { i32 off; @@ -22,7 +22,7 @@ u32* nextBC(u32* p) { case FN1C: case FN2C: case FN1O: case FN2O: case MD1C: case MD2C: case MD2R: case TR2D: case TR3D: case TR3O: - case SETN: case SETU: case SETM: case SETH: + case SETN: case SETU: case SETM: case SETH: case SETC: case POPS: case CHKV: case VFYM: case RETN: case RETD: case FAIL: off = 1; break; @@ -34,7 +34,8 @@ u32* nextBC(u32* p) { case EXTO: case EXTM: case EXTU: case ADDI: case ADDU: case FN1Ci: case FN1Oi: case FN2Ci: case DFND0: case DFND1: case DFND2: - case SETNi: case SETUi: case SETMi: case SETNv: case SETUv: case SETMv: + case SETNi: case SETUi: case SETMi: case SETCi: + case SETNv: case SETUv: case SETMv: case SETCv: off = 3; break; case FN2Oi: case SETHi: off = 5; break; @@ -52,6 +53,7 @@ i32 stackDiff(u32* p) { case SETN: return -1; case SETNi:return 0; case SETNv:return -1; case SETU: return -1; case SETUi:return 0; case SETUv:return -1; + case SETC: return -1; case SETCi:return 0; case SETCv:return -1; case SETM: return -2; case SETMi:return -1; case SETMv:return -2; case FAIL: return 0; } @@ -68,6 +70,7 @@ i32 stackConsumed(u32* p) { case SETN: return 2; case SETNi: case SETNv: return 1; case SETU: return 2; case SETUi: case SETUv: return 1; + case SETC: return 2; case SETCi: case SETCv: return 1; case SETM: return 3; case SETMi: case SETMv: return 2; case FAIL: return 0; } @@ -76,7 +79,7 @@ i32 stackAdded(u32* p) { if (*p==ARRO|*p==ARRM) return 1; return stackDiff(p)+stackConsumed(p); } -char* nameBC(u32* p) { +char* bc_repr(u32* p) { switch(*p) { default: return "(unknown)"; #define F(X) case X: return #X; FOR_BC(F) @@ -84,7 +87,7 @@ char* nameBC(u32* p) { } } void printBC(u32* p) { - printf("%s", nameBC(p)); + printf("%s", bc_repr(p)); u32* n = nextBC(p); p++; i64 am = n-p; @@ -692,6 +695,13 @@ B evalBC(Block* bl, Body* b, Scope* sc) { // doesn't consume ADD(r); break; } + case SETC: { P(s)P(f) GS_UPD; POS_UPD; + B x = v_get(pscs, s); + B r = c1(f,x); dec(f); + v_set(pscs, s, r, true); dec(s); + ADD(r); + break; + } case SETHi:{ P(s) P(x) GS_UPD; POS_UPD; u64 v1 = L64; u64 v2 = L64; bool ok = v_seth(pscs, s, x); dec(x); dec(s); if (!ok) { diff --git a/src/vm.h b/src/vm.h index e4fbfd6a..0f1b88a6 100644 --- a/src/vm.h +++ b/src/vm.h @@ -46,14 +46,15 @@ enum { SETN = 0x30, // set new; _ ←_; ⟨…,x, mut⟩ → mut←x SETU = 0x31, // set upd; _ ↩_; ⟨…,x, mut⟩ → mut↩x SETM = 0x32, // set mod; _ F↩_; ⟨…,x,F,mut⟩ → mut F↩x + SETC = 0x33, // set call; _ F↩; (…, F,mut) → mut F↩ FLDO = 0x40, // N; get field nameList[N] from ToS FLDM = 0x41, // N; get mutable field nameList[N] from ToS ALIM = 0x42, // N; replace ToS with one with a namespace field alias N EXTO, EXTM, EXTU, // alternate versions of VAR_ for extended variables ADDI, ADDU, // separate PUSH for refcounting needed/not needed (stores the object inline as 2 u32s, instead of reading from `objs`) FN1Ci, FN1Oi, FN2Ci, FN2Oi, // FN__ alternatives that don't take the function from the stack, but instead as an 2×u32 immediate in the bytecode - SETNi, SETUi, SETMi, // SET_ alternatives that expect the set variable as a depth-position pair like VAR_ - SETNv, SETUv, SETMv, // SET_i alternatives that also don't return the result + SETNi, SETUi, SETMi, SETCi, // SET_ alternatives that expect the set variable as a depth-position pair like VAR_ + SETNv, SETUv, SETMv, SETCv, // SET_i alternatives that also don't return the result SETHi, // internal version of SETH, with 2×u64 arguments specifying bodies to jump to on fail (or NULL if is last) DFND0, DFND1, DFND2, // internal versions of DFND with a specific type, and a u64 argument representing the block pointer FAIL, // this body cannot be called monadically/dyadically @@ -165,7 +166,7 @@ u32* nextBC(u32* p); i32 stackDiff(u32* p); i32 stackConsumed(u32* p); i32 stackAdded(u32* p); -char* nameBC(u32* p); +char* bc_repr(u32* p); typedef struct FunBlock { struct Fun; Scope* sc; Block* bl; } FunBlock;