merged LOCM;SET_

This commit is contained in:
dzaima 2021-06-19 02:19:28 +03:00
parent d47d538a16
commit fb02f30259
3 changed files with 56 additions and 19 deletions

View File

@ -156,6 +156,14 @@ INS B i_SETM(B s, Scope** pscs, u32* bc GA1) { P(f)P(x) GS_UPD; POS_UPD;
v_set(pscs, s, r, true); dec(s);
return r;
}
INS B i_SETNi(B x, Scope** pscs, u32 d, u32 p, u32* bc GA1) { GS_UPD; POS_UPD; v_setI(pscs, d, p, inc(x), false); return x; }
INS B i_SETUi(B x, Scope** pscs, u32 d, u32 p, u32* bc GA1) { GS_UPD; POS_UPD; v_setI(pscs, d, p, inc(x), true ); return x; }
INS B i_SETMi(B f, Scope** pscs, u32 d, u32 p, u32* bc GA1) { P(x) GS_UPD; POS_UPD;
B w = v_getI(pscs, d, p);
B r = c2(f,w,x); dec(f);
v_setI(pscs, d, p, inc(r), true);
return r;
}
INS B i_FLDO(B ns, u32 p, Scope** pscs GA1) { GS_UPD;
if (!isNsp(ns)) thrM("Trying to read a field from non-namespace");
B r = inc(ns_getU(ns, pscs[0]->body->nsDesc->nameList, p));
@ -218,7 +226,7 @@ void nvm_free(u8* ptr) {
file_wChars(m_str32(U"asm_off"), o); dec(o);
B s = inc(bi_emptyCVec);
#define F(X) AFMT("s/%p$/%p == i_" #X "/;", i_##X, i_##X);
F(POPS) F(ADDI) F(ADDU) F(FN1C) F(FN1O) F(FN2C) F(FN2O) F(FN1Ci) F(FN2Ci) F(FN1Oi) F(FN2Oi) F(ARR_0) F(ARR_p) F(DFND_0) F(DFND_1) F(DFND_2) F(OP1D) F(OP2D) F(OP2H) F(TR2D) F(TR3D) F(TR3O) F(LOCO) F(LOCU) F(EXTO) F(EXTU) F(SETN) F(SETU) F(SETM) F(FLDO) F(NSPM) F(RETD)
F(POPS) F(ADDI) F(ADDU) F(FN1C) F(FN1O) F(FN2C) F(FN2O) F(FN1Ci) F(FN2Ci) F(FN1Oi) F(FN2Oi) F(ARR_0) F(ARR_p) F(DFND_0) F(DFND_1) F(DFND_2) F(OP1D) F(OP2D) F(OP2H) F(TR2D) F(TR3D) F(TR3O) F(LOCO) F(LOCU) F(EXTO) F(EXTU) F(SETN) F(SETU) F(SETM) F(FLDO) F(NSPM) F(RETD) F(SETNi) F(SETUi) F(SETMi)
#undef F
file_wChars(m_str32(U"asm_sed"), s); dec(s);
}
@ -230,7 +238,7 @@ typedef struct SRef { B v; i32 p; } SRef;
typedef struct OptRes { u32* bc; u32* offset; B refs; } OptRes;
static OptRes opt(u32* bc0) {
TSALLOC(SRef, stk, 8);
TSALLOC(u8, actions, 64); // 1 per instruction; 0: nothing; 1: indicates return; 3: FN1_/FN2C; 4: FN2O; 5: replace with PUSH; 6: decrement 1 data; 10+N: ignore N data
TSALLOC(u8, actions, 64); // 1 per instruction; 0: nothing; 1: indicates return; 2: immediate SET; 3: immediate FN1_/FN2C; 4: FN2O; 5: replace with PUSH; 6: decrement 1 data; 10+N: ignore N data
TSALLOC(u64, data, 64); // variable length; whatever things are needed for the specific action
u8 rm_map[] = {10,10,10,11,12,6,6,99,99,99,11,12,13,14,15,16,17,18,19};
#define RM(N) actions[N] = rm_map[actions[N]]
@ -243,6 +251,10 @@ static OptRes opt(u32* bc0) {
#define S(N,I) SRef N = stk[TSSIZE(stk)-1-(I)];
switch (*bc++) { case FN1Ci: case FN1Oi: case FN2Ci: case FN2Oi: thrM("JIT optimization: didn't already expect immediate FN__");
case ADDU: case ADDI: cact = 0; TSADD(stk,SREF(b(L64), pos)); break;
case LOCM: { u32 d = *bc++; u32 p = *bc++;
TSADD(stk,SREF(tag((u64)d<<32 | (u32)p, VAR_TAG), pos));
break;
}
case FN1C: case FN1O: { S(f,0)
if (!isFun(f.v) || v(f.v)->type!=t_funBI) goto defIns;
RM(f.p); cact = 3;
@ -299,6 +311,13 @@ static OptRes opt(u32* bc0) {
stk[TSSIZE(stk)-1] = SREF(d, pos);
break;
}
case SETN: case SETU: case SETM: { S(s,0)
if (!isVar(s.v)) goto defIns;
cact = 2; RM(s.p);
TSADD(data, s.v.u);
TSSIZE(stk)-= SETM==*sbc? 2 : 1;
break;
}
case RETN: case RETD:
ret = true;
cact = 1;
@ -333,6 +352,12 @@ 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);
u64 d = data[dpos++];
TSADD(rbc, (u16)(d>>32));
TSADD(rbc, (u32)d);
break;
case 3: assert(v==FN1C|v==FN1O|v==FN2C);
TSADD(rbc, v==FN1C? FN1Ci : v==FN1O? FN1Oi : FN2Ci);
A64(data[dpos++]);
@ -466,6 +491,9 @@ Nvm_res m_nvm(Body* body) {
case SETN: TOPp; ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,off); INV(3,0,i_SETN); break; // (B, Scope** pscs, u32* bc, S)
case SETU: TOPp; ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,off); INV(3,0,i_SETU); break; // (B, Scope** pscs, u32* bc, S)
case SETM: TOPp; ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,off); INV(3,0,i_SETM); break; // (B, Scope** pscs, u32* bc, S)
case SETNi:TOPp; { u64 d=*bc++; u64 p=*bc++; ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,d); IMM(REG_ARG3,p); IMM(REG_ARG4,off); INV(5,0,i_SETNi); break; } // (B, Scope** pscs. u32 d. u32 p, u32* bc, S)
case SETUi:TOPp; { u64 d=*bc++; u64 p=*bc++; ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,d); IMM(REG_ARG3,p); IMM(REG_ARG4,off); INV(5,0,i_SETUi); break; } // (B, Scope** pscs. u32 d. u32 p, u32* bc, S)
case SETMi:TOPp; { u64 d=*bc++; u64 p=*bc++; ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,d); IMM(REG_ARG3,p); IMM(REG_ARG4,off); INV(5,0,i_SETMi); break; } // (B, Scope** pscs. u32 d. u32 p, u32* bc, S)
case FLDO: TOPp; IMM(REG_ARG1,*bc++); ASM(MOV,REG_ARG2,r_PSCS); INV(3,0,i_FLDO); break; // (B, u32 p, Scope** pscs, S)
case NSPM: TOPp; IMM(REG_ARG1,*bc++); CCALL(i_NSPM); break; // (B, u32 l, S)
case RETD: ASM(MOV,REG_ARG0,r_PSCS); INV(1,1,i_RETD); ret=true; break; // (Scope** pscs, S); stack diff 0 is wrong, but updating it is useless

