Author: zoltan
Date: 2007-12-07 10:29:51 -0500 (Fri, 07 Dec 2007)
New Revision: 90941
Modified:
trunk/mono/mono/mini/ChangeLog
trunk/mono/mono/mini/aot-compiler.c
trunk/mono/mono/mini/aot-runtime.c
trunk/mono/mono/mini/cpu-arm.md
trunk/mono/mono/mini/inssel-arm.brg
trunk/mono/mono/mini/mini-arm.c
trunk/mono/mono/mini/mini-arm.h
trunk/mono/mono/mini/tramp-arm.c
Log:
2007-12-07 Zoltan Varga <[EMAIL PROTECTED]>
* mini-arm.h mini-arm.c tramp-arm.c inssel-arm.brg cpu-arm.md
aot-runtime.c aot-compiler.c: Implement AOT support.
Modified: trunk/mono/mono/mini/ChangeLog
===================================================================
--- trunk/mono/mono/mini/ChangeLog 2007-12-07 15:28:17 UTC (rev 90940)
+++ trunk/mono/mono/mini/ChangeLog 2007-12-07 15:29:51 UTC (rev 90941)
@@ -1,3 +1,8 @@
+2007-12-07 Zoltan Varga <[EMAIL PROTECTED]>
+
+ * mini-arm.h mini-arm.c tramp-arm.c inssel-arm.brg cpu-arm.md
+ aot-runtime.c aot-compiler.c: Implement AOT support.
+
2007-12-07 Mark Probst <[EMAIL PROTECTED]>
* mini-trampolines.c (mono_generic_class_init_trampoline): Fixed
Modified: trunk/mono/mono/mini/aot-compiler.c
===================================================================
--- trunk/mono/mono/mini/aot-compiler.c 2007-12-07 15:28:17 UTC (rev 90940)
+++ trunk/mono/mono/mini/aot-compiler.c 2007-12-07 15:29:51 UTC (rev 90941)
@@ -184,17 +184,10 @@
static gboolean
is_got_patch (MonoJumpInfoType patch_type)
{
-#ifdef __x86_64__
return TRUE;
-#elif defined(__i386__)
- return TRUE;
-#else
- return FALSE;
-#endif
}
-#if defined(__ppc__) && defined(__MACH__)
-static int
+static G_GNUC_UNUSED int
ilog2(register int value)
{
int count = -1;
@@ -202,7 +195,6 @@
while (value) count++, value >>= 1;
return count;
}
-#endif
#ifdef USE_BIN_WRITER
@@ -1261,7 +1253,7 @@
emit_unset_mode (acfg);
#if defined(PLATFORM_WIN32)
fprintf (acfg->fp, ".section %s\n", section_name);
-#elif defined(sparc)
+#elif defined(sparc) || defined(__arm__)
/* For solaris as, GNU as should accept the same */
fprintf (acfg->fp, ".section \"%s\"\n", section_name);
#elif defined(__ppc__) && defined(__MACH__)
@@ -1283,7 +1275,7 @@
stype = "object";
emit_unset_mode (acfg);
-#if defined(sparc)
+#if defined(sparc) || defined(__arm__)
fprintf (acfg->fp, "\t.type %s,#%s\n", name, stype);
#elif defined(PLATFORM_WIN32)
@@ -1353,7 +1345,9 @@
emit_alignment (MonoAotCompile *acfg, int size)
{
emit_unset_mode (acfg);
-#if defined(__ppc__) && defined(__MACH__)
+#if defined(__arm__)
+ fprintf (acfg->fp, "\t.align %d\n", ilog2 (size));
+#elif defined(__ppc__) && defined(__MACH__)
// the mach-o assembler specifies alignments as powers of 2.
fprintf (acfg->fp, "\t.align %d\t; ilog2\n", ilog2(size));
#elif defined(__powerpc__)
@@ -1402,7 +1396,12 @@
acfg->col_count = 0;
}
if ((acfg->col_count++ % 8) == 0)
+#if defined(__arm__)
+ /* FIXME: Use .hword on other archs as well */
+ fprintf (acfg->fp, "\n\t.hword ");
+#else
fprintf (acfg->fp, "\n\t.word ");
+#endif
else
fprintf (acfg->fp, ", ");
fprintf (acfg->fp, "%d", value);
@@ -1949,9 +1948,16 @@
emit_byte (acfg, '\xe8');
emit_symbol_diff (acfg,
direct_call_target, ".", -4);
i += 4;
+#elif defined(__arm__)
+#ifdef USE_BIN_WRITER
+ /* FIXME: Can't encode this using the
current symbol writer functions */
+ g_assert_not_reached ();
#else
- g_assert_not_reached ();
+ emit_unset_mode (acfg);
+ fprintf (acfg->fp, "bl %s\n",
direct_call_target);
+ i += 4 - 1;
#endif
+#endif
} else {
got_slot = get_got_offset (acfg,
patch_info);
@@ -1960,6 +1966,10 @@
emit_symbol_diff (acfg, "got", ".",
(unsigned int) ((got_slot * sizeof (gpointer)) - 4));
#elif defined(__i386__)
emit_int32 (acfg, (unsigned int)
((got_slot * sizeof (gpointer))));
+#elif defined(__arm__)
+ emit_symbol_diff (acfg, "got", ".",
(unsigned int) ((got_slot * sizeof (gpointer))) - 12);
+#else
+ g_assert_not_reached ();
#endif
i += mono_arch_get_patch_offset (code +
i) + 4 - 1;
@@ -2413,7 +2423,7 @@
* - the ELF PLT entries make an indirect jump though the GOT so they expect
the
* GOT pointer to be in EBX. We want to avoid this, so our table contains
direct
* jumps. This means the jumps need to be patched when the address of the
callee is
- * known. Initially the PLT entries jump to code which transfer control to
the
+ * known. Initially the PLT entries jump to code which transfers control to
the
* AOT runtime through the first PLT entry.
*/
static void
@@ -2449,6 +2459,11 @@
emit_alignment (acfg, PAGESIZE);
emit_label (acfg, symbol);
+#if defined(USE_BIN_WRITER) && defined(__arm__)
+ /* FIXME: */
+ g_assert_not_reached ();
+#endif
+
/*
* The first plt entry is used to transfer code to the AOT loader.
*/
@@ -2463,6 +2478,12 @@
emit_byte (acfg, '\x25');
emit_symbol_diff (acfg, "plt_jump_table", ".", -4);
emit_zero_bytes (acfg, 10);
+#elif defined(__arm__)
+ /* This is 8 bytes long, init_plt () depends on this */
+ emit_unset_mode (acfg);
+ fprintf (acfg->fp, "\tldr pc, [pc, #-4]\n");
+ /* This is filled up during loading by the AOT loader */
+ fprintf (acfg->fp, "\t.word 0\n");
#else
g_assert_not_reached ();
#endif
@@ -2498,6 +2519,22 @@
/* jmp .Lp_0 */
emit_byte (acfg, '\xe9');
emit_symbol_diff (acfg, ".Lp_0", ".", -4);
+#elif defined(__arm__)
+ /*
+ * Emit an indirect call since branch displacements are limited
to 24 bits on
+ * ARM. Put the jump table entries inline since offsets are
even smaller on
+ * ARM.
+ * FIXME:
+ * - optimize OP_AOTCONST implementation
+ * - optimize the PLT entries
+ * - optimize SWITCH AOT implementation
+ * - implement IMT support
+ */
+ /* This is 8 bytes long, init_plt () depends on this */
+ emit_unset_mode (acfg);
+ fprintf (acfg->fp, "\tldr pc, [pc, #-4]\n");
+ /* This is filled up during loading by the AOT loader */
+ fprintf (acfg->fp, "\t.word 0\n");
#else
g_assert_not_reached ();
#endif
@@ -2528,6 +2565,12 @@
emit_symbol_diff (acfg, ".Lp_0", ".", -4);
#elif defined(__x86_64__)
/* Emitted along with the PLT entries since they will not be
patched */
+#elif defined(__arm__)
+ /* This is 12 bytes long, init_plt () depends on this */
+ emit_unset_mode (acfg);
+ fprintf (acfg->fp, "\tldr ip, [pc, #0]\n");
+ fprintf (acfg->fp, "\tb .Lp_0\n");
+ fprintf (acfg->fp, "\t.word %d\n", plt_info_offsets [i]);
#else
g_assert_not_reached ();
#endif
@@ -3114,7 +3157,7 @@
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
- /* To reduce size of generate assembly */
+ /* To reduce size of generated assembly */
symbol = g_strdup_printf ("ex");
emit_label (acfg, symbol);
Modified: trunk/mono/mono/mini/aot-runtime.c
===================================================================
--- trunk/mono/mono/mini/aot-runtime.c 2007-12-07 15:28:17 UTC (rev 90940)
+++ trunk/mono/mono/mini/aot-runtime.c 2007-12-07 15:29:51 UTC (rev 90941)
@@ -150,13 +150,7 @@
static inline gboolean
is_got_patch (MonoJumpInfoType patch_type)
{
-#ifdef __x86_64__
return TRUE;
-#elif defined(__i386__)
- return TRUE;
-#else
- return FALSE;
-#endif
}
/*****************************************************/
@@ -2013,9 +2007,10 @@
#ifdef MONO_ARCH_AOT_SUPPORTED
#ifdef __i386__
guint8 *buf = info->plt;
-#endif
-#if defined(__x86_64__)
+#elif defined(__x86_64__)
int i, n_entries;
+#elif defined(__arm__)
+ int i, n_entries;
#endif
gpointer tramp;
@@ -2039,6 +2034,21 @@
for (i = 1; i < n_entries; ++i)
/* Each PLT entry is 16 bytes long, the default entry begins
at offset 6 */
((gpointer*)info->plt_jump_table)[i] = info->plt + (i * 16) +
6;
+#elif defined(__arm__)
+ /* Initialize the first PLT entry */
+ make_writable (info->plt, info->plt_end - info->plt);
+ ((guint32*)info->plt)[1] = (guint32)tramp;
+
+ n_entries = ((guint8*)info->plt_end - (guint8*)info->plt) / 8;
+
+ /*
+ * Initialize the jump targets embedded inside the PLT entries to the
default
+ * targets.
+ */
+ for (i = 1; i < n_entries; ++i)
+ /* Each PLT entry is 8 bytes long, the jump target is at
offset 4 */
+ /* Each default PLT target is 12 bytes long */
+ ((guint32*)info->plt)[(i * 2) + 1] = (guint8*)info->plt_end +
((i - 1) * 12);
#else
g_assert_not_reached ();
#endif
@@ -2068,6 +2078,19 @@
if ((target >= (guint8*)(aot_module->plt)) && (target <
(guint8*)(aot_module->plt_end)))
return target;
}
+#elif defined(__arm__)
+ guint32 ins = ((guint32*)code) [-1];
+
+ /* Should be a 'bl' */
+ if ((((ins >> 25) & 0x7) == 0x5) && (((ins >> 24) & 0x1) == 0x1)) {
+ gint32 disp = ((gint32)ins) & 0xffffff;
+ guint8 *target = code - 4 + 8 + (disp * 4);
+
+ if ((target >= (guint8*)(aot_module->plt)) && (target <
(guint8*)(aot_module->plt_end)))
+ return target;
+ }
+#else
+ g_assert_not_reached ();
#endif
return NULL;
Modified: trunk/mono/mono/mini/cpu-arm.md
===================================================================
--- trunk/mono/mono/mini/cpu-arm.md 2007-12-07 15:28:17 UTC (rev 90940)
+++ trunk/mono/mono/mini/cpu-arm.md 2007-12-07 15:29:51 UTC (rev 90941)
@@ -530,7 +530,7 @@
float_conv_to_u: dest:i src1:f len:36
call_handler: len:12
op_endfilter: src1:i len:16
-aot_const: dest:i len:8
+aot_const: dest:i len:16
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
Modified: trunk/mono/mono/mini/inssel-arm.brg
===================================================================
--- trunk/mono/mono/mini/inssel-arm.brg 2007-12-07 15:28:17 UTC (rev 90940)
+++ trunk/mono/mono/mini/inssel-arm.brg 2007-12-07 15:29:51 UTC (rev 90941)
@@ -496,11 +496,33 @@
MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg1, n);
MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_many_bb [n]);
- mono_bblock_add_inst (s->cbb, label);
- mono_create_jump_table (s, label, tree->inst_many_bb, n);
- /* the backend code will deal with aot vs normal case */
- tree->sreg1 = state->left->reg1;
- mono_bblock_add_inst (s->cbb, tree);
+
+ if (s->compile_aot) {
+ /* FIXME: Optimize this */
+ int offset_reg = mono_regstate_next_int (s->rs);
+ int target_reg = mono_regstate_next_int (s->rs);
+ int table_reg = mono_regstate_next_int (s->rs);
+ int sum_reg = mono_regstate_next_int (s->rs);
+ MonoJumpInfoBBTable *table;
+
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, offset_reg,
state->left->reg1, 2);
+
+ table = mono_mempool_alloc (s->mempool, sizeof
(MonoJumpInfoBBTable));
+ table->table = tree->inst_many_bb;
+ table->table_size = n;
+
+ MONO_EMIT_NEW_AOTCONST (s, table_reg, table,
MONO_PATCH_INFO_SWITCH);
+
+ MONO_EMIT_NEW_BIALU (s, CEE_ADD, sum_reg, table_reg,
offset_reg);
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, target_reg, sum_reg, 0);
+ MONO_EMIT_UNALU (s, tree, OP_BR_REG, -1, target_reg);
+ } else {
+ mono_bblock_add_inst (s->cbb, label);
+ mono_create_jump_table (s, label, tree->inst_many_bb, n);
+ /* the backend code will deal with aot vs normal case */
+ tree->sreg1 = state->left->reg1;
+ mono_bblock_add_inst (s->cbb, tree);
+ }
}
%%
Modified: trunk/mono/mono/mini/mini-arm.c
===================================================================
--- trunk/mono/mono/mini/mini-arm.c 2007-12-07 15:28:17 UTC (rev 90940)
+++ trunk/mono/mono/mini/mini-arm.c 2007-12-07 15:29:51 UTC (rev 90941)
@@ -2410,8 +2410,14 @@
code = mono_arm_emit_load_imm (code, ins->dreg,
ins->inst_c0);
break;
case OP_AOTCONST:
- g_assert_not_reached ();
+ /* Load the GOT offset */
mono_add_patch_info (cfg, offset,
(MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
+ ARM_LDR_IMM (code, ins->dreg, ARMREG_PC, 0);
+ ARM_B (code, 0);
+ *(gpointer*)code = NULL;
+ code += 4;
+ /* Load the value from the GOT */
+ ARM_LDR_REG_REG (code, ins->dreg, ARMREG_PC, ins->dreg);
break;
case CEE_CONV_I4:
case CEE_CONV_U4:
@@ -2502,6 +2508,9 @@
g_assert (ins->sreg1 != ARMREG_LR);
call = (MonoCallInst*)ins;
if (call->method->klass->flags &
TYPE_ATTRIBUTE_INTERFACE) {
+ if (cfg->compile_aot)
+ /* FIXME: */
+ cfg->disable_aot = 1;
ARM_ADD_REG_IMM8 (code, ARMREG_LR, ARMREG_PC,
4);
ARM_LDR_IMM (code, ARMREG_PC, ins->sreg1,
ins->inst_offset);
*((gpointer*)code) = (gpointer)call->method;
@@ -2696,15 +2705,31 @@
/* floating point opcodes */
#ifdef ARM_FPU_FPA
case OP_R8CONST:
- /* FIXME: we can optimize the imm load by dealing with
part of
- * the displacement in LDFD (aligning to 512).
- */
- code = mono_arm_emit_load_imm (code, ARMREG_LR,
(guint32)ins->inst_p0);
- ARM_LDFD (code, ins->dreg, ARMREG_LR, 0);
+ if (cfg->compile_aot) {
+ ARM_LDFD (code, ins->dreg, ARMREG_PC, 0);
+ ARM_B (code, 1);
+ *(guint32*)code = ((guint32*)(ins->inst_p0))[0];
+ code += 4;
+ *(guint32*)code = ((guint32*)(ins->inst_p0))[1];
+ code += 4;
+ } else {
+ /* FIXME: we can optimize the imm load by
dealing with part of
+ * the displacement in LDFD (aligning to 512).
+ */
+ code = mono_arm_emit_load_imm (code, ARMREG_LR,
(guint32)ins->inst_p0);
+ ARM_LDFD (code, ins->dreg, ARMREG_LR, 0);
+ }
break;
case OP_R4CONST:
- code = mono_arm_emit_load_imm (code, ARMREG_LR,
(guint32)ins->inst_p0);
- ARM_LDFS (code, ins->dreg, ARMREG_LR, 0);
+ if (cfg->compile_aot) {
+ ARM_LDFS (code, ins->dreg, ARMREG_PC, 0);
+ ARM_B (code, 0);
+ *(guint32*)code = ((guint32*)(ins->inst_p0))[0];
+ code += 4;
+ } else {
+ code = mono_arm_emit_load_imm (code, ARMREG_LR,
(guint32)ins->inst_p0);
+ ARM_LDFS (code, ins->dreg, ARMREG_LR, 0);
+ }
break;
case OP_STORER8_MEMBASE_REG:
g_assert (arm_is_fpimm8 (ins->inst_offset));
@@ -2756,16 +2781,33 @@
break;
#elif defined(ARM_FPU_VFP)
case OP_R8CONST:
- /* FIXME: we can optimize the imm load by dealing with
part of
- * the displacement in LDFD (aligning to 512).
- */
- code = mono_arm_emit_load_imm (code, ARMREG_LR,
(guint32)ins->inst_p0);
- ARM_FLDD (code, ins->dreg, ARMREG_LR, 0);
+ if (cfg->compile_aot) {
+ ARM_LDFD (code, ins->dreg, ARMREG_PC, 0);
+ ARM_B (code, 1);
+ *(guint32*)code = ((guint32*)(ins->inst_p0))[0];
+ code += 4;
+ *(guint32*)code = ((guint32*)(ins->inst_p0))[1];
+ code += 4;
+ } else {
+ /* FIXME: we can optimize the imm load by
dealing with part of
+ * the displacement in LDFD (aligning to 512).
+ */
+ code = mono_arm_emit_load_imm (code, ARMREG_LR,
(guint32)ins->inst_p0);
+ ARM_FLDD (code, ins->dreg, ARMREG_LR, 0);
+ }
break;
case OP_R4CONST:
- code = mono_arm_emit_load_imm (code, ARMREG_LR,
(guint32)ins->inst_p0);
- ARM_FLDS (code, ins->dreg, ARMREG_LR, 0);
- ARM_CVTS (code, ins->dreg, ins->dreg);
+ if (cfg->compile_aot) {
+ ARM_FLDS (code, ins->dreg, ARMREG_PC, 0);
+ ARM_B (code, 0);
+ *(guint32*)code = ((guint32*)(ins->inst_p0))[0];
+ code += 4;
+ ARM_CVTS (code, ins->dreg, ins->dreg);
+ } else {
+ code = mono_arm_emit_load_imm (code, ARMREG_LR,
(guint32)ins->inst_p0);
+ ARM_FLDS (code, ins->dreg, ARMREG_LR, 0);
+ ARM_CVTS (code, ins->dreg, ins->dreg);
+ }
break;
case OP_STORER8_MEMBASE_REG:
g_assert (arm_is_fpimm8 (ins->inst_offset));
@@ -3082,25 +3124,36 @@
mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code,
MonoJumpInfo *ji, gboolean run_cctors)
{
MonoJumpInfo *patch_info;
+ gboolean compile_aot = !run_cctors;
for (patch_info = ji; patch_info; patch_info = patch_info->next) {
unsigned char *ip = patch_info->ip.i + code;
const unsigned char *target;
- if (patch_info->type == MONO_PATCH_INFO_SWITCH) {
+ if (patch_info->type == MONO_PATCH_INFO_SWITCH && !compile_aot)
{
gpointer *jt = (gpointer*)(ip + 8);
int i;
/* jt is the inlined jump table, 2 instructions after ip
* In the normal case we store the absolute addresses,
* otherwise the displacements.
*/
- for (i = 0; i < patch_info->data.table->table_size;
i++) {
+ for (i = 0; i < patch_info->data.table->table_size; i++)
jt [i] = code +
(int)patch_info->data.table->table [i];
- }
continue;
}
target = mono_resolve_patch_target (method, domain, code,
patch_info, run_cctors);
+ if (compile_aot) {
+ switch (patch_info->type) {
+ case MONO_PATCH_INFO_BB:
+ case MONO_PATCH_INFO_LABEL:
+ break;
+ default:
+ /* No need to patch these */
+ continue;
+ }
+ }
+
switch (patch_info->type) {
case MONO_PATCH_INFO_IP:
g_assert_not_reached ();
@@ -3652,6 +3705,13 @@
return NULL;
}
+guint32
+mono_arch_get_patch_offset (guint8 *code)
+{
+ /* OP_AOTCONST */
+ return 8;
+}
+
void
mono_arch_flush_register_windows (void)
{
Modified: trunk/mono/mono/mini/mini-arm.h
===================================================================
--- trunk/mono/mono/mini/mini-arm.h 2007-12-07 15:28:17 UTC (rev 90940)
+++ trunk/mono/mono/mini/mini-arm.h 2007-12-07 15:29:51 UTC (rev 90941)
@@ -57,6 +57,8 @@
* reproduceable results for benchmarks */
#define MONO_ARCH_CODE_ALIGNMENT 32
+#define MONO_ARCH_AOT_PLT_OFFSET_REG ARMREG_IP
+
void arm_patch (guchar *code, const guchar *target);
guint8* mono_arm_emit_load_imm (guint8 *code, int dreg, guint32 val);
@@ -118,6 +120,8 @@
#define MONO_ARCH_HAVE_IMT 1
+#define MONO_ARCH_AOT_SUPPORTED 1
+
/* we have the stack pointer, not the base pointer in sigcontext */
#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->eip = (int)ip; } while (0);
#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->ebp = (int)bp; } while (0);
Modified: trunk/mono/mono/mini/tramp-arm.c
===================================================================
--- trunk/mono/mono/mini/tramp-arm.c 2007-12-07 15:28:17 UTC (rev 90940)
+++ trunk/mono/mono/mini/tramp-arm.c 2007-12-07 15:29:51 UTC (rev 90941)
@@ -105,7 +105,15 @@
void
mono_arch_patch_plt_entry (guint8 *code, guint8 *addr)
{
- g_assert_not_reached ();
+ guint32 ins = branch_for_target_reachable (code, addr);
+
+ if (ins)
+ /* Patch the branch */
+ ((guint32*)code) [0] = ins;
+ else
+ /* Patch the jump address */
+ ((guint32*)code) [1] = addr;
+ mono_arch_flush_icache ((char*)code, 4);
}
void
@@ -117,7 +125,14 @@
void
mono_arch_nullify_plt_entry (guint8 *code)
{
- g_assert_not_reached ();
+ guint8 buf [4];
+ guint8 *p;
+
+ p = buf;
+ ARM_MOV_REG_REG (p, ARMREG_PC, ARMREG_LR);
+
+ ((guint32*)code) [0] = ((guint32*)buf) [0];
+ mono_arch_flush_icache ((char*)code, 4);
}
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches