static void fix_address_pic_elf(ir_node *const node, void *const data) { (void)data; foreach_irn_in(node, i, pred) { if (!is_Address(pred)) continue; ir_entity *const entity = get_Address_entity(pred); if (is_tls_entity(entity)) continue; ir_graph *const irg = get_irn_irg(node); bool const ext_visible = is_externally_visible(entity); ir_node * res; if (i == n_Call_ptr && is_Call(node)) { /* We can compilation-unit local functions directly, everything else * goes through the PLT */ x86_immediate_kind_t const reloc = ext_visible ? X86_IMM_PLT : X86_IMM_PCREL; res = be_new_Relocation(irg, reloc, entity, mode_P); } else if (!ext_visible) { res = be_new_Relocation(irg, X86_IMM_PCREL, entity, mode_P); } else { res = create_gotpcrel_load(irg, entity); } set_irn_n(node, i, res); } }
static bool check_external_linkage(const ir_entity *entity, ir_linkage linkage, const char *linkage_name) { bool fine = true; if ((get_entity_linkage(entity) & linkage) == 0) return true; if (!is_externally_visible(entity)) { report_error("entity %+F has IR_LINKAGE_%s but is not externally visible", entity, linkage_name); fine = false; } if (!entity_has_definition(entity)) { report_error("entity %+F has IR_LINKAGE_%s but is just a declaration", entity, linkage_name); fine = false; } return fine; }
int check_entity(const ir_entity *entity) { bool fine = true; ir_linkage linkage = get_entity_linkage(entity); if (linkage & IR_LINKAGE_NO_CODEGEN) { if (!is_method_entity(entity)) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not a function", entity); fine = false; } else if (get_entity_irg(entity) == NULL) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but has no ir-graph anyway", entity); fine = false; } if (!is_externally_visible(entity)) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not externally visible", entity); fine = false; } } check_external_linkage(entity, IR_LINKAGE_WEAK, "WEAK"); check_external_linkage(entity, IR_LINKAGE_GARBAGE_COLLECT, "GARBAGE_COLLECT"); check_external_linkage(entity, IR_LINKAGE_MERGE, "MERGE"); ir_type const *const type = get_entity_type(entity); ir_type const *const owner = get_entity_owner(entity); switch (get_entity_kind(entity)) { case IR_ENTITY_ALIAS: if (!is_segment_type(owner)) { report_error("alias entity %+F has non-segment owner %+F", entity, owner); fine = false; } break; case IR_ENTITY_NORMAL: { ir_initializer_t const *const init = get_entity_initializer(entity); if (init) fine &= check_initializer(init, type, entity); if (!is_data_type(type)) { report_error("normal entity %+F has non-data type %+F", entity, type); fine = false; } break; } case IR_ENTITY_COMPOUND_MEMBER: if (!is_compound_type(owner)) { report_error("compound member entity %+F has non-compound owner %+F", entity, owner); fine = false; } break; case IR_ENTITY_LABEL: if (type != get_code_type()) { report_error("label entity %+F has non-code type %+F", entity, type); fine = false; } break; case IR_ENTITY_METHOD: if (!is_Method_type(type)) { report_error("method entity %+F has non-method type %+F", entity, type); fine = false; } ir_graph *irg = get_entity_irg(entity); if (irg != NULL) { ir_entity *irg_entity = get_irg_entity(irg); if (irg_entity != entity) { report_error("entity(%+F)->irg->entity(%+F) relation invalid", entity, irg_entity); fine = false; } } break; case IR_ENTITY_PARAMETER: if (!is_frame_type(owner)) { report_error("parameter entity %+F has non-frame owner %+F", entity, owner); fine = false; } if (!is_data_type(type)) { report_error("parameter entity %+F has non-data type %+F", entity, type); fine = false; } break; case IR_ENTITY_UNKNOWN: break; case IR_ENTITY_SPILLSLOT: if (is_frame_type(owner)) { report_error("spillslot %+F must be on frame type", entity); fine = false; } break; } if (is_frame_type(owner) && entity_has_definition(entity)) { report_error("entity %+F on frame %+F has initialized", entity, owner); fine = false; } return fine; }