Merge pull request #4621 from alexanderkyte/strdup_env
[mono.git] / mono / mini / mini-arm.c
index 108b4abd256a9e381ac6d9cee0da9d329fc14e73..f80d5f5b0272e5f6315be7c26c65cf5941b91f7c 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * mini-arm.c: ARM backend for the Mono code generator
+/**
+ * \file
+ * ARM backend for the Mono code generator
  *
  * Authors:
  *   Paolo Molaro (lupus@ximian.com)
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/debug-helpers.h>
 #include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-hwcap-arm.h>
+#include <mono/utils/mono-hwcap.h>
 #include <mono/utils/mono-memory-model.h>
 #include <mono/utils/mono-threads-coop.h>
 
 #include "mini-arm.h"
-#include "mini-arm-tls.h"
 #include "cpu-arm.h"
 #include "trace.h"
 #include "ir-emit.h"
 #include "mini-gc.h"
 #include "mono/arch/arm/arm-vfp-codegen.h"
 
-#if (defined(HAVE_KW_THREAD) && defined(__linux__) && defined(__ARM_EABI__)) \
-       || defined(TARGET_ANDROID) \
-       || (defined(TARGET_IOS) && !defined(TARGET_WATCHOS))
-#define HAVE_FAST_TLS
-#endif
-
 /* Sanity check: This makes no sense */
 #if defined(ARM_FPU_NONE) && (defined(ARM_FPU_VFP) || defined(ARM_FPU_VFP_HARD))
 #error "ARM_FPU_NONE is defined while one of ARM_FPU_VFP/ARM_FPU_VFP_HARD is defined"
@@ -127,6 +121,7 @@ static int vfp_scratch2 = ARM_VFP_D1;
 static int i8_align;
 
 static gpointer single_step_tramp, breakpoint_tramp;
