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 *_expression_to_firm(const expression_t *expression);
static ir_node *expression_to_firm(const expression_t *expression);
-static void create_local_declaration(entity_t *entity);
static unsigned decide_modulo_shift(unsigned type_size)
{
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 {
}
}
-enum {
- COMPOUND_IS_STRUCT = false,
- COMPOUND_IS_UNION = true
-};
-
/**
* Construct firm type from ast struct type.
*/
-static ir_type *create_compound_type(compound_type_t *type,
- bool incomplete, bool is_union)
+static ir_type *create_compound_type(compound_type_t *const type, bool const incomplete)
{
compound_t *compound = type->compound;
return compound->irtype;
}
+ bool const is_union = type->base.kind == TYPE_COMPOUND_UNION;
+
symbol_t *type_symbol = compound->base.symbol;
ident *id;
if (type_symbol != NULL) {
/* 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);
static ir_type *get_ir_type_incomplete(type_t *type)
{
- assert(type != NULL);
type = skip_typeref(type);
if (type->base.firm_type != NULL) {
return type->base.firm_type;
}
- switch (type->kind) {
- case TYPE_COMPOUND_STRUCT:
- return create_compound_type(&type->compound, true, COMPOUND_IS_STRUCT);
- case TYPE_COMPOUND_UNION:
- return create_compound_type(&type->compound, true, COMPOUND_IS_UNION);
- default:
+ if (is_type_compound(type)) {
+ return create_compound_type(&type->compound, true);
+ } else {
return get_ir_type(type);
}
}
ir_type *get_ir_type(type_t *type)
{
- assert(type != NULL);
-
type = skip_typeref(type);
if (type->base.firm_type != NULL) {
firm_type = create_array_type(&type->array);
break;
case TYPE_COMPOUND_STRUCT:
- firm_type = create_compound_type(&type->compound, false, COMPOUND_IS_STRUCT);
- break;
case TYPE_COMPOUND_UNION:
- firm_type = create_compound_type(&type->compound, false, COMPOUND_IS_UNION);
+ firm_type = create_compound_type(&type->compound, false);
break;
case TYPE_ENUM:
firm_type = create_enum_type(&type->enumt);
create_ld_ident = func;
}
+static bool declaration_is_definition(const entity_t *entity)
+{
+ switch (entity->kind) {
+ case ENTITY_VARIABLE:
+ return entity->declaration.storage_class != STORAGE_CLASS_EXTERN;
+ case ENTITY_FUNCTION:
+ return entity->function.statement != NULL;
+ case ENTITY_PARAMETER:
+ case ENTITY_COMPOUND_MEMBER:
+ return false;
+ case ENTITY_TYPEDEF:
+ case ENTITY_ENUM:
+ case ENTITY_ENUM_VALUE:
+ case ENTITY_NAMESPACE:
+ case ENTITY_LABEL:
+ case ENTITY_LOCAL_LABEL:
+ break;
+ }
+ panic("declaration_is_definition called on non-declaration");
+}
+
/**
* Handle GNU attributes for entities
*
add_entity_additional_properties(irentity, mtp_property_const);
}
}
- if (modifiers & DM_USED) {
+ if ((modifiers & DM_USED) && declaration_is_definition(entity)) {
add_entity_linkage(irentity, IR_LINKAGE_HIDDEN_USER);
}
- if (modifiers & DM_WEAK) {
+ if ((modifiers & DM_WEAK) && declaration_is_definition(entity)
+ && entity->declaration.storage_class != STORAGE_CLASS_EXTERN) {
add_entity_linkage(irentity, IR_LINKAGE_WEAK);
}
}
return NULL;
}
- if (is_main(entity)) {
- /* force main to C linkage */
- type_t *type = entity->declaration.type;
- assert(is_type_function(type));
- if (type->function.linkage != LINKAGE_C) {
- type_t *new_type = duplicate_type(type);
- new_type->function.linkage = LINKAGE_C;
- type = identify_new_type(new_type);
- entity->declaration.type = type;
- }
- }
-
symbol_t *symbol = entity->base.symbol;
ident *id = new_id_from_str(symbol->string);
ir_entity *irentity = entitymap_get(&entitymap, symbol);
bool const has_body = entity->function.statement != NULL;
if (irentity != NULL) {
- if (get_entity_visibility(irentity) == ir_visibility_external
- && has_body) {
- set_entity_visibility(irentity, ir_visibility_default);
- }
goto entity_created;
}
handle_decl_modifiers(irentity, entity);
if (! nested_function) {
- /* static inline => local
- * extern inline => local
- * inline without definition => local
- * inline with definition => external_visible */
storage_class_tag_t const storage_class
= (storage_class_tag_t) entity->declaration.storage_class;
- bool const is_inline = entity->function.is_inline;
-
- if (is_inline && storage_class == STORAGE_CLASS_NONE && has_body) {
- set_entity_visibility(irentity, ir_visibility_default);
- } else if (storage_class == STORAGE_CLASS_STATIC ||
- (is_inline && has_body)) {
+ if (storage_class == STORAGE_CLASS_STATIC) {
set_entity_visibility(irentity, ir_visibility_local);
- } else if (has_body) {
- set_entity_visibility(irentity, ir_visibility_default);
} else {
set_entity_visibility(irentity, ir_visibility_external);
}
+
+ bool const is_inline = entity->function.is_inline;
+ if (is_inline && has_body) {
+ if (((c_mode & _C99) && storage_class == STORAGE_CLASS_NONE)
+ || ((c_mode & _C99) == 0
+ && storage_class == STORAGE_CLASS_EXTERN)) {
+ add_entity_linkage(irentity, IR_LINKAGE_NO_CODEGEN);
+ }
+ }
} else {
/* nested functions are always local */
set_entity_visibility(irentity, ir_visibility_local);
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, unsigned char base)
+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 *mode = atomic_modes[akind];
- ir_tarval *tv = new_integer_tarval_from_str(string, size, 1, base, mode);
+ ir_mode *const mode = atomic_modes[akind];
+ ir_tarval *const tv = new_tarval_from_str(string, size, mode);
if (tv == tarval_bad)
return false;
static void create_integer_tarval(literal_expression_t *literal)
{
- unsigned us = 0;
+ /* -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') { ++us; }
+ if (*c == 'u' || *c == 'U') sign = 1;
if (*c == 'l' || *c == 'L') { ++ls; }
}
}
- unsigned base;
- switch (literal->base.kind) {
- case EXPR_LITERAL_INTEGER_OCTAL: base = 8; break;
- case EXPR_LITERAL_INTEGER: base = 10; break;
- case EXPR_LITERAL_INTEGER_HEXADECIMAL: base = 16; break;
- default: panic("invalid literal kind");
- }
-
tarval_int_overflow_mode_t old_mode = tarval_get_integer_overflow_mode();
/* now try if the constant is small enough for some types */
tarval_set_integer_overflow_mode(TV_OVERFLOW_BAD);
if (ls < 1) {
- if (us == 0 && try_create_integer(literal, type_int, base))
+ if (sign <= 0 && try_create_integer(literal, type_int))
goto finished;
- if ((us == 1 || base != 10)
- && try_create_integer(literal, type_unsigned_int, base))
+ if (sign >= 0 && try_create_integer(literal, type_unsigned_int))
goto finished;
}
if (ls < 2) {
- if (us == 0 && try_create_integer(literal, type_long, base))
+ if (sign <= 0 && try_create_integer(literal, type_long))
goto finished;
- if ((us == 1 || base != 10)
- && try_create_integer(literal, type_unsigned_long, base))
+ if (sign >= 0 && try_create_integer(literal, type_unsigned_long))
goto finished;
}
/* last try? then we should not report tarval_bad */
- if (us != 1 && base == 10)
+ if (sign < 0)
tarval_set_integer_overflow_mode(TV_OVERFLOW_WRAP);
- if (us == 0 && try_create_integer(literal, type_long_long, base))
+ if (sign <= 0 && try_create_integer(literal, type_long_long))
goto finished;
/* last try */
- assert(us == 1 || base != 10);
+ assert(sign >= 0);
tarval_set_integer_overflow_mode(TV_OVERFLOW_WRAP);
- bool res = try_create_integer(literal, type_unsigned_long_long, base);
+ bool res = try_create_integer(literal, type_unsigned_long_long);
if (!res)
panic("internal error when parsing number literal");
{
switch (literal->base.kind) {
case EXPR_LITERAL_INTEGER:
- case EXPR_LITERAL_INTEGER_OCTAL:
- case EXPR_LITERAL_INTEGER_HEXADECIMAL:
create_integer_tarval(literal);
return;
default:
ir_tarval *tv;
switch (literal->base.kind) {
- case EXPR_LITERAL_WIDE_CHARACTER: {
+ 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");
+ }
+
+ 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 character constant.
+ */
+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);
+ const char *string = literal->value.begin;
+ size_t size = literal->value.size;
+ ir_tarval *tv;
+
+ 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);
tv = new_tarval_from_str(buf, len, mode);
- goto make_const;
+ 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;
size_t len = snprintf(buf, sizeof(buf), "%lld", v);
tv = new_tarval_from_str(buf, len, mode);
- goto make_const;
- }
- case EXPR_LITERAL_INTEGER:
- case EXPR_LITERAL_INTEGER_OCTAL:
- case EXPR_LITERAL_INTEGER_HEXADECIMAL:
- assert(literal->target_value != NULL);
- tv = literal->target_value;
- goto make_const;
- case EXPR_LITERAL_FLOATINGPOINT:
- tv = new_tarval_from_str(string, size, mode);
- goto make_const;
- case EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL: {
- char buffer[size + 2];
- memcpy(buffer, "0x", 2);
- memcpy(buffer+2, string, size);
- tv = new_tarval_from_str(buffer, size+2, mode);
- goto make_const;
+ break;
}
- case EXPR_LITERAL_BOOLEAN:
- if (string[0] == 't') {
- tv = get_mode_one(mode);
- } else {
- assert(string[0] == 'f');
- tv = get_mode_null(mode);
- }
- goto make_const;
- case EXPR_LITERAL_MS_NOOP:
- tv = get_mode_null(mode);
- goto make_const;
+
default:
- break;
+ panic("Invalid literal kind found");
}
- panic("Invalid literal kind found");
-make_const: ;
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 new_Const(entity->enum_value.tv);
}
-static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
+static ir_node *reference_addr(const reference_expression_t *ref)
{
dbg_info *dbgi = get_dbg_info(&ref->base.source_position);
entity_t *entity = ref->entity;
assert(is_declaration(entity));
- type_t *type = skip_typeref(entity->declaration.type);
-
- /* make sure the type is constructed */
- (void) get_ir_type(type);
if (entity->kind == ENTITY_FUNCTION
&& entity->function.btk != BUILTIN_NONE) {
* builtins which don't have entities */
if (irentity == NULL) {
source_position_t const *const pos = &ref->base.source_position;
- symbol_t const *const sym = ref->entity->base.symbol;
- warningf(WARN_OTHER, pos, "taking address of builtin '%Y'", sym);
+ warningf(WARN_OTHER, pos, "taking address of builtin '%N'", ref->entity);
/* simply create a NULL pointer */
ir_mode *mode = get_ir_mode_arithmetic(type_void_ptr);
}
}
- switch ((declaration_kind_t) entity->declaration.kind) {
- case DECLARATION_KIND_UNKNOWN:
- break;
-
- case DECLARATION_KIND_LOCAL_VARIABLE: {
- ir_mode *const mode = get_ir_mode_storage(type);
- ir_node *const value = get_value(entity->variable.v.value_number, mode);
- return create_conv(NULL, value, get_ir_mode_arithmetic(type));
- }
- case DECLARATION_KIND_PARAMETER: {
- ir_mode *const mode = get_ir_mode_storage(type);
- ir_node *const value = get_value(entity->parameter.v.value_number,mode);
- return create_conv(NULL, value, get_ir_mode_arithmetic(type));
- }
- case DECLARATION_KIND_FUNCTION: {
- 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, entity->function.irentity);
- } else {
- /* need trampoline here */
- return create_trampoline(dbgi, mode, entity->function.irentity);
- }
- }
- case DECLARATION_KIND_GLOBAL_VARIABLE: {
- const variable_t *variable = &entity->variable;
- ir_node *const addr = create_symconst(dbgi, variable->v.entity);
- return deref_address(dbgi, variable->base.type, addr);
- }
-
- case DECLARATION_KIND_LOCAL_VARIABLE_ENTITY: {
- ir_entity *irentity = entity->variable.v.entity;
- ir_node *frame = get_local_frame(irentity);
- ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, irentity);
- return deref_address(dbgi, entity->declaration.type, sel);
- }
- case DECLARATION_KIND_PARAMETER_ENTITY: {
- ir_entity *irentity = entity->parameter.v.entity;
- ir_node *frame = get_local_frame(irentity);
- ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, irentity);
- return deref_address(dbgi, entity->declaration.type, sel);
- }
-
- case DECLARATION_KIND_VARIABLE_LENGTH_ARRAY:
- return entity->variable.v.vla_base;
-
- case DECLARATION_KIND_COMPOUND_MEMBER:
- panic("not implemented reference type");
- }
-
- panic("reference to declaration with unknown type found");
-}
-
-static ir_node *reference_addr(const reference_expression_t *ref)
-{
- dbg_info *dbgi = get_dbg_info(&ref->base.source_position);
- entity_t *entity = ref->entity;
- assert(is_declaration(entity));
-
switch((declaration_kind_t) entity->declaration.kind) {
case DECLARATION_KIND_UNKNOWN:
break;
ir_node *const addr = create_symconst(dbgi, entity->variable.v.entity);
return addr;
}
- case DECLARATION_KIND_LOCAL_VARIABLE_ENTITY: {
- ir_entity *irentity = entity->variable.v.entity;
- ir_node *frame = get_local_frame(irentity);
- ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, irentity);
- return sel;
- }
+ case DECLARATION_KIND_LOCAL_VARIABLE_ENTITY:
case DECLARATION_KIND_PARAMETER_ENTITY: {
- ir_entity *irentity = entity->parameter.v.entity;
+ ir_entity *irentity = entity->variable.v.entity;
ir_node *frame = get_local_frame(irentity);
ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, irentity);
-
return sel;
}
panic("reference to declaration with unknown type found");
}
+static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
+{
+ dbg_info *const dbgi = get_dbg_info(&ref->base.source_position);
+ entity_t *const entity = ref->entity;
+ assert(is_declaration(entity));
+
+ switch ((declaration_kind_t)entity->declaration.kind) {
+ case DECLARATION_KIND_LOCAL_VARIABLE:
+ case DECLARATION_KIND_PARAMETER: {
+ type_t *const type = skip_typeref(entity->declaration.type);
+ ir_mode *const mode = get_ir_mode_storage(type);
+ ir_node *const value = get_value(entity->variable.v.value_number, mode);
+ return create_conv(dbgi, value, get_ir_mode_arithmetic(type));
+ }
+
+ default: {
+ ir_node *const addr = reference_addr(ref);
+ return deref_address(dbgi, entity->declaration.type, addr);
+ }
+ }
+}
+
/**
* Transform calls to builtin functions.
*/
type_t *arg_type = skip_typeref(expression->base.type);
if (!is_type_compound(arg_type)) {
- ir_mode *mode = get_ir_mode_storage(expression->base.type);
- arg_node = create_conv(dbgi, arg_node, mode);
- arg_node = do_strict_conv(dbgi, arg_node);
+ 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;
entity_t *entity = ref->entity;
assert(is_declaration(entity));
assert(entity->declaration.kind != DECLARATION_KIND_UNKNOWN);
- if (entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE) {
+ if (entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE ||
+ entity->declaration.kind == DECLARATION_KIND_PARAMETER) {
set_value(entity->variable.v.value_number, value);
return value;
- } else if (entity->declaration.kind == DECLARATION_KIND_PARAMETER) {
- set_value(entity->parameter.v.value_number, value);
- return value;
}
}
|| entity->kind == ENTITY_PARAMETER);
assert(entity->declaration.kind != DECLARATION_KIND_UNKNOWN);
int value_number;
- if (entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE) {
+ if (entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE ||
+ entity->declaration.kind == DECLARATION_KIND_PARAMETER) {
value_number = entity->variable.v.value_number;
assert(addr == NULL);
type_t *type = skip_typeref(expression->base.type);
ir_mode *mode = get_ir_mode_storage(type);
ir_node *res = get_value(value_number, mode);
return create_conv(NULL, res, get_ir_mode_arithmetic(type));
- } else if (entity->declaration.kind == DECLARATION_KIND_PARAMETER) {
- value_number = entity->parameter.v.value_number;
- assert(addr == NULL);
- type_t *type = skip_typeref(expression->base.type);
- ir_mode *mode = get_ir_mode_storage(type);
- ir_node *res = get_value(value_number, mode);
- return create_conv(NULL, res, get_ir_mode_arithmetic(type));
}
}
default:
break;
}
- panic("trying to get pn_Cmp from non-comparison binexpr type");
+ panic("trying to get ir_relation from non-comparison binexpr type");
}
/**
if (from_var != NULL) {
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));
+ value_node = new_d_Add(dbgi, value_node, base, mode);
}
if (to_var != NULL) {
ir_node *const addr = create_symconst(dbgi, to_var->v.entity);
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);
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);
if (tp_expression != NULL) {
entity_t *entity = get_expression_entity(tp_expression);
if (entity != NULL) {
- if (entity->kind == ENTITY_FUNCTION) {
- /* a gnu-extension */
- alignment = 1;
- } else {
- alignment = get_cparser_entity_alignment(entity);
- }
+ alignment = get_cparser_entity_alignment(entity);
}
}
ir_graph *old_current_ir_graph = current_ir_graph;
current_ir_graph = get_const_code_irg();
- ir_node *cnst = expression_to_firm(expression);
+ ir_node *const cnst = _expression_to_firm(expression);
+
current_ir_graph = old_current_ir_graph;
set_optimize(old_optimize);
set_opt_constant_folding(old_constant_folding);
constant_folding = constant_folding_old;
- return get_Const_tarval(cnst);
+ ir_tarval *const tv = get_Const_tarval(cnst);
+ ir_mode *const mode = get_ir_mode_arithmetic(skip_typeref(expression->base.type));
+ return tarval_convert_to(tv, mode);
}
/* this function is only used in parser.c, but it relies on libfirm functionality */
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;
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->literal.value);
+ case EXPR_STRING_LITERAL: return string_to_firm(&expr->base.source_position, "str.%u", &expr->string_literal.value);
case EXPR_ERROR: break;
}
}
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));
- return create_Const_from_bool(mode, !is_Const_null(res));
+ return new_Const(fold_constant_to_tarval(expression));
}
/* we have to produce a 0/1 from the mode_b expression */
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);
type_qualifiers_t tq = get_type_qualifier(type, true);
if (initializer->kind == INITIALIZER_VALUE) {
- initializer_value_t *initializer_value = &initializer->value;
- dbg_info *dbgi = get_dbg_info(&entity->base.source_position);
- expression_t *value = initializer_value->value;
- type_t *init_type = value->base.type;
- type_t *skipped = skip_typeref(init_type);
+ expression_t * value = initializer->value.value;
+ type_t *const init_type = skip_typeref(value->base.type);
- if (!is_type_scalar(skipped)) {
+ if (!is_type_scalar(init_type)) {
/* skip convs */
while (value->kind == EXPR_UNARY_CAST)
value = value->unary.value;
goto have_initializer;
}
- ir_node *node = expression_to_firm(initializer_value->value);
-
- ir_mode *mode = get_ir_mode_storage(init_type);
+ ir_node * node = expression_to_firm(value);
+ 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);
set_entity_ld_ident(irentity, id);
set_entity_visibility(irentity, ir_visibility_local);
+ if (entity->variable.initializer == NULL) {
+ ir_initializer_t *null_init = get_initializer_null();
+ set_entity_initializer(irentity, null_init);
+ }
+
ir_graph *const old_current_ir_graph = current_ir_graph;
current_ir_graph = get_const_code_irg();
return expression_to_firm(statement->expression);
}
+static void create_local_declarations(entity_t*);
+
static ir_node *compound_statement_to_firm(compound_statement_t *compound)
{
- entity_t *entity = compound->scope.entities;
- for ( ; entity != NULL; entity = entity->base.next) {
- if (!is_declaration(entity))
- continue;
-
- create_local_declaration(entity);
- }
+ create_local_declarations(compound->scope.entities);
ir_node *result = NULL;
statement_t *statement = compound->statements;
static void create_global_variable(entity_t *entity)
{
- ir_linkage linkage = IR_LINKAGE_DEFAULT;
- ir_visibility visibility = ir_visibility_default;
- ir_entity *irentity;
+ ir_linkage linkage = IR_LINKAGE_DEFAULT;
+ ir_visibility visibility = ir_visibility_external;
+ storage_class_tag_t storage
+ = (storage_class_tag_t)entity->declaration.storage_class;
+ decl_modifiers_t modifiers = entity->declaration.modifiers;
assert(entity->kind == ENTITY_VARIABLE);
- switch ((storage_class_tag_t)entity->declaration.storage_class) {
+ switch (storage) {
case STORAGE_CLASS_EXTERN: visibility = ir_visibility_external; break;
case STORAGE_CLASS_STATIC: visibility = ir_visibility_local; break;
- case STORAGE_CLASS_NONE:
- visibility = ir_visibility_default;
- /* uninitialized globals get merged in C */
- if (entity->variable.initializer == NULL)
- linkage |= IR_LINKAGE_MERGE;
- break;
+ case STORAGE_CLASS_NONE: visibility = ir_visibility_external; break;
case STORAGE_CLASS_TYPEDEF:
case STORAGE_CLASS_AUTO:
case STORAGE_CLASS_REGISTER:
panic("invalid storage class for global var");
}
+ /* "common" symbols */
+ if (storage == STORAGE_CLASS_NONE
+ && entity->variable.initializer == NULL
+ && !entity->variable.thread_local
+ && (modifiers & DM_WEAK) == 0) {
+ linkage |= IR_LINKAGE_MERGE;
+ }
+
ir_type *var_type = get_glob_type();
if (entity->variable.thread_local) {
var_type = get_tls_type();
- /* LINKAGE_MERGE not supported by current linkers */
- linkage &= ~IR_LINKAGE_MERGE;
}
create_variable_entity(entity, DECLARATION_KIND_GLOBAL_VARIABLE, var_type);
- irentity = entity->variable.v.entity;
+ ir_entity *irentity = entity->variable.v.entity;
add_entity_linkage(irentity, linkage);
set_entity_visibility(irentity, visibility);
+ if (entity->variable.initializer == NULL
+ && storage != STORAGE_CLASS_EXTERN) {
+ ir_initializer_t *null_init = get_initializer_null();
+ set_entity_initializer(irentity, null_init);
+ }
}
static void create_local_declaration(entity_t *entity)
panic("invalid storage class found");
}
+static void create_local_declarations(entity_t *e)
+{
+ for (; e; e = e->base.next) {
+ if (is_declaration(e))
+ create_local_declaration(e);
+ }
+}
+
static void initialize_local_declaration(entity_t *entity)
{
if (entity->base.symbol == NULL)
static ir_node *if_statement_to_firm(if_statement_t *statement)
{
+ create_local_declarations(statement->scope.entities);
+
/* Create the condition. */
ir_node *true_block = NULL;
ir_node *false_block = NULL;
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);
static ir_node *do_while_statement_to_firm(do_while_statement_t *statement)
{
+ create_local_declarations(statement->scope.entities);
+
/* create the header block */
ir_node *header_block = new_immBlock();
static ir_node *for_statement_to_firm(for_statement_t *statement)
{
- /* create declarations */
- entity_t *entity = statement->scope.entities;
- for ( ; entity != NULL; entity = entity->base.next) {
- if (!is_declaration(entity))
- continue;
-
- create_local_declaration(entity);
- }
+ create_local_declarations(statement->scope.entities);
if (currently_reachable()) {
- entity = statement->scope.entities;
+ entity_t *entity = statement->scope.entities;
for ( ; entity != NULL; entity = entity->base.next) {
if (!is_declaration(entity))
continue;
int count = 0;
entity_t const *const end = last != NULL ? last->base.next : NULL;
for (; entity != end; entity = entity->base.next) {
- type_t *type;
- bool address_taken;
-
- if (entity->kind == ENTITY_VARIABLE) {
- type = skip_typeref(entity->declaration.type);
- address_taken = entity->variable.address_taken;
- } else if (entity->kind == ENTITY_PARAMETER) {
- type = skip_typeref(entity->declaration.type);
- address_taken = entity->parameter.address_taken;
- } else {
- continue;
- }
-
- if (!address_taken && is_type_scalar(type))
+ if ((entity->kind == ENTITY_VARIABLE || entity->kind == ENTITY_PARAMETER) &&
+ !entity->variable.address_taken &&
+ is_type_scalar(skip_typeref(entity->declaration.type)))
++count;
}
return count;
assert(parameter->declaration.kind == DECLARATION_KIND_UNKNOWN);
type_t *type = skip_typeref(parameter->declaration.type);
- bool needs_entity = parameter->parameter.address_taken;
assert(!is_type_array(type));
- if (is_type_compound(type)) {
- needs_entity = true;
- }
+ 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) {
ir_type *frame_type = get_irg_frame_type(irg);
ir_entity *param
= new_parameter_entity(frame_type, n, param_irtype);
- parameter->declaration.kind
- = DECLARATION_KIND_PARAMETER_ENTITY;
- parameter->parameter.v.entity = param;
+ parameter->declaration.kind = DECLARATION_KIND_PARAMETER_ENTITY;
+ parameter->variable.v.entity = param;
continue;
}
value = create_conv(NULL, value, mode);
value = do_strict_conv(NULL, value);
- parameter->declaration.kind = DECLARATION_KIND_PARAMETER;
- parameter->parameter.v.value_number = next_value_number_function;
+ parameter->declaration.kind = DECLARATION_KIND_PARAMETER;
+ parameter->variable.v.value_number = next_value_number_function;
set_irg_loc_description(current_ir_graph, next_value_number_function,
parameter);
++next_value_number_function;
- set_value(parameter->parameter.v.value_number, value);
+ set_value(parameter->variable.v.value_number, value);
}
}
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);
}
}