[aot] Emit AOT data structures using LLVM when using LLVM.
authorZoltan Varga <vargaz@gmail.com>
Fri, 26 Jun 2015 19:06:58 +0000 (15:06 -0400)
committerZoltan Varga <vargaz@gmail.com>
Fri, 26 Jun 2015 19:07:05 +0000 (15:07 -0400)
mono/mini/aot-compiler.c
mono/mini/mini-llvm-cpp.cpp
mono/mini/mini-llvm-cpp.h
mono/mini/mini-llvm-loaded.c
mono/mini/mini-llvm.c
mono/mini/mini.h

index 58557c47ea37d78606fd7aac787839e67e3a2ff9..2d9a03b1bb2f72394c03b84ec92022caab725148 100644 (file)
@@ -508,9 +508,31 @@ emit_symbol_size (MonoAotCompile *acfg, const char *name, const char *end_label)
        mono_img_writer_emit_symbol_size (acfg->w, name, end_label);
 }
 
+/* Emit a symbol which is referenced by the MonoAotFileInfo structure */
+static void
+emit_info_symbol (MonoAotCompile *acfg, const char *name)
+{
+       char symbol [256];
+
+       if (acfg->llvm) {
+               emit_label (acfg, name);
+               /* LLVM generated code references this */
+               sprintf (symbol, "%s%s", acfg->user_symbol_prefix, name);
+               emit_label (acfg, symbol);
+               emit_global (acfg, symbol, FALSE);
+       } else {
+               emit_label (acfg, name);
+       }
+}
+
 static void
 emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
 {
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data (name, (guint8*)value, strlen (value) + 1);
+               return;
+       }
+
        mono_img_writer_emit_section_change (acfg->w, RODATA_SECT, 1);
 #ifdef TARGET_MACH
        /* On apple, all symbols need to be aligned to avoid warnings from ld */
@@ -2422,11 +2444,14 @@ emit_offset_table (MonoAotCompile *acfg, const char *symbol, int noffsets, int g
 
        g_assert (p - buf <= buf_size);
 
-       emit_section_change (acfg, RODATA_SECT, 1);
-       emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
-
-       emit_bytes (acfg, buf, p - buf);
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data (symbol, buf, p - buf);
+       } else {
+               emit_section_change (acfg, RODATA_SECT, 1);
+               emit_alignment (acfg, 8);
+               emit_label (acfg, symbol);
+               emit_bytes (acfg, buf, p - buf);
+       }
 
        g_free (buf);
        g_free (data_buf);
@@ -5953,7 +5978,7 @@ emit_plt (MonoAotCompile *acfg)
 
        emit_section_change (acfg, ".text", 0);
        emit_alignment_code (acfg, NACL_SIZE(16, kNaClAlignment));
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
        emit_label (acfg, acfg->plt_symbol);
 
        for (i = 0; i < acfg->plt_offset; ++i) {
@@ -6058,7 +6083,7 @@ emit_plt (MonoAotCompile *acfg)
        emit_symbol_size (acfg, acfg->plt_symbol, ".");
 
        sprintf (symbol, "plt_end");
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
 }
 
 /*
@@ -6366,7 +6391,7 @@ emit_trampolines (MonoAotCompile *acfg)
                                emit_local_symbol (acfg, symbol, end_symbol, TRUE);
 
                        emit_alignment_code (acfg, AOT_FUNC_ALIGNMENT);
-                       emit_label (acfg, symbol);
+                       emit_info_symbol (acfg, symbol);
 
                        acfg->trampoline_got_offset_base [ntype] = tramp_got_offset;
 
@@ -7417,7 +7442,7 @@ emit_llvm_file (MonoAotCompile *acfg)
        if (acfg->aot_opts.mtriple)
                g_string_append_printf (acfg->llc_args, " -mtriple=%s", acfg->aot_opts.mtriple);
 
-       g_string_append_printf (acfg->llc_args, " -mono-eh-frame-symbol=%s", acfg->llvm_eh_frame_symbol);
+       g_string_append_printf (acfg->llc_args, " -mono-eh-frame-symbol=%s%s", acfg->user_symbol_prefix, acfg->llvm_eh_frame_symbol);
 
 #if defined(TARGET_MACH) && defined(TARGET_ARM)
        /* ios requires PIC code now */
