From 72dbfb903c405f62fac5533a4ccc7cf56e2cd548 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Sat, 21 Nov 2020 19:40:31 +0100 Subject: [PATCH] :art: Ptr as a struct --- include/env/type.h | 9 ++++ src/emit/emit.c | 106 +++++++++++++++++++++++---------------- src/import/import_cdef.c | 18 +++++-- src/lib/object_op.c | 2 +- src/lib/ptr.c | 70 +++++++++++++++----------- src/vm/vm.c | 4 +- 6 files changed, 130 insertions(+), 79 deletions(-) diff --git a/include/env/type.h b/include/env/type.h index 87c481e3..b6400d90 100644 --- a/include/env/type.h +++ b/include/env/type.h @@ -64,11 +64,20 @@ static inline int safe_tflag(const Type t, const enum tflag flag) { ANN static inline void set_tflag(const Type t, const enum tflag flag) { t->tflag |= flag; } + +static inline void unset_tflag(const Type t, const enum tflag flag) { + t->tflag &= ~flag; +} #else ANN static inline void set_tflag(const Type t, const enum tflag flag) { auto ff = t->tflag | flag; t->tflag = static_cast(ff); } + +static inline void unset_tflag(const Type t, const enum tflag flag) { + const auto ff = t->tflag & ~flag; + t->tflag = static_cast(tt); +} #endif 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 db61a193..84925707 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -76,9 +76,68 @@ ANN static inline void frame_push(Frame* frame) { vector_add(&frame->stack, (vtype)NULL); } +static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushImm4 }; +static const f_instr regpushmem[] = { RegPushMem, RegPushMem2, RegPushMem3, RegPushMem4 }; +static const f_instr regpushbase[] = { RegPushBase, RegPushBase2, RegPushBase3, RegPushBase4 }; +static const f_instr dotstatic[] = { DotStatic, DotStatic2, DotStatic3, RegPushImm }; +static const f_instr allocmember[] = { RegPushImm, RegPushImm2, RegPushImm3, AllocMember4 }; +static const f_instr allocword[] = { AllocWord, AllocWord2, AllocWord3, RegPushMem4 }; +static const f_instr structmember[] = { StructMember, StructMemberFloat, StructMemberOther, StructMemberAddr }; + +#define regxxx(name, instr) \ +ANN static inline Instr reg##name(const Emitter emit, const m_uint sz) { \ + const Instr instr = emit_add_instr(emit, Reg##instr); \ + instr->m_val = sz; \ + return instr; \ +} +regxxx(pop, Pop) +regxxx(push, Push) +regxxx(pushi, PushImm) +regxxx(seti, SetImm) + +static inline enum Kind kindof(const m_uint size, const uint emit_var) { + if(emit_var) + return KIND_ADDR; + return size == SZ_INT ? KIND_INT : size == SZ_FLOAT ? KIND_FLOAT : KIND_OTHER; +} + +ANN /*static */Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]) { + const enum Kind kind = kindof(size, addr); + const Instr instr = emit_add_instr(emit, func[kind]); + instr->m_val2 = size; + return instr; +} + +ANN static void emit_struct_ctor(const Emitter emit, const Type type, const m_uint offset) { + emit->code->frame->curr_offset += SZ_INT; + const Instr instr = emit_add_instr(emit, RegPushMem4); + instr->m_val = offset; + const Instr tomem = emit_add_instr(emit, Reg2Mem); + tomem->m_val = emit->code->frame->curr_offset; + tomem->m_val2 = -SZ_INT; + regpushi(emit, (m_uint)type); + const Instr tomem2 = emit_add_instr(emit, Reg2Mem); + tomem2->m_val = emit->code->frame->curr_offset + SZ_INT; + tomem2->m_val2 = -SZ_INT; + const Instr set_code = regseti(emit, (m_uint)type->nspc->dtor); + set_code->m_val2 = SZ_INT; + const m_uint code_offset = emit_code_offset(emit); + const Instr regset = regseti(emit, code_offset); + regset->m_val2 = SZ_INT *2; + regpush(emit, SZ_INT *2); + const Instr prelude = emit_add_instr(emit, SetCode); + prelude->m_val2 = 2; + prelude->m_val = SZ_INT*3; + const Instr next = emit_add_instr(emit, Overflow); + next->m_val2 = code_offset; + emit->code->frame->curr_offset -= SZ_INT; +} + ANN static void struct_pop(const Emitter emit, const Type type, const m_uint offset) { if(!type->info->tuple) return; + if(type->nspc->dtor) + emit_struct_ctor(emit, type, offset); 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) { @@ -177,17 +236,6 @@ ANN static void emit_pre_ctor(const Emitter emit, const Type type) { emit_array_extend(emit, type->info->parent, type->info->cdef->base.ext->array->exp); } -#define regxxx(name, instr) \ -ANN static inline Instr reg##name(const Emitter emit, const m_uint sz) { \ - const Instr instr = emit_add_instr(emit, Reg##instr); \ - instr->m_val = sz; \ - return instr; \ -} -regxxx(pop, Pop) -regxxx(push, Push) -regxxx(pushi, PushImm) -regxxx(seti, SetImm) - ANN static void struct_expand(const Emitter emit, const Type t) { const Instr instr = emit_add_instr(emit, Reg2RegDeref); instr->m_val = -SZ_INT; @@ -275,8 +323,7 @@ ANN void emit_ext_ctor(const Emitter emit, const Type t) { const m_uint offset = emit_code_offset(emit); const Instr regset = regseti(emit, offset); regset->m_val2 = SZ_INT *2; - const Instr push = emit_add_instr(emit, RegPush); - push->m_val = SZ_INT *2; + regpush(emit, SZ_INT*2); const Instr prelude = emit_add_instr(emit, SetCode); prelude->m_val2 = 2; prelude->m_val = SZ_INT; @@ -310,27 +357,6 @@ ANN2(1,2) m_bool emit_instantiate_object(const Emitter emit, const Type type, return GW_OK; } -static inline enum Kind kindof(const m_uint size, const uint emit_var) { - if(emit_var) - return KIND_ADDR; - return size == SZ_INT ? KIND_INT : size == SZ_FLOAT ? KIND_FLOAT : KIND_OTHER; -} - -ANN /*static */Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]) { - const enum Kind kind = kindof(size, addr); - const Instr instr = emit_add_instr(emit, func[kind]); - instr->m_val2 = size; - return instr; -} - -static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushImm4 }; -static const f_instr regpushmem[] = { RegPushMem, RegPushMem2, RegPushMem3, RegPushMem4 }; -static const f_instr regpushbase[] = { RegPushBase, RegPushBase2, RegPushBase3, RegPushBase4 }; -static const f_instr dotstatic[] = { DotStatic, DotStatic2, DotStatic3, RegPushImm }; -static const f_instr allocmember[] = { RegPushImm, RegPushImm2, RegPushImm3, AllocMember4 }; -static const f_instr allocword[] = { AllocWord, AllocWord2, AllocWord3, RegPushMem4 }; -static const f_instr structmember[] = { StructMember, StructMemberFloat, StructMemberOther, StructMemberAddr }; - ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data); ANN static m_bool emit_symbol_owned(const Emitter emit, const Symbol *data) { const Exp dot = symbol_owned_exp(emit->gwion, data); @@ -1572,20 +1598,12 @@ ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) { return ret; } -ANN static Instr emit_stmt_eachptr_init(const Emitter emit, const Type type) { - const Instr new_obj = emit_add_instr(emit, ObjectInstantiate); - new_obj->m_val2 = (m_uint)type; - (void)emit_addref(emit, 0); - regpop(emit, SZ_INT); - return emit_add_instr(emit, Reg2Mem); -} - ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt, m_uint *end_pc) { const Instr s1 = emit_add_instr(emit, MemSetImm); - Instr cpy = stmt->is_ptr ? emit_stmt_eachptr_init(emit, stmt->v->type) : NULL; + Instr cpy = stmt->is_ptr ? emit_add_instr(emit, MemSetImm) : NULL; emit_local(emit, emit->gwion->type[et_int]); const m_uint offset = emit_local(emit, emit->gwion->type[et_int]); - emit_local(emit, emit->gwion->type[et_int]); + emit_local(emit, emit->gwion->type[et_ptr]);//et_int stmt->v->from->offset = offset + SZ_INT; const m_uint ini_pc = emit_code_size(emit); emit_except(emit, stmt->exp->info->type); diff --git a/src/import/import_cdef.c b/src/import/import_cdef.c index 9c6dbcaa..27a95019 100644 --- a/src/import/import_cdef.c +++ b/src/import/import_cdef.c @@ -102,11 +102,21 @@ ANN2(1,2) Type gwi_class_ini(const Gwi gwi, const m_str name, const m_str parent } ANN Type gwi_struct_ini(const Gwi gwi, const m_str name) { - CHECK_OO(gwi_str2sym(gwi, name)) - const Type t = new_type(gwi->gwion->mp, ++gwi->gwion->env->scope->type_xid, name, gwi->gwion->type[et_compound]); - t->info->tuple = new_tupleform(gwi->gwion->mp, NULL); - gwi_type_flag(t); + struct ImportCK ck = { .name=name }; + CHECK_BO(check_typename_def(gwi, &ck)) + const Type t = new_type(gwi->gwion->mp, ++gwi->gwion->env->scope->type_xid, s_name(ck.sym), gwi->gwion->type[et_compound]); set_tflag(t, tflag_struct); + if(!ck.tmpl) + gwi_type_flag(t); + else { + t->info->cdef = new_class_def(gwi->gwion->mp, 0, ck.sym, NULL, NULL, loc(gwi)); + t->info->cdef->base.type = t; + t->info->cdef->base.tmpl = new_tmpl_base(gwi->gwion->mp, ck.tmpl); + t->info->tuple = new_tupleform(gwi->gwion->mp, NULL); + t->info->parent = NULL; + t->info->cdef->cflag |= cflag_struct; + set_tflag(t, tflag_tmpl); + } return type_finish(gwi, t); } diff --git a/src/lib/object_op.c b/src/lib/object_op.c index 4b7f7111..795166b7 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -262,7 +262,6 @@ OP_EMIT(opem_object_dot) { } struct tmpl_info { -// const Class_Def cdef; Symbol name; ID_List list; Type_List call; @@ -344,6 +343,7 @@ ANN static m_bool scantmpl_class_def(const Env env, struct tmpl_info *info) { const Class_Def cdef = new_class_def(env->gwion->mp, c->flag, info->name, c->base.ext ? cpy_type_decl(env->gwion->mp, c->base.ext) : NULL, c->body ?cpy_ast(env->gwion->mp, c->body) : NULL, loc_cpy(env->gwion->mp, c->pos)); + cdef->cflag = c->cflag; cdef->base.tmpl = mk_tmpl(env, c->base.tmpl, info->call); const m_bool ret = scan0_class_def(env, cdef); if((info->ret = cdef->base.type)) { diff --git a/src/lib/ptr.c b/src/lib/ptr.c index c4e72def..bc8a94e6 100644 --- a/src/lib/ptr.c +++ b/src/lib/ptr.c @@ -26,6 +26,7 @@ static OP_CHECK(opck_ptr_assign) { CHECK_BO(ptr_access(env, bin->lhs)) CHECK_BO(ptr_access(env, bin->rhs)) exp_setvar(bin->lhs, 1); + exp_setvar(bin->rhs, 1); Type t = bin->lhs->info->type; do { // t = unflag_type(t); @@ -41,10 +42,27 @@ static OP_CHECK(opck_ptr_assign) { } static INSTR(instr_ptr_assign) { - POP_REG(shred, SZ_INT) - const M_Object o = *(M_Object*)REG(0); - *(m_uint**)o->data = *(m_uint**)REG(-SZ_INT); - _release(o, shred); + m_bit **o = *(m_bit***)REG(0); + *o = *(m_bit**)REG(-SZ_INT); +} + +static INSTR(instr_ptr_assign_obj) { + m_bit **o = *(m_bit***)REG(0); + release(*(M_Object*)o, shred); + *o = *(m_bit**)REG(-SZ_INT); +} + +static OP_EMIT(opem_ptr_assign) { + const Instr pop = emit_add_instr(emit, RegPop); + pop->m_val = SZ_INT; + const Exp_Binary* bin = (Exp_Binary*)data; + if(isa(bin->lhs->info->type, emit->gwion->type[et_object]) > 0) { + const Instr instr = emit_add_instr(emit, RegAddRefAddr); + instr->m_val = -SZ_INT; + emit_add_instr(emit, instr_ptr_assign_obj); + } else + emit_add_instr(emit, instr_ptr_assign); + return pop; } static OP_CHECK(opck_ptr_deref) { @@ -86,21 +104,20 @@ static OP_CHECK(opck_ptr_implicit) { } static INSTR(instr_ptr_deref) { - const M_Object o = *(M_Object*)REG(-SZ_INT); - if(!*(m_bit**)o->data) + const m_bit *o = *(m_bit**)REG(-SZ_INT); + if(!o) Except(shred, _("EmptyPointerException")); if(instr->m_val2) - memcpy(REG(-SZ_INT), o->data, SZ_INT); + memcpy(REG(-SZ_INT), &o, SZ_INT); else { shred->reg -= SZ_INT - instr->m_val; - memcpy(REG(-instr->m_val), *(m_bit**)o->data, instr->m_val); + memcpy(REG(-instr->m_val), o, instr->m_val); } } static INSTR(Cast2Ptr) { - const M_Object o = new_object(shred->info->mp, shred, (Type)instr->m_val); - *(m_uint**)o->data = *(m_uint**)REG(-SZ_INT); - *(M_Object*)REG(-SZ_INT) = o; + m_bit *o = *(m_bit**)REG(-SZ_INT); + *(m_bit**)REG(-SZ_INT) = o; } static OP_EMIT(opem_ptr_cast) { @@ -128,23 +145,24 @@ static OP_EMIT(opem_ptr_deref) { ANN Type scan_class(const Env env, const Type t, const Type_Decl* td); static DTOR(ptr_object_dtor) { - release(*(M_Object*)o->data, shred); + release(**(M_Object**)o, shred); } static DTOR(ptr_struct_dtor) { - const Type t = (Type)vector_front(&o->type_ref->info->tuple->types); - struct_release(shred, t, *(m_bit**)o->data); + const Type base = *(Type*)(shred->mem + SZ_INT); + const m_uint scope = env_push(shred->info->vm->gwion->env, base->info->owner_class, base->info->owner); + const Type t = known_type(shred->info->vm->gwion->env, base->info->cdef->base.tmpl->call->td); + env_pop(shred->info->vm->gwion->env, scope); + struct_release(shred, t, *(m_bit**)o); } static OP_CHECK(opck_ptr_scan) { struct TemplateScan *ts = (struct TemplateScan*)data; DECL_ON(const Type, t, = (Type)scan_class(env, ts->t, ts->td)) -set_tflag(t, tflag_tmpl); -//if(!tflag(t, tflag_scan1))exit(3); const Type base = known_type(env, t->info->cdef->base.tmpl->call->td); - if(isa(base, env->gwion->type[et_compound]) > 0 && !t->nspc->dtor) { + if(isa(base, env->gwion->type[et_compound]) > 0) { t->nspc->dtor = new_vm_code(env->gwion->mp, NULL, SZ_INT, 1, "@PtrDtor"); - if(!tflag(t, tflag_struct)) + if(!tflag(base, tflag_struct)) t->nspc->dtor->native_func = (m_uint)ptr_object_dtor; else t->nspc->dtor->native_func = (m_uint)ptr_struct_dtor; @@ -154,23 +172,19 @@ set_tflag(t, tflag_tmpl); } GWION_IMPORT(ptr) { - const Type _t_ptr = gwi_class_ini(gwi, "@Ptr", NULL); - GWI_BB(gwi_class_end(gwi)) - set_tflag(_t_ptr, tflag_ntmpl); -// set_tflag(_t_ptr, tflag_tmpl); - GWI_BB(gwi_oper_ini(gwi, "@Ptr", NULL, NULL)) - GWI_BB(gwi_oper_add(gwi, opck_ptr_scan)) - GWI_BB(gwi_oper_end(gwi, "@scan", NULL)) - const Type t_ptr = gwi_class_ini(gwi, "Ptr:[A]", "@Ptr"); + const Type t_ptr = gwi_struct_ini(gwi, "Ptr:[A]"); gwi->gwion->type[et_ptr] = t_ptr; GWI_BB(gwi_item_ini(gwi, "@internal", "@val")) GWI_BB(gwi_item_end(gwi, 0, NULL)) GWI_BB(gwi_class_end(gwi)) set_tflag(t_ptr, tflag_ntmpl); -// set_tflag(t_ptr, tflag_tmpl); + GWI_BB(gwi_oper_ini(gwi, "Ptr", NULL, NULL)) + GWI_BB(gwi_oper_add(gwi, opck_ptr_scan)) + GWI_BB(gwi_oper_end(gwi, "@scan", NULL)) GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "nonnull Ptr", NULL)) GWI_BB(gwi_oper_add(gwi, opck_ptr_assign)) - GWI_BB(gwi_oper_end(gwi, ":=>", instr_ptr_assign)) + GWI_BB(gwi_oper_emi(gwi, opem_ptr_assign)) + GWI_BB(gwi_oper_end(gwi, ":=>", NULL)) GWI_BB(gwi_oper_add(gwi, opck_ptr_implicit)) GWI_BB(gwi_oper_emi(gwi, opem_ptr_implicit)) GWI_BB(gwi_oper_end(gwi, "@implicit", Cast2Ptr)) diff --git a/src/vm/vm.c b/src/vm/vm.c index 86a30293..ae258a3e 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -619,7 +619,7 @@ PRAGMA_PUSH() if(!a.code->builtin) { register const m_uint push = *(m_uint*)(reg + SZ_INT) + *(m_uint*)(mem-SZ_INT); mem += push; - *(m_uint*) mem = push;mem += SZ_INT; + *(m_uint*) mem = push; mem += SZ_INT; *(VM_Code*) mem = code; mem += SZ_INT; *(m_uint*) mem = PC + VAL2; mem += SZ_INT; *(m_uint*) mem = a.code->stack_depth; mem += SZ_INT; @@ -718,7 +718,7 @@ autoloop: m_vector_get(ARRAY(*(M_Object*)(reg-SZ_INT)), *(m_uint*)(mem + VAL), mem + VAL + SZ_INT); goto autoloopcount; autoloopptr: - *(m_bit**)(*(M_Object*)(mem + VAL + SZ_INT))->data = m_vector_addr(ARRAY(*(M_Object*)(reg-SZ_INT)), *(m_uint*)(mem + VAL)); + *(m_bit**)(mem + VAL + SZ_INT) = m_vector_addr(ARRAY(*(M_Object*)(reg-SZ_INT)), *(m_uint*)(mem + VAL)); autoloopcount: *(m_uint*)reg = m_vector_size(ARRAY(*(M_Object*)(reg-SZ_INT))) - (*(m_uint*)(mem + VAL))++; reg += SZ_INT; -- 2.43.0