static ir_node *break_label;
static ir_node *current_switch;
static bool saw_default_label;
-static label_t **all_labels;
static entity_t **inner_functions;
static ir_node *ijmp_list;
+static ir_node **ijmp_blocks;
static bool constant_folding;
#define PUSH_BREAK(val) \
return irtype;
}
-static ir_tarval *fold_constant_to_tarval(expression_t const *);
-
-static void determine_enum_values(enum_type_t *const type)
+void determine_enum_values(enum_type_t *const type)
{
ir_mode *const mode = atomic_modes[type->base.akind];
ir_tarval *const one = get_mode_one(mode);
decl_modifiers_t modifiers = entity->declaration.modifiers;
if (is_method_entity(irentity)) {
- if (modifiers & DM_PURE) {
- set_entity_additional_properties(irentity, mtp_property_pure);
- }
- if (modifiers & DM_CONST) {
+ if (modifiers & DM_PURE)
+ add_entity_additional_properties(irentity, mtp_property_pure);
+ if (modifiers & DM_CONST)
add_entity_additional_properties(irentity, mtp_property_const);
- }
+ if (modifiers & DM_NOINLINE)
+ add_entity_additional_properties(irentity, mtp_property_noinline);
+ if (modifiers & DM_FORCEINLINE)
+ add_entity_additional_properties(irentity, mtp_property_always_inline);
+ if (modifiers & DM_NAKED)
+ add_entity_additional_properties(irentity, mtp_property_naked);
+ if (entity->kind == ENTITY_FUNCTION && entity->function.is_inline)
+ add_entity_additional_properties(irentity,
+ mtp_property_inline_recommended);
}
if ((modifiers & DM_USED) && declaration_is_definition(entity)) {
add_entity_linkage(irentity, IR_LINKAGE_HIDDEN_USER);
static void init_ir_types(void);
-static ir_tarval *fold_constant_to_tarval(const expression_t *expression)
+ir_tarval *fold_constant_to_tarval(const expression_t *expression)
{
assert(is_constant_expression(expression) == EXPR_CLASS_CONSTANT);
ir_node *block = new_immBlock();
label->block = block;
-
- ARR_APP1(label_t *, all_labels, label);
+ if (label->address_taken)
+ ARR_APP1(ir_node*, ijmp_blocks, block);
return block;
}
}
if (l->is_empty_range)
continue;
- ir_tarval *min = fold_constant_to_tarval(l->expression);
- ir_tarval *max = min;
+ ir_tarval *min = l->first_case;
+ ir_tarval *max = l->last_case;
long pn = (long) i+1;
- if (l->end_range != NULL)
- max = fold_constant_to_tarval(l->end_range);
ir_switch_table_set(res, i++, min, max, pn);
l->pn = pn;
}
static ir_node *case_label_to_firm(const case_label_statement_t *statement)
{
- if (statement->is_empty_range)
- return NULL;
-
- if (current_switch != NULL) {
+ if (current_switch != NULL && !statement->is_empty_range) {
ir_node *block = new_immBlock();
/* Fallthrough from previous case */
jump_if_reachable(block);
return statement_to_firm(statement->statement);
}
+static void try_mature_label(label_t *const label)
+{
+ if (--label->n_users == 0 && !label->address_taken)
+ mature_immBlock(label->block);
+}
+
static ir_node *label_to_firm(const label_statement_t *statement)
{
- ir_node *block = get_label_block(statement->label);
+ label_t *const label = statement->label;
+ ir_node *const block = get_label_block(label);
jump_to(block);
keep_alive(block);
keep_all_memory(block);
+ try_mature_label(label);
+
return statement_to_firm(statement->statement);
}
+static ir_node *goto_statement_to_firm(goto_statement_t *const stmt)
+{
+ label_t *const label = stmt->label;
+ create_jump_statement((statement_t*)stmt, get_label_block(label));
+ try_mature_label(label);
+ return NULL;
+}
+
static ir_node *computed_goto_to_firm(computed_goto_statement_t const *const statement)
{
if (!currently_reachable())
case STATEMENT_EMPTY: return NULL; /* nothing */
case STATEMENT_EXPRESSION: return expression_statement_to_firm( &stmt->expression);
case STATEMENT_FOR: return for_statement_to_firm( &stmt->fors);
+ case STATEMENT_GOTO: return goto_statement_to_firm( &stmt->gotos);
case STATEMENT_IF: return if_statement_to_firm( &stmt->ifs);
case STATEMENT_LABEL: return label_to_firm( &stmt->label);
case STATEMENT_LEAVE: return leave_statement_to_firm( &stmt->leave);
case STATEMENT_BREAK: return create_jump_statement(stmt, get_break_label());
case STATEMENT_CONTINUE: return create_jump_statement(stmt, continue_label);
- case STATEMENT_GOTO: return create_jump_statement(stmt, get_label_block(stmt->gotos.label));
case STATEMENT_ERROR: panic("error statement found");
}
}
}
-/**
- * Handle additional decl modifiers for IR-graphs
- *
- * @param irg the IR-graph
- * @param dec_modifiers additional modifiers
- */
-static void handle_decl_modifier_irg(ir_graph *irg,
- decl_modifiers_t decl_modifiers)
-{
- if (decl_modifiers & DM_NAKED) {
- /* TRUE if the declaration includes the Microsoft
- __declspec(naked) specifier. */
- add_irg_additional_properties(irg, mtp_property_naked);
- }
- if (decl_modifiers & DM_FORCEINLINE) {
- /* TRUE if the declaration includes the
- Microsoft __forceinline specifier. */
- set_irg_inline_property(irg, irg_inline_forced);
- }
- if (decl_modifiers & DM_NOINLINE) {
- /* TRUE if the declaration includes the Microsoft
- __declspec(noinline) specifier. */
- set_irg_inline_property(irg, irg_inline_forbidden);
- }
-}
-
static void add_function_pointer(ir_type *segment, ir_entity *method,
const char *unique_template)
{
current_function_name = NULL;
current_funcsig = NULL;
- assert(all_labels == NULL);
- all_labels = NEW_ARR_F(label_t *, 0);
- ijmp_list = NULL;
+ assert(ijmp_blocks == NULL);
+ ijmp_blocks = NEW_ARR_F(ir_node*, 0);
+ ijmp_list = NULL;
int n_local_vars = get_function_n_local_vars(entity);
ir_graph *irg = new_ir_graph(function_entity, n_local_vars);
set_irn_dbg_info(get_irg_start_block(irg),
get_entity_dbg_info(function_entity));
- /* set inline flags */
- if (entity->function.is_inline)
- set_irg_inline_property(irg, irg_inline_recomended);
- handle_decl_modifier_irg(irg, entity->declaration.modifiers);
-
next_value_number_function = 0;
initialize_function_parameters(entity);
current_static_link = entity->function.static_link;
add_immBlock_pred(end_block, ret);
}
- for (int i = ARR_LEN(all_labels) - 1; i >= 0; --i) {
- label_t *label = all_labels[i];
- if (label->address_taken) {
- gen_ijmp_branches(label->block);
- }
- mature_immBlock(label->block);
+ for (size_t i = ARR_LEN(ijmp_blocks); i-- != 0;) {
+ ir_node *const block = ijmp_blocks[i];
+ gen_ijmp_branches(block);
+ mature_immBlock(block);
}
- DEL_ARR_F(all_labels);
- all_labels = NULL;
+ DEL_ARR_F(ijmp_blocks);
+ ijmp_blocks = NULL;
irg_finalize_cons(irg);