@@ -7428,7 +7453,6 @@ emit_llvm_file (MonoAotCompile *acfg)
        else
                g_string_append_printf (acfg->llc_args, " -relocation-model=pic");
 #endif
-       unlink (acfg->tmpfname);
 
        if (acfg->llvm_owriter) {
                /* Emit an object file directly */
@@ -7469,7 +7493,7 @@ emit_code (MonoAotCompile *acfg)
         */
        emit_section_change (acfg, ".text", 0);
        emit_alignment_code (acfg, 8);
-       emit_label (acfg, "jit_code_start");
+       emit_info_symbol (acfg, "jit_code_start");
 
        /* 
         * Emit some padding so the local symbol for the first method doesn't have the
@@ -7529,7 +7553,7 @@ emit_code (MonoAotCompile *acfg)
 
        emit_section_change (acfg, ".text", 0);
        emit_alignment_code (acfg, 8);
-       emit_label (acfg, "jit_code_end");
+       emit_info_symbol (acfg, "jit_code_end");
 
        /* To distinguish it from the next symbol */
        emit_padding (acfg, 4);
@@ -7556,7 +7580,7 @@ emit_code (MonoAotCompile *acfg)
        sprintf (symbol, "method_addresses");
        emit_section_change (acfg, ".text", 1);
        emit_alignment_code (acfg, 8);
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
        emit_local_symbol (acfg, symbol, "method_addresses_end", TRUE);
        emit_unset_mode (acfg);
        if (acfg->need_no_dead_strip)
@@ -7581,7 +7605,7 @@ emit_code (MonoAotCompile *acfg)
        sprintf (symbol, "unbox_trampolines");
        emit_section_change (acfg, RODATA_SECT, 0);
        emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
 
        prev_index = -1;
        for (i = 0; i < acfg->nmethods; ++i) {
@@ -7605,14 +7629,14 @@ emit_code (MonoAotCompile *acfg)
                }
        }
        sprintf (symbol, "unbox_trampolines_end");
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
        emit_int32 (acfg, 0);
 
        /* Emit a separate table with the trampoline addresses/offsets */
        sprintf (symbol, "unbox_trampoline_addresses");
        emit_section_change (acfg, ".text", 0);
        emit_alignment_code (acfg, 8);
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
 
        for (i = 0; i < acfg->nmethods; ++i) {
                MonoCompile *cfg;
@@ -7977,11 +8001,15 @@ emit_extra_methods (MonoAotCompile *acfg)
        g_assert (p - buf <= buf_size);
 
        /* Emit the table */
-       sprintf (symbol, "extra_method_table");
-       emit_section_change (acfg, RODATA_SECT, 0);
-       emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
-       emit_bytes (acfg, buf, p - buf);
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data ("extra_method_table", buf, p - buf);
+       } else {
+               sprintf (symbol, "extra_method_table");
+               emit_section_change (acfg, RODATA_SECT, 0);
+               emit_alignment (acfg, 8);
+               emit_label (acfg, symbol);
+               emit_bytes (acfg, buf, p - buf);
+       }
 
        /* 
         * Emit a table reverse mapping method indexes to their index in extra_method_info.
@@ -7996,11 +8024,15 @@ emit_extra_methods (MonoAotCompile *acfg)
                encode_int (get_method_index (acfg, method), p, &p);
                encode_int (info_offsets [i], p, &p);
        }
-       sprintf (symbol, "extra_method_info_offsets");
-       emit_section_change (acfg, RODATA_SECT, 0);
-       emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
-       emit_bytes (acfg, buf, p - buf);
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data ("extra_method_info_offsets", buf, p - buf);
+       } else {
+               sprintf (symbol, "extra_method_info_offsets");
+               emit_section_change (acfg, RODATA_SECT, 0);
+               emit_alignment (acfg, 8);
+               emit_label (acfg, symbol);
+               emit_bytes (acfg, buf, p - buf);
+       }
 }      
 
 static void
@@ -8064,7 +8096,7 @@ emit_unwind_info (MonoAotCompile *acfg)
        sprintf (symbol, "unwind_info");
        emit_section_change (acfg, RODATA_SECT, 1);
        emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
 
        for (i = 0; i < acfg->unwind_ops->len; ++i) {
                guint32 index = GPOINTER_TO_UINT (g_ptr_array_index (acfg->unwind_ops, i));
@@ -8176,11 +8208,15 @@ emit_class_name_table (MonoAotCompile *acfg)
        }
        g_assert (p - buf <= buf_size);
 
-       sprintf (symbol, "class_name_table");
-       emit_section_change (acfg, RODATA_SECT, 0);
-       emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
-       emit_bytes (acfg, buf, p - buf);
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data ("class_name_table", buf, p - buf);
+       } else {
+               sprintf (symbol, "class_name_table");
+               emit_section_change (acfg, RODATA_SECT, 0);
+               emit_alignment (acfg, 8);
+               emit_label (acfg, symbol);
+               emit_bytes (acfg, buf, p - buf);
+       }
 }
 
 static void
@@ -8227,11 +8263,15 @@ emit_image_table (MonoAotCompile *acfg)
        }
        g_assert (p - buf <= buf_size);
 
-       sprintf (symbol, "image_table");
-       emit_section_change (acfg, RODATA_SECT, 1);
-       emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
-       emit_bytes (acfg, buf, p - buf);
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data ("image_table", buf, p - buf);
+       } else {
+               sprintf (symbol, "image_table");
+               emit_section_change (acfg, RODATA_SECT, 1);
+               emit_alignment (acfg, 8);
+               emit_label (acfg, symbol);
+               emit_bytes (acfg, buf, p - buf);
+       }
 
        g_free (buf);
 }
@@ -8315,6 +8355,8 @@ emit_got (MonoAotCompile *acfg)
        emit_alignment (acfg, 8);
        emit_local_symbol (acfg, symbol, "got_end", FALSE);
        emit_label (acfg, symbol);
+       if (acfg->llvm)
+               emit_info_symbol (acfg, "jit_got");
        if (acfg->got_offset > 0)
                emit_zero_bytes (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
 
@@ -8675,7 +8717,10 @@ emit_file_info (MonoAotCompile *acfg)
        info = g_new0 (MonoAotFileInfo, 1);
        init_aot_file_info (acfg, info, gc_name_offset);
 
-       emit_aot_file_info (acfg, info);
+       if (acfg->llvm)
+               mono_llvm_emit_aot_file_info (info, acfg->has_jitted_code);
+       else
+               emit_aot_file_info (acfg, info);
 }
 
 static void
@@ -8683,6 +8728,11 @@ emit_blob (MonoAotCompile *acfg)
 {
        char symbol [128];
 
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data ("blob", (guint8*)acfg->blob.data, acfg->blob.index);
+               return;
+       }
+
        sprintf (symbol, "blob");
        emit_section_change (acfg, RODATA_SECT, 1);
        emit_alignment (acfg, 8);
@@ -9558,8 +9608,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
 #ifdef ENABLE_LLVM
        if (acfg->llvm) {
-               gboolean res;
-
                if (acfg->aot_opts.asm_only) {
                        if (acfg->aot_opts.outfile) {
                                acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
@@ -9583,10 +9631,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                        acfg->llvm_sfile = g_strdup_printf ("%s-llvm.s", acfg->tmpbasename);
                        acfg->llvm_ofile = g_strdup_printf ("%s-llvm.o", acfg->tmpbasename);
                }
-
-               res = emit_llvm_file (acfg);
-               if (!res)
-                       return 1;
        }
 #endif
 
@@ -9656,7 +9700,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                //acfg->gas_line_numbers = TRUE;
        }
 
-       if (!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) {
+       if ((!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) && acfg->has_jitted_code) {
                if (acfg->aot_opts.dwarf_debug && !mono_debug_enabled ()) {
                        aot_printerrf (acfg, "The dwarf AOT option requires the --debug option.\n");
                        return 1;
@@ -9719,6 +9763,16 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                        fprintf (acfg->fp, "\n.section  .note.GNU-stack,\"\",@progbits\n");
        }
 
+#ifdef ENABLE_LLVM
+       if (acfg->llvm) {
+               gboolean res;
+
+               res = emit_llvm_file (acfg);
+               if (!res)
+                       return 1;
+       }
+#endif
+
        TV_GETTIME (btv);
 
        acfg->stats.gen_time = TV_ELAPSED (atv, btv);
index ad20bbd37f664c94e8b51f3790245cc4dd564e43..5b399ee03b7586a9359283631ecc6d62b46901dc 100644 (file)
@@ -424,6 +424,14 @@ mono_llvm_build_fence (LLVMBuilderRef builder, BarrierKind kind)
        return wrap (ins);
 }
 
+void
+mono_llvm_set_must_tail (LLVMValueRef call_ins)
+{
+       CallInst *ins = (CallInst*)unwrap (call_ins);
+
+       ins->setTailCallKind (CallInst::TailCallKind::TCK_MustTail);
+}
+
 void
 mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
 {
@@ -431,6 +439,12 @@ mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
        unwrap (var)->replaceAllUsesWith (V);
 }
 
+LLVMValueRef
+mono_llvm_create_constant_data_array (const uint8_t *data, int len)
+{
+       return wrap(ConstantDataArray::get (*unwrap(LLVMGetGlobalContext ()), makeArrayRef(data, len)));
+}
+
 static cl::list<const PassInfo*, bool, PassNameParser>
 PassList(cl::desc("Optimizations available:"));
 
index ee502e29d09f31ed11bfdd2d5b910871d471e1f0..a60dcecaae21b4dc86a7ce11f79a1d5b81ee9221 100644 (file)
@@ -84,6 +84,12 @@ mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v);
 LLVMValueRef
 mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef addr, LLVMValueRef comparand, LLVMValueRef value);
 
+void
+mono_llvm_set_must_tail (LLVMValueRef call_ins);
+
+LLVMValueRef
+mono_llvm_create_constant_data_array (const uint8_t *data, int len);
+
 G_END_DECLS
 
 #endif /* __MONO_MINI_LLVM_CPP_H__ */  