+static gpointer get_tls_tramp;
 
 /*
  * The code generated for sequence points reads from this location, which is
@@ -167,6 +162,9 @@ int mono_exc_esp_offset = 0;
 static void mono_arch_compute_omit_fp (MonoCompile *cfg);
 #endif
 
+static guint8*
+emit_aotconst (MonoCompile *cfg, guint8 *code, int dreg, int patch_type, gpointer data);
+
 const char*
 mono_arch_regname (int reg)
 {
@@ -325,83 +323,53 @@ mono_arm_patchable_bl (guint8 *code, int cond)
        return code;
 }
 
-static guint8*
-mono_arm_emit_tls_get (MonoCompile *cfg, guint8* code, int dreg, int tls_offset)
-{
-#ifdef HAVE_FAST_TLS
-       code = mono_arm_emit_load_imm (code, ARMREG_R0, tls_offset);
-       mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
-                       "mono_get_tls_key");
-       code = emit_call_seq (cfg, code);
-       if (dreg != ARMREG_R0)
-               ARM_MOV_REG_REG (code, dreg, ARMREG_R0);
-#else
-       g_assert_not_reached ();
+#if defined(__ARM_EABI__) && defined(__linux__) && !defined(PLATFORM_ANDROID) && !defined(__native_client__)
+#define HAVE_AEABI_READ_TP 1
 #endif
-       return code;
-}
 
-static guint8*
-mono_arm_emit_tls_get_reg (MonoCompile *cfg, guint8* code, int dreg, int tls_offset_reg)
+#ifdef HAVE_AEABI_READ_TP
+gpointer __aeabi_read_tp (void);
+#endif
+
+gboolean
+mono_arch_have_fast_tls (void)
 {
-#ifdef HAVE_FAST_TLS
-       if (tls_offset_reg != ARMREG_R0)
-               ARM_MOV_REG_REG (code, ARMREG_R0, tls_offset_reg);
-       mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
-                       "mono_get_tls_key");
-       code = emit_call_seq (cfg, code);
-       if (dreg != ARMREG_R0)
-               ARM_MOV_REG_REG (code, dreg, ARMREG_R0);
+#ifdef HAVE_AEABI_READ_TP
+       static gboolean have_fast_tls = FALSE;
+        static gboolean inited = FALSE;
+       gpointer tp1, tp2;
+
+       if (mini_get_debug_options ()->use_fallback_tls)
+               return FALSE;
+
+       if (inited)
+               return have_fast_tls;
+
+       tp1 = __aeabi_read_tp ();
+       asm volatile("mrc p15, 0, %0, c13, c0, 3" : "=r" (tp2));
+
+       have_fast_tls = tp1 && tp1 == tp2;
+       inited = TRUE;
+       return have_fast_tls;
 #else
-       g_assert_not_reached ();
+       return FALSE;
 #endif
-       return code;
 }
 
 static guint8*
-mono_arm_emit_tls_set (MonoCompile *cfg, guint8* code, int sreg, int tls_offset)
+emit_tls_get (guint8 *code, int dreg, int tls_offset)
 {
-#ifdef HAVE_FAST_TLS
-       if (sreg != ARMREG_R1)
-               ARM_MOV_REG_REG (code, ARMREG_R1, sreg);
-       code = mono_arm_emit_load_imm (code, ARMREG_R0, tls_offset);
-       mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
-                       "mono_set_tls_key");
-       code = emit_call_seq (cfg, code);
-#else
-       g_assert_not_reached ();
-#endif
+       ARM_MRC (code, 15, 0, dreg, 13, 0, 3);
+       ARM_LDR_IMM (code, dreg, dreg, tls_offset);
        return code;
 }
 
 static guint8*
-mono_arm_emit_tls_set_reg (MonoCompile *cfg, guint8* code, int sreg, int tls_offset_reg)
+emit_tls_set (guint8 *code, int sreg, int tls_offset)
 {
-#ifdef HAVE_FAST_TLS
-       /* Get sreg in R1 and tls_offset_reg in R0 */
-       if (tls_offset_reg == ARMREG_R1) {
-               if (sreg == ARMREG_R0) {
-                       /* swap sreg and tls_offset_reg */
-                       ARM_EOR_REG_REG (code, sreg, sreg, tls_offset_reg);
-                       ARM_EOR_REG_REG (code, tls_offset_reg, sreg, tls_offset_reg);
-                       ARM_EOR_REG_REG (code, sreg, sreg, tls_offset_reg);
-               } else {
-                       ARM_MOV_REG_REG (code, ARMREG_R0, tls_offset_reg);
-                       if (sreg != ARMREG_R1)
-                               ARM_MOV_REG_REG (code, ARMREG_R1, sreg);
-               }
-       } else {
-               if (sreg != ARMREG_R1)
-                       ARM_MOV_REG_REG (code, ARMREG_R1, sreg);
-               if (tls_offset_reg != ARMREG_R0)
-                       ARM_MOV_REG_REG (code, ARMREG_R0, tls_offset_reg);
-       }
-       mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
-                       "mono_set_tls_key");
-       code = emit_call_seq (cfg, code);
-#else
-       g_assert_not_reached ();
-#endif
+       int tp_reg = (sreg != ARMREG_R0) ? ARMREG_R0 : ARMREG_R1;
+       ARM_MRC (code, 15, 0, tp_reg, 13, 0, 3);
+       ARM_STR_IMM (code, sreg, tp_reg, tls_offset);
        return code;
 }
 
@@ -414,31 +382,13 @@ mono_arm_emit_tls_set_reg (MonoCompile *cfg, guint8* code, int sreg, int tls_off
 static guint8*
 emit_save_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset)
 {
-       gboolean get_lmf_fast = FALSE;
        int i;
 
-       if (mono_arm_have_tls_get ()) {
-               get_lmf_fast = TRUE;
-               if (cfg->compile_aot) {
-                       /* OP_AOTCONST */
-                       mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_TLS_OFFSET, (gpointer)TLS_KEY_LMF_ADDR);
-                       ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 0);
-                       ARM_B (code, 0);
-                       *(gpointer*)code = NULL;
-                       code += 4;
-                       /* Load the value from the GOT */
-                       ARM_LDR_REG_REG (code, ARMREG_R1, ARMREG_PC, ARMREG_R1);
-                       code = mono_arm_emit_tls_get_reg (cfg, code, ARMREG_R0, ARMREG_R1);
-               } else {
-                       gint32 lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset ();
-                       g_assert (lmf_addr_tls_offset != -1);
-                       code = mono_arm_emit_tls_get (cfg, code, ARMREG_R0, lmf_addr_tls_offset);
-               }
-       }
-
-       if (!get_lmf_fast) {
-               mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
-                                                        (gpointer)"mono_get_lmf_addr");
+       if (mono_arch_have_fast_tls () && mono_tls_get_tls_offset (TLS_KEY_LMF_ADDR) != -1) {
+               code = emit_tls_get (code, ARMREG_R0, mono_tls_get_tls_offset (TLS_KEY_LMF_ADDR));
+       } else {
+               mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
+                                                        (gpointer)"mono_tls_get_lmf_addr");
                code = emit_call_seq (cfg, code);
        }
        /* we build the MonoLMF structure on the stack - see mini-arm.h */
