X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=ast.c;h=a228f3f7edcb5d7b671db45c9142d26a0d9fb69c;hp=7a8f6cc1c57fab709dea8e31b069fce2699d12b6;hb=3b4a5667ea8b1b7aa8a10734c57c02d1561fcdd7;hpb=d6ca5673dc7f2760faca1200477808d919a290ca diff --git a/ast.c b/ast.c index 7a8f6cc..a228f3f 100644 --- a/ast.c +++ b/ast.c @@ -26,6 +26,7 @@ #include "gmqcc.h" #include "ast.h" +#include "parser.h" #define ast_instantiate(T, ctx, destroyfn) \ T* self = (T*)mem_a(sizeof(T)); \ @@ -368,7 +369,8 @@ ast_value* ast_value_new(lex_ctx_t ctx, const char *name, int t) self->getter = NULL; self->desc = NULL; - self->argcounter = NULL; + self->argcounter = NULL; + self->intrinsic = false; return self; } @@ -442,6 +444,7 @@ ast_binary* ast_binary_new(lex_ctx_t ctx, int op, self->op = op; self->left = left; self->right = right; + self->right_first = false; ast_propagate_effects(self, left); ast_propagate_effects(self, right); @@ -1221,7 +1224,7 @@ void ast_function_delete(ast_function *self) mem_d(self); } -static const char* ast_function_label(ast_function *self, const char *prefix) +const char* ast_function_label(ast_function *self, const char *prefix) { size_t id; size_t len; @@ -1347,6 +1350,20 @@ static bool ast_global_array_set(ast_value *self) return true; } +static bool check_array(ast_value *self, ast_value *array) +{ + if (array->expression.flags & AST_FLAG_ARRAY_INIT && !array->initlist) { + compile_error(ast_ctx(self), "array without size: %s", self->name); + return false; + } + /* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */ + if (!array->expression.count || array->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) { + compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)array->expression.count); + return false; + } + return true; +} + bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) { ir_value *v = NULL; @@ -1394,9 +1411,8 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) return false; } - /* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */ - if (!array->expression.count || array->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) - compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)array->expression.count); + if (!check_array(self, array)) + return false; elemtype = array->expression.next; vtype = elemtype->vtype; @@ -1462,8 +1478,8 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) } /* same as with field arrays */ - if (!self->expression.count || self->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) - compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)self->expression.count); + if (!check_array(self, self)) + return false; v = ir_builder_create_global(ir, self->name, vtype); if (!v) { @@ -1600,9 +1616,8 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param) } /* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */ - if (!self->expression.count || self->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) { - compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)self->expression.count); - } + if (!check_array(self, self)) + return false; self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->expression.count); if (!self->ir_values) { @@ -2024,6 +2039,8 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va if ((OPTS_FLAG(SHORT_LOGIC) || OPTS_FLAG(PERL_LOGIC)) && (self->op == INSTR_AND || self->op == INSTR_OR)) { + /* NOTE: The short-logic path will ignore right_first */ + /* short circuit evaluation */ ir_block *other, *merge; ir_block *from_left, *from_right; @@ -2121,13 +2138,21 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va return true; } - cgen = self->left->codegen; - if (!(*cgen)((ast_expression*)(self->left), func, false, &left)) - return false; - - cgen = self->right->codegen; - if (!(*cgen)((ast_expression*)(self->right), func, false, &right)) - return false; + if (self->right_first) { + cgen = self->right->codegen; + if (!(*cgen)((ast_expression*)(self->right), func, false, &right)) + return false; + cgen = self->left->codegen; + if (!(*cgen)((ast_expression*)(self->left), func, false, &left)) + return false; + } else { + cgen = self->left->codegen; + if (!(*cgen)((ast_expression*)(self->left), func, false, &left)) + return false; + cgen = self->right->codegen; + if (!(*cgen)((ast_expression*)(self->right), func, false, &right)) + return false; + } *out = ir_block_create_binop(func->curblock, ast_ctx(self), ast_function_label(func, "bin"), self->op, left, right); @@ -2513,6 +2538,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va ir_block *ontrue_endblock = NULL; ir_block *onfalse_endblock = NULL; ir_block *merge = NULL; + int fold = 0; /* We don't output any value, thus also don't care about r/lvalue */ (void)out; @@ -2531,7 +2557,9 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va /* update the block which will get the jump - because short-logic or ternaries may have changed this */ cond = func->curblock; - /* on-true path */ + /* try constant folding away the if */ + if ((fold = fold_cond(condval, func, self)) != -1) + return fold; if (self->on_true) { /* create on-true block */