index 310c4a244159cdacb4545dae92883ab9dc87e351..72ec96ab185f93877944ceeae66831a6e079c839 100644 (file)
@@ -16,6 +16,8 @@ typedef void (*MonoLLVMCFGFunc)(MonoCompile *cfg);
 typedef void (*MonoLLVMEmitCallFunc)(MonoCompile *cfg, MonoCallInst *call);
 typedef void (*MonoLLVMCreateAotFunc)(const char *global_prefix, gboolean emit_dwarf);
 typedef void (*MonoLLVMEmitAotFunc)(const char *filename, const char *cu_name);
+typedef void (*MonoLLVMEmitAotInfoFunc)(MonoAotFileInfo *info, gboolean has_jitted_code);
+typedef void (*MonoLLVMEmitAotDataFunc)(const char *symbol, guint8 *data, int data_len);
 typedef void (*MonoLLVMFreeDomainFunc)(MonoDomain *domain);
 
 static MonoLLVMVoidFunc mono_llvm_init_fptr;
@@ -25,6 +27,8 @@ static MonoLLVMEmitCallFunc mono_llvm_emit_call_fptr;
 static MonoLLVMCreateAotFunc mono_llvm_create_aot_module_fptr;
 static MonoLLVMEmitAotFunc mono_llvm_emit_aot_module_fptr;
 static MonoLLVMCFGFunc mono_llvm_check_method_supported_fptr;
