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;
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;
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;
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) {
}
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");
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;