store directly needed blocks in bodies

This commit is contained in:
dzaima 2021-05-26 14:24:15 +03:00
parent 582273229b
commit 7bf3b4be50
7 changed files with 223 additions and 168 deletions

View File

@ -14,7 +14,7 @@ tests ← •FLines path∾"/test/cases/prim.bqn"
'%'{𝕤 '%'{𝕤
•Out 𝕩 •Out 𝕩
"src/gen/interp" •FChars 1,path,𝕩 •Import "cc.bqn" "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"
codeouterr•SH"./BQN" codeouterr•SH"./BQN"
•Out out •Out out
{𝕤•Out"exit code "(code) •Out err}(×code) err {𝕤•Out"exit code "(code) •Out err}(×code) err

View File

@ -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_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_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_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_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"; case t_freed:return"(freed by GC)"; case t_harrPartial:return"partHarr";
#ifdef RT_WRAP #ifdef RT_WRAP
@ -457,7 +457,7 @@ B bqn_merge(B x) { // consumes
NOINLINE void printAllocStats() { NOINLINE void printAllocStats() {
#ifdef ALLOC_STAT #ifdef ALLOC_STAT
printf("total ever allocated: %lu\n", talloc); 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()); printf("used heap size: %ld\n", mm_heapUsed());
ctr_a[t_harr]+= ctr_a[t_harrPartial]; ctr_a[t_harr]+= ctr_a[t_harrPartial];
ctr_a[t_harrPartial] = 0; ctr_a[t_harrPartial] = 0;

View File

@ -8,7 +8,6 @@ static void mm_free(Value* x);
static u64 mm_size(Value* x); static u64 mm_size(Value* x);
static void mm_visit(B x); static void mm_visit(B x);
static void mm_visitP(void* x); static void mm_visitP(void* x);
static u64 mm_heapAllocated();
u64 mm_heapUsed(); u64 mm_heapUsed();
void printAllocStats(); void printAllocStats();
static B mm_alloc(usz sz, u8 type, u64 tag) { 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 TFREE(N) mm_free((Value*)TOBJ(N));
#define TREALLOC(N, AM) talloc_realloc(TOBJ(N), AM) #define TREALLOC(N, AM) talloc_realloc(TOBJ(N), AM)
#define TSIZE(N) (mm_size(TOBJ(N))-TOFF) #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; u64 stored = mm_size((Value*)t)-TOFF;
if (stored > am) return t->data; if (stored > am) return t->data;
TALLOC(u8,r,am); TALLOC(u8,r,am);
@ -40,6 +39,26 @@ static inline void* talloc_realloc(TAlloc* t, u64 am) {
return r; 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 // shape mess
typedef struct ShArr { typedef struct ShArr {

11
src/h.h
View File

@ -28,7 +28,8 @@
// #define TIME // output runtime of every expression // #define TIME // output runtime of every expression
// #define RT_PERF // time runtime primitives // #define RT_PERF // time runtime primitives
// #define RT_VERIFY // compare native and runtime versions of 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> #include <inttypes.h>
@ -133,11 +134,11 @@ enum Type {
/*13*/ t_harr , t_i8arr , t_i32arr , t_fillarr , t_c32arr , t_f64arr , /*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, /*19*/ t_hslice, t_i8slice, t_i32slice, t_fillslice, t_c32slice, t_f64slice,
/*25*/ t_comp, t_block, t_body, t_scope, /*25*/ t_comp, t_block, t_body, t_scope, t_blBlocks,
/*29*/ t_ns, t_nsDesc, t_fldAlias, t_hashmap, t_temp, /*30*/ t_ns, t_nsDesc, t_fldAlias, t_hashmap, t_temp,
/*34*/ t_freed, t_harrPartial, /*35*/ t_freed, t_harrPartial,
#ifdef RT_WRAP #ifdef RT_WRAP
/*36*/ t_funWrap, t_md1Wrap, t_md2Wrap, /*37*/ t_funWrap, t_md1Wrap, t_md2Wrap,
#endif #endif
t_COUNT t_COUNT
}; };

View File

@ -30,19 +30,19 @@ Block* load_compObj(B x, B src) { // consumes
BS2B xget = TI(x).get; BS2B xget = TI(x).get;
usz xia = a(x)->ia; usz xia = a(x)->ia;
if (xia!=5 & xia!=3) thrM("load_compObj: bad item count"); 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) 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); : compile(xget(x,0),xget(x,1),xget(x,2),bi_N, bi_N, src, NULL);
dec(x); dec(x);
return r; return r;
} }
#include "gen/src" #include "gen/src"
#if RT_SRC #if RT_SRC
Block* load_compImport(B bc, B objs, B blocks, B inds, B src) { // consumes all 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 #else
Block* load_compImport(B bc, B objs, B blocks) { // consumes all 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 #endif
@ -110,82 +110,86 @@ static inline void load_init() { // very last init function
for (i32 i = 0; i < rtLen; i++) inc(fruntime[i]); for (i32 i = 0; i < rtLen; i++) inc(fruntime[i]);
B frtObj = m_caB(rtLen, fruntime); 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 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}; #ifndef ALL_R0
#else 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};
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);
#else #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 #endif
if (isNothing(r)) { printf("· in runtime!\n"); exit(1); }
if (isVal(r)) v(r)->flags|= i+1; Block* runtime_b = load_compImport(
#ifdef RT_WRAP #include "gen/runtime1"
r = rtWrap_wrap(r); );
#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; if (isVal(r)) v(r)->flags|= i+1;
#endif #ifdef RT_WRAP
runtimeH.a[i] = r; r = rtWrap_wrap(r);
} if (isVal(r)) v(r)->flags|= i+1;
dec(rtObjRaw); #endif
B* runtime = runtimeH.a; runtimeH.a[i] = r;
B rtObj = runtimeH.b; }
dec(c1(rtFinish, m_v2(inc(bi_decp), inc(bi_primInd)))); dec(rtFinish); 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( Block* c = load_compObj(
#include "gen/interp" #include "gen/interp"
, bi_N , bi_N
@ -194,6 +198,12 @@ static inline void load_init() { // very last init function
print(interp); print(interp);
printf("\n"); printf("\n");
dec(interp); dec(interp);
#ifdef HEAP_VERIFY
heapVerify();
#endif
rtWrap_print();
CTR_FOR(CTR_PRINT)
printAllocStats();
exit(0); exit(0);
#else // use compiler #else // use compiler
Block* comp_b = load_compImport( Block* comp_b = load_compImport(
@ -216,7 +226,7 @@ static inline void load_init() { // very last init function
dec(fmtM); dec(fmtM);
#endif #endif
gc_enable(); gc_enable();
#endif // NO_COMP #endif // PRECOMP
} }
B bqn_execFile(B path, B args) { // consumes both B bqn_execFile(B path, B args) { // consumes both

171
src/vm.c
View File

@ -119,26 +119,86 @@ void gsPrint() {
} }
} }
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");
NOINLINE Block* compile(B bcq, B objs, B blocksq, B indices, B tokenInfo, B src) { // consumes all BS2B bgetU = TI(block).getU;
HArr* blocksH = toHArr(blocksq); usz ty = o2s(bgetU(block,0)); if (ty>2) thrM("VM compiler: Bad type");
usz bam = blocksH->ia; 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; Body* body = mm_allocN(fsizeof(Body,varIDs,i32,vam), t_body);
// for (usz i = 0; i < objIA; i++) objPtr[i] = c2(bi_fill, c1(bi_pick, inc(objPtr[i])), objPtr[i]); 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); I32Arr* bca = toI32Arr(bcq);
i32* bc = bca->a; i32* bc = bca->a;
usz bcl = bca->ia; usz bcIA = bca->ia;
Comp* comp = mm_allocN(fsizeof(Comp,blocks,Block*,bam), t_comp); Comp* comp = mm_allocN(sizeof(Comp), t_comp);
comp->bc = tag(bca, ARR_TAG); comp->bc = tag(bca, ARR_TAG);
comp->indices = indices; comp->indices = indices;
comp->src = src; comp->src = src;
comp->objs = toHArr(objs); comp->objs = toHArr(objs);
comp->blockAm = bam; comp->blockAm = 0;
B* blockDefs = blocksH->a;
B nameList; B nameList;
if (isNothing(tokenInfo)) { if (isNothing(tokenInfo)) {
nameList = bi_emptyHVec; 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); nameList = TI(t).getU(t,0);
} }
if (!isNothing(src) && !isNothing(indices)) { 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++) { for (i32 i = 0; i < 2; i++) {
B ind = TI(indices).getU(indices,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; 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));
} }
} }
TALLOC(bool,bDone,bIA);
for (usz i = 0; i < bam; i++) { for (usz i = 0; i < bIA; i++) bDone[i] = false;
B cbld = blockDefs[i]; Block* ret = compileBlock(TI(blocks).getU(blocks, 0), comp, bDone, bc, bcIA, blocks, nameList, sc, 0);
usz cbia = a(cbld)->ia; TFREE(bDone);
if (cbia!=4 && cbia!=6) thrM("bad compile block"); ptr_dec(comp); dec(blocks); dec(tokenInfo);
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);
return ret; return ret;
} }
@ -290,7 +301,7 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume
printf("new eval\n"); printf("new eval\n");
#endif #endif
B* objs = b->comp->objs->a; B* objs = b->comp->objs->a;
Block** blocks = b->comp->blocks; Block** blocks = b->blocks->a; // b->comp->blocks;
i32* bc = b->bc; i32* bc = b->bc;
pushEnv(sc, bc); pushEnv(sc, bc);
gsReserve(b->maxStack); gsReserve(b->maxStack);
@ -527,11 +538,6 @@ B m_md2Block(Block* bl, Scope* psc) {
return r; 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) { void scope_free(Value* x) {
Scope* c = (Scope*)x; Scope* c = (Scope*)x;
if (c->psc) ptr_decR(c->psc); if (c->psc) ptr_decR(c->psc);
@ -539,18 +545,15 @@ void scope_free(Value* x) {
u16 am = c->varAm; u16 am = c->varAm;
for (u32 i = 0; i < am; i++) dec(c->vars[i]); 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 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 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 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 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 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) { void scope_visit(Value* x) {
Scope* c = (Scope*)x; Scope* c = (Scope*)x;
if (c->psc) mm_visitP(c->psc); if (c->psc) mm_visitP(c->psc);
@ -558,18 +561,21 @@ void scope_visit(Value* x) {
u16 am = c->varAm; u16 am = c->varAm;
for (u32 i = 0; i < am; i++) mm_visit(c->vars[i]); 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 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 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 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 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 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 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 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 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 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 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 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); } // 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_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_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_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_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_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; 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;

View File

@ -1,7 +1,10 @@
#pragma once #pragma once
typedef struct Comp Comp;
typedef struct BlBlocks BlBlocks;
typedef struct Block Block; typedef struct Block Block;
typedef struct Body Body; typedef struct Body Body;
typedef struct Scope Scope; typedef struct Scope Scope;
typedef struct ScopeExt ScopeExt;
typedef struct Comp { typedef struct Comp {
struct Value; struct Value;
@ -10,9 +13,14 @@ typedef struct Comp {
B indices; B indices;
HArr* objs; HArr* objs;
u32 blockAm; u32 blockAm;
Block* blocks[];
} Comp; } Comp;
struct BlBlocks {
struct Value;
u32 am;
Block* a[];
};
struct Block { struct Block {
struct Value; struct Value;
bool imm; bool imm;
@ -24,6 +32,7 @@ typedef struct NSDesc NSDesc;
struct Body { struct Body {
struct Value; struct Value;
Comp* comp; Comp* comp;
BlBlocks* blocks;
// B* objs; // B* objs;
i32* bc; // pointer in comp->bc i32* bc; // pointer in comp->bc
u32 maxStack; u32 maxStack;
@ -34,20 +43,29 @@ struct Body {
i32 varIDs[]; i32 varIDs[];
}; };
struct ScopeExt {
u16 varAm;
B vars[];
};
struct Scope { struct Scope {
struct Value; struct Value;
Scope* psc; Scope* psc;
Body* body; Body* body;
u16 varAm; u16 varAm;
ScopeExt* ext;
B vars[]; B vars[];
}; };
Block* compile(B bcq, B objs, B blocksq, B indices, B tokenInfo, B src, Scope* sc);
typedef struct Env { typedef struct Env {
Scope* sc; Scope* sc;
union { i32* bcL; i32 bcV; }; union { i32* bcL; i32 bcV; };
} Env; } Env;
Block* compile(B bcq, B objs, B blocksq, B indices, B tokenInfo, B src);
void vm_pst(Env* s, Env* e); void vm_pst(Env* s, Env* e);
void vm_pstLive(); void vm_pstLive();