void analyze_irg_args_weight(ir_graph *irg) { ir_entity *entity = get_irg_entity(irg); if (entity == NULL) return; assert(is_method_entity(entity)); if (entity->attr.mtd_attr.param_weight != NULL) return; ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED); inc_irg_visited(irg); analyze_method_params_weight(entity); ir_free_resources(irg, IR_RESOURCE_IRN_VISITED); }
void init_rta_callbacks() { // collect rtti entities cpmap_init(&rtti2class, hash_ptr, ptr_equals); class_walk_super2sub(NULL, walk_classes_and_collect_rtti, NULL); // collect clinit entities cpmap_init(&class2init, hash_ptr, ptr_equals); ir_type *glob = get_glob_type(); for (size_t i=0; i<get_class_n_members(glob); i++) { ir_entity *entity = get_class_member(glob, i); if (is_method_entity(entity) && strcmp(get_entity_name(entity), "<clinit>.()V") == 0) { char *classname = read_classname_from_clinit_ldname(get_entity_ld_name(entity)); ir_type *klass = class_registry_get(classname); assert(klass); //printf(" %s -> %s (%s)\n", get_compound_name(klass), get_entity_name(entity), get_entity_ld_name(entity)); cpmap_set(&class2init, klass, entity); free(classname); } } }
int tr_verify(void) { bool fine = true; type_walk(check_tore, NULL, &fine); for (ir_segment_t s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) { ir_type const *const segment = get_segment_type(s); for (size_t e = 0; e < get_compound_n_members(segment); ++e) { ir_entity const *const entity = get_compound_member(segment, e); ident *const ld_ident = get_entity_ld_ident(entity); if (ld_ident == NULL && get_entity_visibility(entity) != ir_visibility_private) { report_error("public segment member %+F has no name", entity); fine = false; continue; } if (segment->flags & tf_info) fine &= verify_info_member(segment, entity); } } ir_type const *const thread_locals = get_segment_type(IR_SEGMENT_THREAD_LOCAL); for (size_t i = 0, n = get_compound_n_members(thread_locals); i < n; ++i) { const ir_entity *entity = get_compound_member(thread_locals, i); /* this is odd and should not be allowed I think */ if (is_method_entity(entity)) { report_error("method %+F in thread local segment", entity); fine = false; } if (get_entity_linkage(entity) & IR_LINKAGE_CONSTANT) { report_error("entity %+F in thread local segment is constant", entity); fine = false; } } return fine; }
/** * Creates a deep copy of an entity. */ static ir_entity *deep_entity_copy(ir_entity *old) { ir_entity *newe = XMALLOC(ir_entity); *newe = *old; if (old->initializer != NULL) { /* FIXME: the initializers are NOT copied */ } else if (is_method_entity(old)) { /* do NOT copy them, reanalyze. This might be the best solution */ newe->attr.mtd_attr.param_access = NULL; newe->attr.mtd_attr.param_weight = NULL; } newe->overwrites = NULL; newe->overwrittenby = NULL; #ifdef DEBUG_libfirm newe->nr = get_irp_new_node_nr(); #endif hook_new_entity(newe); return newe; }
void jit_compile_execute_main(void) { unsigned const alignment = 16; unsigned const align_mask = ~(alignment-1); optimize_lower_ir_prog(); /* This is somewhat ad-hoc testing code for the jit, it is limited and * will not handle all firm programs. */ const struct { char const *name; void const *func; } external_functions[] = { { "atoi", (void const*)(intptr_t)atoi }, { "free", (void const*)(intptr_t)free }, { "getchar", (void const*)(intptr_t)getchar }, { "malloc", (void const*)(intptr_t)malloc }, { "printf", (void const*)(intptr_t)printf }, { "puts", (void const*)(intptr_t)puts }, { "rand", (void const*)(intptr_t)rand }, { "realloc", (void const*)(intptr_t)realloc }, }; ir_jit_segment_t *const segment = be_new_jit_segment(); ir_entity ** funcents = NEW_ARR_F(ir_entity*, 0); ir_jit_function_t ** functions = NEW_ARR_F(ir_jit_function_t*, 0); ir_entity *main_entity = NULL; size_t code_size = 0; ir_type *const global_type = get_glob_type(); for (size_t i = 0, n = get_compound_n_members(global_type); i < n; ++i) { ir_entity *const entity = get_compound_member(global_type, i); char const *const ld_name = get_entity_ld_name(entity); if (is_method_entity(entity) && !(get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN)) { ir_graph *const irg = get_entity_irg(entity); if (irg != NULL) { ir_jit_function_t *const func = be_jit_compile(segment, irg); if (func == NULL) panic("Could not jit compile '%s'", ld_name); unsigned const misalign = alignment - (code_size%alignment); code_size += (misalign != alignment ? misalign : 0); ARR_APP1(ir_jit_function_t*, functions, func); ARR_APP1(ir_entity*, funcents, entity); code_size += be_get_function_size(func); if (streq(ld_name, "main") || streq(ld_name, "_main")) main_entity = entity; continue; } } /* See if its one of our well-known functions */ for (unsigned f = 0; f < ARRAY_SIZE(external_functions); ++f) { char const *const name = external_functions[f].name; void const *const func = external_functions[f].func; if (streq(ld_name, name) || (ld_name[0] == '_' && streq(&ld_name[1], name))) { be_jit_set_entity_addr(entity, func); break; } } } if (main_entity == NULL) panic("Could not find main() function"); /* Allocate executable memory */ char *const memory = mmap(0, code_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (memory == NULL) panic("Could not mmap memory"); /* Determine final function addresses */ size_t const n_functions = ARR_LEN(functions); assert(ARR_LEN(funcents) == n_functions); unsigned offset = 0; for (size_t i = 0; i < n_functions; ++i) { offset = (offset + alignment - 1) & align_mask; char *const dest = memory + offset; ir_entity *const entity = funcents[i]; be_jit_set_entity_addr(entity, dest); offset += be_get_function_size(functions[i]); } assert(offset == code_size); /* Emit and resolve */ for (size_t i = 0; i < n_functions; ++i) { ir_entity *const entity = funcents[i]; char *const dest = memory + ((char const*)be_jit_get_entity_addr(entity) - memory); be_emit_function(dest, functions[i]); } be_destroy_jit_segment(segment); if (mprotect(memory, code_size, PROT_EXEC) != 0) panic("Couldn't make memory executable"); typedef int (*mainfunc)(int argc, char **argv); mainfunc main_ptr = (mainfunc)(intptr_t)be_jit_get_entity_addr(main_entity); int res = main_ptr(0, NULL); fprintf(stderr, "Exit code: %d\n", res); munmap(memory, code_size); }
/* * Optimize the frame type of an irg by removing * never touched entities. */ void opt_frame_irg(ir_graph *irg) { ir_type *frame_tp = get_irg_frame_type(irg); ir_entity *ent, *list; ir_node *frame, *sel; size_t i, n = get_class_n_members(frame_tp); int o; if (n <= 0) return; assure_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS); irp_reserve_resources(irp, IRP_RESOURCE_ENTITY_LINK); /* clear all entity links */ for (i = n; i > 0;) { ent = get_class_member(frame_tp, --i); set_entity_link(ent, NULL); } /* look for uses */ frame = get_irg_frame(irg); /* mark all used entities */ for (o = get_irn_n_outs(frame) - 1; o >= 0; --o) { sel = get_irn_out(frame, o); if (is_Sel(sel)) { ent = get_Sel_entity(sel); /* only entities on the frame */ if (get_entity_owner(ent) == frame_tp) set_entity_link(ent, ent); } } /* link unused ones */ list = NULL; for (i = n; i > 0;) { ent = get_class_member(frame_tp, --i); /* beware of inner functions: those are NOT unused */ if (get_entity_link(ent) == NULL && !is_method_entity(ent)) { set_entity_link(ent, list); list = ent; } } if (list != NULL) { /* delete list members */ for (ent = list; ent; ent = list) { list = (ir_entity*)get_entity_link(ent); free_entity(ent); } /* we changed the frame type, its layout should be redefined */ set_type_state(frame_tp, layout_undefined); } irp_free_resources(irp, IRP_RESOURCE_ENTITY_LINK); /* we changed the type, this affects none of the currently known graph * properties, but I don't use ALL because I don't know if someone adds * type-based properties at some point */ confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_CONTROL_FLOW | IR_GRAPH_PROPERTY_NO_BADS | IR_GRAPH_PROPERTY_NO_TUPLES | IR_GRAPH_PROPERTY_CONSISTENT_OUT_EDGES | IR_GRAPH_PROPERTY_CONSISTENT_OUTS | IR_GRAPH_PROPERTY_CONSISTENT_ENTITY_USAGE | IR_GRAPH_PROPERTY_MANY_RETURNS); }
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; }
int tr_verify(void) { bool fine = true; ir_type *constructors; ir_type *destructors; ir_type *thread_locals; type_walk(check_tore, NULL, &fine); for (ir_segment_t s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) { const ir_type *type = get_segment_type(s); for (size_t e = 0; e < get_compound_n_members(type); ++e) { ir_entity *entity = get_compound_member(type, e); if (get_entity_ld_ident(entity) == NULL && get_entity_visibility(entity) != ir_visibility_private) { report_error("public segment member %+F has no name", entity); fine = false; } } } constructors = get_segment_type(IR_SEGMENT_CONSTRUCTORS); for (size_t i = 0, n = get_compound_n_members(constructors); i < n; ++i) { const ir_entity *entity = get_compound_member(constructors, i); if ((get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER) == 0) { report_error("entity %+F in constructors without LINKAGE_HIDDEN_USER", entity); fine = false; } /* Mach-O doesn't like labels in this section */ if (get_entity_ld_name(entity)[0] != '\0') { report_error("entity %+F in constructors must not have an ld_name", entity); fine = false; } } destructors = get_segment_type(IR_SEGMENT_DESTRUCTORS); for (size_t i = 0, n = get_compound_n_members(destructors); i < n; ++i) { const ir_entity *entity = get_compound_member(destructors, i); if ((get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER) == 0) { report_error("entity %+F in destructors without LINKAGE_HIDDEN_USER", entity); fine = false; } /* Mach-O doesn't like labels in this section */ if (get_entity_ld_name(entity)[0] != '\0') { report_error("entity %+F in destructors must not have an ld_name", entity); fine = false; } } thread_locals = get_segment_type(IR_SEGMENT_THREAD_LOCAL); for (size_t i = 0, n = get_compound_n_members(thread_locals); i < n; ++i) { const ir_entity *entity = get_compound_member(thread_locals, i); /* this is odd and should not be allowed I think */ if (is_method_entity(entity)) { report_error("method %+F in thread local segment"); fine = false; } if (get_entity_linkage(entity) & IR_LINKAGE_CONSTANT) { report_error("entity %+F in thread local segment is constant"); fine = false; } } return fine; }
int check_entity(const ir_entity *entity) { bool fine = true; ir_type *tp = get_entity_type(entity); ir_linkage linkage = get_entity_linkage(entity); fine &= constants_on_wrong_irg(entity); if (is_method_entity(entity)) { 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; } } if (get_entity_peculiarity(entity) == peculiarity_existent) { ir_entity *impl = get_SymConst_entity(get_atomic_ent_value(entity)); if (impl == NULL) { report_error("inherited method entity %+F must have constant pointing to existent entity.", entity); fine = false; } } } 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 (get_entity_visibility(entity) != ir_visibility_external) { 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"); if (is_atomic_entity(entity) && entity->initializer != NULL) { ir_mode *mode = NULL; ir_initializer_t *initializer = entity->initializer; switch (initializer->kind) { case IR_INITIALIZER_CONST: mode = get_irn_mode(get_initializer_const_value(initializer)); break; case IR_INITIALIZER_TARVAL: mode = get_tarval_mode(get_initializer_tarval_value(initializer)); break; case IR_INITIALIZER_NULL: case IR_INITIALIZER_COMPOUND: break; } if (mode != NULL && mode != get_type_mode(tp)) { report_error("initializer of entity %+F has wrong mode.", entity); fine = false; } } return fine; }