gboolean gas_line_numbers;
/* Whenever to emit an object file directly from llc */
gboolean llvm_owriter;
+ gboolean llvm_owriter_supported;
MonoImageWriter *w;
MonoDwarfWriter *dwarf;
FILE *fp;
static char*
get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache);
+static void
+add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean gsharedvt_in, gboolean gsharedvt_out);
+
static void
aot_printf (MonoAotCompile *acfg, const gchar *format, ...)
{
{
acfg->llc_args = g_string_new ("");
acfg->as_args = g_string_new ("");
+ acfg->llvm_owriter_supported = TRUE;
/*
* The prefix LLVM likes to put in front of symbol names on darwin.
#ifdef MONOTOUCH
acfg->global_symbols = TRUE;
#endif
+
+#ifdef TARGET_ANDROID
+ acfg->llvm_owriter_supported = FALSE;
+#endif
}
#ifdef TARGET_ARM64
/* Trampoline argument */
arm_ldrx (code, ARMREG_IP1, ARMREG_IP0, 0);
- /* Same as arch_emit_imt_thunk () */
+ /* Same as arch_emit_imt_trampoline () */
labels [0] = code;
arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 0);
arm_cmpx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
emit_code_bytes (acfg, buf, code - buf);
common_tramp_size = code - buf;
- acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = common_tramp_size;
+ acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT] = common_tramp_size;
arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
}
}
static void
-arm64_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
+arm64_emit_imt_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
{
guint8 buf [128];
guint8 *code, *labels [16];
acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_SPECIFIC] = 16;
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_IMT] = 72;
acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = 16;
/* Unwind info for specifc trampolines */
}
/*
- * arch_emit_imt_thunk:
+ * arch_emit_imt_trampoline:
*
- * Emit an IMT thunk usable in full-aot mode. The thunk uses 1 got slot which
+ * Emit an IMT trampoline usable in full-aot mode. The trampoline uses 1 got slot which
* points to an array of pointer pairs. The pairs of the form [key, ptr], where
* key is the IMT key, and ptr holds the address of a memory location holding
* the address to branch to if the IMT arg matches the key. The array is
* TRAMP_SIZE is set to the size of the emitted trampoline.
*/
static void
-arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
+arch_emit_imt_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
{
#if defined(TARGET_AMD64)
guint8 *buf, *code;
*tramp_size = code - buf + 4;
#elif defined(TARGET_ARM64)
- arm64_emit_imt_thunk (acfg, offset, tramp_size);
+ arm64_emit_imt_trampoline (acfg, offset, tramp_size);
#elif defined(TARGET_POWERPC)
guint8 buf [128];
guint8 *code, *labels [16];
* information.
*/
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
guint32 token;
g_assert (klass->type_token);
encode_value (MONO_AOT_TYPEREF_TYPESPEC_TOKEN, p, &p);
encode_value (token, p, &p);
} else {
- MonoClass *gclass = klass->generic_class->container_class;
- MonoGenericInst *inst = klass->generic_class->context.class_inst;
+ MonoClass *gclass = mono_class_get_generic_class (klass)->container_class;
+ MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
static int count = 0;
guint8 *p1 = p;
/*
* The encoding of generic instances is large so emit them only once.
*/
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
guint32 token;
g_assert (klass->type_token);
MonoMarshalType *info;
int i;
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+ if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
return FALSE;
info = mono_marshal_load_type_info (klass);
csig->params [1] = &mono_defaults.exception_class->byval_arg;
add_method (acfg, get_runtime_invoke_sig (csig));
- /* Assembly runtime-invoke (string, bool) [DoAssemblyResolve] */
- csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
+ /* Assembly runtime-invoke (string, Assembly, bool) [DoAssemblyResolve] */
+ csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
csig->hasthis = 1;
csig->ret = &(mono_class_load_from_name (
mono_defaults.corlib, "System.Reflection", "Assembly"))->byval_arg;
csig->params [0] = &mono_defaults.string_class->byval_arg;
- csig->params [1] = &mono_defaults.boolean_class->byval_arg;
+ csig->params [1] = &(mono_class_load_from_name (mono_defaults.corlib, "System.Reflection", "Assembly"))->byval_arg;
+ csig->params [2] = &mono_defaults.boolean_class->byval_arg;
add_method (acfg, get_runtime_invoke_sig (csig));
/* runtime-invoke used by finalizers */
(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
add_method (acfg, mono_marshal_get_native_wrapper (method, TRUE, TRUE));
}
+
+ if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
+ if (acfg->aot_opts.llvm_only) {
+ /* The wrappers have a different signature (hasthis is not set) so need to add this too */
+ add_gsharedvt_wrappers (acfg, mono_method_signature (method), FALSE, TRUE);
+ }
+ }
}
/* native-to-managed wrappers */
return TRUE;
if (klass->rank)
return has_type_vars (klass->element_class);
- if (klass->generic_class) {
- MonoGenericContext *context = &klass->generic_class->context;
+ if (mono_class_is_ginst (klass)) {
+ MonoGenericContext *context = &mono_class_get_generic_class (klass)->context;
if (context->class_inst) {
int i;
return opts->mode == MONO_AOT_MODE_FULL;
}
+static
+gboolean mono_aot_mode_is_hybrid (MonoAotOptions *opts)
+{
+ return opts->mode == MONO_AOT_MODE_HYBRID;
+}
+
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 (!mono_aot_mode_is_full (&acfg->aot_opts) && !force)
+ if (!mono_aot_mode_is_full (&acfg->aot_opts) && !mono_aot_mode_is_hybrid (&acfg->aot_opts) && !force)
return;
add_generic_class_with_depth (acfg, klass, 0, ref);
mono_class_init (klass);
- if (klass->generic_class && klass->generic_class->context.class_inst->is_open)
+ if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open)
return;
if (has_type_vars (klass))
return;
- if (!klass->generic_class && !klass->rank)
+ if (!mono_class_is_ginst (klass) && !klass->rank)
return;
if (mono_class_has_failure (klass))
* Use gsharedvt for generic collections with vtype arguments to avoid code blowup.
* Enable this only for some classes since gsharedvt might not support all methods.
*/
- if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && klass->generic_class && klass->generic_class->context.class_inst && is_vt_inst (klass->generic_class->context.class_inst) &&
+ if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst && is_vt_inst (mono_class_get_generic_class (klass)->context.class_inst) &&
(!strcmp (klass->name, "Dictionary`2") || !strcmp (klass->name, "List`1") || !strcmp (klass->name, "ReadOnlyCollection`1")))
use_gsharedvt = TRUE;
*/
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") &&
(!strcmp(klass->name, "ICollection`1") || !strcmp (klass->name, "IEnumerable`1") || !strcmp (klass->name, "IList`1") || !strcmp (klass->name, "IEnumerator`1") || !strcmp (klass->name, "IReadOnlyList`1"))) {
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoClass *array_class = mono_bounded_array_class_get (tclass, 1, FALSE);
gpointer iter;
char *name_prefix;
break;
}
g_assert (nclass);
- nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (klass->generic_class), &error);
+ nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (mono_class_get_generic_class (klass)), &error);
mono_error_assert_ok (&error); /* FIXME don't swallow the error */
add_generic_class (acfg, nclass, FALSE, "ICollection<T>");
}
/* Add an instance of GenericComparer<T> which is created dynamically by Comparer<T> */
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
MonoError error;
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoClass *icomparable, *gcomparer, *icomparable_inst;
MonoGenericContext ctx;
MonoType *args [16];
/* 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")) {
MonoError error;
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoClass *iface, *gcomparer, *iface_inst;
MonoGenericContext ctx;
MonoType *args [16];
/* Add an instance of EnumComparer<T> which is created dynamically by EqualityComparer<T> for enums */
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
MonoClass *enum_comparer;
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoGenericContext ctx;
MonoType *args [16];
/* Add an instance of ObjectComparer<T> which is created dynamically by Comparer<T> for enums */
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
MonoClass *comparer;
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoGenericContext ctx;
MonoType *args [16];
if (callee_cfg) {
gboolean direct_callable = TRUE;
- if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
+ if (direct_callable && !(!callee_cfg->has_got_slots && (mono_class_get_flags (callee_cfg->method->klass) & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
direct_callable = FALSE;
if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && (!method || method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED))
// FIXME: Maybe call the wrapper directly ?
* These include the following:
* - specific trampolines
* - static rgctx invoke trampolines
- * - imt thunks
+ * - imt trampolines
* These trampolines have the same code, they are parameterized by GOT
* slots.
* They are defined in this file, in the arch_... routines instead of
case MONO_AOT_TRAMP_STATIC_RGCTX:
sprintf (symbol, "static_rgctx_trampolines");
break;
- case MONO_AOT_TRAMP_IMT_THUNK:
- sprintf (symbol, "imt_thunks");
+ case MONO_AOT_TRAMP_IMT:
+ sprintf (symbol, "imt_trampolines");
break;
case MONO_AOT_TRAMP_GSHAREDVT_ARG:
sprintf (symbol, "gsharedvt_arg_trampolines");
arch_emit_static_rgctx_trampoline (acfg, tramp_got_offset, &tramp_size);
tramp_got_offset += 2;
break;
- case MONO_AOT_TRAMP_IMT_THUNK:
- arch_emit_imt_thunk (acfg, tramp_got_offset, &tramp_size);
+ case MONO_AOT_TRAMP_IMT:
+ arch_emit_imt_trampoline (acfg, tramp_got_offset, &tramp_size);
tramp_got_offset += 1;
break;
case MONO_AOT_TRAMP_GSHAREDVT_ARG:
if (!MONO_TYPE_ISSTRUCT (t))
return TRUE;
klass = mono_class_from_mono_type (t);
- orig_ctx = &klass->generic_class->context;
+ orig_ctx = &mono_class_get_generic_class (klass)->context;
inst = orig_ctx->class_inst;
if (inst) {
case MONO_PATCH_INFO_VTABLE: {
MonoClass *klass = patch_info->data.klass;
- if (klass->generic_class && !mini_class_is_generic_sharable (klass))
+ if (mono_class_is_ginst (klass) && !mini_class_is_generic_sharable (klass))
add_generic_class_with_depth (acfg, klass, depth + 5, "vtable");
break;
}
MonoClass *klass = patch_info->data.field->parent;
/* The .cctor needs to run at runtime. */
- if (klass->generic_class && !mono_generic_context_is_sharable_full (&klass->generic_class->context, FALSE, FALSE) && mono_class_get_cctor (klass))
+ if (mono_class_is_ginst (klass) && !mono_generic_context_is_sharable_full (&mono_class_get_generic_class (klass)->context, FALSE, FALSE) && mono_class_get_cctor (klass))
add_extra_method_with_depth (acfg, mono_class_get_cctor (klass), depth + 1);
break;
}
method = cfg->orig_method;
/* Emit unbox trampoline */
- if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype && !(acfg->aot_opts.llvm_only && cfg->compile_llvm)) {
+ 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);
int call_size;
if (acfg->cfgs [i]) {
- if (acfg->aot_opts.llvm_only && acfg->cfgs [i]->compile_llvm)
- /* Obtained by calling a generated function in the LLVM image */
- arch_emit_direct_call (acfg, symbol, FALSE, FALSE, NULL, &call_size);
- else
- arch_emit_direct_call (acfg, acfg->cfgs [i]->asm_symbol, FALSE, acfg->thumb_mixed && acfg->cfgs [i]->compile_llvm, NULL, &call_size);
+ arch_emit_direct_call (acfg, acfg->cfgs [i]->asm_symbol, FALSE, acfg->thumb_mixed && acfg->cfgs [i]->compile_llvm, NULL, &call_size);
} else {
arch_emit_direct_call (acfg, symbol, FALSE, FALSE, NULL, &call_size);
}
method = cfg->orig_method;
- if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype && !(acfg->aot_opts.llvm_only && cfg->compile_llvm)) {
+ 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 (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype && !(acfg->aot_opts.llvm_only && cfg->compile_llvm)) {
+ if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
#ifdef MONO_ARCH_AOT_SUPPORTED
int call_size;
sig = mono_method_signature (method);
- if (method->klass->generic_class)
- class_ginst = method->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (method->klass))
+ class_ginst = mono_class_get_generic_class (method->klass)->context.class_inst;
if (method->is_inflated)
ginst = ((MonoMethodInflated*)method)->context.method_inst;
if (!method->wrapper_type) {
char *full_name;
- if (klass->generic_class)
- full_name = mono_type_full_name (&klass->generic_class->container_class->byval_arg);
+ if (mono_class_is_ginst (klass))
+ full_name = mono_type_full_name (&mono_class_get_generic_class (klass)->container_class->byval_arg);
else
full_name = mono_type_full_name (&klass->byval_arg);
break;
}
- free (hashes_start);
+ g_free (hashes_start);
return c;
}
static void
generate_aotid (guint8* aotid)
{
- gpointer *rand_handle;
+ gpointer rand_handle;
MonoError error;
mono_rand_open ();
rand_handle = mono_rand_init (NULL, 0);
- mono_rand_try_get_bytes (rand_handle, aotid, 16, &error);
+ mono_rand_try_get_bytes (&rand_handle, aotid, 16, &error);
mono_error_assert_ok (&error);
mono_rand_close (rand_handle);
if (acfg->num_trampoline_got_entries) {
symbols [sindex ++] = "specific_trampolines";
symbols [sindex ++] = "static_rgctx_trampolines";
- symbols [sindex ++] = "imt_thunks";
+ symbols [sindex ++] = "imt_trampolines";
symbols [sindex ++] = "gsharedvt_arg_trampolines";
} else {
symbols [sindex ++] = NULL;
GPtrArray *frag;
int len, j;
GPtrArray *threads;
- HANDLE handle;
+ MonoThreadHandle *thread_handle;
gpointer *user_data;
MonoMethod **methods;
- MonoThreadParm tp;
methods_len = acfg->methods->len;
user_data [1] = acfg;
user_data [2] = frag;
- tp.priority = MONO_THREAD_PRIORITY_NORMAL;
- tp.stack_size = 0;
- tp.creation_flags = 0;
- handle = mono_threads_create_thread (compile_thread_main, (gpointer) user_data, &tp, NULL);
- g_ptr_array_add (threads, handle);
+ thread_handle = mono_threads_create_thread (compile_thread_main, (gpointer) user_data, NULL, NULL);
+ g_ptr_array_add (threads, thread_handle);
}
g_free (methods);
for (i = 0; i < threads->len; ++i) {
- WaitForSingleObjectEx (g_ptr_array_index (threads, i), INFINITE, FALSE);
+ mono_thread_info_wait_one_handle (g_ptr_array_index (threads, i), INFINITE, FALSE);
+ mono_threads_close_thread_handle (g_ptr_array_index (threads, i));
}
} else {
methods_len = 0;
wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
#else
// Default (linux)
- char *args = g_strdup_printf ("%s -shared -o %s %s %s %s", LD_OPTIONS,
- wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
- wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
-
- if (acfg->llvm) {
- command = g_strdup_printf ("clang++ %s", args);
+ if (acfg->aot_opts.tool_prefix) {
+ /* Cross compiling */
+ command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS,
+ wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
+ wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
} else {
- command = g_strdup_printf ("\"%sld\" %s", tool_prefix, args);
+ char *args = g_strdup_printf ("%s -shared -o %s %s %s %s", LD_OPTIONS,
+ wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
+ wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
+
+ if (acfg->llvm) {
+ command = g_strdup_printf ("clang++ %s", args);
+ } else {
+ command = g_strdup_printf ("\"%sld\" %s", tool_prefix, args);
+ }
+ g_free (args);
}
- g_free (args);
#endif
aot_printf (acfg, "Executing the native linker: %s\n", command);
//acfg->aot_opts.print_skipped_methods = TRUE;
#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
- if (opts & MONO_OPT_GSHAREDVT) {
+ if (acfg->opts & MONO_OPT_GSHAREDVT) {
aot_printerrf (acfg, "-O=gsharedvt not supported on this platform.\n");
return 1;
}
-#endif
-
-#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
- if (!acfg->aot_opts.llvm_only && (opts & MONO_OPT_GSHAREDVT)) {
- aot_printerrf (acfg, "-O=gsharedvt not supported on this platform.\n");
+ if (acfg->aot_opts.llvm_only) {
+ aot_printerrf (acfg, "--aot=llvmonly requires a runtime that supports gsharedvt.\n");
return 1;
}
+#else
+ if (acfg->aot_opts.llvm_only || mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts))
+ acfg->opts |= MONO_OPT_GSHAREDVT;
#endif
+#if !defined(ENABLE_LLVM)
if (acfg->aot_opts.llvm_only) {
-#ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
- aot_printerrf (acfg, "--aot=llvmonly requires a runtime that supports gsharedvt.\n");
- return 1;
-#endif
-#ifndef ENABLE_LLVM
aot_printerrf (acfg, "--aot=llvmonly requires a runtime compiled with llvm support.\n");
return 1;
-#endif
- }
-
-#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
- if (acfg->aot_opts.llvm_only || mono_aot_mode_is_full (&acfg->aot_opts)) {
- acfg->opts |= MONO_OPT_GSHAREDVT;
- opts |= MONO_OPT_GSHAREDVT;
}
#endif
- if (opts & MONO_OPT_GSHAREDVT)
+ if (acfg->opts & MONO_OPT_GSHAREDVT)
mono_set_generic_sharing_vt_supported (TRUE);
aot_printf (acfg, "Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
mini_llvm_init ();
if (acfg->aot_opts.asm_only && !acfg->aot_opts.llvm_outfile) {
- aot_printerrf (acfg, "Compiling with LLVM and the asm-only option requires the llvm-outputfile= option.");
+ aot_printerrf (acfg, "Compiling with LLVM and the asm-only option requires the llvm-outfile= option.\n");
return 1;
}
-
- /*
- * Emit all LLVM code into a separate assembly/object file and link with it
- * normally.
- */
- 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 (mono_aot_mode_is_full (&acfg->aot_opts))
#ifdef MONO_ARCH_GSHARED_SUPPORTED
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] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nimt_trampolines : 0;
+ acfg->num_trampolines [MONO_AOT_TRAMP_IMT] = 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] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.ngsharedvt_arg_trampolines : 0;
arch_init (acfg);
+ if (mono_use_llvm || acfg->aot_opts.llvm) {
+
+ /*
+ * Emit all LLVM code into a separate assembly/object file and link with it
+ * normally.
+ */
+ if (!acfg->aot_opts.asm_only && acfg->llvm_owriter_supported) {
+ 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->llvm && acfg->thumb_mixed)
acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_LLVM_THUMB);
if (acfg->aot_opts.llvm_only)
acfg->method_index = 1;
- if (mono_aot_mode_is_full (&acfg->aot_opts))
+ if (mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts))
mono_set_partial_sharing_supported (TRUE);
res = collect_methods (acfg);