View File

@ -30,7 +30,8 @@ u32* nextBC(u32* p) {
return p+2;
case LOCO: case LOCM: case LOCU:
case EXTO: case EXTM: case EXTU:
case ADDI: case ADDU: case FN1Ci: case FN1Oi: case FN2Ci:
case ADDI: case ADDU:
case FN1Ci: case FN1Oi: case FN2Ci: case SETNi: case SETUi: case SETMi:
return p+3;
case FN2Oi:
return p+5;
@ -41,8 +42,8 @@ i32 stackDiff(u32* p) {
if (*p==ARRO|*p==ARRM) return 1-p[1];
switch(*p) { default: UD; // case ARRO: case ARRM: return 1-p[1];
case PUSH: case VARO: case VARM: case DFND: case LOCO: case LOCM: case LOCU: case EXTO: case EXTM: case EXTU: case SYSV: case ADDI: case ADDU: return 1;
case FN1Ci:case FN1Oi:case CHKV: case VFYM: case FLDO: case FLDM: case RETD: case NSPM: return 0;
case FN2Ci:case FN2Oi:case FN1C: case FN1O: case OP1D: case TR2D: case SETN: case SETU: case POPS: case OP2H: case SETH: case RETN: return -1;
case FN1Ci:case FN1Oi:case CHKV: case VFYM: case FLDO: case FLDM: case SETNi:case SETUi:case RETD: case NSPM: return 0;
case FN2Ci:case FN2Oi:case FN1C: case FN1O: case OP1D: case TR2D: case SETN: case SETU: case SETMi:case POPS: case OP2H: case SETH: case RETN: return -1;
case OP2D: case TR3D: case FN2C: case FN2O: case SETM: case TR3O: return -2;
}
}
@ -51,8 +52,8 @@ i32 stackConsumed(u32* p) {
switch(*p) { default: UD; // case ARRO: case ARRM: return -p[1];
case PUSH: case VARO: case VARM: case DFND: case LOCO: case LOCM: case LOCU: case EXTO: case EXTM: case EXTU: case SYSV: case ADDI: case ADDU: return 0;
case CHKV: case VFYM: case RETD: return 0;
case FN1Ci:case FN1Oi:case FLDO: case FLDM: case NSPM: case RETN: case POPS: return 1;
case FN2Ci:case FN2Oi:case FN1C: case FN1O: case OP1D: case TR2D: case SETN: case SETU: case OP2H: case SETH: return 2;
case FN1Ci:case FN1Oi:case FLDO: case FLDM: case NSPM: case RETN: case POPS: case SETNi:case SETUi:return 1;
case FN2Ci:case FN2Oi:case FN1C: case FN1O: case SETMi:case OP1D: case TR2D: case SETN: case SETU: case OP2H: case SETH: return 2;
case OP2D: case TR3D: case FN2C: case FN2O: case SETM: case TR3O: return 3;
}
}

View File

@ -36,6 +36,7 @@ enum {
EXTO, EXTM, EXTU, // alternate versions of LOC_ 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 LOC_
BC_SIZE
};
@ -155,23 +156,30 @@ typedef struct FldAlias {
i32 p;
} FldAlias;
NOINLINE B v_getR(Scope* pscs[], B s);
static B v_get(Scope* pscs[], B s) { // get value representing s, replacing with bi_optOut; doesn't consume
if (RARE(!isVar(s))) return v_getR(pscs, s);
Scope* sc = pscs[(u16)(s.u>>32)];
B r = sc->vars[(u32)s.u];
sc->vars[(u32)s.u] = bi_optOut;
NOINLINE B v_getR(Scope* pscs[], B s); // doesn't consume
static inline B v_getI(Scope* pscs[], u32 d, u32 p) {
Scope* sc = pscs[d];
B r = sc->vars[p];
sc->vars[p] = bi_optOut;
return r;
}
static inline B v_get(Scope* pscs[], B s) { // get value representing s, replacing with bi_optOut; doesn't consume
if (RARE(!isVar(s))) return v_getR(pscs, s);
return v_getI(pscs, (u16)(s.u>>32), (u32)s.u);
}
NOINLINE void v_setR(Scope* pscs[], B s, B x, bool upd);
static void v_set(Scope* pscs[], B s, B x, bool upd) { // doesn't consume
if (RARE(!isVar(s))) return v_setR(pscs, s, x, upd);;
Scope* sc = pscs[(u16)(s.u>>32)];
B prev = sc->vars[(u32)s.u];
NOINLINE void v_setR(Scope* pscs[], B s, B x, bool upd); // doesn't consume
static inline void v_setI(Scope* pscs[], u32 d, u32 p, B x, bool upd) { // consumes x
Scope* sc = pscs[d];
B prev = sc->vars[p];
if (upd) {
if (prev.u==bi_noVar.u) thrM("↩: Updating undefined variable");
dec(prev);
}
sc->vars[(u32)s.u] = inc(x);
sc->vars[p] = x;
}
static inline void v_set(Scope* pscs[], B s, B x, bool upd) { // doesn't consume
if (RARE(!isVar(s))) return v_setR(pscs, s, x, upd);
v_setI(pscs, (u16)(s.u>>32), (u32)s.u, inc(x), upd);
}