+static MonoLLVMEmitAotInfoFunc mono_llvm_emit_aot_file_info_ptr;
+static MonoLLVMEmitAotDataFunc mono_llvm_emit_aot_data_ptr;
 static MonoLLVMFreeDomainFunc mono_llvm_free_domain_info_fptr;
 
 void
@@ -78,6 +82,20 @@ mono_llvm_free_domain_info (MonoDomain *domain)
                mono_llvm_free_domain_info_fptr (domain);
 }
 
+void
+mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code)
+{
+       if (mono_llvm_emit_aot_file_info_ptr)
+               mono_llvm_emit_aot_file_info_ptr (info, has_jitted_code);
+}
+
+void
+mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
+{
+       if (mono_llvm_emit_aot_data_ptr)
+               mono_llvm_emit_aot_data_ptr (symbol, data, data_len);
+}
+
 int
 mono_llvm_load (const char* bpath)
 {
@@ -106,6 +124,10 @@ mono_llvm_load (const char* bpath)
        if (err) goto symbol_error;
        err = mono_dl_symbol (llvm_lib, "mono_llvm_free_domain_info", (void**)&mono_llvm_free_domain_info_fptr);
        if (err) goto symbol_error;
+       err = mono_dl_symbol (llvm_lib, "mono_llvm_emit_aot_file_info", (void**)&mono_llvm_emit_aot_file_info_fptr);
+       if (err) goto symbol_error;
+       err = mono_dl_symbol (llvm_lib, "mono_llvm_emit_aot_data", (void**)&mono_llvm_emit_aot_data_fptr);
+       if (err) goto symbol_error;
        return TRUE;
 symbol_error:
        g_warning ("llvm symbol load failed: %s\n", err);
index 30fa40672d0cd8c30e4c069626e3a0f5b92ca39e..7b3b0e57f47b3c64926f10823b4abff8046228b3 100644 (file)
@@ -63,6 +63,13 @@ typedef struct {
        gboolean external_symbols;
        gboolean emit_dwarf;
        int max_got_offset;
+
+       /* For AOT */
+       MonoAotFileInfo aot_info;
+       const char *jit_got_symbol;
+       const char *eh_frame_symbol;
+       LLVMValueRef code_start, code_end;
+       gboolean has_jitted_code;
 } MonoLLVMModule;
 
 /*
@@ -5877,6 +5884,7 @@ mono_llvm_create_aot_module (const char *global_prefix, gboolean emit_dwarf)
 
        aot_module.module = LLVMModuleCreateWithName ("aot");
        aot_module.got_symbol = g_strdup_printf ("%s_llvm_got", global_prefix);
+       aot_module.eh_frame_symbol = g_strdup_printf ("%s_eh_frame", global_prefix);
        aot_module.external_symbols = TRUE;
        aot_module.emit_dwarf = emit_dwarf;
        /* The first few entries are reserved */
@@ -5920,6 +5928,175 @@ mono_llvm_create_aot_module (const char *global_prefix, gboolean emit_dwarf)
        aot_module.method_to_lmethod = g_hash_table_new (NULL, NULL);
 }
 
