ir_entity *create_compilerlib_entity(ident *id, ir_type *mt) { ir_entity *entity = pmap_get(ir_entity, irp->compilerlib_entities, id); if (entity != NULL) return entity; /* let frontend mangle the name */ ident *ld_name = compilerlib_mangler(id, mt); /* search for an existing entity */ ir_type *glob = get_glob_type(); for (size_t i = 0, n_members = get_compound_n_members(glob); i < n_members; ++i) { ir_entity *member = get_compound_member(glob, i); if (get_entity_ld_ident(member) == ld_name) { entity = member; goto found; } } entity = new_entity(glob, id, mt); set_entity_ld_ident(entity, ld_name); set_entity_visibility(entity, ir_visibility_external); found: pmap_insert(irp->compilerlib_entities, id, entity); return entity; }
void dmemory_init(void) { ir_type *type_reference = new_type_primitive(mode_P); ir_type *type_int = new_type_primitive(mode_Is); ir_type *type_size_t = new_type_primitive(mode_Iu); ir_type *calloc_type = new_type_method(2, 1); set_method_param_type(calloc_type, 0, type_size_t); set_method_param_type(calloc_type, 1, type_size_t); set_method_res_type(calloc_type, 0, type_reference); set_method_additional_properties(calloc_type, mtp_property_malloc); ir_type *glob = get_glob_type(); ident *calloc_id = new_id_from_str("calloc"); calloc_entity = new_entity(glob, calloc_id, calloc_type); set_entity_visibility(calloc_entity, ir_visibility_external); ir_type *arraylength_type = new_type_method(1, 1); set_method_param_type(arraylength_type, 0, type_reference); set_method_res_type(arraylength_type, 0, type_int); set_method_additional_properties(arraylength_type, mtp_property_pure); default_arraylength_mode = mode_Is; dmemory_model.alloc_object = dmemory_default_alloc_object; dmemory_model.alloc_array = dmemory_default_alloc_array; dmemory_model.get_arraylength = dmemory_default_get_arraylength; }
static ir_entity *emit_field_table(ir_type *classtype) { class_t *linked_class = (class_t*) oo_get_type_link(classtype); assert(linked_class); uint16_t n_fields = linked_class->n_fields; if (n_fields == 0) return NULL; ir_type *type_array = new_type_array(type_field_desc, n_fields); unsigned size = n_fields * get_type_size(type_field_desc); set_type_size(type_array, size); ir_initializer_t *init = create_initializer_compound(n_fields); for (uint16_t i = 0; i < n_fields; i++) { ir_entity *field = linked_class->fields[i]->link; ir_initializer_t *desc = get_field_desc(classtype, field); set_initializer_compound_value(init, i, desc); } ident *id = id_unique("_FT"); ir_entity *ft_ent = new_entity(get_glob_type(), id, type_array); set_entity_initializer(ft_ent, init); set_entity_ld_ident(ft_ent, id); return ft_ent; }
static ir_entity *emit_interface_table(ir_type *classtype) { class_t *linked_class = (class_t*) oo_get_type_link(classtype); assert(linked_class); uint16_t n_interfaces = linked_class->n_interfaces; if (n_interfaces == 0) return NULL; ir_type *type_array = new_type_array(type_reference, n_interfaces); unsigned size = n_interfaces * get_type_size(type_reference); set_type_size(type_array, size); ir_initializer_t *init = create_initializer_compound(n_interfaces); for (uint16_t i = 0; i < n_interfaces; i++) { uint16_t iface_ref = linked_class->interfaces[i]; constant_classref_t *clsref = (constant_classref_t*) linked_class->constants[iface_ref]; constant_utf8_string_t *clsname = (constant_utf8_string_t*) linked_class->constants[clsref->name_index]; ir_type *type = class_registry_get(clsname->bytes); assert(type); ir_entity *rtti_entity = gcji_get_rtti_entity(type); assert(rtti_entity != NULL); set_compound_init_entref(init, i, rtti_entity); } ident *id = id_unique("_IF"); ir_entity *if_ent = new_entity(get_glob_type(), id, type_array); set_entity_initializer(if_ent, init); set_entity_ld_ident(if_ent, id); return if_ent; }
void gcji_create_vtable_entity(ir_type *type) { const char *name = get_compound_name(type); ident *vtable_ident = mangle_vtable_name(name); ir_type *unknown = get_unknown_type(); ir_type *glob = get_glob_type(); ir_entity *vtable = new_entity(glob, vtable_ident, unknown); oo_set_class_vtable_entity(type, vtable); }
ir_entity *new_d_label_entity(ir_label_t label, dbg_info *dbgi) { ident *name = id_unique("label_%u"); ir_type *global_type = get_glob_type(); ir_entity *res = intern_new_entity(global_type, IR_ENTITY_LABEL, name, get_code_type(), dbgi); res->attr.code_attr.label = label; hook_new_entity(res); return res; }
void eh_init(void) { obstack_init(&lpads); ir_type *type_reference = new_type_primitive(mode_P); exception_object_entity = new_entity(get_tls_type(), new_id_from_str("__oo_rt_exception_object__"), type_reference); set_entity_initializer(exception_object_entity, get_initializer_null()); ir_type *throw_type = new_type_method(1, 0); set_method_param_type(throw_type, 0, type_reference); throw_entity = new_entity(get_glob_type(), new_id_from_str("firm_personality"), throw_type); set_entity_visibility(throw_entity, ir_visibility_external); top = NULL; }
ir_entity *create_compilerlib_entity(ident *id, ir_type *mt) { ident *ld_name = compilerlib_mangler(id, mt); /* Look for existing entity. */ ir_entity *entity = ir_get_global(ld_name); if (entity != NULL) return entity; /* Create a new one */ ir_type *glob = get_glob_type(); entity = new_entity(glob, ld_name, mt); return entity; }
static ir_entity *make_divmod(char const *const name, ir_type *const even, ir_type *const odd) { ir_type *const mtp = new_type_method(4, 4); set_method_param_type(mtp, 0, even); set_method_param_type(mtp, 1, odd); set_method_param_type(mtp, 2, even); set_method_param_type(mtp, 3, odd); set_method_res_type(mtp, 0, even); set_method_res_type(mtp, 1, odd); set_method_res_type(mtp, 2, even); set_method_res_type(mtp, 3, odd); ident *const id = new_id_from_str(name); ir_type *const glob = get_glob_type(); ir_entity *const ent = new_entity(glob, id, mtp); set_entity_ld_ident(ent, id); set_entity_visibility(ent, ir_visibility_external); return ent; }
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); } } }
static ir_entity *create_ent(ir_entity **const dst, int value, const char *name) { if (!*dst) { ir_mode *const mode = mode_Hu; ir_type *const type = new_type_primitive(mode); set_type_alignment_bytes(type, 4); ir_type *const glob = get_glob_type(); ident *const id = new_id_from_str(name); ir_entity *const ent = new_entity(glob, id, type); set_entity_ld_ident(ent, id); set_entity_visibility(ent, ir_visibility_local); add_entity_linkage(ent, IR_LINKAGE_CONSTANT); ir_graph *const cnst_irg = get_const_code_irg(); ir_node *const cnst = new_r_Const_long(cnst_irg, mode, value); set_atomic_ent_value(ent, cnst); *dst = ent; } return *dst; }
static ir_entity *do_emit_utf8_const(const char *bytes, size_t len) { size_t len0 = len + 1; // incl. the '\0' byte int hash = java_style_hash(bytes) & 0xFFFF; scp_entry test_scpe; test_scpe.s = (char*)bytes; scp_entry *found_scpe = cpset_find(&scp, &test_scpe); if (found_scpe != NULL) { ir_entity *utf8const = found_scpe->utf8c; return utf8const; } ir_initializer_t *data_init = create_initializer_compound(len0); for (size_t i = 0; i < len0; ++i) { set_compound_init_num(data_init, i, mode_Bu, bytes[i]); } ir_initializer_t *cinit = create_initializer_compound(3); set_compound_init_num(cinit, 0, mode_ushort, hash); set_compound_init_num(cinit, 1, mode_ushort, len); set_initializer_compound_value(cinit, 2, data_init); ident *id = id_unique("_Utf8"); ir_entity *utf8c = new_entity(get_glob_type(), id, type_utf8_const); set_entity_initializer(utf8c, cinit); set_entity_ld_ident(utf8c, id); add_entity_linkage(utf8c, IR_LINKAGE_CONSTANT); scp_entry *new_scpe = XMALLOC(scp_entry); new_scpe->s = XMALLOCN(char, len0); memcpy(new_scpe->s, bytes, len0); new_scpe->utf8c = utf8c; cpset_insert(&scp, new_scpe); return utf8c; }
int main(void) { ir_init(); ir_type *type = new_type_primitive(get_modeIs()); ident *id1 = new_id_from_str("foo"); ir_type *glob = get_glob_type(); ir_entity *x = new_global_entity(glob, id1, type, ir_visibility_external, IR_LINKAGE_DEFAULT); assert(get_entity_owner(x) == glob); ident *id2 = new_id_from_str("bar"); ir_type *cls = new_type_class(id2); set_entity_owner(x, cls); assert(get_entity_owner(x) == cls); ir_entity *gx = ir_get_global(id1); assert (NULL == gx); set_entity_owner(x, glob); assert(get_entity_owner(x) == glob); return 0; }
static ir_entity *emit_method_table(ir_type *classtype) { class_t *linked_class = (class_t*) oo_get_type_link(classtype); assert(linked_class); uint16_t n_methods = linked_class->n_methods; ir_type *array_type = new_type_array(type_method_desc, n_methods); unsigned size = n_methods * get_type_size(type_method_desc); set_type_size(array_type, size); ir_initializer_t *cinit = create_initializer_compound(n_methods); for (uint16_t i = 0; i < n_methods; i++) { ir_entity *method = linked_class->methods[i]->link; ir_initializer_t *method_desc = get_method_desc(classtype, method); set_initializer_compound_value(cinit, i, method_desc); } ident *id = id_unique("_MT"); ir_entity *mt_ent = new_entity(get_glob_type(), id, array_type); set_entity_initializer(mt_ent, cinit); set_entity_ld_ident(mt_ent, id); return mt_ent; }
void gcji_init() { class_dollar_ident = new_id_from_str("class$"); glob = get_glob_type(); ir_type *t_ptr = new_type_primitive(mode_reference); ir_type *t_size = new_type_primitive(mode_Iu); // gcj_alloc ir_type *gcj_alloc_method_type = new_type_method(1, 1, false, 0, mtp_property_malloc); set_method_param_type(gcj_alloc_method_type, 0, t_ptr); set_method_res_type(gcj_alloc_method_type, 0, t_ptr); ident *gcj_alloc_id = ir_platform_mangle_global("_Jv_AllocObjectNoFinalizer"); gcj_alloc_entity = new_entity(glob, gcj_alloc_id, gcj_alloc_method_type); set_entity_visibility(gcj_alloc_entity, ir_visibility_external); // gcj_init ir_type *gcj_init_method_type = new_type_method(1, 0, false, 0, 0); set_method_param_type(gcj_init_method_type, 0, t_ptr); ident *gcj_init_id = ir_platform_mangle_global("_Jv_InitClass"); gcj_init_entity = new_entity(glob, gcj_init_id, gcj_init_method_type); set_entity_visibility(gcj_init_entity, ir_visibility_external); // gcj_new_string ir_type *gcj_new_string_method_type = new_type_method(1, 1, false, 0, 0); set_method_param_type(gcj_new_string_method_type, 0, t_ptr); set_method_res_type(gcj_new_string_method_type, 0, t_ptr); ident *gcj_new_string_id = ir_platform_mangle_global("_Z22_Jv_NewStringUtf8ConstP13_Jv_Utf8Const"); gcj_new_string_entity = new_entity(glob, gcj_new_string_id, gcj_new_string_method_type); set_entity_visibility(gcj_new_string_entity, ir_visibility_external); // gcj_new_prim_array ir_type *gcj_new_prim_array_method_type = new_type_method(2, 1, false, 0, 0); set_method_param_type(gcj_new_prim_array_method_type, 0, t_ptr); set_method_param_type(gcj_new_prim_array_method_type, 1, t_size); set_method_res_type(gcj_new_prim_array_method_type, 0, t_ptr); ident *gcj_new_prim_array_id = ir_platform_mangle_global("_Jv_NewPrimArray"); gcj_new_prim_array_entity = new_entity(glob, gcj_new_prim_array_id, gcj_new_prim_array_method_type); set_entity_visibility(gcj_new_prim_array_entity, ir_visibility_external); // gcj_new_object_array ir_type *gcj_new_object_array_method_type = new_type_method(3, 1, false, 0, 0); set_method_param_type(gcj_new_object_array_method_type, 0, t_size); set_method_param_type(gcj_new_object_array_method_type, 1, t_ptr); set_method_param_type(gcj_new_object_array_method_type, 2, t_ptr); set_method_res_type(gcj_new_object_array_method_type, 0, t_ptr); ident *gcj_new_object_array_id = ir_platform_mangle_global("_Jv_NewObjectArray"); gcj_new_object_array_entity = new_entity(glob, gcj_new_object_array_id, gcj_new_object_array_method_type); set_entity_visibility(gcj_new_object_array_entity, ir_visibility_external); // gcji_abstract_method ir_type *gcj_abstract_method_type = new_type_method(0, 0, false, 0, 0); gcj_abstract_method_entity = new_entity(glob, ir_platform_mangle_global("_Jv_ThrowAbstractMethodError"), gcj_abstract_method_type); set_entity_visibility(gcj_abstract_method_entity, ir_visibility_external); // gcji_lookup_interface ir_type *gcj_lookup_interface_type = new_type_method(3, 1, false, 0, 0); set_method_param_type(gcj_lookup_interface_type, 0, t_ptr); set_method_param_type(gcj_lookup_interface_type, 1, t_ptr); set_method_param_type(gcj_lookup_interface_type, 2, t_ptr); set_method_res_type(gcj_lookup_interface_type, 0, t_ptr); gcj_lookup_interface_entity = new_entity(glob, ir_platform_mangle_global("_Jv_LookupInterfaceMethod"), gcj_lookup_interface_type); set_entity_visibility(gcj_lookup_interface_entity, ir_visibility_external); // gcji_instanceof ir_type *gcj_instanceof_type = new_type_method(2, 1, false, 0, 0); set_method_param_type(gcj_instanceof_type, 0, type_reference); set_method_param_type(gcj_instanceof_type, 1, type_reference); set_method_res_type(gcj_instanceof_type, 0, type_int); gcj_instanceof_entity = new_entity(glob, ir_platform_mangle_global("_Jv_IsInstanceOf"), gcj_instanceof_type); set_entity_visibility(gcj_instanceof_entity, ir_visibility_external); // gcji_checkcast ir_type *gcj_checkcast_type = new_type_method(2, 0, false, 0, 0); set_method_param_type(gcj_checkcast_type, 0, type_reference); set_method_param_type(gcj_checkcast_type, 1, type_reference); gcj_checkcast_entity = new_entity(glob, ir_platform_mangle_global("_Jv_CheckCast"), gcj_checkcast_type); set_entity_visibility(gcj_checkcast_entity, ir_visibility_external); // gcji_get_array_class ir_type *gcj_get_array_class_type = new_type_method(2, 1, false, 0, 0); set_method_param_type(gcj_get_array_class_type, 0, type_reference); set_method_param_type(gcj_get_array_class_type, 1, type_reference); set_method_res_type(gcj_get_array_class_type, 0, type_reference); gcj_get_array_class_entity = new_entity(glob, ir_platform_mangle_global("_Z17_Jv_GetArrayClassPN4java4lang5ClassEPNS0_11ClassLoaderE"), gcj_get_array_class_type); set_entity_visibility(gcj_get_array_class_entity, ir_visibility_external); // gcji_new_multi_array ir_type *gcj_new_multiarray_type = new_type_method(3, 1, false, 0, 0); set_method_param_type(gcj_new_multiarray_type, 0, type_reference); set_method_param_type(gcj_new_multiarray_type, 1, type_int); set_method_param_type(gcj_new_multiarray_type, 2, type_reference); // XXX: actually int[] set_method_res_type(gcj_new_multiarray_type, 0, type_reference); gcj_new_multiarray_entity = new_entity(glob, ir_platform_mangle_global("_Z17_Jv_NewMultiArrayPN4java4lang5ClassEiPi"), gcj_new_multiarray_type); set_entity_visibility(gcj_new_multiarray_entity, ir_visibility_external); // primitive classes gcj_boolean_rtti_entity= extvar("_Jv_booleanClass", type_reference); gcj_byte_rtti_entity = extvar("_Jv_byteClass", type_reference); gcj_char_rtti_entity = extvar("_Jv_charClass", type_reference); gcj_short_rtti_entity = extvar("_Jv_shortClass", type_reference); gcj_int_rtti_entity = extvar("_Jv_intClass", type_reference); gcj_long_rtti_entity = extvar("_Jv_longClass", type_reference); gcj_float_rtti_entity = extvar("_Jv_floatClass", type_reference); gcj_double_rtti_entity = extvar("_Jv_doubleClass", type_reference); mode_ushort = new_int_mode("US", 16, 0, 16); type_ushort = new_type_primitive(mode_ushort); cpset_init(&scp, scp_hash, scp_cmp); type_method_desc = create_method_desc_type(); type_field_desc = create_field_desc_type(); type_utf8_const = create_utf8_const_type(); superobject_ident = new_id_from_str("@base"); ddispatch_set_vtable_layout(2, 4, 2, setup_vtable); ddispatch_set_abstract_method_entity(gcj_abstract_method_entity); ddispatch_set_interface_lookup_constructor(gcji_lookup_interface); /* we construct rtti right away */ rtti_set_runtime_typeinfo_constructor(dummy); rtti_set_instanceof_constructor(gcji_instanceof); dmemory_set_allocation_methods(gcji_get_arraylength); }
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); }
static ir_entity *extvar(char const *const name, ir_type *const type) { ident *id = ir_platform_mangle_global(name); return new_global_entity(get_glob_type(), id, type, ir_visibility_external, IR_LINKAGE_DEFAULT); }