Fix the BSD build.
[mono.git] / mono / mini / mini.c
index 7676119f29cdac89778542704ca838da393804d3..397fcf0f0dae3d0627991e6fe75fb61a519962b9 100644 (file)
@@ -114,8 +114,7 @@ static int methods_with_llvm, methods_without_llvm;
 /*
  * This flag controls whenever the runtime uses LLVM compiled code.
  * Enabling this causes different/slower code paths to be used, which is why it
- * defaults to FALSE if ENABLE_LLVM is not defined, i.e. the runtime is only capable of
- * running AOT code compiled by LLVM.
+ * defaults to FALSE.
  * Changes when this flag is set include:
  * - a per method vtable trampoline is used to handle virtual calls, instead of only
  *   one trampoline.
@@ -402,6 +401,34 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 {
        return mono_jump_info_token_new2 (mp, image, token, NULL);
 }
+/*
+ * mono_tramp_info_create:
+ *
+ *   Create a MonoTrampInfo structure from the arguments. This function assumes ownership
+ * of NAME, JI, and UNWIND_OPS.
+ */
+MonoTrampInfo*
+mono_tramp_info_create (const char *name, guint8 *code, guint32 code_size, MonoJumpInfo *ji, GSList *unwind_ops)
+{
+       MonoTrampInfo *info = g_new0 (MonoTrampInfo, 1);
+
+       info->name = (char*)name;
+       info->code = code;
+       info->code_size = code_size;
+       info->ji = ji;
+       info->unwind_ops = unwind_ops;
+
+       return info;
+}
+
+void
+mono_tramp_info_free (MonoTrampInfo *info)
+{
+       g_free (info->name);
+
+       // FIXME: ji + unwind_ops
+}
 
 #define MONO_INIT_VARINFO(vi,id) do { \
        (vi)->range.first_use.pos.bid = 0xffff; \
@@ -2467,18 +2494,19 @@ static MonoInst*
 mono_create_tls_get (MonoCompile *cfg, int offset)
 {
 #ifdef MONO_ARCH_HAVE_TLS_GET
-       MonoInst* ins;
-       
-       if (offset == -1)
-               return NULL;
-       
-       MONO_INST_NEW (cfg, ins, OP_TLS_GET);
-       ins->dreg = mono_alloc_preg (cfg);
-       ins->inst_offset = offset;
-       return ins;
-#else
-       return NULL;
+       if (MONO_ARCH_HAVE_TLS_GET) {
+               MonoInst* ins;
+
+               if (offset == -1)
+                       return NULL;
+
+               MONO_INST_NEW (cfg, ins, OP_TLS_GET);
+               ins->dreg = mono_alloc_preg (cfg);
+               ins->inst_offset = offset;
+               return ins;
+       }
 #endif
+       return NULL;
 }
 
 MonoInst*
@@ -3482,6 +3510,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                table->num_holes = (guint16)num_holes;
                i = 0;
                for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
+                       guint32 start_bb_offset;
                        MonoTryBlockHoleJitInfo *hole;
                        TryBlockHole *hole_data = tmp->data;
                        MonoExceptionClause *ec = hole_data->clause;
@@ -3493,40 +3522,16 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                        if (clause_last_bb->native_offset == hole_end)
                                continue;
 
+                       start_bb_offset = hole_data->start_offset - hole_data->basic_block->native_offset;
                        hole = &table->holes [i++];
                        hole->clause = hole_data->clause - &header->clauses [0];
                        hole->offset = (guint32)hole_data->start_offset;
