From: Jérémie Astor Date: Mon, 14 Dec 2020 20:38:29 +0000 (+0100) Subject: :art: Towards late X-Git-Tag: nightly~1105^2~23 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=0979040d4f41cdd7244c205dc79f8417bacdf9f5;p=gwion.git :art: Towards late --- diff --git a/src/emit/emit.c b/src/emit/emit.c index 7913a0d0..7cb55f3f 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -434,9 +434,67 @@ ANN static VM_Code finalyze(const Emitter emit, const f_instr exec) { return code; } +ANN static inline m_uint exp_size(const Exp e) { + if(exp_getvar(e)) + return SZ_INT; + const Type type = e->info->cast_to ?: e->info->type; + return type->size; +} + + +ANN static inline m_uint exp_totalsize(Exp e) { + m_uint size = 0; + do size += exp_size(e); + while((e = e->next)); + return size; +} + +ANN static Instr emit_addref(const Emitter emit, const m_bool emit_var) { + const f_instr exec = !emit_var ? RegAddRef : RegAddRefAddr; + const Instr instr = emit_add_instr(emit, exec); + instr->m_val = -SZ_INT; + return instr; +} + +ANN static void struct_addref(const Emitter emit, const Type type, + const m_int size, const m_bool offset, const m_bool emit_var) { + if(!type->info->tuple) + return; + for(m_uint i = 0; i < vector_size(&type->info->tuple->types); ++i) { + const Type t = (Type)vector_at(&type->info->tuple->types, i); + if(isa(t, emit->gwion->type[et_object]) > 0) { + const Instr instr = emit_addref(emit, emit_var); + instr->m_val = size; + instr->m_val2 = vector_at(&type->info->tuple->offset, i); + } else if(tflag(t, tflag_struct)) + struct_addref(emit, t, size, offset + vector_at(&type->info->tuple->offset, i), emit_var); + } +} + +ANN2(1) static void emit_exp_addref1(const Emitter emit, /* const */Exp exp, m_int size) { + if(isa(exp->info->type, emit->gwion->type[et_object]) > 0 && + (exp->info->cast_to ? isa(exp->info->cast_to, emit->gwion->type[et_object]) > 0 : 1)) { + if(exp->exp_type == ae_exp_decl && GET_FLAG(exp->d.exp_decl.td, ref) && !exp_getvar(exp)) { + const Instr instr = emit_add_instr(emit, GWOP_EXCEPT); + instr->m_val = size; + } + const Instr instr = emit_addref(emit, exp_getvar(exp)); + instr->m_val = size; + } else if(tflag(exp->info->type, tflag_struct)) // check cast_to ? + struct_addref(emit, exp->info->type, size, 0, exp_getvar(exp)); +} + +ANN2(1) static void emit_exp_addref(const Emitter emit, /* const */Exp exp, m_int size) { + do { + emit_exp_addref1(emit, exp, size); + size += exp_size(exp); + } while((exp = exp->next)); +} + ANN static m_bool emit_prim_array(const Emitter emit, const Array_Sub *data) { Exp e = (*data)->exp; CHECK_BB(emit_exp(emit, e)) + emit_exp_addref(emit, e, -exp_totalsize(e)); m_uint count = 0; do ++count; while((e = e->next)); @@ -546,13 +604,6 @@ ANN static m_bool emit_prim_char(const Emitter emit, const m_str *str) { return GW_OK; } -ANN static Instr emit_addref(const Emitter emit, const m_bool emit_var) { - const f_instr exec = !emit_var ? RegAddRef : RegAddRefAddr; - const Instr instr = emit_add_instr(emit, exec); - instr->m_val = -SZ_INT; - return instr; -} - ANN static m_bool emit_prim_str(const Emitter emit, const m_str *str) { char c[strlen(*str) + 1]; if(strlen(*str)) { @@ -796,8 +847,6 @@ ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl* decl) { CHECK_BB(emit_exp_decl_non_static(emit, decl, list->self, ref, var)) else CHECK_BB(emit_exp_decl_global(emit, decl, list->self, ref, var)) - if(!var && !decl->td->option && (GET_FLAG(decl->td, ref) || is_fptr(emit->gwion, list->self->value->type))) - ERR_B(list->self->pos, "kljlkj") } while((list = list->next)); return GW_OK; } @@ -837,16 +886,6 @@ ANN static void emit_func_arg_vararg(const Emitter emit, const Exp_Call* exp_cal free_vector(emit->gwion->mp, kinds); } -ANN static inline m_uint exp_size(Exp e); -ANN static inline m_uint exp_totalsize(Exp e) { - m_uint size = 0; - do size += exp_size(e); - while((e = e->next)); - return size; -} -ANN static /*inline */void emit_exp_addref1(const Emitter emit, Exp, const m_int size); -ANN static /*inline */void emit_exp_addref(const Emitter emit, Exp, const m_int size); - ANN static m_bool emit_func_args(const Emitter emit, const Exp_Call* exp_call) { if(exp_call->args) { CHECK_BB(emit_exp(emit, exp_call->args)) @@ -1149,11 +1188,13 @@ ANN m_bool emit_exp_call1(const Emitter emit, const Func f) { if(vector_size(&emit->code->instr) && vflag(f->value_ref, vflag_member) && is_fptr(emit->gwion, f->value_ref->type)) { const Instr back = (Instr)vector_back(&emit->code->instr); - m_bit exec = back->opcode; - m_uint val = back->m_val; - m_uint val2 = back->m_val2; - back->opcode = eReg2Reg; - back->m_val2 = -SZ_INT; + const Instr base = back->opcode != eGWOP_EXCEPT ? + back : (Instr)vector_at(&emit->code->instr, vector_size(&emit->code->instr) -2); + const m_bit exec = base->opcode; + const m_uint val = base->m_val; + const m_uint val2 = base->m_val2; + base->opcode = eReg2Reg; + base->m_val2 = -SZ_INT; regpush(emit, SZ_INT); const Instr instr = emit_add_instr(emit, (f_instr)(m_uint)exec); instr->m_val = val; @@ -1349,45 +1390,6 @@ ANN static m_bool emit_exp_if(const Emitter emit, const Exp_If* exp_if) { return ret; } -ANN static void struct_addref(const Emitter emit, const Type type, - const m_int size, const m_bool offset, const m_bool emit_var) { - if(!type->info->tuple) - return; - for(m_uint i = 0; i < vector_size(&type->info->tuple->types); ++i) { - const Type t = (Type)vector_at(&type->info->tuple->types, i); - if(isa(t, emit->gwion->type[et_object]) > 0) { - const Instr instr = emit_addref(emit, emit_var); - instr->m_val = size; - instr->m_val2 = vector_at(&type->info->tuple->offset, i); - } else if(tflag(t, tflag_struct)) - struct_addref(emit, t, size, offset + vector_at(&type->info->tuple->offset, i), emit_var); - } -} - -ANN static inline m_uint exp_size(const Exp e) { - if(exp_getvar(e)) - return SZ_INT; - const Type type = e->info->cast_to ?: e->info->type; - return type->size; -} - -ANN2(1) static void emit_exp_addref1(const Emitter emit, /* const */Exp exp, m_int size) { - if(isa(exp->info->type, emit->gwion->type[et_object]) > 0 && - (exp->info->cast_to ? isa(exp->info->cast_to, emit->gwion->type[et_object]) > 0 : 1)) { - const Instr instr = emit_addref(emit, exp_getvar(exp)); - instr->m_val = size; - } else if(tflag(exp->info->type, tflag_struct)) // check cast_to ? - struct_addref(emit, exp->info->type, size, 0, exp_getvar(exp)); -} - -ANN2(1) static void emit_exp_addref(const Emitter emit, /* const */Exp exp, m_int size) { - do { - emit_exp_addref1(emit, exp, size); - size += exp_size(exp); - } while((exp = exp->next)); -} - - ANN static inline m_bool emit_prim_novar(const Emitter emit, const Exp_Primary *prim) { const Exp e = exp_self(prim); const uint var = exp_getvar(e); @@ -1404,7 +1406,6 @@ ANN static m_bool emit_upvalues(const Emitter emit, const Func func) { const Value v = prim->value; CHECK_BB(emit_prim_novar(emit, prim)); if(isa(prim->value->type, emit->gwion->type[et_compound]) > 0) { - emit_exp_addref1(emit, exp_self(prim), -v->type->size); if(vflag(v, vflag_fglobal) && !vflag(v, vflag_closed)) emit_exp_addref1(emit, exp_self(prim), -v->type->size); map_set(&func->code->closure->m, (vtype)v->type, VVAL(map, i)); diff --git a/src/lib/object_op.c b/src/lib/object_op.c index 519009c2..405313fa 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -207,6 +207,10 @@ OP_EMIT(opem_object_dot) { const Instr instr = emit_add_instr(emit, RegPushImm); instr->m_val = (m_uint)value->type; } + if(GET_FLAG(value, ref)) { + const Instr instr = emit_add_instr(emit, GWOP_EXCEPT); + instr->m_val = -SZ_INT; + } return (Instr)GW_OK; } @@ -226,99 +230,6 @@ ANN static m_bool scantmpl_class_def(const Env env, struct tmpl_info *info) { free_class_def(env->gwion->mp, cdef); return ret; } -/* -ANN static OP_CHECK(opck_option_get) { - Exp_Binary *bin = (Exp_Binary*)data; - exp_setvar(bin->rhs, 1); - return bin->rhs->info->type; -} - -static INSTR(OptionCheck) { - const M_Object o = *(M_Object*)REG(-SZ_INT*2); - if(*(m_uint*)(o->data) != instr->m_val2) - Except(shred, "invalid union access"); - memcpy(*(m_bit**)REG(-SZ_INT), o->data + SZ_INT, instr->m_val); - POP_REG(shred, SZ_INT*2 - instr->m_val); - memcpy(&*(m_bit*)REG(-instr->m_val), o->data + SZ_INT, instr->m_val); -} - -ANN static OP_EMIT(opem_option_get) { - Exp_Binary *bin = (Exp_Binary*)data; - const Instr instr = emit_add_instr(emit, OptionCheck); - instr->m_val = bin->rhs->info->type->size; - instr->m_val2 = 1; - return instr; -} - -ANN static OP_CHECK(opck_option_set) { - Exp_Binary *bin = (Exp_Binary*)data; - CHECK_NN(opck_rassign(env, data, mut)) // check those two lines - exp_setvar(bin->rhs, 0); - const Type rhs = bin->rhs->info->type; - const Nspc nspc = bin->lhs->info->type->nspc; - for(m_uint i = 0; i < nspc->info->class_data_size; i += SZ_INT) { - if(rhs == *(Type*)(nspc->info->class_data + i)) - return rhs; - } -// ERR_N(exp_self(data)->pos, _( -// const Value v = nspc_lookup_value0(bin->rhs->info->type->nspc, insert_symbol(env->gwion->st, "@val")); -// return v->type; -} - -static INSTR(OptionSet) { - M_Object o = *(M_Object*)REG(-SZ_INT); - *(m_uint*)(o->data) = instr->m_val2; - *(m_bit**)(o->data + SZ_INT) = *(void**)REG(-instr->m_val); -} - -ANN static OP_EMIT(opem_option_set) { - Exp_Binary *bin = (Exp_Binary*)data; - const Value v = nspc_lookup_value0(bin->rhs->info->type->nspc, insert_symbol(emit->gwion->st, "@val")); - const Instr set = emit_add_instr(emit, OptionSet); - set->m_val = SZ_INT + v->type->size; - set->m_val2 = 1; - const Instr pop = emit_add_instr(emit, RegPop); - pop->m_val = SZ_INT; - return set; -} - -ANN static OP_CHECK(opck_option_setn) { - Exp_Binary *bin = (Exp_Binary*)data; - CHECK_NN(opck_rassign(env, data, mut)) - exp_setvar(bin->rhs, 1); - return env->gwion->type[et_void]; -} - -ANN static OP_EMIT(opem_option_setn) { - Exp_Binary *bin = (Exp_Binary*)data; - const Instr instr = emit_add_instr(emit, OptionSet); - instr->m_val = bin->rhs->info->type->nspc->info->offset; - const Instr pop2 = emit_add_instr(emit, RegPop); - pop2->m_val = SZ_INT * 2; - return instr; -} - -ANN static OP_EMIT(opem_option_not) { - Exp_Unary *unary = (Exp_Unary*)data; - const Instr pop = emit_add_instr(emit, RegPop); - pop->m_val = unary->exp->info->type->size - SZ_INT; - return emit_add_instr(emit, IntNot); -} - -ANN static OP_EMIT(opem_option_cond) { - Exp exp = (Exp)data; - const Instr pop = emit_add_instr(emit, RegPop); - pop->m_val = exp->info->type->size - SZ_INT; - return emit_add_instr(emit, BranchEqInt); -} - -ANN static OP_EMIT(opem_option_uncond) { - Exp exp = (Exp)data; - const Instr pop = emit_add_instr(emit, RegPop); - pop->m_val = exp->info->type->size - SZ_INT; - return emit_add_instr(emit, BranchNeqInt); -} -*/ ANN static m_bool scantmpl_union_def(const Env env, struct tmpl_info *info) { const Union_Def u = info->base->info->udef; diff --git a/src/parse/check.c b/src/parse/check.c index 87324070..c0c6852b 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -120,6 +120,15 @@ ANN static m_bool check_var_td(const Env env, const Var_Decl var, Type_Decl *con return GW_OK; } +ANN static void set_late(const Gwion gwion, const Exp_Decl *decl, const Value v) { + if(!exp_getvar(exp_self(decl)) && + (GET_FLAG(decl->td, ref) || is_fptr(gwion, v->type))) { + SET_FLAG(decl->td, ref); + SET_FLAG(v, ref); + } else + UNSET_FLAG(v, ref); +} + ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) { Var_Decl_List list = decl->list; do { @@ -128,6 +137,7 @@ ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) { CHECK_BB(check_var_td(env, var, decl->td)) if(is_fptr(env->gwion, decl->type)) CHECK_BB(check_fptr_decl(env, var)) + set_late(env->gwion, decl, list->self->value); set_vflag(var->value, vflag_valid); //set_vflag(var->value, vflag_used)); nspc_add_value(env->curr, var->xid, var->value); @@ -686,6 +696,8 @@ ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) { ANN m_bool func_check(const Env env, const Exp_Call *exp) { CHECK_OB(check_exp(env, exp->func)) + if(exp->func->exp_type == ae_exp_decl) + ERR_B(exp->func->pos, _("Can't call late function pointer at declaration site")) const Type t = actual_type(env->gwion, exp->func->info->type); const Exp e = exp_self(exp); struct Op_Import opi = { .op=insert_symbol("@func_check"), diff --git a/src/vm/vm.c b/src/vm/vm.c index d9c28002..c9032cae 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -765,7 +765,7 @@ newobj: addref: { const M_Object o = *((M_Object*)(reg+(m_int)VAL) + (m_int)VAL2); - if(o) +// if(o) ++o->ref; } DISPATCH() @@ -797,7 +797,7 @@ except: * VAL = offset (no default SZ_INT) * * VAL2 = error message * * grep for GWOP_EXCEPT and Except, exception... */ - if(!*(M_Object*)(reg-SZ_INT-VAL)) { + if(!*(M_Object*)(reg-(m_int)VAL)) { shred->pc = PC; exception(shred, "NullPtrException"); continue; diff --git a/tests/error/fptr_call_decl.gw b/tests/error/fptr_call_decl.gw new file mode 100644 index 00000000..9b66787c --- /dev/null +++ b/tests/error/fptr_call_decl.gw @@ -0,0 +1,3 @@ +#! [contains] Can't call late function pointer at declaration site +funcdef void test(int); +(var test t)(2);