[arm64_32] make "Debug Mode" work on Watch series 4 with --interpreter (mono/mono...
authorBernhard Urban <lewurm@gmail.com>
Tue, 17 Sep 2019 09:15:19 +0000 (11:15 +0200)
committermonojenkins <jo.shields+jenkins@xamarin.com>
Tue, 17 Sep 2019 09:15:19 +0000 (05:15 -0400)
[arm64_32] make "Debug Mode" work on Watch series 4 with --interpreter

Main objective for reviewers: This PR shouldn't change anything for `arm64`.

Context: "Debug Mode" on the Apple Watch allows execution of regular machine code and thus is pretty similar to FullAOT on iPhone, i.e. it doesn't require bitcode, but _still_ doesn't allow `signal(3)` so cooperative suspend is required.

Apple Watch Series 4 and onward use an ARM64 chip, but with a different ABI, also known as `arm64_32`. This PR changes the AOT compiler and related trampolines so that the AOT compiler can generate all necessary code to run the interpreter on this target.

Changes:

--------------------------------------

[arm64_32] set register size to 8 in cross compiler too

-----------------------------------------

 [machine] update `target_mgreg_t` definition

`SIZEOF_REGISTER` is usually the same as `TARGET_SIZEOF_VOID_P`, except when `MONO_ARCH_ILP32 is defined.

`target_mgreg_t` should represent the width of the hardware register, that is, `SIZEOF_REGISTER`.

---------------------------------------------

[arm64_32] fix AOT image layout

---------------------------------------------

 [arm64_32] make trampolines bitwidth aware

* replace pointer loads/stores with bitwidth-dependent macro
* reflect `specific` trampolines so that only two instructions are used for ILP32, since the related pair in the data page only needs 2 * 32bits too
* replace some `sizeof (target_mgreg_t)` with `TARGET_SIZEOF_VOID_P` (former is hardware register size, latter is pointer size)

---------------------------------------------
These regression tests are _not_ passing: https://github.com/mono/mono/issues/16864 Also some of monotouch-tests are crashing, see https://github.com/mono/mono/issues/16819

Here is a screenshot of a debug session in VSMac:
<img width="1321" alt="Screenshot 2019-09-16 at 19 13 22" src="https://user-images.githubusercontent.com/75403/64981326-1dfbc000-d8bc-11e9-9d16-48036f36b638.png">

Contributes to https://github.com/mono/mono/issues/10641

Commit migrated from https://github.com/mono/mono/commit/578e1a9dda135516d51f00680939facbc63061ba

src/mono/configure.ac
src/mono/mono/arch/arm64/arm64-codegen.h
src/mono/mono/mini/aot-compiler.c
src/mono/mono/mini/image-writer.c
src/mono/mono/mini/tramp-arm64.c
src/mono/mono/utils/mono-machine.h

index 2ee1b2e..facf852 100644 (file)
@@ -4613,6 +4613,7 @@ if test "x$host" != "x$target"; then
        aarch64*darwin*_ilp32)
                TARGET=ARM6432;
                AC_DEFINE(MONO_ARCH_ILP32, 1, [64 bit mode with 4 byte longs and pointers])
+               sizeof_register=8
                AC_DEFINE(TARGET_WATCHOS, 1, [...])
                ;;
        aarch64-*)
index 0156b11..239f416 100644 (file)
@@ -857,4 +857,14 @@ arm_encode_arith_imm (int imm, guint32 *shift)
 
 #define arm_mrs(p, rt, sysreg) arm_format_mrs ((p), (sysreg), (rt))
 
+#ifdef MONO_ARCH_ILP32
+#define arm_strp arm_strw
+#define arm_ldrp arm_ldrw
+#define arm_cmpp arm_cmpw
+#else
+#define arm_strp arm_strx
+#define arm_ldrp arm_ldrx
+#define arm_cmpp arm_cmpx
+#endif
+
 #endif /* __arm_CODEGEN_H__ */
index 97ae338..26cf8a6 100644 (file)
@@ -1216,6 +1216,7 @@ arch_init (MonoAotCompile *acfg)
 
 
 /* Load the contents of GOT_SLOT into dreg, clobbering ip0 */
+/* Must emit 12 bytes of instructions */
 static void
 arm64_emit_load_got_slot (MonoAotCompile *acfg, int dreg, int got_slot)
 {
@@ -1224,12 +1225,17 @@ arm64_emit_load_got_slot (MonoAotCompile *acfg, int dreg, int got_slot)
        g_assert (acfg->fp);
        emit_unset_mode (acfg);
        /* r16==ip0 */
-       offset = (int)(got_slot * sizeof (target_mgreg_t));
+       offset = (int)(got_slot * TARGET_SIZEOF_VOID_P);
 #ifdef TARGET_MACH
        /* clang's integrated assembler */
        fprintf (acfg->fp, "adrp x16, %s@PAGE+%d\n", acfg->got_symbol, offset & 0xfffff000);
+#ifdef MONO_ARCH_ILP32
+       fprintf (acfg->fp, "add x16, x16, %s@PAGEOFF+%d\n", acfg->got_symbol, offset & 0xfff);
+       fprintf (acfg->fp, "ldr w%d, [x16, #%d]\n", dreg, 0);
+#else
        fprintf (acfg->fp, "add x16, x16, %s@PAGEOFF\n", acfg->got_symbol);
        fprintf (acfg->fp, "ldr x%d, [x16, #%d]\n", dreg, offset & 0xfff);
+#endif
 #else
        /* Linux GAS */
        fprintf (acfg->fp, "adrp x16, %s+%d\n", acfg->got_symbol, offset & 0xfffff000);
@@ -1307,9 +1313,9 @@ arm64_emit_tramp_page_common_code (MonoAotCompile *acfg, int pagesize, int arg_r
        /* Compute the data slot address */
        arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
        /* Trampoline argument */
-       arm_ldrx (code, arg_reg, ARMREG_IP0, 0);
+       arm_ldrp (code, arg_reg, ARMREG_IP0, 0);
        /* Address */
-       arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 8);
+       arm_ldrp (code, ARMREG_IP0, ARMREG_IP0, TARGET_SIZEOF_VOID_P);
        arm_brx (code, ARMREG_IP0);
 
        /* Emit it */
@@ -1331,9 +1337,11 @@ arm64_emit_tramp_page_specific_code (MonoAotCompile *acfg, int pagesize, int com
                arm_adrx (code, ARMREG_IP0, code);
                /* Branch to the generic code */
                arm_b (code, code - 4 - (i * specific_tramp_size) - common_tramp_size);
+#ifndef MONO_ARCH_ILP32
                /* This has to be 2 pointers long */
                arm_nop (code);
                arm_nop (code);
+#endif
                g_assert (code - buf == specific_tramp_size);
                emit_code_bytes (acfg, buf, code - buf);
        }
@@ -1346,7 +1354,7 @@ arm64_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        guint8 *code;
        guint8 *labels [16];
        int common_tramp_size;
-       int specific_tramp_size = 2 * 8;
+       int specific_tramp_size = 2 * TARGET_SIZEOF_VOID_P;
        int imm, pagesize;
        char symbol [128];
 
@@ -1416,7 +1424,7 @@ arm64_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        /* Compute the data slot address */
        arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
        /* Address */
-       arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0);
+       arm_ldrp (code, ARMREG_IP0, ARMREG_IP0, 0);
        arm_brx (code, ARMREG_IP0);
 
        /* Emit it */
@@ -1441,12 +1449,12 @@ arm64_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        /* Compute the data slot address */
        arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
        /* Trampoline argument */
-       arm_ldrx (code, ARMREG_IP1, ARMREG_IP0, 0);
+       arm_ldrp (code, ARMREG_IP1, ARMREG_IP0, 0);
 
        /* Same as arch_emit_imt_trampoline () */
        labels [0] = code;
-       arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 0);
-       arm_cmpx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
+       arm_ldrp (code, ARMREG_IP0, ARMREG_IP1, 0);
+       arm_cmpp (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
        labels [1] = code;
        arm_bcc (code, ARMCOND_EQ, 0);
 
@@ -1455,21 +1463,21 @@ arm64_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        arm_cbzx (code, ARMREG_IP0, 0);
 
        /* Loop footer */
-       arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 2 * 8);
+       arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 2 * TARGET_SIZEOF_VOID_P);
        arm_b (code, labels [0]);
 
        /* Match */
        mono_arm_patch (labels [1], code, MONO_R_ARM64_BCC);
        /* Load vtable slot addr */
-       arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8);
+       arm_ldrp (code, ARMREG_IP0, ARMREG_IP1, TARGET_SIZEOF_VOID_P);
        /* Load vtable slot */
-       arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0);
+       arm_ldrp (code, ARMREG_IP0, ARMREG_IP0, 0);
        arm_brx (code, ARMREG_IP0);
 
        /* No match */
        mono_arm_patch (labels [2], code, MONO_R_ARM64_CBZ);
        /* Load fail addr */
-       arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8);
+       arm_ldrp (code, ARMREG_IP0, ARMREG_IP1, TARGET_SIZEOF_VOID_P);
        arm_brx (code, ARMREG_IP0);
 
        emit_code_bytes (acfg, buf, code - buf);
@@ -1523,8 +1531,8 @@ arm64_emit_imt_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 
        code = buf;
        labels [0] = code;
-       arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 0);
-       arm_cmpx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
+       arm_ldrp (code, ARMREG_IP0, ARMREG_IP1, 0);
+       arm_cmpp (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
        labels [1] = code;
        arm_bcc (code, ARMCOND_EQ, 0);
 
@@ -1539,15 +1547,15 @@ arm64_emit_imt_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
        /* Match */
        mono_arm_patch (labels [1], code, MONO_R_ARM64_BCC);
        /* Load vtable slot addr */
-       arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8);
+       arm_ldrp (code, ARMREG_IP0, ARMREG_IP1, TARGET_SIZEOF_VOID_P);
        /* Load vtable slot */
-       arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0);
+       arm_ldrp (code, ARMREG_IP0, ARMREG_IP0, 0);
        arm_brx (code, ARMREG_IP0);
 
        /* No match */
        mono_arm_patch (labels [2], code, MONO_R_ARM64_CBZ);
        /* Load fail addr */
-       arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8);
+       arm_ldrp (code, ARMREG_IP0, ARMREG_IP1, TARGET_SIZEOF_VOID_P);
        arm_brx (code, ARMREG_IP0);
 
        emit_code_bytes (acfg, buf, code - buf);
index fc1c457..7314c5e 100644 (file)
 #define AS_POINTER_DIRECTIVE ".quad"
 #elif defined(TARGET_ARM64)
 
+#ifdef MONO_ARCH_ILP32
+#define AS_POINTER_DIRECTIVE AS_INT32_DIRECTIVE
+#else
 #ifdef TARGET_ASM_APPLE
 #define AS_POINTER_DIRECTIVE ".quad"
 #else
 #define AS_POINTER_DIRECTIVE ".xword"
 #endif
+#endif
 
 #else
 #define AS_POINTER_DIRECTIVE ".long"
@@ -1862,7 +1866,7 @@ static void
 asm_writer_emit_pointer (MonoImageWriter *acfg, const char *target)
 {
        asm_writer_emit_unset_mode (acfg);
-       asm_writer_emit_alignment (acfg, sizeof (target_mgreg_t));
+       asm_writer_emit_alignment (acfg, TARGET_SIZEOF_VOID_P);
        asm_writer_emit_pointer_unaligned (acfg, target);
 }
 
index e8fda2a..ab79035 100644 (file)
@@ -204,12 +204,12 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        /* ip0 = lmf */
        arm_addx_imm (code, ARMREG_IP0, ARMREG_FP, lmf_offset);
        /* lmf->lmf_addr = lmf_addr */
-       arm_strx (code, ARMREG_R0, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, lmf_addr));
+       arm_strp (code, ARMREG_R0, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, lmf_addr));
        /* lmf->previous_lmf = *lmf_addr */
-       arm_ldrx (code, ARMREG_IP1, ARMREG_R0, 0);
-       arm_strx (code, ARMREG_IP1, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
+       arm_ldrp (code, ARMREG_IP1, ARMREG_R0, 0);
+       arm_strp (code, ARMREG_IP1, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
        /* *lmf_addr = lmf */
-       arm_strx (code, ARMREG_IP0, ARMREG_R0, 0);
+       arm_strp (code, ARMREG_IP0, ARMREG_R0, 0);
 
        /* Call the C trampoline function */
        /* Arg 1 = gregs */
@@ -245,11 +245,11 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        /* ip0 = lmf */
        arm_addx_imm (code, ARMREG_IP0, ARMREG_FP, lmf_offset);
        /* ip1 = lmf->previous_lmf */
-       arm_ldrx (code, ARMREG_IP1, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
+       arm_ldrp (code, ARMREG_IP1, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
        /* ip0 = lmf->lmf_addr */
-       arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, lmf_addr));
+       arm_ldrp (code, ARMREG_IP0, ARMREG_IP0, MONO_STRUCT_OFFSET (MonoLMF, lmf_addr));
        /* *lmf_addr = previous_lmf */
-       arm_strx (code, ARMREG_IP1, ARMREG_IP0, 0);
+       arm_strp (code, ARMREG_IP1, ARMREG_IP0, 0);
 
        /* Check for thread interruption */
        /* This is not perf critical code so no need to check the interrupt flag */
@@ -663,14 +663,14 @@ mono_arch_get_interp_to_native_trampoline (MonoTrampInfo **info)
        arm_strx (code, ARMREG_R0, ARMREG_FP, off_targetaddr);
 
        /* allocate the stack space necessary for the call */
-       arm_ldrx (code, ARMREG_R0, ARMREG_R1, MONO_STRUCT_OFFSET (CallContext, stack_size));
+       arm_ldrw (code, ARMREG_R0, ARMREG_R1, MONO_STRUCT_OFFSET (CallContext, stack_size));
        arm_movspx (code, ARMREG_IP0, ARMREG_SP);
        arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_R0);
        arm_movspx (code, ARMREG_SP, ARMREG_IP0);
 
        /* copy stack from the CallContext, IP0 = dest, IP1 = source */
        arm_movspx (code, ARMREG_IP0, ARMREG_SP);
-       arm_ldrx (code, ARMREG_IP1, ARMREG_R1, MONO_STRUCT_OFFSET (CallContext, stack));
+       arm_ldrp (code, ARMREG_IP1, ARMREG_R1, MONO_STRUCT_OFFSET (CallContext, stack));
 
        label_start_copy = code;
 
@@ -774,12 +774,12 @@ mono_arch_get_native_to_interp_trampoline (MonoTrampInfo **info)
 
        /* set the stack pointer to the value at call site */
        arm_addx_imm (code, ARMREG_R0, ARMREG_FP, framesize);
-       arm_strx (code, ARMREG_R0, ARMREG_FP, ccontext_offset + MONO_STRUCT_OFFSET (CallContext, stack));
+       arm_strp (code, ARMREG_R0, ARMREG_FP, ccontext_offset + MONO_STRUCT_OFFSET (CallContext, stack));
 
        /* call interp_entry with the ccontext and rmethod as arguments */
        arm_addx_imm (code, ARMREG_R0, ARMREG_FP, ccontext_offset);
-       arm_ldrx (code, ARMREG_R1, MONO_ARCH_RGCTX_REG, MONO_STRUCT_OFFSET (MonoFtnDesc, arg));
-       arm_ldrx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG, MONO_STRUCT_OFFSET (MonoFtnDesc, addr));
+       arm_ldrp (code, ARMREG_R1, MONO_ARCH_RGCTX_REG, MONO_STRUCT_OFFSET (MonoFtnDesc, arg));
+       arm_ldrp (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG, MONO_STRUCT_OFFSET (MonoFtnDesc, addr));
        arm_blrx (code, ARMREG_IP0);
 
        /* load the return values from the context */
index 036e7b1..922b5d2 100644 (file)
@@ -31,19 +31,12 @@ typedef gssize host_mgreg_t;
 typedef gsize host_umgreg_t;
 #endif
 
-// SIZEOF_REGISTER is target. mgreg_t is usually target, sometimes host.
-// There is a mismatch in cross (AOT) compilers, and the
-// never executed JIT and runtime truncate pointers.
-// When casting to/from pointers, use gsize or gssize.
-// When dealing with register context, use host_mgreg_t.
-// Or ifndef MONO_CROSS_COMPILE out runtime code.
+/* SIZEOF_REGISTER      ... machine register size of target machine
+ * TARGET_SIZEOF_VOID_P ... pointer size of target machine
+ *
+ * SIZEOF_REGISTER is usually the same as TARGET_SIZEOF_VOID_P, except when MONO_ARCH_ILP32 is defined
+ */
 #if SIZEOF_REGISTER == 4
-//typedef gint32 mgreg_t;
-#elif SIZEOF_REGISTER == 8
-//typedef gint64 mgreg_t;
-#endif
-
-#if TARGET_SIZEOF_VOID_P == 4
 typedef gint32 target_mgreg_t;
 #else
 typedef gint64 target_mgreg_t;