@@ -581,22 +531,6 @@ emit_restore_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset)
 
 #endif /* #ifndef DISABLE_JIT */
 
-/*
- * mono_arm_have_tls_get:
- *
- * Returns whether we have tls access implemented on the current
- * platform
- */
-gboolean
-mono_arm_have_tls_get (void)
-{
-#ifdef HAVE_FAST_TLS
-       return TRUE;
-#else
-       return FALSE;
-#endif
-}
-
 /*
  * mono_arch_get_argument_info:
  * @csig:  a method signature
@@ -836,8 +770,8 @@ mono_arch_init (void)
                if (!mono_aot_only)
                        breakpoint_tramp = mini_get_breakpoint_trampoline ();
        } else {
-               ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
-               bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
+               ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT, MONO_MEM_ACCOUNT_OTHER);
+               bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT, MONO_MEM_ACCOUNT_OTHER);
                mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
        }
 
@@ -848,7 +782,7 @@ mono_arch_init (void)
        mono_aot_register_jit_icall ("mono_arm_start_gsharedvt_call", mono_arm_start_gsharedvt_call);
 #endif
        mono_aot_register_jit_icall ("mono_arm_unaligned_stack", mono_arm_unaligned_stack);
-
+       mono_aot_register_jit_icall ("mono_arm_handler_block_trampoline_helper", mono_arm_handler_block_trampoline_helper);
 #if defined(__ARM_EABI__)
        eabi_supported = TRUE;
 #endif
@@ -858,7 +792,7 @@ mono_arch_init (void)
 #else
        arm_fpu = MONO_ARM_FPU_VFP;
 
-#if defined(ARM_FPU_NONE) && !defined(__APPLE__)
+#if defined(ARM_FPU_NONE) && !defined(TARGET_IOS)
        /*
         * If we're compiling with a soft float fallback and it
         * turns out that no VFP unit is available, we need to
@@ -878,6 +812,7 @@ mono_arch_init (void)
 
        if (soft && !strncmp (soft, "1", 1))
                arm_fpu = MONO_ARM_FPU_NONE;
+       g_free (soft);
 #endif
 #endif
 
@@ -900,7 +835,7 @@ mono_arch_init (void)
        v7_supported = TRUE;
 #endif
 
-#if defined(__APPLE__)
+#if defined(TARGET_IOS)
        /* iOS is special-cased here because we don't yet
           have a way to properly detect CPU features on it. */
        thumb_supported = TRUE;
@@ -925,6 +860,7 @@ mono_arch_init (void)
 
                thumb_supported = strstr (cpu_arch, "thumb") != NULL;
                thumb2_supported = strstr (cpu_arch, "thumb2") != NULL;
+               g_free (cpu_arch);
        }
 }
 
@@ -1008,10 +944,6 @@ is_regsize_var (MonoType *t)
        case MONO_TYPE_FNPTR:
                return TRUE;
        case MONO_TYPE_OBJECT:
-       case MONO_TYPE_STRING:
-       case MONO_TYPE_CLASS:
-       case MONO_TYPE_SZARRAY:
-       case MONO_TYPE_ARRAY:
                return TRUE;
        case MONO_TYPE_GENERICINST:
                if (!mono_type_generic_inst_is_valuetype (t))
@@ -1336,11 +1268,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
        case MONO_TYPE_U:
        case MONO_TYPE_PTR:
        case MONO_TYPE_FNPTR:
-       case MONO_TYPE_CLASS:
        case MONO_TYPE_OBJECT:
