#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/marshal.h>
#include <mono/metadata/gc-internal.h>
-#include <mono/metadata/monitor.h>
#include <mono/metadata/mempool-internals.h>
#include <mono/metadata/mono-endian.h>
#include <mono/metadata/threads-types.h>
#endif
+static guint32
+get_unwind_info_offset (MonoAotCompile *acfg, guint8 *encoded, guint32 encoded_len);
+
static char*
get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache);
mono_img_writer_emit_symbol_size (acfg->w, name, end_label);
}
+/* Emit a symbol which is referenced by the MonoAotFileInfo structure */
+static void
+emit_info_symbol (MonoAotCompile *acfg, const char *name)
+{
+ char symbol [256];
+
+ if (acfg->llvm) {
+ emit_label (acfg, name);
+ /* LLVM generated code references this */
+ sprintf (symbol, "%s%s%s", acfg->user_symbol_prefix, acfg->global_prefix, name);
+ emit_label (acfg, symbol);
+ emit_global_inner (acfg, symbol, FALSE);
+ } else {
+ emit_label (acfg, name);
+ }
+}
+
static void
emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
{
+ if (acfg->llvm) {
+ mono_llvm_emit_aot_data (name, (guint8*)value, strlen (value) + 1);
+ return;
+ }
+
mono_img_writer_emit_section_change (acfg->w, RODATA_SECT, 1);
#ifdef TARGET_MACH
/* On apple, all symbols need to be aligned to avoid warnings from ld */
#endif
}
+/* Save unwind_info in the module and emit the offset to the information at symbol */
+static void save_unwind_info (MonoAotCompile *acfg, char *symbol, GSList *unwind_ops)
+{
+ guint32 uw_offset, encoded_len;
+ guint8 *encoded;
+
+ emit_section_change (acfg, RODATA_SECT, 0);
+ emit_global (acfg, symbol, FALSE);
+ emit_label (acfg, symbol);
+
+ encoded = mono_unwind_ops_encode (unwind_ops, &encoded_len);
+ uw_offset = get_unwind_info_offset (acfg, encoded, encoded_len);
+ g_free (encoded);
+ emit_int32 (acfg, uw_offset);
+}
+
/*
* arch_emit_specific_trampoline_pages:
*
guint8 *loop_start, *loop_branch_back, *loop_end_check, *imt_found_check;
int i;
int pagesize = MONO_AOT_TRAMP_PAGE_SIZE;
+ GSList *unwind_ops = NULL;
#define COMMON_TRAMP_SIZE 16
int count = (pagesize - COMMON_TRAMP_SIZE) / 8;
int imm8, rot_amount;
/* now the imt trampolines: each specific trampolines puts in the ip register
* the instruction pointer address, so the generic trampoline at the start of the page
* subtracts 4096 to get to the data page and loads the values
- * We again fit the generic trampiline in 16 bytes.
*/
#define IMT_TRAMP_SIZE 72
sprintf (symbol, "%simt_trampolines_page", acfg->user_symbol_prefix);
acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = 16;
acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = 72;
acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = 16;
+
+ /* Unwind info for specifc trampolines */
+ sprintf (symbol, "%sspecific_trampolines_page_gen_p", acfg->user_symbol_prefix);
+ /* We unwind to the original caller, from the stack, since lr is clobbered */
+ mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 14 * sizeof (mgreg_t));
+ mono_add_unwind_op_offset (unwind_ops, 0, 0, ARMREG_LR, -4);
+ save_unwind_info (acfg, symbol, unwind_ops);
+ mono_free_unwind_info (unwind_ops);
+
+ sprintf (symbol, "%sspecific_trampolines_page_sp_p", acfg->user_symbol_prefix);
+ mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+ mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 14 * sizeof (mgreg_t));
+ save_unwind_info (acfg, symbol, unwind_ops);
+ mono_free_unwind_info (unwind_ops);
+
+ /* Unwind info for rgctx trampolines */
+ sprintf (symbol, "%srgctx_trampolines_page_gen_p", acfg->user_symbol_prefix);
+ mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+ save_unwind_info (acfg, symbol, unwind_ops);
+
+ sprintf (symbol, "%srgctx_trampolines_page_sp_p", acfg->user_symbol_prefix);
+ save_unwind_info (acfg, symbol, unwind_ops);
+ mono_free_unwind_info (unwind_ops);
+
+ /* Unwind info for gsharedvt trampolines */
+ sprintf (symbol, "%sgsharedvt_trampolines_page_gen_p", acfg->user_symbol_prefix);
+ mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+ mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 4 * sizeof (mgreg_t));
+ save_unwind_info (acfg, symbol, unwind_ops);
+ mono_free_unwind_info (unwind_ops);
+
+ sprintf (symbol, "%sgsharedvt_trampolines_page_sp_p", acfg->user_symbol_prefix);
+ mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+ save_unwind_info (acfg, symbol, unwind_ops);
+ mono_free_unwind_info (unwind_ops);
+
+ /* Unwind info for imt trampolines */
+ sprintf (symbol, "%simt_trampolines_page_gen_p", acfg->user_symbol_prefix);
+ mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+ mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 3 * sizeof (mgreg_t));
+ save_unwind_info (acfg, symbol, unwind_ops);
+ mono_free_unwind_info (unwind_ops);
+
+ sprintf (symbol, "%simt_trampolines_page_sp_p", acfg->user_symbol_prefix);
+ mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+ save_unwind_info (acfg, symbol, unwind_ops);
+ mono_free_unwind_info (unwind_ops);
#elif defined(TARGET_ARM64)
arm64_emit_specific_trampoline_pages (acfg);
#endif
/* FIXME: Could this clobber the register needed by get_vcall_slot () ? */
- /* We clobber ECX, since EAX is used as MONO_ARCH_MONITOR_OBJECT_REG */
-#ifdef MONO_ARCH_MONITOR_OBJECT_REG
- g_assert (MONO_ARCH_MONITOR_OBJECT_REG != X86_ECX);
-#ifdef MONO_ARCH_MONITOR_LOCK_TAKEN_REG
- g_assert (MONO_ARCH_MONITOR_LOCK_TAKEN_REG != X86_ECX);
-#endif
-#endif
-
code = buf;
/* Load mscorlib got address */
x86_mov_reg_membase (code, X86_ECX, MONO_ARCH_GOT_REG, sizeof (gpointer), 4);
g_assert (p - buf <= buf_size);
- emit_section_change (acfg, RODATA_SECT, 1);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
-
- emit_bytes (acfg, buf, p - buf);
+ if (acfg->llvm) {
+ mono_llvm_emit_aot_data (symbol, buf, p - buf);
+ } else {
+ emit_section_change (acfg, RODATA_SECT, 1);
+ emit_alignment (acfg, 8);
+ emit_label (acfg, symbol);
+ emit_bytes (acfg, buf, p - buf);
+ }
g_free (buf);
g_free (data_buf);
case MONO_PATCH_INFO_INTERNAL_METHOD:
case MONO_PATCH_INFO_JIT_ICALL_ADDR:
case MONO_PATCH_INFO_ICALL_ADDR:
- case MONO_PATCH_INFO_CLASS_INIT:
case MONO_PATCH_INFO_RGCTX_FETCH:
- case MONO_PATCH_INFO_MONITOR_ENTER:
- case MONO_PATCH_INFO_MONITOR_ENTER_V4:
- case MONO_PATCH_INFO_MONITOR_EXIT:
case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE:
return TRUE;
default:
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;
+ method = mini_get_shared_method_full (method, TRUE, TRUE);
if (acfg->aot_opts.log_generics)
aot_printf (acfg, "%*sAdding method %s.\n", depth, "", mono_method_full_name (method, TRUE));
return;
name = g_strdup_printf ("__icall_wrapper_%s", callinfo->name);
- wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_for_pending_exc);
+ wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, TRUE);
g_free (name);
add_method (acfg, wrapper);
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_DELEGATE_TRAMPOLINE:
encode_patch (acfg, entry->data, p, &p);
break;
}
- case MONO_PATCH_INFO_MONITOR_ENTER:
- case MONO_PATCH_INFO_MONITOR_ENTER_V4:
- case MONO_PATCH_INFO_MONITOR_EXIT:
case MONO_PATCH_INFO_SEQ_POINT_INFO:
break;
case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE:
get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache)
{
char *debug_sym = NULL;
- char *s;
char *prefix;
if (acfg->llvm && llvm_acfg->aot_opts.static_link) {
case MONO_PATCH_INFO_INTERNAL_METHOD:
debug_sym = g_strdup_printf ("%s_jit_icall_%s", prefix, ji->data.name);
break;
- case MONO_PATCH_INFO_CLASS_INIT:
- s = mono_type_get_name (&ji->data.klass->byval_arg);
- debug_sym = g_strdup_printf ("%s__class_init_%s", prefix, s);
- g_free (s);
- break;
case MONO_PATCH_INFO_RGCTX_FETCH:
debug_sym = g_strdup_printf ("%s_rgctx_fetch_%d", prefix, acfg->label_generator ++);
break;
emit_section_change (acfg, ".text", 0);
emit_alignment_code (acfg, NACL_SIZE(16, kNaClAlignment));
- emit_label (acfg, symbol);
+ emit_info_symbol (acfg, symbol);
emit_label (acfg, acfg->plt_symbol);
for (i = 0; i < acfg->plt_offset; ++i) {
emit_symbol_size (acfg, acfg->plt_symbol, ".");
sprintf (symbol, "plt_end");
- emit_label (acfg, symbol);
+ emit_info_symbol (acfg, symbol);
}
/*
static G_GNUC_UNUSED void
emit_trampoline (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info)
{
- emit_trampoline_full (acfg, got_offset, info, FALSE);
+ emit_trampoline_full (acfg, got_offset, info, TRUE);
}
static void
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);
-#if defined(MONO_ARCH_MONITOR_LOCK_TAKEN_REG)
- mono_arch_create_monitor_enter_trampoline (&info, TRUE, TRUE);
- emit_trampoline (acfg, acfg->got_offset, info);
-#endif
- mono_arch_create_monitor_exit_trampoline (&info, TRUE);
- emit_trampoline (acfg, acfg->got_offset, info);
-#endif
-
/* Emit the exception related code pieces */
mono_arch_get_restore_context (&info, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
emit_local_symbol (acfg, symbol, end_symbol, TRUE);
emit_alignment_code (acfg, AOT_FUNC_ALIGNMENT);
- emit_label (acfg, symbol);
+ emit_info_symbol (acfg, symbol);
acfg->trampoline_got_offset_base [ntype] = tramp_got_offset;
return clean;
}
+static GPtrArray *
+mono_aot_split_options (const char *aot_options)
+{
+ enum MonoAotOptionState {
+ MONO_AOT_OPTION_STATE_DEFAULT,
+ MONO_AOT_OPTION_STATE_STRING,
+ MONO_AOT_OPTION_STATE_ESCAPE,
+ };
+
+ GPtrArray *args = g_ptr_array_new ();
+ enum MonoAotOptionState state = MONO_AOT_OPTION_STATE_DEFAULT;
+ gchar const *opt_start = aot_options;
+ gboolean end_of_string = FALSE;
+ gchar cur;
+
+ g_return_val_if_fail (aot_options != NULL, NULL);
+
+ while ((cur = *aot_options) != '\0') {
+ if (state == MONO_AOT_OPTION_STATE_ESCAPE)
+ goto next;
+
+ switch (cur) {
+ case '"':
+ // If we find a quote, then if we're in the default case then
+ // it means we've found the start of a string, if not then it
+ // means we've found the end of the string and should switch
+ // back to the default case.
+ switch (state) {
+ case MONO_AOT_OPTION_STATE_DEFAULT:
+ state = MONO_AOT_OPTION_STATE_STRING;
+ break;
+ case MONO_AOT_OPTION_STATE_STRING:
+ state = MONO_AOT_OPTION_STATE_DEFAULT;
+ break;
+ case MONO_AOT_OPTION_STATE_ESCAPE:
+ g_assert_not_reached ();
+ break;
+ }
+ break;
+ case '\\':
+ // If we've found an escaping operator, then this means we
+ // should not process the next character if inside a string.
+ if (state == MONO_AOT_OPTION_STATE_STRING)
+ state = MONO_AOT_OPTION_STATE_ESCAPE;
+ break;
+ case ',':
+ // If we're in the default state then this means we've found
+ // an option, store it for later processing.
+ if (state == MONO_AOT_OPTION_STATE_DEFAULT)
+ goto new_opt;
+ break;
+ }
+
+ next:
+ aot_options++;
+ // If the next character is end of string, then process the last option.
+ if (*(aot_options) == '\0') {
+ end_of_string = TRUE;
+ goto new_opt;
+ }
+ continue;
+
+ new_opt:
+ g_ptr_array_add (args, g_strndup (opt_start, aot_options - opt_start));
+ opt_start = ++aot_options;
+ if (end_of_string)
+ break;
+ goto next;
+ }
+
+ return args;
+}
+
static void
mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
{
- gchar **args, **ptr;
+ GPtrArray* args;
- args = g_strsplit (aot_options ? aot_options : "", ",", -1);
- for (ptr = args; ptr && *ptr; ptr ++) {
- const char *arg = *ptr;
+ args = mono_aot_split_options (aot_options ? aot_options : "");
+ for (int i = 0; i < args->len; ++i) {
+ const char *arg = g_ptr_array_index (args, i);
if (str_begins_with (arg, "outfile=")) {
opts->outfile = g_strdup (arg + strlen ("outfile="));
fprintf (stderr, "AOT : Unknown argument '%s'.\n", arg);
exit (1);
}
+
+ g_free ((gpointer) arg);
}
if (opts->use_trampolines_page) {
opts->nimt_trampolines = 0;
opts->ngsharedvt_arg_trampolines = 0;
}
- g_strfreev (args);
+
+ g_ptr_array_free (args, /*free_seg=*/TRUE);
}
static void
return can_encode_method (acfg, method);
}
case MONO_PATCH_INFO_VTABLE:
- case MONO_PATCH_INFO_CLASS_INIT:
case MONO_PATCH_INFO_CLASS:
case MONO_PATCH_INFO_IID:
case MONO_PATCH_INFO_ADJUSTED_IID:
if (!acfg->aot_opts.no_instances && depth < 32) {
for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
switch (patch_info->type) {
+ case MONO_PATCH_INFO_RGCTX_FETCH:
case MONO_PATCH_INFO_METHOD: {
- MonoMethod *m = patch_info->data.method;
+ MonoMethod *m = NULL;
+
+ if (patch_info->type == MONO_PATCH_INFO_RGCTX_FETCH) {
+ MonoJumpInfoRgctxEntry *e = patch_info->data.rgctx_entry;
+
+ if (e->info_type == MONO_RGCTX_INFO_GENERIC_METHOD_CODE)
+ m = e->data->data.method;
+ } else {
+ m = patch_info->data.method;
+ }
+
+ if (!m)
+ break;
if (m->is_inflated) {
if (!(mono_class_generic_sharing_enabled (m->klass) &&
mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE)) &&
if (acfg->aot_opts.mtriple)
g_string_append_printf (acfg->llc_args, " -mtriple=%s", acfg->aot_opts.mtriple);
- g_string_append_printf (acfg->llc_args, " -mono-eh-frame-symbol=%s", acfg->llvm_eh_frame_symbol);
+ g_string_append_printf (acfg->llc_args, " -mono-eh-frame-symbol=%s%s", acfg->user_symbol_prefix, acfg->llvm_eh_frame_symbol);
#if defined(TARGET_MACH) && defined(TARGET_ARM)
/* ios requires PIC code now */
else
g_string_append_printf (acfg->llc_args, " -relocation-model=pic");
#endif
- unlink (acfg->tmpfname);
if (acfg->llvm_owriter) {
/* Emit an object file directly */
emit_code (MonoAotCompile *acfg)
{
int oindex, i, prev_index;
+ gboolean saved_unbox_info = FALSE;
char symbol [256];
#if defined(TARGET_POWERPC64)
*/
emit_section_change (acfg, ".text", 0);
emit_alignment_code (acfg, 8);
- emit_label (acfg, "jit_code_start");
+ emit_info_symbol (acfg, "jit_code_start");
/*
* Emit some padding so the local symbol for the first method doesn't have the
if (acfg->thumb_mixed && cfg->compile_llvm)
emit_set_arm_mode (acfg);
+
+ if (!saved_unbox_info) {
+ char user_symbol [128];
+ GSList *unwind_ops;
+ sprintf (user_symbol, "%sunbox_trampoline_p", acfg->user_symbol_prefix);
+
+ emit_label (acfg, "ut_end");
+
+ unwind_ops = mono_unwind_get_cie_program ();
+ save_unwind_info (acfg, user_symbol, unwind_ops);
+ mono_free_unwind_info (unwind_ops);
+
+ /* Save the unbox trampoline size */
+ emit_symbol_diff (acfg, "ut_end", symbol, 0);
+
+ saved_unbox_info = TRUE;
+ }
}
if (cfg->compile_llvm)
emit_section_change (acfg, ".text", 0);
emit_alignment_code (acfg, 8);
- emit_label (acfg, "jit_code_end");
+ emit_info_symbol (acfg, "jit_code_end");
/* To distinguish it from the next symbol */
emit_padding (acfg, 4);
sprintf (symbol, "method_addresses");
emit_section_change (acfg, ".text", 1);
emit_alignment_code (acfg, 8);
- emit_label (acfg, symbol);
+ emit_info_symbol (acfg, symbol);
emit_local_symbol (acfg, symbol, "method_addresses_end", TRUE);
emit_unset_mode (acfg);
if (acfg->need_no_dead_strip)
sprintf (symbol, "unbox_trampolines");
emit_section_change (acfg, RODATA_SECT, 0);
emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
+ emit_info_symbol (acfg, symbol);
prev_index = -1;
for (i = 0; i < acfg->nmethods; ++i) {
}
}
sprintf (symbol, "unbox_trampolines_end");
- emit_label (acfg, symbol);
+ emit_info_symbol (acfg, symbol);
emit_int32 (acfg, 0);
/* Emit a separate table with the trampoline addresses/offsets */
sprintf (symbol, "unbox_trampoline_addresses");
emit_section_change (acfg, ".text", 0);
emit_alignment_code (acfg, 8);
- emit_label (acfg, symbol);
+ emit_info_symbol (acfg, symbol);
for (i = 0; i < acfg->nmethods; ++i) {
MonoCompile *cfg;
g_assert (p - buf <= buf_size);
/* Emit the table */
- sprintf (symbol, "extra_method_table");
- emit_section_change (acfg, RODATA_SECT, 0);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
- emit_bytes (acfg, buf, p - buf);
+ if (acfg->llvm) {
+ mono_llvm_emit_aot_data ("extra_method_table", buf, p - buf);
+ } else {
+ sprintf (symbol, "extra_method_table");
+ emit_section_change (acfg, RODATA_SECT, 0);
+ emit_alignment (acfg, 8);
+ emit_label (acfg, symbol);
+ emit_bytes (acfg, buf, p - buf);
+ }
/*
* Emit a table reverse mapping method indexes to their index in extra_method_info.
encode_int (get_method_index (acfg, method), p, &p);
encode_int (info_offsets [i], p, &p);
}
- sprintf (symbol, "extra_method_info_offsets");
- emit_section_change (acfg, RODATA_SECT, 0);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
- emit_bytes (acfg, buf, p - buf);
+ if (acfg->llvm) {
+ mono_llvm_emit_aot_data ("extra_method_info_offsets", buf, p - buf);
+ } else {
+ sprintf (symbol, "extra_method_info_offsets");
+ emit_section_change (acfg, RODATA_SECT, 0);
+ emit_alignment (acfg, 8);
+ emit_label (acfg, symbol);
+ emit_bytes (acfg, buf, p - buf);
+ }
}
static void
sprintf (symbol, "unwind_info");
emit_section_change (acfg, RODATA_SECT, 1);
emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
+ emit_info_symbol (acfg, symbol);
for (i = 0; i < acfg->unwind_ops->len; ++i) {
guint32 index = GPOINTER_TO_UINT (g_ptr_array_index (acfg->unwind_ops, i));
}
g_assert (p - buf <= buf_size);
- sprintf (symbol, "class_name_table");
- emit_section_change (acfg, RODATA_SECT, 0);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
- emit_bytes (acfg, buf, p - buf);
+ if (acfg->llvm) {
+ mono_llvm_emit_aot_data ("class_name_table", buf, p - buf);
+ } else {
+ sprintf (symbol, "class_name_table");
+ emit_section_change (acfg, RODATA_SECT, 0);
+ emit_alignment (acfg, 8);
+ emit_label (acfg, symbol);
+ emit_bytes (acfg, buf, p - buf);
+ }
}
static void
}
g_assert (p - buf <= buf_size);
- sprintf (symbol, "image_table");
- emit_section_change (acfg, RODATA_SECT, 1);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
- emit_bytes (acfg, buf, p - buf);
+ if (acfg->llvm) {
+ mono_llvm_emit_aot_data ("image_table", buf, p - buf);
+ } else {
+ sprintf (symbol, "image_table");
+ emit_section_change (acfg, RODATA_SECT, 1);
+ emit_alignment (acfg, 8);
+ emit_label (acfg, symbol);
+ emit_bytes (acfg, buf, p - buf);
+ }
g_free (buf);
}
/* Don't make GOT global so accesses to it don't need relocations */
sprintf (symbol, "%s", acfg->got_symbol);
+
+#ifdef TARGET_MACH
+ emit_unset_mode (acfg);
+ fprintf (acfg->fp, ".section __DATA, __bss\n");
+ emit_alignment (acfg, 8);
+ if (acfg->llvm)
+ emit_info_symbol (acfg, "jit_got");
+ fprintf (acfg->fp, ".lcomm %s, %d\n", acfg->got_symbol, (int)(acfg->got_offset * sizeof (gpointer)));
+#else
emit_section_change (acfg, ".bss", 0);
emit_alignment (acfg, 8);
emit_local_symbol (acfg, symbol, "got_end", FALSE);
emit_label (acfg, symbol);
+ if (acfg->llvm)
+ emit_info_symbol (acfg, "jit_got");
if (acfg->got_offset > 0)
emit_zero_bytes (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
+#endif
sprintf (symbol, "got_end");
emit_label (acfg, symbol);
emit_section_change (acfg, ".data", 0);
/* This is not a global, since it is accessed by the init function */
emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
+ emit_info_symbol (acfg, symbol);
sprintf (symbol, "%sglobals_hash", acfg->temp_prefix);
emit_pointer (acfg, symbol);
info = g_new0 (MonoAotFileInfo, 1);
init_aot_file_info (acfg, info, gc_name_offset);
- emit_aot_file_info (acfg, info);
+ if (acfg->llvm)
+ mono_llvm_emit_aot_file_info (info, acfg->has_jitted_code);
+ else
+ emit_aot_file_info (acfg, info);
}
static void
{
char symbol [128];
+ if (acfg->llvm) {
+ mono_llvm_emit_aot_data ("blob", (guint8*)acfg->blob.data, acfg->blob.index);
+ return;
+ }
+
sprintf (symbol, "blob");
emit_section_change (acfg, RODATA_SECT, 1);
emit_alignment (acfg, 8);
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);
+ MonoMethod *wrapper = mono_marshal_get_native_wrapper (method, TRUE, TRUE);
method = wrapper;
}
tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
if (acfg->llvm) {
- llvm_ofile = g_strdup (acfg->llvm_ofile);
+ llvm_ofile = g_strdup_printf ("\"%s\"", acfg->llvm_ofile);
} else {
llvm_ofile = g_strdup ("");
}
g_strdelimit (ld_flags, ";", ' ');
#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);
+ 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,
acfg->tmpfname, ld_flags);
rename (tmp_outfile_name, outfile_name);
#if defined(TARGET_MACH)
- command = g_strdup_printf ("dsymutil %s", outfile_name);
+ command = g_strdup_printf ("dsymutil \"%s\"", outfile_name);
aot_printf (acfg, "Executing dsymutil: %s\n", command);
if (execute_system (command) != 0) {
return 1;
#ifdef ENABLE_LLVM
if (acfg->llvm) {
llvm_acfg = acfg;
- mono_llvm_create_aot_module (acfg->global_prefix, TRUE);
+ mono_llvm_create_aot_module (acfg->image->assembly, acfg->global_prefix, TRUE, acfg->aot_opts.static_link);
}
#endif
#ifdef ENABLE_LLVM
if (acfg->llvm) {
- gboolean res;
-
if (acfg->aot_opts.asm_only) {
if (acfg->aot_opts.outfile) {
acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
acfg->llvm_sfile = g_strdup_printf ("%s-llvm.s", acfg->tmpbasename);
acfg->llvm_ofile = g_strdup_printf ("%s-llvm.o", acfg->tmpbasename);
}
-
- res = emit_llvm_file (acfg);
- if (!res)
- return 1;
}
#endif
//acfg->gas_line_numbers = TRUE;
}
- if (!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) {
+ if ((!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) && acfg->has_jitted_code) {
if (acfg->aot_opts.dwarf_debug && !mono_debug_enabled ()) {
aot_printerrf (acfg, "The dwarf AOT option requires the --debug option.\n");
return 1;
fprintf (acfg->fp, "\n.section .note.GNU-stack,\"\",@progbits\n");
}
+#ifdef ENABLE_LLVM
+ if (acfg->llvm) {
+ gboolean res;
+
+ res = emit_llvm_file (acfg);
+ if (!res)
+ return 1;
+ }
+#endif
+
TV_GETTIME (btv);
acfg->stats.gen_time = TV_ELAPSED (atv, btv);