+static LLVMValueRef
+llvm_array_from_uints (LLVMTypeRef el_type, guint32 *values, int nvalues)
+{
+       int i;
+       LLVMValueRef res, *vals;
+
+       vals = g_new0 (LLVMValueRef, nvalues);
+       for (i = 0; i < nvalues; ++i)
+               vals [i] = LLVMConstInt (LLVMInt32Type (), values [i], FALSE);
+       res = LLVMConstArray (LLVMInt32Type (), vals, nvalues);
+       g_free (vals);
+       return res;
+}
+
+/*
+ * mono_llvm_emit_aot_file_info:
+ *
+ *   Emit the MonoAotFileInfo structure.
+ * Same as emit_aot_file_info () in aot-compiler.c.
+ */
+void
+mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code)
+{
+       /* Save these for later */
+       memcpy (&aot_module.aot_info, info, sizeof (MonoAotFileInfo));
+       aot_module.has_jitted_code = has_jitted_code;
+}
+
+/*
+ * mono_llvm_emit_aot_data:
+ *
+ *   Emit the binary data DATA pointed to by symbol SYMBOL.
+ */
+void
+mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
+{
+       MonoLLVMModule *lmodule = &aot_module;
+       LLVMTypeRef type;
+       LLVMValueRef d;
+
+       type = LLVMArrayType (LLVMInt8Type (), data_len);
+       d = LLVMAddGlobal (lmodule->module, type, symbol);
+       LLVMSetInitializer (d, mono_llvm_create_constant_data_array (data, data_len));
+}
+
+static void
+emit_aot_file_info (MonoLLVMModule *lmodule)
+{
+       LLVMTypeRef file_info_type;
+       LLVMTypeRef *eltypes, eltype;
+       LLVMValueRef info_var;
+       LLVMValueRef *fields;
+       int i, nfields, tindex;
+       MonoAotFileInfo *info;
+
+       info = &lmodule->aot_info;
+
+       /* Create an LLVM type to represent MonoAotFileInfo */
+       nfields = 50;
+       eltypes = g_new (LLVMTypeRef, nfields);
+       tindex = 0;
+       eltypes [tindex ++] = LLVMInt32Type ();
+       eltypes [tindex ++] = LLVMInt32Type ();
+       /* Symbols */
+       for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i)
+               eltypes [tindex ++] = LLVMPointerType (LLVMInt8Type (), 0);
+       /* Scalars */
+       for (i = 0; i < 13; ++i)
+               eltypes [tindex ++] = LLVMInt32Type ();
+       /* Arrays */
+       for (i = 0; i < 4; ++i)
+               eltypes [tindex ++] = LLVMArrayType (LLVMInt32Type (), MONO_AOT_TRAMP_NUM);
+       g_assert (tindex == nfields);
+       file_info_type = LLVMStructCreateNamed (LLVMGetGlobalContext (), "MonoAotFileInfo");
+       LLVMStructSetBody (file_info_type, eltypes, nfields, FALSE);
+
+       info_var = LLVMAddGlobal (aot_module.module, file_info_type, "mono_aot_file_info");
+       fields = g_new (LLVMValueRef, nfields);
+       tindex = 0;
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->version, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->dummy, FALSE);
+
+       /* Symbols */
+       /*
+        * We use LLVMGetNamedGlobal () for symbol which are defined in LLVM code, and LLVMAddGlobal ()
+        * for symbols defined in the .s file emitted by the aot compiler.
+        */
+       eltype = eltypes [tindex];
+       fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "jit_got");
+       fields [tindex ++] = aot_module.got_var;
+       /* llc defines this directly */
+       fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, aot_module.eh_frame_symbol);
+       if (TRUE || aot_module.has_jitted_code) {
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "jit_code_start");
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "jit_code_end");
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "method_addresses");
+       } else {
+               fields [tindex ++] = LLVMConstNull (eltype);
+               fields [tindex ++] = LLVMConstNull (eltype);
+               fields [tindex ++] = LLVMConstNull (eltype);
+       }
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "blob");
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "class_name_table");
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "class_info_offsets");
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "method_info_offsets");
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "ex_info_offsets");
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "extra_method_info_offsets");
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "extra_method_table");
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "got_info_offsets");
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "llvm_got_info_offsets");
+       /* Not needed (mem_end) */
+       fields [tindex ++] = LLVMConstNull (eltype);
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "image_table");
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "assembly_guid");
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "runtime_version");
+       if (info->trampoline_size [0]) {
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "specific_trampolines");
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "static_rgctx_trampolines");
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "imt_thunks");
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "gsharedvt_arg_trampolines");
+       } else {
+               fields [tindex ++] = LLVMConstNull (eltype);
+               fields [tindex ++] = LLVMConstNull (eltype);
+               fields [tindex ++] = LLVMConstNull (eltype);
+               fields [tindex ++] = LLVMConstNull (eltype);
+       }
+       // FIXME:
+       fields [tindex ++] = LLVMConstNull (eltype);
+       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "assembly_name");
+       if (TRUE || aot_module.has_jitted_code) {
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "plt");
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "plt_end");
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "unwind_info");
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "unbox_trampolines");
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "unbox_trampolines_end");
+               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "unbox_trampoline_addresses");
+       } else {
+               fields [tindex ++] = LLVMConstNull (eltype);
+               fields [tindex ++] = LLVMConstNull (eltype);
+               fields [tindex ++] = LLVMConstNull (eltype);
+               fields [tindex ++] = LLVMConstNull (eltype);
+               fields [tindex ++] = LLVMConstNull (eltype);
+               fields [tindex ++] = LLVMConstNull (eltype);
+       }
+
+       /* Scalars */
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->plt_got_offset_base, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->got_size, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->plt_size, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nmethods, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->flags, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->opts, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->simd_opts, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->gc_name_index, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->num_rgctx_fetch_trampolines, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->double_align, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->long_align, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->generic_tramp_num, FALSE);
+       fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->tramp_page_size, FALSE);
+       /* Arrays */
+       fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->num_trampolines, MONO_AOT_TRAMP_NUM);
+       fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->trampoline_got_offset_base, MONO_AOT_TRAMP_NUM);
+       fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->trampoline_size, MONO_AOT_TRAMP_NUM);
+       fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->tramp_page_code_offsets, MONO_AOT_TRAMP_NUM);
+       g_assert (tindex == nfields);
+
+       LLVMSetInitializer (info_var, LLVMConstNamedStruct (file_info_type, fields, nfields));
+}
+
 /*
  * Emit the aot module into the LLVM bitcode file FILENAME.
  */
