This commit is contained in:
dzaima 2021-09-25 23:05:15 +03:00
parent 4f0841c95e
commit 084eaaecbd
3 changed files with 37 additions and 15 deletions

View File

@ -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); v_set(pscs, s, r, true); dec(s);
return r; 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; 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); bool ok = v_seth(pscs, s, x); dec(x); dec(s);
if (ok) return bi_okHdr; 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_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_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_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_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_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_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) { INS B i_FLDO(B ns, u32 p, Scope* sc) {
if (!isNsp(ns)) thrM("Trying to read a field from non-namespace"); if (!isNsp(ns)) thrM("Trying to read a field from non-namespace");
B r = inc(ns_getU(ns, sc->body->nsDesc->nameList, p)); 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); stk[TSSIZE(stk)-1] = SREF(d, pos);
break; 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; if (!isVar(s.v)) goto defIns;
cact = 2; RM(s.p); cact = 2; RM(s.p);
TSADD(data, s.v.u); TSADD(data, s.v.u);
@ -356,15 +364,15 @@ static OptRes opt(u32* bc0) {
u64 psz = TSSIZE(rbc); u64 psz = TSSIZE(rbc);
#define A64(X) { u64 a64=(X); TSADD(rbc, (u32)a64); TSADD(rbc, a64>>32); } #define A64(X) { u64 a64=(X); TSADD(rbc, (u32)a64); TSADD(rbc, a64>>32); }
switch (ctype) { default: UD; switch (ctype) { default: UD;
case 2: { assert(v==SETN|v==SETU|v==SETM); case 2: { assert(v==SETN|v==SETU|v==SETM|v==SETC);
TSADD(rbc, v==SETN? SETNi : v==SETU? SETUi : SETMi); TSADD(rbc, v==SETN? SETNi : v==SETU? SETUi : v==SETC? SETCi : SETMi);
u64 d = data[dpos++]; u64 d = data[dpos++];
TSADD(rbc, (u16)(d>>32)); TSADD(rbc, (u16)(d>>32));
TSADD(rbc, (u32)d); TSADD(rbc, (u32)d);
break; break;
} }
case 7: { assert(v==SETN|v==SETU|v==SETM); case 7: { assert(v==SETN|v==SETU|v==SETM|v==SETC);
TSADD(rbc, v==SETN? SETNv : v==SETU? SETUv : SETMv); TSADD(rbc, v==SETN? SETNv : v==SETU? SETUv : v==SETC? SETCv : SETMv);
u64 d = data[dpos++]; u64 d = data[dpos++];
TSADD(rbc, (u16)(d>>32)); TSADD(rbc, (u16)(d>>32));
TSADD(rbc, (u32)d); 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 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 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 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 // 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 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 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 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 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 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 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 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 ALIM: TOPp; IMM(R_A1,*bc++); CCALL(i_ALIM); break; // (B, u32 l)
case VFYM: TOPp; CCALL(i_VFYM); break; // (B) 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 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 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; 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 GET
#undef GS_SET #undef GS_SET

View File

@ -11,10 +11,10 @@
#endif #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) \ #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(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(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) { u32* nextBC(u32* p) {
i32 off; i32 off;
@ -22,7 +22,7 @@ u32* nextBC(u32* p) {
case FN1C: case FN2C: case FN1O: case FN2O: case FN1C: case FN2C: case FN1O: case FN2O:
case MD1C: case MD2C: case MD2R: case MD1C: case MD2C: case MD2R:
case TR2D: case TR3D: case TR3O: 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 POPS: case CHKV: case VFYM: case RETN: case RETD:
case FAIL: case FAIL:
off = 1; break; off = 1; break;
@ -34,7 +34,8 @@ u32* nextBC(u32* p) {
case EXTO: case EXTM: case EXTU: case EXTO: case EXTM: case EXTU:
case ADDI: case ADDU: case ADDI: case ADDU:
case FN1Ci: case FN1Oi: case FN2Ci: case DFND0: case DFND1: case DFND2: 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; off = 3; break;
case FN2Oi: case SETHi: case FN2Oi: case SETHi:
off = 5; break; off = 5; break;
@ -52,6 +53,7 @@ i32 stackDiff(u32* p) {
case SETN: return -1; case SETNi:return 0; case SETNv:return -1; 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 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 SETM: return -2; case SETMi:return -1; case SETMv:return -2;
case FAIL: return 0; case FAIL: return 0;
} }
@ -68,6 +70,7 @@ i32 stackConsumed(u32* p) {
case SETN: return 2; case SETNi: case SETNv: return 1; case SETN: return 2; case SETNi: case SETNv: return 1;
case SETU: return 2; case SETUi: case SETUv: 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 SETM: return 3; case SETMi: case SETMv: return 2;
case FAIL: return 0; case FAIL: return 0;
} }
@ -76,7 +79,7 @@ i32 stackAdded(u32* p) {
if (*p==ARRO|*p==ARRM) return 1; if (*p==ARRO|*p==ARRM) return 1;
return stackDiff(p)+stackConsumed(p); return stackDiff(p)+stackConsumed(p);
} }
char* nameBC(u32* p) { char* bc_repr(u32* p) {
switch(*p) { default: return "(unknown)"; switch(*p) { default: return "(unknown)";
#define F(X) case X: return #X; #define F(X) case X: return #X;
FOR_BC(F) FOR_BC(F)
@ -84,7 +87,7 @@ char* nameBC(u32* p) {
} }
} }
void printBC(u32* p) { void printBC(u32* p) {
printf("%s", nameBC(p)); printf("%s", bc_repr(p));
u32* n = nextBC(p); u32* n = nextBC(p);
p++; p++;
i64 am = n-p; i64 am = n-p;
@ -692,6 +695,13 @@ B evalBC(Block* bl, Body* b, Scope* sc) { // doesn't consume
ADD(r); ADD(r);
break; 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; 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); bool ok = v_seth(pscs, s, x); dec(x); dec(s);
if (!ok) { if (!ok) {

View File

@ -46,14 +46,15 @@ enum {
SETN = 0x30, // set new; _ ←_; ⟨…,x, mut⟩ → mut←x SETN = 0x30, // set new; _ ←_; ⟨…,x, mut⟩ → mut←x
SETU = 0x31, // set upd; _ ↩_; ⟨…,x, mut⟩ → mut↩x SETU = 0x31, // set upd; _ ↩_; ⟨…,x, mut⟩ → mut↩x
SETM = 0x32, // set mod; _ F↩_; ⟨…,x,F,mut⟩ → mut F↩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 FLDO = 0x40, // N; get field nameList[N] from ToS
FLDM = 0x41, // N; get mutable 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 ALIM = 0x42, // N; replace ToS with one with a namespace field alias N
EXTO, EXTM, EXTU, // alternate versions of VAR_ for extended variables 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`) 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 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_ SETNi, SETUi, SETMi, SETCi, // 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 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) 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 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 FAIL, // this body cannot be called monadically/dyadically
@ -165,7 +166,7 @@ u32* nextBC(u32* p);
i32 stackDiff(u32* p); i32 stackDiff(u32* p);
i32 stackConsumed(u32* p); i32 stackConsumed(u32* p);
i32 stackAdded(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; typedef struct FunBlock { struct Fun; Scope* sc; Block* bl; } FunBlock;