- dbg_info *const dbgi = get_dbg_info(&declaration->source_position);
- ir_entity *const entity = new_d_entity(global_type, id, ir_type_method, dbgi);
- set_entity_ld_ident(entity, id);
- if(declaration->storage_class == STORAGE_CLASS_STATIC
- || declaration->is_inline) {
- set_entity_visibility(entity, visibility_local);
- } else if(declaration->init.statement != NULL) {
- set_entity_visibility(entity, visibility_external_visible);
- } else {
- set_entity_visibility(entity, visibility_external_allocated);
-
- /* We should check for file scope here, but as long as we compile C only
- this is not needed. */
- int n_params = get_method_n_params(ir_type_method);
- int n_res = get_method_n_ress(ir_type_method);
- int i;
-
- if (n_params == 0 && n_res == 0 && id == predef_idents[rts_abort]) {
- /* found abort(), store for later */
- //abort_ent = ent;
- //abort_tp = ftype;
- } else {
- if (! firm_opt.freestanding) {
- /* check for a known runtime function */
- for (i = 0; i < rts_max; ++i) {
- /* ignore those rts functions not necessary needed for current mode */
- if ((c_mode & rts_data[i].flags) == 0)
- continue;
- if (n_params == rts_data[i].n_params && n_res == rts_data[i].n_res &&
- id == predef_idents[rts_data[i].id])
- rts_entities[rts_data[i].id] = entity;
- }
+/**
+ * Handle GNU attributes for entities
+ *
+ * @param ent the entity
+ * @param decl the routine declaration
+ */
+static void handle_decl_modifiers(ir_entity *irentity, entity_t *entity)
+{
+ assert(is_declaration(entity));
+ decl_modifiers_t modifiers = entity->declaration.modifiers;
+ if (modifiers & DM_PURE) {
+ /* TRUE if the declaration includes the GNU
+ __attribute__((pure)) specifier. */
+ set_entity_additional_property(irentity, mtp_property_pure);
+ }
+ if (modifiers & DM_CONST) {
+ set_entity_additional_property(irentity, mtp_property_const);
+ have_const_functions = true;
+ }
+ if (modifiers & DM_USED) {
+ /* TRUE if the declaration includes the GNU
+ __attribute__((used)) specifier. */
+ set_entity_stickyness(irentity, stickyness_sticky);
+ }
+}
+
+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.
+ *
+ * @param declaration the function declaration
+ * @param owner_type the owner type of this function, NULL
+ * for global functions
+ */
+static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type)
+{
+ assert(entity->kind == ENTITY_FUNCTION);
+ if (entity->function.irentity != NULL) {
+ return entity->function.irentity;
+ }
+
+ 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);
+
+
+ /* already an entity defined? */
+ ir_entity *irentity = entitymap_get(&entitymap, symbol);
+ bool const has_body = entity->function.statement != NULL;
+ if (irentity != NULL) {
+ if (get_entity_visibility(irentity) == visibility_external_allocated
+ && has_body) {
+ set_entity_visibility(irentity, visibility_external_visible);
+ }
+ goto entity_created;
+ }
+
+ ir_type *ir_type_method;
+ if (entity->function.need_closure)
+ ir_type_method = create_method_type(&entity->declaration.type->function, true);
+ else
+ ir_type_method = get_ir_type(entity->declaration.type);
+
+ bool nested_function = false;
+ if (owner_type == NULL)
+ owner_type = get_glob_type();
+ else
+ nested_function = true;
+
+ dbg_info *const dbgi = get_dbg_info(&entity->base.source_position);
+ irentity = new_d_entity(owner_type, id, ir_type_method, dbgi);
+
+ ident *ld_id;
+ if (nested_function)
+ ld_id = id_unique("inner.%u");
+ else
+ ld_id = create_ld_ident(entity);
+ set_entity_ld_ident(irentity, ld_id);
+
+ 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, 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(irentity, peculiarity_description);