type_t *from_type, type_t *type)
{
type = skip_typeref(type);
+ if (type == type_void) {
+ /* make sure firm type is constructed */
+ (void) get_ir_type(type);
+ return NULL;
+ }
if (!is_type_scalar(type)) {
/* make sure firm type is constructed */
(void) get_ir_type(type);
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;
}
}
}
- 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;
}
/* we're past the last member of the current sub-aggregate, try if we
* can ascend in the type hierarchy and continue with another subobject */
- size_t len = ARR_LEN(path->path);
+ size_t len = ARR_LEN(path->path);
if (len > 1) {
ascend_from_subtype(path);
panic("unknown initializer");
}
-static void create_dynamic_initializer_sub(ir_initializer_t *initializer,
- ir_entity *entity, ir_type *type, dbg_info *dbgi, ir_node *base_addr)
+/** ANSI C §6.7.8:21: If there are fewer initializers [..] than there
+ * are elements [...] the remainder of the aggregate shall be initialized
+ * implicitly the same as objects that have static storage duration. */
+static void create_dynamic_null_initializer(ir_entity *entity, dbg_info *dbgi,
+ ir_node *base_addr)
{
- switch(get_initializer_kind(initializer)) {
- case IR_INITIALIZER_NULL: {
- /* ANSI C §6.7.8:21: If there are fewer initializers [..] than there
- are elements [...] the remainder of the aggregate shall be initialized
- implicitly the same as objects that have static storage duration. */
- ir_type *ent_type = get_entity_type(entity);
- ir_mode *value_mode = get_type_mode(ent_type);
- ir_node *node = new_Const_long(value_mode, 0);
+ /* for unions we must NOT do anything for null initializers */
+ ir_type *owner = get_entity_owner(entity);
+ if (is_Union_type(owner)) {
+ return;
+ }
- /* is it a bitfield type? */
- if (is_Primitive_type(ent_type) &&
- get_primitive_base_type(ent_type) != NULL) {
- bitfield_store_to_firm(dbgi, entity, base_addr, node, false);
- return;
+ ir_type *ent_type = get_entity_type(entity);
+ /* create sub-initializers for a compound type */
+ if (is_compound_type(ent_type)) {
+ unsigned n_members = get_compound_n_members(ent_type);
+ for (unsigned n = 0; n < n_members; ++n) {
+ ir_entity *member = get_compound_member(ent_type, n);
+ ir_node *addr = new_d_simpleSel(dbgi, new_NoMem(), base_addr,
+ member);
+ create_dynamic_null_initializer(member, dbgi, addr);
}
+ return;
+ }
+ if (is_Array_type(ent_type)) {
+ assert(has_array_upper_bound(ent_type, 0));
+ long n = get_array_upper_bound_int(ent_type, 0);
+ for (long i = 0; i < n; ++i) {
+ ir_tarval *index_tv = new_tarval_from_long(i, mode_uint);
+ ir_node *cnst = new_d_Const(dbgi, index_tv);
+ ir_node *in[1] = { cnst };
+ ir_entity *arrent = get_array_element_entity(ent_type);
+ ir_node *addr = new_d_Sel(dbgi, new_NoMem(), base_addr, 1, in,
+ arrent);
+ create_dynamic_null_initializer(arrent, dbgi, addr);
+ }
+ return;
+ }
- assert(get_type_mode(type) == get_irn_mode(node));
- ir_node *mem = get_store();
- ir_node *store = new_d_Store(dbgi, mem, base_addr, node, cons_none);
- ir_node *proj_m = new_Proj(store, mode_M, pn_Store_M);
- set_store(proj_m);
+ ir_mode *value_mode = get_type_mode(ent_type);
+ ir_node *node = new_Const_long(value_mode, 0);
+
+ /* is it a bitfield type? */
+ if (is_Primitive_type(ent_type) &&
+ get_primitive_base_type(ent_type) != NULL) {
+ bitfield_store_to_firm(dbgi, entity, base_addr, node, false);
return;
}
+
+ ir_node *mem = get_store();
+ ir_node *store = new_d_Store(dbgi, mem, base_addr, node, cons_none);
+ ir_node *proj_m = new_Proj(store, mode_M, pn_Store_M);
+ set_store(proj_m);
+}
+
+static void create_dynamic_initializer_sub(ir_initializer_t *initializer,
+ ir_entity *entity, ir_type *type, dbg_info *dbgi, ir_node *base_addr)
+{
+ switch(get_initializer_kind(initializer)) {
+ case IR_INITIALIZER_NULL:
+ create_dynamic_null_initializer(entity, dbgi, base_addr);
+ return;
case IR_INITIALIZER_CONST: {
ir_node *node = get_initializer_const_value(initializer);
ir_type *ent_type = get_entity_type(entity);
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 *true_block = NULL;
- if (statement->true_statement != NULL) {
- true_block = new_immBlock();
- set_cur_block(true_block);
- statement_to_firm(statement->true_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);
- }
+ /* Create the condition. */
+ ir_node *true_block = NULL;
+ ir_node *false_block = NULL;
+ if (get_cur_block() != NULL) {
+ 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 (true_block == NULL || false_block == NULL) {
- if (fallthrough_block == NULL)
- fallthrough_block = new_immBlock();
- if (true_block == NULL)
- true_block = fallthrough_block;
- if (false_block == NULL)
- 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)
{
- ir_node *jmp = NULL;
if (get_cur_block() != NULL) {
- jmp = new_Jmp();
+ add_immBlock_pred(target_block, new_Jmp());
}
+}
- /* create the header block */
- ir_node *header_block = new_immBlock();
- if (jmp != NULL) {
- 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;
+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);
- if (get_cur_block() != NULL) {
- jmp = new_Jmp();
- add_immBlock_pred(header_block, jmp);
- }
+ /* Create the condition. */
+ ir_node * body_block;
+ ir_node * false_block;
+ expression_t *const cond = statement->condition;
+ if (is_constant_expression(cond) && fold_constant_to_bool(cond)) {
+ /* Shortcut for while (true). */
+ body_block = header_block;
+ false_block = NULL;
- /* 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);
-
- 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 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 header block */
+ /* 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);
- }
- add_immBlock_pred(header_block, step_jmp);
-
- /* the false block */
- ir_node *const false_block = new_immBlock();
+ jump_if_reachable(header_block);
- /* the loop body */
+ /* Create the condition. */
ir_node *body_block;
- if (statement->body != NULL) {
- ir_node *const old_continue_label = continue_label;
- ir_node *const old_break_label = break_label;
- continue_label = step_block;
- break_label = false_block;
-
- body_block = new_immBlock();
- set_cur_block(body_block);
- statement_to_firm(statement->body);
-
- assert(continue_label == step_block);
- assert(break_label == false_block);
- continue_label = old_continue_label;
- break_label = old_break_label;
+ ir_node *false_block;
+ if (statement->condition != NULL) {
+ body_block = new_immBlock();
+ false_block = new_immBlock();
- if (get_cur_block() != NULL) {
- jmp = new_Jmp();
- add_immBlock_pred(step_block, jmp);
- }
+ set_cur_block(header_block);
+ create_condition_evaluation(statement->condition, body_block, false_block);
+ mature_immBlock(body_block);
} else {
- body_block = step_block;
- }
+ /* for-ever. */
+ body_block = header_block;
+ false_block = NULL;
- /* 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);
}
- mature_immBlock(body_block);
- mature_immBlock(false_block);
- mature_immBlock(step_block);
- mature_immBlock(header_block);
- mature_immBlock(false_block);
+ /* 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();
+ }
+ ir_node *const old_continue_label = continue_label;
+ ir_node *const old_break_label = break_label;
+ continue_label = step_block;
+ break_label = false_block;
+
+ /* Create the loop body. */
+ set_cur_block(body_block);
+ statement_to_firm(statement->body);
+ jump_if_reachable(step_block);
+
+ /* 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(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 == 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;
}
statement->default_proj_nr = default_proj_nr;
/* safety check: cond might already be folded to a Bad */
- if (is_Cond(cond)) {
+ if (cond != NULL && is_Cond(cond)) {
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)
set_entity_ld_ident(ptr, new_id_from_chars("", 0));
set_entity_compiler_generated(ptr, 1);
- set_entity_visibility(ptr, ir_visibility_local);
+ set_entity_visibility(ptr, ir_visibility_private);
add_entity_linkage(ptr, IR_LINKAGE_CONSTANT|IR_LINKAGE_HIDDEN_USER);
set_atomic_ent_value(ptr, val);
}