From: Jérémie Astor Date: Thu, 6 May 2021 21:26:48 +0000 (+0200) Subject: :art: debug instruction X-Git-Tag: nightly~691 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=e5c701975972fda0118597b6526e245a1b9030ee;p=gwion.git :art: debug instruction --- diff --git a/include/emit.h b/include/emit.h index a9afcd1a..bd6b762c 100644 --- a/include/emit.h +++ b/include/emit.h @@ -26,6 +26,8 @@ struct EmitterInfo_ { VM_Code code; uint memoize; uint unroll; + uint line; + bool debug; }; struct Emitter_ { diff --git a/include/gwi.h b/include/gwi.h index 3f7add09..ac9c2905 100644 --- a/include/gwi.h +++ b/include/gwi.h @@ -2,7 +2,7 @@ #define __GWI #ifdef GWION_DOC -#include "lint.h" +#include "gwfmt.h" #define gwiheader(a,...) do { lint_nl(a->lint); lint_indent(a->lint); lint(a->lint, "{-}#!+ {/}%s{0}\n", __VA_ARGS__); } while(0) #define gwidoc(a,...) do { lint_nl(a->lint); lint_indent(a->lint); lint(a->lint, "{-}#!- {/}%s{0}\n", __VA_ARGS__); } while(0) #define gwinote(a,...) do { lint_indent(a->lint); lint(a->lint, "{-}#!- {/}%s{0}\n", __VA_ARGS__); } while(0) diff --git a/include/gwion.h b/include/gwion.h index 50610636..89834da5 100644 --- a/include/gwion.h +++ b/include/gwion.h @@ -35,4 +35,6 @@ ANN static inline Type type_class(const Gwion gwion, const Type t) { const Value v = nspc_lookup_value1(t->info->value->from->owner, insert_symbol(gwion->st, t->name)); return v->type; } + +ANN void gwion_set_debug(const Gwion gwion, const bool dbg); #endif diff --git a/include/opcode.h b/include/opcode.h index fab83001..d0e695d1 100644 --- a/include/opcode.h +++ b/include/opcode.h @@ -188,6 +188,10 @@ enum { eHandleEffect, ePerformEffect, eNoOp, + eDebugLine, + eDebugValue, + eDebugPush, + eDebugPop, eEOC, eUnroll2, eOP_MAX, @@ -381,6 +385,10 @@ enum { #define HandleEffect (f_instr)eHandleEffect #define PerformEffect (f_instr)ePerformEffect #define NoOp (f_instr)eNoOp +#define DebugLine (f_instr)eDebugLine +#define DebugValue (f_instr)eDebugValue +#define DebugPush (f_instr)eDebugPush +#define DebugPop (f_instr)eDebugPop #define EOC (f_instr)eEOC #define Unroll2 (f_instr)eUnroll2 #define OP_MAX (f_instr)eOP_MAX diff --git a/include/vm.h b/include/vm.h index 3e2944c5..917cb0a1 100644 --- a/include/vm.h +++ b/include/vm.h @@ -13,7 +13,7 @@ typedef struct VM_Code_* VM_Code; struct VM_Code_ { m_bit *bytecode; union { - Vector instr; + struct Vector_ instr; m_uint native_func; }; size_t stack_depth; @@ -35,6 +35,12 @@ typedef struct Shreduler_* Shreduler; typedef struct Emitter_ * Emitter; typedef struct VM_Shred_* VM_Shred; +typedef struct Debugger_ { + struct Vector_ breakpoint; + Nspc nspc; + bool step; +} Debugger; + typedef struct VM_ { Shreduler shreduler; struct Vector_ ugen; @@ -42,18 +48,18 @@ typedef struct VM_ { struct Gwion_* gwion; VM_Shred cleaner_shred; struct VM_ *parent; + Debugger debugger; uint32_t rand[2]; } VM; - struct ShredInfo_ { VM* vm; struct M_Object_* me; - m_str name; Vector args; MemPool mp; VM_Code orig; struct Vector_ frame; + struct Vector_ line; }; struct ShredTick_ { diff --git a/libcmdapp b/libcmdapp index 27eb025e..9a2bcfb8 160000 --- a/libcmdapp +++ b/libcmdapp @@ -1 +1 @@ -Subproject commit 27eb025e264a6251f595c0177b51ee58987324f5 +Subproject commit 9a2bcfb85e5ca94cc6f2697f5a41c09c1c18db3f diff --git a/opcode.txt b/opcode.txt index bb4b88ec..73536e3a 100644 --- a/opcode.txt +++ b/opcode.txt @@ -185,6 +185,10 @@ TryEnd HandleEffect PerformEffect NoOp +DebugLine +DebugValue +DebugPush +DebugPop EOC Unroll2 OP_MAX diff --git a/src/arg.c b/src/arg.c index aa39573b..15d51cb5 100644 --- a/src/arg.c +++ b/src/arg.c @@ -18,6 +18,7 @@ enum { DRIVER, SRATE, NINPUT, NOUTPUT, // pp options DEFINE, UNDEF, INCLUDE, + DEBUG, NOPTIONS }; @@ -47,7 +48,8 @@ enum arg_type { ARG_STDIN, ARG_DEFINE, ARG_UNDEF, - ARG_INCLUDE + ARG_INCLUDE, + ARG_DEBUG }; ANN static void arg_init(Arg* arg) { @@ -68,6 +70,19 @@ ANN void arg_release(Arg* arg) { vector_release(&arg->config); } +static inline bool _get_debug(const m_str dbg) { + if(!dbg || !strcmp(dbg, "true")) + return true; + if(!strcmp(dbg, "false")) + return false; + return atoi(dbg) ? true : false; +} + +ANN static inline void get_debug(const Gwion gwion, const m_str dbg) { + const bool is_dbg = _get_debug(dbg); + gwion_set_debug(gwion, is_dbg); +} + ANN void arg_compile(const Gwion gwion, Arg *arg) { const Vector v = &arg->add; for(m_uint i = 0; i < vector_size(v); i++) { @@ -87,6 +102,9 @@ ANN void arg_compile(const Gwion gwion, Arg *arg) { case ARG_INCLUDE: pparg_inc(gwion->ppa, (m_str)VPTR(v, ++i)); break; + case ARG_DEBUG: + get_debug(gwion, (m_str)VPTR(v, ++i)); + break; } } } @@ -180,6 +198,11 @@ static void setup_options(cmdapp_t* app, cmdopt_t* opt) { CMDOPT_TAKESARG, NULL, "add ARG to include path", &opt[INCLUDE] ); + cmdapp_set(app, + 'G', "debug", + CMDOPT_MAYTAKEARG, NULL, + "set/unset debug mode", &opt[DEBUG] + ); } static inline void add2arg(Arg *const arg, const char *data, const enum arg_type type) { @@ -299,6 +322,10 @@ static void myproc(void *data, cmdopt_t* option, const char* arg) { case 'I': add2arg(_arg, option->value, ARG_INCLUDE); break; +// debug + case 'G': + add2arg(_arg, option->value, ARG_DEBUG); + break; } } } diff --git a/src/emit/emit.c b/src/emit/emit.c index 6255ac28..9791df9a 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -41,6 +41,13 @@ static inline m_uint emit_push_global(const Emitter emit) { return env_push_global(emit->env); } +static inline void emit_debug(const Emitter emit, const Value v) { + if(!emit->info->debug) + return; + const Instr instr = emit_add_instr(emit, DebugValue); + instr->m_val = (m_uint)v; +} + ANEW static Frame* new_frame(MemPool p) { Frame* frame = mp_calloc(p, Frame); vector_init(&frame->stack); @@ -243,11 +250,15 @@ ANN static void emit_pop_scope(const Emitter emit) { instr->m_val = (m_uint)offset; } vector_pop(&emit->info->pure); + if(emit->info->debug) + emit_add_instr(emit, DebugPop); } ANN static inline void emit_push_code(const Emitter emit, const m_str name) { vector_add(&emit->stack, (vtype)emit->code); emit->code = new_code(emit, name); + if(emit->info->debug) + emit_add_instr(emit, DebugLine); } ANN static inline void emit_pop_code(const Emitter emit) { @@ -257,6 +268,8 @@ ANN static inline void emit_pop_code(const Emitter emit) { ANN static inline void emit_push_scope(const Emitter emit) { frame_push(emit->code->frame); vector_add(&emit->info->pure, 0); + if(emit->info->debug) + emit_add_instr(emit, DebugPush); } ANN static inline m_uint emit_code_size(const Emitter emit) { @@ -805,6 +818,7 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter emit, const Exp_Decl *d f_instr *exec = (f_instr*)allocmember; if(!vflag(v, vflag_member)) { v->from->offset = emit_local(emit, type); + emit_debug(emit, v); exec = (f_instr*)(allocword); if(GET_FLAG(v, late)) { // ref or emit_var ? const Instr clean = emit_add_instr(emit, MemSetImm); @@ -1501,10 +1515,13 @@ ANN static m_bool emit_exp_td(const Emitter emit, Type_Decl* td) { DECL_EXP_FUNC(emit, m_bool, Emitter) - ANN2(1) /*static */m_bool emit_exp(const Emitter emit, /* const */Exp e) { Exp exp = e; do { + if(emit->info->debug && emit->info->line < e->pos.first.line) { + const Instr instr = emit_add_instr(emit, DebugLine); + instr->m_val = emit->info->line = e->pos.first.line; + } CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d)); if(exp->cast_to) CHECK_BB(emit_implicit_cast(emit, exp, exp->cast_to)); @@ -1546,8 +1563,10 @@ ANN static m_bool emit_stmt_if(const Emitter emit, const Stmt_If stmt) { } ANN static m_bool emit_stmt_code(const Emitter emit, const Stmt_Code stmt) { + emit_push_scope(emit); ++emit->env->scope->depth; const m_bool ret = stmt->stmt_list ? emit_stmt_list(emit, stmt->stmt_list) : 1; + emit_pop_scope(emit); --emit->env->scope->depth; return ret; } @@ -1810,6 +1829,7 @@ ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt, m_ui loop_idx->m_val = offset + SZ_INT; loop_idx->m_val2 = -1; stmt->v->from->offset = offset + SZ_INT *2; + emit_debug(emit, stmt->v); if(stmt->idx) stmt->idx->v->from->offset = offset + SZ_INT; if(n) { @@ -1984,6 +2004,7 @@ ANN static m_bool emit_case_body(const Emitter emit, const struct Stmt_Match_* s ANN static m_bool case_value(const Emitter emit, const Exp base, const Exp e) { const Value v = e->d.prim.value; v->from->offset = emit_local(emit, base->type); + emit_debug(emit, v); const Instr instr = emit_add_instr(emit, Reg2Mem4); instr->m_val = v->from->offset; instr->m_val2 = base->type->size; @@ -2173,6 +2194,7 @@ ANN static void emit_func_def_args(const Emitter emit, Arg_List a) { const Type type = a->var_decl->value->type; emit->code->stack_depth += type->size; a->var_decl->value->from->offset = emit_localn(emit, type); + emit_debug(emit, a->var_decl->value); } while((a = a->next)); } diff --git a/src/gwion.c b/src/gwion.c index 361f96d2..879843a5 100644 --- a/src/gwion.c +++ b/src/gwion.c @@ -207,3 +207,7 @@ ANN Nspc pop_global(struct Gwion_ *gwion) { nspc_remref(gwion->env->global_nspc, gwion); return gwion->env->curr = gwion->env->global_nspc = nspc; } + +ANN void gwion_set_debug(const Gwion gwion, const bool dbg) { + gwion->emit->info->debug = dbg; +} diff --git a/src/lib/array.c b/src/lib/array.c index 5c0077dc..ba652879 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -922,7 +922,7 @@ INSTR(ArrayAlloc) { aai.data = init_array(shred, info, &num_obj); const M_Object ref = do_alloc_array(shred, &aai); if(!ref) { - gw_err("[Gwion](VM): (note: in shred[id=%" UINT_F ":%s])\n", shred->tick->xid, shred->info->name); + gw_err("[Gwion](VM): (note: in shred[id=%" UINT_F ":%s])\n", shred->tick->xid, shred->code->name); vm_shred_exit(shred); return; // TODO make exception vararg } diff --git a/src/lib/modules.c b/src/lib/modules.c index c1c22207..016d6e63 100644 --- a/src/lib/modules.c +++ b/src/lib/modules.c @@ -226,7 +226,7 @@ static INSTR(UURet) { ANN static void code_prepare(const VM_Code code) { m_bit *byte = code->bytecode; - for(m_uint i = 0; i < vector_size(code->instr); ++i) { + for(m_uint i = 0; i < vector_size(&code->instr); ++i) { if(*(m_bit*)(byte + i *BYTECODE_SZ) == eFuncReturn) { *(m_bit*)(byte + i * BYTECODE_SZ)= eOP_MAX; *(f_instr*)(byte + (i*BYTECODE_SZ) + SZ_INT*2) = UURet; diff --git a/src/lib/shred.c b/src/lib/shred.c index ebf21334..756d6e70 100644 --- a/src/lib/shred.c +++ b/src/lib/shred.c @@ -124,7 +124,7 @@ static MFUN(shred##name##_name) { \ const m_str str = code_name((src), 0); \ *(m_uint*)RETURN = (m_uint)new_string(shred->info->mp, shred, str); \ } -describe_name(, s->info->name) +describe_name(, s->info->orig->name) describe_name(_code, s->code->name) #define describe_path_and_dir(name, src) \ @@ -149,7 +149,7 @@ static MFUN(shred##name##_dir) { \ }\ *(m_uint*)RETURN = (m_uint)new_string(shred->info->mp, shred, c); \ } -describe_path_and_dir(, s->info->name) +describe_path_and_dir(, s->info->orig->name) describe_path_and_dir(_code, s->code->name) static DTOR(shred_dtor) { diff --git a/src/vm/vm.c b/src/vm/vm.c index 5692ccd1..3bd9f363 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -40,11 +40,17 @@ uint32_t gw_rand(uint32_t s[2]) { return ret; } -ANN static bool unwind(VM_Shred shred, const Symbol effect) { - if(!shred->info->frame.ptr || !vector_size(&shred->info->frame)) +ANN static inline void shred_unwind(VM_Shred shred) { + shred->pc = *(m_uint*) (shred->mem - SZ_INT * 2); + shred->code = *(VM_Code*)(shred->mem - SZ_INT * 3); + shred->mem -= (*(m_uint*)(shred->mem - SZ_INT * 4) + SZ_INT * 4); +} + +ANN static bool unwind(VM_Shred shred, const Symbol effect, const m_uint size) { + if(!size) return true; if(shred->code->handlers.ptr) { - const m_uint start = VKEY(&shred->info->frame, VLEN(&shred->info->frame) - 1); + const m_uint start = VKEY(&shred->info->frame, size - 1); if(start > shred->pc) return true; const Map m = &shred->code->handlers; @@ -54,7 +60,7 @@ ANN static bool unwind(VM_Shred shred, const Symbol effect) { break; if(start < shred->pc && VKEY(m, i) > shred->pc) { const m_uint next = VKEY(m, i); - const Instr instr = (Instr)vector_at(shred->code->instr, next + 1); + const Instr instr = (Instr)vector_at(&shred->code->instr, next + 1); if(!instr->m_val2 || (Symbol)instr->m_val2 == effect) { pc = next + 1; break; @@ -66,31 +72,50 @@ ANN static bool unwind(VM_Shred shred, const Symbol effect) { shred->reg = (m_bit*)VPTR(&shred->info->frame, VLEN(&shred->info->frame) - 1); shredule(shred->tick->shreduler, shred, 0); shred->pc = pc;//VKEY(m, i); + // should we pop? + VLEN(&shred->info->frame) = size; return false; } // there might be no more stack to unwind - vector_pop(&shred->info->frame); - vector_pop(&shred->info->frame); if(shred->mem == (m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG) return true; - // literally unwind - shred->pc = *(m_uint*) (shred->mem - SZ_INT * 2); - shred->code = *(VM_Code*)(shred->mem - SZ_INT * 3); - shred->mem -= (*(m_uint*)(shred->mem - SZ_INT * 4) + SZ_INT * 4); - return unwind(shred, effect); + shred_unwind(shred); + return unwind(shred, effect, size - 2); +} + +ANN static void trace(VM_Shred shred, const m_uint size) { + const m_uint line = vector_at(&shred->info->line, size-1); + m_uint i; + for(i = size; --i;) { + if(VPTR(&shred->info->line, i-1)) + break; + } + loc_t loc = {.first={.line=line, .column=1},.last={.line=line, .column=1}}; + gw_err(" {-B}┃{0} in function {+}%s{0}{-}:{0}\n", shred->code->name); + gwerr_secondary("called from here", code_name(shred->code->name, true), loc); + if(shred->mem == (m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG) + return; + shred_unwind(shred); + trace(shred, i); } ANN void handle(VM_Shred shred, const m_str effect) { - // remove from the shreduler - // TODO: get shred->mem and shred->reg offsets + m_bit *const reg = shred->reg; + m_bit *const mem = shred->mem; + const m_uint size = shred->info->frame.ptr ? + vector_size(&shred->info->frame) : 0; + const VM_Code code = shred->code; shreduler_remove(shred->tick->shreduler, shred, false); - // do the unwiding - if(unwind(shred, insert_symbol(shred->info->vm->gwion->st, effect))) { - vm_shred_exit(shred); - gw_err("{-C}shred{W}[{Y}% 5" UINT_F "{W}]{-}: {-R}Unhandled {+R}%s{0}\n", shred->tick->xid, effect); + if(!unwind(shred, insert_symbol(shred->info->vm->gwion->st, effect), size)) + return; + gw_err("{-C}shred{W}[{Y}% 5" UINT_F "{W}]{-}: {-R}Unhandled {+R}%s{0}\n", shred->tick->xid, effect); + if(shred->info->line.ptr) { // trace if available + shred->reg = reg; + shred->mem = mem; + shred->code = code; + trace(shred, vector_size(&shred->info->line)); } - // I guess the VM could have *trace mode* - // which would happen here from the top + vm_shred_exit(shred); } @@ -385,7 +410,9 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] &&upvalueint, &&upvaluefloat, &&upvalueother, &&upvalueaddr, &&dotfunc, &&gcini, &&gcadd, &&gcend, - &&gacktype, &&gackend, &&gack, &&try_ini, &&try_end, &&handleeffect, &&performeffect, &&noop, &&eoc, &&unroll2, &&other, &®pushimm + &&gacktype, &&gackend, &&gack, &&try_ini, &&try_end, &&handleeffect, &&performeffect, &&noop, + &&debugline, &&debugvalue, &&debugpush, &&debugpop, + &&eoc, &&unroll2, &&other, &®pushimm }; const Shreduler s = vm->shreduler; register VM_Shred shred; @@ -1019,9 +1046,9 @@ handleeffect: // this should check the *xid* of the exception DISPATCH(); performeffect: + VM_OUT handle(shred, (m_str)VAL); break; -// this should check the *xid* of the exception noop: DISPATCH(); other: @@ -1035,6 +1062,27 @@ in: reg = shred->reg; mem = shred->mem; PC_DISPATCH(shred->pc) +debugline: + if(!shred->info->line.ptr) {// from a problem with spork it seems + vector_init(&shred->info->line); + vector_add(&shred->info->line, VAL); + } else if(!VAL) { + vector_add(&shred->info->line, VAL); + } else { + const m_uint sz = vector_size(&shred->info->line); + vector_set(&shred->info->line, sz - 1, VAL); + } + DISPATCH(); +debugvalue: + DISPATCH(); +debugpush: + if(!shred->info->line.ptr) + vector_init(&shred->info->line); + vector_add(&shred->info->line, 0); + DISPATCH(); +debugpop: + vector_pop(&shred->info->line); + DISPATCH(); eoc: VM_OUT vm_shred_exit(shred); diff --git a/src/vm/vm_code.c b/src/vm/vm_code.c index aed65b8a..1aa3ae89 100644 --- a/src/vm/vm_code.c +++ b/src/vm/vm_code.c @@ -23,7 +23,7 @@ ANN void free_code_instr(const Vector v, const Gwion gwion) { ANN void free_vmcode(VM_Code a, Gwion gwion) { if(!a->builtin) { - _mp_free(gwion->mp, vector_size(a->instr) * BYTECODE_SZ, a->bytecode); + _mp_free(gwion->mp, vector_size(&a->instr) * BYTECODE_SZ, a->bytecode); if(likely(!a->callback)) { if(a->closure) { if(!a->is_memoize) @@ -31,11 +31,11 @@ ANN void free_vmcode(VM_Code a, Gwion gwion) { else memoize_end(gwion->mp, a->memoize); } - free_code_instr(a->instr, gwion); + free_code_instr(&a->instr, gwion); } if(a->handlers.ptr) map_release(&a->handlers); - free_vector(gwion->mp, a->instr); + vector_release(&a->instr); } free_mstr(gwion->mp, a->name); mp_free(gwion->mp , VM_Code, a); @@ -53,7 +53,7 @@ static inline void setpc(const m_bit *data, const m_uint i) { } ANN static m_bit* tobytecode(MemPool p, const VM_Code code) { - const Vector v = code->instr; + const Vector v = &code->instr; const m_uint sz = vector_size(v); m_bit *ptr = _mp_malloc(p, sz * BYTECODE_SZ); struct Vector_ nop; @@ -155,7 +155,9 @@ VM_Code new_vmcode(MemPool p, const Vector instr, const m_uint stack_depth, VM_Code code = mp_calloc(p, VM_Code); code->name = mstrdup(p, name); if(instr) { - code->instr = vector_copy(p, instr); +// code->instr = vector_copy(p, instr); + vector_init(&code->instr); + vector_copy2(instr, &code->instr); code->bytecode = tobytecode(p, code); } code->stack_depth = stack_depth; @@ -169,9 +171,9 @@ VM_Code new_vmcode(MemPool p, const Vector instr, const m_uint stack_depth, VM_Code vmcode_callback(MemPool mp, VM_Code base) { char name[strlen(base->name) + 11]; sprintf(name, "%s(callback)", base->name); - const Instr instr = (Instr)vector_back(base->instr); + const Instr instr = (Instr)vector_back(&base->instr); instr->opcode = eEOC; - VM_Code code = new_vmcode(mp, base->instr, base->stack_depth, base->builtin, name); + VM_Code code = new_vmcode(mp, &base->instr, base->stack_depth, base->builtin, name); code->closure = base->closure; code->callback = 1; instr->opcode = eFuncReturn; diff --git a/src/vm/vm_shred.c b/src/vm/vm_shred.c index 737f8b78..b81a4e54 100644 --- a/src/vm/vm_shred.c +++ b/src/vm/vm_shred.c @@ -11,22 +11,23 @@ struct Stack_ { char d[SIZEOF_MEM]; }; -static inline struct ShredInfo_ *new_shredinfo(MemPool p, const m_str name) { +static inline struct ShredInfo_ *new_shredinfo(MemPool p, const VM_Code c) { struct ShredInfo_ *info = mp_calloc(p, ShredInfo); info->mp = p; - info->name = mstrdup(p, name); + info->orig = c; return info; } static inline void free_shredinfo(MemPool mp, struct ShredInfo_ *info) { - free_mstr(mp, info->name); - if(info->args) { + if(info->args) { // could be a struct const Vector v = info->args; LOOP_OPTIM for(m_uint i = vector_size(v) + 1; --i;) xfree((void*)vector_at(v, i - 1)); free_vector(mp, v); } + if(info->line.ptr) + vector_release(&info->line); mp_free(mp, ShredInfo, info); } @@ -35,8 +36,7 @@ VM_Shred new_vm_shred(MemPool p, VM_Code c) { shred->code = c; shred->reg = (m_bit*)shred + sizeof(struct VM_Shred_); shred->base = shred->mem = shred->reg + SIZEOF_REG; - shred->info = new_shredinfo(p, c->name); - shred->info->orig = c; + shred->info = new_shredinfo(p, c); vector_init(&shred->gc); return shred; }