#if !defined(DISABLE_AOT) && !defined(DISABLE_JIT)
-#if defined(__linux__)
+#if defined(__linux__) || defined(__native_client_codegen__)
#define RODATA_SECT ".rodata"
#else
#define RODATA_SECT ".text"
#define SHARED_EXT ".dll"
#elif defined(__ppc__) && defined(__MACH__)
#define SHARED_EXT ".dylib"
+#elif defined(__APPLE__) && defined(TARGET_X86) && !defined(__native_client_codegen__)
+#define SHARED_EXT ".dylib"
#else
#define SHARED_EXT ".so"
#endif
gboolean stats;
char *tool_prefix;
gboolean autoreg;
+ char *mtriple;
} MonoAotOptions;
typedef struct MonoAotStats {
gboolean llvm;
MonoAotFileFlags flags;
MonoDynamicStream blob;
+ MonoClass **typespec_classes;
+ GString *llc_args;
+ GString *as_args;
} MonoAotCompile;
typedef struct {
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);
+}
+#endif
+
static G_GNUC_UNUSED void
emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
{
#else
#define AOT_FUNC_ALIGNMENT 16
#endif
+#if defined(TARGET_X86) && defined(__native_client_codegen__)
+#undef AOT_FUNC_ALIGNMENT
+#define AOT_FUNC_ALIGNMENT 32
+#endif
#if defined(TARGET_POWERPC64) && !defined(__mono_ilp32__)
#define PPC_LD_OP "ld"
#define PPC_LDX_OP "lwzx"
#endif
-//#define TARGET_ARM
+static void
+arch_process_target_triple (MonoAotCompile *acfg)
+{
+ char *mtriple = acfg->aot_opts.mtriple;
+
+ if (!mtriple)
+ return;
+
+ acfg->llc_args = g_string_new ("");
+ acfg->as_args = g_string_new ("");
#ifdef TARGET_ARM
-#define LLVM_LABEL_PREFIX "_"
+ if (strstr (acfg->aot_opts.mtriple, "darwin")) {
+ g_string_append (acfg->llc_args, "-mattr=+v6");
+ acfg->llvm_label_prefix = "_";
+ } else {
+#ifdef ARM_FPU_VFP
+ g_string_append (acfg->llc_args, " -mattr=+vfp2,+d16");
+ g_string_append (acfg->as_args, " -mfpu=vfp3");
#else
-#define LLVM_LABEL_PREFIX ""
+ g_string_append (acfg->llc_args, " -soft-float");
#endif
+ }
-#ifdef TARGET_ARM
-/* iphone */
-#define LLC_TARGET_ARGS "-march=arm -mattr=+v6 -mtriple=arm-apple-darwin"
-/* ELF */
-//#define LLC_TARGET_ARGS "-march=arm -mtriple=arm-linux-gnueabi -soft-float"
-#else
-#define LLC_TARGET_ARGS ""
+ mono_arch_set_target (mtriple);
#endif
+}
/*
* arch_emit_direct_call:
#if defined(TARGET_X86)
guint32 offset = (acfg->plt_got_offset_base + index) * sizeof (gpointer);
+#ifdef __native_client_codegen__
+ const guint8 kSizeOfNaClJmp = 11;
+ guint8 bytes[kSizeOfNaClJmp];
+ guint8 *pbytes = &bytes[0];
+
+ x86_jump_membase32 (pbytes, X86_EBX, offset);
+ emit_bytes (acfg, 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_alignment (acfg, AOT_FUNC_ALIGNMENT);
+#else
/* 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]);
+#endif /* __native_client_codegen__ */
#elif defined(TARGET_AMD64)
/*
* We can't emit jumps because they are 32 bits only so they can't be patched.
/* Branch to generic trampoline */
x86_jump_reg (code, X86_ECX);
+#ifdef __native_client_codegen__
+ {
+ /* emit nops to next 32 byte alignment */
+ int a = (~kNaClAlignmentMask) & ((code - buf) + kNaClAlignment - 1);
+ while (code < (buf + a)) x86_nop(code);
+ }
+#endif
emit_bytes (acfg, buf, code - buf);
- *tramp_size = 17;
+ *tramp_size = NACL_SIZE(17, kNaClAlignment);
g_assert (code - buf == *tramp_size);
#else
g_assert_not_reached ();
* CALL_TARGET is the symbol pointing to the native code of METHOD.
*/
static void
-arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoMethod *method, MonoGenericSharingContext *gsctx, const char *call_target)
+arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoMethod *method, const char *call_target)
{
#if defined(TARGET_AMD64)
guint8 buf [32];
guint8 *code;
int this_reg;
- this_reg = mono_arch_get_this_arg_reg (mono_method_signature (method), gsctx, NULL);
+ this_reg = mono_arch_get_this_arg_reg (NULL);
code = buf;
amd64_alu_reg_imm (code, X86_ADD, this_reg, sizeof (MonoObject));
/* Branch to the target address */
x86_jump_membase (code, X86_ECX, (offset + 1) * sizeof (gpointer));
+#ifdef __native_client_codegen__
+ {
+ /* emit nops to next 32 byte alignment */
+ int a = (~kNaClAlignmentMask) & ((code - buf) + kNaClAlignment - 1);
+ while (code < (buf + a)) x86_nop(code);
+ }
+#endif
+
emit_bytes (acfg, buf, code - buf);
- *tramp_size = 15;
+ *tramp_size = NACL_SIZE (15, kNaClAlignment);
g_assert (code - buf == *tramp_size);
#else
g_assert_not_reached ();
*tramp_size = code - buf + 7;
#elif defined(TARGET_X86)
guint8 *buf, *code;
+#ifdef __native_client_codegen__
+ guint8 *buf_alloc;
+#endif
guint8 *labels [3];
+#ifdef __native_client_codegen__
+ buf_alloc = g_malloc (256 + kNaClAlignment);
+ code = buf = ((guint)buf_alloc + kNaClAlignment) & ~kNaClAlignmentMask;
+#else
code = buf = g_malloc (256);
+#endif
/* Allocate a temporary stack slot */
x86_push_reg (code, X86_EAX);
mono_x86_patch (labels [1], code);
x86_breakpoint (code);
+#ifdef __native_client_codegen__
+ {
+ /* emit nops to next 32 byte alignment */
+ int a = (~kNaClAlignmentMask) & ((code - buf) + kNaClAlignment - 1);
+ while (code < (buf + a)) x86_nop(code);
+ }
+#endif
emit_bytes (acfg, buf, code - buf);
*tramp_size = code - buf;
sh->data = g_malloc (4096);
/* So offsets are > 0 */
+ sh->data [0] = 0;
sh->index ++;
}
* blob where the data was stored.
*/
static guint32
-add_to_blob (MonoAotCompile *acfg, guint8 *data, guint32 data_len)
+add_to_blob (MonoAotCompile *acfg, const guint8 *data, guint32 data_len)
{
if (acfg->blob.alloc_size == 0)
stream_init (&acfg->blob);
find_typespec_for_class (MonoAotCompile *acfg, MonoClass *klass)
{
int i;
- MonoClass *k = NULL;
+ int len = acfg->image->tables [MONO_TABLE_TYPESPEC].rows;
/* FIXME: Search referenced images as well */
- for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
- k = mono_class_get_full (acfg->image, MONO_TOKEN_TYPE_SPEC | (i + 1), NULL);
- if (k == klass)
+ if (!acfg->typespec_classes) {
+ acfg->typespec_classes = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoClass*) * len);
+ for (i = 0; i < len; ++i) {
+ acfg->typespec_classes [i] = mono_class_get_full (acfg->image, MONO_TOKEN_TYPE_SPEC | (i + 1), NULL);
+ }
+ }
+ for (i = 0; i < len; ++i) {
+ if (acfg->typespec_classes [i] == klass)
break;
}
- if (i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows)
+ if (i < len)
return MONO_TOKEN_TYPE_SPEC | (i + 1);
else
return 0;
case MONO_WRAPPER_ALLOC: {
AllocatorWrapperInfo *info = mono_marshal_get_wrapper_info (method);
+ /* The GC name is saved once in MonoAotFileInfo */
g_assert (info->alloc_type != -1);
encode_value (info->alloc_type, p, &p);
break;
}
case MONO_WRAPPER_WRITE_BARRIER:
break;
- case MONO_WRAPPER_STELEMREF:
+ case MONO_WRAPPER_STELEMREF: {
+ MonoClass *klass = mono_marshal_get_wrapper_info (method);
+
+ /* Make sure this is the 'normal' stelemref wrapper, not the virtual one */
+ g_assert (!klass);
break;
+ }
case MONO_WRAPPER_UNKNOWN:
if (strcmp (method->name, "FastMonitorEnter") == 0)
encode_value (MONO_AOT_WRAPPER_MONO_ENTER, p, &p);
/* Skip methods which can not be handled by get_runtime_invoke () */
sig = mono_method_signature (method);
+ if (!sig)
+ continue;
if ((sig->ret->type == MONO_TYPE_PTR) ||
(sig->ret->type == MONO_TYPE_TYPEDBYREF))
skip = TRUE;
if (method)
add_method (acfg, method);
#endif
+
+ /* Stelemref wrappers */
+ /* There is only a constant number of these, iterating over all types should handle them all */
+ for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
+ MonoClass *klass;
+
+ token = MONO_TOKEN_TYPE_DEF | (i + 1);
+ klass = mono_class_get (acfg->image, token);
+ if (klass)
+ add_method (acfg, mono_marshal_get_virtual_stelemref (mono_array_class_get (klass, 1)));
+ }
}
/*
static void add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth);
static void
-add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
+add_generic_class (MonoAotCompile *acfg, MonoClass *klass, gboolean force)
{
+ /* This might lead to a huge code blowup so only do it if neccesary */
+ if (!acfg->aot_opts.full_aot && !force)
+ return;
+
add_generic_class_with_depth (acfg, klass, 0);
}
}
g_assert (nclass);
nclass = mono_class_inflate_generic_class (nclass, mono_generic_class_get_context (klass->generic_class));
- add_generic_class (acfg, nclass);
+ add_generic_class (acfg, nclass, FALSE);
}
iter = NULL;
if (mono_class_is_assignable_from (mono_class_inflate_generic_class (icomparable, &ctx), tclass)) {
gcomparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "GenericComparer`1");
g_assert (gcomparer);
- add_generic_class (acfg, mono_class_inflate_generic_class (gcomparer, &ctx));
+ add_generic_class (acfg, mono_class_inflate_generic_class (gcomparer, &ctx), FALSE);
+ }
+ }
+
+ /* Add an instance of GenericEqualityComparer<T> which is created dynamically by EqualityComparer<T> */
+ if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
+ MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *iface, *gcomparer;
+ MonoGenericContext ctx;
+ MonoType *args [16];
+
+ memset (&ctx, 0, sizeof (ctx));
+
+ iface = mono_class_from_name (mono_defaults.corlib, "System", "IEquatable`1");
+ g_assert (iface);
+ args [0] = &tclass->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+
+ if (mono_class_is_assignable_from (mono_class_inflate_generic_class (iface, &ctx), tclass)) {
+ gcomparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "GenericEqualityComparer`1");
+ g_assert (gcomparer);
+ add_generic_class (acfg, mono_class_inflate_generic_class (gcomparer, &ctx), FALSE);
}
}
}
static void
-add_instances_of (MonoAotCompile *acfg, MonoClass *klass, MonoType **insts, int ninsts)
+add_instances_of (MonoAotCompile *acfg, MonoClass *klass, MonoType **insts, int ninsts, gboolean force)
{
int i;
MonoGenericContext ctx;
for (i = 0; i < ninsts; ++i) {
args [0] = insts [i];
ctx.class_inst = mono_metadata_get_generic_inst (1, args);
- add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx), force);
}
}
token = MONO_TOKEN_METHOD_SPEC | (i + 1);
method = mono_get_method (acfg->image, token, NULL);
+ if (!method)
+ continue;
+
if (method->klass->image != acfg->image)
continue;
if (!klass || klass->rank)
continue;
- add_generic_class (acfg, klass);
+ add_generic_class (acfg, klass, FALSE);
}
/* Add types of args/locals */
if (sig) {
for (j = 0; j < sig->param_count; ++j)
if (sig->params [j]->type == MONO_TYPE_GENERICINST)
- add_generic_class (acfg, mono_class_from_mono_type (sig->params [j]));
+ add_generic_class (acfg, mono_class_from_mono_type (sig->params [j]), FALSE);
}
header = mono_method_get_header (method);
if (header) {
for (j = 0; j < header->num_locals; ++j)
if (header->locals [j]->type == MONO_TYPE_GENERICINST)
- add_generic_class (acfg, mono_class_from_mono_type (header->locals [j]));
+ add_generic_class (acfg, mono_class_from_mono_type (header->locals [j]), FALSE);
}
}
/* Add GenericComparer<T> instances for primitive types for Enum.ToString () */
klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericComparer`1");
if (klass)
- add_instances_of (acfg, klass, insts, ninsts);
+ add_instances_of (acfg, klass, insts, ninsts, TRUE);
klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericEqualityComparer`1");
if (klass)
- add_instances_of (acfg, klass, insts, ninsts);
+ add_instances_of (acfg, klass, insts, ninsts, TRUE);
/* Add instances of the array generic interfaces for primitive types */
/* This will add instances of the InternalArray_ helper methods in Array too */
klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "ICollection`1");
if (klass)
- add_instances_of (acfg, klass, insts, ninsts);
+ add_instances_of (acfg, klass, insts, ninsts, TRUE);
klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "IList`1");
if (klass)
- add_instances_of (acfg, klass, insts, ninsts);
+ add_instances_of (acfg, klass, insts, ninsts, TRUE);
klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "IEnumerable`1");
if (klass)
- add_instances_of (acfg, klass, insts, ninsts);
+ add_instances_of (acfg, klass, insts, ninsts, TRUE);
/*
* Add a managed-to-native wrapper of Array.GetGenericValueImpl<object>, which is
encode_value (get_image_index (acfg, patch_info->data.image), p, &p);
break;
case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
+ case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
break;
case MONO_PATCH_INFO_METHOD_REL:
encode_value ((gint)patch_info->data.offset, p, &p);
continue;
}
+ if (patch_info->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR) {
+ /* Stored in a GOT slot initialized at module load time */
+ patch_info->type = MONO_PATCH_INFO_NONE;
+ continue;
+ }
+
if (is_plt_patch (patch_info)) {
/* Calls are made through the PLT */
patch_info->type = MONO_PATCH_INFO_NONE;
ji = info->ji;
unwind_ops = info->unwind_ops;
+#ifdef __native_client_codegen__
+ mono_nacl_fix_patches (code, ji);
+#endif
+
/* Emit code */
sprintf (start_symbol, "%s", name);
emit_section_change (acfg, ".text", 0);
emit_global (acfg, start_symbol, TRUE);
- emit_alignment (acfg, 16);
+ emit_alignment (acfg, AOT_FUNC_ALIGNMENT);
emit_label (acfg, start_symbol);
sprintf (symbol, "%snamed_%s", acfg->temp_prefix, name);
}
emit_global (acfg, symbol, TRUE);
- emit_alignment (acfg, 16);
+ emit_alignment (acfg, AOT_FUNC_ALIGNMENT);
emit_label (acfg, symbol);
acfg->trampoline_got_offset_base [ntype] = tramp_got_offset;
default:
g_assert_not_reached ();
}
+#ifdef __native_client_codegen__
+ /* align to avoid 32-byte boundary crossings */
+ emit_alignment (acfg, AOT_FUNC_ALIGNMENT);
+#endif
if (!acfg->trampoline_size [ntype]) {
g_assert (tramp_size);
opts->print_skipped_methods = TRUE;
} else if (str_begins_with (arg, "stats")) {
opts->stats = TRUE;
+ } else if (str_begins_with (arg, "mtriple=")) {
+ opts->mtriple = g_strdup (arg + strlen ("mtriple="));
} else {
fprintf (stderr, "AOT : Unknown argument '%s'.\n", arg);
exit (1);
return TRUE;
}
-static void
-add_generic_class (MonoAotCompile *acfg, MonoClass *klass);
-
/*
* compile_method:
*
switch (patch_info->type) {
case MONO_PATCH_INFO_GOT_OFFSET:
case MONO_PATCH_INFO_NONE:
+ case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
break;
case MONO_PATCH_INFO_IMAGE:
/* The assembly is stored in GOT slot 0 */
char *command, *opts;
int i;
MonoJumpInfo *patch_info;
- const char *llc_extra_args;
+ const char *llc_args;
/*
* When using LLVM, we let llvm emit the got since the LLVM IL needs to refer
#if !LLVM_CHECK_VERSION(2, 8)
/* LLVM 2.8 removed the -f flag ??? */
- llc_extra_args = "-f";
+ llc_args = "-f";
#else
- llc_extra_args = "";
+ llc_args = "";
#endif
- command = g_strdup_printf ("llc %s %s -relocation-model=pic -unwind-tables -o %s temp.opt.bc", LLC_TARGET_ARGS, llc_extra_args, acfg->tmpfname);
+
+ if (!acfg->aot_opts.mtriple) {
+ fprintf (stderr, "The mtriple= option is required when compiling using LLVM.\n");
+ exit (1);
+ }
+
+ command = g_strdup_printf ("llc -mtriple=%s %s %s -relocation-model=pic -unwind-tables -o %s temp.opt.bc", acfg->aot_opts.mtriple, llc_args, acfg->llc_args ? acfg->llc_args->str : "", acfg->tmpfname);
printf ("Executing llc: %s\n", command);
}
emit_section_change (acfg, ".text", 0);
+#ifdef __native_client_codegen__
+ emit_alignment (acfg, AOT_FUNC_ALIGNMENT);
+#endif
emit_global (acfg, symbol, TRUE);
emit_label (acfg, symbol);
sprintf (call_target, "%s", cfg->asm_symbol);
- arch_emit_unbox_trampoline (acfg, cfg->orig_method, cfg->generic_sharing_context, call_target);
+ arch_emit_unbox_trampoline (acfg, cfg->orig_method, call_target);
}
if (cfg->compile_llvm)
{
MonoMethodSignature *sig;
MonoClass *klass;
- int i;
+ int i, hindex;
int hashes_count;
guint32 *hashes_start, *hashes;
guint32 a, b, c;
+ MonoGenericInst *ginst = NULL;
/* Similar to the hash in mono_method_get_imt_slot () */
sig = mono_method_signature (method);
- hashes_count = sig->param_count + 5;
- hashes_start = malloc (hashes_count * sizeof (guint32));
+ if (method->is_inflated)
+ ginst = ((MonoMethodInflated*)method)->context.method_inst;
+
+ hashes_count = sig->param_count + 5 + (ginst ? ginst->type_argc : 0);
+ hashes_start = g_malloc0 (hashes_count * sizeof (guint32));
hashes = hashes_start;
/* Some wrappers are assigned to random classes */
hashes [2] = mono_metadata_str_hash (method->name);
hashes [3] = method->wrapper_type;
hashes [4] = mono_aot_type_hash (sig->ret);
+ hindex = 5;
for (i = 0; i < sig->param_count; i++) {
- hashes [5 + i] = mono_aot_type_hash (sig->params [i]);
+ hashes [hindex ++] = mono_aot_type_hash (sig->params [i]);
}
-
+ if (ginst) {
+ for (i = 0; i < ginst->type_argc; ++i)
+ hashes [hindex ++] = mono_aot_type_hash (ginst->type_argv [i]);
+ }
+ g_assert (hindex == hashes_count);
+
/* Setup internal state */
a = b = c = 0xdeadbeef + (((guint32)hashes_count)<<2);
* Emit a global symbol which can be passed by an embedding app to
* mono_aot_register_module ().
*/
-#if defined(__MACH__)
+#if defined(__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);
{
char symbol [128];
int i;
+ int gc_name_offset;
+ const char *gc_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);
sprintf (symbol, "mono_aot_file_info");
emit_section_change (acfg, ".data", 0);
emit_label (acfg, symbol);
emit_global (acfg, symbol, FALSE);
- /* The data emitted here must match MonoAotFileInfo in aot-runtime.c. */
+ /* The data emitted here must match MonoAotFileInfo. */
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, gc_name_offset);
for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
emit_int32 (acfg, acfg->num_trampolines [i]);
#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__)
+#define AS_OPTIONS "-arch i386 -W"
#else
#define AS_OPTIONS ""
#endif
+#ifdef __native_client_codegen__
+#define AS_NAME "nacl-as"
+#else
+#define AS_NAME "as"
+#endif
+
#ifndef LD_OPTIONS
#define LD_OPTIONS ""
#endif
} else {
objfile = g_strdup_printf ("%s.o", acfg->tmpfname);
}
- command = g_strdup_printf ("%sas %s %s -o %s", tool_prefix, AS_OPTIONS, acfg->tmpfname, objfile);
+ command = g_strdup_printf ("%s%s %s %s -o %s %s", tool_prefix, AS_NAME, AS_OPTIONS, acfg->as_args ? acfg->as_args->str : "", objfile, acfg->tmpfname);
printf ("Executing the native assembler: %s\n", command);
if (system (command) != 0) {
g_free (command);
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__)
+ 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);
#endif
fprintf (stderr, "The soft-debug AOT option requires the --debug option.\n");
return 1;
}
+ acfg->flags |= MONO_AOT_FILE_FLAG_DEBUG;
}
-#ifdef ENABLE_LLVM
- acfg->llvm = TRUE;
- acfg->aot_opts.asm_writer = TRUE;
- acfg->flags |= MONO_AOT_FILE_FLAG_WITH_LLVM;
-#endif
+ if (mono_use_llvm) {
+ acfg->llvm = TRUE;
+ acfg->aot_opts.asm_writer = TRUE;
+ acfg->flags |= MONO_AOT_FILE_FLAG_WITH_LLVM;
+ }
if (acfg->aot_opts.full_aot)
acfg->flags |= MONO_AOT_FILE_FLAG_FULL_AOT;
* symbols.
*/
acfg->llvm_label_prefix = "";
- if (acfg->llvm)
- acfg->llvm_label_prefix = LLVM_LABEL_PREFIX;
+
+ arch_process_target_triple (acfg);
acfg->method_index = 1;
acfg->plt_offset = 1;
#ifdef ENABLE_LLVM
- llvm_acfg = acfg;
- mono_llvm_create_aot_module (acfg->got_symbol_base);
+ if (acfg->llvm) {
+ llvm_acfg = acfg;
+ mono_llvm_create_aot_module (acfg->got_symbol_base);
+ }
#endif
/* GOT offset 0 is reserved for the address of the current assembly */
ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
ji->type = MONO_PATCH_INFO_MSCORLIB_GOT_ADDR;
get_got_offset (acfg, ji);
+
+ /* This is very common */
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
+ ji->type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
+ get_got_offset (acfg, ji);
}
TV_GETTIME (atv);
} else {
acfg->tmpfname = g_strdup ("temp.s");
}
- }
- emit_llvm_file (acfg);
+ emit_llvm_file (acfg);
+ }
#endif
if (!acfg->aot_opts.asm_only && !acfg->aot_opts.asm_writer && bin_writer_supported ()) {
MonoCompile *cfg = acfg->cfgs [i];
int method_index = get_method_index (acfg, cfg->orig_method);
- cfg->asm_symbol = g_strdup_printf ("%s%sm_%x", acfg->temp_prefix, LLVM_LABEL_PREFIX, method_index);
+ cfg->asm_symbol = g_strdup_printf ("%s%sm_%x", acfg->temp_prefix, acfg->llvm_label_prefix, method_index);
}
}