X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ast2firm.c;h=21b50277e35655260cef106b7c48c1bc8ecd3a56;hb=650d8cd4db5cb8a71a2fc96cf6336001b99aabc6;hp=950ee3528fb75b6979caec5d91580b51cc4d8723;hpb=1c4f7c9f6ddb6c289ccab22a3795ebc6facfd518;p=cparser diff --git a/ast2firm.c b/ast2firm.c index 950ee35..21b5027 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -82,8 +82,6 @@ static ir_node *ijmp_list; static bool constant_folding; static bool initializer_use_bitfield_basetype; -extern bool have_const_functions; - static const entity_t *current_function_entity; static ir_node *current_function_name; static ir_node *current_funcsig; @@ -133,7 +131,7 @@ static ir_node *uninitialized_local_var(ir_graph *irg, ir_mode *mode, int pos) { const entity_t *entity = get_irg_loc_description(irg, pos); - if (entity != NULL) { + if (entity != NULL && warning.uninitialized) { warningf(&entity->base.source_position, "%s '%#T' might be used uninitialized", get_entity_kind_name(entity->kind), @@ -172,6 +170,18 @@ static type_dbg_info *get_type_dbg_info_(const type_t *type) return (type_dbg_info*) type; } +/* is the current block a reachable one? */ +static bool currently_reachable(void) +{ + ir_node *const block = get_cur_block(); + return block != NULL && !is_Bad(block); +} + +static void set_unreachable_now(void) +{ + set_cur_block(NULL); +} + static ir_mode *atomic_modes[ATOMIC_TYPE_LAST+1]; static ir_mode *mode_int, *mode_uint; @@ -745,9 +755,6 @@ ir_type *get_ir_type(type_t *type) case TYPE_ENUM: firm_type = create_enum_type(&type->enumt); break; - case TYPE_BUILTIN: - firm_type = get_ir_type(type->builtin.real_type); - break; case TYPE_BITFIELD: firm_type = create_bitfield_type(&type->bitfield); break; @@ -901,7 +908,6 @@ static void handle_decl_modifiers(ir_entity *irentity, entity_t *entity) } if (modifiers & DM_CONST) { add_entity_additional_properties(irentity, mtp_property_const); - have_const_functions = true; } } if (modifiers & DM_USED) { @@ -1068,35 +1074,37 @@ entity_created: * Creates a SymConst for a given entity. * * @param dbgi debug info - * @param mode the (reference) mode for the SymConst * @param entity the entity */ -static ir_node *create_symconst(dbg_info *dbgi, ir_mode *mode, - ir_entity *entity) +static ir_node *create_symconst(dbg_info *dbgi, ir_entity *entity) { assert(entity != NULL); union symconst_symbol sym; sym.entity_p = entity; - return new_d_SymConst(dbgi, mode, sym, symconst_addr_ent); + return new_d_SymConst(dbgi, mode_P, sym, symconst_addr_ent); } static ir_node *create_conv(dbg_info *dbgi, ir_node *value, ir_mode *dest_mode) { ir_mode *value_mode = get_irn_mode(value); - if (value_mode == dest_mode || is_Bad(value)) + if (value_mode == dest_mode) return value; if (dest_mode == mode_b) { ir_node *zero = new_Const(get_mode_null(value_mode)); - ir_node *cmp = new_d_Cmp(dbgi, value, zero); - ir_node *proj = new_d_Proj(dbgi, cmp, mode_b, pn_Cmp_Lg); - return proj; + ir_node *cmp = new_d_Cmp(dbgi, value, zero, ir_relation_less_greater); + return cmp; } return new_d_Conv(dbgi, value, dest_mode); } +static ir_node *create_Const_from_bool(ir_mode *const mode, bool const v) +{ + return new_Const((v ? get_mode_one : get_mode_null)(mode)); +} + /** * Creates a SymConst node representing a wide string literal. * @@ -1135,7 +1143,7 @@ static ir_node *wide_string_literal_to_firm( } set_entity_initializer(entity, initializer); - return create_symconst(dbgi, mode_P_data, entity); + return create_symconst(dbgi, entity); } /** @@ -1178,7 +1186,7 @@ static ir_node *string_to_firm(const source_position_t *const src_pos, } set_entity_initializer(entity, initializer); - return create_symconst(dbgi, mode_P_data, entity); + return create_symconst(dbgi, entity); } static bool try_create_integer(literal_expression_t *literal, @@ -1418,7 +1426,7 @@ static ir_node *create_trampoline(dbg_info *dbgi, ir_mode *mode, assert(entity != NULL); ir_node *in[3]; in[0] = get_trampoline_region(dbgi, entity); - in[1] = create_symconst(dbgi, mode, entity); + in[1] = create_symconst(dbgi, entity); in[2] = get_irg_frame(current_ir_graph); ir_node *irn = new_d_Builtin(dbgi, get_store(), 3, in, ir_bk_inner_trampoline, get_unknown_type()); @@ -1483,25 +1491,6 @@ static ir_node *do_strict_conv(dbg_info *dbgi, ir_node *node) return new_d_strictConv(dbgi, node, mode); } -/** - * Returns the address of a global variable. - * - * @param dbgi debug info - * @param variable the variable - */ -static ir_node *get_global_var_address(dbg_info *const dbgi, - const variable_t *const variable) -{ - ir_entity *const irentity = variable->v.entity; - if (variable->thread_local) { - ir_node *const no_mem = new_NoMem(); - ir_node *const tls = get_irg_tls(current_ir_graph); - return new_d_simpleSel(dbgi, no_mem, tls, irentity); - } else { - return create_symconst(dbgi, mode_P_data, irentity); - } -} - /** * Returns the correct base address depending on whether it is a parameter or a * normal local variable. @@ -1565,7 +1554,7 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref) /* simply create a NULL pointer */ ir_mode *mode = get_ir_mode_arithmetic(type_void_ptr); - ir_node *res = new_Const_long(mode, 0); + ir_node *res = new_Const(get_mode_null(mode)); return res; } @@ -1586,14 +1575,13 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref) return create_conv(NULL, value, get_ir_mode_arithmetic(type)); } case DECLARATION_KIND_FUNCTION: { - ir_mode *const mode = get_ir_mode_storage(type); - return create_symconst(dbgi, mode, entity->function.irentity); + return create_symconst(dbgi, entity->function.irentity); } case DECLARATION_KIND_INNER_FUNCTION: { ir_mode *const mode = get_ir_mode_storage(type); if (!entity->function.goto_to_outer && !entity->function.need_closure) { /* inner function not using the closure */ - return create_symconst(dbgi, mode, entity->function.irentity); + return create_symconst(dbgi, entity->function.irentity); } else { /* need trampoline here */ return create_trampoline(dbgi, mode, entity->function.irentity); @@ -1601,7 +1589,7 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref) } case DECLARATION_KIND_GLOBAL_VARIABLE: { const variable_t *variable = &entity->variable; - ir_node *const addr = get_global_var_address(dbgi, variable); + ir_node *const addr = create_symconst(dbgi, variable->v.entity); return deref_address(dbgi, variable->base.type, addr); } @@ -1643,7 +1631,7 @@ static ir_node *reference_addr(const reference_expression_t *ref) * as an indicator for no real address) */ return NULL; case DECLARATION_KIND_GLOBAL_VARIABLE: { - ir_node *const addr = get_global_var_address(dbgi, &entity->variable); + ir_node *const addr = create_symconst(dbgi, entity->variable.v.entity); return addr; } case DECLARATION_KIND_LOCAL_VARIABLE_ENTITY: { @@ -1665,9 +1653,7 @@ static ir_node *reference_addr(const reference_expression_t *ref) return entity->variable.v.vla_base; case DECLARATION_KIND_FUNCTION: { - type_t *const type = skip_typeref(entity->declaration.type); - ir_mode *const mode = get_ir_mode_storage(type); - return create_symconst(dbgi, mode, entity->function.irentity); + return create_symconst(dbgi, entity->function.irentity); } case DECLARATION_KIND_INNER_FUNCTION: { @@ -1675,7 +1661,7 @@ static ir_node *reference_addr(const reference_expression_t *ref) ir_mode *const mode = get_ir_mode_storage(type); if (!entity->function.goto_to_outer && !entity->function.need_closure) { /* inner function not using the closure */ - return create_symconst(dbgi, mode, entity->function.irentity); + return create_symconst(dbgi, entity->function.irentity); } else { /* need trampoline here */ return create_trampoline(dbgi, mode, entity->function.irentity); @@ -1890,13 +1876,9 @@ static ir_node *process_builtin_call(const call_expression_t *call) long type_val = fold_constant_to_int(type_expression); type_t *type = function_type->function.return_type; ir_mode *mode = get_ir_mode_arithmetic(type); - ir_tarval *result; - /* just produce a "I don't know" result */ - if (type_val & 2) - result = new_tarval_from_long(0, mode); - else - result = new_tarval_from_long(-1, mode); + ir_tarval *result = type_val & 2 ? get_mode_null(mode) : + get_mode_minus_one(mode); return new_d_Const(dbgi, result); } @@ -1917,7 +1899,7 @@ static ir_node *process_builtin_call(const call_expression_t *call) case bk_ms_ReturnAddress: { ir_node *in[2]; - in[0] = new_Const_long(mode_int, 0); + in[0] = new_Const(get_mode_null(mode_int)); in[1] = get_irg_frame(current_ir_graph); ir_type *tp = get_ir_type(function_type); ir_node *irn = new_d_Builtin(dbgi, get_irg_no_mem(current_ir_graph), 2, in, ir_bk_return_address, tp); @@ -1967,7 +1949,7 @@ static ir_node *process_builtin_call(const call_expression_t *call) static ir_node *call_expression_to_firm(const call_expression_t *const call) { dbg_info *const dbgi = get_dbg_info(&call->base.source_position); - assert(get_cur_block() != NULL); + assert(currently_reachable()); expression_t *function = call->function; if (function->kind == EXPR_REFERENCE) { @@ -2413,22 +2395,21 @@ static bool is_local_variable(expression_t *expression) return entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE; } -static pn_Cmp get_pnc(const expression_kind_t kind, type_t *const type) +static ir_relation get_relation(const expression_kind_t kind) { switch(kind) { - case EXPR_BINARY_EQUAL: return pn_Cmp_Eq; - case EXPR_BINARY_ISLESSGREATER: return pn_Cmp_Lg; - case EXPR_BINARY_NOTEQUAL: - return is_type_float(skip_typeref(type)) ? pn_Cmp_Ne : pn_Cmp_Lg; + case EXPR_BINARY_EQUAL: return ir_relation_equal; + case EXPR_BINARY_ISLESSGREATER: return ir_relation_less_greater; + case EXPR_BINARY_NOTEQUAL: return ir_relation_unordered_less_greater; case EXPR_BINARY_ISLESS: - case EXPR_BINARY_LESS: return pn_Cmp_Lt; + case EXPR_BINARY_LESS: return ir_relation_less; case EXPR_BINARY_ISLESSEQUAL: - case EXPR_BINARY_LESSEQUAL: return pn_Cmp_Le; + case EXPR_BINARY_LESSEQUAL: return ir_relation_less_equal; case EXPR_BINARY_ISGREATER: - case EXPR_BINARY_GREATER: return pn_Cmp_Gt; + case EXPR_BINARY_GREATER: return ir_relation_greater; case EXPR_BINARY_ISGREATEREQUAL: - case EXPR_BINARY_GREATEREQUAL: return pn_Cmp_Ge; - case EXPR_BINARY_ISUNORDERED: return pn_Cmp_Uo; + case EXPR_BINARY_GREATEREQUAL: return ir_relation_greater_equal; + case EXPR_BINARY_ISUNORDERED: return ir_relation_unordered; default: break; @@ -2454,10 +2435,8 @@ static ir_node *handle_assume_compare(dbg_info *dbi, expression_t *op1 = expression->left; expression_t *op2 = expression->right; entity_t *var2, *var = NULL; - ir_node *res = NULL; - pn_Cmp cmp_val; - - cmp_val = get_pnc(expression->base.kind, op1->base.type); + ir_node *res = NULL; + ir_relation relation = get_relation(expression->base.kind); if (is_local_variable(op1) && is_local_variable(op2)) { var = op1->reference.entity; @@ -2469,21 +2448,21 @@ static ir_node *handle_assume_compare(dbg_info *dbi, ir_node *const irn1 = get_value(var->variable.v.value_number, mode); ir_node *const irn2 = get_value(var2->variable.v.value_number, mode); - res = new_d_Confirm(dbi, irn2, irn1, get_inversed_pnc(cmp_val)); + res = new_d_Confirm(dbi, irn2, irn1, get_inversed_relation(relation)); set_value(var2->variable.v.value_number, res); - res = new_d_Confirm(dbi, irn1, irn2, cmp_val); + res = new_d_Confirm(dbi, irn1, irn2, relation); set_value(var->variable.v.value_number, res); return res; } 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)) { - cmp_val = get_inversed_pnc(cmp_val); + } else if (is_constant_expression(op1) == EXPR_CLASS_CONSTANT && is_local_variable(op2)) { + relation = get_inversed_relation(relation); var = op2->reference.entity; con = op1; } @@ -2493,7 +2472,7 @@ static ir_node *handle_assume_compare(dbg_info *dbi, ir_mode *const mode = get_ir_mode_storage(type); res = get_value(var->variable.v.value_number, mode); - res = new_d_Confirm(dbi, res, expression_to_firm(con), cmp_val); + res = new_d_Confirm(dbi, res, expression_to_firm(con), relation); set_value(var->variable.v.value_number, res); } return res; @@ -2520,7 +2499,7 @@ static ir_node *handle_assume(dbg_info *dbi, const expression_t *expression) } } -static ir_node *create_cast(dbg_info *dbgi, ir_node *value_node, +static ir_node *create_cast(dbg_info *dbgi, ir_node *value_node, type_t *from_type, type_t *type) { type = skip_typeref(type); @@ -2543,12 +2522,12 @@ static ir_node *create_cast(dbg_info *dbgi, ir_node *value_node, const variable_t *to_var = type->pointer.base_variable; if (from_var != to_var) { if (from_var != NULL) { - ir_node *const addr = get_global_var_address(dbgi, from_var); + ir_node *const addr = create_symconst(dbgi, from_var->v.entity); ir_node *const base = deref_address(dbgi, from_var->base.type, addr); value_node = new_d_Add(dbgi, value_node, base, get_ir_mode_storage(from_type)); } if (to_var != NULL) { - ir_node *const addr = get_global_var_address(dbgi, to_var); + ir_node *const addr = create_symconst(dbgi, to_var->v.entity); ir_node *const base = deref_address(dbgi, to_var->base.type, addr); value_node = new_d_Sub(dbgi, value_node, base, mode); } @@ -2606,7 +2585,7 @@ static ir_node *unary_expression_to_firm(const unary_expression_t *expression) /* check for __based */ const variable_t *const base_var = value_type->pointer.base_variable; if (base_var != NULL) { - ir_node *const addr = get_global_var_address(dbgi, base_var); + ir_node *const addr = create_symconst(dbgi, base_var->v.entity); ir_node *const base = deref_address(dbgi, base_var->base.type, addr); value_node = new_d_Add(dbgi, value_node, base, get_ir_mode_storage(value_type)); } @@ -2639,29 +2618,22 @@ static ir_node *unary_expression_to_firm(const unary_expression_t *expression) 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; } @@ -2694,7 +2666,7 @@ static ir_node *create_op(dbg_info *dbgi, const binary_expression_t *expression, case EXPR_BINARY_SHIFTRIGHT: case EXPR_BINARY_SHIFTLEFT_ASSIGN: case EXPR_BINARY_SHIFTRIGHT_ASSIGN: - mode = get_irn_mode(left); + mode = get_ir_mode_arithmetic(expression->base.type); right = create_conv(dbgi, right, mode_uint); break; @@ -2772,15 +2744,9 @@ normal_node: case EXPR_BINARY_DIV: case EXPR_BINARY_DIV_ASSIGN: { ir_node *pin = new_Pin(new_NoMem()); - ir_node *op; - ir_node *res; - if (mode_is_float(mode)) { - op = new_d_Quot(dbgi, pin, left, right, mode, op_pin_state_floats); - res = new_d_Proj(dbgi, op, mode, pn_Quot_res); - } else { - op = new_d_Div(dbgi, pin, left, right, mode, op_pin_state_floats); - res = new_d_Proj(dbgi, op, mode, pn_Div_res); - } + ir_node *op = new_d_Div(dbgi, pin, left, right, mode, + op_pin_state_floats); + ir_node *res = new_d_Proj(dbgi, op, mode, pn_Div_res); return res; } case EXPR_BINARY_MOD: @@ -2803,7 +2769,7 @@ static ir_node *create_lazy_op(const binary_expression_t *expression) 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); @@ -2817,11 +2783,9 @@ static ir_node *create_lazy_op(const binary_expression_t *expression) } } - 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)) : - new_Const(get_mode_null(mode)); + return create_Const_from_bool(mode, valr); } return produce_condition_result(expression->right, mode, dbgi); @@ -2873,13 +2837,12 @@ static ir_node *binary_expression_to_firm(const binary_expression_t *expression) case EXPR_BINARY_ISLESSEQUAL: case EXPR_BINARY_ISLESSGREATER: case EXPR_BINARY_ISUNORDERED: { - dbg_info *dbgi = get_dbg_info(&expression->base.source_position); - ir_node *left = expression_to_firm(expression->left); - ir_node *right = expression_to_firm(expression->right); - ir_node *cmp = new_d_Cmp(dbgi, left, right); - long pnc = get_pnc(kind, expression->left->base.type); - ir_node *proj = new_d_Proj(dbgi, cmp, mode_b, pnc); - return proj; + dbg_info *dbgi = get_dbg_info(&expression->base.source_position); + ir_node *left = expression_to_firm(expression->left); + ir_node *right = expression_to_firm(expression->right); + ir_relation relation = get_relation(kind); + ir_node *cmp = new_d_Cmp(dbgi, left, right, relation); + return cmp; } case EXPR_BINARY_ASSIGN: { ir_node *addr = expression_to_addr(expression->left); @@ -3054,6 +3017,11 @@ static ir_node *sizeof_to_firm(const typeprop_expression_t *expression) && expression->tp_expression != NULL) { expression_to_firm(expression->tp_expression); } + /* strange gnu extensions: sizeof(function) == 1 */ + if (is_type_function(type)) { + ir_mode *mode = get_ir_mode_storage(type_size_t); + return new_Const(get_mode_one(mode)); + } return get_type_size_node(type); } @@ -3093,7 +3061,12 @@ static ir_node *alignof_to_firm(const typeprop_expression_t *expression) if (tp_expression != NULL) { entity_t *entity = get_expression_entity(tp_expression); if (entity != NULL) { - alignment = get_cparser_entity_alignment(entity); + if (entity->kind == ENTITY_FUNCTION) { + /* a gnu-extension */ + alignment = 1; + } else { + alignment = get_cparser_entity_alignment(entity); + } } } @@ -3119,7 +3092,7 @@ static ir_tarval *fold_constant_to_tarval(const expression_t *expression) 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(); @@ -3162,7 +3135,7 @@ 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)) { + 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; @@ -3174,51 +3147,47 @@ static ir_node *conditional_to_firm(const conditional_expression_t *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); - assert(get_irn_mode(false_val) == mode); - ir_node *val = new_d_Phi(dbgi, 2, in, mode); + ir_node *const in[2] = { true_val, false_val }; + type_t *const type = skip_typeref(expression->base.type); + ir_mode *mode; + if (is_type_compound(type)) { + mode = mode_P; + } else { + mode = get_ir_mode_arithmetic(type); + } + ir_node *const val = new_d_Phi(dbgi, lengthof(in), in, mode); return val; } @@ -3357,7 +3326,6 @@ static ir_node *classify_type_to_firm(const classify_type_expression_t *const ex /* gcc classifies the referenced type */ case TYPE_REFERENCE: type = type->reference.refers_to; continue; - case TYPE_BUILTIN: /* typedef/typeof should be skipped already */ case TYPE_TYPEDEF: case TYPE_TYPEOF: @@ -3500,15 +3468,9 @@ static ir_node *expression_to_addr(const expression_t *expression) static ir_node *builtin_constant_to_firm( const builtin_constant_expression_t *expression) { - ir_mode *mode = get_ir_mode_arithmetic(expression->base.type); - long v; - - if (is_constant_expression(expression->value)) { - v = 1; - } else { - v = 0; - } - return new_Const_long(mode, v); + ir_mode *const mode = get_ir_mode_arithmetic(expression->base.type); + bool const v = is_constant_expression(expression->value) == EXPR_CLASS_CONSTANT; + return create_Const_from_bool(mode, v); } static ir_node *builtin_types_compatible_to_firm( @@ -3516,9 +3478,9 @@ static ir_node *builtin_types_compatible_to_firm( { type_t *const left = get_unqualified_type(skip_typeref(expression->left)); type_t *const right = get_unqualified_type(skip_typeref(expression->right)); - long const value = types_compatible(left, right) ? 1 : 0; + bool const value = types_compatible(left, right); ir_mode *const mode = get_ir_mode_arithmetic(expression->base.type); - return new_Const_long(mode, value); + return create_Const_from_bool(mode, value); } static ir_node *get_label_block(label_t *label) @@ -3687,15 +3649,14 @@ static ir_node *expression_to_firm(const expression_t *expression) return res; } - if (is_constant_expression(expression)) { + if (is_constant_expression(expression) == EXPR_CLASS_CONSTANT) { + bool const constant_folding_old = constant_folding; + constant_folding = true; ir_node *res = _expression_to_firm(expression); + constant_folding = constant_folding_old; ir_mode *mode = get_ir_mode_arithmetic(expression->base.type); assert(is_Const(res)); - if (is_Const_null(res)) { - return new_Const_long(mode, 0); - } else { - return new_Const_long(mode, 1); - } + return create_Const_from_bool(mode, !is_Const_null(res)); } /* we have to produce a 0/1 from the mode_b expression */ @@ -3757,15 +3718,9 @@ static ir_node *create_condition_evaluation(const expression_t *expression, /* 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)) { - bool cnst = fold_constant_to_bool(argument->expression); - cond_jmp_predicate pred; - - if (cnst == false) { - pred = COND_JMP_PRED_FALSE; - } else { - pred = COND_JMP_PRED_TRUE; - } + 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); } } @@ -3773,7 +3728,7 @@ static ir_node *create_condition_evaluation(const expression_t *expression, add_immBlock_pred(true_block, true_proj); add_immBlock_pred(false_block, false_proj); - set_cur_block(NULL); + set_unreachable_now(); return cond_expr; } @@ -4289,7 +4244,7 @@ static void create_dynamic_null_initializer(ir_entity *entity, dbg_info *dbgi, } ir_mode *value_mode = get_type_mode(ent_type); - ir_node *node = new_Const_long(value_mode, 0); + ir_node *node = new_Const(get_mode_null(value_mode)); /* is it a bitfield type? */ if (is_Primitive_type(ent_type) && @@ -4421,7 +4376,7 @@ static void create_local_initializer(initializer_t *initializer, dbg_info *dbgi, 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; @@ -4455,7 +4410,7 @@ static void create_local_initializer(initializer_t *initializer, dbg_info *dbgi, set_entity_initializer(init_entity, irinitializer); - ir_node *const src_addr = create_symconst(dbgi, mode_P_data, init_entity); + ir_node *const src_addr = create_symconst(dbgi, init_entity); ir_node *const copyb = new_d_CopyB(dbgi, memory, addr, src_addr, irtype); ir_node *const copyb_mem = new_Proj(copyb, mode_M, pn_CopyB_M); @@ -4545,7 +4500,7 @@ static void allocate_variable_length_array(entity_t *entity) { assert(entity->kind == ENTITY_VARIABLE); assert(entity->variable.initializer == NULL); - assert(get_cur_block() != NULL); + assert(currently_reachable()); dbg_info *dbgi = get_dbg_info(&entity->base.source_position); type_t *type = entity->declaration.type; @@ -4640,7 +4595,7 @@ static void create_local_static_variable(entity_t *entity) static void return_statement_to_firm(return_statement_t *statement) { - if (get_cur_block() == NULL) + if (!currently_reachable()) return; dbg_info *dbgi = get_dbg_info(&statement->base.source_position); @@ -4686,12 +4641,12 @@ static void return_statement_to_firm(return_statement_t *statement) ir_node *end_block = get_irg_end_block(current_ir_graph); add_immBlock_pred(end_block, ret); - set_cur_block(NULL); + set_unreachable_now(); } static ir_node *expression_statement_to_firm(expression_statement_t *statement) { - if (get_cur_block() == NULL) + if (!currently_reachable()) return NULL; return expression_to_firm(statement->expression); @@ -4812,7 +4767,7 @@ static void initialize_local_declaration(entity_t *entity) // no need to emit code in dead blocks if (entity->declaration.storage_class != STORAGE_CLASS_STATIC - && get_cur_block() == NULL) + && !currently_reachable()) return; switch ((declaration_kind_t) entity->declaration.kind) { @@ -4869,7 +4824,7 @@ static void if_statement_to_firm(if_statement_t *statement) /* Create the condition. */ ir_node *true_block = NULL; ir_node *false_block = NULL; - if (get_cur_block() != NULL) { + if (currently_reachable()) { true_block = new_immBlock(); false_block = new_immBlock(); create_condition_evaluation(statement->condition, true_block, false_block); @@ -4877,7 +4832,7 @@ static void if_statement_to_firm(if_statement_t *statement) } /* Create the false statement. - * Hadle false before true, so if no false statement is present, then the + * Handle 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) { @@ -4886,7 +4841,7 @@ static void if_statement_to_firm(if_statement_t *statement) } set_cur_block(false_block); statement_to_firm(statement->false_statement); - if (get_cur_block() != NULL) { + if (currently_reachable()) { fallthrough_block = new_immBlock(); add_immBlock_pred(fallthrough_block, new_Jmp()); } @@ -4897,7 +4852,7 @@ static void if_statement_to_firm(if_statement_t *statement) /* Create the true statement. */ set_cur_block(true_block); statement_to_firm(statement->true_statement); - if (get_cur_block() != NULL) { + if (currently_reachable()) { if (fallthrough_block == NULL) { fallthrough_block = new_immBlock(); } @@ -4911,19 +4866,26 @@ static void if_statement_to_firm(if_statement_t *statement) set_cur_block(fallthrough_block); } +/* 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 *const pred = currently_reachable() ? new_Jmp() : new_Bad(mode_X); + add_immBlock_pred(target_block, pred); +} + static void while_statement_to_firm(while_statement_t *statement) { /* Create the header block */ ir_node *const header_block = new_immBlock(); - if (get_cur_block() != NULL) { - add_immBlock_pred(header_block, new_Jmp()); - } + 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) && fold_constant_to_bool(cond)) { + if (is_constant_expression(cond) == EXPR_CLASS_CONSTANT && + fold_constant_to_bool(cond)) { /* Shortcut for while (true). */ body_block = header_block; false_block = NULL; @@ -4947,9 +4909,7 @@ static void while_statement_to_firm(while_statement_t *statement) /* Create the loop body. */ set_cur_block(body_block); statement_to_firm(statement->body); - if (get_cur_block() != NULL) { - add_immBlock_pred(header_block, new_Jmp()); - } + jump_if_reachable(header_block); mature_immBlock(header_block); assert(false_block == NULL || false_block == break_label); @@ -4964,6 +4924,14 @@ static void while_statement_to_firm(while_statement_t *statement) break_label = old_break_label; } +static ir_node *get_break_label(void) +{ + 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 */ @@ -4971,9 +4939,7 @@ static void do_while_statement_to_firm(do_while_statement_t *statement) /* the loop body */ ir_node *body_block = new_immBlock(); - if (get_cur_block() != NULL) { - add_immBlock_pred(body_block, new_Jmp()); - } + jump_if_reachable(body_block); ir_node *old_continue_label = continue_label; ir_node *old_break_label = break_label; @@ -4982,20 +4948,13 @@ static void do_while_statement_to_firm(do_while_statement_t *statement) 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); - } - - if (false_block == NULL) { - false_block = new_immBlock(); - } + jump_if_reachable(header_block); /* create the condition */ mature_immBlock(header_block); @@ -5019,7 +4978,7 @@ static void for_statement_to_firm(for_statement_t *statement) create_local_declaration(entity); } - if (get_cur_block() != NULL) { + if (currently_reachable()) { entity = statement->scope.entities; for ( ; entity != NULL; entity = entity->base.next) { if (!is_declaration(entity)) @@ -5035,9 +4994,7 @@ static void for_statement_to_firm(for_statement_t *statement) /* Create the header block */ ir_node *const header_block = new_immBlock(); - if (get_cur_block() != NULL) { - add_immBlock_pred(header_block, new_Jmp()); - } + jump_if_reachable(header_block); /* Create the condition. */ ir_node *body_block; @@ -5073,18 +5030,14 @@ static void for_statement_to_firm(for_statement_t *statement) /* Create the loop body. */ set_cur_block(body_block); statement_to_firm(statement->body); - if (get_cur_block() != NULL) { - add_immBlock_pred(step_block, new_Jmp()); - } + 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); - if (get_cur_block() != NULL) { - add_immBlock_pred(header_block, new_Jmp()); - } + jump_if_reachable(header_block); } mature_immBlock(header_block); @@ -5103,22 +5056,14 @@ static void for_statement_to_firm(for_statement_t *statement) static void create_jump_statement(const statement_t *statement, ir_node *target_block) { - if (get_cur_block() == NULL) + if (!currently_reachable()) return; dbg_info *dbgi = get_dbg_info(&statement->base.source_position); ir_node *jump = new_d_Jmp(dbgi); add_immBlock_pred(target_block, jump); - set_cur_block(NULL); -} - -static ir_node *get_break_label(void) -{ - if (break_label == NULL) { - break_label = new_immBlock(); - } - return break_label; + set_unreachable_now(); } static void switch_statement_to_firm(switch_statement_t *statement) @@ -5127,13 +5072,13 @@ static void switch_statement_to_firm(switch_statement_t *statement) dbg_info *dbgi = get_dbg_info(&statement->base.source_position); ir_node *cond = NULL; - if (get_cur_block() != NULL) { + if (currently_reachable()) { ir_node *expression = expression_to_firm(statement->expression); cond = new_d_Cond(dbgi, expression); first_block = get_cur_block(); } - set_cur_block(NULL); + set_unreachable_now(); ir_node *const old_switch_cond = current_switch_cond; ir_node *const old_break_label = break_label; @@ -5203,10 +5148,7 @@ static void switch_statement_to_firm(switch_statement_t *statement) 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); @@ -5232,11 +5174,8 @@ static void case_label_to_firm(const case_label_statement_t *statement) return; ir_node *block = new_immBlock(); - - if (get_cur_block() != NULL) { - /* Fallthrough from previous case */ - add_immBlock_pred(block, new_Jmp()); - } + /* Fallthrough from previous case */ + jump_if_reachable(block); if (current_switch_cond != NULL) { set_cur_block(get_nodes_block(current_switch_cond)); @@ -5267,11 +5206,7 @@ static void case_label_to_firm(const case_label_statement_t *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); @@ -5282,7 +5217,7 @@ static void label_to_firm(const label_statement_t *statement) static void goto_to_firm(const goto_statement_t *statement) { - if (get_cur_block() == NULL) + if (!currently_reachable()) return; if (statement->expression) { @@ -5297,7 +5232,7 @@ static void goto_to_firm(const goto_statement_t *statement) ir_node *jmp = new_Jmp(); add_immBlock_pred(block, jmp); } - set_cur_block(NULL); + set_unreachable_now(); } static void asm_statement_to_firm(const asm_statement_t *statement) @@ -5543,13 +5478,13 @@ static void asm_statement_to_firm(const asm_statement_t *statement) } } -static void ms_try_statement_to_firm(ms_try_statement_t *statement) +static void ms_try_statement_to_firm(ms_try_statement_t *statement) { statement_to_firm(statement->try_statement); warningf(&statement->base.source_position, "structured exception handling ignored"); } -static void leave_statement_to_firm(leave_statement_t *statement) +static void leave_statement_to_firm(leave_statement_t *statement) { errorf(&statement->base.source_position, "__leave not supported yet"); } @@ -5889,7 +5824,7 @@ static void create_function(entity_t *entity) ir_node *end_block = get_irg_end_block(irg); /* do we have a return statement yet? */ - if (get_cur_block() != NULL) { + if (currently_reachable()) { type_t *type = skip_typeref(entity->declaration.type); assert(is_type_function(type)); const function_type_t *func_type = &type->function;