-                       hole->length = (guint16)(hole_data->basic_block->native_length - hole_data->start_offset);
-               }
-               g_assert (i == num_holes);
-       }
-
-       if (G_UNLIKELY (header->num_clauses && cfg->verbose_level >= 4)) {
-               GSList *tmp;
-               int i;
-               printf ("\nException Handling Data\n");
-               for (i = 0; i < header->num_clauses; i++) {
-                       MonoExceptionClause *ec = &header->clauses [i];
-                       int try_start = cfg->cil_offset_to_bb [ec->try_offset]->native_offset;
-                       int try_end  = cfg->cil_offset_to_bb [ec->try_offset + ec->try_len]->native_offset;
-                       int handler_start = cfg->cil_offset_to_bb [ec->handler_offset]->native_offset;
-                       int handler_end;
-                       if (ec->handler_offset + ec->handler_len < header->code_size)
-                               handler_end =  cfg->cil_offset_to_bb [ec->handler_offset + ec->handler_len]->native_offset;
-                       else
-                               handler_end = cfg->epilog_begin;
+                       hole->length = (guint16)(hole_data->basic_block->native_length - start_bb_offset);
 
-                       printf ("EH clause %d flags %x try IL %x-%x NATIVE %x-%x handler IL %x-%x NATIVE %x-%x\n",
-                               i, ec->flags,
-                               ec->try_offset, ec->try_offset + ec->try_len, try_start, try_end,
-                               ec->handler_offset, ec->handler_offset + ec->handler_len, handler_start, handler_end);
-               }
-               for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
-                       TryBlockHole *hole = tmp->data;
-                       int block = hole->clause - &header->clauses [0];
-                       printf ("try block hole at eh clause %d range %x-%x\n",
-                               block, hole->start_offset, hole->basic_block->native_offset + hole->basic_block->native_length);
+                       if (G_UNLIKELY (cfg->verbose_level >= 4))
+                               printf ("\tTry block hole at eh clause %d offset %x length %x\n", hole->clause, hole->offset, hole->length);
                }
+               g_assert (i == num_holes);
        }
 
        if (COMPILE_LLVM (cfg)) {
@@ -3571,17 +3576,34 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                                gpointer hole_end = cfg->native_code + (hole->basic_block->native_offset + hole->basic_block->native_length);
                                if (hole->clause == ec && hole_end == ei->try_end) {
                                        if (G_UNLIKELY (cfg->verbose_level >= 4))
-                                               printf ("\tShortening try block %d from %p to %p\n", i, ei->try_end, cfg->native_code + hole->start_offset);
+                                               printf ("\tShortening try block %d from %x to %x\n", i, (int)((guint8*)ei->try_end - cfg->native_code), hole->start_offset);
+
                                        ei->try_end = cfg->native_code + hole->start_offset;
                                        break;
                                }
                        }
+
+                       if (ec->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
+                               int end_offset;
+                               if (ec->handler_offset + ec->handler_len < header->code_size) {
+                                       tblock = cfg->cil_offset_to_bb [ec->handler_offset + ec->handler_len];
+                                       g_assert (tblock);
+                                       end_offset = tblock->native_offset;
+                               } else {
+                                       end_offset = cfg->epilog_begin;
+                               }
+                               ei->data.handler_end = cfg->native_code + end_offset;
+                       }
                }
 
                if (G_UNLIKELY (cfg->verbose_level >= 4)) {
                        for (i = 0; i < jinfo->num_clauses; i++) {
                                MonoJitExceptionInfo *ei = &jinfo->clauses [i];
-                               printf ("JitInfo EH clause %d flags %x try %p-%p handler %p\n", i, ei->flags, ei->try_start, ei->try_end, ei->handler_start);
+                               int start = (guint8*)ei->try_start - cfg->native_code;
+                               int end = (guint8*)ei->try_end - cfg->native_code;
+                               int handler = (guint8*)ei->handler_start - cfg->native_code;
+
+                               printf ("JitInfo EH clause %d flags %x try %x-%x handler %x\n", i, ei->flags, start, end, handler);
                        }
                }
 
@@ -3606,6 +3628,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
 
        return jinfo;
 }
+#endif
 
 /*
  * mini_get_shared_method:
@@ -3678,6 +3701,7 @@ mini_get_shared_method (MonoMethod *method)
        return res;
 }
 
+#ifndef DISABLE_JIT
 /*
  * mini_method_compile:
  * @method: the method to compile
@@ -3802,9 +3826,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                cfg->exception_type = MONO_EXCEPTION_TYPE_LOAD;
                cfg->exception_message = g_strdup (mono_error_get_message (&err));
                mono_error_cleanup (&err);
-               return cfg;
                if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
                        MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
+               return cfg;
        }
 
        header = cfg->header;
@@ -3822,11 +3846,10 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                return cfg;
        }
 
-       if (FALSE && header->clauses) {
-               /* 
-                * Cannot be enabled until LLVM supports implicit exceptions, or we use
-                * explicit checks, or we disable this for methods which might throw implicit
-                * exceptions inside clauses.
+       if (header->clauses) {
+               /*
+                * FIXME: LLLVM 2.6/SVN no longer seems to generate correct exception info
+                * for JITted code.
                 */
                cfg->exception_message = g_strdup ("clauses");
                cfg->disable_llvm = TRUE;
