2008-03-20 Mark Probst <mark.probst@gmail.com>
[mono.git] / mono / mini / aot-runtime.c
index 9d30751635390f1851100cfda26f0053159b5832..c3d63f6517e7b16659bcc18ca5311f186aac6081 100644 (file)
@@ -150,13 +150,7 @@ init_plt (MonoAotModule *info);
 static inline gboolean 
 is_got_patch (MonoJumpInfoType patch_type)
 {
-#ifdef __x86_64__
        return TRUE;
-#elif defined(__i386__)
-       return TRUE;
-#else
-       return FALSE;
-#endif
 }
 
 /*****************************************************/
@@ -736,6 +730,7 @@ decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guin
 gboolean
 mono_aot_init_vtable (MonoVTable *vtable)
 {
+#ifdef MONO_ARCH_COMMON_VTABLE_TRAMPOLINE
        int i;
        MonoAotModule *aot_module;
        MonoClass *klass = vtable->klass;
@@ -765,7 +760,6 @@ mono_aot_init_vtable (MonoVTable *vtable)
 
        mono_aot_unlock ();
 
-#ifdef MONO_ARCH_COMMON_VTABLE_TRAMPOLINE
        //printf ("VT0: %s.%s %d\n", klass->name_space, klass->name, vtable_size);
        for (i = 0; i < class_info.vtable_size; ++i) {
                vtable->vtable [i] = mini_get_vtable_trampoline ();
@@ -1159,7 +1153,8 @@ decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji,
        switch (ji->type) {
        case MONO_PATCH_INFO_METHOD:
        case MONO_PATCH_INFO_METHODCONST:
-       case MONO_PATCH_INFO_METHOD_JUMP: {
+       case MONO_PATCH_INFO_METHOD_JUMP:
+       case MONO_PATCH_INFO_ICALL_ADDR: {
                guint32 token;
 
                image = decode_method_ref (aot_module, &token, p, &p);
@@ -1219,8 +1214,6 @@ decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji,
                case MONO_WRAPPER_LDFLD:
                case MONO_WRAPPER_LDFLDA:
                case MONO_WRAPPER_STFLD:
-               case MONO_WRAPPER_LDFLD_REMOTE:
-               case MONO_WRAPPER_STFLD_REMOTE:
                case MONO_WRAPPER_ISINST: {
                        MonoClass *klass = decode_klass_ref (aot_module, p, &p);
                        if (!klass)
@@ -1232,16 +1225,18 @@ decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji,
                                ji->data.method = mono_marshal_get_ldflda_wrapper (&klass->byval_arg);
                        else if (wrapper_type == MONO_WRAPPER_STFLD)
                                ji->data.method = mono_marshal_get_stfld_wrapper (&klass->byval_arg);
-                       else if (wrapper_type == MONO_WRAPPER_LDFLD_REMOTE)
-                               ji->data.method = mono_marshal_get_ldfld_remote_wrapper (klass);
-                       else if (wrapper_type == MONO_WRAPPER_STFLD_REMOTE)
-                               ji->data.method = mono_marshal_get_stfld_remote_wrapper (klass);
                        else if (wrapper_type == MONO_WRAPPER_ISINST)
                                ji->data.method = mono_marshal_get_isinst (klass);
                        else
                                g_assert_not_reached ();
                        break;
                }
+               case MONO_WRAPPER_LDFLD_REMOTE:
+                       ji->data.method = mono_marshal_get_ldfld_remote_wrapper (NULL);
+                       break;
+               case MONO_WRAPPER_STFLD_REMOTE:
+                       ji->data.method = mono_marshal_get_stfld_remote_wrapper (NULL);
+                       break;
                case MONO_WRAPPER_ALLOC: {
                        int atype = decode_value (p, &p);
 
@@ -1970,7 +1965,7 @@ mono_aot_handle_pagefault (void *ptr)
 gpointer
 mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code)
 {
-#ifdef MONO_ARCH_HAVE_PIC_AOT
+#ifdef MONO_ARCH_AOT_SUPPORTED
        guint8 *p, *target, *plt_entry;
        MonoJumpInfo ji;
        MonoAotModule *module = (MonoAotModule*)aot_module;
@@ -2010,11 +2005,12 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code
 static void
 init_plt (MonoAotModule *info)
 {
-#ifdef MONO_ARCH_HAVE_PIC_AOT
+#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 +2035,21 @@ init_plt (MonoAotModule *info)
         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
@@ -2056,6 +2067,9 @@ guint8*
 mono_aot_get_plt_entry (guint8 *code)
 {
        MonoAotModule *aot_module = find_aot_module (code);
+#if defined(__arm__)
+       guint32 ins;
+#endif
 
        if (!aot_module)
                return NULL;
@@ -2068,6 +2082,19 @@ mono_aot_get_plt_entry (guint8 *code)
                if ((target >= (guint8*)(aot_module->plt)) && (target < (guint8*)(aot_module->plt_end)))
                        return target;
        }
+#elif defined(__arm__)
+       ins = ((guint32*)(gpointer)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;