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;
static inline void
emit_section_change (MonoAotCompile *acfg, const char *section_name, int subsection_index)
{
- img_writer_emit_section_change (acfg->w, section_name, subsection_index);
+ mono_img_writer_emit_section_change (acfg->w, section_name, subsection_index);
}
static inline void
emit_local_symbol (MonoAotCompile *acfg, const char *name, const char *end_label, gboolean func)
{
- img_writer_emit_local_symbol (acfg->w, name, end_label, func);
+ mono_img_writer_emit_local_symbol (acfg->w, name, end_label, func);
}
static inline void
emit_label (MonoAotCompile *acfg, const char *name)
{
- img_writer_emit_label (acfg->w, name);
+ mono_img_writer_emit_label (acfg->w, name);
}
static inline void
emit_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
{
- img_writer_emit_bytes (acfg->w, buf, size);
+ mono_img_writer_emit_bytes (acfg->w, buf, size);
}
static inline void
emit_string (MonoAotCompile *acfg, const char *value)
{
- img_writer_emit_string (acfg->w, value);
+ mono_img_writer_emit_string (acfg->w, value);
}
static inline void
emit_line (MonoAotCompile *acfg)
{
- img_writer_emit_line (acfg->w);
+ mono_img_writer_emit_line (acfg->w);
}
static inline void
emit_alignment (MonoAotCompile *acfg, int size)
{
- img_writer_emit_alignment (acfg->w, size);
+ mono_img_writer_emit_alignment (acfg->w, size);
}
static inline void
emit_alignment_code (MonoAotCompile *acfg, int size)
{
if (acfg->align_pad_value)
- img_writer_emit_alignment_fill (acfg->w, size, acfg->align_pad_value);
+ mono_img_writer_emit_alignment_fill (acfg->w, size, acfg->align_pad_value);
else
- img_writer_emit_alignment (acfg->w, size);
+ mono_img_writer_emit_alignment (acfg->w, size);
}
static inline void
static inline void
emit_pointer (MonoAotCompile *acfg, const char *target)
{
- img_writer_emit_pointer (acfg->w, target);
+ mono_img_writer_emit_pointer (acfg->w, target);
}
static inline void
{
if (prefix [0] != '\0') {
char *s = g_strdup_printf ("%s%s", prefix, target);
- img_writer_emit_pointer (acfg->w, s);
+ mono_img_writer_emit_pointer (acfg->w, s);
g_free (s);
} else {
- img_writer_emit_pointer (acfg->w, target);
+ mono_img_writer_emit_pointer (acfg->w, target);
}
}
static inline void
emit_int16 (MonoAotCompile *acfg, int value)
{
- img_writer_emit_int16 (acfg->w, value);
+ mono_img_writer_emit_int16 (acfg->w, value);
}
static inline void
emit_int32 (MonoAotCompile *acfg, int value)
{
- img_writer_emit_int32 (acfg->w, value);
+ mono_img_writer_emit_int32 (acfg->w, value);
}
static inline void
emit_symbol_diff (MonoAotCompile *acfg, const char *end, const char* start, int offset)
{
- img_writer_emit_symbol_diff (acfg->w, end, start, offset);
+ mono_img_writer_emit_symbol_diff (acfg->w, end, start, offset);
}
static inline void
emit_zero_bytes (MonoAotCompile *acfg, int num)
{
- img_writer_emit_zero_bytes (acfg->w, num);
+ mono_img_writer_emit_zero_bytes (acfg->w, num);
}
static inline void
emit_byte (MonoAotCompile *acfg, guint8 val)
{
- img_writer_emit_byte (acfg->w, val);
+ mono_img_writer_emit_byte (acfg->w, val);
}
#ifdef __native_client_codegen__
static inline void
emit_nacl_call_alignment (MonoAotCompile *acfg)
{
- img_writer_emit_nacl_call_alignment (acfg->w);
+ mono_img_writer_emit_nacl_call_alignment (acfg->w);
}
#endif
static G_GNUC_UNUSED void
emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
{
- img_writer_emit_global (acfg->w, name, func);
+ mono_img_writer_emit_global (acfg->w, name, func);
}
static void
{
if (acfg->aot_opts.no_dlsym) {
g_ptr_array_add (acfg->globals, g_strdup (name));
- img_writer_emit_local_symbol (acfg->w, name, NULL, func);
+ mono_img_writer_emit_local_symbol (acfg->w, name, NULL, func);
} else {
- img_writer_emit_global (acfg->w, name, func);
+ mono_img_writer_emit_global (acfg->w, name, func);
}
}
static void
emit_symbol_size (MonoAotCompile *acfg, const char *name, const char *end_label)
{
- img_writer_emit_symbol_size (acfg->w, name, end_label);
+ mono_img_writer_emit_symbol_size (acfg->w, name, end_label);
}
static void
emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
{
- img_writer_emit_section_change (acfg->w, RODATA_SECT, 1);
+ 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 */
emit_alignment (acfg, 4);
#endif
- img_writer_emit_label (acfg->w, name);
- img_writer_emit_string (acfg->w, value);
+ mono_img_writer_emit_label (acfg->w, name);
+ mono_img_writer_emit_string (acfg->w, value);
}
static G_GNUC_UNUSED void
static void
emit_unset_mode (MonoAotCompile *acfg)
{
- img_writer_emit_unset_mode (acfg->w);
+ mono_img_writer_emit_unset_mode (acfg->w);
}
static G_GNUC_UNUSED void
code = buf;
ARM_BL (code, 0);
- img_writer_emit_reloc (acfg->w, R_ARM_CALL, target, -8);
+ mono_img_writer_emit_reloc (acfg->w, R_ARM_CALL, target, -8);
emit_bytes (acfg, buf, 4);
} else {
emit_unset_mode (acfg);
* arch_emit_got_offset:
*
* The memory pointed to by CODE should hold native code for computing the GOT
- * address. Emit this code while patching it with the offset between code and
- * the GOT. CODE_SIZE is set to the number of bytes emitted.
+ * address (OP_LOAD_GOTADDR). Emit this code while patching it with the offset
+ * between code and the GOT. CODE_SIZE is set to the number of bytes emitted.
*/
static void
arch_emit_got_offset (MonoAotCompile *acfg, guint8 *code, int *code_size)
* arch_emit_got_access:
*
* The memory pointed to by CODE should hold native code for loading a GOT
- * slot. Emit this code while patching it so it accesses the GOT slot GOT_SLOT.
- * CODE_SIZE is set to the number of bytes emitted.
+ * slot (OP_AOTCONST/OP_GOT_ENTRY). Emit this code while patching it so it accesses the
+ * GOT slot GOT_SLOT. CODE_SIZE is set to the number of bytes emitted.
*/
static void
-arch_emit_got_access (MonoAotCompile *acfg, guint8 *code, int got_slot, int *code_size)
+arch_emit_got_access (MonoAotCompile *acfg, const char *got_symbol, guint8 *code, int got_slot, int *code_size)
{
- /* This needs to emit the same code as OP_AOTCONST */
-
#ifdef TARGET_AMD64
/* mov reg, got+offset(%rip) */
if (acfg->llvm) {
dreg = ((code [2] >> 3) & 0x7) + (rex_r ? 8 : 0);
emit_unset_mode (acfg);
- fprintf (acfg->fp, "mov %s+%d(%%rip), %s\n", acfg->got_symbol, (unsigned int) ((got_slot * sizeof (gpointer))), mono_arch_regname (dreg));
+ fprintf (acfg->fp, "mov %s+%d(%%rip), %s\n", got_symbol, (unsigned int) ((got_slot * sizeof (gpointer))), mono_arch_regname (dreg));
*code_size = 7;
} else {
emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
- emit_symbol_diff (acfg, acfg->got_symbol, ".", (unsigned int) ((got_slot * sizeof (gpointer)) - 4));
+ emit_symbol_diff (acfg, got_symbol, ".", (unsigned int) ((got_slot * sizeof (gpointer)) - 4));
*code_size = mono_arch_get_patch_offset (code) + 4;
}
#elif defined(TARGET_X86)
*code_size = mono_arch_get_patch_offset (code) + 4;
#elif defined(TARGET_ARM)
emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
- emit_symbol_diff (acfg, acfg->got_symbol, ".", (unsigned int) ((got_slot * sizeof (gpointer))) - 12);
+ emit_symbol_diff (acfg, got_symbol, ".", (unsigned int) ((got_slot * sizeof (gpointer))) - 12);
*code_size = mono_arch_get_patch_offset (code) + 4;
#elif defined(TARGET_ARM64)
emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
sprintf (symbol2, "L_OBJC_SELECTOR_REFERENCES_%d", index);
emit_label (acfg, symbol1);
- img_writer_emit_unset_mode (acfg->w);
+ mono_img_writer_emit_unset_mode (acfg->w);
fprintf (acfg->fp, ".long %s-(%s+12)", symbol2, symbol1);
*code_size = 12;
/*
* arch_emit_plt_entry:
*
- * Emit code for the PLT entry with index INDEX.
+ * Emit code for the PLT entry.
+ * The plt entry should look like this:
+ * <indirect jump to GOT_SYMBOL + OFFSET>
+ * <INFO_OFFSET embedded into the instruction stream>
*/
static void
-arch_emit_plt_entry (MonoAotCompile *acfg, int index)
+arch_emit_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offset, int info_offset)
{
#if defined(TARGET_X86)
- guint32 offset = (acfg->plt_got_offset_base + index) * sizeof (gpointer);
#if defined(__default_codegen__)
/* jmp *<offset>(%ebx) */
emit_byte (acfg, 0xff);
emit_byte (acfg, 0xa3);
emit_int32 (acfg, offset);
/* Used by mono_aot_get_plt_info_offset */
- emit_int32 (acfg, acfg->plt_got_info_offsets [index]);
+ emit_int32 (acfg, info_offset);
#elif defined(__native_client_codegen__)
const guint8 kSizeOfNaClJmp = 11;
guint8 bytes[kSizeOfNaClJmp];
/* four bytes of data, used by mono_arch_patch_plt_entry */
/* For Native Client, make this work with data embedded in push. */
emit_byte (acfg, 0x68); /* hide data in a push */
- emit_int32 (acfg, acfg->plt_got_info_offsets [index]);
+ emit_int32 (acfg, info_offset);
emit_alignment (acfg, AOT_FUNC_ALIGNMENT);
#endif /*__native_client_codegen__*/
#elif defined(TARGET_AMD64)
if (acfg->use_bin_writer) {
emit_byte (acfg, '\xff');
emit_byte (acfg, '\x25');
- emit_symbol_diff (acfg, acfg->got_symbol, ".", ((acfg->plt_got_offset_base + index) * sizeof (gpointer)) -4);
+ emit_symbol_diff (acfg, got_symbol, ".", offset - 4);
} else {
emit_unset_mode (acfg);
- fprintf (acfg->fp, "jmp *%s+%d(%%rip)\n", acfg->got_symbol, (int)((acfg->plt_got_offset_base + index) * sizeof (gpointer)));
+ fprintf (acfg->fp, "jmp *%s+%d(%%rip)\n", got_symbol, offset);
}
/* Used by mono_aot_get_plt_info_offset */
- emit_int32 (acfg, acfg->plt_got_info_offsets [index]);
+ emit_int32 (acfg, info_offset);
acfg->stats.plt_size += 10;
#elif defined(__native_client_codegen__)
guint8 buf [256];
emit_byte (acfg, '\x45');
emit_byte (acfg, '\x8b');
emit_byte (acfg, '\x1d');
- emit_symbol_diff (acfg, acfg->got_symbol, ".", ((acfg->plt_got_offset_base + index) * sizeof (gpointer)) -4);
+ emit_symbol_diff (acfg, got_symbol, ".", offset - 4);
amd64_jump_reg (code, AMD64_R11);
/* This should be constant for the plt patch */
/* Hide data in a push imm32 so it passes validation */
emit_byte (acfg, 0x68); /* push */
- emit_int32 (acfg, acfg->plt_got_info_offsets [index]);
+ emit_int32 (acfg, info_offset);
emit_alignment (acfg, AOT_FUNC_ALIGNMENT);
#endif /*__native_client_codegen__*/
#elif defined(TARGET_ARM)
ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
ARM_LDR_REG_REG (code, ARMREG_PC, ARMREG_PC, ARMREG_IP);
emit_bytes (acfg, buf, code - buf);
- emit_symbol_diff (acfg, acfg->got_symbol, ".", ((acfg->plt_got_offset_base + index) * sizeof (gpointer)) - 4);
+ emit_symbol_diff (acfg, got_symbol, ".", offset - 4);
/* Used by mono_aot_get_plt_info_offset */
- emit_int32 (acfg, acfg->plt_got_info_offsets [index]);
+ emit_int32 (acfg, info_offset);
#elif defined(TARGET_ARM64)
- arm64_emit_plt_entry (acfg, index);
+ arm64_emit_plt_entry (acfg, got_symbol, offset, info_offset);
#elif defined(TARGET_POWERPC)
- guint32 offset = (acfg->plt_got_offset_base + index) * sizeof (gpointer);
-
/* The GOT address is guaranteed to be in r30 by OP_LOAD_GOTADDR */
g_assert (!acfg->use_bin_writer);
emit_unset_mode (acfg);
#endif
fprintf (acfg->fp, "mtctr 11\n");
fprintf (acfg->fp, "bctr\n");
- emit_int32 (acfg, acfg->plt_got_info_offsets [index]);
+ emit_int32 (acfg, info_offset);
#else
g_assert_not_reached ();
#endif
}
+/*
+ * arch_emit_llvm_plt_entry:
+ *
+ * Same as arch_emit_plt_entry, but handles calls from LLVM generated code.
+ * This is only needed on arm to handle thumb interop.
+ */
static void
-arch_emit_llvm_plt_entry (MonoAotCompile *acfg, int index)
+arch_emit_llvm_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offset, int info_offset)
{
#if defined(TARGET_ARM)
-#if 0
- /* LLVM calls the PLT entries using bl, so emit a stub */
- /* FIXME: Too much overhead on every call */
- fprintf (acfg->fp, ".thumb_func\n");
- fprintf (acfg->fp, "bx pc\n");
- fprintf (acfg->fp, "nop\n");
- fprintf (acfg->fp, ".arm\n");
-#endif
/* LLVM calls the PLT entries using bl, so these have to be thumb2 */
/* The caller already transitioned to thumb */
/* The code below should be 12 bytes long */
fprintf (acfg->fp, ".2byte 0x44fc\n");
fprintf (acfg->fp, ".4byte 0xc000f8dc\n");
fprintf (acfg->fp, ".2byte 0x4760\n");
- emit_symbol_diff (acfg, acfg->got_symbol, ".", ((acfg->plt_got_offset_base + index) * sizeof (gpointer)) + 4);
- emit_int32 (acfg, acfg->plt_got_info_offsets [index]);
+ emit_symbol_diff (acfg, got_symbol, ".", offset + 4);
+ emit_int32 (acfg, info_offset);
emit_unset_mode (acfg);
emit_set_arm_mode (acfg);
#else
code = buf;
ARM_B (code, 0);
- img_writer_emit_reloc (acfg->w, R_ARM_JUMP24, call_target, -8);
+ mono_img_writer_emit_reloc (acfg->w, R_ARM_JUMP24, call_target, -8);
emit_bytes (acfg, buf, 4);
} else {
if (acfg->thumb_mixed && cfg->compile_llvm)
encode_value (container ? 1 : 0, p, &p);
if (container) {
encode_value (container->is_method, p, &p);
- g_assert (par->gshared_constraint == 0);
+ g_assert (!par->gshared_constraint);
if (container->is_method)
encode_method_ref (acfg, container->owner.method, p, &p);
else
encode_klass_ref (acfg, container->owner.klass, p, &p);
} else {
- encode_value (par->gshared_constraint, p, &p);
+ encode_value (par->gshared_constraint ? 1 : 0, p, &p);
if (par->gshared_constraint) {
- const char *name = mono_generic_param_name (par);
+ const char *name;
+ encode_type (acfg, par->gshared_constraint, p, &p);
+
+ name = mono_generic_param_name (par);
if (name) {
int len = strlen (name);
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)
{
{
if (mono_method_is_generic_sharable_full (method, FALSE, 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);
got_slot = get_got_offset (acfg, FALSE, patch_info);
- arch_emit_got_access (acfg, code + i, got_slot, &code_size);
+ arch_emit_got_access (acfg, acfg->got_symbol, code + i, got_slot, &code_size);
i += code_size - INST_LEN;
}
skip = TRUE;
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:
encode_klass_ref (acfg, patch_info->data.virt_method->klass, p, &p);
encode_method_ref (acfg, patch_info->data.virt_method->method, p, &p);
break;
+ case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
+ break;
default:
g_warning ("unable to handle jump info %d", patch_info->type);
g_assert_not_reached ();
}
seq_points = cfg->seq_point_info;
- seq_points_size = (store_seq_points)? seq_point_info_get_write_size (seq_points) : 0;
+ seq_points_size = (store_seq_points)? mono_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;
MonoJitExceptionInfo *ei = &jinfo->clauses [k];
encode_value (ei->flags, p, &p);
+#ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
+ /* Not used for catch clauses */
+ if (ei->flags != MONO_EXCEPTION_CLAUSE_NONE)
+ encode_value (ei->exvar_offset, p, &p);
+#else
encode_value (ei->exvar_offset, p, &p);
+#endif
if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER || ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY)
encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
}
if (seq_points_size)
- p += seq_point_info_write (seq_points, p);
+ p += mono_seq_point_info_write (seq_points, p);
g_assert (debug_info_size < buf_size);
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;
}
emit_label (acfg, plt_entry->symbol);
- arch_emit_plt_entry (acfg, i);
+ arch_emit_plt_entry (acfg, acfg->got_symbol, (acfg->plt_got_offset_base + i) * sizeof (gpointer), acfg->plt_got_info_offsets [i]);
if (debug_sym)
emit_symbol_size (acfg, debug_sym, ".");
if (acfg->llvm)
emit_global_inner (acfg, plt_entry->llvm_symbol, TRUE);
- arch_emit_llvm_plt_entry (acfg, i);
+ arch_emit_llvm_plt_entry (acfg, acfg->got_symbol, (acfg->plt_got_offset_base + i) * sizeof (gpointer), acfg->plt_got_info_offsets [i]);
if (debug_sym) {
emit_symbol_size (acfg, debug_sym, ".");
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);
#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;
mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE)) &&
!method_has_type_vars (m)) {
if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
- if (acfg->aot_opts.full_aot)
+ if (mono_aot_mode_is_full (&acfg->aot_opts))
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);
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;
if (method_seq_points_to_file) {
if (!seq_points_to_file) {
- seq_point_data_init (&sp_data, acfg->nmethods);
+ mono_seq_point_data_init (&sp_data, acfg->nmethods);
seq_points_to_file = TRUE;
}
- seq_point_data_add (&sp_data, cfg->method->token, cfg->method_index, cfg->seq_point_info);
+ mono_seq_point_data_add (&sp_data, cfg->method->token, cfg->method_index, 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);
+ mono_seq_point_data_write (&sp_data, seq_points_aot_file);
+ mono_seq_point_data_free (&sp_data);
g_free (seq_points_aot_file);
}
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_objc_selectors (MonoAotCompile *acfg)
{
int i;
+ char symbol [128];
if (!acfg->objc_selectors || acfg->objc_selectors->len == 0)
return;
* EOF
*/
- img_writer_emit_unset_mode (acfg->w);
+ mono_img_writer_emit_unset_mode (acfg->w);
g_assert (acfg->fp);
fprintf (acfg->fp, ".section __DATA,__objc_selrefs,literal_pointers,no_dead_strip\n");
fprintf (acfg->fp, ".align 3\n");
for (i = 0; i < acfg->objc_selectors->len; ++i) {
- fprintf (acfg->fp, "L_OBJC_SELECTOR_REFERENCES_%d:\n", i);
- fprintf (acfg->fp, ".long L_OBJC_METH_VAR_NAME_%d\n", i);
+ sprintf (symbol, "L_OBJC_SELECTOR_REFERENCES_%d", i);
+ emit_label (acfg, symbol);
+ sprintf (symbol, "L_OBJC_METH_VAR_NAME_%d", i);
+ emit_pointer (acfg, symbol);
+
}
fprintf (acfg->fp, ".section __TEXT,__cstring,cstring_literals\n");
for (i = 0; i < acfg->objc_selectors->len; ++i) {
/* 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);
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) && !defined(TARGET_ANDROID)
+#define LD_NAME "gcc --shared"
#endif
if (acfg->aot_opts.asm_only) {
* 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);
{
int i;
- img_writer_destroy (acfg->w);
+ mono_img_writer_destroy (acfg->w);
for (i = 0; i < acfg->nmethods; ++i)
if (acfg->cfgs [i])
g_free (acfg->cfgs [i]);
char * dumpname;
JsonWriter writer;
- json_writer_init (&writer);
+ mono_json_writer_init (&writer);
- json_writer_object_begin(&writer);
+ mono_json_writer_object_begin(&writer);
// Methods
- json_writer_indent (&writer);
- json_writer_object_key(&writer, "methods");
- json_writer_array_begin (&writer);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_object_key(&writer, "methods");
+ mono_json_writer_array_begin (&writer);
int i;
for (i = 0; i < acfg->nmethods; ++i) {
method = cfg->orig_method;
- json_writer_indent (&writer);
- json_writer_object_begin(&writer);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_object_begin(&writer);
- json_writer_indent (&writer);
- json_writer_object_key(&writer, "name");
- json_writer_printf (&writer, "\"%s\",\n", method->name);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_object_key(&writer, "name");
+ mono_json_writer_printf (&writer, "\"%s\",\n", method->name);
- json_writer_indent (&writer);
- json_writer_object_key(&writer, "signature");
- json_writer_printf (&writer, "\"%s\",\n", mono_method_full_name (method,
+ mono_json_writer_indent (&writer);
+ mono_json_writer_object_key(&writer, "signature");
+ mono_json_writer_printf (&writer, "\"%s\",\n", mono_method_full_name (method,
/*signature=*/TRUE));
- json_writer_indent (&writer);
- json_writer_object_key(&writer, "code_size");
- json_writer_printf (&writer, "\"%d\",\n", cfg->code_size);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_object_key(&writer, "code_size");
+ mono_json_writer_printf (&writer, "\"%d\",\n", cfg->code_size);
klass = method->klass;
- json_writer_indent (&writer);
- json_writer_object_key(&writer, "class");
- json_writer_printf (&writer, "\"%s\",\n", klass->name);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_object_key(&writer, "class");
+ mono_json_writer_printf (&writer, "\"%s\",\n", klass->name);
- json_writer_indent (&writer);
- json_writer_object_key(&writer, "namespace");
- json_writer_printf (&writer, "\"%s\",\n", klass->name_space);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_object_key(&writer, "namespace");
+ mono_json_writer_printf (&writer, "\"%s\",\n", klass->name_space);
- json_writer_indent (&writer);
- json_writer_object_key(&writer, "wrapper_type");
- json_writer_printf (&writer, "\"%s\",\n", get_wrapper_type_name(method->wrapper_type));
+ mono_json_writer_indent (&writer);
+ mono_json_writer_object_key(&writer, "wrapper_type");
+ mono_json_writer_printf (&writer, "\"%s\",\n", get_wrapper_type_name(method->wrapper_type));
- json_writer_indent_pop (&writer);
- json_writer_indent (&writer);
- json_writer_object_end (&writer);
- json_writer_printf (&writer, ",\n");
+ mono_json_writer_indent_pop (&writer);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_object_end (&writer);
+ mono_json_writer_printf (&writer, ",\n");
}
- json_writer_indent_pop (&writer);
- json_writer_indent (&writer);
- json_writer_array_end (&writer);
- json_writer_printf (&writer, ",\n");
+ mono_json_writer_indent_pop (&writer);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_array_end (&writer);
+ mono_json_writer_printf (&writer, ",\n");
// PLT entries
#ifdef DUMP_PLT
- json_writer_indent_push (&writer);
- json_writer_indent (&writer);
- json_writer_object_key(&writer, "plt");
- json_writer_array_begin (&writer);
+ mono_json_writer_indent_push (&writer);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_object_key(&writer, "plt");
+ mono_json_writer_array_begin (&writer);
for (i = 0; i < acfg->plt_offset; ++i) {
MonoPltEntry *plt_entry = NULL;
plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
ji = plt_entry->ji;
- json_writer_indent (&writer);
- json_writer_printf (&writer, "{ ");
- json_writer_object_key(&writer, "symbol");
- json_writer_printf (&writer, "\"%s\" },\n", plt_entry->symbol);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_printf (&writer, "{ ");
+ mono_json_writer_object_key(&writer, "symbol");
+ mono_json_writer_printf (&writer, "\"%s\" },\n", plt_entry->symbol);
}
- json_writer_indent_pop (&writer);
- json_writer_indent (&writer);
- json_writer_array_end (&writer);
- json_writer_printf (&writer, ",\n");
+ mono_json_writer_indent_pop (&writer);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_array_end (&writer);
+ mono_json_writer_printf (&writer, ",\n");
#endif
// GOT entries
#ifdef DUMP_GOT
- json_writer_indent_push (&writer);
- json_writer_indent (&writer);
- json_writer_object_key(&writer, "got");
- json_writer_array_begin (&writer);
+ mono_json_writer_indent_push (&writer);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_object_key(&writer, "got");
+ mono_json_writer_array_begin (&writer);
- json_writer_indent_push (&writer);
+ mono_json_writer_indent_push (&writer);
for (i = 0; i < acfg->got_info.got_patches->len; ++i) {
MonoJumpInfo *ji = g_ptr_array_index (acfg->got_info.got_patches, i);
- json_writer_indent (&writer);
- json_writer_printf (&writer, "{ ");
- json_writer_object_key(&writer, "patch_name");
- json_writer_printf (&writer, "\"%s\" },\n", get_patch_name (ji->type));
+ mono_json_writer_indent (&writer);
+ mono_json_writer_printf (&writer, "{ ");
+ mono_json_writer_object_key(&writer, "patch_name");
+ mono_json_writer_printf (&writer, "\"%s\" },\n", get_patch_name (ji->type));
}
- json_writer_indent_pop (&writer);
- json_writer_indent (&writer);
- json_writer_array_end (&writer);
- json_writer_printf (&writer, ",\n");
+ mono_json_writer_indent_pop (&writer);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_array_end (&writer);
+ mono_json_writer_printf (&writer, ",\n");
#endif
- json_writer_indent_pop (&writer);
- json_writer_indent (&writer);
- json_writer_object_end (&writer);
+ mono_json_writer_indent_pop (&writer);
+ mono_json_writer_indent (&writer);
+ mono_json_writer_object_end (&writer);
dumpname = g_strdup_printf ("%s.json", g_path_get_basename (acfg->image->name));
dumpfile = fopen (dumpname, "w+");
fprintf (dumpfile, "%s", writer.text->str);
fclose (dumpfile);
- json_writer_destroy (&writer);
+ mono_json_writer_destroy (&writer);
}
int
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 = img_writer_get_temp_label_prefix (NULL);
+ 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) {
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);
}
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->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
}
#endif
- if (!acfg->aot_opts.asm_only && !acfg->aot_opts.asm_writer && bin_writer_supported ()) {
+ if (!acfg->aot_opts.asm_only && !acfg->aot_opts.asm_writer && mono_bin_writer_supported ()) {
if (acfg->aot_opts.outfile)
outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
else
return 1;
}
- acfg->w = img_writer_create (acfg->fp, TRUE);
+ acfg->w = mono_img_writer_create (acfg->fp, TRUE);
acfg->use_bin_writer = TRUE;
} else {
if (acfg->aot_opts.asm_only) {
aot_printerrf (acfg, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno));
return 1;
}
- acfg->w = img_writer_create (acfg->fp, FALSE);
+ acfg->w = mono_img_writer_create (acfg->fp, FALSE);
tmp_outfile_name = NULL;
outfile_name = NULL;
acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, FALSE, !acfg->gas_line_numbers);
}
- img_writer_emit_start (acfg->w);
+ mono_img_writer_emit_start (acfg->w);
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);
aot_printf (acfg, "%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100);
TV_GETTIME (atv);
- res = img_writer_emit_writeout (acfg->w);
+ res = mono_img_writer_emit_writeout (acfg->w);
if (res != 0) {
acfg_free (acfg);
return res;