catch broken vector member access
[xonotic/gmqcc.git] / ast.cpp
1 #include <new>
2
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "gmqcc.h"
7 #include "ast.h"
8 #include "fold.h"
9 //#include "parser.h"
10
11 #include "algo.h"
12
13 /* Initialize main ast node aprts */
14 ast_node::ast_node(lex_ctx_t ctx, int node_type)
15     : m_context(ctx)
16     , m_node_type(node_type)
17     , m_keep_node(false)
18     , m_side_effects(false)
19 {
20 }
21
22 ast_node::~ast_node()
23 {
24 }
25
26 /* weight and side effects */
27 void ast_node::propagateSideEffects(const ast_node *other)
28 {
29     if (other->m_side_effects)
30         m_side_effects = true;
31 }
32
33 /* General expression initialization */
34 ast_expression::ast_expression(lex_ctx_t ctx, int nodetype, qc_type type)
35     : ast_node(ctx, nodetype)
36     , m_vtype(type)
37 {
38     if (OPTS_OPTION_BOOL(OPTION_COVERAGE))
39         m_flags |= AST_FLAG_BLOCK_COVERAGE;
40 }
41 ast_expression::ast_expression(lex_ctx_t ctx, int nodetype)
42     : ast_expression(ctx, nodetype, TYPE_VOID)
43 {}
44
45 ast_expression::~ast_expression()
46 {
47     if (m_next)
48         delete m_next;
49     if (m_varparam)
50         delete m_varparam;
51 }
52
53 ast_expression::ast_expression(ast_copy_type_t, const ast_expression &other)
54     : ast_expression(ast_copy_type, other.m_context, other)
55 {}
56
57 ast_expression::ast_expression(ast_copy_type_t, lex_ctx_t ctx, const ast_expression &other)
58     : ast_expression(ast_copy_type, TYPE_ast_expression, ctx, other)
59 {}
60
61 ast_expression::ast_expression(ast_copy_type_t, int nodetype, const ast_expression &other)
62     : ast_expression(ast_copy_type, nodetype, other.m_context, other)
63 {}
64
65 ast_expression::ast_expression(ast_copy_type_t, int nodetype, lex_ctx_t ctx, const ast_expression &other)
66     : ast_expression(ctx, nodetype)
67 {
68     m_vtype = other.m_vtype;
69     m_count = other.m_count;
70     m_flags = other.m_flags;
71     if (other.m_next)
72         m_next = new ast_expression(ast_copy_type, *other.m_next);
73     m_type_params.reserve(other.m_type_params.size());
74     for (auto &it : other.m_type_params)
75         m_type_params.emplace_back(new ast_value(ast_copy_type, *it));
76 }
77
78
79 ast_expression *ast_expression::shallowType(lex_ctx_t ctx, qc_type vtype) {
80     auto expr = new ast_expression(ctx, TYPE_ast_expression);
81     expr->m_vtype = vtype;
82     return expr;
83 }
84
85 void ast_expression::adoptType(const ast_expression &other)
86 {
87     m_vtype = other.m_vtype;
88     if (other.m_next)
89         m_next = new ast_expression(ast_copy_type, *other.m_next);
90     m_count = other.m_count;
91     m_flags = other.m_flags;
92     m_type_params.clear();
93     m_type_params.reserve(other.m_type_params.size());
94     for (auto &it : other.m_type_params)
95         m_type_params.emplace_back(new ast_value(ast_copy_type, *it));
96 }
97
98 bool ast_expression::compareType(const ast_expression &other) const
99 {
100     if (m_vtype == TYPE_NIL ||
101         other.m_vtype == TYPE_NIL)
102         return true;
103     if (m_vtype != other.m_vtype)
104         return false;
105     if (!m_next != !other.m_next)
106         return false;
107     if (m_type_params.size() != other.m_type_params.size())
108         return false;
109     if ((m_flags & AST_FLAG_TYPE_MASK) !=
110         (other.m_flags & AST_FLAG_TYPE_MASK) )
111     {
112         return false;
113     }
114     if (m_type_params.size()) {
115         size_t i;
116         for (i = 0; i < m_type_params.size(); ++i) {
117             if (!m_type_params[i]->compareType(*other.m_type_params[i]))
118                 return false;
119         }
120     }
121     if (m_next)
122         return m_next->compareType(*other.m_next);
123     return true;
124 }
125
126 bool ast_expression::codegen(ast_function*, bool, ir_value**) {
127     compile_error(m_context, "ast_expression::codegen called!");
128     abort();
129     return false;
130 }
131
132 ast_value::ast_value(ast_copy_type_t, const ast_value &other, const std::string &name)
133     : ast_value(ast_copy_type, static_cast<const ast_expression&>(other), name)
134 {
135     m_keep_node = true; // keep values, always
136     memset(&m_constval, 0, sizeof(m_constval));
137 }
138
139 ast_value::ast_value(ast_copy_type_t, const ast_value &other)
140     : ast_value(ast_copy_type, static_cast<const ast_expression&>(other), other.m_name)
141 {
142     m_keep_node = true; // keep values, always
143     memset(&m_constval, 0, sizeof(m_constval));
144 }
145
146 ast_value::ast_value(ast_copy_type_t, const ast_expression &other, const std::string &name)
147     : ast_expression(ast_copy_type, TYPE_ast_value, other)
148     , m_name(name)
149 {
150     m_keep_node = true; // keep values, always
151     memset(&m_constval, 0, sizeof(m_constval));
152 }
153
154 ast_value::ast_value(lex_ctx_t ctx, const std::string &name, qc_type t)
155     : ast_expression(ctx, TYPE_ast_value, t)
156     , m_name(name)
157 {
158     m_keep_node = true; // keep values, always
159     memset(&m_constval, 0, sizeof(m_constval));
160 }
161
162 ast_value::~ast_value()
163 {
164     if (m_argcounter)
165         mem_d((void*)m_argcounter);
166     if (m_hasvalue) {
167         switch (m_vtype)
168         {
169         case TYPE_STRING:
170             mem_d((void*)m_constval.vstring);
171             break;
172         case TYPE_FUNCTION:
173             // unlink us from the function node
174             m_constval.vfunc->m_function_type = nullptr;
175             break;
176         // NOTE: delete function? currently collected in
177         // the parser structure
178         default:
179             break;
180         }
181     }
182
183     // initlist imples an array which implies .next in the expression exists.
184     if (m_initlist.size() && m_next->m_vtype == TYPE_STRING) {
185         for (auto &it : m_initlist)
186             if (it.vstring)
187                 mem_d(it.vstring);
188     }
189 }
190
191 static size_t ast_type_to_string_impl(const ast_expression *e, char *buf, size_t bufsize, size_t pos)
192 {
193     const char *typestr;
194     size_t typelen;
195     size_t i;
196
197     if (!e) {
198         if (pos + 6 >= bufsize)
199             goto full;
200         util_strncpy(buf + pos, "(null)", 6);
201         return pos + 6;
202     }
203
204     if (pos + 1 >= bufsize)
205         goto full;
206
207     switch (e->m_vtype) {
208         case TYPE_VARIANT:
209             util_strncpy(buf + pos, "(variant)", 9);
210             return pos + 9;
211
212         case TYPE_FIELD:
213             buf[pos++] = '.';
214             return ast_type_to_string_impl(e->m_next, buf, bufsize, pos);
215
216         case TYPE_POINTER:
217             if (pos + 3 >= bufsize)
218                 goto full;
219             buf[pos++] = '*';
220             buf[pos++] = '(';
221             pos = ast_type_to_string_impl(e->m_next, buf, bufsize, pos);
222             if (pos + 1 >= bufsize)
223                 goto full;
224             buf[pos++] = ')';
225             return pos;
226
227         case TYPE_FUNCTION:
228             pos = ast_type_to_string_impl(e->m_next, buf, bufsize, pos);
229             if (pos + 2 >= bufsize)
230                 goto full;
231             if (e->m_type_params.empty()) {
232                 buf[pos++] = '(';
233                 buf[pos++] = ')';
234                 return pos;
235             }
236             buf[pos++] = '(';
237             pos = ast_type_to_string_impl(e->m_type_params[0].get(), buf, bufsize, pos);
238             for (i = 1; i < e->m_type_params.size(); ++i) {
239                 if (pos + 2 >= bufsize)
240                     goto full;
241                 buf[pos++] = ',';
242                 buf[pos++] = ' ';
243                 pos = ast_type_to_string_impl(e->m_type_params[i].get(), buf, bufsize, pos);
244             }
245             if (pos + 1 >= bufsize)
246                 goto full;
247             buf[pos++] = ')';
248             return pos;
249
250         case TYPE_ARRAY:
251             pos = ast_type_to_string_impl(e->m_next, buf, bufsize, pos);
252             if (pos + 1 >= bufsize)
253                 goto full;
254             buf[pos++] = '[';
255             pos += util_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->m_count);
256             if (pos + 1 >= bufsize)
257                 goto full;
258             buf[pos++] = ']';
259             return pos;
260
261         default:
262             typestr = type_name[e->m_vtype];
263             typelen = strlen(typestr);
264             if (pos + typelen >= bufsize)
265                 goto full;
266             util_strncpy(buf + pos, typestr, typelen);
267             return pos + typelen;
268     }
269
270 full:
271     buf[bufsize-3] = '.';
272     buf[bufsize-2] = '.';
273     buf[bufsize-1] = '.';
274     return bufsize;
275 }
276
277 void ast_type_to_string(const ast_expression *e, char *buf, size_t bufsize)
278 {
279     size_t pos = ast_type_to_string_impl(e, buf, bufsize-1, 0);
280     buf[pos] = 0;
281 }
282
283 void ast_value::addParam(ast_value *p)
284 {
285     m_type_params.emplace_back(p);
286 }
287
288 ast_binary::ast_binary(lex_ctx_t ctx, int op,
289                        ast_expression* left, ast_expression* right)
290     : ast_expression(ctx, TYPE_ast_binary)
291     , m_op(op)
292     // m_left/m_right happen after the peephole step right below
293     , m_right_first(false)
294 {
295     if (ast_istype(right, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) {
296         ast_unary      *unary  = ((ast_unary*)right);
297         ast_expression *normal = unary->m_operand;
298
299         /* make a-(-b) => a + b */
300         if (unary->m_op == VINSTR_NEG_F || unary->m_op == VINSTR_NEG_V) {
301             if (op == INSTR_SUB_F) {
302                 op = INSTR_ADD_F;
303                 right = normal;
304                 ++opts_optimizationcount[OPTIM_PEEPHOLE];
305             } else if (op == INSTR_SUB_V) {
306                 op = INSTR_ADD_V;
307                 right = normal;
308                 ++opts_optimizationcount[OPTIM_PEEPHOLE];
309             }
310         }
311     }
312
313     m_left = left;
314     m_right = right;
315
316     propagateSideEffects(left);
317     propagateSideEffects(right);
318
319     if (op >= INSTR_EQ_F && op <= INSTR_GT)
320         m_vtype = TYPE_FLOAT;
321     else if (op == INSTR_AND || op == INSTR_OR) {
322         if (OPTS_FLAG(PERL_LOGIC))
323             adoptType(*right);
324         else
325             m_vtype = TYPE_FLOAT;
326     }
327     else if (op == INSTR_BITAND || op == INSTR_BITOR)
328         m_vtype = TYPE_FLOAT;
329     else if (op == INSTR_MUL_VF || op == INSTR_MUL_FV)
330         m_vtype = TYPE_VECTOR;
331     else if (op == INSTR_MUL_V)
332         m_vtype = TYPE_FLOAT;
333     else
334         m_vtype = left->m_vtype;
335
336     // references all
337     m_refs = AST_REF_ALL;
338 }
339
340 ast_binary::~ast_binary()
341 {
342     if (m_refs & AST_REF_LEFT)  ast_unref(m_left);
343     if (m_refs & AST_REF_RIGHT) ast_unref(m_right);
344 }
345
346 ast_binstore::ast_binstore(lex_ctx_t ctx, int storop, int mathop,
347                            ast_expression* left, ast_expression* right)
348     : ast_expression(ctx, TYPE_ast_binstore)
349     , m_opstore(storop)
350     , m_opbin(mathop)
351     , m_dest(left)
352     , m_source(right)
353     , m_keep_dest(false)
354 {
355     m_side_effects = true;
356     adoptType(*left);
357 }
358
359 ast_binstore::~ast_binstore()
360 {
361     if (!m_keep_dest)
362         ast_unref(m_dest);
363     ast_unref(m_source);
364 }
365
366 ast_unary* ast_unary::make(lex_ctx_t ctx, int op, ast_expression *expr)
367 {
368     // handle double negation, double bitwise or logical not
369     if (op == opid2('!','P') ||
370         op == opid2('~','P') ||
371         op == opid2('-','P'))
372     {
373         if (ast_istype(expr, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) {
374             ast_unary *unary = reinterpret_cast<ast_unary*>(expr);
375             if (unary->m_op == op) {
376                 auto out = reinterpret_cast<ast_unary*>(unary->m_operand);
377                 unary->m_operand = nullptr;
378                 delete unary;
379                 ++opts_optimizationcount[OPTIM_PEEPHOLE];
380                 return out;
381             }
382         }
383     }
384
385     return new ast_unary(ctx, op, expr);
386 }
387
388 ast_unary::ast_unary(lex_ctx_t ctx, int op, ast_expression *expr)
389     : ast_expression(ctx, TYPE_ast_unary)
390     , m_op(op)
391     , m_operand(expr)
392 {
393     propagateSideEffects(expr);
394     if ((op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) || op == VINSTR_NEG_F) {
395         m_vtype = TYPE_FLOAT;
396     } else if (op == VINSTR_NEG_V) {
397         m_vtype = TYPE_VECTOR;
398     } else {
399         compile_error(ctx, "cannot determine type of unary operation %s", util_instr_str[op]);
400     }
401 }
402
403 ast_unary::~ast_unary()
404 {
405     if (m_operand)
406         ast_unref(m_operand);
407 }
408
409 ast_return::ast_return(lex_ctx_t ctx, ast_expression *expr)
410     : ast_expression(ctx, TYPE_ast_return)
411     , m_operand(expr)
412 {
413     if (expr)
414         propagateSideEffects(expr);
415 }
416
417 ast_return::~ast_return()
418 {
419     if (m_operand)
420         ast_unref(m_operand);
421 }
422
423 ast_entfield::ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field)
424     : ast_entfield(ctx, entity, field, field->m_next)
425 {
426     if (field->m_vtype != TYPE_FIELD)
427         compile_error(ctx, "ast_entfield with expression not of type field");
428 }
429
430 ast_entfield::ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype)
431     : ast_expression(ctx, TYPE_ast_entfield)
432     , m_entity(entity)
433     , m_field(field)
434 {
435     propagateSideEffects(m_entity);
436     propagateSideEffects(m_field);
437
438     if (!outtype) {
439         compile_error(ctx, "ast_entfield: field has no type");
440         m_vtype = TYPE_VOID;
441     }
442     else
443         adoptType(*outtype);
444 }
445
446 ast_entfield::~ast_entfield()
447 {
448     ast_unref(m_entity);
449     ast_unref(m_field);
450 }
451
452 ast_member *ast_member::make(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const std::string &name)
453 {
454     if (field >= 3) {
455         compile_error(ctx, "ast_member: invalid field (>=3): %u", field);
456         return nullptr;
457     }
458     if (owner->m_vtype != TYPE_VECTOR &&
459         owner->m_vtype != TYPE_FIELD)
460     {
461         compile_error(ctx, "member-access on an invalid owner of type %s", type_name[owner->m_vtype]);
462         return nullptr;
463     }
464     return new ast_member(ctx, owner, field, name);
465 }
466
467 ast_member::ast_member(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const std::string &name)
468     : ast_expression(ctx, TYPE_ast_member)
469     , m_owner(owner)
470     , m_field(field)
471     , m_name(name)
472     , m_rvalue(false)
473 {
474     m_keep_node = true;
475
476     if (m_owner->m_vtype == TYPE_VECTOR) {
477         m_vtype = TYPE_FLOAT;
478         m_next  = nullptr;
479     } else {
480         m_vtype = TYPE_FIELD;
481         m_next = ast_expression::shallowType(ctx, TYPE_FLOAT);
482     }
483
484     propagateSideEffects(owner);
485 }
486
487 ast_member::~ast_member()
488 {
489     // The owner is always an ast_value, which has .keep_node=true,
490     // also: ast_members are usually deleted after the owner, thus
491     // this will cause invalid access
492         //ast_unref(self->m_owner);
493     // once we allow (expression).x to access a vector-member, we need