gboolean write_symbols;
gboolean metadata_only;
gboolean bind_to_runtime_version;
- gboolean full_aot;
+ MonoAotMode mode;
gboolean no_dlsym;
gboolean static_link;
gboolean asm_only;
gboolean autoreg;
char *mtriple;
char *llvm_path;
+ char *temp_path;
char *instances_logfile_path;
char *logfile;
gboolean dump_json;
GHashTable *unwind_info_offsets;
GPtrArray *unwind_ops;
guint32 unwind_info_offset;
- char *got_symbol_base;
- char *llvm_got_symbol_base;
+ char *global_prefix;
char *got_symbol;
char *llvm_got_symbol;
char *plt_symbol;
- char *methods_symbol;
char *llvm_eh_frame_symbol;
GHashTable *method_label_hash;
const char *temp_prefix;
int align_pad_value;
guint32 label_generator;
gboolean llvm;
+ gboolean has_jitted_code;
MonoAotFileFlags flags;
MonoDynamicStream blob;
MonoClass **typespec_classes;
*endbuf = p;
}
+static void
+encode_int (gint32 val, guint8 *buf, guint8 **endbuf)
+{
+ // FIXME: Big-endian
+ buf [0] = (val >> 0) & 0xff;
+ buf [1] = (val >> 8) & 0xff;
+ buf [2] = (val >> 16) & 0xff;
+ buf [3] = (val >> 24) & 0xff;
+
+ *endbuf = buf + 4;
+}
+
+static void
+encode_int16 (guint16 val, guint8 *buf, guint8 **endbuf)
+{
+ buf [0] = (val >> 0) & 0xff;
+ buf [1] = (val >> 8) & 0xff;
+
+ *endbuf = buf + 2;
+}
+
+static void
+encode_string (const char *s, guint8 *buf, guint8 **endbuf)
+{
+ int len = strlen (s);
+
+ memcpy (buf, s, len + 1);
+ *endbuf = buf + len + 1;
+}
+
static void
emit_unset_mode (MonoAotCompile *acfg)
{
guint8 *code;
guint8 *loop_start, *loop_branch_back, *loop_end_check, *imt_found_check;
int i;
+ int pagesize = MONO_AOT_TRAMP_PAGE_SIZE;
#define COMMON_TRAMP_SIZE 16
- int count = (mono_pagesize () - COMMON_TRAMP_SIZE) / 8;
+ int count = (pagesize - COMMON_TRAMP_SIZE) / 8;
int imm8, rot_amount;
char symbol [128];
if (!acfg->aot_opts.use_trampolines_page)
return;
- acfg->tramp_page_size = mono_pagesize ();
+ acfg->tramp_page_size = pagesize;
sprintf (symbol, "%sspecific_trampolines_page", acfg->user_symbol_prefix);
- emit_alignment (acfg, mono_pagesize ());
+ emit_alignment (acfg, pagesize);
emit_global (acfg, symbol, TRUE);
emit_label (acfg, symbol);
/* emit the generic code first, the trampoline address + 8 is in the lr register */
code = buf;
- imm8 = mono_arm_is_rotated_imm8 (mono_pagesize (), &rot_amount);
+ imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
ARM_SUB_REG_IMM (code, ARMREG_LR, ARMREG_LR, imm8, rot_amount);
ARM_LDR_IMM (code, ARMREG_R1, ARMREG_LR, -8);
ARM_LDR_IMM (code, ARMREG_PC, ARMREG_LR, -4);
emit_global (acfg, symbol, TRUE);
emit_label (acfg, symbol);
code = buf;
- imm8 = mono_arm_is_rotated_imm8 (mono_pagesize (), &rot_amount);
+ imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
ARM_SUB_REG_IMM (code, ARMREG_IP, ARMREG_IP, imm8, rot_amount);
ARM_LDR_IMM (code, MONO_ARCH_RGCTX_REG, ARMREG_IP, -8);
ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, -4);
emit_label (acfg, symbol);
code = buf;
ARM_PUSH (code, (1 << ARMREG_R0) | (1 << ARMREG_R1) | (1 << ARMREG_R2) | (1 << ARMREG_R3));
- imm8 = mono_arm_is_rotated_imm8 (mono_pagesize (), &rot_amount);
+ imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
ARM_SUB_REG_IMM (code, ARMREG_IP, ARMREG_IP, imm8, rot_amount);
ARM_LDR_IMM (code, ARMREG_R0, ARMREG_IP, -8);
ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, -4);
/* Need at least two free registers, plus a slot for storing the pc */
ARM_PUSH (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_R2));
- imm8 = mono_arm_is_rotated_imm8 (mono_pagesize (), &rot_amount);
+ imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
ARM_SUB_REG_IMM (code, ARMREG_IP, ARMREG_IP, imm8, rot_amount);
ARM_LDR_IMM (code, ARMREG_R0, ARMREG_IP, -8);
* a given entry. Returns the size of the table.
*/
static guint32
-emit_offset_table (MonoAotCompile *acfg, int noffsets, int group_size, gint32 *offsets)
+emit_offset_table (MonoAotCompile *acfg, const char *symbol, int noffsets, int group_size, gint32 *offsets)
{
gint32 current_offset;
int i, buf_size, ngroups, index_entry_size;
guint8 *p, *buf;
+ guint8 *data_p, *data_buf;
guint32 *index_offsets;
ngroups = (noffsets + (group_size - 1)) / group_size;
}
current_offset = offsets [i];
}
+ data_buf = buf;
+ data_p = p;
if (ngroups && index_offsets [ngroups - 1] < 65000)
index_entry_size = 2;
else
index_entry_size = 4;
+ buf_size = (data_p - data_buf) + (ngroups * 4) + 16;
+ p = buf = g_malloc0 (buf_size);
+
/* Emit the header */
- emit_int32 (acfg, noffsets);
- emit_int32 (acfg, group_size);
- emit_int32 (acfg, ngroups);
- emit_int32 (acfg, index_entry_size);
+ encode_int (noffsets, p, &p);
+ encode_int (group_size, p, &p);
+ encode_int (ngroups, p, &p);
+ encode_int (index_entry_size, p, &p);
/* Emit the index */
for (i = 0; i < ngroups; ++i) {
if (index_entry_size == 2)
- emit_int16 (acfg, index_offsets [i]);
+ encode_int16 (index_offsets [i], p, &p);
else
- emit_int32 (acfg, index_offsets [i]);
+ encode_int (index_offsets [i], p, &p);
}
-
/* Emit the data */
+ memcpy (p, data_buf, data_p - data_buf);
+ p += data_p - data_buf;
+
+ 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);
- return (int)(p - buf) + (ngroups * 4);
+ g_free (buf);
+ g_free (data_buf);
+
+ return (int)(p - buf);
}
static guint32
case MONO_PATCH_INFO_ICALL_ADDR:
case MONO_PATCH_INFO_CLASS_INIT:
case MONO_PATCH_INFO_RGCTX_FETCH:
- case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
case MONO_PATCH_INFO_MONITOR_ENTER:
case MONO_PATCH_INFO_MONITOR_ENTER_V4:
case MONO_PATCH_INFO_MONITOR_EXIT:
g_ptr_array_add (acfg->extra_methods, method);
}
+static gboolean
+prefer_gsharedvt_method (MonoAotCompile *acfg, MonoMethod *method)
+{
+ /* One instantiation with valuetypes is generated for each async method */
+ if (method->klass->image == mono_defaults.corlib && (!strcmp (method->klass->name, "AsyncMethodBuilderCore") || !strcmp (method->klass->name, "AsyncVoidMethodBuilder")))
+ return TRUE;
+ else
+ return FALSE;
+}
+
static guint32
get_method_index (MonoAotCompile *acfg, MonoMethod *method)
{
static void
add_extra_method_with_depth (MonoAotCompile *acfg, MonoMethod *method, int depth)
{
- if (mono_method_is_generic_sharable_full (method, FALSE, TRUE, FALSE))
+ if (mono_method_is_generic_sharable_full (method, TRUE, TRUE, FALSE))
method = mini_get_shared_method (method);
+ else if ((acfg->opts & MONO_OPT_GSHAREDVT) && prefer_gsharedvt_method (acfg, method) && mono_method_is_generic_sharable_full (method, FALSE, FALSE, TRUE))
+ /* Use the gsharedvt version */
+ return;
if (acfg->aot_opts.log_generics)
aot_printf (acfg, "%*sAdding method %s.\n", depth, "", mono_method_full_name (method, TRUE));
/* Managed Allocators */
nallocators = mono_gc_get_managed_allocator_types ();
for (i = 0; i < nallocators; ++i) {
- m = mono_gc_get_managed_allocator_by_type (i);
+ m = mono_gc_get_managed_allocator_by_type (i, TRUE);
+ if (m)
+ add_method (acfg, m);
+ }
+ for (i = 0; i < nallocators; ++i) {
+ m = mono_gc_get_managed_allocator_by_type (i, FALSE);
if (m)
add_method (acfg, m);
}
for (j = 0; j < cattr->num_attrs; ++j)
if (cattr->attrs [j].ctor && (!strcmp (cattr->attrs [j].ctor->klass->name, "MonoNativeFunctionWrapperAttribute") || !strcmp (cattr->attrs [j].ctor->klass->name, "UnmanagedFunctionPointerAttribute")))
break;
- if (j < cattr->num_attrs)
- add_method (acfg, mono_marshal_get_native_func_wrapper_aot (klass));
+ if (j < cattr->num_attrs) {
+ MonoMethod *invoke;
+ MonoMethod *wrapper;
+ MonoMethod *del_invoke;
+
+ /* Add wrappers needed by mono_ftnptr_to_delegate () */
+ invoke = mono_get_delegate_invoke (klass);
+ wrapper = mono_marshal_get_native_func_wrapper_aot (klass);
+ del_invoke = mono_marshal_get_delegate_invoke_internal (invoke, FALSE, TRUE, wrapper);
+ add_method (acfg, wrapper);
+ add_method (acfg, del_invoke);
+ }
}
} else if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->generic_container) {
MonoError error;
return FALSE;
}
+static
+gboolean mono_aot_mode_is_full (MonoAotOptions *opts)
+{
+ return opts->mode == MONO_AOT_MODE_FULL;
+}
+
static void add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, const char *ref);
static void
add_generic_class (MonoAotCompile *acfg, MonoClass *klass, gboolean force, const char *ref)
{
/* This might lead to a huge code blowup so only do it if neccesary */
- if (!acfg->aot_opts.full_aot && !force)
+ if (!mono_aot_mode_is_full (&acfg->aot_opts) && !force)
return;
add_generic_class_with_depth (acfg, klass, 0, ref);
add_generic_class (acfg, mono_class_inflate_generic_class (gcomparer, &ctx), FALSE, "EqualityComparer<T>");
}
}
+
+ /* Add an instance of EnumComparer<T> which is created dynamically by EqualityComparer<T> for enums */
+ if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
+ MonoClass *enum_comparer;
+ MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoGenericContext ctx;
+ MonoType *args [16];
+
+ if (mono_class_is_enum (tclass)) {
+ memset (&ctx, 0, sizeof (ctx));
+ args [0] = &tclass->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+
+ enum_comparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "EnumEqualityComparer`1");
+ g_assert (enum_comparer);
+ add_generic_class (acfg, mono_class_inflate_generic_class (enum_comparer, &ctx), FALSE, "EqualityComparer<T>");
+ }
+ }
+
+ /* Add an instance of ObjectComparer<T> which is created dynamically by Comparer<T> for enums */
+ if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
+ MonoClass *comparer;
+ MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoGenericContext ctx;
+ MonoType *args [16];
+
+ if (mono_class_is_enum (tclass)) {
+ memset (&ctx, 0, sizeof (ctx));
+ args [0] = &tclass->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+
+ comparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "ObjectComparer`1");
+ g_assert (comparer);
+ add_generic_class (acfg, mono_class_inflate_generic_class (comparer, &ctx), FALSE, "Comparer<T>");
+ }
+ }
}
static void
memcpy (name2, prefix, strlen (prefix));
j = strlen (prefix);
for (i = 0; i < len; ++i) {
- if (isalnum (name1 [i])) {
+ if (i == 0 && name1 [0] >= '0' && name1 [0] <= '9') {
+ name2 [j ++] = '_';
+ } else if (isalnum (name1 [i])) {
name2 [j ++] = name1 [i];
} else if (name1 [i] == ' ' && name1 [i + 1] == '(' && name1 [i + 2] == ')') {
i += 2;
encode_patch (acfg, entry->data, p, &p);
break;
}
- case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
case MONO_PATCH_INFO_MONITOR_ENTER:
case MONO_PATCH_INFO_MONITOR_ENTER_V4:
case MONO_PATCH_INFO_MONITOR_EXIT:
emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
{
MonoMethod *method;
- GList *l;
int pindex, buf_size, n_patches;
GPtrArray *patches;
MonoJumpInfo *patch_info;
/* Not needed when loading the method */
encode_value (0, p, &p);
- /* String table */
- if (cfg->opt & MONO_OPT_SHARED) {
- encode_value (g_list_length (cfg->ldstr_list), p, &p);
- for (l = cfg->ldstr_list; l; l = l->next) {
- encode_value ((long)l->data, p, &p);
- }
- }
- else
- /* Used only in shared mode */
- g_assert (!cfg->ldstr_list);
+ g_assert (!(cfg->opt & MONO_OPT_SHARED));
n_patches = 0;
for (pindex = 0; pindex < patches->len; ++pindex) {
p += p2 - buf2;
g_free (buf2);
- if (gsctx && (gsctx->var_is_vt || gsctx->mvar_is_vt)) {
- MonoMethodInflated *inflated;
- MonoGenericContext *context;
- MonoGenericInst *inst;
-
- g_assert (jinfo->d.method->is_inflated);
- inflated = (MonoMethodInflated*)jinfo->d.method;
- context = &inflated->context;
-
+ if (gsctx && gsctx->is_gsharedvt) {
encode_value (1, p, &p);
- if (context->class_inst) {
- inst = context->class_inst;
-
- encode_value (inst->type_argc, p, &p);
- for (i = 0; i < inst->type_argc; ++i)
- encode_value (gsctx->var_is_vt [i], p, &p);
- } else {
- encode_value (0, p, &p);
- }
- if (context->method_inst) {
- inst = context->method_inst;
-
- encode_value (inst->type_argc, p, &p);
- for (i = 0; i < inst->type_argc; ++i)
- encode_value (gsctx->mvar_is_vt [i], p, &p);
- } else {
- encode_value (0, p, &p);
- }
} else {
encode_value (0, p, &p);
}
case MONO_PATCH_INFO_JIT_ICALL_ADDR:
debug_sym = g_strdup_printf ("%s_jit_icall_native_%s", prefix, ji->data.name);
break;
- case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
- debug_sym = g_strdup_printf ("%s_generic_class_init", prefix);
- break;
default:
break;
}
int tramp_type;
#endif
- if (!acfg->aot_opts.full_aot)
+ if (!mono_aot_mode_is_full (&acfg->aot_opts))
return;
g_assert (acfg->image->assembly);
emit_trampoline (acfg, acfg->got_offset, info);
}
- mono_arch_get_nullified_class_init_trampoline (&info);
- emit_trampoline (acfg, acfg->got_offset, info);
#if defined(MONO_ARCH_MONITOR_OBJECT_REG)
mono_arch_create_monitor_enter_trampoline (&info, FALSE, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
emit_trampoline (acfg, acfg->got_offset, info);
#endif
- mono_arch_create_generic_class_init_trampoline (&info, TRUE);
- emit_trampoline (acfg, acfg->got_offset, info);
-
/* Emit the exception related code pieces */
mono_arch_get_restore_context (&info, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
readonly_values = rdv;
}
+static gchar *
+clean_path (gchar * path)
+{
+ if (!path)
+ return NULL;
+
+ if (g_str_has_suffix (path, G_DIR_SEPARATOR_S))
+ return path;
+
+ gchar *clean = g_strconcat (path, G_DIR_SEPARATOR_S, NULL);
+ g_free (path);
+
+ return clean;
+}
+
static void
mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
{
opts->outfile = g_strdup (arg + strlen ("outfile="));
} else if (str_begins_with (arg, "llvm-outfile=")) {
opts->llvm_outfile = g_strdup (arg + strlen ("llvm-outfile="));
+ } else if (str_begins_with (arg, "temp-path=")) {
+ opts->temp_path = clean_path (g_strdup (arg + strlen ("temp-path=")));
} else if (str_begins_with (arg, "save-temps")) {
opts->save_temps = TRUE;
} else if (str_begins_with (arg, "keep-temps")) {
} else if (str_begins_with (arg, "bind-to-runtime-version")) {
opts->bind_to_runtime_version = TRUE;
} else if (str_begins_with (arg, "full")) {
- opts->full_aot = TRUE;
+ opts->mode = MONO_AOT_MODE_FULL;
+ } else if (str_begins_with (arg, "hybrid")) {
+ opts->mode = MONO_AOT_MODE_HYBRID;
} else if (str_begins_with (arg, "threads=")) {
opts->nthreads = atoi (arg + strlen ("threads="));
} else if (str_begins_with (arg, "static")) {
} else if (str_begins_with (arg, "mtriple=")) {
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);
- }
+ opts->llvm_path = clean_path (g_strdup (arg + strlen ("llvm-path=")));
} else if (!strcmp (arg, "llvm")) {
opts->llvm = TRUE;
} else if (str_begins_with (arg, "readonly-value=")) {
printf ("Supported options for --aot:\n");
printf (" outfile=\n");
printf (" llvm-outfile=\n");
+ printf (" llvm-path=\n");
+ printf (" temp-path=\n");
printf (" save-temps\n");
printf (" keep-temps\n");
printf (" write-symbols\n");
* does not need to support them by creating a fake GOT etc.
*/
flags = JIT_FLAG_AOT;
- if (acfg->aot_opts.full_aot)
+ if (mono_aot_mode_is_full (&acfg->aot_opts))
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);
+ cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), flags, 0, index);
mono_loader_clear_error ();
if (cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
return;
}
+ if (!cfg->compile_llvm)
+ acfg->has_jitted_code = TRUE;
+
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);
if (m->is_inflated) {
if (!(mono_class_generic_sharing_enabled (m->klass) &&
mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE)) &&
- !method_has_type_vars (m)) {
+ (!method_has_type_vars (m) || mono_method_is_generic_sharable_full (m, TRUE, TRUE, FALSE))) {
if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
- if (acfg->aot_opts.full_aot)
+ if (mono_aot_mode_is_full (&acfg->aot_opts) && !method_has_type_vars (m))
add_extra_method_with_depth (acfg, mono_marshal_get_native_wrapper (m, TRUE, TRUE), depth + 1);
} else {
add_extra_method_with_depth (acfg, m, depth + 1);
g_free (wstr);
g_free (command);
-#else
+#elif defined (HAVE_SYSTEM)
status = system (command);
+#else
+ g_assert_not_reached ();
#endif
return status;
*/
emit_section_change (acfg, ".text", 0);
emit_alignment_code (acfg, 8);
- if (acfg->llvm) {
- for (i = 0; i < acfg->nmethods; ++i) {
- if (acfg->cfgs [i] && acfg->cfgs [i]->compile_llvm) {
- acfg->methods_symbol = g_strdup (acfg->cfgs [i]->asm_symbol);
- break;
- }
- }
- }
- if (!acfg->methods_symbol) {
- sprintf (symbol, "methods");
- emit_label (acfg, symbol);
- acfg->methods_symbol = g_strdup (symbol);
- }
emit_label (acfg, "jit_code_start");
/*
method = cfg->orig_method;
/* Emit unbox trampoline */
- if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype) {
+ if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
sprintf (symbol, "ut_%d", get_method_index (acfg, method));
emit_section_change (acfg, ".text", 0);
method = cfg->orig_method;
- if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype) {
+ if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
index = get_method_index (acfg, method);
emit_int32 (acfg, index);
method = cfg->orig_method;
- if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype) {
+ if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
#ifdef MONO_ARCH_AOT_SUPPORTED
int call_size;
emit_info (MonoAotCompile *acfg)
{
int oindex, i;
- char symbol [256];
gint32 *offsets;
offsets = g_new0 (gint32, acfg->nmethods);
}
}
- sprintf (symbol, "method_info_offsets");
- emit_section_change (acfg, RODATA_SECT, 1);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
-
- acfg->stats.offsets_size += emit_offset_table (acfg, acfg->nmethods, 10, offsets);
+ acfg->stats.offsets_size += emit_offset_table (acfg, "method_info_offsets", acfg->nmethods, 10, offsets);
g_free (offsets);
}
//printf ("MAX: %d\n", max_chain_length);
- /* Emit the table */
- sprintf (symbol, "extra_method_table");
- emit_section_change (acfg, RODATA_SECT, 0);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
+ buf_size = table->len * 12 + 4;
+ p = buf = g_malloc (buf_size);
+ encode_int (table_size, p, &p);
- emit_int32 (acfg, table_size);
for (i = 0; i < table->len; ++i) {
HashEntry *entry = g_ptr_array_index (table, i);
if (entry == NULL) {
- emit_int32 (acfg, 0);
- emit_int32 (acfg, 0);
- emit_int32 (acfg, 0);
+ encode_int (0, p, &p);
+ encode_int (0, p, &p);
+ encode_int (0, p, &p);
} else {
//g_assert (entry->key > 0);
- emit_int32 (acfg, entry->key);
- emit_int32 (acfg, entry->value);
+ encode_int (entry->key, p, &p);
+ encode_int (entry->value, p, &p);
if (entry->next)
- emit_int32 (acfg, entry->next->index);
+ encode_int (entry->next->index, p, &p);
else
- emit_int32 (acfg, 0);
+ encode_int (0, p, &p);
}
}
+ g_assert (p - buf <= buf_size);
- /*
- * Emit a table reverse mapping method indexes to their index in extra_method_info.
- * This is used by mono_aot_find_jit_info ().
- */
- sprintf (symbol, "extra_method_info_offsets");
+ /* 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);
- emit_int32 (acfg, acfg->extra_methods->len);
+ /*
+ * Emit a table reverse mapping method indexes to their index in extra_method_info.
+ * This is used by mono_aot_find_jit_info ().
+ */
+ buf_size = acfg->extra_methods->len * 8 + 4;
+ p = buf = g_malloc (buf_size);
+ encode_int (acfg->extra_methods->len, p, &p);
for (i = 0; i < acfg->extra_methods->len; ++i) {
MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
- emit_int32 (acfg, get_method_index (acfg, method));
- emit_int32 (acfg, info_offsets [i]);
+ 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);
}
static void
emit_exception_info (MonoAotCompile *acfg)
{
int i;
- char symbol [256];
gint32 *offsets;
SeqPointData sp_data;
gboolean seq_points_to_file = FALSE;
g_free (seq_points_aot_file);
}
- sprintf (symbol, "ex_info_offsets");
- emit_section_change (acfg, RODATA_SECT, 1);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
-
- acfg->stats.offsets_size += emit_offset_table (acfg, acfg->nmethods, 10, offsets);
+ acfg->stats.offsets_size += emit_offset_table (acfg, "ex_info_offsets", acfg->nmethods, 10, offsets);
g_free (offsets);
}
emit_class_info (MonoAotCompile *acfg)
{
int i;
- char symbol [256];
gint32 *offsets;
offsets = g_new0 (gint32, acfg->image->tables [MONO_TABLE_TYPEDEF].rows);
for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i)
offsets [i] = emit_klass_info (acfg, MONO_TOKEN_TYPE_DEF | (i + 1));
- sprintf (symbol, "class_info_offsets");
- emit_section_change (acfg, RODATA_SECT, 1);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
-
- acfg->stats.offsets_size += emit_offset_table (acfg, acfg->image->tables [MONO_TABLE_TYPEDEF].rows, 10, offsets);
+ acfg->stats.offsets_size += emit_offset_table (acfg, "class_info_offsets", acfg->image->tables [MONO_TABLE_TYPEDEF].rows, 10, offsets);
g_free (offsets);
}
static void
emit_class_name_table (MonoAotCompile *acfg)
{
- int i, table_size;
+ int i, table_size, buf_size;
guint32 token, hash;
MonoClass *klass;
GPtrArray *table;
char *full_name;
+ guint8 *buf, *p;
char symbol [256];
ClassNameTableEntry *entry, *new_entry;
}
/* Emit the table */
- sprintf (symbol, "class_name_table");
- emit_section_change (acfg, RODATA_SECT, 0);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
+ buf_size = table->len * 4 + 4;
+ p = buf = g_malloc0 (buf_size);
/* FIXME: Optimize memory usage */
g_assert (table_size < 65000);
- emit_int16 (acfg, table_size);
+ encode_int16 (table_size, p, &p);
g_assert (table->len < 65000);
for (i = 0; i < table->len; ++i) {
ClassNameTableEntry *entry = g_ptr_array_index (table, i);
if (entry == NULL) {
- emit_int16 (acfg, 0);
- emit_int16 (acfg, 0);
+ encode_int16 (0, p, &p);
+ encode_int16 (0, p, &p);
} else {
- emit_int16 (acfg, mono_metadata_token_index (entry->token));
+ encode_int16 (mono_metadata_token_index (entry->token), p, &p);
if (entry->next)
- emit_int16 (acfg, entry->next->index);
+ encode_int16 (entry->next->index, p, &p);
else
- emit_int16 (acfg, 0);
+ encode_int16 (0, p, &p);
}
}
+ 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);
}
static void
emit_image_table (MonoAotCompile *acfg)
{
- int i;
+ int i, buf_size;
char symbol [256];
+ guint8 *buf, *p;
/*
* The image table is small but referenced in a lot of places.
* So we emit it at once, and reference its elements by an index.
*/
+ buf_size = acfg->image_table->len * 28 + 4;
+ for (i = 0; i < acfg->image_table->len; i++) {
+ MonoImage *image = (MonoImage*)g_ptr_array_index (acfg->image_table, i);
+ MonoAssemblyName *aname = &image->assembly->aname;
- sprintf (symbol, "image_table");
- emit_section_change (acfg, RODATA_SECT, 1);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
+ buf_size += strlen (image->assembly_name) + strlen (image->guid) + (aname->culture ? strlen (aname->culture) : 1) + strlen ((char*)aname->public_key_token) + 4;
+ }
- emit_int32 (acfg, acfg->image_table->len);
+ buf = p = g_malloc0 (buf_size);
+ encode_int (acfg->image_table->len, p, &p);
for (i = 0; i < acfg->image_table->len; i++) {
MonoImage *image = (MonoImage*)g_ptr_array_index (acfg->image_table, i);
MonoAssemblyName *aname = &image->assembly->aname;
/* FIXME: Support multi-module assemblies */
g_assert (image->assembly->image == image);
- emit_string (acfg, image->assembly_name);
- emit_string (acfg, image->guid);
- emit_string (acfg, aname->culture ? aname->culture : "");
- emit_string (acfg, (const char*)aname->public_key_token);
+ encode_string (image->assembly_name, p, &p);
+ encode_string (image->guid, p, &p);
+ encode_string (aname->culture ? aname->culture : "", p, &p);
+ encode_string ((const char*)aname->public_key_token, p, &p);
- emit_alignment (acfg, 8);
- emit_int32 (acfg, aname->flags);
- emit_int32 (acfg, aname->major);
- emit_int32 (acfg, aname->minor);
- emit_int32 (acfg, aname->build);
- emit_int32 (acfg, aname->revision);
+ while (GPOINTER_TO_UINT (p) % 8 != 0)
+ p ++;
+
+ encode_int (aname->flags, p, &p);
+ encode_int (aname->major, p, &p);
+ encode_int (aname->minor, p, &p);
+ encode_int (aname->build, p, &p);
+ encode_int (aname->revision, p, &p);
}
+ 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);
+
+ g_free (buf);
}
static void
emit_got_info (MonoAotCompile *acfg, gboolean llvm)
{
- char symbol [256];
int i, first_plt_got_patch = 0, buf_size;
guint8 *p, *buf;
guint32 *got_info_offsets;
}
/* Emit got_info_offsets table */
- if (llvm)
- sprintf (symbol, "llvm_got_info_offsets");
- else
- sprintf (symbol, "got_info_offsets");
- emit_section_change (acfg, RODATA_SECT, 1);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
/* No need to emit offsets for the got plt entries, the plt embeds them directly */
- acfg->stats.offsets_size += emit_offset_table (acfg, llvm ? acfg->llvm_got_offset : first_plt_got_patch, 10, (gint32*)got_info_offsets);
+ acfg->stats.offsets_size += emit_offset_table (acfg, llvm ? "llvm_got_info_offsets" : "got_info_offsets", llvm ? acfg->llvm_got_offset : first_plt_got_patch, 10, (gint32*)got_info_offsets);
}
static void
emit_label (acfg, symbol);
}
-/*
- * Emit a structure containing all the information not stored elsewhere.
- */
static void
-emit_file_info (MonoAotCompile *acfg)
+init_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info, int gc_name_offset)
{
- char symbol [256];
int i;
- int gc_name_offset;
- const char *gc_name;
- char *build_info;
- emit_string_symbol (acfg, "assembly_guid" , acfg->image->guid);
+ info->version = MONO_AOT_FILE_VERSION;
+ info->plt_got_offset_base = acfg->plt_got_offset_base;
+ info->got_size = acfg->got_offset * sizeof (gpointer);
+ info->plt_size = acfg->plt_offset;
+ info->nmethods = acfg->nmethods;
+ info->flags = acfg->flags;
+ info->opts = acfg->opts;
+ info->simd_opts = acfg->simd_opts;
+ info->gc_name_index = gc_name_offset;
+ for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
+ info->num_trampolines [i] = acfg->num_trampolines [i];
+ for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
+ info->trampoline_got_offset_base [i] = acfg->trampoline_got_offset_base [i];
+ for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
+ info->trampoline_size [i] = acfg->trampoline_size [i];
+ info->num_rgctx_fetch_trampolines = acfg->aot_opts.nrgctx_fetch_trampolines;
- if (acfg->aot_opts.bind_to_runtime_version) {
- build_info = mono_get_runtime_build_info ();
- emit_string_symbol (acfg, "runtime_version", build_info);
- g_free (build_info);
- } else {
- emit_string_symbol (acfg, "runtime_version", "");
+#if defined (TARGET_ARM) && defined (TARGET_MACH)
+ {
+ MonoType t;
+ int align = 0;
+
+ memset (&t, 0, sizeof (MonoType));
+ t.type = MONO_TYPE_R8;
+ mono_type_size (&t, &align);
+ info->double_align = align;
+
+ memset (&t, 0, sizeof (MonoType));
+ t.type = MONO_TYPE_I8;
+ mono_type_size (&t, &align);
+ info->long_align = align;
}
+#else
+ info->double_align = MONO_ABI_ALIGNOF (double);
+ info->long_align = MONO_ABI_ALIGNOF (gint64);
+#endif
+ info->generic_tramp_num = MONO_TRAMPOLINE_NUM;
+ info->tramp_page_size = acfg->tramp_page_size;
+ for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
+ info->tramp_page_code_offsets [i] = acfg->tramp_page_code_offsets [i];
+}
- /* Emit a string holding the assembly name */
- emit_string_symbol (acfg, "assembly_name", acfg->image->assembly->aname.name);
+static void
+emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
+{
+ char symbol [256];
+ int i, sindex;
+ const char **symbols;
- /*
- * The managed allocators are GC specific, so can't use an AOT image created by one GC
- * in another.
- */
- gc_name = mono_gc_get_gc_name ();
- gc_name_offset = add_to_blob (acfg, (guint8*)gc_name, strlen (gc_name) + 1);
+ symbols = g_new0 (const char *, MONO_AOT_FILE_INFO_NUM_SYMBOLS);
+ sindex = 0;
+ symbols [sindex ++] = acfg->got_symbol;
+ if (acfg->llvm) {
+ symbols [sindex ++] = g_strdup_printf ("%s%s", acfg->user_symbol_prefix, acfg->llvm_got_symbol);
+ symbols [sindex ++] = acfg->llvm_eh_frame_symbol;
+ } else {
+ symbols [sindex ++] = NULL;
+ symbols [sindex ++] = NULL;
+ }
+ symbols [sindex ++] = "jit_code_start";
+ symbols [sindex ++] = "jit_code_end";
+ symbols [sindex ++] = "method_addresses";
+ symbols [sindex ++] = "blob";
+ symbols [sindex ++] = "class_name_table";
+ symbols [sindex ++] = "class_info_offsets";
+ symbols [sindex ++] = "method_info_offsets";
+ symbols [sindex ++] = "ex_info_offsets";
+ symbols [sindex ++] = "extra_method_info_offsets";
+ symbols [sindex ++] = "extra_method_table";
+ symbols [sindex ++] = "got_info_offsets";
+ if (acfg->llvm)
+ symbols [sindex ++] = "llvm_got_info_offsets";
+ else
+ symbols [sindex ++] = NULL;
+ symbols [sindex ++] = "mem_end";
+ symbols [sindex ++] = "image_table";
+ symbols [sindex ++] = "assembly_guid";
+ symbols [sindex ++] = "runtime_version";
+ if (acfg->num_trampoline_got_entries) {
+ symbols [sindex ++] = "specific_trampolines";
+ symbols [sindex ++] = "static_rgctx_trampolines";
+ symbols [sindex ++] = "imt_thunks";
+ symbols [sindex ++] = "gsharedvt_arg_trampolines";
+ } else {
+ symbols [sindex ++] = NULL;
+ symbols [sindex ++] = NULL;
+ symbols [sindex ++] = NULL;
+ symbols [sindex ++] = NULL;
+ }
+ if (acfg->aot_opts.static_link) {
+ symbols [sindex ++] = "globals";
+ } else {
+ symbols [sindex ++] = NULL;
+ }
+ symbols [sindex ++] = "assembly_name";
+ 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";
+ g_assert (sindex == MONO_AOT_FILE_INFO_NUM_SYMBOLS);
sprintf (symbol, "%smono_aot_file_info", acfg->user_symbol_prefix);
emit_section_change (acfg, ".data", 0);
/* The data emitted here must match MonoAotFileInfo. */
- emit_int32 (acfg, MONO_AOT_FILE_VERSION);
- emit_int32 (acfg, 0);
+ emit_int32 (acfg, info->version);
+ emit_int32 (acfg, info->dummy);
/*
* We emit pointers to our data structures instead of emitting global symbols which
* point to them, to reduce the number of globals, and because using globals leads to
* various problems (i.e. arm/thumb).
*/
- emit_pointer (acfg, acfg->got_symbol);
- if (acfg->llvm)
- emit_pointer (acfg, acfg->llvm_got_symbol);
- else
- emit_pointer (acfg, NULL);
- emit_pointer (acfg, acfg->methods_symbol);
- emit_pointer (acfg, "jit_code_start");
- emit_pointer (acfg, "jit_code_end");
- if (acfg->llvm) {
- /*
- * Emit a reference to the mono_eh_frame table created by our modified LLVM compiler.
- */
- emit_pointer (acfg, acfg->llvm_eh_frame_symbol);
- } else {
- emit_pointer (acfg, NULL);
- }
- emit_pointer (acfg, "blob");
- emit_pointer (acfg, "class_name_table");
- emit_pointer (acfg, "class_info_offsets");
- emit_pointer (acfg, "method_info_offsets");
- emit_pointer (acfg, "ex_info_offsets");
- emit_pointer (acfg, "method_addresses");
- emit_pointer (acfg, "extra_method_info_offsets");
- emit_pointer (acfg, "extra_method_table");
- emit_pointer (acfg, "got_info_offsets");
- if (acfg->llvm)
- emit_pointer (acfg, "llvm_got_info_offsets");
- else
- emit_pointer (acfg, NULL);
- emit_pointer (acfg, "unwind_info");
- emit_pointer (acfg, "mem_end");
- emit_pointer (acfg, "image_table");
- emit_pointer (acfg, "plt");
- emit_pointer (acfg, "plt_end");
- emit_pointer (acfg, "assembly_guid");
- emit_pointer (acfg, "runtime_version");
- if (acfg->num_trampoline_got_entries) {
- emit_pointer (acfg, "specific_trampolines");
- emit_pointer (acfg, "static_rgctx_trampolines");
- emit_pointer (acfg, "imt_thunks");
- emit_pointer (acfg, "gsharedvt_arg_trampolines");
- } else {
- emit_pointer (acfg, NULL);
- emit_pointer (acfg, NULL);
- emit_pointer (acfg, NULL);
- emit_pointer (acfg, NULL);
- }
- if (acfg->thumb_mixed) {
- emit_pointer (acfg, "thumb_end");
- } else {
- emit_pointer (acfg, NULL);
- }
- if (acfg->aot_opts.static_link) {
- emit_pointer (acfg, "globals");
- } else {
- emit_pointer (acfg, NULL);
- }
- emit_pointer (acfg, "assembly_name");
- emit_pointer (acfg, "unbox_trampolines");
- emit_pointer (acfg, "unbox_trampolines_end");
- emit_pointer (acfg, "unbox_trampoline_addresses");
-
- emit_int32 (acfg, acfg->plt_got_offset_base);
- emit_int32 (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
- emit_int32 (acfg, acfg->plt_offset);
- emit_int32 (acfg, acfg->nmethods);
- emit_int32 (acfg, acfg->flags);
- emit_int32 (acfg, acfg->opts);
- emit_int32 (acfg, acfg->simd_opts);
- emit_int32 (acfg, gc_name_offset);
+ for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i)
+ emit_pointer (acfg, symbols [i]);
+
+ emit_int32 (acfg, info->plt_got_offset_base);
+ emit_int32 (acfg, info->got_size);
+ emit_int32 (acfg, info->plt_size);
+ emit_int32 (acfg, info->nmethods);
+ emit_int32 (acfg, info->flags);
+ emit_int32 (acfg, info->opts);
+ emit_int32 (acfg, info->simd_opts);
+ emit_int32 (acfg, info->gc_name_index);
+ emit_int32 (acfg, info->num_rgctx_fetch_trampolines);
+ emit_int32 (acfg, info->double_align);
+ emit_int32 (acfg, info->long_align);
+ emit_int32 (acfg, info->generic_tramp_num);
+ emit_int32 (acfg, info->tramp_page_size);
for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
- emit_int32 (acfg, acfg->num_trampolines [i]);
+ emit_int32 (acfg, info->num_trampolines [i]);
for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
- emit_int32 (acfg, acfg->trampoline_got_offset_base [i]);
+ emit_int32 (acfg, info->trampoline_got_offset_base [i]);
for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
- emit_int32 (acfg, acfg->trampoline_size [i]);
- emit_int32 (acfg, acfg->aot_opts.nrgctx_fetch_trampolines);
-
-#if defined (TARGET_ARM) && defined (TARGET_MACH)
- {
- MonoType t;
- int align = 0;
-
- memset (&t, 0, sizeof (MonoType));
- t.type = MONO_TYPE_R8;
- mono_type_size (&t, &align);
- emit_int32 (acfg, align);
-
- memset (&t, 0, sizeof (MonoType));
- t.type = MONO_TYPE_I8;
- mono_type_size (&t, &align);
-
- emit_int32 (acfg, align);
- }
-#else
- emit_int32 (acfg, MONO_ABI_ALIGNOF (double));
- emit_int32 (acfg, MONO_ABI_ALIGNOF (gint64));
-#endif
- emit_int32 (acfg, MONO_TRAMPOLINE_NUM);
- emit_int32 (acfg, acfg->tramp_page_size);
+ emit_int32 (acfg, info->trampoline_size [i]);
for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
- emit_int32 (acfg, acfg->tramp_page_code_offsets [i]);
+ emit_int32 (acfg, info->tramp_page_code_offsets [i]);
if (acfg->aot_opts.static_link) {
char *p;
}
}
+/*
+ * Emit a structure containing all the information not stored elsewhere.
+ */
+static void
+emit_file_info (MonoAotCompile *acfg)
+{
+ int gc_name_offset;
+ const char *gc_name;
+ char *build_info;
+ MonoAotFileInfo *info;
+
+ if (acfg->aot_opts.bind_to_runtime_version) {
+ build_info = mono_get_runtime_build_info ();
+ emit_string_symbol (acfg, "runtime_version", build_info);
+ g_free (build_info);
+ } else {
+ emit_string_symbol (acfg, "runtime_version", "");
+ }
+
+ emit_string_symbol (acfg, "assembly_guid" , acfg->image->guid);
+
+ /* Emit a string holding the assembly name */
+ emit_string_symbol (acfg, "assembly_name", acfg->image->assembly->aname.name);
+
+ /*
+ * The managed allocators are GC specific, so can't use an AOT image created by one GC
+ * in another.
+ */
+ gc_name = mono_gc_get_gc_name ();
+ gc_name_offset = add_to_blob (acfg, (guint8*)gc_name, strlen (gc_name) + 1);
+
+ info = g_new0 (MonoAotFileInfo, 1);
+ init_aot_file_info (acfg, info, gc_name_offset);
+
+ emit_aot_file_info (acfg, info);
+}
+
static void
emit_blob (MonoAotCompile *acfg)
{
/* Load all methods eagerly to skip the slower lazy loading code */
mono_class_setup_methods (method->klass);
- if (acfg->aot_opts.full_aot && method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
+ if (mono_aot_mode_is_full (&acfg->aot_opts) && method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
/* Compile the wrapper instead */
/* We do this here instead of add_wrappers () because it is easy to do it here */
MonoMethod *wrapper = mono_marshal_get_native_wrapper (method, check_for_pending_exc, TRUE);
}
*/
+ if (method->is_generic || method->klass->generic_container)
+ /* Compile the ref shared version instead */
+ method = mini_get_shared_method (method);
+
/* Since we add the normal methods first, their index will be equal to their zero based token index */
add_method_with_index (acfg, method, i, FALSE);
acfg->method_index ++;
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;
- */
- /*
- if (!strstr (method->klass->image->name, "mini"))
- continue;
- */
if (method->is_generic || method->klass->generic_container) {
MonoMethod *gshared;
add_generic_instances (acfg);
- if (acfg->aot_opts.full_aot)
+ if (mono_aot_mode_is_full (&acfg->aot_opts))
add_wrappers (acfg);
return TRUE;
}
#define LD_NAME "gcc -shared --dll"
#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
#define LD_NAME "clang -m32 -dynamiclib"
-#elif defined(TARGET_ARM)
+#elif defined(TARGET_ARM) && !defined(TARGET_ANDROID)
#define LD_NAME "gcc --shared"
#endif
* gas generates 'mapping symbols' each time code and data is mixed, which
* happens a lot in emit_and_reloc_code (), so we need to get rid of them.
*/
- command = g_strdup_printf ("%sstrip --strip-symbol=\\$a --strip-symbol=\\$d %s", tool_prefix, tmp_outfile_name);
+ command = g_strdup_printf ("\"%sstrip\" --strip-symbol=\\$a --strip-symbol=\\$d %s", tool_prefix, tmp_outfile_name);
aot_printf (acfg, "Stripping the binary: %s\n", command);
if (execute_system (command) != 0) {
g_free (tmp_outfile_name);
acfg->aot_opts.nrgctx_fetch_trampolines = 128;
acfg->aot_opts.ngsharedvt_arg_trampolines = 128;
acfg->aot_opts.llvm_path = g_strdup ("");
+ acfg->aot_opts.temp_path = g_strdup ("");
#ifdef MONOTOUCH
acfg->aot_opts.use_trampolines_page = TRUE;
#endif
aot_printf (acfg, "Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
#ifndef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
- if (acfg->aot_opts.full_aot) {
+ if (mono_aot_mode_is_full (&acfg->aot_opts)) {
aot_printerrf (acfg, "--aot=full is not supported on this platform.\n");
return 1;
}
* Emit all LLVM code into a separate assembly/object file and link with it
* normally.
*/
- if (!acfg->aot_opts.asm_only)
+ if (!acfg->aot_opts.asm_only) {
acfg->llvm_owriter = TRUE;
+ } else if (acfg->aot_opts.llvm_outfile) {
+ int len = strlen (acfg->aot_opts.llvm_outfile);
+
+ if (len >= 2 && acfg->aot_opts.llvm_outfile [len - 2] == '.' && acfg->aot_opts.llvm_outfile [len - 1] == 'o')
+ acfg->llvm_owriter = TRUE;
+ }
}
- if (acfg->aot_opts.full_aot)
+ if (mono_aot_mode_is_full (&acfg->aot_opts))
acfg->flags |= MONO_AOT_FILE_FLAG_FULL_AOT;
if (acfg->aot_opts.instances_logfile_path) {
load_profile_files (acfg);
- acfg->num_trampolines [MONO_AOT_TRAMP_SPECIFIC] = acfg->aot_opts.full_aot ? acfg->aot_opts.ntrampolines : 0;
+ acfg->num_trampolines [MONO_AOT_TRAMP_SPECIFIC] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.ntrampolines : 0;
#ifdef MONO_ARCH_GSHARED_SUPPORTED
- acfg->num_trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = acfg->aot_opts.full_aot ? acfg->aot_opts.nrgctx_trampolines : 0;
+ acfg->num_trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nrgctx_trampolines : 0;
#endif
- acfg->num_trampolines [MONO_AOT_TRAMP_IMT_THUNK] = acfg->aot_opts.full_aot ? acfg->aot_opts.nimt_trampolines : 0;
+ acfg->num_trampolines [MONO_AOT_TRAMP_IMT_THUNK] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nimt_trampolines : 0;
#ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
if (acfg->opts & MONO_OPT_GSHAREDVT)
- acfg->num_trampolines [MONO_AOT_TRAMP_GSHAREDVT_ARG] = acfg->aot_opts.full_aot ? acfg->aot_opts.ngsharedvt_arg_trampolines : 0;
+ acfg->num_trampolines [MONO_AOT_TRAMP_GSHAREDVT_ARG] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.ngsharedvt_arg_trampolines : 0;
#endif
acfg->temp_prefix = mono_img_writer_get_temp_label_prefix (NULL);
arch_init (acfg);
+ if (acfg->llvm && acfg->thumb_mixed)
+ acfg->flags |= MONO_AOT_FILE_FLAG_LLVM_THUMB;
+
acfg->assembly_name_sym = g_strdup (acfg->image->assembly->aname.name);
/* Get rid of characters which cannot occur in symbols */
for (p = acfg->assembly_name_sym; *p; ++p) {
*p = '_';
}
- acfg->got_symbol_base = g_strdup_printf ("mono_aot_%s_got", acfg->assembly_name_sym);
- acfg->llvm_got_symbol_base = g_strdup_printf ("mono_aot_%s_llvm_got", acfg->assembly_name_sym);
- acfg->plt_symbol = g_strdup_printf ("%smono_aot_%s_plt", acfg->llvm_label_prefix, acfg->assembly_name_sym);
-
- 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);
- acfg->llvm_eh_frame_symbol = g_strdup_printf ("mono_aot_%s_eh_frame", acfg->assembly_name_sym);
+ acfg->global_prefix = g_strdup_printf ("mono_aot_%s", acfg->assembly_name_sym);
+ acfg->plt_symbol = g_strdup_printf ("%s_plt", acfg->global_prefix);
+ acfg->got_symbol = g_strdup_printf ("%s_got", acfg->global_prefix);
+ if (acfg->llvm) {
+ acfg->llvm_got_symbol = g_strdup_printf ("%s_llvm_got", acfg->global_prefix);
+ acfg->llvm_eh_frame_symbol = g_strdup_printf ("%s_eh_frame", acfg->global_prefix);
}
acfg->method_index = 1;
- if (acfg->aot_opts.full_aot)
+ if (mono_aot_mode_is_full (&acfg->aot_opts))
mono_set_partial_sharing_supported (TRUE);
res = collect_methods (acfg);
#ifdef ENABLE_LLVM
if (acfg->llvm) {
llvm_acfg = acfg;
- mono_llvm_create_aot_module (acfg->llvm_got_symbol_base, TRUE, TRUE);
+ mono_llvm_create_aot_module (acfg->global_prefix, TRUE);
}
#endif
}
g_assert (acfg->aot_opts.llvm_outfile);
acfg->llvm_sfile = g_strdup (acfg->aot_opts.llvm_outfile);
+ if (acfg->llvm_owriter)
+ acfg->llvm_ofile = g_strdup (acfg->aot_opts.llvm_outfile);
+ else
+ acfg->llvm_sfile = g_strdup (acfg->aot_opts.llvm_outfile);
} else {
- acfg->tmpbasename = g_strdup_printf ("%s", "temp");
+ acfg->tmpbasename = (strcmp (acfg->aot_opts.temp_path, "") == 0) ?
+ g_strdup_printf ("%s", "temp") :
+ g_build_filename (acfg->aot_opts.temp_path, "temp", NULL);
+
acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
- acfg->llvm_sfile = g_strdup ("temp-llvm.s");
- acfg->llvm_ofile = g_strdup ("temp-llvm.o");
+ 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 (acfg->dwarf)
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];
- /*
- * This global symbol marks the end of THUMB code, and the beginning of ARM
- * code generated by our JIT.
- */
- sprintf (symbol, "thumb_end");
- emit_section_change (acfg, ".text", 0);
- emit_alignment_code (acfg, 8);
- emit_label (acfg, symbol);
- emit_zero_bytes (acfg, 16);
-
- fprintf (acfg->fp, ".arm\n");
- }
-
emit_code (acfg);
emit_info (acfg);