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 = 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;
+ 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) {
if (!ir_block_create_if(func->curblock, left, other, merge))
return false;
} else {
cgen = self->right->expression.codegen;
if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
return false;
+ 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))
ir_phi_add(phi, from_left, left);
ir_phi_add(phi, from_right, right);
*out = ir_phi_value(phi);
+ 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);
self->expression.outr = *out;
return true;
}
AINSTR_END, /* array */
};
+uint16_t type_not_instr[TYPE_COUNT] = {
+ INSTR_NOT_F, /* should use I when having integer support */
+ INSTR_NOT_S,
+ INSTR_NOT_F,
+ INSTR_NOT_V,
+ INSTR_NOT_ENT,
+ INSTR_NOT_ENT,
+ INSTR_NOT_FNC,
+ INSTR_NOT_ENT, /* should use I */
+#if 0
+ INSTR_NOT_I, /* integer type */
+#else
+ INSTR_NOT_F,
+#endif
+
+ INSTR_NOT_V, /* variant, should never be accessed */
+
+ AINSTR_END, /* struct */
+ AINSTR_END, /* union */
+ AINSTR_END, /* array */
+};
+
static void irerror(lex_ctx ctx, const char *msg, ...)
{
va_list ap;