gboolean soft_debug;
gboolean log_generics;
gboolean log_instances;
+ gboolean gen_seq_points_file;
gboolean direct_pinvoke;
gboolean direct_icalls;
gboolean no_direct_calls;
mono_mutex_t mutex;
gboolean use_bin_writer;
gboolean gas_line_numbers;
- /* Whenever to emit LLVM code into a separate object file */
- gboolean llvm_separate;
/* Whenever to emit an object file directly from llc */
gboolean llvm_owriter;
MonoImageWriter *w;
va_end (args);
}
-/* Wrappers around the image writer functions */
-
-static inline void
-emit_section_change (MonoAotCompile *acfg, const char *section_name, int subsection_index)
+static void
+report_loader_error (MonoAotCompile *acfg, MonoError *error, const char *format, ...)
{
- img_writer_emit_section_change (acfg->w, section_name, subsection_index);
-}
+ FILE *output;
+ va_list args;
-static inline void
-emit_push_section (MonoAotCompile *acfg, const char *section_name, int subsection)
-{
- img_writer_emit_push_section (acfg->w, section_name, subsection);
+ if (mono_error_ok (error))
+ return;
+
+ if (acfg->logfile)
+ output = acfg->logfile;
+ else
+ output = stderr;
+
+ va_start (args, format);
+ vfprintf (output, format, args);
+ va_end (args);
+ mono_error_cleanup (error);
+
+ g_error ("FullAOT cannot continue if there are loader errors");
}
+/* Wrappers around the image writer functions */
+
static inline void
-emit_pop_section (MonoAotCompile *acfg)
+emit_section_change (MonoAotCompile *acfg, const char *section_name, int subsection_index)
{
- img_writer_emit_pop_section (acfg->w);
+ img_writer_emit_section_change (acfg->w, section_name, subsection_index);
}
static inline void
}
}
-static inline void
-emit_pointer_unaligned (MonoAotCompile *acfg, const char *target)
-{
- img_writer_emit_pointer_unaligned (acfg->w, target);
-}
-
static inline void
emit_pointer (MonoAotCompile *acfg, const char *target)
{
#ifdef TARGET_AMD64
/* mov reg, got+offset(%rip) */
- if (acfg->llvm_separate) {
+ if (acfg->llvm) {
/* The GOT symbol is in the LLVM module, the clang assembler has problems emitting symbol diffs for it */
int dreg;
int rex_r;
/* This should be exactly 8 bytes long */
*tramp_size = 8;
/* call *<offset>(%rip) */
- if (acfg->llvm_separate) {
+ if (acfg->llvm) {
emit_unset_mode (acfg);
fprintf (acfg->fp, "call *%s+%d(%%rip)\n", acfg->got_symbol, (int)(offset * sizeof (gpointer)));
emit_zero_bytes (acfg, 2);
emit_bytes (acfg, buf, code - buf);
/* jump <method> */
- if (acfg->llvm_separate) {
+ if (acfg->llvm) {
emit_unset_mode (acfg);
fprintf (acfg->fp, "jmp %s\n", call_target);
} else {
/* This should be exactly 13 bytes long */
*tramp_size = 13;
- if (acfg->llvm_separate) {
+ if (acfg->llvm) {
emit_unset_mode (acfg);
fprintf (acfg->fp, "mov %s+%d(%%rip), %%r10\n", acfg->got_symbol, (int)(offset * sizeof (gpointer)));
fprintf (acfg->fp, "jmp *%s+%d(%%rip)\n", acfg->got_symbol, (int)((offset + 1) * sizeof (gpointer)));
/* MONO_ARCH_IMT_SCRATCH_REG is a free register */
- if (acfg->llvm_separate) {
+ if (acfg->llvm) {
emit_unset_mode (acfg);
fprintf (acfg->fp, "mov %s+%d(%%rip), %s\n", acfg->got_symbol, (int)(offset * sizeof (gpointer)), mono_arch_regname (MONO_ARCH_IMT_SCRATCH_REG));
}
mono_amd64_patch (labels [3], code);
x86_breakpoint (code);
- if (!acfg->llvm_separate) {
+ if (!acfg->llvm) {
/* mov <OFFSET>(%rip), MONO_ARCH_IMT_SCRATCH_REG */
amd64_emit_rex (mov_buf_ptr, sizeof(gpointer), MONO_ARCH_IMT_SCRATCH_REG, 0, AMD64_RIP);
*(mov_buf_ptr)++ = (unsigned char)0x8b; /* mov opcode */
* callers.
*/
for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
+ MonoError error;
MonoMethod *method;
guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
gboolean skip = FALSE;
- method = mono_get_method (acfg->image, token, NULL);
+ method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
+ report_loader_error (acfg, &error, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
(method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
}
}
+ /* write barriers */
+ if (mono_gc_is_moving ()) {
+ add_method (acfg, mono_gc_get_specific_write_barrier (FALSE));
+ add_method (acfg, mono_gc_get_specific_write_barrier (TRUE));
+ }
+
/* Stelemref wrappers */
{
MonoMethod **wrappers;
/* Synchronized wrappers */
for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
+ MonoError error;
token = MONO_TOKEN_METHOD_DEF | (i + 1);
- method = mono_get_method (acfg->image, token, NULL);
+ method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
+ report_loader_error (acfg, &error, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
if (method->is_generic) {
/* pinvoke wrappers */
for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
+ MonoError error;
MonoMethod *method;
guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
- method = mono_get_method (acfg->image, token, NULL);
+ method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
+ report_loader_error (acfg, &error, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
/* native-to-managed wrappers */
for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
+ MonoError error;
MonoMethod *method;
guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
MonoCustomAttrInfo *cattr;
int j;
- method = mono_get_method (acfg->image, token, NULL);
+ method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
+ report_loader_error (acfg, &error, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
/*
* Only generate native-to-managed wrappers for methods which have an
MonoMethodSignature *sig = mono_method_signature (e->ctor);
const char *p = (const char*)e->data;
const char *named;
- int slen, num_named, named_type, data_type;
+ int slen, num_named, named_type;
char *n;
MonoType *t;
MonoClass *klass;
if (num_named == 1) {
int name_len;
char *name;
- MonoType *prop_type;
/* parse ExportSymbol attribute */
named = p;
named_type = *named;
named += 1;
- data_type = *named;
+ /* data_type = *named; */
named += 1;
name_len = mono_metadata_decode_blob_size (named, &named);
g_assert (named_type == 0x54);
g_assert (!strcmp (name, "ExportSymbol"));
- prop_type = &mono_defaults.string_class->byval_arg;
-
/* load_cattr_value (), string case */
g_assert (*named != (char)0xff);
slen = mono_metadata_decode_value (named, &named);
return;
for (i = 0; i < acfg->image->tables [MONO_TABLE_METHODSPEC].rows; ++i) {
+ MonoError error;
token = MONO_TOKEN_METHOD_SPEC | (i + 1);
- method = mono_get_method (acfg->image, token, NULL);
+ method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
- if (!method)
+ if (!method) {
+ aot_printerrf (acfg, "Failed to load methodspec 0x%x due to %s.\n", token, mono_error_get_message (&error));
+ aot_printerrf (acfg, "Run with MONO_LOG_LEVEL=debug for more information.\n");
+ mono_error_cleanup (&error);
continue;
+ }
if (method->klass->image != acfg->image)
continue;
if (callee_cfg->method->wrapper_type == MONO_WRAPPER_ALLOC)
/* sgen does some initialization when the allocator method is created */
direct_callable = FALSE;
+ if (callee_cfg->method->wrapper_type == MONO_WRAPPER_WRITE_BARRIER)
+ /* we don't know at compile time whether sgen is concurrent or not */
+ direct_callable = FALSE;
if (direct_callable)
return TRUE;
static void
emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, guint32 code_len, MonoJumpInfo *relocs, gboolean got_only, MonoDebugMethodJitInfo *debug_info)
{
- int i, pindex, start_index, method_index;
+ int i, pindex, start_index;
GPtrArray *patches;
MonoJumpInfo *patch_info;
- MonoMethodHeader *header;
MonoDebugSourceLocation **locs = NULL;
gboolean skip;
#ifdef MONO_ARCH_AOT_SUPPORTED
const char *direct_pinvoke;
#endif
- if (method) {
- header = mono_method_get_header (method);
-
- method_index = get_method_index (acfg, method);
- }
-
if (acfg->gas_line_numbers && method && debug_info) {
locs = compute_line_numbers (method, code_len, debug_info);
if (!locs) {
char *debug_sym = NULL;
char *symbol = NULL;
int func_alignment = AOT_FUNC_ALIGNMENT;
- MonoMethodHeader *header;
char *export_name;
method = cfg->orig_method;
code = cfg->native_code;
- header = cfg->header;
method_index = get_method_index (acfg, method);
symbol = g_strdup_printf ("%sme_%x", acfg->temp_prefix, method_index);
emit_label (acfg, cfg->asm_symbol);
- if (acfg->aot_opts.write_symbols && !acfg->global_symbols && !acfg->llvm_separate) {
+ if (acfg->aot_opts.write_symbols && !acfg->global_symbols && !acfg->llvm) {
/*
* Write a C style symbol for every method, this has two uses:
* - it works on platforms where the dwarf debugging info is not
case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
case MONO_PATCH_INFO_JIT_TLS_ID:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
+ case MONO_PATCH_INFO_GC_NURSERY_START:
break;
case MONO_PATCH_INFO_CASTCLASS_CACHE:
encode_value (patch_info->data.index, p, &p);
}
case MONO_PATCH_INFO_LDSTR_LIT: {
const char *s = patch_info->data.target;
+ int len = strlen (s);
- encode_value (strlen (s), p, &p);
- memcpy (p, s, strlen (s) + 1);
+ encode_value (len, p, &p);
+ memcpy (p, s, len + 1);
+ p += len + 1;
break;
}
default:
int pindex, buf_size, n_patches;
GPtrArray *patches;
MonoJumpInfo *patch_info;
- MonoMethodHeader *header;
guint32 method_index;
guint8 *p, *buf;
guint32 first_got_offset;
method = cfg->orig_method;
- header = mono_method_get_header (method);
method_index = get_method_index (acfg, method);
continue;
}
- if (patch_info->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR) {
+ if (patch_info->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR ||
+ patch_info->type == MONO_PATCH_INFO_GC_NURSERY_START) {
/* Stored in a GOT slot initialized at module load time */
patch_info->type = MONO_PATCH_INFO_NONE;
continue;
}
static void
-emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
+emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg, gboolean store_seq_points)
{
- MonoMethod *method;
- int i, k, buf_size, method_index;
+ int i, k, buf_size;
guint32 debug_info_size, seq_points_size;
guint8 *code;
MonoMethodHeader *header;
gboolean use_unwind_ops = FALSE;
MonoSeqPointInfo *seq_points;
- method = cfg->orig_method;
code = cfg->native_code;
header = cfg->header;
- method_index = get_method_index (acfg, method);
-
if (!acfg->aot_opts.nodebug) {
mono_debug_serialize_debug_info (cfg, &debug_info, &debug_info_size);
} else {
}
seq_points = cfg->seq_point_info;
-
- seq_points_size = (cfg->gen_seq_points)? seq_point_info_get_write_size (seq_points) : 0;
+ seq_points_size = (store_seq_points)? seq_point_info_get_write_size (seq_points) : 0;
buf_size = header->num_clauses * 256 + debug_info_size + 2048 + seq_points_size + cfg->gc_map_size;
+
p = buf = g_malloc (buf_size);
use_unwind_ops = cfg->unwind_ops != NULL;
- flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0) | (header->num_clauses ? 4 : 0) | (seq_points ? 8 : 0) | (cfg->compile_llvm ? 16 : 0) | (jinfo->has_try_block_holes ? 32 : 0) | (cfg->gc_map ? 64 : 0) | (jinfo->has_arch_eh_info ? 128 : 0);
+ flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0) | (header->num_clauses ? 4 : 0) | (seq_points_size ? 8 : 0) | (cfg->compile_llvm ? 16 : 0) | (jinfo->has_try_block_holes ? 32 : 0) | (cfg->gc_map ? 64 : 0) | (jinfo->has_arch_eh_info ? 128 : 0);
encode_value (flags, p, &p);
if (jinfo->has_generic_jit_info) {
MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (jinfo);
MonoGenericSharingContext* gsctx = gi->generic_sharing_context;
- guint8 *p1;
guint8 *buf2, *p2;
int len;
- p1 = p;
encode_value (gi->nlocs, p, &p);
if (gi->nlocs) {
for (i = 0; i < gi->nlocs; ++i) {
}
}
- if (seq_points)
+ if (seq_points_size)
p += seq_point_info_write (seq_points, p);
g_assert (debug_info_size < buf_size);
char *s;
char *prefix;
- if (acfg->llvm_separate && llvm_acfg->aot_opts.static_link) {
+ if (acfg->llvm && llvm_acfg->aot_opts.static_link) {
/* Need to add a prefix to create unique symbols */
prefix = g_strdup_printf ("plt_%s_", acfg->assembly_name_sym);
} else {
for (i = 0; i < acfg->plt_offset; ++i) {
char *debug_sym = NULL;
MonoPltEntry *plt_entry = NULL;
- MonoJumpInfo *ji;
if (i == 0)
/*
continue;
plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
- ji = plt_entry->ji;
debug_sym = plt_entry->debug_sym;
if (acfg->llvm && !acfg->thumb_mixed) {
emit_label (acfg, plt_entry->llvm_symbol);
- if (acfg->llvm_separate) {
+ if (acfg->llvm) {
emit_global_inner (acfg, plt_entry->llvm_symbol, TRUE);
#if defined(TARGET_MACH)
fprintf (acfg->fp, ".private_extern %s\n", plt_entry->llvm_symbol);
for (i = 0; i < acfg->plt_offset; ++i) {
char *debug_sym = NULL;
MonoPltEntry *plt_entry = NULL;
- MonoJumpInfo *ji;
if (i == 0)
continue;
plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
- ji = plt_entry->ji;
/* Skip plt entries not actually called by LLVM code */
if (!plt_entry->llvm_used)
emit_label (acfg, plt_entry->llvm_symbol);
- if (acfg->llvm_separate)
+ if (acfg->llvm)
emit_global_inner (acfg, plt_entry->llvm_symbol, TRUE);
arch_emit_llvm_plt_entry (acfg, i);
opts->ld_flags = g_strdup (arg + strlen ("ld-flags="));
} else if (str_begins_with (arg, "soft-debug")) {
opts->soft_debug = TRUE;
+ } else if (str_begins_with (arg, "gen-seq-points-file")) {
+ opts->gen_seq_points_file = TRUE;
} else if (str_begins_with (arg, "direct-pinvoke")) {
opts->direct_pinvoke = TRUE;
} else if (str_begins_with (arg, "direct-icalls")) {
opts->direct_icalls = TRUE;
-#if defined(TARGET_ARM) || defined(TARGET_ARM64)
- } else if (str_begins_with (arg, "iphone-abi")) {
- // older full-aot users did depend on this.
-#endif
} else if (str_begins_with (arg, "no-direct-calls")) {
opts->no_direct_calls = TRUE;
} else if (str_begins_with (arg, "print-skipped")) {
opts->mtriple = g_strdup (arg + strlen ("mtriple="));
} else if (str_begins_with (arg, "llvm-path=")) {
opts->llvm_path = g_strdup (arg + strlen ("llvm-path="));
+ if (!g_str_has_suffix (opts->llvm_path, G_DIR_SEPARATOR_S)) {
+ gchar *old = opts->llvm_path;
+ opts->llvm_path = g_strconcat (opts->llvm_path, G_DIR_SEPARATOR_S, NULL);
+ g_free (old);
+ }
} else if (!strcmp (arg, "llvm")) {
opts->llvm = TRUE;
} else if (str_begins_with (arg, "readonly-value=")) {
printf (" tool-prefix=\n");
printf (" readonly-value=\n");
printf (" soft-debug\n");
+ printf (" gen-seq-points-file\n");
printf (" gc-maps\n");
printf (" print-skipped\n");
printf (" no-instances\n");
flags |= JIT_FLAG_FULL_AOT;
if (acfg->llvm)
flags |= JIT_FLAG_LLVM;
+ 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);
mono_loader_clear_error ();
case MONO_PATCH_INFO_GOT_OFFSET:
case MONO_PATCH_INFO_NONE:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
+ case MONO_PATCH_INFO_GC_NURSERY_START:
break;
case MONO_PATCH_INFO_IMAGE:
/* The assembly is stored in GOT slot 0 */
{
MonoJumpInfo *ji = mono_mempool_alloc (llvm_acfg->mempool, sizeof (MonoJumpInfo));
MonoPltEntry *plt_entry;
+ const char *sym = NULL;
ji->type = type;
ji->data.target = data;
if (!can_encode_patch (llvm_acfg, ji))
return 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);
+ }
+
plt_entry = get_plt_entry (llvm_acfg, ji);
plt_entry->llvm_used = TRUE;
int status;
#if _WIN32
+ // We need an extra set of quotes around the whole command to properly handle commands
+ // with spaces since internally the command is called through "cmd /c.
+ command = g_strdup_printf ("\"%s\"", command);
+
int size = MultiByteToWideChar (CP_UTF8, 0 , command , -1, NULL , 0);
wchar_t* wstr = g_malloc (sizeof (wchar_t) * size);
MultiByteToWideChar (CP_UTF8, 0, command, -1, wstr , size);
status = _wsystem (wstr);
g_free (wstr);
+
+ g_free (command);
#else
status = system (command);
#endif
*/
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");
#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);
+ command = g_strdup_printf ("\"%sopt\" -f %s -o \"%s.opt.bc\" \"%s.bc\"", acfg->aot_opts.llvm_path, opts, acfg->tmpbasename, acfg->tmpbasename);
aot_printf (acfg, "Executing opt: %s\n", command);
if (execute_system (command) != 0)
return FALSE;
if (acfg->aot_opts.mtriple)
g_string_append_printf (acfg->llc_args, " -mtriple=%s", acfg->aot_opts.mtriple);
- if (acfg->llvm_separate)
- 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", acfg->llvm_eh_frame_symbol);
#if defined(TARGET_MACH) && defined(TARGET_ARM)
/* ios requires PIC code now */
#endif
unlink (acfg->tmpfname);
- if (acfg->llvm_separate) {
- if (acfg->llvm_owriter) {
- /* Emit an object file directly */
- output_fname = g_strdup_printf ("%s", acfg->llvm_ofile);
- g_string_append_printf (acfg->llc_args, " -filetype=obj");
- } else {
- output_fname = g_strdup_printf ("%s", acfg->llvm_sfile);
- }
+ if (acfg->llvm_owriter) {
+ /* Emit an object file directly */
+ output_fname = g_strdup_printf ("%s", acfg->llvm_ofile);
+ g_string_append_printf (acfg->llc_args, " -filetype=obj");
} else {
- output_fname = g_strdup (acfg->tmpfname);
+ output_fname = g_strdup_printf ("%s", acfg->llvm_sfile);
}
- command = g_strdup_printf ("%sllc %s -o \"%s\" \"%s.opt.bc\"", acfg->aot_opts.llvm_path, acfg->llc_args->str, output_fname, acfg->tmpbasename);
+ command = g_strdup_printf ("\"%sllc\" %s -o \"%s\" \"%s.opt.bc\"", acfg->aot_opts.llvm_path, acfg->llc_args->str, output_fname, acfg->tmpbasename);
+ g_free (output_fname);
aot_printf (acfg, "Executing llc: %s\n", command);
int hashes_count;
guint32 *hashes_start, *hashes;
guint32 a, b, c;
+ MonoGenericInst *class_ginst = NULL;
MonoGenericInst *ginst = NULL;
/* Similar to the hash in mono_method_get_imt_slot () */
sig = mono_method_signature (method);
+ if (method->klass->generic_class)
+ class_ginst = method->klass->generic_class->context.class_inst;
if (method->is_inflated)
ginst = ((MonoMethodInflated*)method)->context.method_inst;
- hashes_count = sig->param_count + 5 + (ginst ? ginst->type_argc : 0);
+ hashes_count = sig->param_count + 5 + (class_ginst ? class_ginst->type_argc : 0) + (ginst ? ginst->type_argc : 0);
hashes_start = g_malloc0 (hashes_count * sizeof (guint32));
hashes = hashes_start;
klass = mono_defaults.object_class;
if (!method->wrapper_type) {
- char *full_name = mono_type_full_name (&klass->byval_arg);
+ char *full_name;
+
+ if (klass->generic_class)
+ full_name = mono_type_full_name (&klass->generic_class->container_class->byval_arg);
+ else
+ full_name = mono_type_full_name (&klass->byval_arg);
hashes [0] = mono_metadata_str_hash (full_name);
hashes [1] = 0;
for (i = 0; i < sig->param_count; i++) {
hashes [hindex ++] = mono_aot_type_hash (sig->params [i]);
}
+ if (class_ginst) {
+ for (i = 0; i < class_ginst->type_argc; ++i)
+ hashes [hindex ++] = mono_aot_type_hash (class_ginst->type_argv [i]);
+ }
if (ginst) {
for (i = 0; i < ginst->type_argc; ++i)
hashes [hindex ++] = mono_aot_type_hash (ginst->type_argv [i]);
value = get_method_index (acfg, method);
hash = mono_aot_method_hash (method) % table_size;
- //printf ("X: %s %d\n", mono_method_full_name (method, 1), hash);
+ //printf ("X: %s %x\n", mono_method_full_name (method, 1), mono_aot_method_hash (method));
chain_lengths [hash] ++;
max_chain_length = MAX (max_chain_length, chain_lengths [hash]);
int i;
char symbol [256];
gint32 *offsets;
+ SeqPointData sp_data;
+ gboolean seq_points_to_file = FALSE;
offsets = g_new0 (gint32, acfg->nmethods);
for (i = 0; i < acfg->nmethods; ++i) {
if (acfg->cfgs [i]) {
- emit_exception_debug_info (acfg, acfg->cfgs [i]);
- offsets [i] = acfg->cfgs [i]->ex_info_offset;
+ MonoCompile *cfg = acfg->cfgs [i];
+
+ // By design aot-runtime decode_exception_debug_info is not able to load sequence point debug data from a file.
+ // As it is not possible to load debug data from a file its is also not possible to store it in a file.
+ gboolean method_seq_points_to_file = acfg->aot_opts.gen_seq_points_file &&
+ cfg->gen_seq_points && !cfg->gen_seq_points_debug_data;
+ gboolean method_seq_points_to_binary = cfg->gen_seq_points && !method_seq_points_to_file;
+
+ emit_exception_debug_info (acfg, cfg, method_seq_points_to_binary);
+ offsets [i] = cfg->ex_info_offset;
+
+ if (method_seq_points_to_file) {
+ if (!seq_points_to_file) {
+ seq_point_data_init (&sp_data, acfg->nmethods);
+ seq_points_to_file = TRUE;
+ }
+ seq_point_data_add (&sp_data, cfg->method->token, cfg->seq_point_info);
+ }
} else {
offsets [i] = 0;
}
}
+ if (seq_points_to_file) {
+ char *seq_points_aot_file;
+ mono_image_get_aot_seq_point_path (acfg->image, &seq_points_aot_file);
+ seq_point_data_write (&sp_data, seq_points_aot_file);
+ seq_point_data_free (&sp_data);
+ g_free (seq_points_aot_file);
+ }
+
sprintf (symbol, "ex_info_offsets");
emit_section_change (acfg, RODATA_SECT, 1);
emit_alignment (acfg, 8);
/* Collect methods */
for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+ MonoError error;
MonoMethod *method;
guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
- method = mono_get_method (acfg->image, token, NULL);
+ method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
if (!method) {
- aot_printerrf (acfg, "Failed to load method 0x%x from '%s'.\n", token, image->name);
+ aot_printerrf (acfg, "Failed to load method 0x%x from '%s' due to %s.\n", token, image->name, mono_error_get_message (&error));
aot_printerrf (acfg, "Run with MONO_LOG_LEVEL=debug for more information.\n");
+ mono_error_cleanup (&error);
return FALSE;
}
/* gsharedvt methods */
for (mindex = 0; mindex < image->tables [MONO_TABLE_METHOD].rows; ++mindex) {
+ MonoError error;
MonoMethod *method;
guint32 token = MONO_TOKEN_METHOD_DEF | (mindex + 1);
if (!(acfg->opts & MONO_OPT_GSHAREDVT))
continue;
- method = mono_get_method (acfg->image, token, NULL);
- if (!method)
- continue;
+ method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
+ report_loader_error (acfg, &error, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
+
/*
if (strcmp (method->name, "gshared2"))
continue;
#define AS_NAME "nacl-as"
#endif
#elif defined(TARGET_OSX)
-#define AS_NAME "clang -c -x assembler"
+#define AS_NAME "clang"
#else
#define AS_NAME "as"
#endif
aot_printf (acfg, "Output file: '%s'.\n", acfg->tmpfname);
if (acfg->aot_opts.static_link)
aot_printf (acfg, "Linking symbol: '%s'.\n", acfg->static_linking_symbol);
- if (acfg->llvm_separate)
+ if (acfg->llvm)
aot_printf (acfg, "LLVM output file: '%s'.\n", acfg->llvm_sfile);
return 0;
}
} else {
objfile = g_strdup_printf ("%s.o", acfg->tmpfname);
}
- command = g_strdup_printf ("%s%s %s %s -o %s %s", tool_prefix, AS_NAME, AS_OPTIONS, acfg->as_args ? acfg->as_args->str : "", objfile, acfg->tmpfname);
+
+#ifdef TARGET_OSX
+ g_string_append (acfg->as_args, "-c -x assembler");
+#endif
+
+ command = g_strdup_printf ("\"%s%s\" %s %s -o %s %s", tool_prefix, AS_NAME, AS_OPTIONS, acfg->as_args ? acfg->as_args->str : "", objfile, acfg->tmpfname);
aot_printf (acfg, "Executing the native assembler: %s\n", command);
if (execute_system (command) != 0) {
g_free (command);
return 1;
}
- if (acfg->llvm_separate && !acfg->llvm_owriter) {
- command = g_strdup_printf ("%s%s %s %s -o %s %s", tool_prefix, AS_NAME, AS_OPTIONS, acfg->as_args ? acfg->as_args->str : "", acfg->llvm_ofile, acfg->llvm_sfile);
+ if (acfg->llvm && !acfg->llvm_owriter) {
+ command = g_strdup_printf ("\"%s%s\" %s %s -o %s %s", tool_prefix, AS_NAME, AS_OPTIONS, acfg->as_args ? acfg->as_args->str : "", acfg->llvm_ofile, acfg->llvm_sfile);
aot_printf (acfg, "Executing the native assembler: %s\n", command);
if (execute_system (command) != 0) {
g_free (command);
tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
- if (acfg->llvm_separate) {
+ if (acfg->llvm) {
llvm_ofile = g_strdup (acfg->llvm_ofile);
} else {
llvm_ofile = g_strdup ("");
#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
- command = g_strdup_printf ("%sld %s -shared -o %s %s %s.o %s", tool_prefix, LD_OPTIONS, tmp_outfile_name, llvm_ofile,
+ command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s.o %s", tool_prefix, LD_OPTIONS, tmp_outfile_name, llvm_ofile,
acfg->tmpfname, ld_flags);
#endif
aot_printf (acfg, "Executing the native linker: %s\n", command);
mini_llvm_init ();
- if (!acfg->aot_opts.asm_only || acfg->aot_opts.llvm_outfile) {
- /*
- * Emit all LLVM code into a separate assembly/object file and link with it
- * normally.
- */
-#if LLVM_API_VERSION >= 3
- acfg->llvm_separate = TRUE;
- if (!acfg->aot_opts.asm_only)
- acfg->llvm_owriter = TRUE;
-#endif
- }
- if (acfg->aot_opts.llvm_outfile && !acfg->llvm_separate) {
- aot_printerrf (acfg, "The llvm-outputfile= option is not supported on this platform.\n");
+ if (acfg->aot_opts.asm_only && !acfg->aot_opts.llvm_outfile) {
+ aot_printerrf (acfg, "Compiling with LLVM and the asm-only option requires the llvm-outputfile= option.");
return 1;
}
+
+ /*
+ * Emit all LLVM code into a separate assembly/object file and link with it
+ * normally.
+ */
+ if (!acfg->aot_opts.asm_only)
+ acfg->llvm_owriter = TRUE;
}
if (acfg->aot_opts.full_aot)
acfg->got_symbol = g_strdup_printf ("%s%s", acfg->llvm_label_prefix, acfg->got_symbol_base);
if (acfg->llvm) {
acfg->llvm_got_symbol = g_strdup_printf ("%s%s", acfg->llvm_label_prefix, acfg->llvm_got_symbol_base);
- if (acfg->llvm_separate)
- acfg->llvm_eh_frame_symbol = g_strdup_printf ("mono_aot_%s_eh_frame", acfg->assembly_name_sym);
- else
- acfg->llvm_eh_frame_symbol = g_strdup ("mono_eh_frame");
+ acfg->llvm_eh_frame_symbol = g_strdup_printf ("mono_aot_%s_eh_frame", acfg->assembly_name_sym);
}
acfg->method_index = 1;
- // FIXME:
- /*
if (acfg->aot_opts.full_aot)
mono_set_partial_sharing_supported (TRUE);
- */
-
- mono_set_partial_sharing_supported (FALSE);
res = collect_methods (acfg);
if (!res)
#ifdef ENABLE_LLVM
if (acfg->llvm) {
llvm_acfg = acfg;
- mono_llvm_create_aot_module (acfg->llvm_got_symbol_base, acfg->llvm_separate, acfg->llvm_separate);
+ mono_llvm_create_aot_module (acfg->llvm_got_symbol_base, TRUE, TRUE);
}
#endif
{
MonoJumpInfo *ji;
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
ji->type = MONO_PATCH_INFO_IMAGE;
ji->data.image = acfg->image;
get_got_offset (acfg, TRUE, ji);
/* Slot 1 is reserved for the mscorlib got addr */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
+ 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);
/* This is very common */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
+ 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 (MonoAotCompile));
+ 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);
acfg->tmpbasename = g_strdup_printf ("%s", acfg->image->name);
acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
}
- if (acfg->llvm_separate) {
- g_assert (acfg->aot_opts.llvm_outfile);
- acfg->llvm_sfile = g_strdup (acfg->aot_opts.llvm_outfile);
- }
+ g_assert (acfg->aot_opts.llvm_outfile);
+ acfg->llvm_sfile = g_strdup (acfg->aot_opts.llvm_outfile);
} else {
acfg->tmpbasename = g_strdup_printf ("%s", "temp");
acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
acfg->w = img_writer_create (acfg->fp, TRUE);
acfg->use_bin_writer = TRUE;
} else {
- if (acfg->llvm && !acfg->llvm_separate) {
- /* Append to the .s file created by llvm */
- /* FIXME: Use multiple files instead */
- acfg->fp = fopen (acfg->tmpfname, "a+");
+ if (acfg->aot_opts.asm_only) {
+ if (acfg->aot_opts.outfile)
+ acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
+ else
+ acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
+ acfg->fp = fopen (acfg->tmpfname, "w+");
} else {
- if (acfg->aot_opts.asm_only) {
- if (acfg->aot_opts.outfile)
- acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
- else
- acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
- acfg->fp = fopen (acfg->tmpfname, "w+");
- } else {
- int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
- acfg->fp = fdopen (i, "w+");
- }
+ int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
+ acfg->fp = fdopen (i, "w+");
}
if (acfg->fp == 0) {
aot_printerrf (acfg, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno));
if (COMPILE_LLVM (cfg))
cfg->asm_symbol = g_strdup_printf ("%s%s", acfg->llvm_label_prefix, cfg->llvm_method_name);
- else if (acfg->global_symbols || acfg->llvm_separate)
+ else if (acfg->global_symbols || acfg->llvm)
cfg->asm_symbol = get_debug_sym (cfg->orig_method, "", acfg->method_label_hash);
else
cfg->asm_symbol = g_strdup_printf ("%s%sm_%x", acfg->temp_prefix, acfg->llvm_label_prefix, method_index);