@@ -4274,7 +4297,10 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                mono_decompose_array_access_opts (cfg);
 
        if (cfg->got_var) {
+#ifndef MONO_ARCH_GOT_REG
                GList *regs;
+#endif
+               int got_reg;
 
                g_assert (cfg->got_var_allocated);
 
@@ -4285,13 +4311,17 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                 * branches problem. Testcase: mcs crash in 
                 * System.MonoCustomAttrs:GetCustomAttributes.
                 */
+#ifdef MONO_ARCH_GOT_REG
+               got_reg = MONO_ARCH_GOT_REG;
+#else
                regs = mono_arch_get_global_int_regs (cfg);
                g_assert (regs);
+               got_reg = GPOINTER_TO_INT (regs->data);
+               g_list_free (regs);
+#endif
                cfg->got_var->opcode = OP_REGVAR;
-               cfg->got_var->dreg = GPOINTER_TO_INT (regs->data);
+               cfg->got_var->dreg = got_reg;
                cfg->used_int_regs |= 1LL << cfg->got_var->dreg;
-               
-               g_list_free (regs);
        }
 
        /*
@@ -4310,7 +4340,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        }
 
        if ((cfg->opt & MONO_OPT_LINEARS) && !cfg->globalra) {
-               GList *vars, *regs;
+               GList *vars, *regs, *l;
                
                /* fixme: maybe we can avoid to compute livenesss here if already computed ? */
                cfg->comp_done &= ~MONO_COMP_LIVENESS;
@@ -4319,8 +4349,15 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
 
                if ((vars = mono_arch_get_allocatable_int_vars (cfg))) {
                        regs = mono_arch_get_global_int_regs (cfg);
-                       if (cfg->got_var)
-                               regs = g_list_delete_link (regs, regs);
+                       /* Remove the reg reserved for holding the GOT address */
+                       if (cfg->got_var) {
+                               for (l = regs; l; l = l->next) {
+                                       if (GPOINTER_TO_UINT (l->data) == cfg->got_var->dreg) {
+                                               regs = g_list_delete_link (regs, l);
+                                               break;
+                                       }
+                               }
+                       }
                        mono_linear_scan (cfg, vars, regs, &cfg->used_int_regs);
                }
        }
@@ -4611,6 +4648,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        }
 #endif
 
+#ifndef DISABLE_JIT
        if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
            (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
                MonoMethod *nm;
@@ -4669,6 +4707,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                }
                return NULL;
        }
+#endif
 
        if (mono_aot_only) {
                char *fullname = mono_method_full_name (method, TRUE);
@@ -4796,6 +4835,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 
        mono_destroy_compile (cfg);
 
+#ifndef DISABLE_JIT
        if (domain_jit_info (target_domain)->jump_target_hash) {
                MonoJumpInfo patch_info;
                GSList *list, *tmp;
@@ -4813,6 +4853,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        }
 
        mono_emit_jit_map (jinfo);
+#endif
        mono_domain_unlock (target_domain);
        mono_loader_unlock ();
 
@@ -4825,11 +4866,15 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        }
 
        if (prof_options & MONO_PROFILE_JIT_COMPILATION) {
-               if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
-                       /* The profiler doesn't know about wrappers, so pass the original icall method */
-                       mono_profiler_method_end_jit (mono_marshal_method_from_wrapper (method), jinfo, MONO_PROFILE_OK);
-               else
+               if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
+                       if (mono_marshal_method_from_wrapper (method)) {
+                               /* Native func wrappers have no method */
+                               /* The profiler doesn't know about wrappers, so pass the original icall method */
+                               mono_profiler_method_end_jit (mono_marshal_method_from_wrapper (method), jinfo, MONO_PROFILE_OK);
+                       }
+               } else {
                        mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
+               }
        }
 
        mono_runtime_class_init (vtable);
@@ -5671,8 +5716,6 @@ mini_init (const char *filename, const char *runtime_version)
        if (!g_thread_supported ())
                g_thread_init (NULL);
 
-       mono_gc_base_init ();
-
        mono_jit_tls_id = TlsAlloc ();
        setup_jit_tls_data ((gpointer)-1, mono_thread_abort);