store directly needed blocks in bodies
This commit is contained in:
parent
582273229b
commit
7bf3b4be50
@ -14,7 +14,7 @@ tests ← •FLines path∾"/test/cases/prim.bqn"
|
||||
'%'⊸∊◶{𝕤
|
||||
•Out 𝕩
|
||||
"src/gen/interp" •FChars ⟨1,path,𝕩⟩ •Import "cc.bqn"
|
||||
(×⊑)◶@‿{𝕤⋄•Out "############ Failed to compile! ############" ⋄ •Out¨1↓𝕩}{env⇐<"PATH="∾envP}•SH"./debugBuild"‿"-DNO_COMP"
|
||||
(×⊑)◶@‿{𝕤⋄•Out "############ Failed to compile! ############" ⋄ •Out¨1↓𝕩}{env⇐<"PATH="∾envP}•SH"./debugBuild"‿"-DPRECOMP"
|
||||
code‿out‿err←•SH"./BQN"
|
||||
•Out out
|
||||
{𝕤⋄•Out"exit code "∾(⍕code) ⋄ •Out err}⍟(×code) err
|
||||
|
||||
@ -337,7 +337,7 @@ char* format_type(u8 u) {
|
||||
case t_md1D:return"md1D"; case t_md2D:return"md2D"; case t_md2H:return"md2H";
|
||||
case t_harr :return"harr" ; case t_i8arr :return"i8arr" ; case t_i32arr :return"i32arr" ; case t_fillarr :return"fillarr" ; case t_c32arr :return"c32arr" ; case t_f64arr :return"f64arr" ;
|
||||
case t_hslice:return"hslice"; case t_i8slice:return"i8slice"; case t_i32slice:return"i32slice"; case t_fillslice:return"fillslice"; case t_c32slice:return"c32slice"; case t_f64slice:return"f64slice";
|
||||
case t_comp:return"comp"; case t_block:return"block"; case t_body:return"body"; case t_scope:return"scope";
|
||||
case t_comp:return"comp"; case t_block:return"block"; case t_body:return"body"; case t_scope:return"scope"; case t_blBlocks: return "block list";
|
||||
case t_ns:return"ns"; case t_nsDesc:return"nsDesc"; case t_fldAlias:return"alias"; case t_hashmap:return"hashmap"; case t_temp:return"temporary";
|
||||
case t_freed:return"(freed by GC)"; case t_harrPartial:return"partHarr";
|
||||
#ifdef RT_WRAP
|
||||
@ -457,7 +457,7 @@ B bqn_merge(B x) { // consumes
|
||||
NOINLINE void printAllocStats() {
|
||||
#ifdef ALLOC_STAT
|
||||
printf("total ever allocated: %lu\n", talloc);
|
||||
printf("allocated heap size: %ld\n", mm_heapAllocated());
|
||||
printf("allocated heap size: %ld\n", mm_heapAlloc);
|
||||
printf("used heap size: %ld\n", mm_heapUsed());
|
||||
ctr_a[t_harr]+= ctr_a[t_harrPartial];
|
||||
ctr_a[t_harrPartial] = 0;
|
||||
|
||||
@ -8,7 +8,6 @@ static void mm_free(Value* x);
|
||||
static u64 mm_size(Value* x);
|
||||
static void mm_visit(B x);
|
||||
static void mm_visitP(void* x);
|
||||
static u64 mm_heapAllocated();
|
||||
u64 mm_heapUsed();
|
||||
void printAllocStats();
|
||||
static B mm_alloc(usz sz, u8 type, u64 tag) {
|
||||
@ -31,7 +30,7 @@ typedef struct TAlloc {
|
||||
#define TFREE(N) mm_free((Value*)TOBJ(N));
|
||||
#define TREALLOC(N, AM) talloc_realloc(TOBJ(N), AM)
|
||||
#define TSIZE(N) (mm_size(TOBJ(N))-TOFF)
|
||||
static inline void* talloc_realloc(TAlloc* t, u64 am) {
|
||||
static inline void* talloc_realloc(TAlloc* t, u64 am) { // TODO maybe shouldn't be inline?
|
||||
u64 stored = mm_size((Value*)t)-TOFF;
|
||||
if (stored > am) return t->data;
|
||||
TALLOC(u8,r,am);
|
||||
@ -40,6 +39,26 @@ static inline void* talloc_realloc(TAlloc* t, u64 am) {
|
||||
return r;
|
||||
}
|
||||
|
||||
typedef struct TStack {
|
||||
struct Value;
|
||||
usz size;
|
||||
usz cap;
|
||||
u8 data[];
|
||||
} TStack;
|
||||
#define TSALLOC(T,N) u32 N##_e=sizeof(T); TStack* N##_o = (TStack*)mm_allocN(sizeof(TStack)+N##_e*2, t_temp); N##_o->size=0; N##_o->cap=2; T* N = (T*)N##_o->data;
|
||||
#define TSFREE(N) mm_free((Value*)N##_o);
|
||||
#define TSADD(N,X) { if (N##_o->size==N##_o->cap) { N##_o = tstack_ext(N##_o, N##_e); N = (void*)N##_o->data; } N[N##_o->size++] = X; }
|
||||
#define TSSIZE(N) (N##_o->size)
|
||||
static NOINLINE TStack* tstack_ext(TStack* o, u32 elsz) {
|
||||
usz ncap = o->cap*2;
|
||||
TStack* n = (TStack*)mm_allocN(sizeof(TStack) + elsz*ncap, t_temp);
|
||||
memcpy(n->data, o->data, o->cap*elsz);
|
||||
n->cap = ncap;
|
||||
n->size = o->size;
|
||||
mm_free((Value*)o);
|
||||
return n;
|
||||
}
|
||||
|
||||
// shape mess
|
||||
|
||||
typedef struct ShArr {
|
||||
|
||||
11
src/h.h
11
src/h.h
@ -28,7 +28,8 @@
|
||||
// #define TIME // output runtime of every expression
|
||||
// #define RT_PERF // time runtime primitives
|
||||
// #define RT_VERIFY // compare native and runtime versions of primitives
|
||||
// #define NO_COMP // don't load the compiler, instead execute src/interp; needed for ./precompiled.bqn
|
||||
// #define NO_RT // whether to completely disable self-hosted runtime loading
|
||||
// #define PRECOMP // execute just precompiled code at src/gen/interp
|
||||
|
||||
|
||||
#include <inttypes.h>
|
||||
@ -133,11 +134,11 @@ enum Type {
|
||||
/*13*/ t_harr , t_i8arr , t_i32arr , t_fillarr , t_c32arr , t_f64arr ,
|
||||
/*19*/ t_hslice, t_i8slice, t_i32slice, t_fillslice, t_c32slice, t_f64slice,
|
||||
|
||||
/*25*/ t_comp, t_block, t_body, t_scope,
|
||||
/*29*/ t_ns, t_nsDesc, t_fldAlias, t_hashmap, t_temp,
|
||||
/*34*/ t_freed, t_harrPartial,
|
||||
/*25*/ t_comp, t_block, t_body, t_scope, t_blBlocks,
|
||||
/*30*/ t_ns, t_nsDesc, t_fldAlias, t_hashmap, t_temp,
|
||||
/*35*/ t_freed, t_harrPartial,
|
||||
#ifdef RT_WRAP
|
||||
/*36*/ t_funWrap, t_md1Wrap, t_md2Wrap,
|
||||
/*37*/ t_funWrap, t_md1Wrap, t_md2Wrap,
|
||||
#endif
|
||||
t_COUNT
|
||||
};
|
||||
|
||||
158
src/load.c
158
src/load.c
@ -30,19 +30,19 @@ Block* load_compObj(B x, B src) { // consumes
|
||||
BS2B xget = TI(x).get;
|
||||
usz xia = a(x)->ia;
|
||||
if (xia!=5 & xia!=3) thrM("load_compObj: bad item count");
|
||||
Block* r = xia==5? compile(xget(x,0),xget(x,1),xget(x,2),xget(x,3),xget(x,4), src)
|
||||
: compile(xget(x,0),xget(x,1),xget(x,2),bi_N, bi_N, src);
|
||||
Block* r = xia==5? compile(xget(x,0),xget(x,1),xget(x,2),xget(x,3),xget(x,4), src, NULL)
|
||||
: compile(xget(x,0),xget(x,1),xget(x,2),bi_N, bi_N, src, NULL);
|
||||
dec(x);
|
||||
return r;
|
||||
}
|
||||
#include "gen/src"
|
||||
#if RT_SRC
|
||||
Block* load_compImport(B bc, B objs, B blocks, B inds, B src) { // consumes all
|
||||
return compile(bc, objs, blocks, inds, bi_N, src);
|
||||
return compile(bc, objs, blocks, inds, bi_N, src, NULL);
|
||||
}
|
||||
#else
|
||||
Block* load_compImport(B bc, B objs, B blocks) { // consumes all
|
||||
return compile(bc, objs, blocks, bi_N, bi_N, bi_N);
|
||||
return compile(bc, objs, blocks, bi_N, bi_N, bi_N, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -110,82 +110,86 @@ static inline void load_init() { // very last init function
|
||||
for (i32 i = 0; i < rtLen; i++) inc(fruntime[i]);
|
||||
B frtObj = m_caB(rtLen, fruntime);
|
||||
|
||||
B provide[] = {bi_type,bi_fill,bi_log,bi_grLen,bi_grOrd,bi_asrt,bi_add,bi_sub,bi_mul,bi_div,bi_pow,bi_floor,bi_eq,bi_le,bi_fne,bi_shape,bi_pick,bi_ud,bi_tbl,bi_scan,bi_fillBy,bi_val,bi_catch};
|
||||
|
||||
#ifndef ALL_R0
|
||||
B runtime_0[] = {bi_floor,bi_ceil,bi_stile,bi_lt,bi_gt,bi_ne,bi_ge,bi_rtack,bi_ltack,bi_join,bi_take,bi_drop,bi_select,bi_const,bi_swap,bi_each,bi_fold,bi_atop,bi_over,bi_before,bi_after,bi_cond,bi_repeat};
|
||||
#else
|
||||
Block* runtime0_b = load_compImport(
|
||||
#include "gen/runtime0"
|
||||
);
|
||||
B r0r = m_funBlock(runtime0_b, 0); ptr_dec(runtime0_b);
|
||||
B* runtime_0 = toHArr(r0r)->a;
|
||||
#endif
|
||||
|
||||
Block* runtime_b = load_compImport(
|
||||
#include "gen/runtime1"
|
||||
);
|
||||
|
||||
#ifdef ALL_R0
|
||||
dec(r0r);
|
||||
#endif
|
||||
|
||||
B rtRes = m_funBlock(runtime_b, 0); ptr_dec(runtime_b);
|
||||
B rtObjRaw = TI(rtRes).get(rtRes,0);
|
||||
B rtFinish = TI(rtRes).get(rtRes,1);
|
||||
dec(rtRes);
|
||||
|
||||
if (c(Arr,rtObjRaw)->ia != rtLen) err("incorrectly defined rtLen!");
|
||||
HArr_p runtimeH = m_harrUc(rtObjRaw);
|
||||
BS2B rtObjGet = TI(rtObjRaw).get;
|
||||
|
||||
rt_sortDsc = rtObjGet(rtObjRaw, 11); gc_add(rt_sortDsc);
|
||||
rt_merge = rtObjGet(rtObjRaw, 13); gc_add(rt_merge);
|
||||
rt_undo = rtObjGet(rtObjRaw, 48); gc_add(rt_undo);
|
||||
rt_select = rtObjGet(rtObjRaw, 35); gc_add(rt_select);
|
||||
rt_slash = rtObjGet(rtObjRaw, 32); gc_add(rt_slash);
|
||||
rt_join = rtObjGet(rtObjRaw, 23); gc_add(rt_join);
|
||||
rt_ud = rtObjGet(rtObjRaw, 27); gc_add(rt_ud);
|
||||
rt_pick = rtObjGet(rtObjRaw, 36); gc_add(rt_pick);
|
||||
rt_take = rtObjGet(rtObjRaw, 25); gc_add(rt_take);
|
||||
rt_drop = rtObjGet(rtObjRaw, 26); gc_add(rt_drop);
|
||||
rt_group = rtObjGet(rtObjRaw, 41); gc_add(rt_group);
|
||||
rt_under = rtObjGet(rtObjRaw, 56); gc_add(rt_under);
|
||||
rt_reverse = rtObjGet(rtObjRaw, 30); gc_add(rt_reverse);
|
||||
rt_indexOf = rtObjGet(rtObjRaw, 37); gc_add(rt_indexOf);
|
||||
rt_count = rtObjGet(rtObjRaw, 38); gc_add(rt_count);
|
||||
rt_memberOf= rtObjGet(rtObjRaw, 39); gc_add(rt_memberOf);
|
||||
rt_find = rtObjGet(rtObjRaw, 40); gc_add(rt_find);
|
||||
rt_cell = rtObjGet(rtObjRaw, 45); gc_add(rt_cell);
|
||||
|
||||
for (usz i = 0; i < rtLen; i++) {
|
||||
#ifdef RT_WRAP
|
||||
r1Objs[i] = rtObjGet(rtObjRaw, i); gc_add(r1Objs[i]);
|
||||
#endif
|
||||
#ifdef ALL_R1
|
||||
B r = rtObjGet(rtObjRaw, i);
|
||||
#ifndef NO_RT
|
||||
B provide[] = {bi_type,bi_fill,bi_log,bi_grLen,bi_grOrd,bi_asrt,bi_add,bi_sub,bi_mul,bi_div,bi_pow,bi_floor,bi_eq,bi_le,bi_fne,bi_shape,bi_pick,bi_ud,bi_tbl,bi_scan,bi_fillBy,bi_val,bi_catch};
|
||||
|
||||
#ifndef ALL_R0
|
||||
B runtime_0[] = {bi_floor,bi_ceil,bi_stile,bi_lt,bi_gt,bi_ne,bi_ge,bi_rtack,bi_ltack,bi_join,bi_take,bi_drop,bi_select,bi_const,bi_swap,bi_each,bi_fold,bi_atop,bi_over,bi_before,bi_after,bi_cond,bi_repeat};
|
||||
#else
|
||||
B r = rtComplete[i]? inc(fruntime[i]) : rtObjGet(rtObjRaw, i);
|
||||
Block* runtime0_b = load_compImport(
|
||||
#include "gen/runtime0"
|
||||
);
|
||||
B r0r = m_funBlock(runtime0_b, 0); ptr_dec(runtime0_b);
|
||||
B* runtime_0 = toHArr(r0r)->a;
|
||||
#endif
|
||||
if (isNothing(r)) { printf("· in runtime!\n"); exit(1); }
|
||||
if (isVal(r)) v(r)->flags|= i+1;
|
||||
#ifdef RT_WRAP
|
||||
r = rtWrap_wrap(r);
|
||||
|
||||
Block* runtime_b = load_compImport(
|
||||
#include "gen/runtime1"
|
||||
);
|
||||
|
||||
#ifdef ALL_R0
|
||||
dec(r0r);
|
||||
#endif
|
||||
|
||||
B rtRes = m_funBlock(runtime_b, 0); ptr_dec(runtime_b);
|
||||
B rtObjRaw = TI(rtRes).get(rtRes,0);
|
||||
B rtFinish = TI(rtRes).get(rtRes,1);
|
||||
dec(rtRes);
|
||||
|
||||
if (c(Arr,rtObjRaw)->ia != rtLen) err("incorrectly defined rtLen!");
|
||||
HArr_p runtimeH = m_harrUc(rtObjRaw);
|
||||
BS2B rtObjGet = TI(rtObjRaw).get;
|
||||
|
||||
rt_sortDsc = rtObjGet(rtObjRaw, 11); gc_add(rt_sortDsc);
|
||||
rt_merge = rtObjGet(rtObjRaw, 13); gc_add(rt_merge);
|
||||
rt_undo = rtObjGet(rtObjRaw, 48); gc_add(rt_undo);
|
||||
rt_select = rtObjGet(rtObjRaw, 35); gc_add(rt_select);
|
||||
rt_slash = rtObjGet(rtObjRaw, 32); gc_add(rt_slash);
|
||||
rt_join = rtObjGet(rtObjRaw, 23); gc_add(rt_join);
|
||||
rt_ud = rtObjGet(rtObjRaw, 27); gc_add(rt_ud);
|
||||
rt_pick = rtObjGet(rtObjRaw, 36); gc_add(rt_pick);
|
||||
rt_take = rtObjGet(rtObjRaw, 25); gc_add(rt_take);
|
||||
rt_drop = rtObjGet(rtObjRaw, 26); gc_add(rt_drop);
|
||||
rt_group = rtObjGet(rtObjRaw, 41); gc_add(rt_group);
|
||||
rt_under = rtObjGet(rtObjRaw, 56); gc_add(rt_under);
|
||||
rt_reverse = rtObjGet(rtObjRaw, 30); gc_add(rt_reverse);
|
||||
rt_indexOf = rtObjGet(rtObjRaw, 37); gc_add(rt_indexOf);
|
||||
rt_count = rtObjGet(rtObjRaw, 38); gc_add(rt_count);
|
||||
rt_memberOf= rtObjGet(rtObjRaw, 39); gc_add(rt_memberOf);
|
||||
rt_find = rtObjGet(rtObjRaw, 40); gc_add(rt_find);
|
||||
rt_cell = rtObjGet(rtObjRaw, 45); gc_add(rt_cell);
|
||||
|
||||
for (usz i = 0; i < rtLen; i++) {
|
||||
#ifdef RT_WRAP
|
||||
r1Objs[i] = rtObjGet(rtObjRaw, i); gc_add(r1Objs[i]);
|
||||
#endif
|
||||
#ifdef ALL_R1
|
||||
B r = rtObjGet(rtObjRaw, i);
|
||||
#else
|
||||
B r = rtComplete[i]? inc(fruntime[i]) : rtObjGet(rtObjRaw, i);
|
||||
#endif
|
||||
if (isNothing(r)) { printf("· in runtime!\n"); exit(1); }
|
||||
if (isVal(r)) v(r)->flags|= i+1;
|
||||
#endif
|
||||
runtimeH.a[i] = r;
|
||||
}
|
||||
dec(rtObjRaw);
|
||||
B* runtime = runtimeH.a;
|
||||
B rtObj = runtimeH.b;
|
||||
dec(c1(rtFinish, m_v2(inc(bi_decp), inc(bi_primInd)))); dec(rtFinish);
|
||||
#ifdef RT_WRAP
|
||||
r = rtWrap_wrap(r);
|
||||
if (isVal(r)) v(r)->flags|= i+1;
|
||||
#endif
|
||||
runtimeH.a[i] = r;
|
||||
}
|
||||
dec(rtObjRaw);
|
||||
B* runtime = runtimeH.a;
|
||||
B rtObj = runtimeH.b;
|
||||
dec(c1(rtFinish, m_v2(inc(bi_decp), inc(bi_primInd)))); dec(rtFinish);
|
||||
load_compArg = m_v2(FAKE_RUNTIME? frtObj : rtObj, inc(bi_sys)); gc_add(FAKE_RUNTIME? rtObj : frtObj);
|
||||
gc_add(load_compArg);
|
||||
#else
|
||||
B* runtime = fruntime;
|
||||
#endif
|
||||
|
||||
|
||||
load_compArg = m_v2(FAKE_RUNTIME? frtObj : rtObj, inc(bi_sys)); gc_add(FAKE_RUNTIME? rtObj : frtObj);
|
||||
gc_add(load_compArg);
|
||||
|
||||
|
||||
#ifdef NO_COMP
|
||||
#ifdef PRECOMP
|
||||
Block* c = load_compObj(
|
||||
#include "gen/interp"
|
||||
, bi_N
|
||||
@ -194,6 +198,12 @@ static inline void load_init() { // very last init function
|
||||
print(interp);
|
||||
printf("\n");
|
||||
dec(interp);
|
||||
#ifdef HEAP_VERIFY
|
||||
heapVerify();
|
||||
#endif
|
||||
rtWrap_print();
|
||||
CTR_FOR(CTR_PRINT)
|
||||
printAllocStats();
|
||||
exit(0);
|
||||
#else // use compiler
|
||||
Block* comp_b = load_compImport(
|
||||
@ -216,7 +226,7 @@ static inline void load_init() { // very last init function
|
||||
dec(fmtM);
|
||||
#endif
|
||||
gc_enable();
|
||||
#endif // NO_COMP
|
||||
#endif // PRECOMP
|
||||
}
|
||||
|
||||
B bqn_execFile(B path, B args) { // consumes both
|
||||
|
||||
171
src/vm.c
171
src/vm.c
@ -119,26 +119,86 @@ void gsPrint() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
NOINLINE Block* compile(B bcq, B objs, B blocksq, B indices, B tokenInfo, B src) { // consumes all
|
||||
HArr* blocksH = toHArr(blocksq);
|
||||
usz bam = blocksH->ia;
|
||||
Block* compileBlock(B block, Comp* comp, bool* bDone, i32* bc, usz bcIA, B blocks, B nameList, Scope* sc, i32 depth) {
|
||||
usz cIA = a(block)->ia;
|
||||
if (cIA!=4 && cIA!=6) thrM("VM compiler: Bad block info size");
|
||||
BS2B bgetU = TI(block).getU;
|
||||
usz ty = o2s(bgetU(block,0)); if (ty>2) thrM("VM compiler: Bad type");
|
||||
bool imm = o2b(bgetU(block,1));
|
||||
usz idx = o2s(bgetU(block,2)); if (idx>=bcIA) thrM("VM compiler: Bytecode index out of bounds");
|
||||
usz vam = o2s(bgetU(block,3)); if (vam!=(u16)vam) thrM("VM compiler: >2⋆16 variables not supported"); // TODO any reason for this? 2⋆32 vars should just work, no?
|
||||
i32* thisBC = bc+idx;
|
||||
i32 h = 0; // stack height
|
||||
i32 hM = 0; // max stack height
|
||||
i32 mpsc = 0;
|
||||
i32* c = thisBC;
|
||||
TSALLOC(Block*,nBlT);
|
||||
while (true) {
|
||||
i32* n = nextBC(c);
|
||||
if (n-thisBC-1 >= bcIA) thrM("VM compiler: No RETN/RETD found before end of bytecode");
|
||||
switch (*c) {
|
||||
case RETN: if(h!=1) thrM("VM compiler: Wrong stack size before RETN");
|
||||
goto returned;
|
||||
case RETD: if(h!=1&h!=0) thrM("VM compiler: Wrong stack size before RETD");
|
||||
goto returned;
|
||||
case DFND:
|
||||
u32 id = c[1];
|
||||
if ((u32)id >= a(blocks)->ia) thrM("VM compiler: DFND index out-of-bounds");
|
||||
if (bDone[id]) thrM("VM compiler: DFND of the same block in multiple places");
|
||||
bDone[id] = true;
|
||||
c[1] = TSSIZE(nBlT);
|
||||
TSADD(nBlT, compileBlock(TI(blocks).getU(blocks,id), comp, bDone, bc, bcIA, blocks, nameList, sc, depth+1));
|
||||
break;
|
||||
case LOCO: case LOCM: case LOCU:
|
||||
if (c[1]>mpsc) mpsc = c[1];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
h+= stackDiff(c);
|
||||
if (h<0) thrM("VM compiler: Stack size goes negative");
|
||||
if (h>hM) hM = h;
|
||||
c = n;
|
||||
} returned:;
|
||||
u64 blC = TSSIZE(nBlT);
|
||||
BlBlocks* nBl = mm_allocN(fsizeof(BlBlocks,a,Block*,blC), t_blBlocks);
|
||||
nBl->am = blC;
|
||||
memcpy(nBl->a, nBlT, blC*sizeof(Block*));
|
||||
TSFREE(nBlT);
|
||||
if (mpsc>U16_MAX) thrM("VM compiler: LOC_ too deep");
|
||||
|
||||
// B* objPtr = harr_ptr(objs); usz objIA = a(objs)->ia;
|
||||
// for (usz i = 0; i < objIA; i++) objPtr[i] = c2(bi_fill, c1(bi_pick, inc(objPtr[i])), objPtr[i]);
|
||||
Body* body = mm_allocN(fsizeof(Body,varIDs,i32,vam), t_body);
|
||||
body->comp = comp; ptr_inc(comp);
|
||||
body->bc = thisBC;
|
||||
body->blocks = nBl;
|
||||
body->maxStack = hM;
|
||||
body->maxPSC = (u16)mpsc;
|
||||
body->endStack = h;
|
||||
body->varAm = (u16)vam;
|
||||
if (cIA==4) {
|
||||
body->nsDesc = NULL;
|
||||
for (i32 i = 0; i < vam; i++) body->varIDs[i] = -1;
|
||||
} else m_nsDesc(body, imm, ty, inc(nameList), bgetU(block,4), bgetU(block,5));
|
||||
|
||||
Block* bl = mm_allocN(sizeof(Block), t_block);
|
||||
bl->body = body;
|
||||
bl->imm = imm;
|
||||
bl->ty = (u8)ty;
|
||||
return bl;
|
||||
}
|
||||
|
||||
NOINLINE Block* compile(B bcq, B objs, B blocks, B indices, B tokenInfo, B src, Scope* sc) { // consumes all; assumes arguments are valid (verifies some stuff, but definitely not everything)
|
||||
usz bIA = a(blocks)->ia;
|
||||
|
||||
I32Arr* bca = toI32Arr(bcq);
|
||||
i32* bc = bca->a;
|
||||
usz bcl = bca->ia;
|
||||
Comp* comp = mm_allocN(fsizeof(Comp,blocks,Block*,bam), t_comp);
|
||||
usz bcIA = bca->ia;
|
||||
Comp* comp = mm_allocN(sizeof(Comp), t_comp);
|
||||
comp->bc = tag(bca, ARR_TAG);
|
||||
comp->indices = indices;
|
||||
comp->src = src;
|
||||
comp->objs = toHArr(objs);
|
||||
comp->blockAm = bam;
|
||||
B* blockDefs = blocksH->a;
|
||||
comp->blockAm = 0;
|
||||
B nameList;
|
||||
if (isNothing(tokenInfo)) {
|
||||
nameList = bi_emptyHVec;
|
||||
@ -147,68 +207,19 @@ NOINLINE Block* compile(B bcq, B objs, B blocksq, B indices, B tokenInfo, B src)
|
||||
nameList = TI(t).getU(t,0);
|
||||
}
|
||||
if (!isNothing(src) && !isNothing(indices)) {
|
||||
if (isAtm(indices) || rnk(indices)!=1 || a(indices)->ia!=2) thrM("compile: bad indices");
|
||||
if (isAtm(indices) || rnk(indices)!=1 || a(indices)->ia!=2) thrM("VM compiler: Bad indices");
|
||||
for (i32 i = 0; i < 2; i++) {
|
||||
B ind = TI(indices).getU(indices,i);
|
||||
if (isAtm(ind) || rnk(ind)!=1 || a(ind)->ia!=bcl) thrM("compile: bad indices");
|
||||
if (isAtm(ind) || rnk(ind)!=1 || a(ind)->ia!=bcIA) thrM("VM compiler: Bad indices");
|
||||
BS2B indGetU = TI(ind).getU;
|
||||
for (usz j = 0; j < bcl; j++) o2i(indGetU(ind,j));
|
||||
for (usz j = 0; j < bcIA; j++) o2i(indGetU(ind,j));
|
||||
}
|
||||
}
|
||||
|
||||
for (usz i = 0; i < bam; i++) {
|
||||
B cbld = blockDefs[i];
|
||||
usz cbia = a(cbld)->ia;
|
||||
if (cbia!=4 && cbia!=6) thrM("bad compile block");
|
||||
BS2B bgetU = TI(cbld).getU;
|
||||
usz ty = o2s(bgetU(cbld,0)); if (ty>2) thrM("bad block type");
|
||||
bool imm = o2s(bgetU(cbld,1)); // todo o2b or something
|
||||
usz idx = o2s(bgetU(cbld,2)); if (idx>=bcl) thrM("oob bytecode index");
|
||||
usz vam = o2s(bgetU(cbld,3)); if (vam!=(u16)vam) thrM("too many variables");
|
||||
i32* cbc = bc+idx;
|
||||
i32* scan = cbc;
|
||||
i32 ssz = 0, mssz=0;
|
||||
i32 mpsc = 0;
|
||||
while (true) {
|
||||
if (*scan==RETN) { if(ssz!=1)thrM("Wrong stack size before RETN"); break; }
|
||||
if (*scan==RETD) { if(ssz!=1&ssz!=0)thrM("Wrong stack size before RETN"); break; }
|
||||
ssz+= stackDiff(scan);
|
||||
if (ssz < 0) thrM("Invalid bytecode: stack size goes negative");
|
||||
if (ssz>mssz) mssz = ssz;
|
||||
if (*scan==LOCO | *scan==LOCM | *scan==LOCU) {
|
||||
if (scan[1]>mpsc) mpsc = scan[1];
|
||||
}
|
||||
scan = nextBC(scan);
|
||||
if (scan-bc >= bcl) thrM("no RETN/RETD found at end of bytecode");
|
||||
}
|
||||
if (mpsc>U16_MAX) thrM("LOC_ too deep");
|
||||
|
||||
Body* body = mm_allocN(fsizeof(Body,varIDs,i32,vam), t_body);
|
||||
body->comp = comp;
|
||||
body->bc = cbc;
|
||||
body->maxStack = mssz;
|
||||
body->maxPSC = (u16)mpsc;
|
||||
body->endStack = ssz;
|
||||
body->varAm = (u16)vam;
|
||||
if (cbia==4) {
|
||||
body->nsDesc = NULL;
|
||||
for (i32 i = 0; i < vam; i++) body->varIDs[i] = -1;
|
||||
} else m_nsDesc(body, imm, ty, inc(nameList), bgetU(cbld,4), bgetU(cbld,5));
|
||||
ptr_inc(comp);
|
||||
|
||||
Block* bl = mm_allocN(sizeof(Block), t_block);
|
||||
bl->body = body;
|
||||
bl->imm = imm;
|
||||
bl->ty = (u8)ty;
|
||||
comp->blocks[i] = bl;
|
||||
}
|
||||
|
||||
Block* ret = c(Block,inc(tag(comp->blocks[0], OBJ_TAG)));
|
||||
// TODO store blocks in each body, then decrement each of comp->blocks; also then move temp block list out of Comp as it's useless then
|
||||
// for (usz i = 0; i < bam; i++) ptr_dec(comp->blocks[i]);
|
||||
ptr_dec(comp);
|
||||
ptr_dec(blocksH);
|
||||
dec(tokenInfo);
|
||||
TALLOC(bool,bDone,bIA);
|
||||
for (usz i = 0; i < bIA; i++) bDone[i] = false;
|
||||
Block* ret = compileBlock(TI(blocks).getU(blocks, 0), comp, bDone, bc, bcIA, blocks, nameList, sc, 0);
|
||||
TFREE(bDone);
|
||||
ptr_dec(comp); dec(blocks); dec(tokenInfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -290,7 +301,7 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume
|
||||
printf("new eval\n");
|
||||
#endif
|
||||
B* objs = b->comp->objs->a;
|
||||
Block** blocks = b->comp->blocks;
|
||||
Block** blocks = b->blocks->a; // b->comp->blocks;
|
||||
i32* bc = b->bc;
|
||||
pushEnv(sc, bc);
|
||||
gsReserve(b->maxStack);
|
||||
@ -527,11 +538,6 @@ B m_md2Block(Block* bl, Scope* psc) {
|
||||
return r;
|
||||
}
|
||||
|
||||
void comp_free(Value* x) {
|
||||
Comp* c = (Comp*)x;
|
||||
ptr_decR(c->objs); decR(c->bc); decR(c->src); decR(c->indices);
|
||||
u32 am = c->blockAm; for(u32 i = 0; i < am; i++) ptr_dec(c->blocks[i]);
|
||||
}
|
||||
void scope_free(Value* x) {
|
||||
Scope* c = (Scope*)x;
|
||||
if (c->psc) ptr_decR(c->psc);
|
||||
@ -539,18 +545,15 @@ void scope_free(Value* x) {
|
||||
u16 am = c->varAm;
|
||||
for (u32 i = 0; i < am; i++) dec(c->vars[i]);
|
||||
}
|
||||
void body_free(Value* x) { Body* c = (Body *)x; ptr_decR(c->comp); if(c->nsDesc)ptr_decR(c->nsDesc); }
|
||||
void comp_free(Value* x) { Comp* c = (Comp *)x; ptr_decR(c->objs); decR(c->bc); decR(c->src); decR(c->indices); }
|
||||
void body_free(Value* x) { Body* c = (Body *)x; ptr_decR(c->comp); if(c->nsDesc)ptr_decR(c->nsDesc); ptr_decR(c->blocks); }
|
||||
void block_free(Value* x) { Block* c = (Block *)x; ptr_decR(c->body); }
|
||||
void funBl_free(Value* x) { FunBlock* c = (FunBlock*)x; ptr_decR(c->sc); ptr_decR(c->bl); }
|
||||
void md1Bl_free(Value* x) { Md1Block* c = (Md1Block*)x; ptr_decR(c->sc); ptr_decR(c->bl); }
|
||||
void md2Bl_free(Value* x) { Md2Block* c = (Md2Block*)x; ptr_decR(c->sc); ptr_decR(c->bl); }
|
||||
void alias_free(Value* x) { dec(((FldAlias*)x)->obj); }
|
||||
void bBlks_free(Value* x) { BlBlocks* c = (BlBlocks*)x; u16 am = c->am; for (u32 i = 0; i < am; i++) ptr_dec(c->a[i]); }
|
||||
|
||||
void comp_visit(Value* x) {
|
||||
Comp* c = (Comp*)x;
|
||||
mm_visitP(c->objs); mm_visit(c->bc); mm_visit(c->src); mm_visit(c->indices);
|
||||
u32 am = c->blockAm; for(u32 i = 0; i < am; i++) mm_visitP(c->blocks[i]);
|
||||
}
|
||||
void scope_visit(Value* x) {
|
||||
Scope* c = (Scope*)x;
|
||||
if (c->psc) mm_visitP(c->psc);
|
||||
@ -558,18 +561,21 @@ void scope_visit(Value* x) {
|
||||
u16 am = c->varAm;
|
||||
for (u32 i = 0; i < am; i++) mm_visit(c->vars[i]);
|
||||
}
|
||||
void body_visit(Value* x) { Body* c = (Body *)x; mm_visitP(c->comp); if(c->nsDesc)mm_visitP(c->nsDesc); }
|
||||
void comp_visit(Value* x) { Comp* c = (Comp *)x; mm_visitP(c->objs); mm_visit(c->bc); mm_visit(c->src); mm_visit(c->indices); }
|
||||
void body_visit(Value* x) { Body* c = (Body *)x; mm_visitP(c->comp); if(c->nsDesc)mm_visitP(c->nsDesc); mm_visitP(c->blocks); }
|
||||
void block_visit(Value* x) { Block* c = (Block *)x; mm_visitP(c->body); }
|
||||
void funBl_visit(Value* x) { FunBlock* c = (FunBlock*)x; mm_visitP(c->sc); mm_visitP(c->bl); }
|
||||
void md1Bl_visit(Value* x) { Md1Block* c = (Md1Block*)x; mm_visitP(c->sc); mm_visitP(c->bl); }
|
||||
void md2Bl_visit(Value* x) { Md2Block* c = (Md2Block*)x; mm_visitP(c->sc); mm_visitP(c->bl); }
|
||||
void alias_visit(Value* x) { mm_visit(((FldAlias*)x)->obj); }
|
||||
void bBlks_visit(Value* x) { BlBlocks* c = (BlBlocks*)x; u16 am = c->am; for (u32 i = 0; i < am; i++) mm_visitP(c->a[i]); }
|
||||
|
||||
void comp_print (B x) { printf("(%p: comp)",v(x)); }
|
||||
void body_print (B x) { printf("(%p: body varam=%d)",v(x),c(Body,x)->varAm); }
|
||||
void block_print(B x) { printf("(%p: block for %p)",v(x),c(Block,x)->body); }
|
||||
void scope_print(B x) { printf("(%p: scope; vars:",v(x));Scope*sc=c(Scope,x);for(u64 i=0;i<sc->varAm;i++){printf(" ");print(sc->vars[i]);}printf(")"); }
|
||||
void alias_print(B x) { printf("(alias %d of ", c(FldAlias,x)->p); print(c(FldAlias,x)->obj); printf(")"); }
|
||||
void bBlks_print(B x) { printf("(block list)"); }
|
||||
|
||||
// void funBl_print(B x) { printf("(%p: function"" block bl=%p sc=%p)",v(x),c(FunBlock,x)->bl,c(FunBlock,x)->sc); }
|
||||
// void md1Bl_print(B x) { printf("(%p: 1-modifier block bl=%p sc=%p)",v(x),c(Md1Block,x)->bl,c(Md1Block,x)->sc); }
|
||||
@ -609,6 +615,7 @@ void comp_init() {
|
||||
ti[t_body ].free = body_free; ti[t_body ].visit = body_visit; ti[t_body ].print = body_print;
|
||||
ti[t_block ].free = block_free; ti[t_block ].visit = block_visit; ti[t_block ].print = block_print;
|
||||
ti[t_scope ].free = scope_free; ti[t_scope ].visit = scope_visit; ti[t_scope ].print = scope_print;
|
||||
ti[t_blBlocks ].free = bBlks_free; ti[t_blBlocks ].visit = bBlks_visit; ti[t_blBlocks ].print = bBlks_print;
|
||||
ti[t_fldAlias ].free = alias_free; ti[t_fldAlias ].visit = alias_visit; ti[t_fldAlias ].print = alias_print;
|
||||
ti[t_fun_block].free = funBl_free; ti[t_fun_block].visit = funBl_visit; ti[t_fun_block].print = funBl_print; ti[t_fun_block].decompose = block_decompose;
|
||||
ti[t_md1_block].free = md1Bl_free; ti[t_md1_block].visit = md1Bl_visit; ti[t_md1_block].print = md1Bl_print; ti[t_md1_block].decompose = block_decompose; ti[t_md1_block].m1_d=bl_m1d;
|
||||
|
||||
22
src/vm.h
22
src/vm.h
@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
typedef struct Comp Comp;
|
||||
typedef struct BlBlocks BlBlocks;
|
||||
typedef struct Block Block;
|
||||
typedef struct Body Body;
|
||||
typedef struct Scope Scope;
|
||||
typedef struct ScopeExt ScopeExt;
|
||||
|
||||
typedef struct Comp {
|
||||
struct Value;
|
||||
@ -10,9 +13,14 @@ typedef struct Comp {
|
||||
B indices;
|
||||
HArr* objs;
|
||||
u32 blockAm;
|
||||
Block* blocks[];
|
||||
} Comp;
|
||||
|
||||
struct BlBlocks {
|
||||
struct Value;
|
||||
u32 am;
|
||||
Block* a[];
|
||||
};
|
||||
|
||||
struct Block {
|
||||
struct Value;
|
||||
bool imm;
|
||||
@ -24,6 +32,7 @@ typedef struct NSDesc NSDesc;
|
||||
struct Body {
|
||||
struct Value;
|
||||
Comp* comp;
|
||||
BlBlocks* blocks;
|
||||
// B* objs;
|
||||
i32* bc; // pointer in comp->bc
|
||||
u32 maxStack;
|
||||
@ -34,20 +43,29 @@ struct Body {
|
||||
i32 varIDs[];
|
||||
};
|
||||
|
||||
struct ScopeExt {
|
||||
u16 varAm;
|
||||
B vars[];
|
||||
};
|
||||
|
||||
struct Scope {
|
||||
struct Value;
|
||||
Scope* psc;
|
||||
Body* body;
|
||||
u16 varAm;
|
||||
ScopeExt* ext;
|
||||
B vars[];
|
||||
};
|
||||
|
||||
|
||||
Block* compile(B bcq, B objs, B blocksq, B indices, B tokenInfo, B src, Scope* sc);
|
||||
|
||||
|
||||
typedef struct Env {
|
||||
Scope* sc;
|
||||
union { i32* bcL; i32 bcV; };
|
||||
} Env;
|
||||
|
||||
Block* compile(B bcq, B objs, B blocksq, B indices, B tokenInfo, B src);
|
||||
void vm_pst(Env* s, Env* e);
|
||||
void vm_pstLive();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user