X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=ast.c;h=907a944d02f747bd8c00439be2ee1a654b9c6757;hb=c5f8fbb871f045f26e1b68b97a8ce197ff772ef8;hp=7487e2332798f0a4512f3602cfd802263ee46715;hpb=ca2b414c7c73f367472053b5a5c5fab17582cc14;p=xonotic%2Fgmqcc.git diff --git a/ast.c b/ast.c index 7487e23..907a944 100644 --- a/ast.c +++ b/ast.c @@ -651,7 +651,11 @@ ast_ternary* ast_ternary_new(lex_ctx ctx, ast_expression *cond, ast_expression * self->cond = cond; self->on_true = ontrue; self->on_false = onfalse; - self->phi_out = NULL; + + if (!ast_type_adopt(self, ontrue)) { + ast_ternary_delete(self); + return NULL; + } return self; } @@ -784,8 +788,12 @@ bool ast_call_check_types(ast_call *self) for (i = 0; i < count; ++i) { if (!ast_compare_type(self->params[i], (ast_expression*)(func->expression.params[i]))) { - asterror(ast_ctx(self), "invalid type for parameter %u in function call", - (unsigned int)(i+1)); + char texp[1024]; + char tgot[1024]; + ast_type_to_string(self->params[i], tgot, sizeof(tgot)); + ast_type_to_string((ast_expression*)func->expression.params[i], texp, sizeof(texp)); + asterror(ast_ctx(self), "invalid type for parameter %u in function call: expected %s, got %s", + (unsigned int)(i+1), texp, tgot); /* we don't immediately return */ retval = false; } @@ -932,7 +940,7 @@ const char* ast_function_label(ast_function *self, const char *prefix) size_t len; char *from; - if (!opts_dump) + if (!opts_dump && !opts_dumpfin) return NULL; id = (self->labelcount++); @@ -1521,28 +1529,62 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va ir_block *from_left, *from_right; ir_instr *phi; size_t merge_id; + uint16_t notop; + + /* Note about casting to true boolean values: + * We use a single NOT for sub expressions, and an + * overall NOT at the end, and for that purpose swap + * all the jump conditions in order for the NOT to get + * doubled. + * ie: (a && b) usually becomes (!!a ? !!b : !!a) + * but we translate this to (!(!a ? !a : !b)) + */ - merge_id = vec_size(func->blocks); + merge_id = vec_size(func->ir_func->blocks); merge = ir_function_create_block(func->ir_func, ast_function_label(func, "sce_merge")); cgen = self->left->expression.codegen; if (!(*cgen)((ast_expression*)(self->left), func, false, &left)) return false; - + if (!OPTS_FLAG(PERL_LOGIC)) { + notop = type_not_instr[left->vtype]; + if (notop == AINSTR_END) { + asterror(ast_ctx(self), "don't know how to cast to bool..."); + return false; + } + left = ir_block_create_unary(func->curblock, + ast_function_label(func, "sce_not"), + notop, + left); + } from_left = func->curblock; + other = ir_function_create_block(func->ir_func, ast_function_label(func, "sce_other")); - if (self->op == INSTR_AND) { + if ( !(self->op == INSTR_OR) != !OPTS_FLAG(PERL_LOGIC) ) { if (!ir_block_create_if(func->curblock, left, other, merge)) return false; } else { if (!ir_block_create_if(func->curblock, left, merge, other)) return false; } + /* use the likely flag */ + vec_last(func->curblock->instr)->likely = true; func->curblock = other; cgen = self->right->expression.codegen; if (!(*cgen)((ast_expression*)(self->right), func, false, &right)) return false; + if (!OPTS_FLAG(PERL_LOGIC)) { + notop = type_not_instr[right->vtype]; + if (notop == AINSTR_END) { + asterror(ast_ctx(self), "don't know how to cast to bool..."); + return false; + } + right = ir_block_create_unary(func->curblock, + ast_function_label(func, "sce_not"), + notop, + right); + } from_right = func->curblock; if (!ir_block_create_jump(func->curblock, merge)) @@ -1556,6 +1598,19 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va ir_phi_add(phi, from_left, left); ir_phi_add(phi, from_right, right); *out = ir_phi_value(phi); + if (!OPTS_FLAG(PERL_LOGIC)) { + notop = type_not_instr[(*out)->vtype]; + if (notop == AINSTR_END) { + asterror(ast_ctx(self), "don't know how to cast to bool..."); + return false; + } + *out = ir_block_create_unary(func->curblock, + ast_function_label(func, "sce_final_not"), + notop, + *out); + } + if (!*out) + return false; self->expression.outr = *out; return true; } @@ -1965,8 +2020,8 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ * may still happen, thus we remember a created ir_value and simply return one * if it already exists. */ - if (self->phi_out) { - *out = self->phi_out; + if (self->expression.outr) { + *out = self->expression.outr; return true; } @@ -2040,8 +2095,8 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ ir_phi_add(phi, ontrue, trueval); ir_phi_add(phi, onfalse, falseval); - self->phi_out = ir_phi_value(phi); - *out = self->phi_out; + self->expression.outr = ir_phi_value(phi); + *out = self->expression.outr; return true; }