static const backend_params *be_params;
static ir_type *ir_type_char;
-static ir_type *ir_type_wchar_t;
/* architecture specific floating point arithmetic mode (if any) */
static ir_mode *mode_float_arithmetic;
static ir_node *current_switch;
static bool saw_default_label;
static entity_t **inner_functions;
-static ir_node *ijmp_list;
+static jump_target ijmp_target;
+static ir_node **ijmp_ops;
static ir_node **ijmp_blocks;
static bool constant_folding;
case ENTITY_LOCAL_LABEL:
break;
}
- panic("declaration_is_definition called on non-declaration");
+ panic("entity is not a declaration");
}
/**
ir_initializer_t *const initializer = create_initializer_compound(slen);
ir_type * elem_type;
switch (value->encoding) {
- case STRING_ENCODING_CHAR: {
+ case STRING_ENCODING_CHAR:
+ case STRING_ENCODING_UTF8: {
elem_type = ir_type_char;
ir_mode *const mode = get_type_mode(elem_type);
goto finish;
}
- case STRING_ENCODING_WIDE: {
- elem_type = ir_type_wchar_t;
+ {
+ type_t *type;
+ case STRING_ENCODING_CHAR16: type = type_char16_t; goto init_wide;
+ case STRING_ENCODING_CHAR32: type = type_char32_t; goto init_wide;
+ case STRING_ENCODING_WIDE: type = type_wchar_t; goto init_wide;
+init_wide:;
+ elem_type = get_ir_type(type);
ir_mode *const mode = get_type_mode(elem_type);
char const *p = value->begin;
break;
default:
- panic("Invalid literal kind found");
+ panic("invalid literal kind");
}
dbg_info *dbgi = get_dbg_info(&literal->base.source_position);
}
default:
- panic("Invalid literal kind found");
+ panic("invalid literal kind");
}
dbg_info *dbgi = get_dbg_info(&literal->base.source_position);
}
/**
- * Keep all memory edges of the given block.
+ * Keep the current block and memory.
+ * This is necessary for all loops, because they could become infinite.
*/
-static void keep_all_memory(ir_node *block)
+static void keep_loop(void)
{
- ir_node *old = get_cur_block();
-
- set_cur_block(block);
+ keep_alive(get_cur_block());
keep_alive(get_store());
- /* TODO: keep all memory edges from restricted pointers */
- set_cur_block(old);
}
static ir_node *enum_constant_to_firm(reference_expression_t const *const ref)
panic("not implemented reference type");
}
- panic("reference to declaration with unknown type found");
+ panic("reference to declaration with unknown type");
}
static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
case BUILTIN_LIBC_CHECK:
panic("builtin did not produce an entity");
}
- panic("invalid builtin found");
+ panic("invalid builtin");
}
/**
store_value = result;
break;
default:
- panic("no incdec expr in create_incdec");
+ panic("no incdec expr");
}
set_value_for_expression_addr(value_expr, store_value, addr);
default:
break;
}
- panic("invalid UNEXPR type found");
+ panic("invalid unary expression type");
}
/**
type_t *type = expression->type;
initializer_t *initializer = expression->initializer;
- if (is_constant_initializer(initializer) == EXPR_CLASS_CONSTANT) {
+ if (expression->global_scope ||
+ ((type->base.qualifiers & TYPE_QUALIFIER_CONST)
+ && is_constant_initializer(initializer) == EXPR_CLASS_CONSTANT)) {
ir_entity *entity = create_initializer_entity(dbgi, initializer, type);
return create_symconst(dbgi, entity);
} else {
static ir_node *conditional_to_firm(const conditional_expression_t *expression)
{
- dbg_info *const dbgi = get_dbg_info(&expression->base.source_position);
-
/* first try to fold a constant condition */
if (is_constant_expression(expression->condition) == EXPR_CLASS_CONSTANT) {
bool val = fold_constant_to_bool(expression->condition);
ir_node *const false_val = expression_to_firm(expression->false_expression);
jump_to_target(&exit_target);
if (val) {
- ir_node *const in[] = { val, false_val };
+ ir_node *const in[] = { val, false_val };
+ dbg_info *const dbgi = get_dbg_info(&expression->base.source_position);
val = new_rd_Phi(dbgi, exit_target.block, lengthof(in), in, get_irn_mode(val));
} else {
val = false_val;
tc = real_type_class;
goto make_const;
}
- panic("Unexpected atomic type in classify_type_to_firm().");
+ panic("Unexpected atomic type.");
}
case TYPE_COMPLEX: tc = complex_type_class; goto make_const;
case TYPE_ERROR:
break;
}
- panic("unexpected TYPE classify_type_to_firm().");
+ panic("unexpected type.");
}
make_const:;
return create_Const_from_bool(mode, value);
}
-static ir_node *get_label_block(label_t *label)
+static void prepare_label_target(label_t *const label)
{
- if (label->block != NULL)
- return label->block;
-
- ir_node *block = new_immBlock();
- label->block = block;
- if (label->address_taken) {
+ if (label->address_taken && !label->indirect_block) {
ir_node *const iblock = new_immBlock();
label->indirect_block = iblock;
- add_immBlock_pred(block, new_r_Jmp(iblock));
ARR_APP1(ir_node*, ijmp_blocks, iblock);
+ jump_from_block_to_target(&label->target, iblock);
}
- return block;
}
/**
/* Beware: Might be called from create initializer with current_ir_graph
* set to const_code_irg. */
PUSH_IRG(current_function);
- get_label_block(label->label);
+ prepare_label_target(label->label);
POP_IRG();
symconst_symbol value;
case EXPR_ERROR: break;
}
- panic("invalid expression found");
+ panic("invalid expression");
}
/**
break;
}
- dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
- ir_node *cond_expr = _expression_to_firm(expression);
- ir_node *condition = create_conv(dbgi, cond_expr, mode_b);
- ir_node *cond = new_d_Cond(dbgi, condition);
- ir_node *true_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true);
- ir_node *false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false);
-
- /* 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) == EXPR_CLASS_CONSTANT) {
- bool const cnst = fold_constant_to_bool(argument->expression);
- cond_jmp_predicate const pred = cnst ? COND_JMP_PRED_TRUE : COND_JMP_PRED_FALSE;
- set_Cond_jmp_pred(cond, pred);
+ ir_node *cond_expr = _expression_to_firm(expression);
+ if (is_Const(cond_expr)) {
+ if (tarval_is_null(get_Const_tarval(cond_expr))) {
+ jump_to_target(false_target);
+ } else {
+ jump_to_target(true_target);
+ }
+ } else {
+ dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
+ ir_node *condition = create_conv(dbgi, cond_expr, mode_b);
+ ir_node *cond = new_d_Cond(dbgi, condition);
+ ir_node *true_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true);
+ ir_node *false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false);
+
+ /* 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) == EXPR_CLASS_CONSTANT) {
+ bool const cnst = fold_constant_to_bool(argument->expression);
+ cond_jmp_predicate const pred = cnst ? COND_JMP_PRED_TRUE : COND_JMP_PRED_FALSE;
+ set_Cond_jmp_pred(cond, pred);
+ }
}
- }
-
- add_pred_to_jump_target(true_target, true_proj);
- add_pred_to_jump_target(false_target, false_proj);
+ add_pred_to_jump_target(true_target, true_proj);
+ add_pred_to_jump_target(false_target, false_proj);
+ }
set_unreachable_now();
return cond_expr;
}
{
if (path->invalid) {
/* TODO: handle this... */
- panic("invalid initializer in ast2firm (excessive elements)");
+ panic("invalid initializer (excessive elements)");
}
type_path_entry_t *top = get_type_path_top(path);
static ir_initializer_t *create_ir_initializer_value(
const initializer_value_t *initializer)
{
- if (is_type_compound(initializer->value->base.type)) {
- panic("initializer creation for compounds not implemented yet");
- }
- type_t *type = initializer->value->base.type;
expression_t *expr = initializer->value;
+ type_t *type = skip_typeref(expr->base.type);
+
+ if (is_type_compound(type)) {
+ if (expr->kind == EXPR_UNARY_CAST) {
+ expr = expr->unary.value;
+ type = skip_typeref(expr->base.type);
+ }
+ /* must be a compound literal... */
+ if (expr->kind == EXPR_COMPOUND_LITERAL) {
+ return create_ir_initializer(expr->compound_literal.initializer,
+ type);
+ }
+ }
+
ir_node *value = expression_to_firm(expr);
- ir_mode *mode = get_ir_mode_storage(type);
- value = create_conv(NULL, value, mode);
+ if (!is_type_compound(type)) {
+ ir_mode *mode = get_ir_mode_storage(type);
+ value = create_conv(NULL, value, mode);
+ }
return create_initializer_const(value);
}
}
if (sub_initializer->kind == INITIALIZER_VALUE) {
- /* we might have to descend into types until we're at a scalar
- * type */
+ const expression_t *expr = sub_initializer->value.value;
+ const type_t *expr_type = skip_typeref(expr->base.type);
+ /* we might have to descend into types until the types match */
while(true) {
type_t *orig_top_type = path.top_type;
type_t *top_type = skip_typeref(orig_top_type);
- if (is_type_scalar(top_type))
+ if (types_compatible(top_type, expr_type))
break;
descend_into_subtype(&path);
}
char const * p = str->value.begin;
switch (str->value.encoding) {
case STRING_ENCODING_CHAR:
+ case STRING_ENCODING_UTF8:
for (size_t i = 0; i != arr_len; ++i) {
char const c = i < str_len ? *p++ : 0;
ir_tarval *const tv = new_tarval_from_long(c, mode);
}
break;
+ case STRING_ENCODING_CHAR16:
+ case STRING_ENCODING_CHAR32:
case STRING_ENCODING_WIDE:
for (size_t i = 0; i != arr_len; ++i) {
utf32 const c = i < str_len ? read_utf8_char(&p) : 0;
return create_ir_initializer_value(&initializer->value);
case INITIALIZER_DESIGNATOR:
- panic("unexpected designator initializer found");
+ panic("unexpected designator initializer");
}
panic("unknown initializer");
}
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_node *mem = get_store();
+ ir_node *new_mem;
+ if (is_compound_type(ent_type)) {
+ ir_node *copyb = new_d_CopyB(dbgi, mem, base_addr, node, ent_type);
+ new_mem = new_Proj(copyb, mode_M, pn_CopyB_M);
+ } else {
+ assert(get_type_mode(type) == get_irn_mode(node));
+ ir_node *store = new_d_Store(dbgi, mem, base_addr, node, cons_none);
+ new_mem = new_Proj(store, mode_M, pn_Store_M);
+ }
+ set_store(new_mem);
return;
}
case IR_INITIALIZER_TARVAL: {
}
}
- panic("invalid IR_INITIALIZER found");
+ panic("invalid ir_initializer");
}
static void create_dynamic_initializer(ir_initializer_t *initializer,
case STORAGE_CLASS_TYPEDEF:
break;
}
- panic("invalid storage class found");
+ panic("invalid storage class");
}
static void create_local_declarations(entity_t *e)
return NULL;
}
-/**
- * Add an unconditional jump to the target block. If the source block is not
- * reachable, then a Bad predecessor is created to prevent Phi-less unreachable
- * loops. This is necessary if the jump potentially enters a loop.
- */
-static void jump_to(ir_node *const target_block)
-{
- ir_node *const pred = currently_reachable() ? new_Jmp() : new_Bad(mode_X);
- add_immBlock_pred(target_block, pred);
- set_cur_block(target_block);
-}
-
static ir_node *do_while_statement_to_firm(do_while_statement_t *statement)
{
create_local_declarations(statement->scope.entities);
init_jump_target(&body_target, NULL);
jump_to_target(&body_target);
enter_immature_jump_target(&body_target);
+ keep_loop();
statement_to_firm(statement->body);
jump_to_target(&continue_target);
if (enter_jump_target(&continue_target))
init_jump_target(&header_target, NULL);
jump_to_target(&header_target);
enter_immature_jump_target(&header_target);
+ keep_loop();
expression_t *const step = statement->step;
PUSH_BREAK(NULL);
init_jump_target(&body_target, NULL);
create_condition_evaluation(cond, &body_target, &break_target);
enter_jump_target(&body_target);
- } else {
- /* for-ever. */
- keep_alive(header_target.block);
- keep_all_memory(header_target.block);
}
/* Create the loop body. */
return NULL;
}
-static ir_node *create_jump_statement(const statement_t *statement, ir_node *target_block)
-{
- if (!currently_reachable())
- return NULL;
-
- dbg_info *dbgi = get_dbg_info(&statement->base.source_position);
- ir_node *jump = new_d_Jmp(dbgi);
- add_immBlock_pred(target_block, jump);
-
- set_unreachable_now();
- return NULL;
-}
-
static ir_switch_table *create_switch_table(const switch_statement_t *statement)
{
/* determine number of cases */
return statement_to_firm(statement->statement);
}
-static void try_mature_label(label_t *const label)
-{
- if (--label->n_users == 0)
- mature_immBlock(label->block);
-}
-
static ir_node *label_to_firm(const label_statement_t *statement)
{
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);
+ prepare_label_target(label);
+ jump_to_target(&label->target);
+ if (--label->n_users == 0) {
+ enter_jump_target(&label->target);
+ } else {
+ enter_immature_jump_target(&label->target);
+ keep_loop();
+ }
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);
+ prepare_label_target(label);
+ jump_to_target(&label->target);
+ if (--label->n_users == 0)
+ enter_jump_target(&label->target);
+ set_unreachable_now();
return NULL;
}
static ir_node *computed_goto_to_firm(computed_goto_statement_t const *const statement)
{
- if (!currently_reachable())
- return NULL;
-
- ir_node *const irn = expression_to_firm(statement->expression);
- dbg_info *const dbgi = get_dbg_info(&statement->base.source_position);
- ir_node *const ijmp = new_d_IJmp(dbgi, irn);
-
- set_irn_link(ijmp, ijmp_list);
- ijmp_list = ijmp;
-
- set_unreachable_now();
+ if (currently_reachable()) {
+ ir_node *const op = expression_to_firm(statement->expression);
+ ARR_APP1(ir_node*, ijmp_ops, op);
+ jump_to_target(&ijmp_target);
+ set_unreachable_now();
+ }
return NULL;
}
return NULL;
}
- case STATEMENT_ERROR: panic("error statement found");
+ case STATEMENT_ERROR: panic("error statement");
}
panic("statement not implemented");
}
set_atomic_ent_value(ptr, val);
}
-/**
- * Generate possible IJmp branches to a given label block.
- */
-static void gen_ijmp_branches(ir_node *block)
-{
- ir_node *ijmp;
- for (ijmp = ijmp_list; ijmp != NULL; ijmp = get_irn_link(ijmp)) {
- add_immBlock_pred(block, ijmp);
- }
-}
-
/**
* Create code for a function and all inner functions.
*
current_function_name = NULL;
current_funcsig = NULL;
- assert(ijmp_blocks == NULL);
+ assert(!ijmp_ops);
+ assert(!ijmp_blocks);
+ init_jump_target(&ijmp_target, NULL);
+ ijmp_ops = NEW_ARR_F(ir_node*, 0);
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);
add_immBlock_pred(end_block, ret);
}
- for (size_t i = ARR_LEN(ijmp_blocks); i-- != 0;) {
- ir_node *const block = ijmp_blocks[i];
- gen_ijmp_branches(block);
- mature_immBlock(block);
+ if (enter_jump_target(&ijmp_target)) {
+ keep_loop();
+ size_t const n = ARR_LEN(ijmp_ops);
+ ir_node *const op = n == 1 ? ijmp_ops[0] : new_Phi(n, ijmp_ops, get_irn_mode(ijmp_ops[0]));
+ ir_node *const ijmp = new_IJmp(op);
+ for (size_t i = ARR_LEN(ijmp_blocks); i-- != 0;) {
+ ir_node *const block = ijmp_blocks[i];
+ add_immBlock_pred(block, ijmp);
+ mature_immBlock(block);
+ }
}
+ DEL_ARR_F(ijmp_ops);
DEL_ARR_F(ijmp_blocks);
+ ijmp_ops = NULL;
ijmp_blocks = NULL;
irg_finalize_cons(irg);
return;
ir_types_initialized = 1;
- ir_type_char = get_ir_type(type_char);
- ir_type_wchar_t = get_ir_type(type_wchar_t);
+ ir_type_char = get_ir_type(type_char);
be_params = be_get_backend_param();
mode_float_arithmetic = be_params->mode_float_arithmetic;