#include "mini.h"
#include "image-writer.h"
#include "dwarfwriter.h"
+#include "mini-gc.h"
#if !defined(DISABLE_AOT) && !defined(DISABLE_JIT)
#ifdef TARGET_WIN32
#define SHARED_EXT ".dll"
-#elif defined(__ppc__) && defined(__APPLE__)
+#elif defined(__ppc__) && defined(TARGET_MACH)
#define SHARED_EXT ".dylib"
-#elif defined(__APPLE__) && defined(TARGET_X86) && !defined(__native_client_codegen__)
+#elif defined(TARGET_MACH) && defined(TARGET_X86) && !defined(__native_client_codegen__)
#define SHARED_EXT ".dylib"
#else
#define SHARED_EXT ".so"
emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
{
img_writer_emit_section_change (acfg->w, RODATA_SECT, 1);
-#ifdef __APPLE__
+#ifdef TARGET_MACH
/* On apple, all symbols need to be aligned to avoid warnings from ld */
emit_alignment (acfg, 4);
#endif
#endif
#ifdef TARGET_ARM
-#ifdef __MACH__
+#ifdef TARGET_MACH
#define AOT_TARGET_STR "ARM (MACH)"
#else
#define AOT_TARGET_STR "ARM (!MACH)"
g_string_append (acfg->llc_args, "-mattr=+v6");
} else {
#ifdef ARM_FPU_VFP
- g_string_append (acfg->llc_args, " -mattr=+vfp2,+d16");
+ g_string_append (acfg->llc_args, " -mattr=+vfp2,-neon,+d16");
g_string_append (acfg->as_args, " -mfpu=vfp3");
#else
g_string_append (acfg->llc_args, " -soft-float");
mono_arch_set_target (acfg->aot_opts.mtriple);
#endif
-#ifdef __APPLE__
+#ifdef TARGET_MACH
acfg->llvm_label_prefix = "_";
acfg->need_no_dead_strip = TRUE;
#endif
#if defined(__native_client_codegen__)
guint8 *buf_alloc;
#endif
- guint8 *labels [3];
+ guint8 *labels [16];
guint8 mov_buf[3];
guint8 *mov_buf_ptr = mov_buf;
amd64_jump_membase (code, MONO_ARCH_IMT_SCRATCH_REG, 0);
/* No match */
- /* FIXME: */
mono_amd64_patch (labels [1], code);
+ /* Load fail tramp */
+ amd64_alu_reg_imm (code, X86_ADD, MONO_ARCH_IMT_SCRATCH_REG, sizeof (gpointer));
+ /* Check if there is a fail tramp */
+ amd64_alu_membase_imm (code, X86_CMP, MONO_ARCH_IMT_SCRATCH_REG, 0, 0);
+ labels [3] = code;
+ amd64_branch8 (code, X86_CC_Z, 0, FALSE);
+ /* Jump to fail tramp */
+ amd64_jump_membase (code, MONO_ARCH_IMT_SCRATCH_REG, 0);
+
+ /* Fail */
+ mono_amd64_patch (labels [3], code);
x86_breakpoint (code);
/* mov <OFFSET>(%rip), MONO_ARCH_IMT_SCRATCH_REG */
#ifdef __native_client_codegen__
guint8 *buf_alloc;
#endif
- guint8 *labels [3];
+ guint8 *labels [16];
#if defined(__default_codegen__)
code = buf = g_malloc (256);
x86_ret (code);
/* No match */
- /* FIXME: */
mono_x86_patch (labels [1], code);
+ /* Load fail tramp */
+ x86_mov_reg_membase (code, X86_EAX, X86_EAX, sizeof (gpointer), 4);
+ x86_alu_membase_imm (code, X86_CMP, X86_EAX, 0, 0);
+ labels [3] = code;
+ x86_branch8 (code, X86_CC_Z, FALSE, 0);
+ /* Jump to fail tramp */
+ x86_mov_membase_reg (code, X86_ESP, 4, X86_EAX, 4);
+ x86_pop_reg (code, X86_EAX);
+ x86_ret (code);
+
+ /* Fail */
+ mono_x86_patch (labels [3], code);
x86_breakpoint (code);
#ifdef __native_client_codegen__
}
} else if ((klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR)) {
MonoGenericContainer *container = mono_type_get_generic_param_owner (&klass->byval_arg);
- g_assert (container);
+ MonoGenericParam *par = klass->byval_arg.data.generic_param;
encode_value (MONO_AOT_TYPEREF_VAR, p, &p);
encode_value (klass->byval_arg.type, p, &p);
encode_value (mono_type_get_generic_param_num (&klass->byval_arg), p, &p);
-
- encode_value (container->is_method, p, &p);
- if (container->is_method)
- encode_method_ref (acfg, container->owner.method, p, &p);
- else
- encode_klass_ref (acfg, container->owner.klass, p, &p);
+
+ encode_value (container ? 1 : 0, p, &p);
+ if (container) {
+ encode_value (container->is_method, p, &p);
+ g_assert (par->serial == 0);
+ 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->serial, p, &p);
+ }
} else if (klass->byval_arg.type == MONO_TYPE_PTR) {
encode_value (MONO_AOT_TYPEREF_PTR, p, &p);
encode_type (acfg, &klass->byval_arg, p, &p);
static char*
get_plt_symbol (MonoAotCompile *acfg, int plt_offset, MonoJumpInfo *patch_info)
{
-#ifdef __APPLE__
+#ifdef TARGET_MACH
/*
* The Apple linker reorganizes object files, so it doesn't like branches to local
* labels, since those have no relocations.
/* Special cases */
/* Its hard to compute whenever these can be marshalled or not */
- if (!strcmp (klass->name_space, "System.Net.NetworkInformation.MacOsStructs"))
+ if (!strcmp (klass->name_space, "System.Net.NetworkInformation.MacOsStructs") && strcmp (klass->name, "sockaddr_dl"))
return TRUE;
return can_marshal;
int j;
for (j = 0; j < cattr->num_attrs; ++j)
- if (cattr->attrs [j].ctor && !strcmp (cattr->attrs [j].ctor->klass->name, "MonoNativeFunctionWrapperAttribute"))
+ 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));
direct_pinvoke = get_pinvoke_import (acfg, patch_info->data.method);
if (direct_pinvoke) {
const char*prefix;
-#if defined(__APPLE__)
+#if defined(TARGET_MACH)
prefix = "_";
#else
prefix = "";
}
if (debug_sym) {
-#if defined(__APPLE__)
+#if defined(TARGET_MACH)
fprintf (acfg->fp, " .thumb_func %s\n", debug_sym);
fprintf (acfg->fp, " .no_dead_strip %s\n", debug_sym);
#endif
opts->direct_pinvoke = TRUE;
} else if (str_begins_with (arg, "direct-icalls")) {
opts->direct_icalls = TRUE;
+#if defined(TARGET_ARM)
+ } else if (str_begins_with (arg, "iphone-abi")) {
+ // older full-aot users did depend on this.
+#endif
} else if (str_begins_with (arg, "print-skipped")) {
opts->print_skipped_methods = TRUE;
} else if (str_begins_with (arg, "stats")) {
} else if (str_begins_with (arg, "info")) {
printf ("AOT target setup: %s.\n", AOT_TARGET_STR);
exit (0);
+ } else if (str_begins_with (arg, "gc-maps")) {
+ mini_gc_enable_gc_maps_for_aot ();
} else if (str_begins_with (arg, "help") || str_begins_with (arg, "?")) {
printf ("Supported options for --aot:\n");
printf (" outfile=\n");
printf (" tool-prefix=\n");
printf (" readonly-value=\n");
printf (" soft-debug\n");
+ printf (" gc-maps\n");
printf (" print-skipped\n");
printf (" stats\n");
printf (" info\n");
plt_entry = get_plt_entry (llvm_acfg, ji);
plt_entry->llvm_used = TRUE;
-#if defined(__APPLE__)
+#if defined(TARGET_MACH)
return g_strdup_printf (plt_entry->llvm_symbol + strlen (llvm_acfg->llvm_label_prefix));
#else
return g_strdup_printf (plt_entry->llvm_symbol);
static void
emit_llvm_file (MonoAotCompile *acfg)
{
- char *command, *opts;
+ char *command, *opts, *tempbc;
int i;
MonoJumpInfo *patch_info;
}
- mono_llvm_emit_aot_module ("temp.bc", acfg->final_got_size);
+ tempbc = g_strdup_printf ("%s.bc", acfg->tmpfname);
+ mono_llvm_emit_aot_module (tempbc, acfg->final_got_size);
+ g_free (tempbc);
/*
* FIXME: Experiment with adding optimizations, the -std-compile-opts set takes
opts = g_strdup ("-instcombine -simplifycfg");
opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -simplifycfg -preverify -domtree -verify");
#if 1
- command = g_strdup_printf ("%sopt -f %s -o temp.opt.bc temp.bc", acfg->aot_opts.llvm_path, opts);
+ command = g_strdup_printf ("%sopt -f %s -o %s.opt.bc %s.bc", acfg->aot_opts.llvm_path, opts, acfg->tmpfname, acfg->tmpfname);
printf ("Executing opt: %s\n", command);
if (system (command) != 0) {
exit (1);
g_string_append_printf (acfg->llc_args, " -relocation-model=pic");
unlink (acfg->tmpfname);
- command = g_strdup_printf ("%sllc %s -disable-gnu-eh-frame -enable-mono-eh-frame -o %s temp.opt.bc", acfg->aot_opts.llvm_path, acfg->llc_args->str, acfg->tmpfname);
+ command = g_strdup_printf ("%sllc %s -disable-gnu-eh-frame -enable-mono-eh-frame -o %s %s.opt.bc", acfg->aot_opts.llvm_path, acfg->llc_args->str, acfg->tmpfname, acfg->tmpfname);
printf ("Executing llc: %s\n", command);
sprintf (symbol, "name_%d", i);
emit_section_change (acfg, RODATA_SECT, 1);
-#ifdef __APPLE__
+#ifdef TARGET_MACH
emit_alignment (acfg, 4);
#endif
emit_label (acfg, symbol);
for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
emit_int32 (acfg, acfg->trampoline_size [i]);
-#if defined (TARGET_ARM) && defined (__APPLE__)
+#if defined (TARGET_ARM) && defined (TARGET_MACH)
{
MonoType t;
int align = 0;
* mono_aot_register_module (). The symbol points to a pointer to the the file info
* structure.
*/
-#if defined(__APPLE__) && !defined(__native_client_codegen__)
+#if defined(TARGET_MACH) && !defined(__native_client_codegen__)
sprintf (symbol, "_mono_aot_module_%s_info", acfg->image->assembly->aname.name);
#else
sprintf (symbol, "mono_aot_module_%s_info", acfg->image->assembly->aname.name);
#define LD_OPTIONS "-m elf64ppc"
#elif defined(sparc) && SIZEOF_VOID_P == 8
#define AS_OPTIONS "-xarch=v9"
-#elif defined(TARGET_X86) && defined(__APPLE__) && !defined(__native_client_codegen__)
+#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
#define AS_OPTIONS "-arch i386 -W"
#else
#define AS_OPTIONS ""
#if defined(sparc)
command = g_strdup_printf ("ld -shared -G -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
-#elif defined(__ppc__) && defined(__APPLE__)
+#elif defined(__ppc__) && defined(TARGET_MACH)
command = g_strdup_printf ("gcc -dynamiclib -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
#elif defined(HOST_WIN32)
command = g_strdup_printf ("gcc -shared --dll -mno-cygwin -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
-#elif defined(TARGET_X86) && defined(__APPLE__) && !defined(__native_client_codegen__)
+#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
command = g_strdup_printf ("gcc -m32 -dynamiclib -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
#else
command = g_strdup_printf ("%sld %s %s -shared -o %s %s.o", tool_prefix, EH_LD_OPTIONS, LD_OPTIONS, tmp_outfile_name, acfg->tmpfname);
}
g_free (command);
- unlink (objfile);
+
/*com = g_strdup_printf ("strip --strip-unneeded %s%s", acfg->image->name, SHARED_EXT);
printf ("Stripping the binary: %s\n", com);
system (com);
g_free (com);*/
-#if defined(TARGET_ARM) && !defined(__APPLE__)
+#if defined(TARGET_ARM) && !defined(TARGET_MACH)
/*
* 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.
rename (tmp_outfile_name, outfile_name);
+#if defined(TARGET_MACH)
+ command = g_strdup_printf ("dsymutil %s", outfile_name);
+ printf ("Generating debug symbols: %s\n", command);
+ if (system (command) != 0) {
+ return 1;
+ }
+#endif
+
+ if (!acfg->aot_opts.save_temps)
+ unlink (objfile);
+
g_free (tmp_outfile_name);
g_free (outfile_name);
g_free (objfile);
*/
sprintf (symbol, "thumb_end");
emit_section_change (acfg, ".text", 0);
+ emit_alignment (acfg, 8);
emit_label (acfg, symbol);
emit_zero_bytes (acfg, 16);
g_assert (acfg->got_offset <= acfg->final_got_size);
printf ("Code: %d Info: %d Ex Info: %d Unwind Info: %d Class Info: %d PLT: %d GOT Info: %d GOT: %d Offsets: %d\n", acfg->stats.code_size, acfg->stats.info_size, acfg->stats.ex_info_size, acfg->stats.unwind_info_size, acfg->stats.class_info_size, acfg->plt_offset, acfg->stats.got_info_size, (int)(acfg->got_offset * sizeof (gpointer)), acfg->stats.offsets_size);
+ printf ("Compiled: %d/%d (%d%%), No GOT slots: %d (%d%%), Direct calls: %d (%d%%)\n",
+ acfg->stats.ccount, acfg->stats.mcount, acfg->stats.mcount ? (acfg->stats.ccount * 100) / acfg->stats.mcount : 100,
+ acfg->stats.methods_without_got_slots, acfg->stats.mcount ? (acfg->stats.methods_without_got_slots * 100) / acfg->stats.mcount : 100,
+ acfg->stats.direct_calls, acfg->stats.all_calls ? (acfg->stats.direct_calls * 100) / acfg->stats.all_calls : 100);
+ if (acfg->stats.genericcount)
+ printf ("%d methods are generic (%d%%)\n", acfg->stats.genericcount, acfg->stats.mcount ? (acfg->stats.genericcount * 100) / acfg->stats.mcount : 100);
+ if (acfg->stats.abscount)
+ printf ("%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100);
+ if (acfg->stats.lmfcount)
+ printf ("%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100);
+ if (acfg->stats.ocount)
+ printf ("%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100);
+ if (acfg->llvm)
+ printf ("Methods compiled with LLVM: %d (%d%%)\n", acfg->stats.llvm_count, acfg->stats.mcount ? (acfg->stats.llvm_count * 100) / acfg->stats.mcount : 100);
TV_GETTIME (atv);
res = img_writer_emit_writeout (acfg->w);
TV_GETTIME (btv);
acfg->stats.link_time = TV_ELAPSED (atv, btv);
- printf ("Compiled %d out of %d methods (%d%%)\n", acfg->stats.ccount, acfg->stats.mcount, acfg->stats.mcount ? (acfg->stats.ccount * 100) / acfg->stats.mcount : 100);
- if (acfg->stats.genericcount)
- printf ("%d methods are generic (%d%%)\n", acfg->stats.genericcount, acfg->stats.mcount ? (acfg->stats.genericcount * 100) / acfg->stats.mcount : 100);
- if (acfg->stats.abscount)
- printf ("%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100);
- if (acfg->stats.lmfcount)
- printf ("%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100);
- if (acfg->stats.ocount)
- printf ("%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100);
- if (acfg->llvm)
- printf ("Methods compiled with LLVM: %d (%d%%)\n", acfg->stats.llvm_count, acfg->stats.mcount ? (acfg->stats.llvm_count * 100) / acfg->stats.mcount : 100);
- printf ("Methods without GOT slots: %d (%d%%)\n", acfg->stats.methods_without_got_slots, acfg->stats.mcount ? (acfg->stats.methods_without_got_slots * 100) / acfg->stats.mcount : 100);
- printf ("Direct calls: %d (%d%%)\n", acfg->stats.direct_calls, acfg->stats.all_calls ? (acfg->stats.direct_calls * 100) / acfg->stats.all_calls : 100);
-
if (acfg->aot_opts.stats) {
int i;