diff options
author | Zoltan Varga <vargaz@gmail.com> | 2013-09-04 06:34:19 +0400 |
---|---|---|
committer | Zoltan Varga <vargaz@gmail.com> | 2013-09-04 06:34:36 +0400 |
commit | ec46c85cc468cb5977dd46ca746109d31ccfb21b (patch) | |
tree | 1ceb7125f161fe2487753143084e24cd302f11bc | |
parent | 11df177e10385c6ae897fbff68b407ab960eeffc (diff) |
Implement an intrinsics for Selector.GetHandle ().
-rwxr-xr-x | mono/mini/aot-compiler.c | 97 | ||||
-rw-r--r-- | mono/mini/cpu-arm.md | 1 | ||||
-rw-r--r-- | mono/mini/method-to-ir.c | 29 | ||||
-rw-r--r-- | mono/mini/mini-arm.c | 8 | ||||
-rw-r--r-- | mono/mini/mini-arm.h | 1 | ||||
-rw-r--r-- | mono/mini/mini-ops.h | 2 | ||||
-rw-r--r-- | mono/mini/mini.c | 4 | ||||
-rw-r--r-- | mono/mini/patch-info.h | 1 |
8 files changed, 143 insertions, 0 deletions
diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 366e811baa2..ac44136b93e 100755 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -233,6 +233,9 @@ typedef struct MonoAotCompile { GHashTable *dwarf_ln_filenames; gboolean global_symbols; gboolean direct_method_addresses; + int objc_selector_index, objc_selector_index_2; + GPtrArray *objc_selectors; + GHashTable *objc_selector_to_index; } MonoAotCompile; typedef struct { @@ -835,6 +838,35 @@ arch_emit_got_access (MonoAotCompile *acfg, guint8 *code, int got_slot, int *cod #endif /* + * arch_emit_objc_selector_ref: + * + * Emit the implementation of OP_OBJC_GET_SELECTOR, which itself implements @selector(foo:) in objective-c. + */ +static void +arch_emit_objc_selector_ref (MonoAotCompile *acfg, guint8 *code, int index, int *code_size) +{ +#if defined(TARGET_ARM) + char symbol1 [256]; + char symbol2 [256]; + int lindex = acfg->objc_selector_index_2 ++; + + /* Emit ldr.imm/b */ + emit_bytes (acfg, code, 8); + + sprintf (symbol1, "L_OBJC_SELECTOR_%d", lindex); + sprintf (symbol2, "L_OBJC_SELECTOR_REFERENCES_%d", index); + + emit_label (acfg, symbol1); + img_writer_emit_unset_mode (acfg->w); + fprintf (acfg->fp, ".long %s-(%s+12)", symbol2, symbol1); + + *code_size = 12; +#else + g_assert_not_reached (); +#endif +} + +/* * arch_emit_plt_entry: * * Emit code for the PLT entry with index INDEX. @@ -4511,6 +4543,30 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui patch_info->type = MONO_PATCH_INFO_NONE; break; } + case MONO_PATCH_INFO_OBJC_SELECTOR_REF: { + int code_size, index; + char *selector = (void*)patch_info->data.target; + + if (!acfg->objc_selector_to_index) + acfg->objc_selector_to_index = g_hash_table_new (g_str_hash, g_str_equal); + if (!acfg->objc_selectors) + acfg->objc_selectors = g_ptr_array_new (); + index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->objc_selector_to_index, selector)); + if (index) + index --; + else { + index = acfg->objc_selector_index; + g_ptr_array_add (acfg->objc_selectors, (void*)patch_info->data.target); + g_hash_table_insert (acfg->objc_selector_to_index, selector, GUINT_TO_POINTER (index + 1)); + acfg->objc_selector_index ++; + } + + arch_emit_objc_selector_ref (acfg, code + i, index, &code_size); + i += code_size - 1; + skip = TRUE; + patch_info->type = MONO_PATCH_INFO_NONE; + break; + } default: { /* * If this patch is a call, try emitting a direct call instead of @@ -8078,6 +8134,45 @@ emit_blob (MonoAotCompile *acfg) } static void +emit_objc_selectors (MonoAotCompile *acfg) +{ + int i; + + if (!acfg->objc_selectors || acfg->objc_selectors->len == 0) + return; + + /* + * From + * cat > foo.m << EOF + * void *ret () + * { + * return @selector(print:); + * } + * EOF + */ + + img_writer_emit_unset_mode (acfg->w); + g_assert (acfg->fp); + fprintf (acfg->fp, ".section __DATA,__objc_selrefs,literal_pointers,no_dead_strip\n"); + fprintf (acfg->fp, ".align 2\n"); + for (i = 0; i < acfg->objc_selectors->len; ++i) { + fprintf (acfg->fp, "L_OBJC_SELECTOR_REFERENCES_%d:\n", i); + fprintf (acfg->fp, ".long L_OBJC_METH_VAR_NAME_%d\n", i); + } + fprintf (acfg->fp, ".section __TEXT,__cstring,cstring_literals\n"); + for (i = 0; i < acfg->objc_selectors->len; ++i) { + fprintf (acfg->fp, "L_OBJC_METH_VAR_NAME_%d:\n", i); + fprintf (acfg->fp, ".asciz \"%s\"\n", (char*)g_ptr_array_index (acfg->objc_selectors, i)); + } + + fprintf (acfg->fp, ".section __DATA,__objc_imageinfo,regular,no_dead_strip\n"); + fprintf (acfg->fp, ".align 2\n"); + fprintf (acfg->fp, "L_OBJC_IMAGE_INFO:\n"); + fprintf (acfg->fp, ".long 0\n"); + fprintf (acfg->fp, ".long 16\n"); +} + +static void emit_dwarf_info (MonoAotCompile *acfg) { #ifdef EMIT_DWARF_INFO @@ -8789,6 +8884,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) emit_blob (acfg); + emit_objc_selectors (acfg); + emit_globals (acfg); emit_autoreg (acfg); diff --git a/mono/mini/cpu-arm.md b/mono/mini/cpu-arm.md index 0ff8a13f839..b00f5647876 100644 --- a/mono/mini/cpu-arm.md +++ b/mono/mini/cpu-arm.md @@ -194,6 +194,7 @@ float_clt_un: dest:i src1:f src2:f len:20 float_conv_to_u: dest:i src1:f len:36 setfret: src1:f len:12 aot_const: dest:i len:16 +objc_get_selector: dest:i len:32 sqrt: dest:f src1:f len:4 adc: dest:i src1:i src2:i len:4 addcc: dest:i src1:i src2:i len:4 diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 4e4ca8e3200..3619fc039fd 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -5384,6 +5384,35 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign * all inputs: * http://everything2.com/?node_id=1051618 */ + } else if ((!strcmp (cmethod->klass->image->assembly->aname.name, "MonoMac") || !strcmp (cmethod->klass->image->assembly->aname.name, "monotouch")) && !strcmp (cmethod->klass->name, "Selector") && !strcmp (cmethod->name, "GetHandle") && cfg->compile_aot && (args [0]->opcode == OP_GOT_ENTRY || args[0]->opcode == OP_AOTCONST)) { +#ifdef MONO_ARCH_HAVE_OBJC_GET_SELECTOR + MonoInst *pi; + MonoJumpInfoToken *ji; + MonoString *s; + + cfg->disable_llvm = TRUE; + + if (args [0]->opcode == OP_GOT_ENTRY) { + pi = args [0]->inst_p1; + g_assert (pi->opcode == OP_PATCH_INFO); + g_assert ((int)pi->inst_p1 == MONO_PATCH_INFO_LDSTR); + ji = pi->inst_p0; + } else { + g_assert ((int)args [0]->inst_p1 == MONO_PATCH_INFO_LDSTR); + ji = args [0]->inst_p0; + } + + NULLIFY_INS (args [0]); + + // FIXME: Ugly + s = mono_ldstr (cfg->domain, ji->image, mono_metadata_token_index (ji->token)); + MONO_INST_NEW (cfg, ins, OP_OBJC_GET_SELECTOR); + ins->dreg = mono_alloc_ireg (cfg); + // FIXME: Leaks + ins->inst_p0 = mono_string_to_utf8 (s); + MONO_ADD_INS (cfg->cbb, ins); + return ins; +#endif } #ifdef MONO_ARCH_SIMD_INTRINSICS diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c index 2aa2fdc0a9f..544607bd90a 100644 --- a/mono/mini/mini-arm.c +++ b/mono/mini/mini-arm.c @@ -4284,6 +4284,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* Load the value from the GOT */ ARM_LDR_REG_REG (code, ins->dreg, ARMREG_PC, ins->dreg); break; + case OP_OBJC_GET_SELECTOR: + mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_OBJC_SELECTOR_REF, ins->inst_p0); + ARM_LDR_IMM (code, ins->dreg, ARMREG_PC, 0); + ARM_B (code, 0); + *(gpointer*)code = NULL; + code += 4; + ARM_LDR_REG_REG (code, ins->dreg, ARMREG_PC, ins->dreg); + break; case OP_ICONV_TO_I4: case OP_ICONV_TO_U4: case OP_MOVE: diff --git a/mono/mini/mini-arm.h b/mono/mini/mini-arm.h index 913dafc5e0d..93a256b5632 100644 --- a/mono/mini/mini-arm.h +++ b/mono/mini/mini-arm.h @@ -231,6 +231,7 @@ typedef struct MonoCompileArch { #define MONO_ARCH_GSHAREDVT_SUPPORTED 1 #define MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE 1 #define MONO_ARCH_HAVE_OPCODE_NEEDS_EMULATION 1 +#define MONO_ARCH_HAVE_OBJC_GET_SELECTOR 1 #if defined(__native_client__) #undef MONO_ARCH_SOFT_DEBUG_SUPPORTED diff --git a/mono/mini/mini-ops.h b/mono/mini/mini-ops.h index a56f24bd6ec..f6c8c64d53b 100644 --- a/mono/mini/mini-ops.h +++ b/mono/mini/mini-ops.h @@ -1231,3 +1231,5 @@ MINI_OP(OP_MIPS_COND_EXC_INC, "mips_cond_exc_inc", NONE, IREG, IREG) MINI_OP(OP_LLVM_OUTARG_VT, "llvm_outarg_vt", IREG, VREG, NONE) #endif +MINI_OP(OP_OBJC_GET_SELECTOR, "objc_get_selector", IREG, NONE, NONE) + diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 9882d07a588..9dda83ac764 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -3513,6 +3513,10 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, case MONO_PATCH_INFO_TLS_OFFSET: target = GINT_TO_POINTER (mini_get_tls_offset (GPOINTER_TO_INT (patch_info->data.target))); break; + case MONO_PATCH_INFO_OBJC_SELECTOR_REF: { + target = NULL; + break; + } default: g_assert_not_reached (); } diff --git a/mono/mini/patch-info.h b/mono/mini/patch-info.h index daf32f03df5..a966be512bb 100644 --- a/mono/mini/patch-info.h +++ b/mono/mini/patch-info.h @@ -49,6 +49,7 @@ PATCH_INFO(GSHAREDVT_CALL, "gsharedvt_call") PATCH_INFO(GSHAREDVT_METHOD, "gsharedvt_method") PATCH_INFO(JIT_TLS_ID, "jit_tls_id") PATCH_INFO(TLS_OFFSET, "tls_offset") +PATCH_INFO(OBJC_SELECTOR_REF, "objc_selector_ref") PATCH_INFO(NONE, "none") |