From 0fe71af4ce486cbb2c309850463cb76316c6cd1f Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Sat, 22 Dec 2012 17:18:37 +0100 Subject: [PATCH] -fcorrect-logic now handles only vectors --- ast.c | 57 ++++++++++++-------------------------------------------- parser.c | 33 ++++++++++---------------------- 2 files changed, 22 insertions(+), 68 deletions(-) diff --git a/ast.c b/ast.c index e544e48..2eb9faa 100644 --- a/ast.c +++ b/ast.c @@ -1707,64 +1707,42 @@ 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)) - */ + /* prepare end-block */ merge_id = vec_size(func->ir_func->blocks); - merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge")); + merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge")); + /* generate the left expression */ 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) { - compile_error(ast_ctx(self), "don't know how to cast to bool..."); - return false; - } - left = ir_block_create_unary(func->curblock, ast_ctx(self), - ast_function_label(func, "sce_not"), - notop, - left); - } + /* remember the block */ from_left = func->curblock; + /* create a new block for the right expression */ other = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_other")); - if ( !(self->op == INSTR_OR) != !OPTS_FLAG(PERL_LOGIC) ) { + if (self->op == INSTR_AND) { + /* on AND: left==true -> other */ if (!ir_block_create_if(func->curblock, ast_ctx(self), left, other, merge)) return false; } else { + /* on OR: left==false -> other */ if (!ir_block_create_if(func->curblock, ast_ctx(self), left, merge, other)) return false; } /* use the likely flag */ vec_last(func->curblock->instr)->likely = true; + /* enter the right-expression's block */ func->curblock = other; + /* generate */ 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) { - compile_error(ast_ctx(self), "don't know how to cast to bool..."); - return false; - } - right = ir_block_create_unary(func->curblock, ast_ctx(self), - ast_function_label(func, "sce_not"), - notop, - right); - } + /* remember block */ from_right = func->curblock; + /* jump to the merge block */ if (!ir_block_create_jump(func->curblock, ast_ctx(self), merge)) return false; @@ -1776,17 +1754,6 @@ 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) { - compile_error(ast_ctx(self), "don't know how to cast to bool..."); - return false; - } - *out = ir_block_create_unary(func->curblock, ast_ctx(self), - ast_function_label(func, "sce_final_not"), - notop, - *out); - } if (!*out) return false; self->expression.outr = *out; diff --git a/parser.c b/parser.c index f593d0e..c2d1157 100644 --- a/parser.c +++ b/parser.c @@ -893,14 +893,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (OPTS_FLAG(CORRECT_LOGIC)) { /* non-floats need to be NOTed */ for (i = 0; i < 2; ++i) { - if (exprs[i]->expression.vtype != TYPE_FLOAT) { - if (type_not_instr[exprs[i]->expression.vtype] == AINSTR_END) { - ast_type_to_string(exprs[0], ty1, sizeof(ty1)); - ast_type_to_string(exprs[1], ty2, sizeof(ty2)); - parseerror(parser, "invalid types for logical operation with -fcorrect-logic: %s and %s", ty1, ty2); - return false; - } - out = (ast_expression*)ast_unary_new(ctx, type_not_instr[exprs[i]->expression.vtype], exprs[i]); + if (exprs[i]->expression.vtype == TYPE_VECTOR) { + out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]); if (!out) break; out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out); if (!out) break; @@ -1901,7 +1895,8 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond, ast_unary *unary; ast_expression *prev; - if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->expression.vtype == TYPE_STRING) { + if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->expression.vtype == TYPE_STRING) + { prev = cond; cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond); if (!cond) { @@ -1911,22 +1906,15 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond, } ifnot = !ifnot; } - if (OPTS_FLAG(CORRECT_LOGIC) && - !(cond->expression.vtype == TYPE_STRING && OPTS_FLAG(TRUE_EMPTY_STRINGS))) + else if (OPTS_FLAG(CORRECT_LOGIC) && cond->expression.vtype == TYPE_VECTOR) { - /* non-floats need to use NOT; except for strings on -ftrue-empty-strings */ - unary = (ast_unary*)cond; - if (!ast_istype(cond, ast_unary) || unary->op < INSTR_NOT_F || unary->op > INSTR_NOT_FNC) + /* vector types need to be cast to true booleans */ + ast_binary *bin = (ast_binary*)cond; + if (!OPTS_FLAG(PERL_LOGIC) || !ast_istype(cond, ast_binary) || !(bin->op == INSTR_AND || bin->op == INSTR_OR)) { - /* use the right NOT_ */ + /* in perl-logic, AND and OR take care of the -fcorrect-logic */ prev = cond; - cond = (ast_expression*)ast_unary_new(ast_ctx(cond), type_not_instr[cond->expression.vtype], cond); - - /* - * cppcheck: it thinks there is a possible null pointer dereference - * otherwise it would be "redundant" to check it ast_unary_new returned - * null, it's wrong. - */ + cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_V, cond); if (!cond) { ast_unref(prev); parseerror(parser, "internal error: failed to process condition"); @@ -1938,7 +1926,6 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond, unary = (ast_unary*)cond; while (ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F) - /*&& unary->operand->expression.vtype != TYPE_STRING) */ { cond = unary->operand; unary->operand = NULL; -- 2.39.2