gboolean dwarf_debug;
gboolean soft_debug;
gboolean log_generics;
+ gboolean log_instances;
gboolean direct_pinvoke;
gboolean direct_icalls;
gboolean no_direct_calls;
gboolean autoreg;
char *mtriple;
char *llvm_path;
+ char *instances_logfile_path;
} MonoAotOptions;
typedef struct MonoAotStats {
int ccount, mcount, lmfcount, abscount, gcount, ocount, genericcount;
- int code_size, info_size, ex_info_size, unwind_info_size, got_size, class_info_size, got_info_size;
+ int code_size, info_size, ex_info_size, unwind_info_size, got_size, class_info_size, got_info_size, plt_size;
int methods_without_got_slots, direct_calls, all_calls, llvm_count;
int got_slots, offsets_size;
int got_slot_types [MONO_PATCH_INFO_NONE];
int objc_selector_index, objc_selector_index_2;
GPtrArray *objc_selectors;
GHashTable *objc_selector_to_index;
+ FILE *instances_logfile;
} MonoAotCompile;
typedef struct {
fprintf (acfg->fp, ".code 32\n");
}
+static inline void
+emit_code_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
+{
+ emit_bytes (acfg, buf, size);
+}
+
/* ARCHITECTURE SPECIFIC CODE */
#if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_POWERPC)
#endif
}
+#ifdef MONO_ARCH_AOT_SUPPORTED
/*
* arch_emit_direct_call:
*
* calling code.
*/
static void
-arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, MonoJumpInfo *ji, int *call_size)
+arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, gboolean thumb, MonoJumpInfo *ji, int *call_size)
{
#if defined(TARGET_X86) || defined(TARGET_AMD64)
/* Need to make sure this is exactly 5 bytes long */
emit_bytes (acfg, buf, 4);
} else {
emit_unset_mode (acfg);
- fprintf (acfg->fp, "bl %s\n", target);
+ if (thumb)
+ fprintf (acfg->fp, "blx %s\n", target);
+ else
+ fprintf (acfg->fp, "bl %s\n", target);
}
*call_size = 4;
#elif defined(TARGET_POWERPC)
g_assert_not_reached ();
#endif
}
+#endif
/*
* PPC32 design:
#endif
+#ifdef MONO_ARCH_AOT_SUPPORTED
/*
* arch_emit_objc_selector_ref:
*
g_assert_not_reached ();
#endif
}
+#endif
/*
* arch_emit_plt_entry:
emit_symbol_diff (acfg, acfg->got_symbol, ".", ((acfg->plt_got_offset_base + index) * sizeof (gpointer)) -4);
/* Used by mono_aot_get_plt_info_offset */
emit_int32 (acfg, acfg->plt_got_info_offsets [index]);
+ acfg->stats.plt_size += 10;
#elif defined(__native_client_codegen__)
guint8 buf [256];
guint8 *buf_aligned = ALIGN_TO(buf, kNaClAlignment);
} else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_AOT) {
encode_method_ref (acfg, info->d.managed_to_native.method, p, &p);
} else {
- g_assert (info->subtype == WRAPPER_SUBTYPE_NONE);
+ g_assert (info->subtype == WRAPPER_SUBTYPE_NONE || info->subtype == WRAPPER_SUBTYPE_PINVOKE);
encode_method_ref (acfg, info->d.managed_to_native.method, p, &p);
}
break;
* so there is only one wrapper of a given type, or inlining their contents into their
* callers.
*/
-
- /*
- * FIXME: This depends on the fact that different wrappers have different
- * names.
- */
-
for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
MonoMethod *method;
guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
(method->flags & METHOD_ATTRIBUTE_ABSTRACT))
skip = TRUE;
- if (method->is_generic || method->klass->generic_container)
- skip = TRUE;
-
/* Skip methods which can not be handled by get_runtime_invoke () */
sig = mono_method_signature (method);
if (!sig)
if ((sig->ret->type == MONO_TYPE_PTR) ||
(sig->ret->type == MONO_TYPE_TYPEDBYREF))
skip = TRUE;
+ if (mono_class_is_open_constructed_type (sig->ret))
+ skip = TRUE;
for (j = 0; j < sig->param_count; j++) {
if (sig->params [j]->type == MONO_TYPE_TYPEDBYREF)
skip = TRUE;
+ if (mono_class_is_open_constructed_type (sig->params [j]))
+ skip = TRUE;
}
#ifdef MONO_ARCH_DYN_CALL_SUPPORTED
#endif
/* JIT icall wrappers */
- /* FIXME: locking */
+ /* FIXME: locking - this is "safe" as full-AOT threads don't mutate the icall hash*/
g_hash_table_foreach (mono_get_jit_icall_info (), add_jit_icall_wrapper, acfg);
}
return FALSE;
}
+static void
+add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method);
+
/*
* add_generic_class:
*
* Use gsharedvt for generic collections with vtype arguments to avoid code blowup.
* Enable this only for some classes since gsharedvt might not support all methods.
*/
- if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && klass->generic_class && klass->generic_class->context.class_inst && is_vt_inst (klass->generic_class->context.class_inst) && (!strcmp (klass->name, "Dictionary`2") || !strcmp (klass->name, "List`1")))
+ if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && klass->generic_class && klass->generic_class->context.class_inst && is_vt_inst (klass->generic_class->context.class_inst) &&
+ (!strcmp (klass->name, "Dictionary`2") || !strcmp (klass->name, "List`1") || !strcmp (klass->name, "ReadOnlyCollection`1")))
use_gsharedvt = TRUE;
iter = NULL;
continue;
}
- if (mono_method_is_generic_sharable_full (method, FALSE, FALSE, use_gsharedvt))
+ if (mono_method_is_generic_sharable_full (method, FALSE, FALSE, use_gsharedvt)) {
/* Already added */
+ add_types_from_method_header (acfg, method);
continue;
+ }
if (method->is_generic)
/* FIXME: */
return FALSE;
}
+#ifdef MONO_ARCH_AOT_SUPPORTED
static const char *
get_pinvoke_import (MonoAotCompile *acfg, MonoMethod *method)
{
return import;
}
+#endif
static gint
compare_lne (MonoDebugLineNumberEntry *a, MonoDebugLineNumberEntry *b)
return findex;
}
+#define INST_LEN 1
+
/*
* emit_and_reloc_code:
*
MonoJumpInfo *patch_info;
MonoMethodHeader *header;
MonoDebugSourceLocation **locs = NULL;
- gboolean skip, direct_call, external_call;
+ gboolean skip;
+#ifdef MONO_ARCH_AOT_SUPPORTED
+ gboolean direct_call, external_call;
guint32 got_slot;
const char *direct_call_target = 0;
const char *direct_pinvoke;
+#endif
if (method) {
header = mono_method_get_header (method);
g_ptr_array_sort (patches, compare_patches);
start_index = 0;
- for (i = 0; i < code_len; i++) {
+ for (i = 0; i < code_len; i += INST_LEN) {
patch_info = NULL;
for (pindex = start_index; pindex < patches->len; ++pindex) {
patch_info = g_ptr_array_index (patches, pindex);
int code_size;
arch_emit_got_offset (acfg, code + i, &code_size);
- i += code_size - 1;
+ i += code_size - INST_LEN;
skip = TRUE;
patch_info->type = MONO_PATCH_INFO_NONE;
break;
}
arch_emit_objc_selector_ref (acfg, code + i, index, &code_size);
- i += code_size - 1;
+ i += code_size - INST_LEN;
skip = TRUE;
patch_info->type = MONO_PATCH_INFO_NONE;
break;
if (direct_call) {
int call_size;
- arch_emit_direct_call (acfg, direct_call_target, external_call, patch_info, &call_size);
- i += call_size - 1;
+ arch_emit_direct_call (acfg, direct_call_target, external_call, FALSE, patch_info, &call_size);
+ i += call_size - INST_LEN;
} else {
int code_size;
got_slot = get_got_offset (acfg, patch_info);
arch_emit_got_access (acfg, code + i, got_slot, &code_size);
- i += code_size - 1;
+ i += code_size - INST_LEN;
}
skip = TRUE;
}
if (pindex < patches->len && patch_info->ip.i > i) {
int limit;
- for (limit = i + 1; limit < patch_info->ip.i; ++limit) {
+ for (limit = i + INST_LEN; limit < patch_info->ip.i; limit += INST_LEN) {
if (locs && locs [limit])
break;
}
- emit_bytes (acfg, code + i, limit - i);
- i = limit - 1;
+ emit_code_bytes (acfg, code + i, limit - i);
+ i = limit - INST_LEN;
} else {
- emit_bytes (acfg, code + i, 1);
+ emit_code_bytes (acfg, code + i, INST_LEN);
}
}
}
/*
* sanitize_symbol:
*
- * Modify SYMBOL so it only includes characters permissible in symbols.
+ * Return a modified version of S which only includes characters permissible in symbols.
*/
-static void
-sanitize_symbol (char *symbol)
+static char*
+sanitize_symbol (MonoAotCompile *acfg, char *s)
{
- int i, len = strlen (symbol);
+ gboolean process = FALSE;
+ int i, len;
+ GString *gs;
+ char *res;
+ if (!s)
+ return s;
+
+ len = strlen (s);
for (i = 0; i < len; ++i)
- if (!isalnum (symbol [i]) && (symbol [i] != '_'))
- symbol [i] = '_';
+ if (!(s [i] <= 0x7f && (isalnum (s [i]) || s [i] == '_')))
+ process = TRUE;
+ if (!process)
+ return s;
+
+ gs = g_string_sized_new (len);
+ for (i = 0; i < len; ++i) {
+ guint8 c = s [i];
+ if (c <= 0x7f && (isalnum (c) || c == '_')) {
+ g_string_append_c (gs, c);
+ } else if (c > 0x7f) {
+ /* multi-byte utf8 */
+ g_string_append_printf (gs, "_0x%x", c);
+ i ++;
+ c = s [i];
+ while (c >> 6 == 0x2) {
+ g_string_append_printf (gs, "%x", c);
+ i ++;
+ c = s [i];
+ }
+ g_string_append_printf (gs, "_");
+ i --;
+ } else {
+ g_string_append_c (gs, '_');
+ }
+ }
+
+ res = mono_mempool_strdup (acfg->mempool, gs->str);
+ g_string_free (gs, TRUE);
+ return res;
}
static char*
case MONO_PATCH_INFO_METHOD_JUMP:
case MONO_PATCH_INFO_ICALL_ADDR:
case MONO_PATCH_INFO_METHOD_RGCTX:
+ case MONO_PATCH_INFO_METHOD_CODE_SLOT:
encode_method_ref (acfg, patch_info->data.method, p, &p);
break;
case MONO_PATCH_INFO_INTERNAL_METHOD:
case MONO_PATCH_INFO_CLASS:
case MONO_PATCH_INFO_IID:
case MONO_PATCH_INFO_ADJUSTED_IID:
+ case MONO_PATCH_INFO_CLASS_INIT:
encode_klass_ref (acfg, patch_info->data.klass, p, &p);
break;
- case MONO_PATCH_INFO_CLASS_INIT:
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
- encode_klass_ref (acfg, patch_info->data.klass, p, &p);
+ encode_klass_ref (acfg, patch_info->data.del_tramp->klass, p, &p);
+ if (patch_info->data.del_tramp->method) {
+ encode_value (1, p, &p);
+ encode_method_ref (acfg, patch_info->data.del_tramp->method, p, &p);
+ } else {
+ encode_value (0, p, &p);
+ }
break;
case MONO_PATCH_INFO_FIELD:
case MONO_PATCH_INFO_SFLDA:
int i;
encode_method_ref (acfg, info->method, p, &p);
- encode_value (info->entries->len, p, &p);
- for (i = 0; i < info->entries->len; ++i) {
- MonoRuntimeGenericContextInfoTemplate *template = g_ptr_array_index (info->entries, i);
+ encode_value (info->num_entries, p, &p);
+ for (i = 0; i < info->num_entries; ++i) {
+ MonoRuntimeGenericContextInfoTemplate *template = &info->entries [i];
encode_value (template->info_type, p, &p);
switch (mini_rgctx_info_type_to_patch_info_type (template->info_type)) {
get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache)
{
char *debug_sym = NULL;
+ char *s;
switch (ji->type) {
case MONO_PATCH_INFO_METHOD:
debug_sym = g_strdup_printf ("plt__jit_icall_%s", ji->data.name);
break;
case MONO_PATCH_INFO_CLASS_INIT:
- debug_sym = g_strdup_printf ("plt__class_init_%s", mono_type_get_name (&ji->data.klass->byval_arg));
- sanitize_symbol (debug_sym);
+ s = mono_type_get_name (&ji->data.klass->byval_arg);
+ debug_sym = g_strdup_printf ("plt__class_init_%s", s);
+ g_free (s);
break;
case MONO_PATCH_INFO_RGCTX_FETCH:
debug_sym = g_strdup_printf ("plt__rgctx_fetch_%d", acfg->label_generator ++);
break;
}
- return debug_sym;
+ return sanitize_symbol (acfg, debug_sym);
}
/*
opts->no_instances = TRUE;
} else if (str_begins_with (arg, "log-generics")) {
opts->log_generics = TRUE;
+ } else if (str_begins_with (arg, "log-instances=")) {
+ opts->log_instances = TRUE;
+ opts->instances_logfile_path = g_strdup (arg + strlen ("log-instances="));
+ } else if (str_begins_with (arg, "log-instances")) {
+ opts->log_instances = TRUE;
} else if (str_begins_with (arg, "mtriple=")) {
opts->mtriple = g_strdup (arg + strlen ("mtriple="));
} else if (str_begins_with (arg, "llvm-path=")) {
{
switch (patch_info->type) {
case MONO_PATCH_INFO_METHOD:
- case MONO_PATCH_INFO_METHODCONST: {
+ case MONO_PATCH_INFO_METHODCONST:
+ case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
MonoMethod *method = patch_info->data.method;
return can_encode_method (acfg, method);
}
case MONO_PATCH_INFO_VTABLE:
case MONO_PATCH_INFO_CLASS_INIT:
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
case MONO_PATCH_INFO_CLASS:
case MONO_PATCH_INFO_IID:
case MONO_PATCH_INFO_ADJUSTED_IID:
return FALSE;
}
break;
+ case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
+ if (!can_encode_class (acfg, patch_info->data.del_tramp->klass)) {
+ //printf ("Skip: %s\n", mono_type_full_name (&patch_info->data.klass->byval_arg));
+ return FALSE;
+ }
+ break;
+ }
case MONO_PATCH_INFO_RGCTX_FETCH: {
MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
* the runtime will not see AOT methods during AOT compilation,so it
* does not need to support them by creating a fake GOT etc.
*/
- cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), FALSE, TRUE, 0);
+ cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), acfg->aot_opts.full_aot ? (JIT_FLAG_AOT|JIT_FLAG_FULL_AOT) : (JIT_FLAG_AOT), 0);
mono_loader_clear_error ();
if (cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
return;
}
+ if (method->is_inflated && acfg->aot_opts.log_instances) {
+ if (acfg->instances_logfile)
+ fprintf (acfg->instances_logfile, "%s ### %d\n", mono_method_full_name (method, TRUE), cfg->code_size);
+ else
+ printf ("%s ### %d\n", mono_method_full_name (method, TRUE), cfg->code_size);
+ }
+
/* Adds generic instances referenced by this method */
/*
* The depth is used to avoid infinite loops when generic virtual recursion is
* 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 -preverify -domtree -verify");
- opts = g_strdup ("-targetlibinfo -no-aa -basicaa -notti -instcombine -simplifycfg -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 -dse -adce -simplifycfg -instcombine -strip-dead-prototypes -preverify -domtree -verify");
+ //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 */
+ /*
+ * The dse bug is in DeadStoreElimination.cpp:isOverwrite ():
+ * // If we have no DataLayout information around, then the size of the store
+ * // is inferrable from the pointee type. If they are the same type, then
+ * // we know that the store is safe.
+ * if (AA.getDataLayout() == 0 &&
+ * Later.Ptr->getType() == Earlier.Ptr->getType()) {
+ * 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 -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);
printf ("Executing opt: %s\n", command);
}
}
-#ifdef MONOTOUCH
if (acfg->direct_method_addresses) {
acfg->flags |= MONO_AOT_FILE_FLAG_DIRECT_METHOD_ADDRESSES;
fprintf (acfg->fp, " .no_dead_strip %s\n", symbol);
for (i = 0; i < acfg->nmethods; ++i) {
- if (acfg->cfgs [i]) {
- if (acfg->thumb_mixed && acfg->cfgs [i]->compile_llvm)
- fprintf (acfg->fp, "\tblx %s\n", acfg->cfgs [i]->asm_symbol);
- else
- fprintf (acfg->fp, "\tbl %s\n", acfg->cfgs [i]->asm_symbol);
- } else {
- fprintf (acfg->fp, "\tbl method_addresses\n");
- }
+ int call_size;
+
+#ifdef MONO_ARCH_AOT_SUPPORTED
+ if (acfg->cfgs [i])
+ arch_emit_direct_call (acfg, acfg->cfgs [i]->asm_symbol, FALSE, acfg->thumb_mixed && acfg->cfgs [i]->compile_llvm, NULL, &call_size);
+ else
+ arch_emit_direct_call (acfg, "method_addresses", FALSE, FALSE, NULL, &call_size);
+#endif
}
sprintf (symbol, "method_addresses_end");
}
}
}
-#else
- sprintf (symbol, "code_offsets");
- emit_section_change (acfg, RODATA_SECT, 1);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
-
- acfg->stats.offsets_size += acfg->nmethods * 4;
-
- for (i = 0; i < acfg->nmethods; ++i) {
- if (acfg->cfgs [i]) {
- emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, acfg->methods_symbol, 0);
- } else {
- emit_int32 (acfg, 0xffffffff);
- }
- }
-#endif
emit_line (acfg);
/* Emit a sorted table mapping methods to their unbox trampolines */
method = cfg->orig_method;
if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype) {
+ int call_size;
+
index = get_method_index (acfg, method);
sprintf (symbol, "ut_%d", index);
emit_int32 (acfg, index);
if (acfg->direct_method_addresses) {
- emit_unset_mode (acfg);
- if (acfg->thumb_mixed && cfg->compile_llvm)
- fprintf (acfg->fp, "\n\tblx %s\n", symbol);
- else
- fprintf (acfg->fp, "\n\tbl %s\n", symbol);
+#ifdef MONO_ARCH_AOT_SUPPORTED
+ arch_emit_direct_call (acfg, symbol, FALSE, acfg->thumb_mixed && cfg->compile_llvm, NULL, &call_size);
+#endif
} else {
emit_symbol_diff (acfg, symbol, acfg->methods_symbol, 0);
}
if (!method) {
printf ("Failed to load method 0x%x from '%s'.\n", token, image->name);
+ printf ("Run with MONO_LOG_LEVEL=debug for more information.\n");
exit (1);
}
user_data [1] = acfg;
user_data [2] = frag;
- handle = mono_create_thread (NULL, 0, (gpointer)compile_thread_main, user_data, 0, NULL);
+ handle = mono_threads_create_thread ((gpointer)compile_thread_main, user_data, 0, 0, NULL);
g_ptr_array_add (threads, handle);
}
g_free (methods);
#elif defined(sparc) && SIZEOF_VOID_P == 8
#define AS_OPTIONS "-xarch=v9"
#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
-#define AS_OPTIONS "-arch i386 -W"
+#define AS_OPTIONS "-arch i386"
#else
#define AS_OPTIONS ""
#endif
mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
{
MonoImage *image = ass->image;
- int i, res;
+ int i, res, all_sizes;
MonoAotCompile *acfg;
char *outfile_name, *tmp_outfile_name, *p;
char llvm_stats_msg [256];
TV_DECLARE (atv);
TV_DECLARE (btv);
-#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || (!defined(MONO_EXTENSIONS) && !defined(MONOTOUCH))
+#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || !defined(ENABLE_GSHAREDVT)
if (opts & MONO_OPT_GSHAREDVT) {
fprintf (stderr, "-O=gsharedvt not supported on this platform.\n");
exit (1);
if (acfg->aot_opts.full_aot)
acfg->flags |= MONO_AOT_FILE_FLAG_FULL_AOT;
+ if (acfg->aot_opts.instances_logfile_path) {
+ acfg->instances_logfile = fopen (acfg->aot_opts.instances_logfile_path, "w");
+ if (!acfg->instances_logfile) {
+ fprintf (stderr, "Unable to create logfile: '%s'.\n", acfg->aot_opts.instances_logfile_path);
+ exit (1);
+ }
+ }
+
load_profile_files (acfg);
acfg->num_trampolines [MONO_AOT_TRAMP_SPECIFIC] = acfg->aot_opts.full_aot ? acfg->aot_opts.ntrampolines : 0;
if (acfg->aot_opts.dwarf_debug && acfg->aot_opts.asm_only && acfg->aot_opts.gnu_asm) {
/*
* CLANG supports GAS .file/.loc directives, so emit line number information this way
+ * FIXME: CLANG only emits line number info for .loc directives followed by assembly, not
+ * .byte directives.
*/
- acfg->gas_line_numbers = TRUE;
+ //acfg->gas_line_numbers = TRUE;
}
if (!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) {
img_writer_emit_start (acfg->w);
if (acfg->dwarf)
- mono_dwarf_writer_emit_base_info (acfg->dwarf, mono_unwind_get_cie_program ());
+ mono_dwarf_writer_emit_base_info (acfg->dwarf, g_path_get_basename (acfg->image->name), mono_unwind_get_cie_program ());
if (acfg->thumb_mixed) {
char symbol [256];
sprintf (llvm_stats_msg, ", LLVM: %d (%d%%)", acfg->stats.llvm_count, acfg->stats.mcount ? (acfg->stats.llvm_count * 100) / acfg->stats.mcount : 100);
else
strcpy (llvm_stats_msg, "");
- printf ("Code: %d Info: %d Ex Info: %d Unwind Info: %d Class Info: %d PLT: %d GOT Info: %d GOT: %d Offsets: %d\n", acfg->stats.code_size, acfg->stats.info_size, acfg->stats.ex_info_size, acfg->stats.unwind_info_size, acfg->stats.class_info_size, acfg->plt_offset, acfg->stats.got_info_size, (int)(acfg->got_offset * sizeof (gpointer)), acfg->stats.offsets_size);
+
+ all_sizes = acfg->stats.code_size + acfg->stats.info_size + acfg->stats.ex_info_size + acfg->stats.unwind_info_size + acfg->stats.class_info_size + acfg->stats.got_info_size + acfg->stats.offsets_size + acfg->stats.plt_size;
+
+ printf ("Code: %d(%d%%) Info: %d(%d%%) Ex Info: %d(%d%%) Unwind Info: %d(%d%%) Class Info: %d(%d%%) PLT: %d(%d%%) GOT Info: %d(%d%%) Offsets: %d(%d%%) GOT: %d\n",
+ acfg->stats.code_size, acfg->stats.code_size * 100 / all_sizes,
+ acfg->stats.info_size, acfg->stats.info_size * 100 / all_sizes,
+ acfg->stats.ex_info_size, acfg->stats.ex_info_size * 100 / all_sizes,
+ acfg->stats.unwind_info_size, acfg->stats.unwind_info_size * 100 / all_sizes,
+ acfg->stats.class_info_size, acfg->stats.class_info_size * 100 / all_sizes,
+ acfg->stats.plt_size ? acfg->stats.plt_size : acfg->plt_offset, acfg->stats.plt_size ? acfg->stats.plt_size * 100 / all_sizes : 0,
+ acfg->stats.got_info_size, acfg->stats.got_info_size * 100 / all_sizes,
+ acfg->stats.offsets_size, acfg->stats.offsets_size * 100 / all_sizes,
+ (int)(acfg->got_offset * sizeof (gpointer)));
printf ("Compiled: %d/%d (%d%%)%s, No GOT slots: %d (%d%%), Direct calls: %d (%d%%)\n",
acfg->stats.ccount, acfg->stats.mcount, acfg->stats.mcount ? (acfg->stats.ccount * 100) / acfg->stats.mcount : 100,
llvm_stats_msg,