GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
#include "gwion_util.h" |
||
2 |
#include "gwion_ast.h" |
||
3 |
#include "gwion_env.h" |
||
4 |
#include "vm.h" |
||
5 |
#include "gwion.h" |
||
6 |
#include "instr.h" |
||
7 |
#include "emit.h" |
||
8 |
#include "object.h" |
||
9 |
#include "array.h" |
||
10 |
#include "traverse.h" |
||
11 |
#include "template.h" |
||
12 |
#include "escape.h" |
||
13 |
#include "parse.h" |
||
14 |
#include "memoize.h" |
||
15 |
#include "operator.h" |
||
16 |
#include "import.h" |
||
17 |
#include "match.h" |
||
18 |
#include "parser.h" |
||
19 |
#include "specialid.h" |
||
20 |
#include "vararg.h" |
||
21 |
|||
22 |
#undef insert_symbol |
||
23 |
#define insert_symbol(a) insert_symbol(emit->gwion->st, (a)) |
||
24 |
|||
25 |
#undef ERR_B |
||
26 |
#define ERR_B(a, b, ...) { env_err(emit->env, (a), (b), ## __VA_ARGS__); return GW_ERROR; } |
||
27 |
#undef ERR_O |
||
28 |
#define ERR_O(a, b, ...) { env_err(emit->env, (a), (b), ## __VA_ARGS__); return NULL; } |
||
29 |
|||
30 |
typedef struct Local_ { |
||
31 |
Type type; |
||
32 |
m_uint offset; |
||
33 |
} Local; |
||
34 |
|||
35 |
76 |
static inline void emit_pop(const Emitter emit, const m_uint scope) { env_pop(emit->env, scope); } |
|
36 |
59 |
static inline m_uint emit_push(const Emitter emit, const Type type, const Nspc nspc) { |
|
37 |
59 |
return env_push(emit->env, type, nspc); |
|
38 |
} |
||
39 |
10 |
static inline m_uint emit_push_type(const Emitter emit, const Type type) { |
|
40 |
10 |
return env_push_type(emit->env, type); |
|
41 |
} |
||
42 |
6 |
static inline m_uint emit_push_global(const Emitter emit) { |
|
43 |
6 |
return env_push_global(emit->env); |
|
44 |
} |
||
45 |
|||
46 |
856 |
ANEW static Frame* new_frame(MemPool p) { |
|
47 |
856 |
Frame* frame = mp_calloc(p, Frame); |
|
48 |
856 |
vector_init(&frame->stack); |
|
49 |
856 |
vector_add(&frame->stack, (vtype)NULL); |
|
50 |
856 |
return frame; |
|
51 |
} |
||
52 |
|||
53 |
856 |
ANN static void free_frame(MemPool p, Frame* a) { |
|
54 |
LOOP_OPTIM |
||
55 |
✓✓ | 2819 |
for(vtype i = vector_size(&a->stack) + 1; --i;) |
56 |
✓✓ | 1107 |
if(vector_at(&a->stack, i - 1)) |
57 |
251 |
mp_free(p, Local, (Local*)vector_at(&a->stack, i - 1)); |
|
58 |
856 |
vector_release(&a->stack); |
|
59 |
856 |
mp_free(p, Frame, a); |
|
60 |
856 |
} |
|
61 |
|||
62 |
1091 |
ANN static Local* new_local(MemPool p, const Type type) { |
|
63 |
1091 |
Local* local = mp_calloc(p, Local); |
|
64 |
1091 |
local->type = type; |
|
65 |
1091 |
return local; |
|
66 |
} |
||
67 |
|||
68 |
1091 |
ANN static m_uint frame_local(MemPool p, Frame* frame, const Type t) { |
|
69 |
1091 |
Local* local = new_local(p, t); |
|
70 |
1091 |
local->offset = frame->curr_offset; |
|
71 |
1091 |
frame->curr_offset += t->size; |
|
72 |
1091 |
vector_add(&frame->stack, (vtype)local); |
|
73 |
1091 |
return local->offset; |
|
74 |
} |
||
75 |
|||
76 |
1134 |
ANN static inline void frame_push(Frame* frame) { |
|
77 |
1134 |
vector_add(&frame->stack, (vtype)NULL); |
|
78 |
1134 |
} |
|
79 |
|||
80 |
9 |
ANN static void struct_pop(const Emitter emit, const Type type, const m_uint offset) { |
|
81 |
✗✓ | 9 |
if(!type->e->tuple) |
82 |
return; |
||
83 |
✓✓ | 25 |
for(m_uint i = 0; i < vector_size(&type->e->tuple->types); ++i) { |
84 |
16 |
const Type t = (Type)vector_at(&type->e->tuple->types, i); |
|
85 |
✓✓ | 16 |
if(isa(t, emit->gwion->type[et_object]) > 0) { |
86 |
1 |
const Instr instr = emit_add_instr(emit, ObjectRelease); |
|
87 |
1 |
instr->m_val = offset + vector_at(&type->e->tuple->offset, i); |
|
88 |
✗✓ | 15 |
} else if(GET_FLAG(t, struct)) |
89 |
struct_pop(emit, t, offset + vector_at(&type->e->tuple->offset, i)); |
||
90 |
} |
||
91 |
} |
||
92 |
|||
93 |
1974 |
ANN static m_int frame_pop(const Emitter emit) { |
|
94 |
1974 |
Frame *frame = emit->code->frame; |
|
95 |
✓✓ | 1974 |
DECL_OB(const Local*, l, = (Local*)vector_pop(&frame->stack)) |
96 |
840 |
frame->curr_offset -= l->type->size; |
|
97 |
✓✓ | 840 |
if(GET_FLAG(l->type, struct)) { |
98 |
9 |
struct_pop(emit, l->type, l->offset); |
|
99 |
9 |
return frame_pop(emit); |
|
100 |
} |
||
101 |
✓✓ | 831 |
return isa(l->type, emit->gwion->type[et_object]) > 0 ? (m_int)l->offset : frame_pop(emit); |
102 |
} |
||
103 |
|||
104 |
ANN /*static */m_bool emit_exp(const Emitter emit, Exp exp); |
||
105 |
ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt, const m_bool pop); |
||
106 |
ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List list); |
||
107 |
ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member); |
||
108 |
ANN static m_bool emit_func_def(const Emitter emit, const Func_Def func_def); |
||
109 |
|||
110 |
856 |
ANEW static Code* new_code(const Emitter emit, const m_str name) { |
|
111 |
856 |
Code* code = mp_calloc(emit->gwion->mp, Code); |
|
112 |
856 |
code->name = code_name_set(emit->gwion->mp, name, emit->env->name); |
|
113 |
856 |
vector_init(&code->instr); |
|
114 |
856 |
vector_init(&code->stack_break); |
|
115 |
856 |
vector_init(&code->stack_cont); |
|
116 |
856 |
vector_init(&code->stack_return); |
|
117 |
856 |
code->frame = new_frame(emit->gwion->mp); |
|
118 |
856 |
return code; |
|
119 |
} |
||
120 |
|||
121 |
856 |
ANN static void free_code(MemPool p, Code* code) { |
|
122 |
856 |
vector_release(&code->instr); |
|
123 |
856 |
vector_release(&code->stack_break); |
|
124 |
856 |
vector_release(&code->stack_cont); |
|
125 |
856 |
vector_release(&code->stack_return); |
|
126 |
856 |
free_frame(p, code->frame); |
|
127 |
856 |
free_mstr(p, code->name); |
|
128 |
856 |
mp_free(p, Code, code); |
|
129 |
856 |
} |
|
130 |
|||
131 |
1134 |
ANN static void emit_pop_scope(const Emitter emit) { |
|
132 |
m_int offset; |
||
133 |
✓✓ | 2543 |
while((offset = frame_pop(emit)) > -1) { |
134 |
275 |
Instr instr = emit_add_instr(emit, ObjectRelease); |
|
135 |
275 |
instr->m_val = (m_uint)offset; |
|
136 |
} |
||
137 |
1134 |
vector_pop(&emit->info->pure); |
|
138 |
1134 |
} |
|
139 |
|||
140 |
444 |
ANN static inline void emit_push_code(const Emitter emit, const m_str name) { |
|
141 |
444 |
vector_add(&emit->stack, (vtype)emit->code); |
|
142 |
444 |
emit->code = new_code(emit, name); |
|
143 |
444 |
} |
|
144 |
|||
145 |
ANN static inline void emit_pop_code(const Emitter emit) { |
||
146 |
emit->code = (Code*)vector_pop(&emit->stack); |
||
147 |
} |
||
148 |
|||
149 |
1134 |
ANN static inline void emit_push_scope(const Emitter emit) { |
|
150 |
1134 |
frame_push(emit->code->frame); |
|
151 |
1134 |
vector_add(&emit->info->pure, 0); |
|
152 |
1134 |
} |
|
153 |
|||
154 |
565 |
ANN static inline m_uint emit_code_size(const Emitter emit) { |
|
155 |
565 |
return vector_size(&emit->code->instr); |
|
156 |
} |
||
157 |
|||
158 |
1760 |
ANN m_uint emit_code_offset(const Emitter emit) { |
|
159 |
1760 |
return emit->code->frame->curr_offset; |
|
160 |
} |
||
161 |
|||
162 |
1091 |
ANN m_uint emit_local(const Emitter emit, const Type t) { |
|
163 |
1091 |
return frame_local(emit->gwion->mp, emit->code->frame, t); |
|
164 |
} |
||
165 |
|||
166 |
ANN void emit_ext_ctor(const Emitter emit, const Type t); |
||
167 |
|||
168 |
656 |
ANN static inline void maybe_ctor(const Emitter emit, const Type t) { |
|
169 |
✓✓✓✓ |
656 |
if(!is_special(t) && GET_FLAG(t, ctor)) |
170 |
161 |
emit_ext_ctor(emit, t); |
|
171 |
656 |
} |
|
172 |
|||
173 |
656 |
ANN static void emit_pre_ctor(const Emitter emit, const Type type) { |
|
174 |
✓✓ | 656 |
if(type->e->parent) |
175 |
447 |
emit_pre_ctor(emit, type->e->parent); |
|
176 |
656 |
maybe_ctor(emit, type); |
|
177 |
✓✓✓✓ |
656 |
if(GET_FLAG(type, typedef) && type->e->parent->array_depth) |
178 |
7 |
emit_array_extend(emit, type->e->parent, type->e->def->base.ext->array->exp); |
|
179 |
656 |
} |
|
180 |
|||
181 |
#define regxxx(name, instr) \ |
||
182 |
ANN static inline Instr reg##name(const Emitter emit, const m_uint sz) { \ |
||
183 |
const Instr instr = emit_add_instr(emit, Reg##instr); \ |
||
184 |
instr->m_val = sz; \ |
||
185 |
return instr; \ |
||
186 |
} |
||
187 |
1913 |
regxxx(pop, Pop) |
|
188 |
58 |
regxxx(push, Push) |
|
189 |
1826 |
regxxx(pushi, PushImm) |
|
190 |
3058 |
regxxx(seti, SetImm) |
|
191 |
|||
192 |
12 |
ANN static void struct_expand(const Emitter emit, const Type t) { |
|
193 |
12 |
const Instr instr = emit_add_instr(emit, Reg2RegDeref); |
|
194 |
12 |
instr->m_val = -SZ_INT; |
|
195 |
12 |
instr->m_val2 = t->size; |
|
196 |
// regpush(emit, t->size - SZ_INT); |
||
197 |
12 |
} |
|
198 |
|||
199 |
|||
200 |
INSTR(ArrayStruct); |
||
201 |
|||
202 |
12 |
ANN static void emit_pre_constructor_array(const Emitter emit, const Type type) { |
|
203 |
12 |
const m_uint start_index = emit_code_size(emit); |
|
204 |
12 |
const Instr top = emit_add_instr(emit, ArrayTop); |
|
205 |
12 |
top->m_val2 = (m_uint)type; |
|
206 |
✗✓ | 12 |
if(GET_FLAG(type, struct)) { |
207 |
const Instr instr = emit_add_instr(emit, ArrayStruct); |
||
208 |
instr->m_val = type->size; |
||
209 |
} |
||
210 |
12 |
emit_pre_ctor(emit, type); |
|
211 |
✓✗ | 12 |
if(!GET_FLAG(type, struct)) |
212 |
12 |
emit_add_instr(emit, ArrayBottom); |
|
213 |
else |
||
214 |
regpop(emit, SZ_INT); |
||
215 |
12 |
regpop(emit, SZ_INT); |
|
216 |
12 |
const Instr pc = emit_add_instr(emit, Goto); |
|
217 |
12 |
pc->m_val = start_index; |
|
218 |
12 |
top->m_val = emit_code_size(emit); |
|
219 |
12 |
regpop(emit, SZ_INT*3); |
|
220 |
12 |
emit_add_instr(emit, ArrayPost); |
|
221 |
12 |
} |
|
222 |
|||
223 |
38 |
ANN2(1) static m_bool extend_indices(const Emitter emit, Exp e, const m_uint depth) { |
|
224 |
✓✓ | 38 |
if(e) |
225 |
✗✓ | 36 |
CHECK_BB(emit_exp(emit, e)) |
226 |
38 |
m_uint count = 0; |
|
227 |
✓✓ | 133 |
while(e) { |
228 |
57 |
++count; |
|
229 |
57 |
e = e->next; |
|
230 |
} |
||
231 |
✓✓ | 40 |
for(m_uint i = count; i < depth; ++i) |
232 |
2 |
regpushi(emit, 0); |
|
233 |
38 |
return GW_OK; |
|
234 |
} |
||
235 |
|||
236 |
38 |
ANEW ANN static ArrayInfo* new_arrayinfo(const Emitter emit, const Type t) { |
|
237 |
38 |
const Type base = array_base(t); |
|
238 |
38 |
ArrayInfo* info = mp_calloc(emit->gwion->mp, ArrayInfo); |
|
239 |
38 |
vector_init(&info->type); |
|
240 |
✓✓ | 59 |
for(m_uint i = 1; i < t->array_depth; ++i) |
241 |
21 |
vector_add(&info->type, (vtype)array_type(emit->env, base, i)); |
|
242 |
38 |
vector_add(&info->type, (vtype)t); |
|
243 |
38 |
info->depth = (m_int)t->array_depth; |
|
244 |
38 |
info->base = base; |
|
245 |
38 |
return info; |
|
246 |
} |
||
247 |
|||
248 |
38 |
ANN static inline void arrayinfo_ctor(const Emitter emit, ArrayInfo *info) { |
|
249 |
38 |
const Type base = info->base; |
|
250 |
✓✓✓✗ |
38 |
if(isa(base, emit->gwion->type[et_compound]) > 0 && !GET_FLAG(base, abstract)) { |
251 |
12 |
emit_pre_constructor_array(emit, base); |
|
252 |
// if(isa(base, emit->gwion->type[et_object]) > 0) |
||
253 |
12 |
info->is_obj = 1; |
|
254 |
} |
||
255 |
38 |
} |
|
256 |
|||
257 |
38 |
ANN2(1,2) static ArrayInfo* emit_array_extend_inner(const Emitter emit, const Type t, const Exp e) { |
|
258 |
✗✓ | 38 |
CHECK_BO(extend_indices(emit, e, t->array_depth)) |
259 |
38 |
ArrayInfo* info = new_arrayinfo(emit, t); |
|
260 |
38 |
const Instr alloc = emit_add_instr(emit, ArrayAlloc); |
|
261 |
38 |
alloc->m_val = (m_uint)info; |
|
262 |
38 |
arrayinfo_ctor(emit, info); |
|
263 |
38 |
return info; |
|
264 |
} |
||
265 |
|||
266 |
173 |
ANN void emit_ext_ctor(const Emitter emit, const Type t) { |
|
267 |
173 |
const Instr cpy = emit_add_instr(emit, Reg2Reg); |
|
268 |
173 |
cpy->m_val2 = -SZ_INT; |
|
269 |
✓✓ | 173 |
if(t->nspc->pre_ctor) { |
270 |
171 |
const Instr set_code = regseti(emit, (m_uint)t->nspc->pre_ctor); |
|
271 |
171 |
set_code->m_val2 = SZ_INT; |
|
272 |
} else { |
||
273 |
2 |
const Instr instr = emit_add_instr(emit, SetCtor); |
|
274 |
2 |
instr->m_val = (m_uint)t; |
|
275 |
} |
||
276 |
173 |
const m_uint offset = emit_code_offset(emit); |
|
277 |
173 |
const Instr regset = regseti(emit, offset); |
|
278 |
173 |
regset->m_val2 = SZ_INT *2; |
|
279 |
173 |
const Instr push = emit_add_instr(emit, RegPush); |
|
280 |
173 |
push->m_val = SZ_INT *2; |
|
281 |
173 |
const Instr prelude = emit_add_instr(emit, SetCode); |
|
282 |
173 |
prelude->m_val2 = 2; |
|
283 |
173 |
prelude->m_val = SZ_INT; |
|
284 |
173 |
emit_add_instr(emit, Reg2Mem); |
|
285 |
173 |
const Instr next = emit_add_instr(emit, Overflow); |
|
286 |
173 |
next->m_val2 = offset; |
|
287 |
173 |
} |
|
288 |
|||
289 |
7 |
ANN m_bool emit_array_extend(const Emitter emit, const Type t, const Exp e) { |
|
290 |
✗✓ | 7 |
CHECK_OB(emit_array_extend_inner(emit, t, e)) |
291 |
7 |
emit_add_instr(emit, PopArrayClass); |
|
292 |
7 |
emit_add_instr(emit, RegAddRef); |
|
293 |
7 |
return GW_OK; |
|
294 |
} |
||
295 |
|||
296 |
240 |
ANN static inline void emit_notpure(const Emitter emit) { |
|
297 |
240 |
++VPTR(&emit->info->pure, VLEN(&emit->info->pure) - 1); |
|
298 |
240 |
} |
|
299 |
|||
300 |
228 |
ANN2(1,2) m_bool emit_instantiate_object(const Emitter emit, const Type type, |
|
301 |
const Array_Sub array, const m_bool is_ref) { |
||
302 |
228 |
emit_notpure(emit); |
|
303 |
✓✓ | 228 |
if(type->array_depth) { |
304 |
✓✓ | 31 |
ArrayInfo* info = emit_array_extend_inner(emit, type, array ? array->exp : NULL); |
305 |
✓✗ | 31 |
if(info) |
306 |
31 |
info->is_ref = is_ref; |
|
307 |
✓✗ | 31 |
return info ? GW_OK : GW_ERROR; |
308 |
✓✗ | 197 |
} else if(!is_ref) { |
309 |
197 |
const Instr instr = emit_add_instr(emit, ObjectInstantiate); |
|
310 |
197 |
instr->m_val2 = (m_uint)type; |
|
311 |
197 |
emit_pre_ctor(emit, type); |
|
312 |
} |
||
313 |
197 |
return GW_OK; |
|
314 |
} |
||
315 |
|||
316 |
2261 |
static inline enum Kind kindof(const m_uint size, const uint emit_var) { |
|
317 |
✓✓ | 2261 |
if(emit_var) |
318 |
479 |
return KIND_ADDR; |
|
319 |
✓✓✓✓ |
1782 |
return size == SZ_INT ? KIND_INT : size == SZ_FLOAT ? KIND_FLOAT : KIND_OTHER; |
320 |
} |
||
321 |
|||
322 |
2261 |
ANN /*static */Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]) { |
|
323 |
2261 |
const enum Kind kind = kindof(size, addr); |
|
324 |
2261 |
const Instr instr = emit_add_instr(emit, func[kind]); |
|
325 |
2261 |
instr->m_val2 = size; |
|
326 |
2261 |
return instr; |
|
327 |
} |
||
328 |
|||
329 |
static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushImm4 }; |
||
330 |
static const f_instr regpushmem[] = { RegPushMem, RegPushMem2, RegPushMem3, RegPushMem4 }; |
||
331 |
static const f_instr regpushbase[] = { RegPushBase, RegPushBase2, RegPushBase3, RegPushBase4 }; |
||
332 |
static const f_instr dotstatic[] = { DotStatic, DotStatic2, DotStatic3, RegPushImm }; |
||
333 |
static const f_instr allocmember[] = { RegPushImm, RegPushImm2, RegPushImm3, AllocMember4 }; |
||
334 |
static const f_instr allocword[] = { AllocWord, AllocWord2, AllocWord3, RegPushMem4 }; |
||
335 |
static const f_instr structmember[] = { StructMember, StructMemberFloat, StructMemberOther, StructMemberAddr }; |
||
336 |
|||
337 |
ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data); |
||
338 |
144 |
ANN static m_bool emit_symbol_owned(const Emitter emit, const Symbol *data) { |
|
339 |
144 |
const Exp dot = symbol_owned_exp(emit->gwion, data); |
|
340 |
144 |
dot->info->nspc = prim_exp(data)->info->nspc; |
|
341 |
144 |
const m_bool ret = emit_exp_dot(emit, &dot->d.exp_dot); |
|
342 |
144 |
free_exp(emit->gwion->mp, dot); |
|
343 |
144 |
return ret; |
|
344 |
} |
||
345 |
|||
346 |
167 |
ANN static m_bool emit_symbol_builtin(const Emitter emit, const Symbol *data) { |
|
347 |
167 |
const Value v = prim_self(data)->value; |
|
348 |
✓✓ | 167 |
if(GET_FLAG(v, union)) { |
349 |
7 |
const m_uint size = v->type->size; |
|
350 |
7 |
const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), dotstatic); |
|
351 |
7 |
instr->m_val = (m_uint)v->d.ptr; |
|
352 |
} else { |
||
353 |
160 |
const m_uint size = v->type->size; |
|
354 |
160 |
const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), regpushimm); |
|
355 |
✓✓✓✓ |
160 |
if(!exp_getvar(prim_exp(data)) && size == SZ_INT) { |
356 |
✓✓ | 166 |
if(isa(v->type, emit->gwion->type[et_object]) > 0) |
357 |
34 |
instr->m_val = (m_uint)v->d.ptr; |
|
358 |
✓✓ | 49 |
else if(v->d.ptr) |
359 |
34 |
instr->m_val = *(m_uint*)v->d.ptr; |
|
360 |
} else { |
||
361 |
assert(v->d.ptr); // instr->m_val = v->d.ptr; |
||
362 |
77 |
memcpy(&instr->m_val, v->d.ptr, v->type->size); |
|
363 |
} |
||
364 |
160 |
instr->m_val2 = size; |
|
365 |
} |
||
366 |
167 |
return GW_OK; |
|
367 |
} |
||
368 |
|||
369 |
1421 |
ANN static m_bool _emit_symbol(const Emitter emit, const Symbol *data) { |
|
370 |
1421 |
const Value v = prim_self(data)->value; |
|
371 |
✓✓ | 1421 |
if(is_class(emit->gwion, v->type)) { |
372 |
8 |
regpushi(emit, (m_uint)actual_type(emit->gwion, v->type)); |
|
373 |
8 |
return GW_OK; |
|
374 |
} |
||
375 |
✓✓ | 1413 |
if(v->from->owner_class) |
376 |
144 |
return emit_symbol_owned(emit, data); |
|
377 |
✓✓✓✓ ✓✓ |
1269 |
if(GET_FLAG(v, builtin) || GET_FLAG(v, union) || GET_FLAG(v, enum)) |
378 |
167 |
return emit_symbol_builtin(emit, data); |
|
379 |
1102 |
const m_uint size = v->type->size; |
|
380 |
✓✓ | 1102 |
const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), !GET_FLAG(v, global) ? regpushmem : regpushbase); |
381 |
1102 |
instr->m_val = v->from->offset; |
|
382 |
1102 |
return GW_OK; |
|
383 |
} |
||
384 |
|||
385 |
1421 |
ANN static m_bool emit_symbol(const Emitter emit, const Exp_Primary* prim) { |
|
386 |
1421 |
return _emit_symbol(emit, &prim->d.var); |
|
387 |
} |
||
388 |
|||
389 |
852 |
ANN static VM_Code finalyze(const Emitter emit, const f_instr exec) { |
|
390 |
852 |
emit_add_instr(emit, exec); |
|
391 |
852 |
const VM_Code code = emit->info->emit_code(emit); |
|
392 |
852 |
free_code(emit->gwion->mp, emit->code); |
|
393 |
852 |
emit->code = (Code*)vector_pop(&emit->stack); |
|
394 |
852 |
return code; |
|
395 |
} |
||
396 |
|||
397 |
12 |
ANN static m_bool emit_prim_array(const Emitter emit, const Array_Sub *data) { |
|
398 |
12 |
Exp e = (*data)->exp; |
|
399 |
✗✓ | 12 |
CHECK_BB(emit_exp(emit, e)) |
400 |
12 |
m_uint count = 0; |
|
401 |
39 |
do ++count; |
|
402 |
✓✓ | 39 |
while((e = e->next)); |
403 |
12 |
const Type type = (*data)->type; |
|
404 |
12 |
regseti(emit, count); |
|
405 |
12 |
const Instr instr = emit_add_instr(emit, ArrayInit); |
|
406 |
12 |
instr->m_val = (m_uint)type; |
|
407 |
✓✓ | 12 |
instr->m_val2 = type->array_depth == 1 ? array_base(type)->size : SZ_INT; |
408 |
12 |
emit_add_instr(emit, GcAdd); |
|
409 |
12 |
emit_notpure(emit); |
|
410 |
12 |
return GW_OK; |
|
411 |
} |
||
412 |
|||
413 |
ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e); |
||
414 |
|||
415 |
9 |
ANN static m_bool emit_range(const Emitter emit, Range *range) { |
|
416 |
✓✓ | 9 |
if(range->start) |
417 |
✗✓ | 8 |
CHECK_BB(emit_exp_pop_next(emit, range->start)) |
418 |
else |
||
419 |
1 |
regpushi(emit, 0); |
|
420 |
✓✓ | 9 |
if(range->end) |
421 |
✗✓ | 7 |
CHECK_BB(emit_exp_pop_next(emit, range->end)) |
422 |
else |
||
423 |
2 |
regpushi(emit, -1); |
|
424 |
9 |
return GW_OK; |
|
425 |
} |
||
426 |
|||
427 |
2 |
ANN static m_bool emit_prim_range(const Emitter emit, Range **data) { |
|
428 |
2 |
Range *range = *data; |
|
429 |
✗✓ | 2 |
CHECK_BB(emit_range(emit, range)) |
430 |
✓✗ | 2 |
const Exp e = range->start ?: range->end; |
431 |
2 |
const Symbol sym = insert_symbol("@range"); |
|
432 |
6 |
struct Op_Import opi = { .op=sym, .rhs=e->info->type, |
|
433 |
4 |
.pos=e->pos, .data=(uintptr_t)prim_exp(data), .op_type=op_exp }; |
|
434 |
✗✓ | 2 |
CHECK_OB(op_emit(emit, &opi)) |
435 |
2 |
emit_add_instr(emit, GcAdd); |
|
436 |
2 |
return GW_OK; |
|
437 |
} |
||
438 |
|||
439 |
25 |
ANN m_bool emit_array_access(const Emitter emit, struct ArrayAccessInfo *const info) { |
|
440 |
✗✓ | 25 |
if(GET_FLAG(info->array.type, typedef)) { |
441 |
info->array.type = info->array.type->e->parent; |
||
442 |
return emit_array_access(emit, info); |
||
443 |
} |
||
444 |
// look mum no pos |
||
445 |
50 |
struct Op_Import opi = { .op=insert_symbol("@array"), .lhs=info->array.exp->info->type, .rhs=info->array.type, |
|
446 |
25 |
.data=(uintptr_t)info, .op_type=op_array }; |
|
447 |
✓✗ | 25 |
return op_emit(emit, &opi) != (Instr)GW_ERROR ? GW_OK : GW_ERROR; |
448 |
} |
||
449 |
|||
450 |
25 |
ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array* array) { |
|
451 |
✗✓ | 25 |
CHECK_BB(emit_exp(emit, array->base)) |
452 |
25 |
const Exp e = exp_self(array); |
|
453 |
25 |
struct ArrayAccessInfo info = { *array->array, e->info->type, exp_getvar(e) }; |
|
454 |
25 |
return emit_array_access(emit, &info); |
|
455 |
} |
||
456 |
|||
457 |
7 |
ANN static m_bool emit_exp_slice(const Emitter emit, const Exp_Slice* range) { |
|
458 |
✗✓ | 7 |
CHECK_BB(emit_exp(emit, range->base)) |
459 |
✗✓ | 7 |
CHECK_BB(emit_range(emit, range->range)) |
460 |
7 |
const Symbol sym = insert_symbol("@slice"); |
|
461 |
✓✓ | 7 |
const Exp e = range->range->start ?: range->range->end; |
462 |
21 |
struct Op_Import opi = { .op=sym, .lhs=e->info->type, .rhs=range->base->info->type, |
|
463 |
14 |
.pos=e->pos, .data=(uintptr_t)exp_self(range), .op_type=op_exp }; |
|
464 |
✗✓ | 7 |
CHECK_OB(op_emit(emit, &opi)) |
465 |
7 |
return GW_OK; |
|
466 |
} |
||
467 |
|||
468 |
1799 |
ANN static m_bool emit_prim_id(const Emitter emit, const Symbol *data) { |
|
469 |
1799 |
struct SpecialId_ * spid = specialid_get(emit->gwion, *data); |
|
470 |
✓✓ | 1799 |
if(spid) |
471 |
✓✗ | 378 |
return specialid_instr(emit, spid, prim_self(data)) ? GW_OK : GW_ERROR; |
472 |
1421 |
return emit_symbol(emit, prim_self(data)); |
|
473 |
} |
||
474 |
|||
475 |
570 |
ANN static m_bool emit_prim_num(const Emitter emit, const m_uint *num) { |
|
476 |
570 |
regpushi(emit, *num); |
|
477 |
570 |
return GW_OK; |
|
478 |
} |
||
479 |
|||
480 |
74 |
ANN static m_bool emit_prim_float(const Emitter emit, const m_float *fnum) { |
|
481 |
74 |
const Instr instr = emit_add_instr(emit, RegPushImm2); |
|
482 |
74 |
instr->f = *fnum; |
|
483 |
74 |
return GW_OK; |
|
484 |
} |
||
485 |
|||
486 |
15 |
ANN static m_bool emit_prim_char(const Emitter emit, const m_str *str) { |
|
487 |
15 |
const char c = str2char(emit, *str, prim_pos(str)); |
|
488 |
15 |
regpushi(emit, c); |
|
489 |
15 |
return GW_OK; |
|
490 |
} |
||
491 |
|||
492 |
565 |
ANN static Instr emit_addref(const Emitter emit, const m_bool emit_var) { |
|
493 |
✓✓ | 565 |
const f_instr exec = !emit_var ? RegAddRef : RegAddRefAddr; |
494 |
565 |
const Instr instr = emit_add_instr(emit, exec); |
|
495 |
565 |
instr->m_val = -SZ_INT; |
|
496 |
565 |
return instr; |
|
497 |
} |
||
498 |
|||
499 |
310 |
ANN static m_bool emit_prim_str(const Emitter emit, const m_str *str) { |
|
500 |
310 |
char c[strlen(*str) + 1]; |
|
501 |
✓✓ | 310 |
if(strlen(*str)) { |
502 |
304 |
strcpy(c, *str); |
|
503 |
✓✓ | 304 |
CHECK_BB(escape_str(emit, c, prim_pos(str))); |
504 |
6 |
} else c[0] = '\0'; |
|
505 |
308 |
const Value v = prim_self(str)->value; |
|
506 |
308 |
const Symbol sym = insert_symbol(c); |
|
507 |
✓✓ | 308 |
if(!v->d.ptr) |
508 |
246 |
v->d.ptr = (m_uint*)new_string2(emit->gwion, NULL, s_name(sym)); |
|
509 |
308 |
regpushi(emit, (m_uint)v->d.ptr); |
|
510 |
308 |
emit_addref(emit, 0); |
|
511 |
308 |
return GW_OK; |
|
512 |
} |
||
513 |
|||
514 |
#define emit_prim_nil (void*)dummy_func |
||
515 |
|||
516 |
24 |
ANN static m_bool emit_prim_typeof(const Emitter emit, const Exp *exp) { |
|
517 |
24 |
const Exp e = *exp; |
|
518 |
✓✓ | 24 |
if(!e->info->type->array_depth) |
519 |
23 |
regpushi(emit, (m_uint)(actual_type(emit->gwion, e->info->type))); |
|
520 |
else |
||
521 |
1 |
regpushi(emit, (m_uint)e->info->type); |
|
522 |
24 |
return GW_OK; |
|
523 |
} |
||
524 |
|||
525 |
24 |
ANN static void interp_multi(const Emitter emit, const Exp e) { |
|
526 |
24 |
Var_Decl_List list = e->d.exp_decl.list; |
|
527 |
24 |
const int emit_var = exp_getvar(e); |
|
528 |
24 |
m_uint offset = 0; |
|
529 |
✗✓ | 48 |
while((list = list->next)) |
530 |
offset += !emit_var ? list->self->value->type->size : SZ_INT; |
||
531 |
✗✓ | 24 |
if(offset) |
532 |
regpop(emit, offset); |
||
533 |
24 |
} |
|
534 |
|||
535 |
1115 |
ANN static inline void interp_size(const Emitter emit, const Type t) { |
|
536 |
1115 |
const Instr instr = regseti(emit, t->size); |
|
537 |
1115 |
instr->m_val2 = SZ_INT; |
|
538 |
1115 |
} |
|
539 |
|||
540 |
856 |
ANN static m_bool emit_interp(const Emitter emit, const Exp exp) { |
|
541 |
856 |
regpushi(emit, 0); |
|
542 |
856 |
Exp e = exp, next = NULL; |
|
543 |
do { |
||
544 |
1117 |
next = e->next; |
|
545 |
1117 |
e->next = NULL; |
|
546 |
✓✓ | 1117 |
if(emit_exp(emit, e) < 0) { |
547 |
2 |
e->next = next; |
|
548 |
2 |
return GW_ERROR; |
|
549 |
} |
||
550 |
✓✓ | 1115 |
if(e->exp_type == ae_exp_decl) // why only objects? |
551 |
24 |
interp_multi(emit, e); |
|
552 |
1115 |
regseti(emit, (m_uint)e->info->type); |
|
553 |
1115 |
interp_size(emit, e->info->type); |
|
554 |
1115 |
const m_bool isobj = isa(e->info->type, emit->gwion->type[et_object]) > 0; |
|
555 |
✓✓✓✓ |
1115 |
if(isobj && !GET_FLAG(e->info->type, force)) |
556 |
491 |
emit_add_instr(emit, GackType); |
|
557 |
1115 |
const Instr instr = emit_add_instr(emit, Gack); |
|
558 |
1115 |
instr->m_val = emit_code_offset(emit); |
|
559 |
✓✓ | 1115 |
} while((e = e->next = next)); |
560 |
854 |
return GW_OK; |
|
561 |
} |
||
562 |
|||
563 |
851 |
ANN static m_bool emit_prim_hack(const Emitter emit, const Exp *exp) { |
|
564 |
✓✓ | 851 |
CHECK_BB(emit_interp(emit, *exp)) |
565 |
✓✓✓✓ |
849 |
if(!(emit->env->func && emit->env->func->def->base->xid == insert_symbol("@gack"))) |
566 |
847 |
emit_add_instr(emit, GackEnd); |
|
567 |
else { |
||
568 |
2 |
const Instr instr = emit_add_instr(emit, Reg2Mem); |
|
569 |
2 |
instr->m_val = SZ_INT; |
|
570 |
2 |
instr->m_val2 = -SZ_INT; |
|
571 |
} |
||
572 |
849 |
return GW_OK; |
|
573 |
} |
||
574 |
|||
575 |
5 |
ANN static m_bool emit_prim_interp(const Emitter emit, const Exp *exp) { |
|
576 |
5 |
const Exp e = *exp; |
|
577 |
✗✓ | 5 |
CHECK_BB(emit_interp(emit, e)) |
578 |
5 |
const Instr instr = emit_add_instr(emit, GackEnd); |
|
579 |
5 |
instr->m_val = 1; |
|
580 |
5 |
return GW_OK; |
|
581 |
} |
||
582 |
|||
583 |
DECL_PRIM_FUNC(emit, m_bool , Emitter); |
||
584 |
3669 |
ANN static m_bool emit_prim(const Emitter emit, Exp_Primary *const prim) { |
|
585 |
3669 |
return emit_prim_func[prim->prim_type](emit, &prim->d); |
|
586 |
} |
||
587 |
|||
588 |
21 |
ANN static m_bool emit_dot_static_data(const Emitter emit, const Value v, const uint emit_var) { |
|
589 |
21 |
const m_uint size = v->type->size; |
|
590 |
21 |
const Instr instr = emit_kind(emit, size, emit_var, dotstatic); |
|
591 |
21 |
instr->m_val = (m_uint)(v->from->owner->info->class_data + v->from->offset); |
|
592 |
21 |
instr->m_val2 = size; |
|
593 |
21 |
return GW_OK; |
|
594 |
} |
||
595 |
|||
596 |
5 |
ANN static m_bool decl_static(const Emitter emit, const Var_Decl var_decl, const uint is_ref) { |
|
597 |
5 |
const Value v = var_decl->value; |
|
598 |
5 |
Code* code = emit->code; |
|
599 |
5 |
emit->code = (Code*)vector_back(&emit->stack); |
|
600 |
✗✓ | 5 |
CHECK_BB(emit_instantiate_object(emit, v->type, var_decl->array, is_ref)) |
601 |
✗✓ | 5 |
CHECK_BB(emit_dot_static_data(emit, v, 1)) |
602 |
5 |
emit_add_instr(emit, Assign); |
|
603 |
5 |
(void)emit_addref(emit, 0); |
|
604 |
5 |
regpop(emit, SZ_INT); |
|
605 |
5 |
emit->code = code; |
|
606 |
5 |
return GW_OK; |
|
607 |
} |
||
608 |
|||
609 |
1090 |
ANN static inline int struct_ctor(const Value v) { |
|
610 |
✓✓✓✓ |
1090 |
return GET_FLAG(v->type, struct) && v->type->nspc->pre_ctor; |
611 |
} |
||
612 |
|||
613 |
12 |
ANN static void decl_expand(const Emitter emit, const Type t) { |
|
614 |
12 |
struct_expand(emit, t); |
|
615 |
12 |
regpush(emit, t->size - SZ_INT); |
|
616 |
12 |
} |
|
617 |
|||
618 |
12 |
ANN static void emit_struct_decl_finish(const Emitter emit, const Type t, const uint emit_addr) { |
|
619 |
12 |
emit->code->frame->curr_offset += t->size + SZ_INT; |
|
620 |
12 |
emit_ext_ctor(emit, t); |
|
621 |
✓✗ | 12 |
if(!emit_addr) |
622 |
12 |
decl_expand(emit, t); |
|
623 |
12 |
emit->code->frame->curr_offset -= t->size + SZ_INT; |
|
624 |
12 |
} |
|
625 |
|||
626 |
16 |
ANN static m_bool emit_exp_decl_static(const Emitter emit, const Var_Decl var_decl, const uint is_ref, const uint emit_addr) { |
|
627 |
16 |
const Value v = var_decl->value; |
|
628 |
✓✓✓✗ |
16 |
if(isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref) |
629 |
✗✓ | 5 |
CHECK_BB(decl_static(emit, var_decl, 0)) |
630 |
✓✓✗✓ |
16 |
CHECK_BB(emit_dot_static_data(emit, v, !struct_ctor(v) ? emit_addr : 1)) |
631 |
✓✓ | 16 |
if(struct_ctor(v) /* && !GET_FLAG(decl->td, ref) */) |
632 |
1 |
emit_struct_decl_finish(emit, v->type, emit_addr); |
|
633 |
16 |
return GW_OK; |
|
634 |
} |
||
635 |
|||
636 |
26 |
ANN static Instr emit_struct_decl(const Emitter emit, const Value v, const m_bool emit_addr) { |
|
637 |
26 |
emit_add_instr(emit, RegPushMem); |
|
638 |
26 |
const Instr instr = emit_kind(emit, v->type->size, emit_addr, structmember); |
|
639 |
✓✓ | 26 |
if(!emit_addr) |
640 |
15 |
regpush(emit, v->type->size - SZ_INT); |
|
641 |
26 |
return instr; |
|
642 |
} |
||
643 |
|||
644 |
625 |
ANN static m_bool emit_exp_decl_non_static(const Emitter emit, const Exp_Decl *decl, const Var_Decl var_decl, |
|
645 |
const uint is_ref, const uint emit_var) { |
||
646 |
625 |
const Value v = var_decl->value; |
|
647 |
625 |
const Type type = v->type; |
|
648 |
625 |
const Array_Sub array = var_decl->array; |
|
649 |
✓✓✓✓ |
625 |
const m_bool is_array = (array && array->exp) /*|| GET_FLAG(decl->td, force)*/; |
650 |
625 |
const m_bool is_obj = isa(type, emit->gwion->type[et_object]) > 0; |
|
651 |
✓✓✓✓ ✓✗ |
625 |
const uint emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : 1; |
652 |
✓✓✓✓ ✓✓✓✗ |
625 |
if(is_obj && (is_array || !is_ref) && !GET_FLAG(v, ref)) |
653 |
✗✓ | 202 |
CHECK_BB(emit_instantiate_object(emit, type, array, is_ref)) |
654 |
625 |
f_instr *exec = (f_instr*)allocmember; |
|
655 |
✓✓ | 625 |
if(!GET_FLAG(v, member)) { |
656 |
499 |
v->from->offset = emit_local(emit, type); |
|
657 |
499 |
exec = (f_instr*)(allocword); |
|
658 |
✓✓ | 499 |
if(GET_FLAG(v, ref)) { // ref or emit_var ? |
659 |
55 |
const Instr clean = emit_add_instr(emit, MemSetImm); |
|
660 |
55 |
clean->m_val = v->from->offset; |
|
661 |
} |
||
662 |
} |
||
663 |
✓✓✗✓ |
1384 |
const Instr instr = !(SAFE_FLAG(emit->env->class_def, struct) && !emit->env->scope->depth) ? |
664 |
✓✓✓✓ ✓✗ |
1224 |
emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, exec) : emit_struct_decl(emit, v, !struct_ctor(v) ? emit_addr : 1); |
665 |
625 |
instr->m_val = v->from->offset; |
|
666 |
✓✓✓✓ ✓✓✓✗ |
827 |
if(is_obj && (is_array || !is_ref) && !GET_FLAG(v, ref)) { |
667 |
✓✗ | 202 |
if(!emit_var) |
668 |
202 |
emit_add_instr(emit, Assign); |
|
669 |
else { |
||
670 |
regpop(emit, SZ_INT); |
||
671 |
const Instr instr = emit_add_instr(emit, Reg2Reg); |
||
672 |
instr->m_val = -SZ_INT; |
||
673 |
} |
||
674 |
✓✓ | 202 |
const size_t missing_depth = type->array_depth - (array ? array->depth : 0); |
675 |
✓✓✓✗ |
202 |
if(missing_depth && !GET_FLAG(decl->td, force)) { |
676 |
2 |
const Instr push = emit_add_instr(emit, Reg2Reg); |
|
677 |
2 |
push->m_val = -(missing_depth) * SZ_INT; |
|
678 |
} |
||
679 |
✓✓ | 423 |
} else if(struct_ctor(v) /* && !GET_FLAG(decl->td, ref) */) |
680 |
10 |
emit_struct_decl_finish(emit, v->type, emit_addr); |
|
681 |
625 |
return GW_OK; |
|
682 |
} |
||
683 |
|||
684 |
6 |
ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl, const Var_Decl var_decl, |
|
685 |
const uint is_ref, const uint emit_var) { |
||
686 |
6 |
const Value v = var_decl->value; |
|
687 |
6 |
const Type type = v->type; |
|
688 |
6 |
const Array_Sub array = var_decl->array; |
|
689 |
✗✓✗✗ |
6 |
const m_bool is_array = array && array->exp; |
690 |
6 |
const m_bool is_obj = isa(type, emit->gwion->type[et_object]) > 0; |
|
691 |
✓✓✗✓ ✗✗ |
6 |
const uint emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : 1; |
692 |
✓✓✓✗ ✓✗✓✗ |
6 |
if(is_obj && (is_array || !is_ref) && !GET_FLAG(v, ref)) |
693 |
✗✓ | 2 |
CHECK_BB(emit_instantiate_object(emit, type, array, is_ref)) |
694 |
✓✓ | 6 |
const Instr instr = emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, dotstatic); |
695 |
6 |
v->d.ptr = mp_calloc2(emit->gwion->mp, v->type->size); |
|
696 |
6 |
SET_FLAG(v, union); |
|
697 |
6 |
instr->m_val = (m_uint)v->d.ptr; |
|
698 |
6 |
instr->m_val2 = v->type->size; |
|
699 |
✓✓✓✗ ✓✗✓✗ |
8 |
if(is_obj && (is_array || !is_ref) && !GET_FLAG(v, ref)) { |
700 |
2 |
const Instr assign = emit_add_instr(emit, Assign); |
|
701 |
✗✓ | 2 |
const size_t missing_depth = type->array_depth - (array ? array->depth : 0); |
702 |
✗✓✗✗ |
2 |
if(missing_depth && !GET_FLAG(decl->td, force)) { |
703 |
const Instr push = emit_add_instr(emit, Reg2Reg); |
||
704 |
push->m_val = -(missing_depth) * SZ_INT; |
||
705 |
} |
||
706 |
2 |
assign->m_val = emit_var; |
|
707 |
2 |
(void)emit_addref(emit, emit_var); |
|
708 |
✓✓ | 4 |
} else if(struct_ctor(v) /* && !GET_FLAG(decl->td, ref) */) |
709 |
1 |
emit_struct_decl_finish(emit, v->type, emit_addr); |
|
710 |
6 |
return GW_OK; |
|
711 |
} |
||
712 |
|||
713 |
ANN static m_bool emit_class_def(const Emitter, const Class_Def); |
||
714 |
ANN static m_bool emit_cdef(const Emitter, const Class_Def); |
||
715 |
|||
716 |
31 |
ANN static inline m_bool ensure_emit(const Emitter emit, const Type t) { |
|
717 |
62 |
struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef, |
|
718 |
31 |
.scope=emit->env->scope->depth, .flag=ae_flag_emit }; |
|
719 |
31 |
return envset_run(&es, t); |
|
720 |
} |
||
721 |
|||
722 |
640 |
ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl* decl) { |
|
723 |
640 |
const m_bool global = GET_FLAG(decl->td, global); |
|
724 |
640 |
const uint var = exp_getvar(exp_self(decl)); |
|
725 |
✓✓✗✓ |
640 |
const uint ref = GET_FLAG(decl->td, ref) || type_ref(decl->type); |
726 |
640 |
Var_Decl_List list = decl->list; |
|
727 |
do { |
||
728 |
647 |
const uint r = GET_FLAG(list->self->value, ref) + ref; |
|
729 |
✓✓ | 647 |
if(GET_FLAG(decl->td, static)) |
730 |
✗✓ | 16 |
CHECK_BB(emit_exp_decl_static(emit, list->self, r, var)) |
731 |
✓✓ | 631 |
else if(!global) |
732 |
✗✓ | 625 |
CHECK_BB(emit_exp_decl_non_static(emit, decl, list->self, r, var)) |
733 |
else |
||
734 |
✗✓ | 6 |
CHECK_BB(emit_exp_decl_global(emit, decl, list->self, r, var)) |
735 |
✓✓ | 647 |
} while((list = list->next)); |
736 |
640 |
return GW_OK; |
|
737 |
} |
||
738 |
|||
739 |
640 |
ANN /*static */m_bool emit_exp_decl(const Emitter emit, const Exp_Decl* decl) { |
|
740 |
640 |
const Type t = get_type(decl->type); |
|
741 |
✓✓✓✓ |
640 |
if(!GET_FLAG(t, emit) && t->e->def) |
742 |
✗✓ | 24 |
CHECK_BB(ensure_emit(emit, t)) |
743 |
640 |
const m_bool global = GET_FLAG(decl->td, global); |
|
744 |
✓✓ | 640 |
const m_uint scope = !global ? emit->env->scope->depth : emit_push_global(emit); |
745 |
640 |
const m_bool ret = emit_decl(emit, decl); |
|
746 |
✓✓ | 640 |
if(global) |
747 |
6 |
emit_pop(emit, scope); |
|
748 |
640 |
return ret; |
|
749 |
} |
||
750 |
|||
751 |
24 |
ANN static m_uint vararg_size(const Exp_Call* exp_call, const Vector kinds) { |
|
752 |
24 |
Exp e = exp_call->args; |
|
753 |
24 |
Arg_List l = exp_call->m_func->def->base->args; |
|
754 |
24 |
m_uint size = 0; |
|
755 |
✓✓ | 102 |
while(e) { |
756 |
✓✓ | 54 |
if(!l) { |
757 |
45 |
size += e->info->type->size; |
|
758 |
45 |
vector_add(kinds, (vtype)e->info->type); // ->size |
|
759 |
} else |
||
760 |
9 |
l = l->next; |
|
761 |
54 |
e = e->next; |
|
762 |
} |
||
763 |
24 |
return size; |
|
764 |
} |
||
765 |
|||
766 |
24 |
ANN static void emit_func_arg_vararg(const Emitter emit, const Exp_Call* exp_call) { |
|
767 |
24 |
const Instr instr = emit_add_instr(emit, VarargIni); |
|
768 |
24 |
const Vector kinds = new_vector(emit->gwion->mp); |
|
769 |
✓✓ | 24 |
if((instr->m_val = vararg_size(exp_call, kinds))) |
770 |
18 |
instr->m_val2 = (m_uint)kinds; |
|
771 |
else |
||
772 |
6 |
free_vector(emit->gwion->mp, kinds); |
|
773 |
24 |
} |
|
774 |
|||
775 |
ANN static inline m_uint exp_size(Exp e); |
||
776 |
277 |
ANN static inline m_uint exp_totalsize(Exp e) { |
|
777 |
277 |
m_uint size = 0; |
|
778 |
383 |
do size += exp_size(e); |
|
779 |
✓✓ | 383 |
while((e = e->next)); |
780 |
277 |
return size; |
|
781 |
} |
||
782 |
ANN static /*inline */void emit_exp_addref1(const Emitter emit, Exp, const m_int size); |
||
783 |
ANN static /*inline */void emit_exp_addref(const Emitter emit, Exp, const m_int size); |
||
784 |
|||
785 |
459 |
ANN static m_bool emit_func_args(const Emitter emit, const Exp_Call* exp_call) { |
|
786 |
✓✓ | 459 |
if(exp_call->args) { |
787 |
✗✓ | 234 |
CHECK_BB(emit_exp(emit, exp_call->args)) |
788 |
234 |
emit_exp_addref(emit, exp_call->args, -exp_totalsize(exp_call->args)); |
|
789 |
} |
||
790 |
✓✗✓✓ |
459 |
if(exp_call->m_func && GET_FLAG(exp_call->m_func->def, variadic)) |
791 |
24 |
emit_func_arg_vararg(emit, exp_call); |
|
792 |
459 |
return GW_OK; |
|
793 |
} |
||
794 |
|||
795 |
458 |
ANN static m_bool prepare_call(const Emitter emit, const Exp_Call* exp_call) { |
|
796 |
✗✓ | 458 |
CHECK_BB(emit_func_args(emit, exp_call)) |
797 |
458 |
return emit_exp(emit, exp_call->func); |
|
798 |
} |
||
799 |
|||
800 |
431 |
ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call* exp_call) { |
|
801 |
✗✓ | 431 |
CHECK_BB(prepare_call(emit, exp_call)) |
802 |
✓✗ | 431 |
if(exp_call->m_func) |
803 |
✗✓ | 431 |
CHECK_OB(emit_exp_call1(emit, exp_call->m_func)) |
804 |
else { |
||
805 |
struct Op_Import opi = { .op=insert_symbol("@ctor"), .rhs=exp_call->func->info->type->e->d.base_type, |
||
806 |
.data=(uintptr_t)exp_call, .pos=exp_self(exp_call)->pos, .op_type=op_exp }; |
||
807 |
CHECK_OB(op_emit(emit, &opi)) |
||
808 |
} |
||
809 |
431 |
const Exp e = exp_self(exp_call); |
|
810 |
✓✓ | 431 |
if(exp_getvar(e)) { |
811 |
2 |
regpop(emit, exp_self(exp_call)->info->type->size - SZ_INT); |
|
812 |
2 |
const Instr instr = emit_add_instr(emit, Reg2RegAddr); |
|
813 |
2 |
instr->m_val = -SZ_INT; |
|
814 |
2 |
instr->m_val2 = -SZ_INT; |
|
815 |
✗✓✗✗ |
429 |
} else if(!exp_call->m_func && GET_FLAG(e->info->type, struct)) |
816 |
regpop(emit, SZ_INT); |
||
817 |
431 |
return GW_OK; |
|
818 |
} |
||
819 |
|||
820 |
477 |
ANN static m_uint get_decl_size(Var_Decl_List a, uint emit_addr) { |
|
821 |
477 |
m_uint size = 0; |
|
822 |
do //if(GET_FLAG(a->self->value, used)) |
||
823 |
✓✗ | 484 |
size += !emit_addr ? a->self->value->type->size : SZ_INT; |
824 |
✓✓ | 484 |
while((a = a->next)); |
825 |
477 |
return size; |
|
826 |
} |
||
827 |
|||
828 |
1994 |
ANN static m_uint pop_exp_size(Exp e) { |
|
829 |
1994 |
const uint emit_addr = exp_getvar(e); |
|
830 |
1994 |
m_uint size = 0; |
|
831 |
do { // account for emit_var ? |
||
832 |
3988 |
size += (e->exp_type == ae_exp_decl ? |
|
833 |
✓✓ | 1994 |
get_decl_size(e->d.exp_decl.list, emit_addr) : e->info->type->size); |
834 |
✗✓ | 1994 |
} while((e = e->next)); |
835 |
1994 |
return size; |
|
836 |
} |
||
837 |
|||
838 |
1994 |
ANN static inline void pop_exp(const Emitter emit, Exp e) { |
|
839 |
1994 |
const m_uint size = pop_exp_size(e); |
|
840 |
✓✓ | 1994 |
if(size) |
841 |
1802 |
regpop(emit, size); |
|
842 |
1994 |
} |
|
843 |
|||
844 |
1226 |
ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e) { |
|
845 |
✗✓ | 1226 |
CHECK_BB(emit_exp(emit, e)) |
846 |
✓✓ | 1226 |
if(e->exp_type == ae_exp_decl) { |
847 |
123 |
Var_Decl_List list = e->d.exp_decl.list->next; |
|
848 |
✗✓ | 246 |
while(list) { |
849 |
regpop(emit, !exp_getvar(e) ? list->self->value->type->size : SZ_INT); |
||
850 |
list = list->next; |
||
851 |
} |
||
852 |
} |
||
853 |
✓✓ | 1226 |
if(e->next) |
854 |
1 |
pop_exp(emit, e->next); |
|
855 |
1226 |
return GW_OK; |
|
856 |
} |
||
857 |
|||
858 |
1258 |
ANN static inline m_bool op_emit_bool(const Emitter emit, const struct Op_Import* opi) { |
|
859 |
✗✓ | 1258 |
DECL_OB(const Instr, instr, = op_emit(emit, opi)) |
860 |
1258 |
return GW_OK; |
|
861 |
} |
||
862 |
|||
863 |
497 |
ANN static m_bool emit_exp_binary(const Emitter emit, const Exp_Binary* bin) { |
|
864 |
497 |
const Exp lhs = bin->lhs; |
|
865 |
497 |
const Exp rhs = bin->rhs; |
|
866 |
1491 |
struct Op_Import opi = { .op=bin->op, .lhs=lhs->info->type, .rhs=rhs->info->type, |
|
867 |
994 |
.pos=exp_self(bin)->pos, .data=(uintptr_t)bin, .op_type=op_binary }; |
|
868 |
✗✓ | 497 |
CHECK_BB(emit_exp_pop_next(emit, lhs)) |
869 |
✗✓ | 497 |
CHECK_BB(emit_exp_pop_next(emit, rhs)) |
870 |
497 |
const m_int size = exp_size(rhs); |
|
871 |
497 |
emit_exp_addref1(emit, lhs, -exp_size(lhs) - size); |
|
872 |
497 |
emit_exp_addref1(emit, rhs, -size); |
|
873 |
497 |
return op_emit_bool(emit, &opi); |
|
874 |
} |
||
875 |
|||
876 |
34 |
ANN static m_bool emit_exp_cast(const Emitter emit, const Exp_Cast* cast) { |
|
877 |
// no pos ? |
||
878 |
68 |
struct Op_Import opi = { .op=insert_symbol("$"), .lhs=cast->exp->info->type, .rhs=exp_self(cast)->info->type, |
|
879 |
34 |
.data=(uintptr_t)cast, .op_type=op_cast}; |
|
880 |
✗✓ | 34 |
CHECK_BB(emit_exp(emit, cast->exp)) |
881 |
34 |
(void)op_emit(emit, &opi); |
|
882 |
34 |
return GW_OK; |
|
883 |
} |
||
884 |
|||
885 |
35 |
ANN static m_bool emit_exp_post(const Emitter emit, const Exp_Postfix* post) { |
|
886 |
// no pos ? |
||
887 |
70 |
struct Op_Import opi = { .op=post->op, .lhs=post->exp->info->type, |
|
888 |
35 |
.data=(uintptr_t)post, .op_type=op_postfix }; |
|
889 |
✗✓ | 35 |
CHECK_BB(emit_exp(emit, post->exp)) |
890 |
35 |
emit_exp_addref(emit, post->exp, -exp_totalsize(post->exp)); |
|
891 |
35 |
return op_emit_bool(emit, &opi); |
|
892 |
} |
||
893 |
|||
894 |
20 |
ANN static inline m_bool traverse_emit_func_def(const Emitter emit, const Func_Def fdef) { |
|
895 |
✓✗ | 20 |
if(!fdef->base->ret_type) |
896 |
✓✓ | 20 |
CHECK_BB(traverse_func_def(emit->env, fdef)) |
897 |
18 |
return emit_func_def(emit, fdef); |
|
898 |
} |
||
899 |
|||
900 |
20 |
ANN m_bool traverse_dot_tmpl(const Emitter emit, const struct dottmpl_ *dt) { |
|
901 |
20 |
const m_uint scope = emit->env->scope->depth; |
|
902 |
20 |
struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef, |
|
903 |
.scope=scope, .flag=ae_flag_emit }; |
||
904 |
✗✓ | 20 |
CHECK_BB(envset_push(&es, dt->owner_class, dt->owner)) |
905 |
20 |
(void)emit_push(emit, dt->owner_class, dt->owner); |
|
906 |
20 |
const m_bool ret = traverse_emit_func_def(emit, dt->def); |
|
907 |
✓✓ | 20 |
if(es.run) |
908 |
4 |
envset_pop(&es, dt->owner_class); |
|
909 |
20 |
emit_pop(emit, scope); |
|
910 |
20 |
return ret; |
|
911 |
} |
||
912 |
|||
913 |
191 |
static inline m_bool push_func_code(const Emitter emit, const Func f) { |
|
914 |
✓✓ | 191 |
if(!vector_size(&emit->code->instr)) |
915 |
10 |
return GW_OK; |
|
916 |
181 |
const Instr instr = (Instr)vector_back(&emit->code->instr); |
|
917 |
✓✓ | 181 |
if(instr->opcode == eDotTmplVal) { |
918 |
45 |
size_t len = strlen(f->name); |
|
919 |
45 |
size_t sz = len - strlen(f->value_ref->from->owner_class->name); |
|
920 |
45 |
char c[sz + 1]; |
|
921 |
45 |
memcpy(c, f->name, sz); |
|
922 |
45 |
c[sz] = '\0'; |
|
923 |
45 |
struct dottmpl_ *dt = mp_calloc(emit->gwion->mp, dottmpl); |
|
924 |
45 |
dt->name = s_name(insert_symbol(c)); |
|
925 |
45 |
dt->vt_index = f->def->base->tmpl->base; |
|
926 |
45 |
dt->tl = cpy_type_list(emit->gwion->mp, f->def->base->tmpl->call); |
|
927 |
45 |
dt->base = f->def; |
|
928 |
45 |
instr->opcode = eOP_MAX; |
|
929 |
45 |
instr->m_val = (m_uint)dt; |
|
930 |
45 |
instr->m_val2 = strlen(c); |
|
931 |
45 |
instr->execute = DotTmpl; |
|
932 |
45 |
return GW_OK; |
|
933 |
} |
||
934 |
136 |
instr->opcode = eRegPushImm; |
|
935 |
136 |
instr->m_val = (m_uint)f->code; |
|
936 |
136 |
return GW_OK; |
|
937 |
} |
||
938 |
|||
939 |
39 |
ANN static m_bool emit_template_code(const Emitter emit, const Func f) { |
|
940 |
39 |
const Value v = f->value_ref; |
|
941 |
39 |
const size_t scope = emit->env->scope->depth; |
|
942 |
39 |
struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef, |
|
943 |
.scope=scope, .flag=ae_flag_emit }; |
||
944 |
✗✓ | 39 |
CHECK_BB(envset_push(&es, v->from->owner_class, v->from->owner)) |
945 |
39 |
(void)emit_push(emit, v->from->owner_class, v->from->owner); |
|
946 |
39 |
const m_bool ret = emit_func_def(emit, f->def); |
|
947 |
✓✓ | 39 |
if(es.run) |
948 |
18 |
envset_pop(&es, v->from->owner_class); |
|
949 |
39 |
emit_pop(emit, scope); |
|
950 |
✓✗ | 39 |
return ret > 0 ? push_func_code(emit, f) : GW_ERROR; |
951 |
} |
||
952 |
|||
953 |
18 |
ANN static void tmpl_prelude(const Emitter emit, const Func f) { |
|
954 |
18 |
struct dottmpl_ *dt = (struct dottmpl_*)mp_calloc(emit->gwion->mp, dottmpl); |
|
955 |
18 |
size_t len = strlen(f->name); |
|
956 |
18 |
size_t slen = strlen(f->value_ref->from->owner->name); |
|
957 |
assert(len > slen); |
||
958 |
18 |
size_t sz = len - slen; |
|
959 |
18 |
char c[sz + 1]; |
|
960 |
18 |
memcpy(c, f->name, sz); |
|
961 |
18 |
c[sz] = '\0'; |
|
962 |
18 |
dt->tl = cpy_type_list(emit->gwion->mp, f->def->base->tmpl->call); |
|
963 |
18 |
dt->name = s_name(insert_symbol(c)); |
|
964 |
18 |
dt->vt_index = f->def->base->tmpl->base; |
|
965 |
18 |
dt->base = f->def; |
|
966 |
18 |
dt->owner = f->value_ref->from->owner; |
|
967 |
18 |
dt->owner_class = f->value_ref->from->owner_class; |
|
968 |
18 |
const Instr gtmpl = emit_add_instr(emit, GTmpl); |
|
969 |
18 |
gtmpl->m_val = (m_uint)dt; |
|
970 |
18 |
gtmpl->m_val2 = strlen(c); |
|
971 |
18 |
} |
|
972 |
|||
973 |
472 |
ANN static Instr get_prelude(const Emitter emit, const Func f) { |
|
974 |
472 |
const Type t = actual_type(emit->gwion, f->value_ref->type); |
|
975 |
✓✓ | 472 |
if(is_fptr(emit->gwion, t)) { |
976 |
64 |
emit_except(emit, t); |
|
977 |
✓✓ | 64 |
if(f->def->base->tmpl) |
978 |
18 |
tmpl_prelude(emit, f); |
|
979 |
} |
||
980 |
472 |
const Instr instr = emit_add_instr(emit, SetCode); |
|
981 |
472 |
instr->m_val2 = 1; |
|
982 |
472 |
return instr; |
|
983 |
} |
||
984 |
|||
985 |
248 |
ANN static void emit_args(const Emitter emit, const Func f) { |
|
986 |
248 |
const m_uint member = GET_FLAG(f, member) ? SZ_INT : 0; |
|
987 |
✓✓ | 248 |
if((f->def->stack_depth - member) == SZ_INT) { |
988 |
155 |
const Instr instr = emit_add_instr(emit, Reg2Mem); |
|
989 |
155 |
instr->m_val = member; |
|
990 |
} else { |
||
991 |
93 |
const Instr instr = emit_add_instr(emit, Reg2Mem4); |
|
992 |
93 |
instr->m_val = member; |
|
993 |
93 |
instr->m_val2 = f->def->stack_depth - member; |
|
994 |
} |
||
995 |
248 |
} |
|
996 |
|||
997 |
typedef struct { |
||
998 |
const Emitter emit; |
||
999 |
const Func_Def fdef; |
||
1000 |
struct Vector_ branch; |
||
1001 |
const m_uint offset; |
||
1002 |
m_uint arg_offset; |
||
1003 |
} MemoizeEmitter; |
||
1004 |
|||
1005 |
2 |
ANN static Instr me_push(const MemoizeEmitter *me, const m_uint sz) { |
|
1006 |
2 |
const Instr instr = emit_kind(me->emit, sz, 0, regpushmem); |
|
1007 |
2 |
instr->m_val = me->arg_offset; |
|
1008 |
2 |
return instr; |
|
1009 |
} |
||
1010 |
|||
1011 |
1 |
static m_bool me_cmp(MemoizeEmitter *me, const Arg_List arg) { |
|
1012 |
1 |
const Emitter emit = me->emit; |
|
1013 |
1 |
const Symbol sym = insert_symbol("=="); |
|
1014 |
1 |
struct ExpInfo_ info = { .nspc=me->fdef->base->func->value_ref->from->owner }; |
|
1015 |
1 |
struct Exp_ exp = { .info=&info }; |
|
1016 |
3 |
struct Op_Import opi = { .op=sym, .lhs=arg->type, .rhs=arg->type, |
|
1017 |
2 |
.pos=me->fdef->pos, .data=(uintptr_t)&exp.d, .op_type=op_binary }; |
|
1018 |
✗✓ | 1 |
CHECK_BB(op_emit_bool(emit, &opi)) |
1019 |
1 |
const Instr instr = emit_add_instr(emit, BranchEqInt); |
|
1020 |
1 |
vector_add(&me->branch, (vtype)instr); |
|
1021 |
1 |
return GW_OK; |
|
1022 |
} |
||
1023 |
|||
1024 |
1 |
ANN static m_bool me_arg(MemoizeEmitter *me) { |
|
1025 |
1 |
Arg_List arg = me->fdef->base->args; |
|
1026 |
do { |
||
1027 |
1 |
const m_uint sz = arg->type->size; |
|
1028 |
1 |
(void)me_push(me, sz); |
|
1029 |
1 |
const Instr instr = me_push(me, sz); |
|
1030 |
1 |
instr->m_val += me->offset + SZ_INT *2; |
|
1031 |
✗✓ | 1 |
CHECK_BB(me_cmp(me, arg)) |
1032 |
1 |
me->arg_offset += arg->type->size; |
|
1033 |
✗✓ | 1 |
} while((arg = arg->next)); |
1034 |
1 |
return GW_OK; |
|
1035 |
} |
||
1036 |
|||
1037 |
472 |
ANN static Instr emit_call(const Emitter emit, const Func f) { |
|
1038 |
472 |
const Instr prelude = get_prelude(emit, f); |
|
1039 |
472 |
prelude->m_val = f->def->stack_depth; |
|
1040 |
472 |
const m_uint member = GET_FLAG(f, member) ? SZ_INT : 0; |
|
1041 |
✓✓ | 472 |
if(member) { |
1042 |
259 |
const Instr instr = emit_add_instr(emit, Reg2Mem); |
|
1043 |
259 |
instr->m_val2 = f->def->stack_depth - SZ_INT; |
|
1044 |
259 |
++prelude->m_val2; |
|
1045 |
} |
||
1046 |
✓✓ | 472 |
if(f->def->stack_depth - member) { |
1047 |
247 |
emit_args(emit, f); |
|
1048 |
247 |
++prelude->m_val2; |
|
1049 |
} |
||
1050 |
472 |
return emit_add_instr(emit, Overflow); |
|
1051 |
} |
||
1052 |
|||
1053 |
472 |
ANN Instr emit_exp_call1(const Emitter emit, const Func f) { |
|
1054 |
✓✓✓✓ ✓✗ |
472 |
if(!f->code || (GET_FLAG(f, ref) && !GET_FLAG(f, builtin))) { |
1055 |
✓✓✓✗ |
244 |
if(GET_FLAG(f, template) && !is_fptr(emit->gwion, f->value_ref->type)) { |
1056 |
✓✓ | 88 |
if(emit->env->func != f) |
1057 |
✗✓ | 39 |
CHECK_BO(emit_template_code(emit, f)) |
1058 |
else { // recursive function. (maybe should be used only for global funcs) |
||
1059 |
10 |
const Instr back = (Instr) vector_size(&emit->code->instr) ? |
|
1060 |
✓✗ | 5 |
(Instr)vector_back(&emit->code->instr) : emit_add_instr(emit, RegPushImm); |
1061 |
5 |
back->opcode = eOP_MAX; |
|
1062 |
5 |
back->execute = SetRecurs; |
|
1063 |
5 |
back->m_val = 0; |
|
1064 |
} |
||
1065 |
✓✓✓✓ ✓✗✓✓ |
78 |
} else if(emit->env->func != f && !f->value_ref->from->owner_class && !f->code && !is_fptr(emit->gwion, f->value_ref->type)) { |
1066 |
✗✓ | 1 |
if(GET_FLAG(f->def, op)) { |
1067 |
const Instr back = (Instr)vector_back(&emit->code->instr); |
||
1068 |
back->m_val = (m_uint)f; |
||
1069 |
} else { |
||
1070 |
// ensure env? |
||
1071 |
✗✓ | 1 |
CHECK_BO(emit_func_def(emit, f->def)) |
1072 |
1 |
const Instr instr = emit_add_instr(emit, RegSetImm); |
|
1073 |
1 |
instr->m_val = (m_uint)f->code; |
|
1074 |
1 |
instr->m_val2 = -SZ_INT; |
|
1075 |
} |
||
1076 |
} |
||
1077 |
✓✓✓✓ ✓✓ |
695 |
} else if((f->value_ref->from->owner_class && GET_FLAG(f->value_ref->from->owner_class, struct)) || |
1078 |
✓✓✓✗ |
597 |
!f->value_ref->from->owner_class || (GET_FLAG(f, template) && |
1079 |
27 |
!is_fptr(emit->gwion, f->value_ref->type))) |
|
1080 |
152 |
push_func_code(emit, f); |
|
1081 |
✓✓ | 198 |
else if(vector_size(&emit->code->instr)) { |
1082 |
187 |
const Instr back = (Instr)vector_back(&emit->code->instr); |
|
1083 |
✓✓✓✓ |
187 |
if((f_instr)(m_uint)back->opcode == DotFunc || (f_instr)(m_uint)back->opcode == DotStaticFunc) |
1084 |
169 |
back->m_val = f->vt_index; |
|
1085 |
} |
||
1086 |
✓✓✓✓ ✓✓ |
717 |
if(vector_size(&emit->code->instr) && GET_FLAG(f, member) && |
1087 |
273 |
is_fptr(emit->gwion, f->value_ref->type)) { |
|
1088 |
28 |
const Instr back = (Instr)vector_back(&emit->code->instr); |
|
1089 |
28 |
m_bit exec = back->opcode; |
|
1090 |
28 |
m_uint val = back->m_val; |
|
1091 |
28 |
m_uint val2 = back->m_val2; |
|
1092 |
28 |
back->opcode = eReg2Reg; |
|
1093 |
28 |
back->m_val2 = -SZ_INT; |
|
1094 |
28 |
regpush(emit, SZ_INT); |
|
1095 |
28 |
const Instr instr = emit_add_instr(emit, (f_instr)(m_uint)exec); |
|
1096 |
28 |
instr->m_val = val; |
|
1097 |
28 |
instr->m_val2 = val2; |
|
1098 |
✓✓✓✓ ✓✓ |
444 |
} else if(f != emit->env->func && !f->code && !is_fptr(emit->gwion, f->value_ref->type)){ |
1099 |
// not yet emitted static func |
||
1100 |
✓✗ | 2 |
if(f->value_ref->from->owner_class) { |
1101 |
4 |
const Instr instr = vector_size(&emit->code->instr) ? |
|
1102 |
✓✗ | 2 |
(Instr)vector_back(&emit->code->instr) : emit_add_instr(emit, SetFunc); |
1103 |
2 |
instr->opcode = eOP_MAX; |
|
1104 |
2 |
instr->execute = SetFunc; |
|
1105 |
2 |
instr->m_val = (m_uint)f; |
|
1106 |
} else { |
||
1107 |
const Instr instr = emit_add_instr(emit, SetFunc); |
||
1108 |
instr->m_val = (m_uint)f; |
||
1109 |
} |
||
1110 |
} |
||
1111 |
472 |
const m_uint offset = emit_code_offset(emit); |
|
1112 |
472 |
regseti(emit, offset); |
|
1113 |
472 |
const Instr instr = emit_call(emit, f); |
|
1114 |
472 |
instr->m_val = f->def->base->ret_type->size; |
|
1115 |
472 |
instr->m_val2 = offset; |
|
1116 |
472 |
return instr; |
|
1117 |
} |
||
1118 |
|||
1119 |
24 |
ANN static void emit_exp_spork_finish(const Emitter emit, const m_uint depth) { |
|
1120 |
24 |
regpop(emit, depth); |
|
1121 |
24 |
const Instr spork = emit_add_instr(emit, SporkFunc); |
|
1122 |
24 |
spork->m_val = depth + SZ_INT; |
|
1123 |
24 |
spork->m_val2 = -SZ_INT; |
|
1124 |
24 |
} |
|
1125 |
|||
1126 |
263 |
static inline void stack_alloc(const Emitter emit) { // maybe vararg could use t_vararg instead |
|
1127 |
263 |
emit_local(emit, emit->gwion->type[et_int]); // hiding the fact it is an object |
|
1128 |
263 |
emit->code->stack_depth += SZ_INT; |
|
1129 |
263 |
} |
|
1130 |
|||
1131 |
251 |
static inline void stack_alloc_this(const Emitter emit) { |
|
1132 |
251 |
SET_FLAG(emit->code, member); |
|
1133 |
251 |
stack_alloc(emit); |
|
1134 |
251 |
} |
|
1135 |
|||
1136 |
372 |
static m_bool scoped_stmt(const Emitter emit, const Stmt stmt, const m_bool pop) { |
|
1137 |
372 |
++emit->env->scope->depth; |
|
1138 |
372 |
emit_push_scope(emit); |
|
1139 |
372 |
const Instr gc = emit_add_instr(emit, NoOp); |
|
1140 |
372 |
const m_bool ret = emit_stmt(emit, stmt, pop); |
|
1141 |
✓✗ | 372 |
if(ret > 0) { |
1142 |
372 |
const m_bool pure = !vector_back(&emit->info->pure); |
|
1143 |
✓✓ | 372 |
if(!pure) { |
1144 |
8 |
gc->opcode = eGcIni; |
|
1145 |
8 |
emit_add_instr(emit, GcEnd); |
|
1146 |
} |
||
1147 |
} |
||
1148 |
372 |
emit_pop_scope(emit); |
|
1149 |
372 |
--emit->env->scope->depth; |
|
1150 |
372 |
return ret; |
|
1151 |
} |
||
1152 |
|||
1153 |
#define SPORK_FUNC_PREFIX "spork~func:%i" |
||
1154 |
#define FORK_FUNC_PREFIX "fork~func:%i" |
||
1155 |
#define SPORK_CODE_PREFIX "spork~code:%i" |
||
1156 |
#define FORK_CODE_PREFIX "fork~code:%i" |
||
1157 |
|||
1158 |
53 |
static void push_spork_code(const Emitter emit, const m_str prefix, const loc_t pos) { |
|
1159 |
53 |
char c[strlen(SPORK_FUNC_PREFIX) + num_digit(pos->first.line) + 1]; |
|
1160 |
53 |
sprintf(c, prefix, pos->first.line); |
|
1161 |
53 |
emit_push_code(emit, c); |
|
1162 |
53 |
} |
|
1163 |
|||
1164 |
27 |
ANN static m_bool call_spork_func(const Emitter emit, const Exp_Call *exp) { |
|
1165 |
✓✓ | 27 |
if(GET_FLAG(exp->m_func, member)) |
1166 |
14 |
SET_FLAG(emit->code, member); |
|
1167 |
✓✗ | 27 |
return emit_exp_call1(emit, exp->m_func) ? GW_OK : GW_ERROR; |
1168 |
} |
||
1169 |
|||
1170 |
struct Sporker { |
||
1171 |
const Stmt code; |
||
1172 |
const Exp exp; |
||
1173 |
VM_Code vm_code; |
||
1174 |
const Type type; |
||
1175 |
const m_bool emit_var; |
||
1176 |
const m_bool is_spork; |
||
1177 |
}; |
||
1178 |
|||
1179 |
26 |
ANN static m_bool spork_prepare_code(const Emitter emit, const struct Sporker *sp) { |
|
1180 |
26 |
emit_add_instr(emit, RegPushImm); |
|
1181 |
✓✓ | 26 |
push_spork_code(emit, sp->is_spork ? SPORK_CODE_PREFIX : FORK_CODE_PREFIX, sp->code->pos); |
1182 |
✓✓✓✓ |
26 |
if(SAFE_FLAG(emit->env->func, member)) |
1183 |
2 |
stack_alloc_this(emit); |
|
1184 |
26 |
return scoped_stmt(emit, sp->code, 0); |
|
1185 |
} |
||
1186 |
|||
1187 |
27 |
ANN static m_bool spork_prepare_func(const Emitter emit, const struct Sporker *sp) { |
|
1188 |
✓✗ | 27 |
push_spork_code(emit, sp->is_spork ? SPORK_FUNC_PREFIX : FORK_CODE_PREFIX, sp->exp->pos); |
1189 |
27 |
return call_spork_func(emit, &sp->exp->d.exp_call); |
|
1190 |
} |
||
1191 |
|||
1192 |
53 |
ANN static VM_Code spork_prepare(const Emitter emit, const struct Sporker *sp) { |
|
1193 |
✓✓ | 53 |
if(!sp->code) |
1194 |
✗✓ | 27 |
CHECK_BO(prepare_call(emit, &sp->exp->d.exp_call)) |
1195 |
✓✓✓✗ |
53 |
if((sp->code ? spork_prepare_code : spork_prepare_func)(emit, sp) > 0) |
1196 |
53 |
return finalyze(emit, EOC); |
|
1197 |
emit_pop_code(emit); |
||
1198 |
return NULL; |
||
1199 |
} |
||
1200 |
|||
1201 |
26 |
ANN void spork_code(const Emitter emit, const struct Sporker *sp) { |
|
1202 |
26 |
const Instr args = emit_add_instr(emit, SporkExp); |
|
1203 |
26 |
args->m_val = emit->code->stack_depth; |
|
1204 |
26 |
const Instr instr = emit_add_instr(emit, SporkEnd); |
|
1205 |
26 |
instr->m_val = sp->emit_var; |
|
1206 |
26 |
} |
|
1207 |
|||
1208 |
27 |
ANN void spork_func(const Emitter emit, const struct Sporker *sp) { |
|
1209 |
27 |
const Func f = sp->exp->d.exp_call.m_func; |
|
1210 |
✓✓✓✓ |
30 |
if(GET_FLAG(f, member) && is_fptr(emit->gwion, f->value_ref->type)) { |
1211 |
3 |
regpush(emit, SZ_INT*2); |
|
1212 |
// (re-)emit owner |
||
1213 |
✓✓ | 3 |
if(sp->exp->d.exp_call.func->exp_type == ae_exp_dot) |
1214 |
1 |
emit_exp(emit, sp->exp->d.exp_call.func->d.exp_dot.base); |
|
1215 |
else { |
||
1216 |
assert(sp->exp->d.exp_call.func->exp_type == ae_exp_primary); |
||
1217 |
2 |
emit_add_instr(emit, RegPushMem); |
|
1218 |
} |
||
1219 |
3 |
regpop(emit, SZ_INT*3); |
|
1220 |
3 |
const m_uint depth = f->def->stack_depth; |
|
1221 |
3 |
regpop(emit, depth -SZ_INT); |
|
1222 |
3 |
const Instr spork = emit_add_instr(emit, SporkMemberFptr); |
|
1223 |
3 |
spork->m_val = depth; |
|
1224 |
} else |
||
1225 |
24 |
emit_exp_spork_finish(emit, f->def->stack_depth); |
|
1226 |
27 |
(void)emit_add_instr(emit, SporkEnd); |
|
1227 |
27 |
} |
|
1228 |
|||
1229 |
53 |
ANN static Instr spork_ini(const Emitter emit, const struct Sporker *sp) { |
|
1230 |
✓✓ | 53 |
if(sp->is_spork) { |
1231 |
45 |
const Instr instr = emit_add_instr(emit, SporkIni); |
|
1232 |
45 |
instr->m_val = (m_uint)sp->vm_code; |
|
1233 |
45 |
instr->m_val2 = sp->is_spork; |
|
1234 |
45 |
return instr; |
|
1235 |
} |
||
1236 |
8 |
regpushi(emit, (m_uint)sp->type); |
|
1237 |
✗✓ | 8 |
const Func f = !sp->code ? sp->exp->d.exp_call.m_func : NULL; |
1238 |
8 |
const Instr instr = emit_add_instr(emit, ForkIni); |
|
1239 |
8 |
instr->m_val = (m_uint)sp->vm_code; |
|
1240 |
✗✓ | 8 |
instr->m_val2 = f ? sp->type->size : 0; |
1241 |
8 |
return instr; |
|
1242 |
} |
||
1243 |
|||
1244 |
53 |
ANN Instr emit_exp_spork(const Emitter emit, const Exp_Unary* unary) { |
|
1245 |
318 |
struct Sporker sporker = { |
|
1246 |
53 |
.exp=unary->exp, |
|
1247 |
53 |
.code=unary->code, |
|
1248 |
53 |
.type=exp_self(unary)->info->type, |
|
1249 |
53 |
.is_spork=(unary->op == insert_symbol("spork")), |
|
1250 |
53 |
.emit_var=exp_getvar(exp_self(unary)) |
|
1251 |
}; |
||
1252 |
✗✓ | 53 |
CHECK_OO((sporker.vm_code = spork_prepare(emit, &sporker))) |
1253 |
53 |
const Instr ini = spork_ini(emit, &sporker); |
|
1254 |
✓✓ | 53 |
(unary->code ? spork_code : spork_func)(emit, &sporker); |
1255 |
53 |
return ini; |
|
1256 |
} |
||
1257 |
|||
1258 |
119 |
ANN static m_bool emit_exp_unary(const Emitter emit, const Exp_Unary* unary) { |
|
1259 |
119 |
const Type t = exp_self(unary)->info->type; |
|
1260 |
119 |
const Type base = get_type(actual_type(emit->gwion, t)); |
|
1261 |
✓✓✓✓ |
119 |
if(base->e->def && !GET_FLAG(base, emit)) |
1262 |
✗✓ | 1 |
CHECK_BB(ensure_emit(emit, base)) |
1263 |
// no pos ? |
||
1264 |
119 |
struct Op_Import opi = { .op=unary->op, .data=(uintptr_t)unary, .op_type=op_unary }; |
|
1265 |
✓✓✓✓ ✓✓ |
119 |
if(unary->op != insert_symbol("spork") && unary->op != insert_symbol("fork") && unary->exp) { |
1266 |
✗✓ | 47 |
CHECK_BB(emit_exp_pop_next(emit, unary->exp)) |
1267 |
47 |
emit_exp_addref1(emit, unary->exp, -exp_size(unary->exp)); |
|
1268 |
47 |
opi.rhs = unary->exp->info->type; |
|
1269 |
} |
||
1270 |
119 |
return op_emit_bool(emit, &opi); |
|
1271 |
} |
||
1272 |
|||
1273 |
40 |
ANN static m_bool emit_implicit_cast(const Emitter emit, |
|
1274 |
const restrict Exp from, const restrict Type to) { |
||
1275 |
40 |
const struct Implicit imp = { from, to, from->pos }; |
|
1276 |
// no pos |
||
1277 |
80 |
struct Op_Import opi = { .op=insert_symbol("@implicit"), .lhs=from->info->type, .rhs=to, |
|
1278 |
40 |
.data=(m_uint)&imp, .op_type=op_implicit }; |
|
1279 |
40 |
return op_emit_bool(emit, &opi); |
|
1280 |
} |
||
1281 |
|||
1282 |
87 |
ANN static Instr _flow(const Emitter emit, const Exp e, const m_bool b) { |
|
1283 |
✗✓ | 87 |
CHECK_BO(emit_exp_pop_next(emit, e)) |
1284 |
87 |
emit_exp_addref1(emit, e, -exp_size(e)); |
|
1285 |
✓✓ | 348 |
struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"), |
1286 |
261 |
.rhs=e->info->type, .pos=e->pos, .data=(uintptr_t)e, .op_type=op_exp }; |
|
1287 |
87 |
const Instr instr = op_emit(emit, &opi); |
|
1288 |
assert(instr != (Instr)GW_OK); |
||
1289 |
87 |
return instr; |
|
1290 |
} |
||
1291 |
#define emit_flow(emit,b) _flow(emit, b, 1) |
||
1292 |
|||
1293 |
7 |
ANN static m_bool emit_exp_if(const Emitter emit, const Exp_If* exp_if) { |
|
1294 |
✗✓ | 7 |
DECL_OB(const Instr, op, = emit_flow(emit, exp_if->cond)) |
1295 |
✓✓✗✓ |
7 |
CHECK_BB(emit_exp_pop_next(emit, exp_if->if_exp ?: exp_if->cond)) |
1296 |
7 |
const Instr op2 = emit_add_instr(emit, Goto); |
|
1297 |
7 |
op->m_val = emit_code_size(emit); |
|
1298 |
7 |
const m_bool ret = emit_exp_pop_next(emit, exp_if->else_exp); |
|
1299 |
7 |
op2->m_val = emit_code_size(emit); |
|
1300 |
7 |
return ret; |
|
1301 |
} |
||
1302 |
|||
1303 |
13 |
ANN static m_bool emit_lambda(const Emitter emit, const Exp_Lambda * lambda) { |
|
1304 |
✗✓ | 13 |
CHECK_BB(emit_func_def(emit, lambda->def)) |
1305 |
✓✓✓✓ |
13 |
if(GET_FLAG(lambda->def, member) && !exp_getvar(exp_self(lambda))) |
1306 |
7 |
emit_add_instr(emit, RegPushMem); |
|
1307 |
13 |
regpushi(emit, (m_uint)lambda->def->base->func->code); |
|
1308 |
13 |
return GW_OK; |
|
1309 |
} |
||
1310 |
|||
1311 |
14 |
ANN static m_bool emit_exp_lambda(const Emitter emit, const Exp_Lambda * lambda) { |
|
1312 |
✓✓ | 14 |
if(!lambda->def->base->func) { |
1313 |
1 |
regpushi(emit, SZ_INT); |
|
1314 |
1 |
return GW_OK; |
|
1315 |
} |
||
1316 |
26 |
struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef, |
|
1317 |
13 |
.scope=emit->env->scope->depth, .flag=ae_flag_emit }; |
|
1318 |
✗✓ | 13 |
CHECK_BB(envset_push(&es, lambda->owner, lambda->def->base->func->value_ref->from->owner)) |
1319 |
13 |
const m_bool ret = emit_lambda(emit, lambda); |
|
1320 |
✓✓ | 13 |
if(es.run) |
1321 |
5 |
envset_pop(&es, lambda->owner); |
|
1322 |
13 |
return ret; |
|
1323 |
} |
||
1324 |
|||
1325 |
DECL_EXP_FUNC(emit, m_bool, Emitter) |
||
1326 |
|||
1327 |
|||
1328 |
1 |
ANN static void struct_addref(const Emitter emit, const Type type, |
|
1329 |
const m_int size, const m_bool offset, const m_bool emit_var) { |
||
1330 |
✓✗ | 1 |
if(!type->e->tuple) |
1331 |
1 |
return; |
|
1332 |
for(m_uint i = 0; i < vector_size(&type->e->tuple->types); ++i) { |
||
1333 |
const Type t = (Type)vector_at(&type->e->tuple->types, i); |
||
1334 |
if(isa(t, emit->gwion->type[et_object]) > 0) { |
||
1335 |
const Instr instr = emit_addref(emit, emit_var); |
||
1336 |
instr->m_val = size; |
||
1337 |
instr->m_val2 = vector_at(&type->e->tuple->offset, i); |
||
1338 |
} else if(GET_FLAG(t, struct)) |
||
1339 |
struct_addref(emit, t, size, offset + vector_at(&type->e->tuple->offset, i), emit_var); |
||
1340 |
} |
||
1341 |
} |
||
1342 |
|||
1343 |
1901 |
ANN static inline m_uint exp_size(const Exp e) { |
|
1344 |
✓✓ | 1901 |
if(exp_getvar(e)) |
1345 |
354 |
return SZ_INT; |
|
1346 |
✓✓ | 1547 |
const Type type = e->info->cast_to ?: e->info->type; |
1347 |
1547 |
return type->size; |
|
1348 |
} |
||
1349 |
|||
1350 |
1518 |
ANN2(1) static void emit_exp_addref1(const Emitter emit, /* const */Exp exp, m_int size) { |
|
1351 |
✓✓✓✓ ✓✓ |
1778 |
if(isa(exp->info->type, emit->gwion->type[et_object]) > 0 && |
1352 |
506 |
(exp->info->cast_to ? isa(exp->info->cast_to, emit->gwion->type[et_object]) > 0 : 1)) { |
|
1353 |
246 |
const Instr instr = emit_addref(emit, exp_getvar(exp)); |
|
1354 |
246 |
instr->m_val = size; |
|
1355 |
✓✓ | 1272 |
} else if(GET_FLAG(exp->info->type, struct)) // check cast_to ? |
1356 |
1 |
struct_addref(emit, exp->info->type, size, 0, exp_getvar(exp)); |
|
1357 |
1518 |
} |
|
1358 |
|||
1359 |
383 |
ANN2(1) static void emit_exp_addref(const Emitter emit, /* const */Exp exp, m_int size) { |
|
1360 |
do { |
||
1361 |
383 |
emit_exp_addref1(emit, exp, size); |
|
1362 |
383 |
size += exp_size(exp); |
|
1363 |
✓✓ | 383 |
} while((exp = exp->next)); |
1364 |
277 |
} |
|
1365 |
|||
1366 |
5720 |
ANN2(1) /*static */m_bool emit_exp(const Emitter emit, /* const */Exp e) { |
|
1367 |
5720 |
Exp exp = e; |
|
1368 |
do { |
||
1369 |
✓✓ | 5887 |
CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d)) |
1370 |
✓✓ | 5883 |
if(exp_getnonnull(exp)) |
1371 |
91 |
emit_except(emit, exp->info->type); |
|
1372 |
✓✓ | 5883 |
if(exp->info->cast_to) |
1373 |
✗✓ | 40 |
CHECK_BB(emit_implicit_cast(emit, exp, exp->info->cast_to)) |
1374 |
✓✓ | 5883 |
} while((exp = exp->next)); |
1375 |
5716 |
return GW_OK; |
|
1376 |
} |
||
1377 |
|||
1378 |
40 |
ANN static m_bool emit_if(const Emitter emit, const Stmt_If stmt) { |
|
1379 |
✗✓ | 40 |
DECL_OB(const Instr, op, = emit_flow(emit, stmt->cond)) |
1380 |
✗✓ | 40 |
CHECK_BB(scoped_stmt(emit, stmt->if_body, 1)) |
1381 |
40 |
const Instr op2 = emit_add_instr(emit, Goto); |
|
1382 |
40 |
op->m_val = emit_code_size(emit); |
|
1383 |
✓✓ | 40 |
if(stmt->else_body) |
1384 |
✗✓ | 12 |
CHECK_BB(scoped_stmt(emit, stmt->else_body, 1)) |
1385 |
40 |
op2->m_val = emit_code_size(emit); |
|
1386 |
40 |
return GW_OK; |
|
1387 |
} |
||
1388 |
|||
1389 |
40 |
ANN static m_bool emit_stmt_if(const Emitter emit, const Stmt_If stmt) { |
|
1390 |
40 |
emit_push_scope(emit); |
|
1391 |
40 |
const m_bool ret = emit_if(emit, stmt); |
|
1392 |
40 |
emit_pop_scope(emit); |
|
1393 |
40 |
return ret; |
|
1394 |
} |
||
1395 |
|||
1396 |
395 |
ANN static m_bool emit_stmt_code(const Emitter emit, const Stmt_Code stmt) { |
|
1397 |
395 |
++emit->env->scope->depth; |
|
1398 |
✓✓ | 395 |
const m_bool ret = stmt->stmt_list ? emit_stmt_list(emit, stmt->stmt_list) : 1; |
1399 |
395 |
--emit->env->scope->depth; |
|
1400 |
395 |
return ret; |
|
1401 |
} |
||
1402 |
|||
1403 |
1 |
ANN static m_bool optimize_taill_call(const Emitter emit, const Exp_Call* e) { |
|
1404 |
✓✗ | 1 |
if(e->args) { |
1405 |
1 |
emit_func_args(emit, e); |
|
1406 |
1 |
regpop(emit, e->m_func->def->stack_depth); |
|
1407 |
1 |
emit_args(emit, e->m_func); |
|
1408 |
} |
||
1409 |
1 |
emit_add_instr(emit, Goto); |
|
1410 |
1 |
return GW_OK; |
|
1411 |
} |
||
1412 |
|||
1413 |
58 |
ANN static m_bool emit_stmt_return(const Emitter emit, const Stmt_Exp stmt) { |
|
1414 |
✓✓ | 58 |
if(stmt->val) { |
1415 |
✓✓✓✗ |
56 |
if(stmt->val->exp_type == ae_exp_call && emit->env->func == stmt->val->d.exp_call.m_func) |
1416 |
1 |
return optimize_taill_call(emit, &stmt->val->d.exp_call); |
|
1417 |
✗✓ | 55 |
CHECK_BB(emit_exp_pop_next(emit, stmt->val)) |
1418 |
} |
||
1419 |
57 |
vector_add(&emit->code->stack_return, (vtype)emit_add_instr(emit, Goto)); |
|
1420 |
57 |
return GW_OK; |
|
1421 |
} |
||
1422 |
|||
1423 |
9 |
ANN static inline m_bool emit_stmt_continue(const Emitter emit, const Stmt stmt NUSED) { |
|
1424 |
9 |
vector_add(&emit->code->stack_cont, (vtype)emit_add_instr(emit, Goto)); |
|
1425 |
9 |
return GW_OK; |
|
1426 |
} |
||
1427 |
|||
1428 |
8 |
ANN static inline m_bool emit_stmt_break(const Emitter emit, const Stmt stmt NUSED) { |
|
1429 |
8 |
vector_add(&emit->code->stack_break, (vtype)emit_add_instr(emit, Goto)); |
|
1430 |
8 |
return GW_OK; |
|
1431 |
} |
||
1432 |
|||
1433 |
53 |
ANN static inline void emit_push_stack(const Emitter emit) { |
|
1434 |
53 |
emit_push_scope(emit); |
|
1435 |
53 |
vector_add(&emit->code->stack_cont, (vtype)NULL); |
|
1436 |
53 |
vector_add(&emit->code->stack_break, (vtype)NULL); |
|
1437 |
53 |
} |
|
1438 |
|||
1439 |
106 |
ANN static void pop_vector(Vector v, const m_uint pc) { |
|
1440 |
Instr instr; |
||
1441 |
✓✓ | 229 |
while((instr = (Instr)vector_pop(v))) |
1442 |
17 |
instr->m_val = pc; |
|
1443 |
106 |
} |
|
1444 |
|||
1445 |
53 |
ANN static void emit_pop_stack(const Emitter emit, const m_uint index) { |
|
1446 |
53 |
pop_vector(&emit->code->stack_cont, index); |
|
1447 |
53 |
pop_vector(&emit->code->stack_break, emit_code_size(emit)); |
|
1448 |
53 |
emit_pop_scope(emit); |
|
1449 |
53 |
} |
|
1450 |
|||
1451 |
26 |
ANN static m_bool _emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt, const m_uint index) { |
|
1452 |
26 |
Instr op = NULL; |
|
1453 |
✓✓ | 26 |
if(!stmt->is_do) |
1454 |
12 |
op = _flow(emit, stmt->cond, stmt_self(stmt)->stmt_type == ae_stmt_while); |
|
1455 |
✗✓ | 26 |
CHECK_BB(scoped_stmt(emit, stmt->body, 1)) |
1456 |
✓✓ | 26 |
if(stmt->is_do) { |
1457 |
✗✓ | 14 |
CHECK_OB((op = _flow(emit, stmt->cond, stmt_self(stmt)->stmt_type != ae_stmt_while))) |
1458 |
14 |
op->m_val = index; |
|
1459 |
} else { |
||
1460 |
12 |
const Instr goto_ = emit_add_instr(emit, Goto); |
|
1461 |
12 |
goto_->m_val = index; |
|
1462 |
12 |
op->m_val = emit_code_size(emit); |
|
1463 |
} |
||
1464 |
26 |
return GW_OK; |
|
1465 |
} |
||
1466 |
|||
1467 |
26 |
ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) { |
|
1468 |
26 |
const m_uint index = emit_code_size(emit); |
|
1469 |
26 |
emit_push_stack(emit); |
|
1470 |
26 |
const m_bool ret = _emit_stmt_flow(emit, stmt, index); |
|
1471 |
26 |
emit_pop_stack(emit, index); |
|
1472 |
26 |
return ret; |
|
1473 |
} |
||
1474 |
|||
1475 |
18 |
ANN static m_bool variadic_state(const Emitter emit, const Stmt_VarLoop stmt, const m_uint status) { |
|
1476 |
18 |
regpushi(emit, status); |
|
1477 |
✗✓ | 18 |
CHECK_BB(emit_exp(emit, stmt->exp)) |
1478 |
18 |
const Instr member = emit_add_instr(emit, DotMember4); |
|
1479 |
18 |
member->m_val = SZ_INT; |
|
1480 |
18 |
emit_add_instr(emit, int_r_assign); |
|
1481 |
18 |
regpop(emit, SZ_INT); |
|
1482 |
18 |
return GW_OK; |
|
1483 |
} |
||
1484 |
|||
1485 |
9 |
ANN static m_bool emit_stmt_varloop(const Emitter emit, const Stmt_VarLoop stmt) { |
|
1486 |
✗✓ | 9 |
CHECK_BB(variadic_state(emit, stmt, 1)) |
1487 |
✗✓ | 9 |
CHECK_BB(emit_exp(emit, stmt->exp)) |
1488 |
9 |
const Instr check = emit_add_instr(emit, VarargCheck); |
|
1489 |
9 |
const Instr member = emit_add_instr(emit, DotMember4); |
|
1490 |
9 |
member->m_val = SZ_INT*2; |
|
1491 |
9 |
const Instr instr = emit_add_instr(emit, BranchEqInt); |
|
1492 |
9 |
const m_uint pc = emit_code_size(emit); |
|
1493 |
9 |
emit_stmt(emit, stmt->body, 1); |
|
1494 |
✗✓ | 9 |
CHECK_BB(emit_exp(emit, stmt->exp)) |
1495 |
9 |
emit_vararg_end(emit, pc); |
|
1496 |
✗✓ | 9 |
CHECK_BB(variadic_state(emit, stmt, 0)) |
1497 |
9 |
check->m_val = instr->m_val = emit_code_size(emit); |
|
1498 |
9 |
return GW_OK; |
|
1499 |
} |
||
1500 |
|||
1501 |
10 |
ANN static m_bool _emit_stmt_for(const Emitter emit, const Stmt_For stmt, m_uint *action_index) { |
|
1502 |
✗✓ | 10 |
CHECK_BB(emit_stmt(emit, stmt->c1, 1)) |
1503 |
10 |
const m_uint index = emit_code_size(emit); |
|
1504 |
✗✓ | 10 |
DECL_OB(const Instr, op, = emit_flow(emit, stmt->c2->d.stmt_exp.val)) |
1505 |
✗✓ | 10 |
CHECK_BB(scoped_stmt(emit, stmt->body, 1)) |
1506 |
10 |
*action_index = emit_code_size(emit); |
|
1507 |
✓✓ | 10 |
if(stmt->c3) { |
1508 |
✗✓ | 9 |
CHECK_BB(emit_exp(emit, stmt->c3)) |
1509 |
9 |
pop_exp(emit, stmt->c3); |
|
1510 |
} |
||
1511 |
10 |
const Instr _goto = emit_add_instr(emit, Goto); |
|
1512 |
10 |
_goto->m_val = index; |
|
1513 |
10 |
op->m_val = emit_code_size(emit); |
|
1514 |
10 |
return GW_OK; |
|
1515 |
} |
||
1516 |
|||
1517 |
10 |
ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) { |
|
1518 |
10 |
emit_push_stack(emit); |
|
1519 |
10 |
m_uint action_index = 0; |
|
1520 |
10 |
const m_bool ret = _emit_stmt_for(emit, stmt, &action_index); |
|
1521 |
10 |
emit_pop_stack(emit, action_index); |
|
1522 |
10 |
return ret; |
|
1523 |
} |
||
1524 |
|||
1525 |
4 |
ANN static Instr emit_stmt_autoptr_init(const Emitter emit, const Type type) { |
|
1526 |
4 |
const Instr new_obj = emit_add_instr(emit, ObjectInstantiate); |
|
1527 |
4 |
new_obj->m_val2 = (m_uint)type; |
|
1528 |
4 |
(void)emit_addref(emit, 0); |
|
1529 |
4 |
regpop(emit, SZ_INT); |
|
1530 |
4 |
return emit_add_instr(emit, Reg2Mem); |
|
1531 |
} |
||
1532 |
|||
1533 |
10 |
ANN static m_bool _emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt, m_uint *end_pc) { |
|
1534 |
10 |
const Instr s1 = emit_add_instr(emit, MemSetImm); |
|
1535 |
✓✓ | 10 |
Instr cpy = stmt->is_ptr ? emit_stmt_autoptr_init(emit, stmt->v->type) : NULL; |
1536 |
10 |
emit_local(emit, emit->gwion->type[et_int]); |
|
1537 |
10 |
const m_uint offset = emit_local(emit, emit->gwion->type[et_int]); |
|
1538 |
10 |
emit_local(emit, emit->gwion->type[et_int]); |
|
1539 |
10 |
stmt->v->from->offset = offset + SZ_INT; |
|
1540 |
10 |
const m_uint ini_pc = emit_code_size(emit); |
|
1541 |
10 |
emit_except(emit, stmt->exp->info->type); |
|
1542 |
✓✓ | 10 |
const Instr loop = emit_add_instr(emit, stmt->is_ptr ? AutoLoopPtr : AutoLoop); |
1543 |
10 |
const Instr end = emit_add_instr(emit, BranchEqInt); |
|
1544 |
10 |
const m_bool ret = scoped_stmt(emit, stmt->body, 1); |
|
1545 |
10 |
*end_pc = emit_code_size(emit); |
|
1546 |
✓✓ | 10 |
if(stmt->is_ptr) { |
1547 |
4 |
loop->m_val2 = (m_uint)stmt->v->type; |
|
1548 |
4 |
cpy->m_val = stmt->v->from->offset; |
|
1549 |
} |
||
1550 |
10 |
const Instr tgt = emit_add_instr(emit, Goto); |
|
1551 |
10 |
end->m_val = emit_code_size(emit); |
|
1552 |
10 |
tgt->m_val = ini_pc; |
|
1553 |
10 |
s1->m_val = loop->m_val = offset; |
|
1554 |
10 |
return ret; |
|
1555 |
} |
||
1556 |
|||
1557 |
10 |
ANN static m_bool emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt) { |
|
1558 |
✗✓ | 10 |
CHECK_BB(emit_exp(emit, stmt->exp)) |
1559 |
10 |
emit_push_stack(emit); |
|
1560 |
10 |
m_uint end_pc = 0; |
|
1561 |
10 |
const m_bool ret = _emit_stmt_auto(emit, stmt, &end_pc); |
|
1562 |
10 |
emit_pop_stack(emit, end_pc); |
|
1563 |
10 |
regpop(emit, SZ_INT); |
|
1564 |
10 |
return ret; |
|
1565 |
} |
||
1566 |
|||
1567 |
7 |
ANN static m_bool _emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt, m_uint *index) { |
|
1568 |
✗✓ | 7 |
CHECK_BB(emit_exp_pop_next(emit, stmt->cond)) |
1569 |
7 |
const m_uint offset = emit_local(emit, emit->gwion->type[et_int]); |
|
1570 |
7 |
const Instr tomem = emit_add_instr(emit, Reg2Mem); |
|
1571 |
7 |
tomem->m_val = offset; |
|
1572 |
7 |
tomem->m_val2 = -SZ_INT; |
|
1573 |
7 |
regpop(emit, SZ_INT); |
|
1574 |
7 |
*index = emit_code_size(emit); |
|
1575 |
7 |
const Instr cpy = emit_add_instr(emit, RegPushMem4); |
|
1576 |
7 |
cpy->m_val = offset; |
|
1577 |
7 |
emit_add_instr(emit, int_post_dec); |
|
1578 |
7 |
const Instr op = emit_add_instr(emit, BranchEqInt); |
|
1579 |
✗✓ | 7 |
CHECK_BB(scoped_stmt(emit, stmt->body, 1)) |
1580 |
7 |
const Instr _goto = emit_add_instr(emit, Goto); |
|
1581 |
7 |
_goto->m_val = *index; |
|
1582 |
7 |
op->m_val = emit_code_size(emit); |
|
1583 |
7 |
return GW_OK; |
|
1584 |
} |
||
1585 |
|||
1586 |
7 |
ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) { |
|
1587 |
7 |
emit_push_stack(emit); |
|
1588 |
7 |
m_uint index = 0; |
|
1589 |
7 |
const m_bool ret = _emit_stmt_loop(emit, stmt, &index); |
|
1590 |
7 |
emit_pop_stack(emit, index); |
|
1591 |
7 |
return ret; |
|
1592 |
} |
||
1593 |
|||
1594 |
8 |
ANN static m_bool emit_stmt_jump(const Emitter emit, const Stmt_Jump stmt) { |
|
1595 |
✓✓ | 8 |
if(!stmt->is_label) |
1596 |
3 |
stmt->data.instr = emit_add_instr(emit, Goto); |
|
1597 |
else { |
||
1598 |
assert(stmt->data.v.ptr); |
||
1599 |
5 |
const m_uint size = vector_size(&stmt->data.v); |
|
1600 |
✓✓ | 5 |
if(!size) |
1601 |
//return GW_OK; |
||
1602 |
1 |
ERR_B(stmt_self(stmt)->pos, _("label '%s' defined but not used."), s_name(stmt->name)) |
|
1603 |
LOOP_OPTIM |
||
1604 |
✓✓ | 11 |
for(m_uint i = size + 1; --i;) { |
1605 |
4 |
const Stmt_Jump label = (Stmt_Jump)vector_at(&stmt->data.v, i - 1); |
|
1606 |
✓✓ | 4 |
if(!label->data.instr) |
1607 |
1 |
ERR_B(stmt_self(label)->pos, _("you are trying to use a upper label.")) |
|
1608 |
3 |
label->data.instr->m_val = emit_code_size(emit); |
|
1609 |
} |
||
1610 |
} |
||
1611 |
6 |
return GW_OK; |
|
1612 |
} |
||
1613 |
|||
1614 |
14 |
ANN static m_bool emit_type_def(const Emitter emit, const Type_Def tdef) { |
|
1615 |
✓✓ | 14 |
return tdef->type->e->def ? emit_class_def(emit, tdef->type->e->def) : GW_OK; |
1616 |
} |
||
1617 |
|||
1618 |
5 |
ANN static m_bool emit_enum_def(const Emitter emit, const Enum_Def edef) { |
|
1619 |
LOOP_OPTIM |
||
1620 |
✓✓ | 18 |
for(m_uint i = 0; i < vector_size(&edef->values); ++i) { |
1621 |
13 |
const Value v = (Value)vector_at(&edef->values, i); |
|
1622 |
✓✓ | 13 |
if(!emit->env->class_def) { |
1623 |
7 |
ALLOC_PTR(emit->gwion->mp, addr, m_uint, i); |
|
1624 |
7 |
v->from->offset = emit_local(emit, emit->gwion->type[et_int]); |
|
1625 |
7 |
v->d.ptr = addr; |
|
1626 |
} else |
||
1627 |
6 |
*(m_bit*)(emit->env->class_def->nspc->info->class_data + v->from->offset) = i; |
|
1628 |
} |
||
1629 |
5 |
return GW_OK; |
|
1630 |
} |
||
1631 |
|||
1632 |
34 |
ANN void emit_union_offset(Decl_List l, const m_uint o) { |
|
1633 |
do { |
||
1634 |
34 |
Var_Decl_List v = l->self->d.exp_decl.list; |
|
1635 |
34 |
do v->self->value->from->offset = o; |
|
1636 |
✗✓ | 34 |
while((v = v->next)); |
1637 |
✓✓ | 34 |
} while((l = l->next)); |
1638 |
18 |
} |
|
1639 |
|||
1640 |
10 |
ANN static inline void union_allocdata(MemPool mp, const Union_Def udef) { |
|
1641 |
✓✓ | 10 |
const Nspc nspc = (udef->xid ? udef->value->type : udef->type)->nspc; |
1642 |
10 |
nspc_allocdata(mp, nspc); |
|
1643 |
10 |
nspc->info->offset = udef->s; |
|
1644 |
10 |
} |
|
1645 |
|||
1646 |
18 |
ANN static m_bool emit_union_def(const Emitter emit, const Union_Def udef) { |
|
1647 |
✓✓ | 18 |
if(tmpl_base(udef->tmpl)) |
1648 |
3 |
return GW_OK; |
|
1649 |
15 |
Decl_List l = udef->l; |
|
1650 |
15 |
m_uint scope = emit->env->scope->depth; |
|
1651 |
15 |
const m_bool global = GET_FLAG(udef, global); |
|
1652 |
✓✓ | 15 |
if(udef->xid) { |
1653 |
6 |
union_allocdata(emit->gwion->mp, udef); |
|
1654 |
12 |
Type_Decl *type_decl = new_type_decl(emit->gwion->mp, |
|
1655 |
6 |
udef->xid, loc_cpy(emit->gwion->mp, udef->pos)); |
|
1656 |
6 |
type_decl->flag = udef->flag; |
|
1657 |
6 |
const Var_Decl var_decl = new_var_decl(emit->gwion->mp, udef->xid, NULL, loc_cpy(emit->gwion->mp, udef->pos)); |
|
1658 |
6 |
const Var_Decl_List var_decl_list = new_var_decl_list(emit->gwion->mp, var_decl, NULL); |
|
1659 |
6 |
const Exp exp = new_exp_decl(emit->gwion->mp, type_decl, var_decl_list); |
|
1660 |
6 |
exp->d.exp_decl.type = udef->value->type; |
|
1661 |
6 |
var_decl->value = udef->value; |
|
1662 |
6 |
const m_bool ret = emit_exp_decl(emit, &exp->d.exp_decl); |
|
1663 |
6 |
free_exp(emit->gwion->mp, exp); |
|
1664 |
✗✓ | 6 |
CHECK_BB(ret) |
1665 |
✓✓ | 6 |
if(global) { |
1666 |
1 |
const M_Object o = new_object(emit->gwion->mp, NULL, udef->value->type); |
|
1667 |
1 |
udef->value->d.ptr = (m_uint*)o; |
|
1668 |
1 |
SET_FLAG(udef->value, builtin); |
|
1669 |
1 |
UNSET_FLAG(udef->value, union); |
|
1670 |
} |
||
1671 |
6 |
scope = emit_push_type(emit, udef->value->type); |
|
1672 |
✓✓ | 9 |
} else if(udef->type_xid) { |
1673 |
4 |
union_allocdata(emit->gwion->mp, udef); |
|
1674 |
4 |
scope = emit_push_type(emit, udef->type); |
|
1675 |
✓✓ | 5 |
} else if(global) { |
1676 |
// TODO: use mpool allocation |
||
1677 |
1 |
void* ptr = (void*)xcalloc(1, udef->s); |
|
1678 |
1 |
l = udef->l; |
|
1679 |
1 |
udef->value->d.ptr = ptr; |
|
1680 |
1 |
SET_FLAG(udef->value, enum); |
|
1681 |
1 |
SET_FLAG(udef->value, dtor); |
|
1682 |
do { |
||
1683 |
2 |
Var_Decl_List list = l->self->d.exp_decl.list; |
|
1684 |
2 |
list->self->value->d.ptr = ptr; |
|
1685 |
2 |
SET_FLAG(list->self->value, union); |
|
1686 |
✓✓ | 2 |
} while((l = l->next)); |
1687 |
1 |
SET_FLAG(udef->l->self->d.exp_decl.list->self->value, enum); |
|
1688 |
1 |
SET_FLAG(udef->l->self->d.exp_decl.list->self->value, dtor); |
|
1689 |
} |
||
1690 |
✓✓ | 15 |
if(udef->xid) |
1691 |
6 |
regpop(emit, SZ_INT); |
|
1692 |
15 |
emit_union_offset(udef->l, udef->o); |
|
1693 |
✓✓✓✓ ✓✓ |
15 |
if(udef->xid || udef->type_xid || global) |
1694 |
11 |
emit_pop(emit, scope); |
|
1695 |
15 |
union_flag(udef, ae_flag_emit); |
|
1696 |
15 |
return GW_OK; |
|
1697 |
} |
||
1698 |
|||
1699 |
2003 |
ANN static m_bool emit_stmt_exp(const Emitter emit, const struct Stmt_Exp_* exp) { |
|
1700 |
✓✓ | 2003 |
return exp->val ? emit_exp(emit, exp->val) : GW_OK; |
1701 |
} |
||
1702 |
|||
1703 |
7 |
ANN static m_bool emit_case_head(const Emitter emit, const Exp base, |
|
1704 |
const Exp e, const Symbol op, const Vector v) { |
||
1705 |
✗✓ | 7 |
CHECK_BB(emit_exp(emit, base)) |
1706 |
✗✓ | 7 |
CHECK_BB(emit_exp_pop_next(emit, e)) |
1707 |
7 |
const m_int size = -exp_size(e); |
|
1708 |
7 |
emit_exp_addref(emit, base, -exp_totalsize(base) - size); |
|
1709 |
7 |
emit_exp_addref1(emit, e, -size); |
|
1710 |
7 |
const Exp_Binary bin = { .lhs=base, .rhs=e, .op=op }; |
|
1711 |
7 |
struct ExpInfo_ info = { .nspc=e->info->nspc }; |
|
1712 |
7 |
struct Exp_ ebin = { .d={.exp_binary=bin}, .info=&info }; |
|
1713 |
21 |
struct Op_Import opi = { .op=op, .lhs=base->info->type, .rhs=e->info->type, |
|
1714 |
14 |
.data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos, .op_type=op_binary }; |
|
1715 |
✗✓ | 7 |
CHECK_BB(op_emit_bool(emit, &opi)) |
1716 |
7 |
const Instr instr = emit_add_instr(emit, BranchEqInt); |
|
1717 |
7 |
vector_add(v, (vtype)instr); |
|
1718 |
7 |
return GW_OK; |
|
1719 |
} |
||
1720 |
|||
1721 |
10 |
ANN static m_bool emit_case_body(const Emitter emit, const struct Stmt_Match_* stmt) { |
|
1722 |
✓✓ | 10 |
const Instr when = stmt->when ? emit_flow(emit, stmt->when) : NULL; |
1723 |
✓✓ | 10 |
if(stmt->when) |
1724 |
✗✓ | 4 |
CHECK_OB(when) |
1725 |
✗✓ | 10 |
CHECK_BB(emit_stmt_list(emit, stmt->list)) |
1726 |
10 |
const Instr instr = emit_add_instr(emit, Goto); |
|
1727 |
10 |
vector_add(&emit->env->scope->match->vec, (vtype)instr); |
|
1728 |
✓✓ | 10 |
if(when) |
1729 |
4 |
when->m_val = emit_code_size(emit); |
|
1730 |
10 |
return GW_OK; |
|
1731 |
} |
||
1732 |
|||
1733 |
1 |
ANN static m_bool case_value(const Emitter emit, const Exp base, const Exp e) { |
|
1734 |
1 |
const Value v = e->d.prim.value; |
|
1735 |
1 |
v->from->offset = emit_local(emit, base->info->type); |
|
1736 |
✗✓ | 1 |
CHECK_BB(emit_exp(emit, base)) |
1737 |
1 |
emit_exp_addref(emit, base, -exp_totalsize(base)); |
|
1738 |
1 |
regpop(emit, base->info->type->size); |
|
1739 |
1 |
const Instr instr = emit_add_instr(emit, Reg2Mem4); |
|
1740 |
1 |
instr->m_val = v->from->offset; |
|
1741 |
1 |
instr->m_val2 = base->info->type->size; |
|
1742 |
1 |
return GW_OK; |
|
1743 |
} |
||
1744 |
|||
1745 |
|||
1746 |
#define CASE_PASS (Symbol)1 |
||
1747 |
10 |
ANN static Symbol case_op(const Emitter emit, const Exp base, const Exp e) { |
|
1748 |
✓✗ | 10 |
if(e->exp_type == ae_exp_primary) { |
1749 |
✓✓ | 10 |
if(e->d.prim.prim_type == ae_prim_id) { |
1750 |
✓✓ | 3 |
if(e->d.prim.d.var == insert_symbol("_")) |
1751 |
2 |
return CASE_PASS; |
|
1752 |
✓✗ | 1 |
if(!nspc_lookup_value1(emit->env->curr, e->d.prim.d.var)) { |
1753 |
✗✓ | 1 |
CHECK_BO(case_value(emit, base, e)) |
1754 |
1 |
return CASE_PASS; |
|
1755 |
} |
||
1756 |
} |
||
1757 |
} |
||
1758 |
7 |
return insert_symbol("=="); |
|
1759 |
} |
||
1760 |
|||
1761 |
10 |
ANN static m_bool _emit_stmt_match_case(const Emitter emit, const struct Stmt_Match_* stmt, |
|
1762 |
const Vector v) { |
||
1763 |
10 |
Exp e = stmt->cond; |
|
1764 |
10 |
const Map map = &emit->env->scope->match->map; |
|
1765 |
✓✓✓✗ |
20 |
for(m_uint i = 0; i < map_size(map) && e; e = e->next, ++i) { |
1766 |
10 |
const Exp base = (Exp)VKEY(map, i); |
|
1767 |
10 |
const Symbol op = case_op(emit, base, e); |
|
1768 |
✓✓ | 10 |
if(op != CASE_PASS) |
1769 |
✗✓ | 7 |
CHECK_BB(emit_case_head(emit, base, e, op, v)) |
1770 |
} |
||
1771 |
✗✓ | 10 |
CHECK_BB(emit_case_body(emit, stmt)) |
1772 |
10 |
return GW_OK; |
|
1773 |
} |
||
1774 |
|||
1775 |
10 |
ANN static m_bool emit_stmt_match_case(const Emitter emit, const struct Stmt_Match_* stmt) { |
|
1776 |
10 |
emit_push_scope(emit); |
|
1777 |
struct Vector_ v; |
||
1778 |
10 |
vector_init(&v); |
|
1779 |
10 |
const m_bool ret = _emit_stmt_match_case(emit, stmt, &v); |
|
1780 |
10 |
emit_pop_scope(emit); |
|
1781 |
✓✓ | 17 |
for(m_uint i = 0; i < vector_size(&v); ++i) { |
1782 |
7 |
const Instr instr = (Instr)vector_at(&v, i); |
|
1783 |
7 |
instr->m_val = emit_code_size(emit); |
|
1784 |
} |
||
1785 |
10 |
vector_release(&v); |
|
1786 |
10 |
return ret; |
|
1787 |
} |
||
1788 |
|||
1789 |
6 |
ANN static inline void match_unvec(struct Match_ *const match , const m_uint pc) { |
|
1790 |
6 |
const Vector vec = &match->vec; |
|
1791 |
✓✓ | 16 |
for(m_uint i = 0; i < vector_size(vec); ++i) { |
1792 |
10 |
const Instr instr = (Instr)VPTR(vec, i); |
|
1793 |
10 |
instr->m_val = pc; |
|
1794 |
} |
||
1795 |
6 |
vector_release(vec); |
|
1796 |
6 |
} |
|
1797 |
|||
1798 |
10 |
ANN static m_bool emit_stmt_cases(const Emitter emit, Stmt_List list) { |
|
1799 |
✗✓ | 10 |
do CHECK_BB(emit_stmt_match_case(emit, &list->stmt->d.stmt_match)) |
1800 |
✓✓ | 10 |
while((list = list->next)); |
1801 |
6 |
return GW_OK; |
|
1802 |
} |
||
1803 |
|||
1804 |
6 |
ANN static m_bool emit_match(const Emitter emit, const struct Stmt_Match_* stmt) { |
|
1805 |
✓✓ | 6 |
if(stmt->where) |
1806 |
✗✓ | 2 |
CHECK_BB(emit_stmt(emit, stmt->where, 1)) |
1807 |
6 |
MATCH_INI(emit->env->scope) |
|
1808 |
6 |
vector_init(&m.vec); |
|
1809 |
6 |
const m_bool ret = emit_stmt_cases(emit, stmt->list); |
|
1810 |
6 |
match_unvec(&m, emit_code_size(emit)); |
|
1811 |
6 |
MATCH_END(emit->env->scope) |
|
1812 |
6 |
return ret; |
|
1813 |
} |
||
1814 |
|||
1815 |
6 |
ANN static m_bool emit_stmt_match(const Emitter emit, const struct Stmt_Match_* stmt) { |
|
1816 |
6 |
emit_push_scope(emit); |
|
1817 |
6 |
const m_bool ret = emit_match(emit, stmt); |
|
1818 |
6 |
emit_pop_scope(emit); |
|
1819 |
6 |
return ret; |
|
1820 |
} |
||
1821 |
|||
1822 |
1 |
ANN static m_bool emit_stmt_pp(const Emitter emit, const struct Stmt_PP_* stmt) { |
|
1823 |
✓✗ | 1 |
if(stmt->pp_type == ae_pp_pragma) { |
1824 |
✓✗ | 1 |
if(!strncmp(stmt->data, "memoize", strlen("memoize"))) |
1825 |
1 |
emit->info->memoize = strtol(stmt->data + 7, NULL, 10); |
|
1826 |
} |
||
1827 |
1 |
return GW_OK; |
|
1828 |
} |
||
1829 |
|||
1830 |
#define emit_stmt_while emit_stmt_flow |
||
1831 |
#define emit_stmt_until emit_stmt_flow |
||
1832 |
DECL_STMT_FUNC(emit, m_bool , Emitter) |
||
1833 |
|||
1834 |
2590 |
ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt, const m_bool pop) { |
|
1835 |
✓✓ | 2590 |
CHECK_BB(emit_stmt_func[stmt->stmt_type](emit, &stmt->d)) |
1836 |
✓✓✓✓ ✓✓ |
2586 |
if(pop && stmt->stmt_type == ae_stmt_exp && stmt->d.stmt_exp.val) { |
1837 |
1984 |
pop_exp(emit, stmt->d.stmt_exp.val); |
|
1838 |
} |
||
1839 |
2586 |
return GW_OK; |
|
1840 |
} |
||
1841 |
|||
1842 |
2197 |
ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List l) { |
|
1843 |
✓✓ | 2197 |
do CHECK_BB(emit_stmt(emit, l->stmt, 1)) |
1844 |
✓✓ | 2193 |
while((l = l->next)); |
1845 |
899 |
return GW_OK; |
|
1846 |
} |
||
1847 |
|||
1848 |
559 |
ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member) { |
|
1849 |
2236 |
struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base, |
|
1850 |
1677 |
.rhs=exp_self(member)->info->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos, .op_type=op_dot }; |
|
1851 |
559 |
return op_emit_bool(emit, &opi); |
|
1852 |
} |
||
1853 |
|||
1854 |
95 |
ANN static inline void emit_func_def_global(const Emitter emit, const Value value) { |
|
1855 |
95 |
const Instr set_mem = emit_add_instr(emit, MemSetImm); |
|
1856 |
95 |
set_mem->m_val = value->from->offset; |
|
1857 |
95 |
set_mem->m_val2 = (m_uint)value->d.func_ref->code; |
|
1858 |
95 |
} |
|
1859 |
|||
1860 |
241 |
ANN static void emit_func_def_init(const Emitter emit, const Func func) { |
|
1861 |
241 |
const Type t = emit->env->class_def; |
|
1862 |
✓✓ | 241 |
char c[(t ? strlen(t->name) + 1 : 0) + strlen(func->name) + 6]; |
1863 |
✓✓✓✓ |
241 |
sprintf(c, "%s%s%s(...)", t ? t->name : "", t ? "." : "", func->name); |
1864 |
241 |
emit_push_code(emit, c); |
|
1865 |
241 |
} |
|
1866 |
|||
1867 |
187 |
ANN static void emit_func_def_args(const Emitter emit, Arg_List a) { |
|
1868 |
do { |
||
1869 |
187 |
const Type type = a->var_decl->value->type; |
|
1870 |
187 |
emit->code->stack_depth += type->size; |
|
1871 |
187 |
a->var_decl->value->from->offset = emit_local(emit, type); |
|
1872 |
✓✓ | 187 |
} while((a = a->next)); |
1873 |
134 |
} |
|
1874 |
|||
1875 |
241 |
ANN static void emit_func_def_ensure(const Emitter emit, const Func_Def fdef) { |
|
1876 |
241 |
const m_uint size = fdef->base->ret_type->size; |
|
1877 |
✓✓ | 241 |
if(size) { |
1878 |
83 |
const Instr instr = emit_kind(emit, size, 0, regpushimm); |
|
1879 |
83 |
instr->m_val2 = size; |
|
1880 |
} |
||
1881 |
241 |
vector_add(&emit->code->stack_return, (vtype)emit_add_instr(emit, Goto)); |
|
1882 |
241 |
} |
|
1883 |
|||
1884 |
241 |
ANN static void emit_func_def_return(const Emitter emit) { |
|
1885 |
241 |
const m_uint val = emit_code_size(emit); |
|
1886 |
LOOP_OPTIM |
||
1887 |
✓✓ | 780 |
for(m_uint i = vector_size(&emit->code->stack_return) + 1; --i; ) { |
1888 |
298 |
const Instr instr = (Instr)vector_at(&emit->code->stack_return, i-1); |
|
1889 |
298 |
instr->m_val = val; |
|
1890 |
} |
||
1891 |
241 |
vector_clear(&emit->code->stack_return); |
|
1892 |
✓✓✓✗ |
241 |
if(emit->info->memoize && GET_FLAG(emit->env->func, pure)) { |
1893 |
1 |
const Instr instr = emit_add_instr(emit, MemoizeStore); |
|
1894 |
1 |
instr->m_val = emit->env->func->def->stack_depth; |
|
1895 |
} |
||
1896 |
241 |
} |
|
1897 |
|||
1898 |
11 |
ANN static VM_Code emit_internal(const Emitter emit, const Func f) { |
|
1899 |
✓✓ | 11 |
if(f->def->base->xid == insert_symbol("@dtor")) { |
1900 |
6 |
emit->env->class_def->nspc->dtor = f->code = finalyze(emit, DTOR_EOC); |
|
1901 |
6 |
ADD_REF(f->code) |
|
1902 |
6 |
return f->code; |
|
1903 |
✓✓ | 5 |
} else if(f->def->base->xid == insert_symbol("@gack")) { |
1904 |
2 |
regpop(emit, SZ_INT + f->value_ref->from->owner_class->size); |
|
1905 |
2 |
const Instr instr = emit_add_instr(emit, RegPushMem); |
|
1906 |
2 |
instr->m_val = SZ_INT; |
|
1907 |
2 |
f->code = finalyze(emit, FuncReturn); |
|
1908 |
2 |
return emit->env->class_def->e->gack = f->code; |
|
1909 |
} |
||
1910 |
3 |
return finalyze(emit, FuncReturn); |
|
1911 |
} |
||
1912 |
|||
1913 |
241 |
ANN static VM_Code emit_func_def_code(const Emitter emit, const Func func) { |
|
1914 |
✓✓ | 241 |
if(GET_FLAG(func->def, typedef)) |
1915 |
11 |
return emit_internal(emit, func); |
|
1916 |
else |
||
1917 |
230 |
return finalyze(emit, FuncReturn); |
|
1918 |
} |
||
1919 |
|||
1920 |
241 |
ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) { |
|
1921 |
✓✓ | 241 |
if(fdef->base->args) |
1922 |
134 |
emit_func_def_args(emit, fdef->base->args); |
|
1923 |
✓✓ | 241 |
if(GET_FLAG(fdef, variadic)) |
1924 |
12 |
stack_alloc(emit); |
|
1925 |
✓✗ | 241 |
if(fdef->d.code) |
1926 |
✗✓ | 241 |
CHECK_BB(scoped_stmt(emit, fdef->d.code, 1)) |
1927 |
241 |
emit_func_def_ensure(emit, fdef); |
|
1928 |
241 |
return GW_OK; |
|
1929 |
} |
||
1930 |
|||
1931 |
1 |
ANN static Instr me_top(MemoizeEmitter *me) { |
|
1932 |
1 |
const Instr idx = emit_add_instr(me->emit, MemSetImm); |
|
1933 |
1 |
idx->m_val = me->offset; |
|
1934 |
1 |
const Instr pc = emit_add_instr(me->emit, MemSetImm); |
|
1935 |
1 |
pc->m_val = me->offset + SZ_INT; |
|
1936 |
1 |
return pc; |
|
1937 |
} |
||
1938 |
|||
1939 |
1 |
ANN static void me_ini(MemoizeEmitter *me) { |
|
1940 |
1 |
const Instr ini = emit_add_instr(me->emit, MemoizeIni); |
|
1941 |
1 |
ini->m_val = me->offset; |
|
1942 |
1 |
ini->m_val2 = me->fdef->stack_depth + me->fdef->base->ret_type->size; |
|
1943 |
1 |
} |
|
1944 |
|||
1945 |
1 |
ANN static void me_end(MemoizeEmitter *me, const m_uint pc) { |
|
1946 |
✓✓ | 2 |
for(m_uint i = 0; i < vector_size(&me->branch); ++i) |
1947 |
1 |
((Instr)vector_at(&me->branch, i))->m_val = pc; |
|
1948 |
1 |
} |
|
1949 |
|||
1950 |
1 |
ANN static void me_bottom(MemoizeEmitter *me, const m_uint pc) { |
|
1951 |
1 |
const Instr idx = emit_add_instr(me->emit, RegPushMem4); |
|
1952 |
1 |
idx->m_val = me->offset; |
|
1953 |
1 |
emit_add_instr(me->emit, int_pre_inc); |
|
1954 |
1 |
regpop(me->emit, SZ_INT); |
|
1955 |
1 |
const Instr loop = emit_add_instr(me->emit, Goto); |
|
1956 |
1 |
loop->m_val = pc; |
|
1957 |
1 |
} |
|
1958 |
|||
1959 |
1 |
ANN static void me_ret(MemoizeEmitter *me) { |
|
1960 |
1 |
const Instr instr = emit_kind(me->emit, me->fdef->base->ret_type->size, 0, regpushmem); |
|
1961 |
1 |
instr->m_val = (me->offset + SZ_INT)*2; |
|
1962 |
1 |
emit_add_instr(me->emit, FuncReturn); |
|
1963 |
1 |
} |
|
1964 |
|||
1965 |
1 |
ANN static m_bool me_run(MemoizeEmitter *me, const m_uint pc) { |
|
1966 |
1 |
me_ini(me); |
|
1967 |
✓✗ | 1 |
if(me->fdef->base->args) |
1968 |
✗✓ | 1 |
CHECK_BB(me_arg(me)) |
1969 |
1 |
me_ret(me); |
|
1970 |
1 |
me_end(me, emit_code_size(me->emit)); |
|
1971 |
1 |
me_bottom(me, pc); |
|
1972 |
1 |
return GW_OK; |
|
1973 |
} |
||
1974 |
|||
1975 |
1 |
ANN static m_bool emit_memoize(const Emitter emit, const Func_Def fdef) { |
|
1976 |
1 |
MemoizeEmitter me = { .emit=emit, .fdef=fdef, .offset=fdef->stack_depth }; |
|
1977 |
1 |
const Instr pc = me_top(&me); |
|
1978 |
1 |
const m_uint top = emit_code_size(emit); |
|
1979 |
1 |
vector_init(&me.branch); |
|
1980 |
1 |
const m_bool ret = me_run(&me, top); |
|
1981 |
1 |
vector_release(&me.branch); |
|
1982 |
1 |
pc->m_val2 = emit_code_size(emit); |
|
1983 |
1 |
return ret; |
|
1984 |
} |
||
1985 |
|||
1986 |
241 |
ANN static m_bool emit_fdef(const Emitter emit, const Func_Def fdef) { |
|
1987 |
✓✓✓✗ |
241 |
if(emit->info->memoize && GET_FLAG(fdef->base->func, pure)) |
1988 |
✗✓ | 1 |
CHECK_BB(emit_memoize(emit, fdef)) |
1989 |
✗✓ | 241 |
CHECK_BB(emit_func_def_body(emit, fdef)) |
1990 |
241 |
emit_func_def_return(emit); |
|
1991 |
241 |
return GW_OK; |
|
1992 |
} |
||
1993 |
|||
1994 |
482 |
static ANN int fdef_is_file_global(const Emitter emit, const Func_Def fdef) { |
|
1995 |
✓✓ | 948 |
return isa(fdef->base->func->value_ref->type, emit->gwion->type[et_lambda]) < 0 && |
1996 |
✓✓✓✓ ✓✓✓✓ |
918 |
!emit->env->class_def && !GET_FLAG(fdef, global) && !fdef->base->tmpl && |
1997 |
192 |
!emit->env->scope->depth; |
|
1998 |
} |
||
1999 |
|||
2000 |
241 |
ANN static void emit_fdef_finish(const Emitter emit, const Func_Def fdef) { |
|
2001 |
241 |
const Func func = fdef->base->func; |
|
2002 |
241 |
func->code = emit_func_def_code(emit, func); |
|
2003 |
✓✓ | 241 |
if(fdef_is_file_global(emit, fdef)) |
2004 |
95 |
emit_func_def_global(emit, func->value_ref); |
|
2005 |
✓✓✓✗ |
241 |
if(emit->info->memoize && GET_FLAG(func, pure)) |
2006 |
1 |
func->code->memoize = memoize_ini(emit, func); |
|
2007 |
241 |
} |
|
2008 |
|||
2009 |
286 |
ANN static m_bool emit_func_def(const Emitter emit, const Func_Def f) { |
|
2010 |
286 |
const Func func = f->base->func; |
|
2011 |
286 |
const Func_Def fdef = func->def; |
|
2012 |
286 |
const Func former = emit->env->func; |
|
2013 |
✓✓✓✓ |
286 |
if(func->code || tmpl_base(fdef->base->tmpl)) |
2014 |
45 |
return GW_OK; |
|
2015 |
✓✓✗✓ ✗✗ |
241 |
if(SAFE_FLAG(emit->env->class_def, builtin) && GET_FLAG(emit->env->class_def, template)) |
2016 |
return GW_OK; |
||
2017 |
✓✓ | 241 |
if(fdef_is_file_global(emit, fdef)) |
2018 |
95 |
func->value_ref->from->offset = emit_local(emit, emit->gwion->type[et_int]); |
|
2019 |
241 |
emit_func_def_init(emit, func); |
|
2020 |
✓✓ | 241 |
if(GET_FLAG(func, member)) |
2021 |
99 |
stack_alloc_this(emit); |
|
2022 |
241 |
emit->env->func = func; |
|
2023 |
241 |
emit_push_scope(emit); |
|
2024 |
✓✓ | 241 |
if(!strcmp(s_name(fdef->base->xid), "@gack")) { |
2025 |
2 |
emit_local(emit, emit->gwion->type[et_int]); |
|
2026 |
2 |
const Instr instr = emit_add_instr(emit, MemSetImm); |
|
2027 |
2 |
instr->m_val = SZ_INT; |
|
2028 |
} |
||
2029 |
241 |
const m_bool ret = scanx_fdef(emit->env, emit, fdef, (_exp_func)emit_fdef); |
|
2030 |
241 |
emit_pop_scope(emit); |
|
2031 |
241 |
emit->env->func = former; |
|
2032 |
✓✗ | 241 |
if(ret > 0) |
2033 |
241 |
emit_fdef_finish(emit, fdef); |
|
2034 |
else |
||
2035 |
emit_pop_code(emit); |
||
2036 |
241 |
return ret; |
|
2037 |
} |
||
2038 |
|||
2039 |
#define emit_fptr_def dummy_func |
||
2040 |
981 |
HANDLE_SECTION_FUNC(emit, m_bool, Emitter) |
|
2041 |
|||
2042 |
150 |
ANN Code* emit_class_code(const Emitter emit, const m_str name) { |
|
2043 |
150 |
const m_uint len = strlen(name) + 7; |
|
2044 |
150 |
char c[len]; |
|
2045 |
150 |
snprintf(c, len, "class %s", name); |
|
2046 |
150 |
emit_push_code(emit, c); |
|
2047 |
150 |
stack_alloc_this(emit); |
|
2048 |
150 |
return emit->code; |
|
2049 |
} |
||
2050 |
|||
2051 |
6 |
ANN static m_bool emit_parent(const Emitter emit, const Class_Def cdef) { |
|
2052 |
6 |
const Type parent = cdef->base.type->e->parent; |
|
2053 |
✓✗ | 6 |
return !GET_FLAG(parent, emit) ? ensure_emit(emit, parent) : GW_OK; |
2054 |
} |
||
2055 |
|||
2056 |
31 |
ANN static inline m_bool emit_cdef(const Emitter emit, const Class_Def cdef) { |
|
2057 |
31 |
return scanx_cdef(emit->env, emit, cdef, |
|
2058 |
(_exp_func)emit_class_def, (_exp_func)emit_union_def); |
||
2059 |
} |
||
2060 |
|||
2061 |
150 |
ANN void emit_class_finish(const Emitter emit, const Nspc nspc) { |
|
2062 |
150 |
nspc->pre_ctor = finalyze(emit, FuncReturn); |
|
2063 |
150 |
SET_FLAG(nspc->pre_ctor, ctor); |
|
2064 |
150 |
} |
|
2065 |
|||
2066 |
6 |
ANN static m_bool cdef_parent(const Emitter emit, const Class_Def cdef) { |
|
2067 |
✓✓✓✗ |
6 |
if(cdef->base.tmpl && cdef->base.tmpl->list) |
2068 |
✗✓ | 4 |
CHECK_BB(template_push_types(emit->env, cdef->base.tmpl)) |
2069 |
6 |
const m_bool ret = emit_parent(emit, cdef); |
|
2070 |
✓✓✓✗ |
6 |
if(cdef->base.tmpl && cdef->base.tmpl->list) |
2071 |
4 |
nspc_pop_type(emit->gwion->mp, emit->env->curr); |
|
2072 |
6 |
return ret; |
|
2073 |
} |
||
2074 |
|||
2075 |
193 |
ANN static m_bool emit_class_def(const Emitter emit, const Class_Def cdef) { |
|
2076 |
✓✓ | 193 |
if(tmpl_base(cdef->base.tmpl)) |
2077 |
19 |
return GW_OK; |
|
2078 |
174 |
const Type t = cdef->base.type; |
|
2079 |
✗✓ | 174 |
if(GET_FLAG(t, emit)) |
2080 |
return GW_OK; |
||
2081 |
174 |
SET_FLAG(t, emit); |
|
2082 |
✓✓✗✓ |
174 |
if(t->e->owner_class && !GET_FLAG(t->e->owner_class, emit)) |
2083 |
CHECK_BB(ensure_emit(emit, t->e->owner_class)) |
||
2084 |
✓✓✓✓ ✓✓ |
174 |
if(cdef->base.ext && t->e->parent->e->def && !GET_FLAG(t->e->parent, emit)) |
2085 |
✗✓ | 6 |
CHECK_BB(cdef_parent(emit, cdef)) |
2086 |
174 |
nspc_allocdata(emit->gwion->mp, t->nspc); |
|
2087 |
✓✓ | 174 |
if(cdef->body) { |
2088 |
150 |
emit_class_code(emit, t->name); |
|
2089 |
✓✗ | 150 |
if(scanx_body(emit->env, cdef, (_exp_func)emit_section, emit) > 0) |
2090 |
150 |
emit_class_finish(emit, t->nspc); |
|
2091 |
else { |
||
2092 |
free_code(emit->gwion->mp, emit->code); |
||
2093 |
emit_pop_code(emit); |
||
2094 |
return GW_ERROR; |
||
2095 |
} |
||
2096 |
} |
||
2097 |
174 |
return GW_OK; |
|
2098 |
} |
||
2099 |
|||
2100 |
4 |
ANN static inline void emit_free_code(const Emitter emit, Code* code) { |
|
2101 |
✓✓ | 4 |
if(vector_size(&code->instr)) |
2102 |
2 |
free_code_instr(&code->instr, emit->gwion); |
|
2103 |
4 |
free_code(emit->gwion->mp, code); |
|
2104 |
4 |
} |
|
2105 |
|||
2106 |
4 |
ANN static VM_Code emit_free_stack(const Emitter emit) { |
|
2107 |
LOOP_OPTIM |
||
2108 |
✗✓ | 8 |
for(m_uint i = vector_size(&emit->stack) + 1; --i;) |
2109 |
emit_free_code(emit, (Code*)vector_at(&emit->stack, i - 1)); |
||
2110 |
4 |
vector_clear(&emit->stack); |
|
2111 |
4 |
vector_clear(&emit->info->pure); |
|
2112 |
4 |
emit_free_code(emit, emit->code); |
|
2113 |
4 |
return NULL; |
|
2114 |
} |
||
2115 |
|||
2116 |
699 |
ANN static inline m_bool emit_ast_inner(const Emitter emit, Ast ast) { |
|
2117 |
✓✓ | 699 |
do CHECK_BB(emit_section(emit, ast->section)) |
2118 |
✓✓ | 695 |
while((ast = ast->next)); |
2119 |
408 |
return GW_OK; |
|
2120 |
} |
||
2121 |
|||
2122 |
412 |
ANN m_bool emit_ast(const Env env, Ast ast) { |
|
2123 |
412 |
const Emitter emit = env->gwion->emit; |
|
2124 |
412 |
emit->info->memoize = 0; |
|
2125 |
412 |
emit->code = new_code(emit, emit->env->name); |
|
2126 |
412 |
emit_push_scope(emit); |
|
2127 |
412 |
const m_bool ret = emit_ast_inner(emit, ast); |
|
2128 |
412 |
emit_pop_scope(emit); |
|
2129 |
✓✓ | 412 |
if(ret > 0) |
2130 |
408 |
emit->info->code = finalyze(emit, emit->info->finalyzer); |
|
2131 |
else |
||
2132 |
4 |
emit_free_stack(emit); |
|
2133 |
412 |
return ret; |
|
2134 |
} |
Generated by: GCOVR (Version 4.2) |