#include "gmqcc.h"
#include "ast.h"
+#include "parser.h"
#define ast_instantiate(T, ctx, destroyfn) \
T* self = (T*)mem_a(sizeof(T)); \
self->getter = NULL;
self->desc = NULL;
- self->argcounter = NULL;
+ self->argcounter = NULL;
+ self->intrinsic = false;
return self;
}
self->op = op;
self->left = left;
self->right = right;
+ self->right_first = false;
ast_propagate_effects(self, left);
ast_propagate_effects(self, right);
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;
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;
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;
}
/* 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) {
}
/* 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) {
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;
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);
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;
/* update the block which will get the jump - because short-logic or ternaries may have changed this */
cond = func->curblock;
- /* eliminate branches if value is constant */
- if (condval->vtype == TYPE_FLOAT && condval->hasvalue && condval->cvq == CV_CONST) {
- /* don't generate if statements */
- if (condval->constval.vfloat == 1.0f && self->on_true) {
- if (!(ontrue = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "ontrue"))))
- return false;
- /* generate */
- if (!(*(cgen = self->on_true->codegen))((ast_expression*)(self->on_true), func, false, &dummy))
- return false;
- if (!ir_block_create_jump(func->curblock, ast_ctx(self), ontrue))
- return false;
- func->curblock = ontrue;
- return true;
- } else if (condval->constval.vfloat == 0.0f && self->on_false) {
- if (!(onfalse = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "onfalse"))))
- return false;
- /* generate */
- if (!(*(cgen = self->on_false->codegen))((ast_expression*)(self->on_false), func, false, &dummy))
- return false;
- if (!ir_block_create_jump(func->curblock, ast_ctx(self), onfalse))
- return false;
- func->curblock = onfalse;
- return true;
- }
- }
- /* 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 */