}
expression_t *con;
- if (is_local_variable(op1) && is_constant_expression(op2)) {
+ if (is_local_variable(op1) && is_constant_expression(op2) == EXPR_CLASS_CONSTANT) {
var = op1->reference.entity;
con = op2;
- } else if (is_constant_expression(op1) && is_local_variable(op2)) {
+ } else if (is_constant_expression(op1) == EXPR_CLASS_CONSTANT && is_local_variable(op2)) {
cmp_val = get_inversed_pnc(cmp_val);
var = op2->reference.entity;
con = op1;
static ir_node *produce_condition_result(const expression_t *expression,
ir_mode *mode, dbg_info *dbgi)
{
- ir_node *cur_block = get_cur_block();
-
- ir_node *one_block = new_immBlock();
- set_cur_block(one_block);
- ir_node *one = new_Const(get_mode_one(mode));
- ir_node *jmp_one = new_d_Jmp(dbgi);
-
- ir_node *zero_block = new_immBlock();
- set_cur_block(zero_block);
- ir_node *zero = new_Const(get_mode_null(mode));
- ir_node *jmp_zero = new_d_Jmp(dbgi);
-
- set_cur_block(cur_block);
+ ir_node *const one_block = new_immBlock();
+ ir_node *const zero_block = new_immBlock();
create_condition_evaluation(expression, one_block, zero_block);
mature_immBlock(one_block);
mature_immBlock(zero_block);
- ir_node *in_cf[2] = { jmp_one, jmp_zero };
- ir_node *block = new_Block(2, in_cf);
+ ir_node *const jmp_one = new_rd_Jmp(dbgi, one_block);
+ ir_node *const jmp_zero = new_rd_Jmp(dbgi, zero_block);
+ ir_node *const in_cf[2] = { jmp_one, jmp_zero };
+ ir_node *const block = new_Block(lengthof(in_cf), in_cf);
set_cur_block(block);
- ir_node *in[2] = { one, zero };
- ir_node *val = new_d_Phi(dbgi, 2, in, mode);
+ ir_node *const one = new_Const(get_mode_one(mode));
+ ir_node *const zero = new_Const(get_mode_null(mode));
+ ir_node *const in[2] = { one, zero };
+ ir_node *const val = new_d_Phi(dbgi, lengthof(in), in, mode);
return val;
}
type_t *type = skip_typeref(expression->base.type);
ir_mode *mode = get_ir_mode_arithmetic(type);
- if (is_constant_expression(expression->left)) {
+ if (is_constant_expression(expression->left) == EXPR_CLASS_CONSTANT) {
bool val = fold_constant_to_bool(expression->left);
expression_kind_t ekind = expression->base.kind;
assert(ekind == EXPR_BINARY_LOGICAL_AND || ekind == EXPR_BINARY_LOGICAL_OR);
}
}
- if (is_constant_expression(expression->right)) {
+ if (is_constant_expression(expression->right) == EXPR_CLASS_CONSTANT) {
bool valr = fold_constant_to_bool(expression->right);
return valr ?
new_Const(get_mode_one(mode)) :
init_ir_types();
- assert(is_constant_expression(expression));
+ assert(is_constant_expression(expression) == EXPR_CLASS_CONSTANT);
ir_graph *old_current_ir_graph = current_ir_graph;
current_ir_graph = get_const_code_irg();
dbg_info *const dbgi = get_dbg_info(&expression->base.source_position);
/* first try to fold a constant condition */
- if (is_constant_expression(expression->condition)) {
+ if (is_constant_expression(expression->condition) == EXPR_CLASS_CONSTANT) {
bool val = fold_constant_to_bool(expression->condition);
if (val) {
expression_t *true_expression = expression->true_expression;
}
}
- ir_node *cur_block = get_cur_block();
+ ir_node *const true_block = new_immBlock();
+ ir_node *const false_block = new_immBlock();
+ ir_node *const cond_expr = create_condition_evaluation(expression->condition, true_block, false_block);
+ mature_immBlock(true_block);
+ mature_immBlock(false_block);
- /* create the true block */
- ir_node *true_block = new_immBlock();
set_cur_block(true_block);
+ ir_node *true_val;
+ if (expression->true_expression != NULL) {
+ true_val = expression_to_firm(expression->true_expression);
+ } else if (cond_expr != NULL && get_irn_mode(cond_expr) != mode_b) {
+ true_val = cond_expr;
+ } else {
+ /* Condition ended with a short circuit (&&, ||, !) operation or a
+ * comparison. Generate a "1" as value for the true branch. */
+ true_val = new_Const(get_mode_one(mode_Is));
+ }
+ ir_node *const true_jmp = new_d_Jmp(dbgi);
- ir_node *true_val = expression->true_expression != NULL ?
- expression_to_firm(expression->true_expression) : NULL;
- ir_node *true_jmp = new_Jmp();
-
- /* create the false block */
- ir_node *false_block = new_immBlock();
set_cur_block(false_block);
-
- ir_node *false_val = expression_to_firm(expression->false_expression);
- ir_node *false_jmp = new_Jmp();
-
- /* create the condition evaluation */
- set_cur_block(cur_block);
- ir_node *const cond_expr = create_condition_evaluation(expression->condition, true_block, false_block);
- if (expression->true_expression == NULL) {
- if (cond_expr != NULL && get_irn_mode(cond_expr) != mode_b) {
- true_val = cond_expr;
- } else {
- /* Condition ended with a short circuit (&&, ||, !) operation or a
- * comparison. Generate a "1" as value for the true branch. */
- true_val = new_Const(get_mode_one(mode_Is));
- }
- }
- mature_immBlock(true_block);
- mature_immBlock(false_block);
+ ir_node *const false_val = expression_to_firm(expression->false_expression);
+ ir_node *const false_jmp = new_d_Jmp(dbgi);
/* create the common block */
- ir_node *in_cf[2] = { true_jmp, false_jmp };
- ir_node *block = new_Block(2, in_cf);
+ ir_node *const in_cf[2] = { true_jmp, false_jmp };
+ ir_node *const block = new_Block(lengthof(in_cf), in_cf);
set_cur_block(block);
/* TODO improve static semantics, so either both or no values are NULL */
if (true_val == NULL || false_val == NULL)
return NULL;
- ir_node *in[2] = { true_val, false_val };
- ir_mode *mode = get_irn_mode(true_val);
+ ir_node *const in[2] = { true_val, false_val };
+ ir_mode *const mode = get_irn_mode(true_val);
assert(get_irn_mode(false_val) == mode);
- ir_node *val = new_d_Phi(dbgi, 2, in, mode);
+ ir_node *const val = new_d_Phi(dbgi, lengthof(in), in, mode);
return val;
}
ir_mode *mode = get_ir_mode_arithmetic(expression->base.type);
long v;
- if (is_constant_expression(expression->value)) {
+ if (is_constant_expression(expression->value) == EXPR_CLASS_CONSTANT) {
v = 1;
} else {
v = 0;
return res;
}
- if (is_constant_expression(expression)) {
+ if (is_constant_expression(expression) == EXPR_CLASS_CONSTANT) {
ir_node *res = _expression_to_firm(expression);
ir_mode *mode = get_ir_mode_arithmetic(expression->base.type);
assert(is_Const(res));
/* set branch prediction info based on __builtin_expect */
if (is_builtin_expect(expression) && is_Cond(cond)) {
call_argument_t *argument = expression->call.arguments->next;
- if (is_constant_expression(argument->expression)) {
+ if (is_constant_expression(argument->expression) == EXPR_CLASS_CONSTANT) {
bool cnst = fold_constant_to_bool(argument->expression);
cond_jmp_predicate pred;
return;
}
- if (!is_constant_initializer(initializer)) {
+ if (is_constant_initializer(initializer) == EXPR_CLASS_VARIABLE) {
bool old_initializer_use_bitfield_basetype
= initializer_use_bitfield_basetype;
initializer_use_bitfield_basetype = true;
static void if_statement_to_firm(if_statement_t *statement)
{
- ir_node *cur_block = get_cur_block();
-
- ir_node *fallthrough_block = NULL;
-
- /* the true (blocks) */
- ir_node *const true_block = new_immBlock();
- set_cur_block(true_block);
- statement_to_firm(statement->true_statement);
+ /* Create the condition. */
+ ir_node *true_block = NULL;
+ ir_node *false_block = NULL;
if (get_cur_block() != NULL) {
- ir_node *jmp = new_Jmp();
- if (fallthrough_block == NULL)
- fallthrough_block = new_immBlock();
- add_immBlock_pred(fallthrough_block, jmp);
+ true_block = new_immBlock();
+ false_block = new_immBlock();
+ create_condition_evaluation(statement->condition, true_block, false_block);
+ mature_immBlock(true_block);
}
- /* the false (blocks) */
- ir_node *false_block = NULL;
+ /* Create the false statement.
+ * Hadle false before true, so if no false statement is present, then the
+ * empty false block is reused as fallthrough block. */
+ ir_node *fallthrough_block = NULL;
if (statement->false_statement != NULL) {
- false_block = new_immBlock();
+ if (false_block != NULL) {
+ mature_immBlock(false_block);
+ }
set_cur_block(false_block);
-
statement_to_firm(statement->false_statement);
if (get_cur_block() != NULL) {
- ir_node *jmp = new_Jmp();
- if (fallthrough_block == NULL)
- fallthrough_block = new_immBlock();
- add_immBlock_pred(fallthrough_block, jmp);
+ fallthrough_block = new_immBlock();
+ add_immBlock_pred(fallthrough_block, new_Jmp());
}
+ } else {
+ fallthrough_block = false_block;
}
- /* create the condition */
- if (cur_block != NULL) {
- if (false_block == NULL) {
- if (fallthrough_block == NULL)
- fallthrough_block = new_immBlock();
- false_block = fallthrough_block;
+ /* Create the true statement. */
+ set_cur_block(true_block);
+ statement_to_firm(statement->true_statement);
+ if (get_cur_block() != NULL) {
+ if (fallthrough_block == NULL) {
+ fallthrough_block = new_immBlock();
}
-
- set_cur_block(cur_block);
- create_condition_evaluation(statement->condition, true_block,
- false_block);
+ add_immBlock_pred(fallthrough_block, new_Jmp());
}
- mature_immBlock(true_block);
- if (false_block != fallthrough_block && false_block != NULL) {
- mature_immBlock(false_block);
- }
+ /* Handle the block after the if-statement. */
if (fallthrough_block != NULL) {
mature_immBlock(fallthrough_block);
}
-
set_cur_block(fallthrough_block);
}
-static void while_statement_to_firm(while_statement_t *statement)
+/* Create a jump node which jumps into target_block, if the current block is
+ * reachable. */
+static void jump_if_reachable(ir_node *const target_block)
{
- /* create the header block */
- ir_node *header_block = new_immBlock();
if (get_cur_block() != NULL) {
- ir_node *const jmp = new_Jmp();
- add_immBlock_pred(header_block, jmp);
- }
-
- /* the loop body */
- ir_node *old_continue_label = continue_label;
- ir_node *old_break_label = break_label;
- continue_label = header_block;
- break_label = NULL;
-
- ir_node *body_block = new_immBlock();
- set_cur_block(body_block);
- statement_to_firm(statement->body);
- ir_node *false_block = break_label;
-
- assert(continue_label == header_block);
- continue_label = old_continue_label;
- break_label = old_break_label;
-
- if (get_cur_block() != NULL) {
- ir_node *const jmp = new_Jmp();
- add_immBlock_pred(header_block, jmp);
+ add_immBlock_pred(target_block, new_Jmp());
}
+}
- /* shortcut for while(true) */
- if (is_constant_expression(statement->condition)
- && fold_constant_to_bool(statement->condition) != 0) {
- set_cur_block(header_block);
- ir_node *header_jmp = new_Jmp();
- add_immBlock_pred(body_block, header_jmp);
+static void while_statement_to_firm(while_statement_t *statement)
+{
+ /* Create the header block */
+ ir_node *const header_block = new_immBlock();
+ jump_if_reachable(header_block);
+
+ /* Create the condition. */
+ ir_node * body_block;
+ ir_node * false_block;
+ expression_t *const cond = statement->condition;
+ if (is_constant_expression(cond) == EXPR_CLASS_CONSTANT &&
+ fold_constant_to_bool(cond)) {
+ /* Shortcut for while (true). */
+ body_block = header_block;
+ false_block = NULL;
- keep_alive(body_block);
- keep_all_memory(body_block);
- set_cur_block(body_block);
+ keep_alive(header_block);
+ keep_all_memory(header_block);
} else {
- if (false_block == NULL) {
- false_block = new_immBlock();
- }
+ body_block = new_immBlock();
+ false_block = new_immBlock();
- /* create the condition */
set_cur_block(header_block);
-
- create_condition_evaluation(statement->condition, body_block,
- false_block);
+ create_condition_evaluation(cond, body_block, false_block);
+ mature_immBlock(body_block);
}
- mature_immBlock(body_block);
+ ir_node *const old_continue_label = continue_label;
+ ir_node *const old_break_label = break_label;
+ continue_label = header_block;
+ break_label = false_block;
+
+ /* Create the loop body. */
+ set_cur_block(body_block);
+ statement_to_firm(statement->body);
+ jump_if_reachable(header_block);
+
mature_immBlock(header_block);
+ assert(false_block == NULL || false_block == break_label);
+ false_block = break_label;
if (false_block != NULL) {
mature_immBlock(false_block);
}
-
set_cur_block(false_block);
+
+ assert(continue_label == header_block);
+ continue_label = old_continue_label;
+ break_label = old_break_label;
}
-static void do_while_statement_to_firm(do_while_statement_t *statement)
+static ir_node *get_break_label(void)
{
- ir_node *jmp = NULL;
- if (get_cur_block() != NULL) {
- jmp = new_Jmp();
+ if (break_label == NULL) {
+ break_label = new_immBlock();
}
+ return break_label;
+}
+static void do_while_statement_to_firm(do_while_statement_t *statement)
+{
/* create the header block */
ir_node *header_block = new_immBlock();
/* the loop body */
ir_node *body_block = new_immBlock();
- if (jmp != NULL) {
- add_immBlock_pred(body_block, jmp);
- }
+ jump_if_reachable(body_block);
ir_node *old_continue_label = continue_label;
ir_node *old_break_label = break_label;
set_cur_block(body_block);
statement_to_firm(statement->body);
- ir_node *false_block = break_label;
+ ir_node *const false_block = get_break_label();
assert(continue_label == header_block);
continue_label = old_continue_label;
break_label = old_break_label;
- if (get_cur_block() != NULL) {
- ir_node *body_jmp = new_Jmp();
- add_immBlock_pred(header_block, body_jmp);
- mature_immBlock(header_block);
- }
-
- if (false_block == NULL) {
- false_block = new_immBlock();
- }
+ jump_if_reachable(header_block);
/* create the condition */
+ mature_immBlock(header_block);
set_cur_block(header_block);
create_condition_evaluation(statement->condition, body_block, false_block);
mature_immBlock(body_block);
- mature_immBlock(header_block);
mature_immBlock(false_block);
set_cur_block(false_block);
static void for_statement_to_firm(for_statement_t *statement)
{
- ir_node *jmp = NULL;
-
/* create declarations */
entity_t *entity = statement->scope.entities;
for ( ; entity != NULL; entity = entity->base.next) {
if (statement->initialisation != NULL) {
expression_to_firm(statement->initialisation);
}
-
- jmp = new_Jmp();
}
+ /* Create the header block */
+ ir_node *const header_block = new_immBlock();
+ jump_if_reachable(header_block);
- /* create the step block */
- ir_node *const step_block = new_immBlock();
- set_cur_block(step_block);
- if (statement->step != NULL) {
- expression_to_firm(statement->step);
- }
- ir_node *const step_jmp = new_Jmp();
+ /* Create the condition. */
+ ir_node *body_block;
+ ir_node *false_block;
+ if (statement->condition != NULL) {
+ body_block = new_immBlock();
+ false_block = new_immBlock();
- /* create the header block */
- ir_node *const header_block = new_immBlock();
- set_cur_block(header_block);
- if (jmp != NULL) {
- add_immBlock_pred(header_block, jmp);
+ set_cur_block(header_block);
+ create_condition_evaluation(statement->condition, body_block, false_block);
+ mature_immBlock(body_block);
+ } else {
+ /* for-ever. */
+ body_block = header_block;
+ false_block = NULL;
+
+ keep_alive(header_block);
+ keep_all_memory(header_block);
}
- add_immBlock_pred(header_block, step_jmp);
- /* the false block */
- ir_node *const false_block = new_immBlock();
+ /* Create the step block, if necessary. */
+ ir_node * step_block = header_block;
+ expression_t *const step = statement->step;
+ if (step != NULL) {
+ step_block = new_immBlock();
+ }
- /* the loop body */
ir_node *const old_continue_label = continue_label;
ir_node *const old_break_label = break_label;
continue_label = step_block;
break_label = false_block;
- ir_node *const body_block = new_immBlock();
+ /* Create the loop body. */
set_cur_block(body_block);
statement_to_firm(statement->body);
+ jump_if_reachable(step_block);
- assert(continue_label == step_block);
- assert(break_label == false_block);
- continue_label = old_continue_label;
- break_label = old_break_label;
-
- if (get_cur_block() != NULL) {
- jmp = new_Jmp();
- add_immBlock_pred(step_block, jmp);
- }
-
- /* create the condition */
- set_cur_block(header_block);
- if (statement->condition != NULL) {
- create_condition_evaluation(statement->condition, body_block,
- false_block);
- } else {
- keep_alive(header_block);
- keep_all_memory(header_block);
- jmp = new_Jmp();
- add_immBlock_pred(body_block, jmp);
+ /* Create the step code. */
+ if (step != NULL) {
+ mature_immBlock(step_block);
+ set_cur_block(step_block);
+ expression_to_firm(step);
+ jump_if_reachable(header_block);
}
- mature_immBlock(body_block);
- mature_immBlock(false_block);
- mature_immBlock(step_block);
mature_immBlock(header_block);
- mature_immBlock(false_block);
-
+ assert(false_block == NULL || false_block == break_label);
+ false_block = break_label;
+ if (false_block != NULL) {
+ mature_immBlock(false_block);
+ }
set_cur_block(false_block);
+
+ assert(continue_label == step_block);
+ continue_label = old_continue_label;
+ break_label = old_break_label;
}
static void create_jump_statement(const statement_t *statement,
set_cur_block(NULL);
}
-static ir_node *get_break_label(void)
-{
- if (break_label == NULL) {
- break_label = new_immBlock();
- }
- return break_label;
-}
-
static void switch_statement_to_firm(switch_statement_t *statement)
{
ir_node *first_block = NULL;
set_Cond_default_proj(cond, default_proj_nr);
}
- if (statement->body != NULL) {
- statement_to_firm(statement->body);
- }
+ statement_to_firm(statement->body);
- if (get_cur_block() != NULL) {
- ir_node *jmp = new_Jmp();
- add_immBlock_pred(get_break_label(), jmp);
- }
+ jump_if_reachable(get_break_label());
if (!saw_default_label && first_block != NULL) {
set_cur_block(first_block);
if (statement->is_empty_range)
return;
- dbg_info *dbgi = get_dbg_info(&statement->base.source_position);
-
- ir_node *const fallthrough = (get_cur_block() == NULL ? NULL : new_Jmp());
-
- ir_node *proj;
ir_node *block = new_immBlock();
+ /* Fallthrough from previous case */
+ jump_if_reachable(block);
if (current_switch_cond != NULL) {
set_cur_block(get_nodes_block(current_switch_cond));
+ dbg_info *const dbgi = get_dbg_info(&statement->base.source_position);
if (statement->expression != NULL) {
long pn = statement->first_case;
long end_pn = statement->last_case;
assert(pn <= end_pn);
/* create jumps for all cases in the given range */
do {
- proj = new_d_Proj(dbgi, current_switch_cond, mode_X, pn);
+ ir_node *const proj = new_d_Proj(dbgi, current_switch_cond, mode_X, pn);
add_immBlock_pred(block, proj);
} while (pn++ < end_pn);
} else {
saw_default_label = true;
- proj = new_d_Proj(dbgi, current_switch_cond, mode_X,
- current_switch->default_proj_nr);
-
+ ir_node *const proj = new_d_Proj(dbgi, current_switch_cond, mode_X,
+ current_switch->default_proj_nr);
add_immBlock_pred(block, proj);
}
}
- if (fallthrough != NULL) {
- add_immBlock_pred(block, fallthrough);
- }
mature_immBlock(block);
set_cur_block(block);
- if (statement->statement != NULL) {
- statement_to_firm(statement->statement);
- }
+ statement_to_firm(statement->statement);
}
static void label_to_firm(const label_statement_t *statement)
{
ir_node *block = get_label_block(statement->label);
-
- if (get_cur_block() != NULL) {
- ir_node *jmp = new_Jmp();
- add_immBlock_pred(block, jmp);
- }
+ jump_if_reachable(block);
set_cur_block(block);
keep_alive(block);
keep_all_memory(block);
- if (statement->statement != NULL) {
- statement_to_firm(statement->statement);
- }
+ statement_to_firm(statement->statement);
}
static void goto_to_firm(const goto_statement_t *statement)