-       case MONO_TYPE_SZARRAY:
-       case MONO_TYPE_ARRAY:
-       case MONO_TYPE_STRING:
                cinfo->ret.storage = RegTypeGeneral;
                cinfo->ret.reg = ARMREG_R0;
                break;
@@ -1489,11 +1417,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
                case MONO_TYPE_U:
                case MONO_TYPE_PTR:
                case MONO_TYPE_FNPTR:
-               case MONO_TYPE_CLASS:
                case MONO_TYPE_OBJECT:
-               case MONO_TYPE_STRING:
-               case MONO_TYPE_SZARRAY:
-               case MONO_TYPE_ARRAY:
                        cinfo->args [n].size = sizeof (gpointer);
                        add_general (&gr, &stack_size, ainfo, TRUE);
                        break;
@@ -1582,6 +1506,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
                        nwords = (align_size + sizeof (gpointer) -1 ) / sizeof (gpointer);
                        ainfo->storage = RegTypeStructByVal;
                        ainfo->struct_size = size;
+                       ainfo->align = align;
                        /* FIXME: align stack_size if needed */
                        if (eabi_supported) {
                                if (align >= 8 && (gr & 1))
@@ -1713,8 +1638,7 @@ debug_omit_fp (void)
 
 /**
  * mono_arch_compute_omit_fp:
- *
- *   Determine whenever the frame pointer can be eliminated.
+ * Determine whether the frame pointer can be eliminated.
  */
 static void
 mono_arch_compute_omit_fp (MonoCompile *cfg)
@@ -2206,6 +2130,11 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
                linfo->ret.nslots = cinfo->ret.nregs;
                break;
 #endif
+       case RegTypeHFA:
+               linfo->ret.storage = LLVMArgFpStruct;
+               linfo->ret.nslots = cinfo->ret.nregs;
+               linfo->ret.esize = cinfo->ret.esize;
+               break;
        default:
                cfg->exception_message = g_strdup_printf ("unknown ret conv (%d)", cinfo->ret.storage);
                cfg->disable_llvm = TRUE;
@@ -2228,12 +2157,31 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
                        break;
                case RegTypeStructByVal:
                        lainfo->storage = LLVMArgAsIArgs;
-                       lainfo->nslots = ainfo->struct_size / sizeof (gpointer);
+                       if (eabi_supported && ainfo->align == 8) {
+                               /* LLVM models this by passing an int64 array */
+                               lainfo->nslots = ALIGN_TO (ainfo->struct_size, 8) / 8;
+                               lainfo->esize = 8;
+                       } else {
+                               lainfo->nslots = ainfo->struct_size / sizeof (gpointer);
+                               lainfo->esize = 4;
+                       }
+
+                       printf ("D: %d\n", ainfo->align);
                        break;
                case RegTypeStructByAddr:
                case RegTypeStructByAddrOnStack:
                        lainfo->storage = LLVMArgVtypeByRef;
                        break;
+               case RegTypeHFA: {
+                       int j;
+
+                       lainfo->storage = LLVMArgAsFpArgs;
+                       lainfo->nslots = ainfo->nregs;
+                       lainfo->esize = ainfo->esize;
+                       for (j = 0; j < ainfo->nregs; ++j)
+                               lainfo->pair_storage [j] = LLVMArgInFPReg;
+                       break;
+               }
                default:
                        cfg->exception_message = g_strdup_printf ("ainfo->storage (%d)", ainfo->storage);
                        cfg->disable_llvm = TRUE;
@@ -2842,10 +2790,6 @@ mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, g
                }
 
                switch (t->type) {
-               case MONO_TYPE_STRING:
-               case MONO_TYPE_CLASS:  
-               case MONO_TYPE_ARRAY:
-               case MONO_TYPE_SZARRAY:
                case MONO_TYPE_OBJECT:
                case MONO_TYPE_PTR:
                case MONO_TYPE_I:
@@ -2947,10 +2891,6 @@ mono_arch_finish_dyn_call (MonoDynCallInfo *info, guint8 *buf)
        case MONO_TYPE_VOID:
                *(gpointer*)ret = NULL;
                break;
-       case MONO_TYPE_STRING:
-       case MONO_TYPE_CLASS:  
-       case MONO_TYPE_ARRAY:
-       case MONO_TYPE_SZARRAY:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_I:
        case MONO_TYPE_U:
@@ -4265,16 +4205,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        }
                        break;
                case OP_TLS_GET:
