/** * Calculate a weight for each argument of an entity. * * @param ent The entity of the ir_graph. */ static void analyze_method_params_weight(ir_entity *ent) { /* allocate a new array. currently used as 'analysed' flag */ ir_type *mtp = get_entity_type(ent); size_t nparams = get_method_n_params(mtp); ent->attr.mtd_attr.param_weight = NEW_ARR_F(unsigned, nparams); /* If the method haven't parameters we have nothing to do. */ if (nparams <= 0) return; /* First we initialize the parameter weights with 0. */ for (size_t i = nparams; i-- > 0; ) ent->attr.mtd_attr.param_weight[i] = null_weight; ir_graph *irg = get_entity_irg(ent); if (irg == NULL) { /* no graph, no better info */ return; } /* Call algorithm that computes the out edges */ assure_irg_outs(irg); ir_node *irg_args = get_irg_args(irg); for (int i = get_irn_n_outs(irg_args); i-- > 0; ) { ir_node *arg = get_irn_out(irg_args, i); long proj_nr = get_Proj_proj(arg); ent->attr.mtd_attr.param_weight[proj_nr] += calc_method_param_weight(arg); } }
/** * Check if a argument of the ir graph with mode * reference is read, write or both. * * @param irg The ir graph to analyze. */ static void analyze_ent_args(ir_entity *ent) { ir_type *mtp = get_entity_type(ent); size_t nparams = get_method_n_params(mtp); ent->attr.mtd_attr.param_access = NEW_ARR_F(ptr_access_kind, nparams); /* If the method haven't parameters we have * nothing to do. */ if (nparams <= 0) return; /* we have not yet analyzed the graph, set ALL access for pointer args */ for (size_t i = nparams; i-- > 0; ) { ir_type *type = get_method_param_type(mtp, i); ent->attr.mtd_attr.param_access[i] = is_Pointer_type(type) ? ptr_access_all : ptr_access_none; } ir_graph *irg = get_entity_irg(ent); if (irg == NULL) { /* no graph, no better info */ return; } assure_irg_outs(irg); ir_node *irg_args = get_irg_args(irg); /* A array to save the information for each argument with mode reference.*/ ptr_access_kind *rw_info; NEW_ARR_A(ptr_access_kind, rw_info, nparams); /* We initialize the element with none state. */ for (size_t i = nparams; i-- > 0; ) rw_info[i] = ptr_access_none; /* search for arguments with mode reference to analyze them.*/ for (int i = get_irn_n_outs(irg_args); i-- > 0; ) { ir_node *arg = get_irn_out(irg_args, i); ir_mode *arg_mode = get_irn_mode(arg); long proj_nr = get_Proj_proj(arg); if (mode_is_reference(arg_mode)) rw_info[proj_nr] |= analyze_arg(arg, rw_info[proj_nr]); } /* copy the temporary info */ memcpy(ent->attr.mtd_attr.param_access, rw_info, nparams * sizeof(ent->attr.mtd_attr.param_access[0])); }
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); }
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 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; }