#include "diagnostic.h"
#include "lang_features.h"
#include "types.h"
+#include "type_hash.h"
+#include "mangle.h"
#include "walk_statements.h"
#include "warning.h"
#include "entitymap_t.h"
#include "driver/firm_opt.h"
#include "driver/firm_cmdline.h"
-/* some idents needed for name mangling */
-static ident *id_underscore;
-static ident *id_imp;
-
static ir_type *ir_type_const_char;
static ir_type *ir_type_wchar_t;
static ir_type *ir_type_void;
static ir_node *current_funcsig;
static switch_statement_t *current_switch;
static ir_graph *current_function;
+static translation_unit_t *current_translation_unit;
static entitymap_t entitymap;
DECLARATION_KIND_INNER_FUNCTION
} declaration_kind_t;
-static ir_type *get_ir_type(type_t *type);
+static ir_mode *get_ir_mode(type_t *type);
static ir_type *get_ir_type_incomplete(type_t *type);
static void enqueue_inner_function(entity_t *entity)
return (dbg_info*) pos;
}
-static ir_mode *_atomic_modes[ATOMIC_TYPE_LAST+1];
+static ir_mode *atomic_modes[ATOMIC_TYPE_LAST+1];
static ir_mode *mode_int, *mode_uint;
static ir_node *_expression_to_firm(const expression_t *expression);
static ir_node *expression_to_firm(const expression_t *expression);
-static inline ir_mode *get_ir_mode(type_t *type);
static void create_local_declaration(entity_t *entity);
static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind)
unsigned bit_size = size * 8;
bool is_signed = (flags & ATOMIC_TYPE_FLAG_SIGNED) != 0;
ir_mode_arithmetic arithmetic;
- unsigned modulo_shift;
if (flags & ATOMIC_TYPE_FLAG_INTEGER) {
assert(! (flags & ATOMIC_TYPE_FLAG_FLOAT));
- snprintf(name, sizeof(name), "i%s%u", is_signed ? "" : "u", bit_size);
+ snprintf(name, sizeof(name), "%s%u", is_signed ? "I" : "U",
+ bit_size);
sort = irms_int_number;
arithmetic = irma_twos_complement;
- modulo_shift = bit_size < machine_size ? machine_size : bit_size;
} else {
assert(flags & ATOMIC_TYPE_FLAG_FLOAT);
- snprintf(name, sizeof(name), "f%u", bit_size);
+ snprintf(name, sizeof(name), "F%u", bit_size);
sort = irms_float_number;
arithmetic = irma_ieee754;
- modulo_shift = 0;
}
+ /* note: modulo_shift is 0, as in C it's undefined anyway to shift
+ * a too big amount */
return new_ir_mode(name, sort, bit_size, is_signed, arithmetic,
- modulo_shift);
+ 0);
}
return NULL;
static void init_atomic_modes(void)
{
for (int i = 0; i <= ATOMIC_TYPE_LAST; ++i) {
- _atomic_modes[i] = init_atomic_ir_mode((atomic_type_kind_t) i);
+ atomic_modes[i] = init_atomic_ir_mode((atomic_type_kind_t) i);
}
- mode_int = _atomic_modes[ATOMIC_TYPE_INT];
- mode_uint = _atomic_modes[ATOMIC_TYPE_UINT];
+ mode_int = atomic_modes[ATOMIC_TYPE_INT];
+ mode_uint = atomic_modes[ATOMIC_TYPE_UINT];
/* there's no real void type in firm */
- _atomic_modes[ATOMIC_TYPE_VOID] = mode_int;
+ atomic_modes[ATOMIC_TYPE_VOID] = mode_int;
/* initialize pointer modes */
char name[64];
ir_mode *ptr_mode = new_ir_mode(name, sort, bit_size, is_signed, arithmetic,
modulo_shift);
- set_reference_mode_signed_eq(ptr_mode, _atomic_modes[get_intptr_kind()]);
- set_reference_mode_unsigned_eq(ptr_mode, _atomic_modes[get_uintptr_kind()]);
+ set_reference_mode_signed_eq(ptr_mode, atomic_modes[get_intptr_kind()]);
+ set_reference_mode_unsigned_eq(ptr_mode, atomic_modes[get_uintptr_kind()]);
/* Hmm, pointers should be machine size */
set_modeP_data(ptr_mode);
set_modeP_code(ptr_mode);
}
+ir_mode *get_atomic_mode(atomic_type_kind_t kind)
+{
+ assert(kind <= ATOMIC_TYPE_LAST);
+ return atomic_modes[kind];
+}
+
static unsigned get_compound_type_size(compound_type_t *type)
{
ir_type *irtype = get_ir_type((type_t*) type);
return get_type_size_bytes(irtype);
}
-
static unsigned get_type_size_const(type_t *type)
{
switch(type->kind) {
static ir_type *create_atomic_type(const atomic_type_t *type)
{
atomic_type_kind_t kind = type->akind;
- ir_mode *mode = _atomic_modes[kind];
+ ir_mode *mode = atomic_modes[kind];
ident *id = get_mode_ident(mode);
ir_type *irtype = new_type_primitive(id, mode);
static ir_type *create_complex_type(const complex_type_t *type)
{
atomic_type_kind_t kind = type->akind;
- ir_mode *mode = _atomic_modes[kind];
+ ir_mode *mode = atomic_modes[kind];
ident *id = get_mode_ident(mode);
(void) id;
static ir_type *create_imaginary_type(const imaginary_type_t *type)
{
atomic_type_kind_t kind = type->akind;
- ir_mode *mode = _atomic_modes[kind];
+ ir_mode *mode = atomic_modes[kind];
ident *id = get_mode_ident(mode);
ir_type *irtype = new_type_primitive(id, mode);
/* Hmm, leave default, not accepted by the parser yet. */
break;
}
+
return irtype;
}
snprintf(name, sizeof(name), "I%u", size);
ident *id = new_id_from_str(name);
dbg_info *dbgi = get_dbg_info(&builtin_source_position);
- res = new_d_type_primitive(mangle_u(get_type_ident(base_tp), id), mode, dbgi);
+ res = new_d_type_primitive(id_mangle_u(get_type_ident(base_tp), id), mode, dbgi);
set_primitive_base_type(res, base_tp);
return res;
snprintf(name, sizeof(name), "U%u", size);
ident *id = new_id_from_str(name);
dbg_info *dbgi = get_dbg_info(&builtin_source_position);
- res = new_d_type_primitive(mangle_u(get_type_ident(base_tp), id), mode, dbgi);
+ res = new_d_type_primitive(id_mangle_u(get_type_ident(base_tp), id), mode, dbgi);
set_primitive_base_type(res, base_tp);
return res;
}
}
-static ir_type *get_ir_type(type_t *type)
+ir_type *get_ir_type(type_t *type)
{
assert(type != NULL);
return firm_type;
}
-static inline ir_mode *get_ir_mode(type_t *type)
+ir_mode *get_ir_mode(type_t *type)
{
ir_type *irtype = get_ir_type(type);
static ident *rts_idents[sizeof(rts_data) / sizeof(rts_data[0])];
-/**
- * Mangles an entity linker (ld) name for win32 usage.
- *
- * @param ent the entity to be mangled
- * @param declaration the declaration
- */
-static ident *create_ld_ident_win32(ir_entity *irentity, entity_t *entity)
-{
- ident *id;
-
- if (is_Method_type(get_entity_type(irentity)))
- id = decorate_win32_c_fkt(irentity, get_entity_ident(irentity));
- else {
- /* always add an underscore in win32 */
- id = mangle(id_underscore, get_entity_ident(irentity));
- }
-
- assert(is_declaration(entity));
- decl_modifiers_t decl_modifiers = entity->declaration.modifiers;
- if (decl_modifiers & DM_DLLIMPORT) {
- /* add prefix for imported symbols */
- id = mangle(id_imp, id);
- }
- return id;
-}
-
-/**
- * Mangles an entity linker (ld) name for Linux ELF usage.
- *
- * @param ent the entity to be mangled
- * @param declaration the declaration
- */
-static ident *create_ld_ident_linux_elf(ir_entity *irentity, entity_t *entity)
-{
- (void) entity;
- return get_entity_ident(irentity);
-}
-
-/**
- * Mangles an entity linker (ld) name for Mach-O usage.
- *
- * @param ent the entity to be mangled
- * @param declaration the declaration
- */
-static ident *create_ld_ident_macho(ir_entity *irentity, entity_t *entity)
-{
- (void) entity;
- ident *id = mangle(id_underscore, get_entity_ident(irentity));
- return id;
-}
-
-typedef ident* (*create_ld_ident_func)(ir_entity *irentity, entity_t *entity);
-create_ld_ident_func create_ld_ident = create_ld_ident_linux_elf;
+static ident* (*create_ld_ident)(entity_t*) = create_name_linux_elf;
/**
* Handle GNU attributes for entities
}
}
+static bool is_main(entity_t *entity)
+{
+ static symbol_t *sym_main = NULL;
+ if (sym_main == NULL) {
+ sym_main = symbol_table_insert("main");
+ }
+
+ if (entity->base.symbol != sym_main)
+ return false;
+ /* must be in outermost scope */
+ if (entity->base.parent_scope != ¤t_translation_unit->scope)
+ return false;
+
+ return true;
+}
+
/**
* Creates an entity representing a function.
*
return entity->function.entity;
}
+ 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 = typehash_insert(new_type);
+ if (type != new_type) {
+ obstack_free(type_obst, new_type);
+ }
+ entity->declaration.type = type;
+ }
+ }
+
symbol_t *symbol = entity->base.symbol;
ident *id = new_id_from_str(symbol->string);
dbg_info *const dbgi = get_dbg_info(&entity->base.source_position);
irentity = new_d_entity(global_type, id, ir_type_method, dbgi);
- set_entity_ld_ident(irentity, create_ld_ident(irentity, entity));
+ set_entity_ld_ident(irentity, create_ld_ident(entity));
handle_gnu_attributes_ent(irentity, entity);
variable->declaration.kind = (unsigned char) declaration_kind;
variable->variable.v.entity = irentity;
set_entity_variability(irentity, variability_uninitialized);
- set_entity_ld_ident(irentity, create_ld_ident(irentity, variable));
+ set_entity_ld_ident(irentity, create_ld_ident(variable));
if (parent_type == get_tls_type())
set_entity_allocation(irentity, allocation_automatic);
else if (declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE)
return create_initializer_const(value);
}
+/** 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 {
+ return false;
+ }
+
+ return is_type_integer(inner);
+}
+
static ir_initializer_t *create_ir_initializer_list(
const initializer_list_t *initializer, type_t *type)
{
break;
descend_into_subtype(&path);
}
+ } else if (sub_initializer->kind == INITIALIZER_STRING
+ || sub_initializer->kind == INITIALIZER_WIDE_STRING) {
+ /* we might have to descend into types until we're at a scalar
+ * type */
+ while (true) {
+ type_t *orig_top_type = path.top_type;
+ type_t *top_type = skip_typeref(orig_top_type);
+
+ if (is_string_type(top_type))
+ break;
+ descend_into_subtype(&path);
+ }
}
ir_initializer_t *sub_irinitializer
entity->declaration.kind = DECLARATION_KIND_GLOBAL_VARIABLE;
entity->variable.v.entity = irentity;
- set_entity_ld_ident(irentity, create_ld_ident(irentity, entity));
+ set_entity_ld_ident(irentity, id);
set_entity_variability(irentity, variability_uninitialized);
set_entity_visibility(irentity, visibility_local);
set_entity_allocation(irentity, allocation_static);
ir_node *in[1];
/* ยง5.1.2.2.3 main implicitly returns 0 */
- if (strcmp(entity->base.symbol->string, "main") == 0) {
+ if (is_main(entity)) {
in[0] = new_Const(mode, get_mode_null(mode));
} else {
in[0] = new_Unknown(mode);
}
}
-static void set_be_option(const char *option)
-{
- int res = firm_be_option(option);
- assert(res);
-}
-
void init_ast2firm(void)
{
obstack_init(&asm_obst);
init_atomic_modes();
- id_underscore = new_id_from_chars("_", 1);
- id_imp = new_id_from_chars("__imp_", 6);
-
/* OS option must be set to the backend */
switch (firm_opt.os_support) {
case OS_SUPPORT_MINGW:
- create_ld_ident = create_ld_ident_win32;
- set_be_option("ia32-gasmode=mingw");
+ create_ld_ident = create_name_win32;
break;
case OS_SUPPORT_LINUX:
- create_ld_ident = create_ld_ident_linux_elf;
- set_be_option("ia32-gasmode=elf");
+ create_ld_ident = create_name_linux_elf;
break;
case OS_SUPPORT_MACHO:
- create_ld_ident = create_ld_ident_macho;
- set_be_option("ia32-gasmode=macho");
- set_be_option("ia32-stackalign=4");
- set_be_option("pic");
+ create_ld_ident = create_name_macho;
break;
+ default:
+ panic("unexpected OS support mode");
}
/* create idents for all known runtime functions */
void translation_unit_to_firm(translation_unit_t *unit)
{
/* just to be sure */
- continue_label = NULL;
- break_label = NULL;
- current_switch_cond = NULL;
+ continue_label = NULL;
+ break_label = NULL;
+ current_switch_cond = NULL;
+ current_translation_unit = unit;
init_ir_types();
inner_functions = NEW_ARR_F(entity_t *, 0);
DEL_ARR_F(inner_functions);
inner_functions = NULL;
- current_ir_graph = NULL;
+ current_ir_graph = NULL;
+ current_translation_unit = NULL;
}