2010-02-10 Miguel de Icaza <miguel@novell.com>
[mono.git] / mono / mini / mini-llvm.c
index d899d95252baf473e57e1ab8a0dba5e35e4c3495..ec83b7a13f95b699cd1f0268c3e9c3eb6ddfa845 100644 (file)
@@ -167,6 +167,9 @@ static LLVMExecutionEngineRef ee;
 static guint32 current_cfg_tls_id;
 
 static MonoLLVMModule jit_module, aot_module;
+static gboolean jit_module_inited;
+
+static void init_jit_module (void);
 
 /*
  * IntPtrType:
@@ -945,6 +948,8 @@ get_plt_entry (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gc
        if (!callee) {
                callee = LLVMAddFunction (ctx->module, callee_name, llvm_sig);
 
+               LLVMSetVisibility (callee, LLVMHiddenVisibility);
+
                g_hash_table_insert (ctx->lmodule->plt_entries, (char*)callee_name, callee);
        }
 
@@ -1281,6 +1286,11 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder, int *pindexes)
                        ctx->addresses [reg] = build_alloca (ctx, sig->params [i]);
 
                        emit_reg_to_vtype (ctx, builder, sig->params [i], ctx->addresses [reg], ainfo, regs);
+
+                       if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (sig->params [i]))) {
+                               /* Treat these as normal values */
+                               ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "");
+                       }
                } else if (ainfo->storage == LLVMArgVtypeByVal) {
                        ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindexes [i]);
                } else {
@@ -1399,6 +1409,7 @@ mono_llvm_emit_method (MonoCompile *cfg)
                method_name = mono_aot_get_method_name (cfg);
                debug_name = mono_aot_get_method_debug_name (cfg);
        } else {
+               init_jit_module ();
                ctx->lmodule = &jit_module;
                method_name = mono_method_full_name (cfg->method, TRUE);
                debug_name = NULL;
@@ -1643,6 +1654,9 @@ mono_llvm_emit_method (MonoCompile *cfg)
                                type_info = LLVMAddGlobal (module, LLVMInt32Type (), ti_name);
                                LLVMSetInitializer (type_info, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE));
 
+                               LLVMSetLinkage (type_info, LLVMPrivateLinkage);
+                               LLVMSetVisibility (type_info, LLVMHiddenVisibility);
+
                                /* 
                                 * FIXME: llc currently generates incorrect data in the LSDA:
                                 *      .byte   0x9B                                        # @TType format (indirect pcrel sdata4)
@@ -2462,15 +2476,21 @@ mono_llvm_emit_method (MonoCompile *cfg)
                        case OP_STORER8_MEMBASE_REG:
                        case OP_STORE_MEMBASE_REG: {
                                int size = 8;
-                               LLVMValueRef index;
+                               LLVMValueRef index, addr;
                                LLVMTypeRef t;
                                gboolean sext = FALSE, zext = FALSE;
 
                                t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
 
-                               g_assert (ins->inst_offset % size == 0);
-                               index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);                                
-                               LLVMBuildStore (builder, convert (ctx, values [ins->sreg1], t), LLVMBuildGEP (builder, convert (ctx, values [ins->inst_destbasereg], LLVMPointerType (t, 0)), &index, 1, ""));
+                               if (ins->inst_offset % size != 0) {
+                                       /* Unaligned store */
+                                       index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
+                                       addr = LLVMBuildGEP (builder, convert (ctx, values [ins->inst_destbasereg], LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
+                               } else {
+                                       index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);                                
+                                       addr = LLVMBuildGEP (builder, convert (ctx, values [ins->inst_destbasereg], LLVMPointerType (t, 0)), &index, 1, "");
+                               }
+                               LLVMBuildStore (builder, convert (ctx, values [ins->sreg1], t), convert (ctx, addr, LLVMPointerType (t, 0)));
                                break;
                        }
 
