/* Maps MonoMethod* -> blob offset */
GHashTable *method_blob_hash;
guint32 *plt_got_info_offsets;
- guint32 got_offset, llvm_got_offset, plt_offset, plt_got_offset_base;
+ guint32 got_offset, llvm_got_offset, plt_offset, plt_got_offset_base, nshared_got_entries;
/* Number of GOT entries reserved for trampolines */
guint32 num_trampoline_got_entries;
guint32 tramp_page_size;
} else {
encode_value (par->gshared_constraint ? 1 : 0, p, &p);
if (par->gshared_constraint) {
- const char *name;
-
+ MonoGSharedGenericParam *gpar = (MonoGSharedGenericParam*)par;
encode_type (acfg, par->gshared_constraint, p, &p);
-
- name = mono_generic_param_name (par);
- if (name) {
- int len = strlen (name);
-
- encode_value (len, p, &p);
- memcpy (p, name, len);
- p += len;
- } else {
- encode_value (0, p, &p);
- }
+ encode_klass_ref (acfg, mono_class_from_generic_parameter (gpar->parent, NULL, klass->byval_arg.type == MONO_TYPE_MVAR), p, &p);
}
}
} else if (klass->byval_arg.type == MONO_TYPE_PTR) {
case MONO_PATCH_INFO_METHOD_CODE_SLOT:
encode_method_ref (acfg, patch_info->data.method, p, &p);
break;
+ case MONO_PATCH_INFO_AOT_JIT_INFO:
+ encode_value (patch_info->data.index, p, &p);
+ break;
case MONO_PATCH_INFO_INTERNAL_METHOD:
case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
guint32 len = strlen (patch_info->data.name);
} else {
encode_value (0, p, &p);
}
- encode_value (patch_info->data.del_tramp->virtual, p, &p);
+ encode_value (patch_info->data.del_tramp->is_virtual, p, &p);
break;
case MONO_PATCH_INFO_FIELD:
case MONO_PATCH_INFO_SFLDA:
encode_value (0, p, &p);
}
+ /* Emit the IL ranges too, since they might not be available at runtime */
+ encode_value (clause->try_offset, p, &p);
+ encode_value (clause->try_len, p, &p);
+ encode_value (clause->handler_offset, p, &p);
+ encode_value (clause->handler_len, p, &p);
+
/* Emit a list of nesting clauses */
for (i = 0; i < header->num_clauses; ++i) {
gint32 cindex1 = k;
{
int i;
- if (!acfg->has_jitted_code) {
+ if (acfg->aot_opts.llvm_only) {
g_assert (acfg->plt_offset == 1);
return;
}
int tramp_type;
#endif
- if (!mono_aot_mode_is_full (&acfg->aot_opts))
+ if (!mono_aot_mode_is_full (&acfg->aot_opts) || acfg->aot_opts.llvm_only)
return;
g_assert (acfg->image->assembly);
if (acfg->llvm)
flags |= JIT_FLAG_LLVM;
if (acfg->aot_opts.llvm_only)
- flags |= JIT_FLAG_LLVM_ONLY;
+ flags |= JIT_FLAG_LLVM_ONLY | JIT_FLAG_EXPLICIT_NULL_CHECKS;
if (acfg->aot_opts.no_direct_calls)
flags |= JIT_FLAG_NO_DIRECT_ICALLS;
cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), flags, 0, index);
return get_got_offset (llvm_acfg, TRUE, ji);
}
+/*
+ * mono_aot_is_shared_got_offset:
+ *
+ * Return whenever OFFSET refers to a GOT slot which is preinitialized
+ * when the AOT image is loaded.
+ */
+gboolean
+mono_aot_is_shared_got_offset (int offset)
+{
+ return offset < llvm_acfg->nshared_got_entries;
+}
+
char*
mono_aot_get_method_name (MonoCompile *cfg)
{
plt_entry->llvm_used = FALSE;
}
+char*
+mono_aot_get_direct_call_symbol (MonoJumpInfoType type, gconstpointer data)
+{
+ const char *sym = NULL;
+
+ if (llvm_acfg->aot_opts.direct_icalls) {
+ if (type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
+ /* Call to a C function implementing a jit icall */
+ sym = mono_lookup_jit_icall_symbol (data);
+ } else if (type == MONO_PATCH_INFO_ICALL_ADDR) {
+ MonoMethod *method = (gpointer)data;
+ if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
+ sym = mono_lookup_icall_symbol (method);
+ }
+ if (sym)
+ return g_strdup (sym);
+ }
+ return NULL;
+}
+
char*
mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
{
char *command, *opts, *tempbc, *output_fname;
/* Emit the LLVM code into a .bc file */
+ if (acfg->aot_opts.llvm_only && acfg->aot_opts.asm_only) {
+ mono_llvm_emit_aot_module (acfg->aot_opts.llvm_outfile, g_path_get_basename (acfg->image->name));
+ return TRUE;
+ }
+
tempbc = g_strdup_printf ("%s.bc", acfg->tmpbasename);
mono_llvm_emit_aot_module (tempbc, g_path_get_basename (acfg->image->name));
g_free (tempbc);
-#ifdef TARGET_MACH
- if (FALSE && acfg->aot_opts.llvm_only) {
+ if (acfg->aot_opts.llvm_only) {
/* Use the stock clang from xcode */
// FIXME: arch
// FIXME: -O2
// FIXME: llc/opt flags
- command = g_strdup_printf ("clang -march=x86-64 -fpic -O0 -c -o \"%s\" \"%s.bc\"", acfg->llvm_ofile, acfg->tmpbasename);
+ command = g_strdup_printf ("clang -march=x86-64 -fpic -msse -msse2 -msse3 -msse4 -O0 -c -o \"%s\" \"%s.bc\"", acfg->llvm_ofile, acfg->tmpbasename);
+ //command = g_strdup_printf ("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk -Qunused-arguments -miphoneos-version-min=8.2 -arch arm64 -fpic -O0 -c -o \"%s\" \"%s.bc\"", acfg->llvm_ofile, acfg->tmpbasename);
aot_printf (acfg, "Executing clang: %s\n", command);
if (execute_system (command) != 0)
return FALSE;
return TRUE;
}
-#endif
/*
* FIXME: Experiment with adding optimizations, the -std-compile-opts set takes
* then removing tailcallelim + the global opts.
* strip-dead-prototypes deletes unused intrinsics definitions.
*/
- //opts = g_strdup ("-instcombine -simplifycfg");
//opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -simplifycfg -domtree -verify");
/* The dse pass is disabled because of #13734 and #17616 */
/*
* return OverwriteComplete;
* Here, if 'Earlier' refers to a memset, and Later has no size info, it mistakenly thinks the memset is redundant.
*/
- //opts = g_strdup ("-targetlibinfo -no-aa -basicaa -notti -instcombine -simplifycfg -inline-cost -inline -sroa -domtree -early-cse -lazy-value-info -correlated-propagation -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -indvars -loop-idiom -loop-deletion -loop-unroll -memdep -gvn -memdep -memcpyopt -sccp -instcombine -lazy-value-info -correlated-propagation -domtree -memdep -adce -simplifycfg -instcombine -strip-dead-prototypes -domtree -verify");
+ opts = g_strdup ("-targetlibinfo -no-aa -basicaa -notti -instcombine -simplifycfg -inline-cost -inline -sroa -domtree -early-cse -lazy-value-info -correlated-propagation -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -indvars -loop-idiom -loop-deletion -loop-unroll -memdep -gvn -memdep -memcpyopt -sccp -instcombine -lazy-value-info -correlated-propagation -domtree -memdep -adce -simplifycfg -instcombine -strip-dead-prototypes -domtree -verify");
opts = g_strdup ("");
#if 1
command = g_strdup_printf ("\"%sopt\" -f %s -o \"%s.opt.bc\" \"%s.bc\"", acfg->aot_opts.llvm_path, opts, acfg->tmpbasename, acfg->tmpbasename);
/* Verbose asm slows down llc greatly */
g_string_append (acfg->llc_args, " -asm-verbose=false");
- g_string_append (acfg->llc_args, " -disable-gnu-eh-frame -enable-mono-eh-frame");
-
if (acfg->aot_opts.mtriple)
g_string_append_printf (acfg->llc_args, " -mtriple=%s", acfg->aot_opts.mtriple);
+ g_string_append (acfg->llc_args, " -disable-gnu-eh-frame -enable-mono-eh-frame");
+
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)
gboolean saved_unbox_info = FALSE;
char symbol [256];
- if (!acfg->has_jitted_code)
+ if (acfg->aot_opts.llvm_only)
return;
#if defined(TARGET_POWERPC64)
int i;
char symbol [128];
- if (!acfg->has_jitted_code) {
+ if (acfg->aot_opts.llvm_only) {
g_assert (acfg->unwind_ops->len == 0);
return;
}
{
char symbol [256];
+ if (acfg->aot_opts.llvm_only)
+ return;
+
/* Don't make GOT global so accesses to it don't need relocations */
sprintf (symbol, "%s", acfg->got_symbol);
{
char symbol [128];
+ if (acfg->aot_opts.llvm_only)
+ return;
+
sprintf (symbol, "mem_end");
emit_section_change (acfg, ".text", 1);
emit_alignment_code (acfg, 8);
info->long_align = MONO_ABI_ALIGNOF (gint64);
info->generic_tramp_num = MONO_TRAMPOLINE_NUM;
info->tramp_page_size = acfg->tramp_page_size;
+ info->nshared_got_entries = acfg->nshared_got_entries;
for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
info->tramp_page_code_offsets [i] = acfg->tramp_page_code_offsets [i];
}
symbols [sindex ++] = NULL;
/* llvm_get_unbox_tramp */
symbols [sindex ++] = NULL;
- symbols [sindex ++] = "jit_code_start";
- symbols [sindex ++] = "jit_code_end";
- symbols [sindex ++] = "method_addresses";
+ if (!acfg->aot_opts.llvm_only) {
+ symbols [sindex ++] = "jit_code_start";
+ symbols [sindex ++] = "jit_code_end";
+ symbols [sindex ++] = "method_addresses";
+ } else {
+ symbols [sindex ++] = NULL;
+ symbols [sindex ++] = NULL;
+ symbols [sindex ++] = NULL;
+ }
symbols [sindex ++] = "blob";
symbols [sindex ++] = "class_name_table";
symbols [sindex ++] = "class_info_offsets";
symbols [sindex ++] = "plt";
symbols [sindex ++] = "plt_end";
symbols [sindex ++] = "unwind_info";
- symbols [sindex ++] = "unbox_trampolines";
- symbols [sindex ++] = "unbox_trampolines_end";
- symbols [sindex ++] = "unbox_trampoline_addresses";
+ if (!acfg->aot_opts.llvm_only) {
+ symbols [sindex ++] = "unbox_trampolines";
+ symbols [sindex ++] = "unbox_trampolines_end";
+ symbols [sindex ++] = "unbox_trampoline_addresses";
+ } else {
+ symbols [sindex ++] = NULL;
+ symbols [sindex ++] = NULL;
+ symbols [sindex ++] = NULL;
+ }
+
g_assert (sindex == MONO_AOT_FILE_INFO_NUM_SYMBOLS);
sprintf (symbol, "%smono_aot_file_info", acfg->user_symbol_prefix);
emit_int32 (acfg, info->long_align);
emit_int32 (acfg, info->generic_tramp_num);
emit_int32 (acfg, info->tramp_page_size);
+ emit_int32 (acfg, info->nshared_got_entries);
for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
emit_int32 (acfg, info->num_trampolines [i]);
/* replace the ; flags separators with spaces */
g_strdelimit (ld_flags, ";", ' ');
+ if (acfg->aot_opts.llvm_only)
+ ld_flags = g_strdup_printf ("%s %s", ld_flags, "-lstdc++");
+
#ifdef LD_NAME
command = g_strdup_printf ("%s -o \"%s\" %s \"%s.o\" %s", LD_NAME, tmp_outfile_name, llvm_ofile, acfg->tmpfname, ld_flags);
#else
mono_json_writer_destroy (&writer);
}
+static const char *preinited_jit_icalls[] = {
+ "mono_aot_init_llvm_method",
+ "mono_aot_init_gshared_method_this",
+ "mono_aot_init_gshared_method_rgctx",
+ "mono_llvm_throw_corlib_exception",
+ "mono_resolve_vcall",
+ "mono_helper_ldstr_mscorlib"
+};
+
+static void
+add_preinit_got_slots (MonoAotCompile *acfg)
+{
+ MonoJumpInfo *ji;
+ int i;
+
+ /*
+ * Allocate the first few GOT entries to information which is needed frequently, or it is needed
+ * during method initialization etc.
+ */
+
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+ ji->type = MONO_PATCH_INFO_IMAGE;
+ ji->data.image = acfg->image;
+ get_got_offset (acfg, FALSE, ji);
+ get_got_offset (acfg, TRUE, ji);
+
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+ ji->type = MONO_PATCH_INFO_MSCORLIB_GOT_ADDR;
+ get_got_offset (acfg, FALSE, ji);
+ get_got_offset (acfg, TRUE, ji);
+
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+ ji->type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
+ get_got_offset (acfg, FALSE, ji);
+ get_got_offset (acfg, TRUE, ji);
+
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+ ji->type = MONO_PATCH_INFO_GC_NURSERY_START;
+ get_got_offset (acfg, FALSE, ji);
+ get_got_offset (acfg, TRUE, ji);
+
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+ ji->type = MONO_PATCH_INFO_JIT_TLS_ID;
+ get_got_offset (acfg, FALSE, ji);
+ get_got_offset (acfg, TRUE, ji);
+
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+ ji->type = MONO_PATCH_INFO_AOT_MODULE;
+ get_got_offset (acfg, FALSE, ji);
+ get_got_offset (acfg, TRUE, ji);
+
+ for (i = 0; i < sizeof (preinited_jit_icalls) / sizeof (char*); ++i) {
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
+ ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
+ ji->data.name = preinited_jit_icalls [i];
+ get_got_offset (acfg, FALSE, ji);
+ get_got_offset (acfg, TRUE, ji);
+ }
+
+ acfg->nshared_got_entries = acfg->got_offset;
+}
+
int
mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
{
if (mono_aot_mode_is_full (&acfg->aot_opts))
acfg->flags |= MONO_AOT_FILE_FLAG_FULL_AOT;
+ if (mono_threads_is_coop_enabled ())
+ acfg->flags |= MONO_AOT_FILE_FLAG_SAFEPOINTS;
+
if (acfg->aot_opts.instances_logfile_path) {
acfg->instances_logfile = fopen (acfg->aot_opts.instances_logfile_path, "w");
if (!acfg->instances_logfile) {
/* PLT offset 0 is reserved for the PLT trampoline */
acfg->plt_offset = 1;
+ add_preinit_got_slots (acfg);
#ifdef ENABLE_LLVM
if (acfg->llvm) {
}
#endif
- {
- MonoJumpInfo *ji;
-
- /* Slot 0 */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
- ji->type = MONO_PATCH_INFO_IMAGE;
- ji->data.image = acfg->image;
- get_got_offset (acfg, FALSE, ji);
- get_got_offset (acfg, TRUE, ji);
-
- /* Slot 1 */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
- ji->type = MONO_PATCH_INFO_MSCORLIB_GOT_ADDR;
- get_got_offset (acfg, FALSE, ji);
- get_got_offset (acfg, TRUE, ji);
-
- /* Slot 2 */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
- ji->type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
- get_got_offset (acfg, FALSE, ji);
- get_got_offset (acfg, TRUE, ji);
-
- /* Slot 3 */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
- ji->type = MONO_PATCH_INFO_GC_NURSERY_START;
- get_got_offset (acfg, FALSE, ji);
- get_got_offset (acfg, TRUE, ji);
-
- /* Slot 4 */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
- ji->type = MONO_PATCH_INFO_JIT_TLS_ID;
- get_got_offset (acfg, FALSE, ji);
- get_got_offset (acfg, TRUE, ji);
-
- /* Slot 5 */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
- ji->type = MONO_PATCH_INFO_AOT_MODULE;
- get_got_offset (acfg, FALSE, ji);
- get_got_offset (acfg, TRUE, ji);
-
- /* Slot 6 */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
- ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
- ji->data.name = "mono_aot_init_llvm_method";
- get_got_offset (acfg, FALSE, ji);
- get_got_offset (acfg, TRUE, ji);
-
- /* Slot 7 */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
- ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
- ji->data.name = "mono_aot_init_gshared_method_this";
- get_got_offset (acfg, FALSE, ji);
- get_got_offset (acfg, TRUE, ji);
-
- /* Slot 8 */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
- ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
- ji->data.name = "mono_aot_init_gshared_method_rgctx";
- get_got_offset (acfg, FALSE, ji);
- get_got_offset (acfg, TRUE, ji);
- }
-
TV_GETTIME (atv);
compile_methods (acfg);
return 0;
}
+gboolean
+mono_aot_is_shared_got_offset (int offset)
+{
+ return FALSE;
+}
+
#endif