@@ -5949,9 +6126,11 @@ mono_llvm_emit_aot_module (const char *filename, const char *cu_name)
 
        /* Delete the dummy got so it doesn't become a global */
        LLVMDeleteGlobal (aot_module.got_var);
+       aot_module.got_var = real_got;
 
        emit_llvm_used (&aot_module);
        emit_dbg_info (&aot_module, filename, cu_name);
+       emit_aot_file_info (&aot_module);
 
        /* Replace PLT entries for directly callable methods with the methods themselves */
        {
index fe1942682f9d64bf3c0cd4a3040e9d29a53b2f3d..375e8c79f60d9f6be343f755a4698475aa894717 100644 (file)
@@ -2341,6 +2341,8 @@ void     mono_llvm_emit_method              (MonoCompile *cfg) MONO_LLVM_INTERNA
 void     mono_llvm_emit_call                (MonoCompile *cfg, MonoCallInst *call) MONO_LLVM_INTERNAL;
 void     mono_llvm_create_aot_module        (const char *global_prefix, gboolean emit_dwarf) MONO_LLVM_INTERNAL;
 void     mono_llvm_emit_aot_module          (const char *filename, const char *cu_name) MONO_LLVM_INTERNAL;
+void     mono_llvm_emit_aot_file_info       (MonoAotFileInfo *info, gboolean has_jitted_code) MONO_LLVM_INTERNAL;
+void     mono_llvm_emit_aot_data            (const char *symbol, guint8 *data, int data_len) MONO_LLVM_INTERNAL;
 void     mono_llvm_check_method_supported   (MonoCompile *cfg) MONO_LLVM_INTERNAL;
 void     mono_llvm_free_domain_info         (MonoDomain *domain) MONO_LLVM_INTERNAL;
 MONO_API void mono_personality              (void);