@@ -2480,15 +2500,21 @@ mono_llvm_emit_method (MonoCompile *cfg)
                        case OP_STOREI8_MEMBASE_IMM:
                        case OP_STORE_MEMBASE_IMM: {
                                int size = 8;
-                               LLVMValueRef index;
+                               LLVMValueRef index, addr;
                                LLVMTypeRef t;
                                gboolean sext = FALSE, zext = FALSE;
 
                                t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
 
-                               g_assert (ins->inst_offset % size == 0);
-                               index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);                                
-                               LLVMBuildStore (builder, convert (ctx, LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE), t), LLVMBuildGEP (builder, convert (ctx, values [ins->inst_destbasereg], LLVMPointerType (t, 0)), &index, 1, ""));
+                               if (ins->inst_offset % size != 0) {
+                                       /* Unaligned store */
+                                       index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
+                                       addr = LLVMBuildGEP (builder, convert (ctx, values [ins->inst_destbasereg], LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
+                               } else {
+                                       index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);                                
+                                       addr = LLVMBuildGEP (builder, convert (ctx, values [ins->inst_destbasereg], LLVMPointerType (t, 0)), &index, 1, "");
+                               }
+                               LLVMBuildStore (builder, convert (ctx, LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE), t), addr);
                                break;
                        }
 
@@ -3449,6 +3475,7 @@ mono_llvm_emit_method (MonoCompile *cfg)
                /* Can't delete the method if it has an alias, so only add it if successful */
                if (debug_name) {
                        debug_alias = LLVMAddAlias (module, LLVMTypeOf (method), method, debug_name);
+                       LLVMSetLinkage (debug_alias, LLVMInternalLinkage);
                        LLVMSetVisibility (debug_alias, LLVMHiddenVisibility);
                }
 
@@ -3770,6 +3797,20 @@ void
 mono_llvm_init (void)
 {
        current_cfg_tls_id = TlsAlloc ();
+}
+
+static void
+init_jit_module (void)
+{
+       if (jit_module_inited)
+               return;
+
+       mono_loader_lock ();
+
+       if (jit_module_inited) {
+               mono_loader_unlock ();
+               return;
+       }
 
        jit_module.module = LLVMModuleCreateWithName ("mono");
 
@@ -3780,14 +3821,20 @@ mono_llvm_init (void)
        jit_module.llvm_types = g_hash_table_new (NULL, NULL);
 
        LLVMAddGlobalMapping (ee, LLVMGetNamedFunction (jit_module.module, "mono_resume_unwind"), mono_resume_unwind);
+
+       jit_module_inited = TRUE;
+
+       mono_loader_unlock ();
 }
 
 void
 mono_llvm_cleanup (void)
 {
-       mono_llvm_dispose_ee (ee);
+       if (ee)
+               mono_llvm_dispose_ee (ee);
 
-       g_hash_table_destroy (jit_module.llvm_types);
+       if (jit_module.llvm_types)
+               g_hash_table_destroy (jit_module.llvm_types);
 }
 
 void
@@ -3818,15 +3865,6 @@ mono_llvm_create_aot_module (const char *got_symbol)
                LLVMSetInitializer (aot_module.got_var, LLVMConstNull (got_type));
        }
 
-       /* Add a method to generate the 'methods' symbol needed by the AOT compiler */
-       {
-               LLVMValueRef methods_method = LLVMAddFunction (aot_module.module, "methods", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
-               LLVMBasicBlockRef bb = LLVMAppendBasicBlock (methods_method, "BB_ENTRY");
-               LLVMBuilderRef builder = LLVMCreateBuilder ();
-               LLVMPositionBuilderAtEnd (builder, bb);
-               LLVMBuildRetVoid (builder);
-       }
-
        /* Add a dummy personality function */
        {
                LLVMBasicBlockRef lbb;
@@ -3867,6 +3905,9 @@ mono_llvm_emit_aot_module (const char *filename, int got_size)
 
        mark_as_used (aot_module.module, real_got);
 
+       /* Delete the dummy got so it doesn't become a global */
+       LLVMDeleteGlobal (aot_module.got_var);
+
 #if 0
        {
                char *verifier_err;