-
Notifications
You must be signed in to change notification settings - Fork 43
/
instr.c
167 lines (159 loc) · 5.55 KB
/
instr.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include <stdlib.h>
#include <string.h>
#include "gwion_util.h"
#include "gwion_ast.h"
#include "gwion_env.h"
#include "vm.h"
#include "instr.h"
#include "gwion.h"
#include "object.h"
#include "operator.h"
#include "import.h"
#include "emit.h"
#include "traverse.h"
#include "parse.h"
ANN static Func_Def traverse_tmpl(const Emitter emit, Func_Def fdef, Func_Def fbase,
const Nspc nspc) {
const Env env = emit->env;
const Symbol sym = func_symbol(env, nspc->name, s_name(fdef->base->tag.sym),
"template", fbase->vt_index);
DECL_O(const Value, v, = nspc_lookup_value0(nspc, sym)
?: nspc_lookup_value0(nspc, fdef->base->tag.sym));
const f_xfun xfun = v->d.func_ref->def->d.dl_func_ptr;
if (vflag(v, vflag_builtin))
v->d.func_ref->def->d.dl_func_ptr = NULL; // why
const Func_Def def = cpy_func_def(env->gwion->mp, v->d.func_ref->def);
if (vflag(v, vflag_builtin)) v->d.func_ref->def->d.dl_func_ptr = xfun;
def->base->tmpl->call = cpy_tmplarg_list(env->gwion->mp, fbase->base->tmpl->call);
CHECK_O(traverse_dot_tmpl(emit, def, v));
if (vflag(v, vflag_builtin)) builtin_func(emit->gwion, def->base->func, xfun);
return def;
}
ANN static void foo(const VM_Shred shred, Type t, const Func_Def fbase, const m_str tmpl_name) {
const Emitter emit = shred->info->vm->gwion->emit;
emit->env->name = "runtime";
do {
const Func base = fbase->base->func;
const Symbol sym = func_symbol(emit->env, t->name, base->name, tmpl_name, base->def->vt_index);
const Func f = nspc_lookup_func0(t->nspc, sym);
if (f) {
if(!f->code) continue;
if (vflag(f->value_ref, vflag_member)) shred->reg += SZ_INT;
*(VM_Code *)(shred->reg - SZ_INT) = f->code;
return;
} else {
const Func_Def def = traverse_tmpl(emit, fbase, fbase, t->nspc);
if (!def) continue;
const Func f = def->base->func;
if (vflag(f->value_ref, vflag_member)) shred->reg += SZ_INT;
*(VM_Code *)(shred->reg - SZ_INT) = f->code;
return;
}
} while ((t = t->info->parent));
handle(shred, "MissigTmplPtrException");
}
INSTR(GTmpl) {
const Func_Def fbase = (Func_Def)instr->m_val;
const m_str tmpl = (m_str)instr->m_val2;
const Func f = *(Func *)REG(-SZ_INT);
const Func _f = *(Func *)REG(-SZ_INT);
if (!f) {
handle(shred, "EmptyFuncPointerException");
return;
}
if (f->code) {
*(VM_Code *)(shred->reg - SZ_INT) = f->code;
return;
}
const Emitter emit = shred->info->vm->gwion->emit;
emit->env->name = "runtime";
Type t = f->value_ref->from->owner_class;
if(!t) {
const Nspc nspc = f->value_ref->from->owner;
for (m_uint i = 0; i <= f->value_ref->from->offset; ++i) {
const Symbol sym = func_symbol(emit->env, nspc->name, f->name, tmpl, i);
const Func base = nspc_lookup_func0(nspc, sym);
if (base) {
assert(base->code);
*(VM_Code *)(shred->reg - SZ_INT) = base->code;
return;
}
}
const Func_Def def = traverse_tmpl(emit, f->def, fbase, nspc);
if (def) {
*(VM_Code *)(shred->reg - SZ_INT) = def->base->func->code;
return;
}
} else {
do {
const Symbol sym = func_symbol(emit->env, t->name, f->name, tmpl, f->def->vt_index);
const Func f = nspc_lookup_func0(t->nspc, sym);
if (f) {
if (!f->code) continue;
*(VM_Code *)(shred->reg - SZ_INT) = f->code;
return;
} else {
const Func_Def def = traverse_tmpl(emit, _f->def, fbase, t->nspc);
if (!def) continue;
const Func f = def->base->func;
*(VM_Code *)(shred->reg - SZ_INT) = f->code;
return;
}
} while ((t = t->info->parent));
}
}
INSTR(DotTmpl) {
const Func_Def fbase = (Func_Def)instr->m_val;
const M_Object o = *(M_Object *)REG(-SZ_INT);
const Func f = fbase->base->func;
if(o->type_ref == f->value_ref->from->owner_class) {
if (vflag(f->value_ref, vflag_member)) shred->reg += SZ_INT;
*(VM_Code *)(shred->reg - SZ_INT) = f->code;
return;
}
const struct dottmpl_ *dt = (struct dottmpl_*)instr->m_val2;
foo(shred, o->type_ref, fbase, dt->tmpl_name);
}
#define VAL (*(m_uint *)(byte + SZ_INT))
#define FVAL (*(m_float *)(byte + SZ_INT))
#define VAL2 (*(m_uint *)(byte + SZ_INT * 2))
#define BYTE(a) \
m_bit *byte = shred->code->bytecode + (shred->pc - 1) * BYTECODE_SZ; \
*(m_uint *)byte = instr->opcode; \
instr->opcode = a;
INSTR(SetFunc) {
BYTE(eRegPushImm);
const Func f = (Func)instr->m_val;
VAL = *(m_uint *)(shred->reg) = (m_uint)f->code;
shred->reg += SZ_INT;
}
INSTR(FuncWait) {
const Func f = (Func)instr->m_val;
if(f->_wait->len - instr->m_val2) {
if(!handle(shred, "UninitValue")) {
gw_err("{-}some values are not instantiated yet{0}\n");
for(uint32_t i = instr->m_val2; i < f->_wait->len; i++) {
Value v = *mp_vector_at(f->_wait, Value, i);
defined_here(v);
}
}
} else {
BYTE(eNoOp);
}
}
INSTR(fast_except) {
struct FastExceptInfo *info = (struct FastExceptInfo *)instr->m_val2;
if(*(m_uint*)REG(-SZ_INT)) {
BYTE(eNoOp);
VAL = -SZ_INT;
if(info) mp_free2(shred->info->mp, sizeof(struct FastExceptInfo), info);
instr->m_val2 = 0;
return;
} else if(info) {
if(info->file)
gwlog_error("Object not instantiated", NULL, info->file, info->loc, 0);
if(info->file2)
gwlog_related("declared here", info->file2, info->loc2);
}
handle(shred, "NullPtrException");
}