static const backend_params *be_params;
static ir_type *ir_type_char;
-static ir_type *ir_type_const_char;
static ir_type *ir_type_wchar_t;
/* architecture specific floating point arithmetic mode (if any) */
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) \
+ ir_node *const old_break_label = break_label; \
+ ((void)(break_label = (val)))
+#define POP_BREAK() \
+ ((void)(break_label = old_break_label))
+
+#define PUSH_CONTINUE(val) \
+ ir_node *const old_continue_label = continue_label; \
+ ((void)(continue_label = (val)))
+#define POP_CONTINUE() \
+ ((void)(continue_label = old_continue_label))
+
+#define PUSH_IRG(val) \
+ ir_graph *const old_irg = current_ir_graph; \
+ ir_graph *const new_irg = (val); \
+ ((void)(current_ir_graph = new_irg))
+
+#define POP_IRG() \
+ (assert(current_ir_graph == new_irg), (void)(current_ir_graph = old_irg))
+
static const entity_t *current_function_entity;
static ir_node *current_function_name;
static ir_node *current_funcsig;
unsigned size = get_atomic_type_size(kind);
if ((flags & ATOMIC_TYPE_FLAG_FLOAT)
&& !(flags & ATOMIC_TYPE_FLAG_COMPLEX)) {
- if (size == 4) {
- return get_modeF();
- } else if (size == 8) {
- return get_modeD();
- } else {
- panic("unexpected kind");
+ switch (size) {
+ case 4: return get_modeF();
+ case 8: return get_modeD();
+ default: panic("unexpected kind");
}
} else if (flags & ATOMIC_TYPE_FLAG_INTEGER) {
char name[64];
{
assert(entity->kind == ENTITY_COMPOUND_MEMBER);
type_t *base = skip_typeref(entity->declaration.type);
- assert(base->kind == TYPE_ATOMIC || base->kind == TYPE_ENUM);
+ assert(is_type_integer(base));
ir_type *irbase = get_ir_type(base);
unsigned bit_size = entity->compound_member.bit_size;
- assert(!is_type_float(base));
if (is_type_signed(base)) {
return get_signed_int_type_for_bit_size(irbase, bit_size, base);
} else {
/* anonymous bitfield member, skip */
if (entry->compound_member.bitfield)
continue;
- assert(entry_type->kind == TYPE_COMPOUND_STRUCT
- || entry_type->kind == TYPE_COMPOUND_UNION);
+ assert(is_type_compound(entry_type));
ident = id_unique("anon.%u");
} else {
ident = new_id_from_str(symbol->string);
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);
static ir_type *get_ir_type_incomplete(type_t *type)
{
- assert(type != NULL);
type = skip_typeref(type);
if (type->base.firm_type != NULL) {
ir_type *get_ir_type(type_t *type)
{
- assert(type != NULL);
-
type = skip_typeref(type);
if (type->base.firm_type != NULL) {
case ENTITY_VARIABLE:
return entity->declaration.storage_class != STORAGE_CLASS_EXTERN;
case ENTITY_FUNCTION:
- return entity->function.statement != NULL;
+ return entity->function.body != NULL;
case ENTITY_PARAMETER:
case ENTITY_COMPOUND_MEMBER:
return false;
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);
/* already an entity defined? */
ir_entity *irentity = entitymap_get(&entitymap, symbol);
- bool const has_body = entity->function.statement != NULL;
+ bool const has_body = entity->function.body != NULL;
if (irentity != NULL) {
goto entity_created;
}
return new_d_Conv(dbgi, value, dest_mode);
}
-/**
- * Creates a SymConst node representing a wide string literal.
- *
- * @param literal the wide string literal
- */
-static ir_node *wide_string_literal_to_firm(
- const string_literal_expression_t *literal)
-{
- ir_type *const global_type = get_glob_type();
- ir_type *const elem_type = ir_type_wchar_t;
- dbg_info *const dbgi = get_dbg_info(&literal->base.source_position);
- ir_type *const type = new_type_array(1, elem_type);
-
- ident *const id = id_unique("str.%u");
- ir_entity *const entity = new_d_entity(global_type, id, type, dbgi);
- set_entity_ld_ident(entity, id);
- set_entity_visibility(entity, ir_visibility_private);
- add_entity_linkage(entity, IR_LINKAGE_CONSTANT);
-
- ir_mode *const mode = get_type_mode(elem_type);
- const size_t slen = wstrlen(&literal->value);
-
- set_array_lower_bound_int(type, 0, 0);
- set_array_upper_bound_int(type, 0, slen);
- set_type_size_bytes(type, slen * get_mode_size_bytes(mode));
- set_type_state(type, layout_fixed);
-
- ir_initializer_t *initializer = create_initializer_compound(slen);
- const char *p = literal->value.begin;
- for (size_t i = 0; i < slen; ++i) {
- assert(p < literal->value.begin + literal->value.size);
- utf32 v = read_utf8_char(&p);
- ir_tarval *tv = new_tarval_from_long(v, mode);
- ir_initializer_t *val = create_initializer_tarval(tv);
- set_initializer_compound_value(initializer, i, val);
- }
- set_entity_initializer(entity, initializer);
-
- return create_symconst(dbgi, entity);
-}
-
/**
* Creates a SymConst node representing a string constant.
*
* @param id_prefix a prefix for the name of the generated string constant
* @param value the value of the string constant
*/
-static ir_node *string_to_firm(const source_position_t *const src_pos,
- const char *const id_prefix,
- const string_t *const value)
-{
- ir_type *const global_type = get_glob_type();
- dbg_info *const dbgi = get_dbg_info(src_pos);
- ir_type *const type = new_type_array(1, ir_type_const_char);
-
- ident *const id = id_unique(id_prefix);
- ir_entity *const entity = new_d_entity(global_type, id, type, dbgi);
- set_entity_ld_ident(entity, id);
- set_entity_visibility(entity, ir_visibility_private);
- add_entity_linkage(entity, IR_LINKAGE_CONSTANT);
+static ir_node *string_to_firm(source_position_t const *const src_pos, char const *const id_prefix, string_t const *const value)
+{
+ size_t const slen = get_string_len(value) + 1;
+ ir_initializer_t *const initializer = create_initializer_compound(slen);
+ ir_type * elem_type;
+ switch (value->encoding) {
+ case STRING_ENCODING_CHAR: {
+ elem_type = ir_type_char;
+
+ ir_mode *const mode = get_type_mode(elem_type);
+ char const *p = value->begin;
+ for (size_t i = 0; i < slen; ++i) {
+ ir_tarval *tv = new_tarval_from_long(*p++, mode);
+ ir_initializer_t *val = create_initializer_tarval(tv);
+ set_initializer_compound_value(initializer, i, val);
+ }
+ goto finish;
+ }
- ir_type *const elem_type = ir_type_const_char;
- ir_mode *const mode = get_type_mode(elem_type);
+ case STRING_ENCODING_WIDE: {
+ elem_type = ir_type_wchar_t;
- const char* const string = value->begin;
- const size_t slen = value->size;
+ ir_mode *const mode = get_type_mode(elem_type);
+ char const *p = value->begin;
+ for (size_t i = 0; i < slen; ++i) {
+ assert(p <= value->begin + value->size);
+ utf32 v = read_utf8_char(&p);
+ ir_tarval *tv = new_tarval_from_long(v, mode);
+ ir_initializer_t *val = create_initializer_tarval(tv);
+ set_initializer_compound_value(initializer, i, val);
+ }
+ goto finish;
+ }
+ }
+ panic("invalid string encoding");
- set_array_lower_bound_int(type, 0, 0);
- set_array_upper_bound_int(type, 0, slen);
- set_type_size_bytes(type, slen);
- set_type_state(type, layout_fixed);
+finish:;
+ ir_type *const type = new_type_array(1, elem_type);
+ set_array_bounds_int(type, 0, 0, slen);
+ set_type_size_bytes( type, slen * get_type_size_bytes(elem_type));
+ set_type_state( type, layout_fixed);
- ir_initializer_t *initializer = create_initializer_compound(slen);
- for (size_t i = 0; i < slen; ++i) {
- ir_tarval *tv = new_tarval_from_long(string[i], mode);
- ir_initializer_t *val = create_initializer_tarval(tv);
- set_initializer_compound_value(initializer, i, val);
- }
+ ir_type *const global_type = get_glob_type();
+ ident *const id = id_unique(id_prefix);
+ dbg_info *const dbgi = get_dbg_info(src_pos);
+ ir_entity *const entity = new_d_entity(global_type, id, type, dbgi);
+ set_entity_ld_ident( entity, id);
+ set_entity_visibility( entity, ir_visibility_private);
+ add_entity_linkage( entity, IR_LINKAGE_CONSTANT);
set_entity_initializer(entity, initializer);
return create_symconst(dbgi, entity);
static bool try_create_integer(literal_expression_t *literal, type_t *type)
{
- const char *string = literal->value.begin;
- size_t size = literal->value.size;
-
assert(type->kind == TYPE_ATOMIC);
atomic_type_kind_t akind = type->atomic.akind;
- ir_mode *const mode = atomic_modes[akind];
- ir_tarval *const tv = new_tarval_from_str(string, size, mode);
+ ir_mode *const mode = atomic_modes[akind];
+ char const *const str = literal->value.begin;
+ ir_tarval *const tv = new_tarval_from_str(str, literal->suffix - str, mode);
if (tv == tarval_bad)
return false;
return true;
}
-static void create_integer_tarval(literal_expression_t *literal)
+void determine_literal_type(literal_expression_t *const literal)
{
+ assert(literal->base.kind == EXPR_LITERAL_INTEGER);
+
/* -1: signed only, 0: any, 1: unsigned only */
- int sign = literal->value.begin[0] != '0' /* decimal */ ? -1 : 0;
- unsigned ls = 0;
- const string_t *suffix = &literal->suffix;
- /* parse suffix */
- if (suffix->size > 0) {
- for (const char *c = suffix->begin; *c != '\0'; ++c) {
- if (*c == 'u' || *c == 'U') sign = 1;
- if (*c == 'l' || *c == 'L') { ++ls; }
- }
- }
+ int const sign =
+ !is_type_signed(literal->base.type) ? 1 :
+ literal->value.begin[0] == '0' ? 0 :
+ -1; /* Decimal literals only try signed types. */
tarval_int_overflow_mode_t old_mode = tarval_get_integer_overflow_mode();
+ tarval_set_integer_overflow_mode(TV_OVERFLOW_BAD);
+
+ if (try_create_integer(literal, literal->base.type))
+ goto finished;
/* now try if the constant is small enough for some types */
- tarval_set_integer_overflow_mode(TV_OVERFLOW_BAD);
- if (ls < 1) {
- if (sign <= 0 && try_create_integer(literal, type_int))
- goto finished;
- if (sign >= 0 && try_create_integer(literal, type_unsigned_int))
- goto finished;
- }
- if (ls < 2) {
- if (sign <= 0 && try_create_integer(literal, type_long))
- goto finished;
- if (sign >= 0 && try_create_integer(literal, type_unsigned_long))
- goto finished;
- }
+ if (sign >= 0 && try_create_integer(literal, type_unsigned_int))
+ goto finished;
+ if (sign <= 0 && try_create_integer(literal, type_long))
+ goto finished;
+ if (sign >= 0 && try_create_integer(literal, type_unsigned_long))
+ goto finished;
/* last try? then we should not report tarval_bad */
if (sign < 0)
tarval_set_integer_overflow_mode(TV_OVERFLOW_WRAP);
tarval_set_integer_overflow_mode(old_mode);
}
-void determine_literal_type(literal_expression_t *literal)
+/**
+ * Creates a Const node representing a constant.
+ */
+static ir_node *literal_to_firm(const literal_expression_t *literal)
{
+ type_t *type = skip_typeref(literal->base.type);
+ ir_mode *mode = get_ir_mode_storage(type);
+ const char *string = literal->value.begin;
+ size_t size = literal->value.size;
+ ir_tarval *tv;
+
switch (literal->base.kind) {
case EXPR_LITERAL_INTEGER:
- create_integer_tarval(literal);
- return;
- default:
+ assert(literal->target_value != NULL);
+ tv = literal->target_value;
+ break;
+
+ case EXPR_LITERAL_FLOATINGPOINT:
+ tv = new_tarval_from_str(string, size, mode);
break;
+
+ case EXPR_LITERAL_BOOLEAN:
+ if (string[0] == 't') {
+ tv = get_mode_one(mode);
+ } else {
+ assert(string[0] == 'f');
+ case EXPR_LITERAL_MS_NOOP:
+ tv = get_mode_null(mode);
+ }
+ break;
+
+ default:
+ panic("Invalid literal kind found");
}
+
+ dbg_info *dbgi = get_dbg_info(&literal->base.source_position);
+ ir_node *res = new_d_Const(dbgi, tv);
+ ir_mode *mode_arith = get_ir_mode_arithmetic(type);
+ return create_conv(dbgi, res, mode_arith);
}
/**
- * Creates a Const node representing a constant.
+ * Creates a Const node representing a character constant.
*/
-static ir_node *literal_to_firm(const literal_expression_t *literal)
+static ir_node *char_literal_to_firm(string_literal_expression_t const *literal)
{
type_t *type = skip_typeref(literal->base.type);
ir_mode *mode = get_ir_mode_storage(type);
size_t size = literal->value.size;
ir_tarval *tv;
- switch (literal->base.kind) {
- case EXPR_LITERAL_WIDE_CHARACTER: {
+ switch (literal->value.encoding) {
+ case STRING_ENCODING_WIDE: {
utf32 v = read_utf8_char(&string);
char buf[128];
size_t len = snprintf(buf, sizeof(buf), UTF32_PRINTF_FORMAT, v);
break;
}
- case EXPR_LITERAL_CHARACTER: {
+ case STRING_ENCODING_CHAR: {
long long int v;
bool char_is_signed
= get_atomic_type_flags(ATOMIC_TYPE_CHAR) & ATOMIC_TYPE_FLAG_SIGNED;
break;
}
- case EXPR_LITERAL_INTEGER:
- assert(literal->target_value != NULL);
- tv = literal->target_value;
- break;
-
- case EXPR_LITERAL_FLOATINGPOINT:
- tv = new_tarval_from_str(string, size, mode);
- break;
-
- case EXPR_LITERAL_BOOLEAN:
- if (string[0] == 't') {
- tv = get_mode_one(mode);
- } else {
- assert(string[0] == 'f');
- case EXPR_LITERAL_MS_NOOP:
- tv = get_mode_null(mode);
- }
- break;
-
default:
panic("Invalid literal kind found");
}
return create_conv(dbgi, load_res, mode_arithmetic);
}
-/**
- * Creates a strict Conv (to the node's mode) if necessary.
- *
- * @param dbgi debug info
- * @param node the node to strict conv
- */
-static ir_node *do_strict_conv(dbg_info *dbgi, ir_node *node)
-{
- ir_mode *mode = get_irn_mode(node);
-
- if (!(get_irg_fp_model(current_ir_graph) & fp_explicit_rounding))
- return node;
- if (!mode_is_float(mode))
- return node;
-
- /* check if there is already a Conv */
- if (is_Conv(node)) {
- /* convert it into a strict Conv */
- set_Conv_strict(node, 1);
- return node;
- }
-
- /* otherwise create a new one */
- return new_d_strictConv(dbgi, node, mode);
-}
-
/**
* Returns the correct base address depending on whether it is a parameter or a
* normal local variable.
if (!is_type_compound(arg_type)) {
ir_mode *const mode = get_ir_mode_storage(arg_type);
arg_node = create_conv(dbgi, arg_node, mode);
- arg_node = do_strict_conv(dbgi, arg_node);
}
in[n] = arg_node;
if (!is_type_compound(type)) {
ir_mode *mode = get_ir_mode_storage(type);
value = create_conv(dbgi, value, mode);
- value = do_strict_conv(dbgi, value);
}
ir_node *memory = get_store();
if (!is_type_compound(type)) {
ir_mode *mode = get_ir_mode_storage(type);
value = create_conv(dbgi, value, mode);
- value = do_strict_conv(dbgi, value);
}
if (expression->kind == EXPR_REFERENCE) {
default:
break;
}
- panic("trying to get pn_Cmp from non-comparison binexpr type");
+ panic("trying to get ir_relation from non-comparison binexpr type");
}
/**
ir_mode *mode_arith = get_ir_mode_arithmetic(type);
ir_node *node = create_conv(dbgi, value_node, mode);
- node = do_strict_conv(dbgi, node);
node = create_conv(dbgi, node, mode_arith);
return node;
case EXPR_BINARY_MOD:
case EXPR_BINARY_MOD_ASSIGN: {
ir_node *pin = new_Pin(new_NoMem());
- assert(!mode_is_float(mode));
ir_node *op = new_d_Mod(dbgi, pin, left, right, mode,
op_pin_state_floats);
ir_node *res = new_d_Proj(dbgi, op, mode, pn_Mod_res);
ir_node *result = create_op(dbgi, expression, left, right);
result = create_cast(dbgi, result, expression->right->base.type, type);
- result = do_strict_conv(dbgi, result);
result = set_value_for_expression_addr(left_expr, result, left_addr);
case EXPR_BINARY_SHIFTRIGHT_ASSIGN:
return create_assign_binop(expression);
default:
- panic("TODO binexpr type");
+ panic("invalid binexpr type");
}
}
compound_t *compound = type->compound.compound;
entity_t *iter = compound->members.entities;
- for ( ; iter != NULL; iter = iter->base.next) {
- if (iter->base.symbol == symbol) {
- break;
- }
- }
- assert(iter != NULL);
+ for (; iter->base.symbol != symbol; iter = iter->base.next) {}
assert(iter->kind == ENTITY_COMPOUND_MEMBER);
assert(iter->declaration.kind == DECLARATION_KIND_COMPOUND_MEMBER);
type_t *type)
{
/* create the ir_initializer */
- ir_graph *const old_current_ir_graph = current_ir_graph;
- current_ir_graph = get_const_code_irg();
-
+ PUSH_IRG(get_const_code_irg());
ir_initializer_t *irinitializer = create_ir_initializer(initializer, type);
-
- assert(current_ir_graph == get_const_code_irg());
- current_ir_graph = old_current_ir_graph;
+ POP_IRG();
ident *const id = id_unique("initializer.%u");
ir_type *const irtype = get_ir_type(type);
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);
init_ir_types();
- ir_graph *old_current_ir_graph = current_ir_graph;
- current_ir_graph = get_const_code_irg();
-
+ PUSH_IRG(get_const_code_irg());
ir_node *const cnst = _expression_to_firm(expression);
+ POP_IRG();
- current_ir_graph = old_current_ir_graph;
set_optimize(old_optimize);
set_opt_constant_folding(old_constant_folding);
case TYPE_ATOMIC: {
const atomic_type_t *const atomic_type = &type->atomic;
switch (atomic_type->akind) {
- /* should not be reached */
- case ATOMIC_TYPE_INVALID:
- tc = no_type_class;
- goto make_const;
-
/* gcc cannot do that */
case ATOMIC_TYPE_VOID:
tc = void_type_class;
case FUNCNAME_PRETTY_FUNCTION:
case FUNCNAME_FUNCDNAME:
if (current_function_name == NULL) {
- const source_position_t *const src_pos = &expr->base.source_position;
- const char *name = current_function_entity->base.symbol->string;
- const string_t string = { name, strlen(name) + 1 };
+ source_position_t const *const src_pos = &expr->base.source_position;
+ char const *const name = current_function_entity->base.symbol->string;
+ string_t const string = { name, strlen(name), STRING_ENCODING_CHAR };
current_function_name = string_to_firm(src_pos, "__func__.%u", &string);
}
return current_function_name;
case FUNCNAME_FUNCSIG:
if (current_funcsig == NULL) {
- const source_position_t *const src_pos = &expr->base.source_position;
- ir_entity *ent = get_irg_entity(current_ir_graph);
- const char *const name = get_entity_ld_name(ent);
- const string_t string = { name, strlen(name) + 1 };
+ source_position_t const *const src_pos = &expr->base.source_position;
+ ir_entity *const ent = get_irg_entity(current_ir_graph);
+ char const *const name = get_entity_ld_name(ent);
+ string_t const string = { name, strlen(name), STRING_ENCODING_CHAR };
current_funcsig = string_to_firm(src_pos, "__FUNCSIG__.%u", &string);
}
return current_funcsig;
if (label->block != NULL)
return label->block;
- /* beware: might be called from create initializer with current_ir_graph
- * set to const_code_irg. */
- ir_graph *rem = current_ir_graph;
- current_ir_graph = current_function;
-
ir_node *block = new_immBlock();
-
label->block = block;
-
- ARR_APP1(label_t *, all_labels, label);
-
- current_ir_graph = rem;
+ if (label->address_taken)
+ ARR_APP1(ir_node*, ijmp_blocks, block);
return block;
}
*/
static ir_node *label_address_to_firm(const label_address_expression_t *label)
{
+ /* Beware: Might be called from create initializer with current_ir_graph
+ * set to const_code_irg. */
+ PUSH_IRG(current_function);
dbg_info *dbgi = get_dbg_info(&label->base.source_position);
ir_node *block = get_label_block(label->label);
ir_entity *entity = create_Block_entity(block);
+ POP_IRG();
symconst_symbol value;
value.entity_p = entity;
case EXPR_FUNCNAME: return function_name_to_firm( &expr->funcname);
case EXPR_LABEL_ADDRESS: return label_address_to_firm( &expr->label_address);
case EXPR_LITERAL_CASES: return literal_to_firm( &expr->literal);
+ case EXPR_LITERAL_CHARACTER: return char_literal_to_firm( &expr->string_literal);
case EXPR_OFFSETOF: return offsetof_to_firm( &expr->offsetofe);
case EXPR_REFERENCE: return reference_expression_to_firm( &expr->reference);
case EXPR_ENUM_CONSTANT: return enum_constant_to_firm( &expr->reference);
case EXPR_VA_ARG: return va_arg_expression_to_firm( &expr->va_arge);
case EXPR_VA_COPY: return va_copy_expression_to_firm( &expr->va_copye);
case EXPR_VA_START: return va_start_expression_to_firm( &expr->va_starte);
- case EXPR_WIDE_STRING_LITERAL: return wide_string_literal_to_firm( &expr->string_literal);
case EXPR_STRING_LITERAL: return string_to_firm(&expr->base.source_position, "str.%u", &expr->string_literal.value);
compound_t *compound = type->compound.compound;
entity_t *iter = compound->members.entities;
- for ( ; iter != NULL; iter = iter->base.next, ++index) {
- if (iter->base.symbol == symbol) {
- assert(iter->kind == ENTITY_COMPOUND_MEMBER);
- break;
- }
- }
- assert(iter != NULL);
+ for (; iter->base.symbol != symbol; iter = iter->base.next, ++index) {}
+ assert(iter->kind == ENTITY_COMPOUND_MEMBER);
/* revert previous initialisations of other union elements */
if (type->kind == TYPE_COMPOUND_UNION) {
orig_type = iter->declaration.type;
} else {
expression_t *array_index = designator->array_index;
- assert(designator->array_index != NULL);
assert(is_type_array(type));
long index = fold_constant_to_int(array_index);
- assert(index >= 0);
-#ifndef NDEBUG
- if (type->array.size_constant) {
- long array_size = type->array.size;
- assert(index < array_size);
- }
-#endif
+ assert(0 <= index && (!type->array.size_constant || (size_t)index < type->array.size));
top->type = orig_type;
top->index = (size_t) index;
/** test wether type can be initialized by a string constant */
static bool is_string_type(type_t *type)
{
- type_t *inner;
- if (is_type_pointer(type)) {
- inner = skip_typeref(type->pointer.points_to);
- } else if(is_type_array(type)) {
- inner = skip_typeref(type->array.element_type);
- } else {
+ if (!is_type_array(type))
return false;
- }
+ type_t *const inner = skip_typeref(type->array.element_type);
return is_type_integer(inner);
}
break;
descend_into_subtype(&path);
}
- } else if (sub_initializer->kind == INITIALIZER_STRING
- || sub_initializer->kind == INITIALIZER_WIDE_STRING) {
+ } else if (sub_initializer->kind == INITIALIZER_STRING) {
/* we might have to descend into types until we're at a scalar
* type */
while (true) {
return result;
}
-static ir_initializer_t *create_ir_initializer_string(
- const initializer_string_t *initializer, type_t *type)
+static ir_initializer_t *create_ir_initializer_string(initializer_t const *const init, type_t *type)
{
type = skip_typeref(type);
- size_t string_len = initializer->string.size;
assert(type->kind == TYPE_ARRAY);
assert(type->array.size_constant);
- size_t len = type->array.size;
- ir_initializer_t *irinitializer = create_initializer_compound(len);
-
- const char *string = initializer->string.begin;
- ir_mode *mode = get_ir_mode_storage(type->array.element_type);
-
- for (size_t i = 0; i < len; ++i) {
- char c = 0;
- if (i < string_len)
- c = string[i];
-
- ir_tarval *tv = new_tarval_from_long(c, mode);
- ir_initializer_t *char_initializer = create_initializer_tarval(tv);
-
- set_initializer_compound_value(irinitializer, i, char_initializer);
- }
-
- return irinitializer;
-}
-
-static ir_initializer_t *create_ir_initializer_wide_string(
- const initializer_wide_string_t *initializer, type_t *type)
-{
- assert(type->kind == TYPE_ARRAY);
- assert(type->array.size_constant);
- size_t len = type->array.size;
- size_t string_len = wstrlen(&initializer->string);
- ir_initializer_t *irinitializer = create_initializer_compound(len);
-
- const char *p = initializer->string.begin;
- ir_mode *mode = get_type_mode(ir_type_wchar_t);
-
- for (size_t i = 0; i < len; ++i) {
- utf32 c = 0;
- if (i < string_len) {
- c = read_utf8_char(&p);
+ string_literal_expression_t const *const str = get_init_string(init);
+ size_t const str_len = str->value.size;
+ size_t const arr_len = type->array.size;
+ ir_initializer_t *const irinit = create_initializer_compound(arr_len);
+ ir_mode *const mode = get_ir_mode_storage(type->array.element_type);
+ char const * p = str->value.begin;
+ switch (str->value.encoding) {
+ case STRING_ENCODING_CHAR:
+ 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);
+ ir_initializer_t *const tvinit = create_initializer_tarval(tv);
+ set_initializer_compound_value(irinit, i, tvinit);
}
- ir_tarval *tv = new_tarval_from_long(c, mode);
- ir_initializer_t *char_initializer = create_initializer_tarval(tv);
+ break;
- set_initializer_compound_value(irinitializer, i, char_initializer);
+ case STRING_ENCODING_WIDE:
+ for (size_t i = 0; i != arr_len; ++i) {
+ utf32 const c = i < str_len ? read_utf8_char(&p) : 0;
+ ir_tarval *const tv = new_tarval_from_long(c, mode);
+ ir_initializer_t *const tvinit = create_initializer_tarval(tv);
+ set_initializer_compound_value(irinit, i, tvinit);
+ }
+ break;
}
- return irinitializer;
+ return irinit;
}
static ir_initializer_t *create_ir_initializer(
{
switch(initializer->kind) {
case INITIALIZER_STRING:
- return create_ir_initializer_string(&initializer->string, type);
-
- case INITIALIZER_WIDE_STRING:
- return create_ir_initializer_wide_string(&initializer->wide_string,
- type);
+ return create_ir_initializer_string(initializer, type);
case INITIALIZER_LIST:
return create_ir_initializer_list(&initializer->list, type);
dbg_info *const dbgi = get_dbg_info(&entity->base.source_position);
ir_mode *const mode = get_ir_mode_storage(init_type);
node = create_conv(dbgi, node, mode);
- node = do_strict_conv(dbgi, node);
if (declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE) {
set_value(entity->variable.v.value_number, node);
entity->variable.v.vla_base = addr;
}
+static bool var_needs_entity(variable_t const *const var)
+{
+ if (var->address_taken)
+ return true;
+ type_t *const type = skip_typeref(var->base.type);
+ return !is_type_scalar(type) || type->base.qualifiers & TYPE_QUALIFIER_VOLATILE;
+}
+
/**
* Creates a Firm local variable from a declaration.
*/
assert(entity->kind == ENTITY_VARIABLE);
assert(entity->declaration.kind == DECLARATION_KIND_UNKNOWN);
- bool needs_entity = entity->variable.address_taken;
- type_t *type = skip_typeref(entity->declaration.type);
+ if (!var_needs_entity(&entity->variable)) {
+ entity->declaration.kind = DECLARATION_KIND_LOCAL_VARIABLE;
+ entity->variable.v.value_number = next_value_number_function;
+ set_irg_loc_description(current_ir_graph, next_value_number_function, entity);
+ ++next_value_number_function;
+ return;
+ }
/* is it a variable length array? */
+ type_t *const type = skip_typeref(entity->declaration.type);
if (is_type_array(type) && !type->array.size_constant) {
create_variable_length_array(entity);
return;
- } else if (is_type_array(type) || is_type_compound(type)) {
- needs_entity = true;
- } else if (type->base.qualifiers & TYPE_QUALIFIER_VOLATILE) {
- needs_entity = true;
}
- if (needs_entity) {
- ir_type *frame_type = get_irg_frame_type(current_ir_graph);
- create_variable_entity(entity,
- DECLARATION_KIND_LOCAL_VARIABLE_ENTITY,
- frame_type);
- } else {
- entity->declaration.kind = DECLARATION_KIND_LOCAL_VARIABLE;
- entity->variable.v.value_number = next_value_number_function;
- set_irg_loc_description(current_ir_graph, next_value_number_function,
- entity);
- ++next_value_number_function;
- }
+ ir_type *const frame_type = get_irg_frame_type(current_ir_graph);
+ create_variable_entity(entity, DECLARATION_KIND_LOCAL_VARIABLE_ENTITY, frame_type);
}
static void create_local_static_variable(entity_t *entity)
set_entity_initializer(irentity, null_init);
}
- ir_graph *const old_current_ir_graph = current_ir_graph;
- current_ir_graph = get_const_code_irg();
-
+ PUSH_IRG(get_const_code_irg());
create_variable_initializer(entity);
-
- assert(current_ir_graph == get_const_code_irg());
- current_ir_graph = old_current_ir_graph;
+ POP_IRG();
}
ir_mode *const mode = get_ir_mode_storage(type);
if (res) {
res = create_conv(dbgi, res, mode);
- res = do_strict_conv(dbgi, res);
} else {
res = new_Unknown(mode);
}
return;
case STORAGE_CLASS_EXTERN:
if (entity->kind == ENTITY_FUNCTION) {
- assert(entity->function.statement == NULL);
+ assert(entity->function.body == NULL);
(void)get_function_entity(entity, NULL);
} else {
create_global_variable(entity);
case STORAGE_CLASS_AUTO:
case STORAGE_CLASS_REGISTER:
if (entity->kind == ENTITY_FUNCTION) {
- if (entity->function.statement != NULL) {
+ if (entity->function.body != NULL) {
ir_type *owner = get_irg_frame_type(current_ir_graph);
(void)get_function_entity(entity, owner);
entity->declaration.kind = DECLARATION_KIND_INNER_FUNCTION;
{
ir_node *const pred = currently_reachable() ? new_Jmp() : new_Bad(mode_X);
add_immBlock_pred(target_block, pred);
+ set_cur_block(target_block);
}
/**
add_immBlock_pred(target_block, new_Jmp());
}
-static ir_node *while_statement_to_firm(while_statement_t *statement)
-{
- create_local_declarations(statement->scope.entities);
-
- /* Create the header block */
- ir_node *const header_block = new_immBlock();
- jump_to(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(header_block);
- keep_all_memory(header_block);
- } else {
- body_block = new_immBlock();
- false_block = new_immBlock();
-
- set_cur_block(header_block);
- create_condition_evaluation(cond, body_block, false_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;
- return NULL;
-}
-
static ir_node *get_break_label(void)
{
if (break_label == NULL) {
/* create the header block */
ir_node *header_block = new_immBlock();
- /* the loop body */
- ir_node *body_block = new_immBlock();
- jump_to(body_block);
-
- ir_node *old_continue_label = continue_label;
- ir_node *old_break_label = break_label;
- continue_label = header_block;
- break_label = NULL;
+ PUSH_BREAK(NULL);
+ PUSH_CONTINUE(header_block);
- set_cur_block(body_block);
+ /* The loop body. */
+ ir_node *body_block = NULL;
+ expression_t *const cond = statement->condition;
+ /* Avoid an explicit body block in case of do ... while (0);. */
+ if (is_constant_expression(cond) != EXPR_CLASS_CONSTANT || fold_constant_to_bool(cond)) {
+ /* Not do ... while (0);. */
+ body_block = new_immBlock();
+ jump_to(body_block);
+ }
statement_to_firm(statement->body);
- ir_node *const false_block = get_break_label();
-
- assert(continue_label == header_block);
- continue_label = old_continue_label;
- break_label = old_break_label;
-
- jump_if_reachable(header_block);
/* create the condition */
+ jump_if_reachable(header_block);
mature_immBlock(header_block);
set_cur_block(header_block);
-
- create_condition_evaluation(statement->condition, body_block, false_block);
- mature_immBlock(body_block);
+ ir_node *const false_block = get_break_label();
+ if (body_block) {
+ create_condition_evaluation(statement->condition, body_block, false_block);
+ mature_immBlock(body_block);
+ } else {
+ jump_if_reachable(false_block);
+ }
mature_immBlock(false_block);
-
set_cur_block(false_block);
+
+ POP_CONTINUE();
+ POP_BREAK();
return NULL;
}
jump_to(header_block);
/* Create the condition. */
- ir_node *body_block;
- ir_node *false_block;
- if (statement->condition != NULL) {
- body_block = new_immBlock();
+ ir_node *false_block;
+ expression_t *const cond = statement->condition;
+ if (cond && (is_constant_expression(cond) != EXPR_CLASS_CONSTANT || !fold_constant_to_bool(cond))) {
false_block = new_immBlock();
- set_cur_block(header_block);
- create_condition_evaluation(statement->condition, body_block, false_block);
+ ir_node *const body_block = new_immBlock();
+ create_condition_evaluation(cond, body_block, false_block);
mature_immBlock(body_block);
+ set_cur_block(body_block);
} else {
/* for-ever. */
- body_block = header_block;
false_block = NULL;
keep_alive(header_block);
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;
+ PUSH_BREAK(false_block);
+ PUSH_CONTINUE(step_block);
/* Create the loop body. */
- set_cur_block(body_block);
statement_to_firm(statement->body);
jump_if_reachable(step_block);
}
set_cur_block(false_block);
- assert(continue_label == step_block);
- continue_label = old_continue_label;
- break_label = old_break_label;
+ POP_CONTINUE();
+ POP_BREAK();
return NULL;
}
}
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;
}
set_unreachable_now();
+ PUSH_BREAK(NULL);
ir_node *const old_switch = current_switch;
- ir_node *const old_break_label = break_label;
const bool old_saw_default_label = saw_default_label;
saw_default_label = false;
current_switch = switch_node;
- break_label = NULL;
statement_to_firm(statement->body);
assert(current_switch == switch_node);
current_switch = old_switch;
- break_label = old_break_label;
saw_default_label = old_saw_default_label;
+ POP_BREAK();
return NULL;
}
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);
- set_cur_block(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())
static ir_node *asm_statement_to_firm(const asm_statement_t *statement)
{
- bool needs_memory = false;
-
- if (statement->is_volatile) {
- needs_memory = true;
- }
-
- size_t n_clobbers = 0;
- asm_clobber_t *clobber = statement->clobbers;
+ bool needs_memory = statement->is_volatile;
+ size_t n_clobbers = 0;
+ asm_clobber_t *clobber = statement->clobbers;
for ( ; clobber != NULL; clobber = clobber->next) {
const char *clobber_str = clobber->clobber.begin;
constraint.mode = mode_M;
tmp_in_constraints[in_size] = constraint;
- ins[in_size] = expression_to_addr(expr);
+ ins[in_size] = expression_to_addr(expr);
++in_size;
continue;
} else {
ins[in_size++] = input;
}
- if (needs_memory) {
- ir_asm_constraint constraint;
- constraint.pos = next_pos++;
- constraint.constraint = new_id_from_str("");
- constraint.mode = mode_M;
-
- obstack_grow(&asm_obst, &constraint, sizeof(constraint));
- ins[in_size++] = get_store();
- }
-
+ ir_node *mem = needs_memory ? get_store() : new_NoMem();
assert(obstack_object_size(&asm_obst)
== in_size * sizeof(ir_asm_constraint));
ir_asm_constraint *input_constraints = obstack_finish(&asm_obst);
ident *asm_text = new_id_from_str(statement->asm_text.begin);
- ir_node *node = new_d_ASM(dbgi, in_size, ins, input_constraints,
+ ir_node *node = new_d_ASM(dbgi, mem, in_size, ins, input_constraints,
out_size, output_constraints,
n_clobbers, clobbers, asm_text);
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_MS_TRY: return ms_try_statement_to_firm( &stmt->ms_try);
case STATEMENT_RETURN: return return_statement_to_firm( &stmt->returns);
case STATEMENT_SWITCH: return switch_statement_to_firm( &stmt->switchs);
- case STATEMENT_WHILE: return while_statement_to_firm( &stmt->whiles);
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");
}
entity_t const *const end = last != NULL ? last->base.next : NULL;
for (; entity != end; entity = entity->base.next) {
if ((entity->kind == ENTITY_VARIABLE || entity->kind == ENTITY_PARAMETER) &&
- !entity->variable.address_taken &&
- is_type_scalar(skip_typeref(entity->declaration.type)))
+ !var_needs_entity(&entity->variable))
++count;
}
return count;
count += count_local_variables(function->parameters.entities, NULL);
/* count local variables declared in body */
- walk_statements(function->statement, count_local_variables_in_stmt, &count);
+ walk_statements(function->body, count_local_variables_in_stmt, &count);
return count;
}
assert(parameter->declaration.kind == DECLARATION_KIND_UNKNOWN);
type_t *type = skip_typeref(parameter->declaration.type);
- assert(!is_type_array(type));
- bool const needs_entity = parameter->variable.address_taken || is_type_compound(type);
-
- ir_type *param_irtype = get_method_param_type(function_irtype, n);
- if (needs_entity) {
+ dbg_info *const dbgi = get_dbg_info(¶meter->base.source_position);
+ ir_type *const param_irtype = get_method_param_type(function_irtype, n);
+ if (var_needs_entity(¶meter->variable)) {
ir_type *frame_type = get_irg_frame_type(irg);
ir_entity *param
- = new_parameter_entity(frame_type, n, param_irtype);
+ = new_d_parameter_entity(frame_type, n, param_irtype, dbgi);
parameter->declaration.kind = DECLARATION_KIND_PARAMETER_ENTITY;
parameter->variable.v.entity = param;
continue;
ir_mode *param_mode = get_type_mode(param_irtype);
long pn = n;
- ir_node *value = new_r_Proj(args, param_mode, pn);
+ ir_node *value = new_rd_Proj(dbgi, args, param_mode, pn);
ir_mode *mode = get_ir_mode_storage(type);
value = create_conv(NULL, value, mode);
- value = do_strict_conv(NULL, value);
parameter->declaration.kind = DECLARATION_KIND_PARAMETER;
parameter->variable.v.value_number = next_value_number_function;
}
}
-/**
- * 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)
{
assert(entity->kind == ENTITY_FUNCTION);
ir_entity *function_entity = get_function_entity(entity, current_outer_frame);
- if (entity->function.statement == NULL)
+ if (entity->function.body == NULL)
return;
inner_functions = NULL;
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;
- statement_to_firm(entity->function.statement);
+ statement_to_firm(entity->function.body);
ir_node *end_block = get_irg_end_block(irg);
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);
return;
ir_types_initialized = 1;
- ir_type_char = get_ir_type(type_char);
- ir_type_const_char = get_ir_type(type_const_char);
- ir_type_wchar_t = get_ir_type(type_wchar_t);
+ ir_type_char = get_ir_type(type_char);
+ ir_type_wchar_t = get_ir_type(type_wchar_t);
be_params = be_get_backend_param();
mode_float_arithmetic = be_params->mode_float_arithmetic;
assert(s->kind == STATEMENT_ASM);
char const *const text = s->asms.asm_text.begin;
- size_t size = s->asms.asm_text.size;
-
- /* skip the last \0 */
- if (text[size - 1] == '\0')
- --size;
-
- ident *const id = new_id_from_chars(text, size);
+ size_t const size = s->asms.asm_text.size;
+ ident *const id = new_id_from_chars(text, size);
add_irp_asm(id);
}
}
static const char *get_cwd(void)
{
static char buf[1024];
- if (buf[0] == '\0')
- getcwd(buf, sizeof(buf));
+ if (buf[0] == '\0') {
+ return getcwd(buf, sizeof(buf));
+ }
return buf;
}
} else {
be_dwarf_set_source_language(DW_LANG_C);
}
- be_dwarf_set_compilation_directory(get_cwd());
+ const char *cwd = get_cwd();
+ if (cwd != NULL) {
+ be_dwarf_set_compilation_directory(cwd);
+ }
/* initialize firm arithmetic */
tarval_set_integer_overflow_mode(TV_OVERFLOW_WRAP);