From e7afc9a571a3434dfb5f8365c09c14dd0fc271f5 Mon Sep 17 00:00:00 2001 From: fennecdjay Date: Tue, 10 Sep 2019 14:15:39 +0200 Subject: [PATCH] :bug: AFL ... again --- include/type.h | 2 +- src/emit/emit.c | 13 +++++-------- src/lib/gack.c | 9 ++++++--- src/lib/instr.c | 4 +++- src/lib/object.c | 2 ++ src/lib/string.c | 10 +++++----- src/lib/vararg.c | 6 ++---- src/oo/type.c | 13 ++++++++++--- src/parse/check.c | 21 +++++++++++++-------- src/parse/scan0.c | 2 +- src/parse/scan2.c | 6 ++++-- src/parse/type_decl.c | 2 ++ src/vm/vm.c | 7 ++++++- src/vm/vm_code.c | 9 ++++++--- 14 files changed, 66 insertions(+), 40 deletions(-) diff --git a/include/type.h b/include/type.h index 4880184d..e55834ac 100644 --- a/include/type.h +++ b/include/type.h @@ -26,7 +26,7 @@ struct Type_ { extern Type t_void, t_int, t_bool, t_float, t_dur, t_time, t_now, t_complex, t_polar, t_vec3, t_vec4, t_null, t_object, t_shred, t_fork, t_event, t_ugen, t_string, t_ptr, t_array, t_gack, - t_function, t_fptr, t_vararg, t_lambda, t_class, t_union, t_undefined, t_auto, t_tuple; + t_function, t_fptr, t_varloop, t_vararg, t_lambda, t_class, t_union, t_undefined, t_auto, t_tuple; ANN2(1,3) ANEW Type new_type(MemPool, const m_uint xid, const m_str name, const Type); ANEW ANN Type type_copy(MemPool, const Type type); diff --git a/src/emit/emit.c b/src/emit/emit.c index e68bda2d..eb0de8e0 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -235,7 +235,7 @@ ANN m_bool emit_array_extend(const Emitter emit, const Type t, const Exp e) { } ANN static inline void emit_notpure(const Emitter emit) { - ++VPTR(&emit->pure, VLEN(&emit->pure)); + ++VPTR(&emit->pure, VLEN(&emit->pure) - 1); } ANN static Array_Sub instantiate_typedef(MemPool p, const m_uint depth) { @@ -577,6 +577,7 @@ ANN static m_bool prim_str(const Emitter emit, const Exp_Primary* prim) { ANN static m_bool prim_gack(const Emitter emit, const Exp_Primary* primary) { const Exp exp = primary->d.exp; + CHECK_BB(emit_exp(emit, exp, 0)) const Vector v = new_vector(emit->gwion->mp); m_uint offset = 0; Exp e = exp; @@ -584,10 +585,6 @@ ANN static m_bool prim_gack(const Emitter emit, const Exp_Primary* primary) { vector_add(v, (vtype)e->type); offset += e->type->size; } while((e = e->next)); - if(emit_exp(emit, exp, 0) < 0) { - free_vector(emit->gwion->mp, v); - ERR_B(exp->pos, _(" ... in 'gack' expression.")) - } const Instr instr = emit_add_instr(emit, Gack); instr->m_val = offset; instr->m_val2 = (m_uint)v; @@ -972,15 +969,15 @@ ANN m_bool emit_exp_call1(const Emitter emit, const Func f) { back->opcode = ePushStaticCode; back->m_val = 0; } - }else if(emit->env->func != f && !f->value_ref->owner_class && !f->code && !is_fptr(f->value_ref->type)) { - const Instr back = emit_add_instr(emit, PushStaticCode); + } else if(emit->env->func != f && !f->value_ref->owner_class && !f->code && !is_fptr(f->value_ref->type)) { + const Instr back = !GET_FLAG(f->def, op) ? emit_add_instr(emit, PushStaticCode) : (Instr)vector_back(&emit->code->instr); back->m_val = (m_uint)f; } } else if((f->value_ref->owner_class && is_special(f->value_ref->owner_class) > 0) || !f->value_ref->owner_class || (GET_FLAG(f, template) && isa(f->value_ref->type, t_fptr) < 0)) push_func_code(emit, f); - else if(vector_size(&emit->code->instr)){ + else if(vector_size(&emit->code->instr)) { const Instr back = (Instr)vector_back(&emit->code->instr); if((f_instr)(m_uint)back->opcode == DotFunc || (f_instr)(m_uint)back->opcode == DotStaticFunc) back->m_val = f->vt_index; diff --git a/src/lib/gack.c b/src/lib/gack.c index 2bf97e84..3749a3db 100644 --- a/src/lib/gack.c +++ b/src/lib/gack.c @@ -79,9 +79,12 @@ ANN static inline void print_func(const Type type, const m_bit* stack) { gw_out("%s", f ? f->name : "(nil)"); return; } - const VM_Code code = isa(type, t_fptr) > 0 ? - *(VM_Code*)stack : type->e->d.func->code; - gw_out("%s %s %p", type->name, (void*)code ? code->name : NULL, code); + if(type->e->d.func) { + const VM_Code code = isa(type, t_fptr) > 0 ? + *(VM_Code*)stack : type->e->d.func->code; + gw_out("%s %s %p", type->name, (void*)code ? code->name : NULL, code); + } else // uncalled lambda + gw_out("%p", NULL); } ANN static void print_prim(const Type type, const m_bit* stack) { diff --git a/src/lib/instr.c b/src/lib/instr.c index 311d884a..634a7868 100644 --- a/src/lib/instr.c +++ b/src/lib/instr.c @@ -100,7 +100,7 @@ INSTR(DotTmpl) { struct dottmpl_ *dt = (struct dottmpl_*)instr->m_val; const m_str name = dt->name; const M_Object o = *(M_Object*)REG(-SZ_INT); - Type t = o->type_ref; + Type t = !GET_FLAG(o->type_ref, nonnull) ? o->type_ref : o->type_ref->e->parent; do { const Emitter emit = shred->info->vm->gwion->emit; emit->env->name = "runtime"; @@ -109,6 +109,8 @@ INSTR(DotTmpl) { strcpy(str + instr->m_val2, t->name); const Func f = nspc_lookup_func0(t->nspc, insert_symbol(emit->env->gwion->st, str)); if(f) { + if(!f->code) + break; *(VM_Code*)shred->reg = f->code; shred->reg += SZ_INT; return; diff --git a/src/lib/object.c b/src/lib/object.c index e0f103e2..48c09e40 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -109,6 +109,8 @@ static inline Type check_nonnull(const Env env, const Type l, const Type r, if(GET_FLAG(r, nonnull)) { if(isa(l, t_null) > 0) ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name); + if(isa(l, r) < 0) + ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name); return r->e->parent; } if(nonnull_check(l, r)) diff --git a/src/lib/string.c b/src/lib/string.c index 311011a3..dd66025a 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -74,10 +74,10 @@ describe_string_assign(Polar_, m_complex, SZ_COMPLEX,, num_digit((m_uint)creal(lhs)) + num_digit((m_uint)cimag(lhs) / M_PI) + 16, "#(%.4f, %.4f)", creal(lhs), cimag(lhs)/M_PI) describe_string_assign(Vec3_, m_vec3, SZ_VEC3,, - num_digit((m_uint)lhs.x) + num_digit((m_uint)lhs.y) + num_digit((m_uint)lhs.z) + 23, + num_digit((m_uint)lhs.x) + num_digit((m_uint)lhs.y) + num_digit((m_uint)lhs.z) + 25, "#(%.4f, %.4f, %.4f)", lhs.x, lhs.y, lhs.z) describe_string_assign(Vec4_, m_vec4, SZ_VEC4,, - num_digit((m_uint)lhs.x) + num_digit((m_uint)lhs.y) + num_digit((m_uint)lhs.z) + num_digit((m_uint)lhs.w) + 30, + num_digit((m_uint)lhs.x) + num_digit((m_uint)lhs.y) + num_digit((m_uint)lhs.z) + num_digit((m_uint)lhs.w) + 40, "#(%.4f, %.4f, %.4f, %.4f)", lhs.x, lhs.y, lhs.z, lhs.w) describe_string_assign(Object_, M_Object, SZ_INT, release(lhs, shred), 16, @@ -118,15 +118,15 @@ describe_string(Complex, m_complex, SZ_COMPLEX, "#(%.4f, %.4f)%s", creal(lhs), cimag(lhs), rhs ? STRING(rhs) : "") describe_string(Polar, m_complex, SZ_COMPLEX, num_digit((m_uint)creal(lhs)) + num_digit((m_uint)cimag(lhs) / M_PI) + (rhs ? strlen(STRING(rhs)) : 0) + 12,, - "%%(%.4f, %4f*pi)%s", creal(lhs), cimag(lhs) / M_PI, rhs ? STRING(rhs) : "") + "%%(%.4f, %.4f*pi)%s", creal(lhs), cimag(lhs) / M_PI, rhs ? STRING(rhs) : "") describe_string(Vec3, m_vec3, SZ_VEC3, (rhs ? strlen(STRING(rhs)) : 0) + 23 + num_digit((m_uint)lhs.x) + num_digit((m_uint)lhs.y) + num_digit((m_uint)lhs.z),, "@(%.4f, %.4f, %.4f)%s", lhs.x, lhs.y, lhs.z, rhs ? STRING(rhs) : "") describe_string(Vec4, m_vec4, SZ_VEC4, - (rhs ? strlen(STRING(rhs)) : 0) + 28 + num_digit((m_uint)lhs.x) + + (rhs ? strlen(STRING(rhs)) : 0) + 30 + num_digit((m_uint)lhs.x) + num_digit((m_uint)lhs.y) + num_digit((m_uint)lhs.z) + num_digit((m_uint)lhs.w),, - "@(%4f, %4f, %4f, %4f)%s", lhs.x, lhs.y, lhs.z, lhs.w, rhs ? STRING(rhs) : "") + "@(%.4f, %.4f, %.4f, %.4f)%s", lhs.x, lhs.y, lhs.z, lhs.w, rhs ? STRING(rhs) : "") describe_string(Object, M_Object, SZ_INT, 16 + (rhs ? strlen(STRING(rhs)) : 0), release(lhs, shred), "%p%s", (void*)lhs, rhs ? STRING(rhs) : "") diff --git a/src/lib/vararg.c b/src/lib/vararg.c index dc7a68c3..b6acd692 100644 --- a/src/lib/vararg.c +++ b/src/lib/vararg.c @@ -34,7 +34,7 @@ INSTR(VarargTop) { INSTR(VarargIni) { struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg); - POP_REG(shred, instr->m_val - SZ_INT) + POP_REG(shred, instr->m_val - SZ_INT) arg->d = (m_bit*)xmalloc(round2szint(instr->m_val)); for(m_uint i = 0; i < instr->m_val; i += SZ_INT) *(m_uint*)(arg->d + i) = *(m_uint*)(shred->reg - SZ_INT + i); @@ -85,10 +85,8 @@ static FREEARG(freearg_vararg) { GWION_IMPORT(vararg) { GWI_OB((t_vararg = gwi_mk_type(gwi, "@Vararg", SZ_INT, t_object))) const Type t_varobj = gwi_mk_type(gwi, "VarObject", SZ_INT, t_vararg); - GWI_OB(t_varobj) SET_FLAG(t_varobj, abstract); - const Type t_varloop = gwi_mk_type(gwi, "@VarLoop", SZ_INT, NULL); - GWI_OB(t_varloop) + t_varloop = gwi_mk_type(gwi, "@VarLoop", SZ_INT, NULL); GWI_BB(gwi_add_type(gwi, t_varobj)) GWI_BB(gwi_add_type(gwi, t_varloop)) GWI_BB(gwi_class_ini(gwi, t_vararg, NULL, NULL)) diff --git a/src/oo/type.c b/src/oo/type.c index 37ed44b9..aeb17223 100644 --- a/src/oo/type.c +++ b/src/oo/type.c @@ -139,8 +139,15 @@ ANN m_bool type_ref(Type t) { if(GET_FLAG(t, empty)) return GW_OK; if(GET_FLAG(t, typedef) && t->e->def) - if(t->e->def->base.ext && t->e->def->base.ext->array && !t->e->def->base.ext->array->exp) - return GW_OK; + if(t->e->def->base.ext && t->e->def->base.ext->array) { + if(!t->e->def->base.ext->array->exp) + return GW_OK; + else { + const Type type = t->e->parent->e->d.base_type; + if(GET_FLAG(type, empty)) + return GW_OK; + } + } } while((t = t->e->parent)); return 0; } @@ -192,4 +199,4 @@ ANN m_uint get_depth(const Type type) { Type t_void, t_int, t_bool, t_float, t_dur, t_time, t_now, t_complex, t_polar, t_vec3, t_vec4, t_null, t_object, t_shred, t_fork, t_event, t_ugen, t_string, t_ptr, t_array, t_gack, - t_function, t_fptr, t_vararg, t_lambda, t_class, t_union, t_undefined, t_auto, t_tuple; + t_function, t_fptr, t_varloop, t_vararg, t_lambda, t_class, t_union, t_undefined, t_auto, t_tuple; diff --git a/src/parse/check.c b/src/parse/check.c index f71804c3..f5ba6d97 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -62,7 +62,7 @@ ANN static m_bool check_fptr_decl(const Env env, const Var_Decl var) { return GW_OK; ERR_B(var->pos, _("can't use non public typedef at global scope.")) } - if(isa(type, env->class_def) < 0 && !GET_FLAG(func, global)) + if(type && isa(type, env->class_def) < 0 && !GET_FLAG(func, global)) ERR_B(var->pos, _("can't use non global fptr of other class.")) if(GET_FLAG(func, member) && GET_FLAG(v, static)) ERR_B(var->pos, _("can't use static variables for member function.")) @@ -463,7 +463,7 @@ ANN static m_bool func_match_inner(const Env env, const Exp e, const Type t, if(implicit) { const struct Implicit imp = { e, t, e->pos }; struct Op_Import opi = { .op=insert_symbol("@implicit"), .lhs=e->type, .rhs=t, .data=(m_uint)&imp, .pos=e->pos }; - return op_check(env, &opi) ? 1 : -1; + return op_check(env, &opi) ? GW_OK : GW_ERROR; } } return match ? 1 : -1; @@ -596,6 +596,7 @@ CHECK_BO(check_call(env, exp)) if(env->func == exists->d.func_ref) { if(check_call(env, exp) < 0) continue; + CHECK_OO(find_func_match(env, env->func, exp->args)) m_func = env->func; break; } @@ -700,7 +701,7 @@ ANN static Type check_exp_call_template(const Env env, Exp_Call *exp) { DECL_OO(const Value, value, = nspc_lookup_value1(call->type->e->owner, insert_symbol(call->type->name))) Tmpl *tm = value->d.func_ref ? value->d.func_ref->def->base->tmpl : call->type->e->d.func->def->base->tmpl; if(tm->call) { - const Func func = value->d.func_ref ?: predefined_func(env, value, exp, tm); + DECL_OO(const Func, func, = value->d.func_ref ?: predefined_func(env, value, exp, tm)) if(!func->def->base->ret_type) { // template fptr const m_uint scope = env_push(env, value->owner_class, value->owner); CHECK_BO(traverse_func_def(env, func->def)) @@ -774,7 +775,8 @@ ANN Type check_exp_call1(const Env env, const Exp_Call *exp) { return check_lambda_call(env, exp); if(GET_FLAG(exp->func->type->e->d.func, ref)) { const Value value = exp->func->type->e->d.func->value_ref; - CHECK_BO(traverse_class_def(env, value->owner_class->e->def)) + if(value->owner_class) + CHECK_BO(traverse_class_def(env, value->owner_class->e->def)) } if(exp->args) CHECK_OO(check_exp(env, exp->args)) @@ -834,9 +836,9 @@ ANN static m_bool predefined_call(const Env env, const Type t, const loc_t pos) ANN static Type check_exp_call(const Env env, Exp_Call* exp) { if(exp->tmpl) { CHECK_OO(check_exp(env, exp->func)) - const Type t = actual_type(exp->func->type); + const Type t = actual_type(!GET_FLAG(exp->func->type, nonnull) ? + exp->func->type : exp->func->type->e->parent); const Value v = nspc_lookup_value1(t->e->owner, insert_symbol(t->name)); - assert(v); if(!GET_FLAG(v, func) && !GET_FLAG(exp->func->type, func) ) ERR_O(exp_self(exp)->pos, _("template call of non-function value.")) if(!v->d.func_ref || !v->d.func_ref->def->base->tmpl) @@ -936,13 +938,16 @@ static const _type_func exp_func[] = { }; ANN static inline Type check_exp(const Env env, const Exp exp) { - Exp curr = exp; + Exp curr = exp, next = NULL, prev = NULL; do { + next = curr->next; CHECK_OO((curr->type = exp_func[curr->exp_type](env, &curr->d))) + if(isa(curr->type, t_varloop) > 0 && (prev || next)) + ERR_O(exp->pos, _("Varloop must be the only expression")) if(env->func && isa(curr->type, t_lambda) < 0 && isa(curr->type, t_function) > 0 && !GET_FLAG(curr->type->e->d.func, pure)) UNSET_FLAG(env->func, pure); - } while((curr = curr->next)); + } while((prev = curr) && (curr = next)); return exp->type; } diff --git a/src/parse/scan0.c b/src/parse/scan0.c index e87b5614..b05e8d76 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -70,7 +70,7 @@ static void fptr_def(const Env env, const Fptr_Def fptr) { ANN m_bool scan0_fptr_def(const Env env, const Fptr_Def fptr) { CHECK_BB(env_access(env, fptr->base->td->flag, td_pos(fptr->base->td))) - CHECK_OO(known_type(env, fptr->base->td)) + CHECK_OB(known_type(env, fptr->base->td)) CHECK_BB(scan0_defined(env, fptr->base->xid, td_pos(fptr->base->td))); const m_str name = s_name(fptr->base->xid); const Type t = new_type(env->gwion->mp, t_fptr->xid, name, t_fptr); diff --git a/src/parse/scan2.c b/src/parse/scan2.c index 451d3efb..80e9f934 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -81,13 +81,15 @@ ANN static Value scan2_func_assign(const Env env, const Func_Def d, ANN m_bool scan2_fptr_def(const Env env, const Fptr_Def fptr) { - const Func_Def def = fptr->type->e->d.func->def; if(!tmpl_base(fptr->base->tmpl)) { + const Func_Def def = fptr->type->e->d.func->def; def->base->ret_type = fptr->base->ret_type; if(fptr->base->args) CHECK_BB(scan2_args(env, def)) - } else + } else { + CHECK_OB(fptr->type) // should happen before SET_FLAG(fptr->type, func); + } return GW_OK; } diff --git a/src/parse/type_decl.c b/src/parse/type_decl.c index e9fb5dcc..245d5db3 100644 --- a/src/parse/type_decl.c +++ b/src/parse/type_decl.c @@ -18,6 +18,8 @@ ANN Type type_decl_resolve(const Env env, const Type_Decl* td) { DECL_OO(const Type, t, = scan_type(env, base, td)) const Type ret = !td->array ? t : array_type(env, t, td->array->depth); if(GET_FLAG(td, nonnull)) { + if(isa(ret, t_void) > 0) + ERR_O(td_pos(td), _("void types can't be nonnull.")) if(isa(ret, t_object) < 0 && isa(ret, t_function) < 0) return ret; char c[strlen(t->name) + 9]; diff --git a/src/vm/vm.c b/src/vm/vm.c index 129eba1d..0ef90a00 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -306,7 +306,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] &&newobj, &&addref, &&objassign, &&assign, &&remref, &&except, &&allocmemberaddr, &&dotmember, &&dotfloat, &&dotother, &&dotaddr, &&staticint, &&staticfloat, &&staticother, - &&dotfunc, &&dotstaticfunc, &&eoc, &&pushstr, + &&dotfunc, &&dotstaticfunc, &&pushstaticcode, &&pushstr, &&gcini, &&gcadd, &&gcend, &&gack, &®pushimm, &&other, &&eoc }; @@ -801,6 +801,11 @@ PRAGMA_PUSH() *(VM_Code*)(reg-SZ_INT) = ((Func)vector_at(a.obj->vtable, VAL))->code; PRAGMA_POP() DISPATCH() +pushstaticcode: + *(m_bit*)byte = eRegPushImm; + VAL = (*(m_uint*)(reg) = (m_uint)((Func)VAL)->code); + reg += SZ_INT; + DISPATCH() pushstr: *(M_Object*)reg = new_string2(vm->gwion->mp, shred, (m_str)VAL); reg += SZ_INT; diff --git a/src/vm/vm_code.c b/src/vm/vm_code.c index 6a6d29f3..bcb1e2bc 100644 --- a/src/vm/vm_code.c +++ b/src/vm/vm_code.c @@ -52,9 +52,12 @@ ANN static m_bit* tobytecode(MemPool p, const VM_Code code) { instr->opcode = eRegPushImm; instr->m_val = (m_uint)code; } else { - instr->opcode = eRegSetImm; - instr->m_val = (m_uint)((Func)instr->m_val)->code; - instr->m_val2 = -SZ_INT; + const Func f = (Func)instr->m_val; + if(f->code) { + instr->opcode = eRegSetImm; + instr->m_val = (m_uint)((Func)instr->m_val)->code; + instr->m_val2 = -SZ_INT; + } } } if(instr->opcode < eGack) -- 2.43.0