clean_core:
@rm -f core.* *vgcore.*
-clean-all:
+clean-all: clean
${MAKE} -s -C libcmdapp clean
${MAKE} -s -C fmt clean
${MAKE} -s -C ast clean
eCastI2F,
eCastF2I,
eTime_Advance,
+ eRecurs,
eSetCode,
eRegMove,
eReg2Mem,
eReg2Mem4,
eOverflow,
eFuncUsrEnd,
+ eFuncUsrEnd2,
eFuncMemberEnd,
eSporkIni,
eForkIni,
#define CastI2F (f_instr)eCastI2F
#define CastF2I (f_instr)eCastF2I
#define Time_Advance (f_instr)eTime_Advance
+#define Recurs (f_instr)eRecurs
#define SetCode (f_instr)eSetCode
#define RegMove (f_instr)eRegMove
#define Reg2Mem (f_instr)eReg2Mem
#define Reg2Mem4 (f_instr)eReg2Mem4
#define Overflow (f_instr)eOverflow
#define FuncUsrEnd (f_instr)eFuncUsrEnd
+#define FuncUsrEnd2 (f_instr)eFuncUsrEnd2
#define FuncMemberEnd (f_instr)eFuncMemberEnd
#define SporkIni (f_instr)eSporkIni
#define ForkIni (f_instr)eForkIni
bool is_memoize;
};
+struct frame_t {
+ uint32_t push, pc;
+ VM_Code code;
+};
+
typedef struct Shreduler_* Shreduler;
typedef struct Emitter_ * Emitter;
typedef struct VM_Shred_* VM_Shred;
CastI2F
CastF2I
Time_Advance
+Recurs
SetCode
RegMove
Reg2Mem
Reg2Mem4
Overflow
FuncUsrEnd
+FuncUsrEnd2
FuncMemberEnd
SporkIni
ForkIni
return emit_inline(emit, f, exp_call);
#endif
*/
- CHECK_BB(prepare_call(emit, exp_call));
+ // skip when recursing
const Type t = actual_type(emit->gwion, exp_call->func->type);
+ const Func f = t->info->func;
+ if(is_fptr(emit->gwion, t) || f != emit->env->func || f->value_ref->from->owner_class || strstr(emit->code->name, "ork~"))
+ CHECK_BB(prepare_call(emit, exp_call));
+ else
+ CHECK_BB(emit_func_args(emit, exp_call));
if(isa(t, emit->gwion->type[et_function]) > 0)
CHECK_BB(emit_exp_call1(emit, t->info->func));
else {
ANN static Instr get_prelude(const Emitter emit, const Func f) {
const Type t = actual_type(emit->gwion, f->value_ref->type);
+ const bool fp = is_fptr(emit->gwion, t);
if(is_fptr(emit->gwion, t)) {
if(f->def->base->tmpl)
tmpl_prelude(emit, f);
}
- const Instr instr = emit_add_instr(emit, SetCode);
+ if(fp || f != emit->env->func || f->value_ref->from->owner_class || strstr(emit->code->name, "ork~")) {
+ const Instr instr = emit_add_instr(emit, SetCode);
+ instr->m_val2 = 1;
+ return instr;
+ }
+ const Instr instr = emit_add_instr(emit, Recurs);
instr->m_val2 = 1;
+ instr->m_val = SZ_INT;
return instr;
}
ANN static Instr emit_call(const Emitter emit, const Func f) {
const Instr prelude = get_prelude(emit, f);
- prelude->m_val = -f->def->stack_depth - SZ_INT;
+ prelude->m_val += -f->def->stack_depth - SZ_INT;
const m_uint member = vflag(f->value_ref, vflag_member) ? SZ_INT : 0;
if(member) {
const Instr instr = emit_add_instr(emit, Reg2Mem);
++prelude->m_val2;
}
if(f->def->stack_depth - member) {
+// if(is_fptr(emit->gwion, t) || f != emit->env->func || f->value_ref->from->owner_class || strstr(emit->code->name, "ork~"))
+{
emit_args(emit, f);
++prelude->m_val2;
+}
}
return emit_add_instr(emit, Overflow);
}
if(emit->env->func != f)
CHECK_BB(emit_template_code(emit, f));
else { // recursive function. (maybe should be used only for global funcs)
- const Instr back = (Instr) vector_size(&emit->code->instr) ?
+ /* const Instr back = (Instr) vector_size(&emit->code->instr) ?
(Instr)vector_back(&emit->code->instr) : emit_add_instr(emit, RegPushImm);
back->opcode = eOP_MAX;
back->execute = SetRecurs;
- back->m_val = 0;
+ back->m_val = 0;*/
}
} else if(emit->env->func != f && !f->value_ref->from->owner_class && !f->code && !is_fptr(emit->gwion, f->value_ref->type)) {
if(fbflag(f->def->base, fbflag_op)) {
if(!name || !name->next || name->next->next)
ERR_N(name->pos, "Union constructor takes two arguments, "
"'id' and 'value'");
- if(name->exp_type != ae_exp_primary ||
- name->d.prim.prim_type != ae_prim_id)
- return NULL;
- const Exp val = name->next;
- const Type base = actual_type(env->gwion, call->func->type);
- const Map map = &base->nspc->info->value->map;
- for(m_uint i = 0; i < map_size(map); ++i) {
+ if(name->exp_type != ae_exp_primary ||
+ name->d.prim.prim_type != ae_prim_id)
+ return NULL;
+ const Exp val = name->next;
+ const Type base = actual_type(env->gwion, call->func->type);
+ const Map map = &base->nspc->info->value->map;
+ for(m_uint i = 0; i < map_size(map); ++i) {
if(VKEY(map, i) == (m_uint)name->d.prim.d.var) {
const Value v = (Value)VVAL(map, i);
name->d.prim.prim_type = ae_prim_num;
}
ANN static void prepare_call(const VM_Shred shred, const m_uint offset) {
- shred->mem += offset;
- *(m_uint*)(shred->mem + SZ_INT) = offset + SZ_INT;
- *(VM_Code*)(shred->mem + SZ_INT*2) = shred->code;
- *(m_uint*)(shred->mem + SZ_INT*3) = shred->pc;
- *(m_uint*)(shred->mem + SZ_INT*4) = SZ_INT;
- shred->mem += SZ_INT*5;
+ shred->mem += offset + SZ_INT + sizeof(struct frame_t);
+ register struct frame_t *frame = (struct frame_t*)(shred->mem - sizeof(struct frame_t));
+ frame->push = offset + SZ_INT;
+ frame->code = shred->code;
+ frame->pc = shred->pc;
shred->pc = 0;
}
return ret;
}
-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 inline void shred_unwind(const VM_Shred shred) {
+ register struct frame_t *frame = &*(struct frame_t*)(shred->mem - sizeof(struct frame_t));
+ shred->code = frame->code;
+ shred->pc = frame->pc;
+ shred->mem -= (frame->push + sizeof(struct frame_t));
}
ANN static bool unwind(VM_Shred shred, const Symbol effect, const m_uint size) {
&&firassign, &&firadd, &&firsub, &&firmul, &&firdiv,
&&itof, &&ftoi,
&&timeadv,
- &&setcode,
- &®move, &®tomem, &®tomemother, &&overflow, &&funcusrend, &&funcmemberend,
+ &&recurs, &&setcode, &®move, &®tomem, &®tomemother, &&overflow, &&funcusrend, &&funcusrend2, &&funcmemberend,
&&sporkini, &&forkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&sporkend,
&&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat, &&unroll,
&&arrayappend, &&autounrollinit, &&autoloop, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr,
DISPATCH();
funcreturn:
{
- register const m_uint pc = *(m_uint*)(mem-SZ_INT*2);
- bytecode = (code = *(VM_Code*)(mem-SZ_INT*3))->bytecode;
- mem -= (*(m_uint*)(mem-SZ_INT*4) + SZ_INT*4);
- PC_DISPATCH(pc);
+ register struct frame_t frame = *(struct frame_t*)(mem - sizeof(struct frame_t));
+ bytecode = (code = frame.code)->bytecode;
+ mem -= (frame.push + sizeof(struct frame_t));
+ PC_DISPATCH(frame.pc);
}
_goto:
PC_DISPATCH(VAL);
*(m_float*)(reg-SZ_FLOAT) += vm->bbq->pos;
VM_OUT
break;
+recurs:
+{
+ register const uint push = *(m_uint*)reg + code->stack_depth;
+ mem += push + sizeof(struct frame_t);
+ *(struct frame_t*)(mem - sizeof(struct frame_t)) = (struct frame_t){.code=code,.pc=VAL2,.push=push};
+ reg += (m_int)VAL;
+ next = eFuncUsrEnd2;
+}
+ DISPATCH();
setcode:
PRAGMA_PUSH()
a.code = *(VM_Code*)(reg - SZ_INT);
if(!a.code->builtin) {
- register const m_uint push = *(m_uint*)reg + *(m_uint*)(mem-SZ_INT);
- mem += push;
- *(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;
+ register const uint push = *(m_uint*)reg + code->stack_depth;
+ mem += push + sizeof(struct frame_t);
+ *(struct frame_t*)(mem - sizeof(struct frame_t)) = (struct frame_t){.code=code,.pc=PC+VAL2,.push=push};
next = eFuncUsrEnd;
} else {
mem += *(m_uint*)reg;
byte = bytecode = (code = a.code)->bytecode;
PRAGMA_POP()
SDISPATCH();
+funcusrend2:
+ byte = bytecode;
+ SDISPATCH();
funcmemberend:
VM_OUT
{
map_set(&code->handlers, j, new_pc);
}
*(m_uint*)(data + SZ_INT) = new_pc;
+ } else if(opcode == eRecurs /*|| opcode == eSetCode*/) {
+ *(m_uint*)(final + j * BYTECODE_SZ + SZ_INT*2) =
+ instr->m_val2 += j+1;
}
setpc(data, j);
++j;