From 634d25a4bbc3a8b00a3307011a9607e6c5de7570 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Fri, 4 May 2012 14:30:03 +0200 Subject: [PATCH] Introduce IR_LINKAGE_NO_CODEGEN This is used to implement C99 "inline"/GNU89 "extern inline" ie. an entity which is externally defined but where we know an inlineable definition anyway. --- include/libfirm/typerep.h | 13 +++++++++++-- ir/be/begnuas.c | 10 +++------- ir/be/bemain.c | 18 ++++++++++++------ ir/opt/garbage_collect.c | 3 ++- ir/tr/entity.c | 3 ++- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/include/libfirm/typerep.h b/include/libfirm/typerep.h index 45db4bf32..817435102 100644 --- a/include/libfirm/typerep.h +++ b/include/libfirm/typerep.h @@ -154,7 +154,15 @@ typedef enum ir_linkage { * read/write behaviour to global variables or changing calling conventions * from cdecl to fastcall. */ - IR_LINKAGE_HIDDEN_USER = 1 << 4 + IR_LINKAGE_HIDDEN_USER = 1 << 4, + /** + * Do not generate code even if the entity has a graph attached. The graph + * is only used for inlining. Otherwise the entity is regarded as a + * declaration of an externally defined entity. + * This linkage flag can be used to implement C99 "inline" or GNU89 + * "extern inline". + */ + IR_LINKAGE_NO_CODEGEN = 1 << 5, } ir_linkage; ENUM_BITSET(ir_linkage) @@ -180,7 +188,8 @@ FIRM_API int entity_is_externally_visible(const ir_entity *entity); /** * Returns 1 if the entity has a definition (initializer) in the current - * compilation unit + * compilation unit. Note that this function returns false if + * IR_LINKAGE_NO_CODEGEN is set even if a graph is present. */ FIRM_API int entity_has_definition(const ir_entity *entity); diff --git a/ir/be/begnuas.c b/ir/be/begnuas.c index 0904d6475..9d33f2b45 100644 --- a/ir/be/begnuas.c +++ b/ir/be/begnuas.c @@ -1587,14 +1587,10 @@ static void emit_global(be_gas_decl_env_t *env, const ir_entity *entity) if (type == get_code_type()) return; - /* we already emitted all methods. Except for the trampolines which - * the assembler/linker generates */ + /* we already emitted all methods with graphs in other functions like + * be_gas_emit_function_prolog(). All others don't need to be emitted. + */ if (is_Method_type(type) && section != GAS_SECTION_PIC_TRAMPOLINES) { - /* functions with graph are already emitted with - * be_gas_emit_function_prolog */ - if (get_entity_irg(entity) == NULL) { - emit_visibility(entity); - } return; } diff --git a/ir/be/bemain.c b/ir/be/bemain.c index b4e9dfcdd..07c0a0fd8 100644 --- a/ir/be/bemain.c +++ b/ir/be/bemain.c @@ -520,7 +520,9 @@ static void be_main_loop(FILE *file_handle, const char *cup_name) { static const char suffix[] = ".prof"; - size_t i, num_birgs; + size_t i; + size_t num_irgs; + size_t num_birgs; be_main_env_t env; char prof_filename[256]; be_irg_t *birgs; @@ -543,15 +545,19 @@ static void be_main_loop(FILE *file_handle, const char *cup_name) arch_env = env.arch_env; /* we might need 1 birg more for instrumentation constructor */ - num_birgs = get_irp_n_irgs(); - birgs = ALLOCAN(be_irg_t, num_birgs + 1); + num_irgs = get_irp_n_irgs(); + birgs = ALLOCAN(be_irg_t, num_irgs + 1); be_info_init(); /* First: initialize all birgs */ - for (i = 0; i < num_birgs; ++i) { - ir_graph *irg = get_irp_irg(i); - initialize_birg(&birgs[i], irg, &env); + num_birgs = 0; + for (i = 0; i < num_irgs; ++i) { + ir_graph *irg = get_irp_irg(i); + ir_entity *entity = get_irg_entity(irg); + if (get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN) + continue; + initialize_birg(&birgs[num_birgs++], irg, &env); } arch_env_handle_intrinsics(arch_env); diff --git a/ir/opt/garbage_collect.c b/ir/opt/garbage_collect.c index 7fc81ec8b..08cc9a7ae 100644 --- a/ir/opt/garbage_collect.c +++ b/ir/opt/garbage_collect.c @@ -123,7 +123,8 @@ static void visit_segment(ir_type *segment) for (i = 0; i < n_entities; ++i) { ir_entity *entity = get_compound_member(segment, i); if (get_entity_visibility(entity) != ir_visibility_external - && !(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER)) + && !(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER) + && !(get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN)) continue; visit_entity(entity); diff --git a/ir/tr/entity.c b/ir/tr/entity.c index e8e0de788..943ad6b2b 100644 --- a/ir/tr/entity.c +++ b/ir/tr/entity.c @@ -1063,7 +1063,8 @@ int entity_is_externally_visible(const ir_entity *entity) int entity_has_definition(const ir_entity *entity) { if (is_method_entity(entity)) { - return get_entity_irg(entity) != NULL; + return get_entity_irg(entity) != NULL + && (get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN) == 0; } else { return entity->initializer != NULL || entity_has_compound_ent_values(entity); -- 2.20.1