Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2013-09-04 06:34:19 +0400
committerZoltan Varga <vargaz@gmail.com>2013-09-04 06:34:36 +0400
commitec46c85cc468cb5977dd46ca746109d31ccfb21b (patch)
tree1ceb7125f161fe2487753143084e24cd302f11bc
parent11df177e10385c6ae897fbff68b407ab960eeffc (diff)
Implement an intrinsics for Selector.GetHandle ().
-rwxr-xr-xmono/mini/aot-compiler.c97
-rw-r--r--mono/mini/cpu-arm.md1
-rw-r--r--mono/mini/method-to-ir.c29
-rw-r--r--mono/mini/mini-arm.c8
-rw-r--r--mono/mini/mini-arm.h1
-rw-r--r--mono/mini/mini-ops.h2
-rw-r--r--mono/mini/mini.c4
-rw-r--r--mono/mini/patch-info.h1
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")