-                       code = mono_arm_emit_tls_get (cfg, code, ins->dreg, ins->inst_offset);
-                       break;
-               case OP_TLS_GET_REG:
-                       code = mono_arm_emit_tls_get_reg (cfg, code, ins->dreg, ins->sreg1);
+                       code = emit_tls_get (code, ins->dreg, ins->inst_offset);
                        break;
                case OP_TLS_SET:
-                       code = mono_arm_emit_tls_set (cfg, code, ins->sreg1, ins->inst_offset);
-                       break;
-               case OP_TLS_SET_REG:
-                       code = mono_arm_emit_tls_set_reg (cfg, code, ins->sreg1, ins->sreg2);
+                       code = emit_tls_set (code, ins->sreg1, ins->inst_offset);
                        break;
                case OP_ATOMIC_EXCHANGE_I4:
                case OP_ATOMIC_CAS_I4:
@@ -4442,14 +4376,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                ARM_DMB (code, ARM_DMB_SY);
                        break;
                }
-               /*case OP_BIGMUL:
-                       ppc_mullw (code, ppc_r4, ins->sreg1, ins->sreg2);
-                       ppc_mulhw (code, ppc_r3, ins->sreg1, ins->sreg2);
+               case OP_BIGMUL:
+                       ARM_SMULL_REG_REG (code, ins->backend.reg3, ins->dreg, ins->sreg1, ins->sreg2);
                        break;
                case OP_BIGMUL_UN:
-                       ppc_mullw (code, ppc_r4, ins->sreg1, ins->sreg2);
-                       ppc_mulhwu (code, ppc_r3, ins->sreg1, ins->sreg2);
-                       break;*/
+                       ARM_UMULL_REG_REG (code, ins->backend.reg3, ins->dreg, ins->sreg1, ins->sreg2);
+                       break;
                case OP_STOREI1_MEMBASE_IMM:
                        code = mono_arm_emit_load_imm (code, ARMREG_LR, ins->inst_imm & 0xFF);
                        g_assert (arm_is_imm12 (ins->inst_offset));
@@ -5134,19 +5066,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        break;
                }
                case OP_GENERIC_CLASS_INIT: {
-                       static int byte_offset = -1;
-                       static guint8 bitmask;
-                       guint32 imm8;
+                       int byte_offset;
                        guint8 *jump;
 
-                       if (byte_offset < 0)
-                               mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
+                       byte_offset = MONO_STRUCT_OFFSET (MonoVTable, initialized);
 
                        g_assert (arm_is_imm8 (byte_offset));
                        ARM_LDRSB_IMM (code, ARMREG_IP, ins->sreg1, byte_offset);
-                       imm8 = mono_arm_is_rotated_imm8 (bitmask, &rot_amount);
-                       g_assert (imm8 >= 0);
-                       ARM_AND_REG_IMM (code, ARMREG_IP, ARMREG_IP, imm8, rot_amount);
                        ARM_CMP_REG_IMM (code, ARMREG_IP, 0, 0);
                        jump = code;
                        ARM_B_COND (code, ARMCOND_NE, 0);
@@ -5983,38 +5909,6 @@ mono_arch_register_lowlevel_calls (void)
        mono_register_jit_icall (mono_arm_throw_exception, "mono_arm_throw_exception", mono_create_icall_signature ("void"), TRUE);
        mono_register_jit_icall (mono_arm_throw_exception_by_token, "mono_arm_throw_exception_by_token", mono_create_icall_signature ("void"), TRUE);
        mono_register_jit_icall (mono_arm_unaligned_stack, "mono_arm_unaligned_stack", mono_create_icall_signature ("void"), TRUE);
-
-#ifndef MONO_CROSS_COMPILE
-       if (mono_arm_have_tls_get ()) {
-               MonoTlsImplementation tls_imp = mono_arm_get_tls_implementation ();
-
-               mono_register_jit_icall (tls_imp.get_tls_thunk, "mono_get_tls_key", mono_create_icall_signature ("ptr ptr"), TRUE);
-               mono_register_jit_icall (tls_imp.set_tls_thunk, "mono_set_tls_key", mono_create_icall_signature ("void ptr ptr"), TRUE);
-
-               if (tls_imp.get_tls_thunk_end) {
-                       mono_tramp_info_register (
-                               mono_tramp_info_create (
-                                       "mono_get_tls_key",
-                                       (guint8*)tls_imp.get_tls_thunk,
-                                       (guint8*)tls_imp.get_tls_thunk_end - (guint8*)tls_imp.get_tls_thunk,
-                                       NULL,
-                                       mono_arch_get_cie_program ()
-                                       ),
-                               NULL
-                               );
-                       mono_tramp_info_register (
-                               mono_tramp_info_create (
-                                       "mono_set_tls_key",
-                                       (guint8*)tls_imp.set_tls_thunk,
-                                       (guint8*)tls_imp.set_tls_thunk_end - (guint8*)tls_imp.set_tls_thunk,
-                                       NULL,
-                                       mono_arch_get_cie_program ()
-                                       ),
-                               NULL
-                               );
-               }
-       }
-#endif
 }
 
 #define patch_lis_ori(ip,val) do {\
