{
const declaration_t *declaration = get_irg_loc_description(irg, pos);
- warningf(&declaration->source_position,
- "variable '%#T' might be used uninitialized",
- declaration->type, declaration->symbol);
+ if (declaration != NULL) {
+ warningf(&declaration->source_position,
+ "variable '%#T' might be used uninitialized",
+ declaration->type, declaration->symbol);
+ }
return new_r_Unknown(irg, mode);
}
static unsigned get_type_size_const(type_t *type)
{
- type = skip_typeref(type);
-
switch(type->kind) {
case TYPE_ERROR:
panic("error type occurred");
return irtype;
}
+/**
+ * return type of a parameter (and take transparent union gnu extension into
+ * account)
+ */
+static type_t *get_parameter_type(type_t *type)
+{
+ type = skip_typeref(type);
+ if (type->base.modifiers & TYPE_MODIFIER_TRANSPARENT_UNION) {
+ declaration_t *decl = type->compound.declaration;
+ type = decl->scope.declarations->type;
+ }
+
+ return type;
+}
+
static ir_type *create_method_type(const function_type_t *function_type)
{
type_t *return_type = function_type->return_type;
function_parameter_t *parameter = function_type->parameters;
int n = 0;
for ( ; parameter != NULL; parameter = parameter->next) {
- ir_type *p_irtype = get_ir_type(parameter->type);
+ type_t *type = get_parameter_type(parameter->type);
+ ir_type *p_irtype = get_ir_type(type);
set_method_param_type(irtype, n, p_irtype);
++n;
}
set_method_variadicity(irtype, variadicity_variadic);
}
+ unsigned cc = get_method_calling_convention(irtype);
+ switch (function_type->calling_convention) {
+ case CC_DEFAULT: /* unspecified calling convention, equal to one of the other, typically cdecl */
+ case CC_CDECL:
+is_cdecl:
+ set_method_calling_convention(irtype, SET_CDECL(cc));
+ break;
+
+ case CC_STDCALL:
+ if (function_type->variadic || function_type->unspecified_parameters)
+ goto is_cdecl;
+
+ /* only non-variadic function can use stdcall, else use cdecl */
+ set_method_calling_convention(irtype, SET_STDCALL(cc));
+ break;
+
+ case CC_FASTCALL:
+ if (function_type->variadic || function_type->unspecified_parameters)
+ goto is_cdecl;
+ /* only non-variadic function can use fastcall, else use cdecl */
+ set_method_calling_convention(irtype, SET_FASTCALL(cc));
+ break;
+
+ case CC_THISCALL:
+ /* Hmm, leave default, not accepted by the parser yet. */
+ warningf(&function_type->base.source_position, "THISCALL calling convention not supported yet");
+ break;
+ }
return irtype;
}
static ir_type *create_bitfield_type(bitfield_type_t *const type)
{
type_t *base = skip_typeref(type->base_type);
- assert(base->kind == TYPE_ATOMIC);
+ assert(base->kind == TYPE_ATOMIC || base->kind == TYPE_ENUM);
ir_type *irbase = get_ir_type(base);
unsigned size = fold_constant(type->size);
id = mangle(id_underscore, get_entity_ident(ent));
}
- decl_modifiers_t decl_modifiers = declaration->decl_modifiers;
+ decl_modifiers_t decl_modifiers = declaration->modifiers;
if (decl_modifiers & DM_DLLIMPORT) {
/* add prefix for imported symbols */
id = mangle(id_imp, id);
declaration_t *declaration);
create_ld_ident_func create_ld_ident = create_ld_ident_linux_elf;
+/**
+ * Handle GNU attributes for entities
+ *
+ * @param ent the entity
+ * @param decl the routine declaration
+ */
+static void handle_gnu_attributes_ent(ir_entity *ent, declaration_t *decl)
+{
+ if (decl->modifiers & DM_PURE) {
+ /* TRUE if the declaration includes the GNU
+ __attribute__((pure)) specifier. */
+ set_entity_additional_property(ent, mtp_property_pure);
+ }
+ if (decl->modifiers & DM_USED) {
+ /* TRUE if the declaration includes the GNU
+ __attribute__((used)) specifier. */
+ set_entity_stickyness(ent, stickyness_sticky);
+ }
+}
+
/**
* Creates an entity representing a function.
*
dbg_info *const dbgi = get_dbg_info(&declaration->source_position);
entity = new_d_entity(global_type, id, ir_type_method, dbgi);
set_entity_ld_ident(entity, create_ld_ident(entity, declaration));
- if (declaration->storage_class == STORAGE_CLASS_STATIC &&
- declaration->init.statement == NULL) {
- /* this entity was declared, but never defined */
- set_entity_peculiarity(entity, peculiarity_description);
- }
- if (declaration->storage_class == STORAGE_CLASS_STATIC
- || declaration->is_inline) {
+
+ handle_gnu_attributes_ent(entity, declaration);
+
+ /* static inline => local
+ * extern inline => local
+ * inline without definition => local
+ * inline with definition => external_visible */
+ storage_class_tag_t const storage_class = declaration->storage_class;
+ bool const is_inline = declaration->is_inline;
+ bool const has_body = declaration->init.statement != NULL;
+ if (is_inline && storage_class == STORAGE_CLASS_NONE && has_body) {
+ set_entity_visibility(entity, visibility_external_visible);
+ } else if (storage_class == STORAGE_CLASS_STATIC ||
+ (is_inline && has_body)) {
+ if (!has_body) {
+ /* this entity was declared, but is defined nowhere */
+ set_entity_peculiarity(entity, peculiarity_description);
+ }
set_entity_visibility(entity, visibility_local);
- } else if (declaration->init.statement != NULL) {
+ } else if (has_body) {
set_entity_visibility(entity, visibility_external_visible);
} else {
set_entity_visibility(entity, visibility_external_allocated);
/**
* Transform a call expression.
- * Handles some special cases, like alloca() calls, which must be resolved BEFORE the inlines runs.
- * Inlining routines calling alloca() is dangerous, 176.gcc for instance might allocate 2GB instead of
- * 256 MB if alloca is not handled right...
+ * Handles some special cases, like alloca() calls, which must be resolved
+ * BEFORE the inlines runs. Inlining routines calling alloca() is dangerous,
+ * 176.gcc for instance might allocate 2GB instead of 256 MB if alloca is not
+ * handled right...
*/
static ir_node *call_expression_to_firm(const call_expression_t *call)
{
ir_node *value, type_t *type)
{
pointer_type_t *const pointer_type = &type->pointer;
- type_t *const points_to = pointer_type->points_to;
+ type_t *const points_to = skip_typeref(pointer_type->points_to);
unsigned elem_size = get_type_size_const(points_to);
/* gcc extension */
ir_initializer_t *irinitializer = create_initializer_compound(len);
const char *string = initializer->string.begin;
- ir_mode *mode = get_type_mode(ir_type_const_char);
+ ir_mode *mode = get_ir_mode(type->array.element_type);
for(size_t i = 0; i < len; ++i) {
char c = 0;
return;
}
+ type_t *type = skip_typeref(declaration->type);
+
if (initializer->kind == INITIALIZER_VALUE) {
initializer_value_t *initializer_value = &initializer->value;
dbg_info *dbgi
ir_entity *entity = declaration->v.entity;
- set_entity_variability(entity, variability_initialized);
+ if (type->base.qualifiers & TYPE_QUALIFIER_CONST) {
+ set_entity_variability(entity, variability_constant);
+ } else {
+ set_entity_variability(entity, variability_initialized);
+ }
set_atomic_ent_value(entity, value);
}
} else {
ir_entity *entity = declaration->v.entity;
ir_initializer_t *irinitializer
- = create_ir_initializer(initializer, declaration->type);
+ = create_ir_initializer(initializer, type);
- set_entity_variability(entity, variability_initialized);
+ if (type->base.qualifiers & TYPE_QUALIFIER_CONST) {
+ set_entity_variability(entity, variability_constant);
+ } else {
+ set_entity_variability(entity, variability_initialized);
+ }
set_entity_initializer(entity, irinitializer);
}
}
}
/* create output projs & connect them */
+ if (needs_memory) {
+ ir_node *projm = new_Proj(node, mode_M, out_size+1);
+ set_store(projm);
+ }
+
size_t i;
for (i = 0; i < out_size; ++i) {
const expression_t *out_expr = out_exprs[i];
set_value_for_expression_addr(out_expr, proj, addr);
}
- if (needs_memory) {
- ir_node *projm = new_Proj(node, mode_M, i);
- set_store(projm);
- }
}
static void ms_try_statement_to_firm(ms_try_statement_t *statement) {
for (; decl != end; decl = decl->next) {
if (decl->namespc != NAMESPACE_NORMAL)
continue;
- const type_t *type = skip_typeref(decl->type);
+ type_t *type = skip_typeref(decl->type);
+
if (!decl->address_taken && is_type_scalar(type))
++count;
const initializer_t *initializer = decl->init.initializer;
long pn = n;
ir_node *value = new_r_Proj(irg, start_block, args, param_mode, pn);
- ir_mode *mode = get_ir_mode(parameter->type);
+ ir_mode *mode = get_ir_mode(type);
value = create_conv(NULL, value, mode);
value = do_strict_conv(NULL, value);
}
}
+static void add_function_pointer(ir_type *segment, ir_entity *method,
+ const char *unique_template)
+{
+ ir_type *method_type = get_entity_type(method);
+ ident *id = id_unique(unique_template);
+ ir_type *ptr_type = new_type_pointer(id, method_type, mode_P_code);
+
+ ident *ide = id_unique(unique_template);
+ ir_entity *ptr = new_entity(segment, ide, ptr_type);
+ ir_graph *irg = get_const_code_irg();
+ ir_node *val = new_rd_SymConst_addr_ent(NULL, irg, mode_P_code,
+ method, NULL);
+
+ set_entity_compiler_generated(ptr, 1);
+ set_entity_variability(ptr, variability_constant);
+ set_atomic_ent_value(ptr, val);
+}
+
/**
* Create code for a function.
*/
if (declaration->init.statement == NULL)
return;
+ if (declaration->modifiers & DM_CONSTRUCTOR) {
+ ir_type *segment = get_segment_type(IR_SEGMENT_CONSTRUCTORS);
+ add_function_pointer(segment, function_entity, "constructor_ptr.%u");
+ }
+ if (declaration->modifiers & DM_DESTRUCTOR) {
+ ir_type *segment = get_segment_type(IR_SEGMENT_DESTRUCTORS);
+ add_function_pointer(segment, function_entity, "destructor_ptr.%u");
+ }
+
current_function_decl = declaration;
current_function_name = NULL;
current_funcsig = NULL;
/* set inline flags */
if (declaration->is_inline)
set_irg_inline_property(irg, irg_inline_recomended);
- handle_decl_modifier_irg(irg, declaration->decl_modifiers);
+ handle_decl_modifier_irg(irg, declaration->modifiers);
next_value_number_function = 0;
initialize_function_parameters(declaration);
obstack_free(&asm_obst, NULL);
}
+static void global_asm_to_firm(statement_t *s)
+{
+ for (; s != NULL; s = s->base.next) {
+ 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);
+ add_irp_asm(id);
+ }
+}
+
void translation_unit_to_firm(translation_unit_t *unit)
{
/* just to be sure */
init_ir_types();
scope_to_firm(&unit->scope);
+ global_asm_to_firm(unit->global_asm);
}