@@ -6924,7 +6818,7 @@ mini_dump_bad_imt (int input_imt, int compared_imt, int pc)
 #endif
 
 gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
        gpointer fail_tramp)
 {
        int size, i;
@@ -6976,7 +6870,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                size += 4 * count; /* The ARM_ADD_REG_IMM to pop the stack */
 
        if (fail_tramp)
-               code = mono_method_alloc_generic_virtual_thunk (domain, size);
+               code = mono_method_alloc_generic_virtual_trampoline (domain, size);
        else
                code = mono_domain_code_reserve (domain, size);
        start = code;
@@ -6984,7 +6878,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        unwind_ops = mono_arch_get_cie_program ();
 
 #ifdef DEBUG_IMT
-       g_print ("Building IMT thunk for class %s %s entries %d code size %d code at %p end %p vtable %p fail_tramp %p\n", vtable->klass->name_space, vtable->klass->name, count, size, start, ((guint8*)start) + size, vtable, fail_tramp);
+       g_print ("Building IMT trampoline for class %s %s entries %d code size %d code at %p end %p vtable %p fail_tramp %p\n", vtable->klass->name_space, vtable->klass->name, count, size, start, ((guint8*)start) + size, vtable, fail_tramp);
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
                g_print ("method %d (%p) %s vtable slot %p is_equals %d chunk size %d\n", i, item->key, ((MonoMethod*)item->key)->name, &vtable->vtable [item->value.vtable_slot], item->is_equals, item->chunk_size);
@@ -7150,7 +7044,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
 
        mono_arch_flush_icache ((guint8*)start, size);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
-       mono_stats.imt_thunks_size += code - start;
+       mono_stats.imt_trampolines_size += code - start;
 
        g_assert (DISTANCE (start, code) <= size);
 
@@ -7514,3 +7408,37 @@ mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
 {
        return get_call_info (mp, sig);
 }
+
+gpointer
+mono_arch_get_get_tls_tramp (void)
+{
+       return NULL;
+}
+
+static guint8*
+emit_aotconst (MonoCompile *cfg, guint8 *code, int dreg, int patch_type, gpointer data)
+{
+       /* OP_AOTCONST */
+       mono_add_patch_info (cfg, code - cfg->native_code, patch_type, data);
+       ARM_LDR_IMM (code, dreg, ARMREG_PC, 0);
+       ARM_B (code, 0);
+       *(gpointer*)code = NULL;
+       code += 4;
+       /* Load the value from the GOT */
+       ARM_LDR_REG_REG (code, dreg, ARMREG_PC, dreg);
+       return code;
+}
+
+guint8*
+mono_arm_emit_aotconst (gpointer ji_list, guint8 *code, guint8 *buf, int dreg, int patch_type, gconstpointer data)
+{
+       MonoJumpInfo **ji = (MonoJumpInfo**)ji_list;
+
+       *ji = mono_patch_info_list_prepend (*ji, code - buf, patch_type, data);
+       ARM_LDR_IMM (code, dreg, ARMREG_PC, 0);
+       ARM_B (code, 0);
+       *(gpointer*)code = NULL;
+       code += 4;
+       ARM_LDR_REG_REG (code, dreg, ARMREG_PC, dreg);
+       return code;
+}