GPtrArray *extra_methods;
GPtrArray *image_table;
GPtrArray *globals;
- GList *method_order;
+ GPtrArray *method_order;
guint32 *plt_got_info_offsets;
guint32 got_offset, plt_offset, plt_got_offset_base;
guint32 final_got_size;
MonoClass **typespec_classes;
GString *llc_args;
GString *as_args;
- gboolean thumb_mixed, need_no_dead_strip;
+ gboolean thumb_mixed, need_no_dead_strip, need_pt_gnu_stack;
} MonoAotCompile;
typedef struct {
#endif
#endif
+#ifdef TARGET_POWERPC64
+#ifdef __mono_ilp32__
+#define AOT_TARGET_STR "POWERPC64 (mono ilp32)"
+#else
+#define AOT_TARGET_STR "POWERPC64 (!mono ilp32)"
+#endif
+#else
#ifdef TARGET_POWERPC
#ifdef __mono_ilp32__
#define AOT_TARGET_STR "POWERPC (mono ilp32)"
#define AOT_TARGET_STR "POWERPC (!mono ilp32)"
#endif
#endif
-
-#ifdef TARGET_POWERPC64
-#ifdef __mono_ilp32__
-#define AOT_TARGET_STR "POWERPC64 (mono ilp32)"
-#else
-#define AOT_TARGET_STR "POWERPC64 (!mono ilp32)"
-#endif
#endif
#ifdef TARGET_WIN32
acfg->llvm_label_prefix = "_";
acfg->need_no_dead_strip = TRUE;
#endif
+
+#if defined(__linux__) && !defined(TARGET_ARM)
+ acfg->need_pt_gnu_stack = TRUE;
+#endif
}
/*
g_assert_not_reached ();
}
break;
+ case MONO_WRAPPER_CASTCLASS:
+ if (!strcmp (method->name, "__castclass_with_cache")) {
+ encode_value (MONO_AOT_WRAPPER_CASTCLASS_WITH_CACHE, p, &p);
+ } else if (!strcmp (method->name, "__isinst_with_cache")) {
+ encode_value (MONO_AOT_WRAPPER_ISINST_WITH_CACHE, p, &p);
+ } else {
+ g_assert_not_reached ();
+ }
+ break;
default:
g_assert_not_reached ();
}
index = acfg->method_index;
add_method_with_index (acfg, method, index, extra);
- /* FIXME: Fix quadratic behavior */
- acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (index));
+ g_ptr_array_add (acfg->method_order, GUINT_TO_POINTER (index));
g_hash_table_insert (acfg->method_depth, method, GUINT_TO_POINTER (depth));
klass = mono_class_get (acfg->image, token);
if (klass)
add_method (acfg, mono_marshal_get_virtual_stelemref (mono_array_class_get (klass, 1)));
+ else
+ mono_loader_clear_error ();
}
+
+ /* castclass_with_check wrapper */
+ add_method (acfg, mono_marshal_get_castclass_with_cache ());
+ /* isinst_with_check wrapper */
+ add_method (acfg, mono_marshal_get_isinst_with_cache ());
}
/*
token = MONO_TOKEN_TYPE_DEF | (i + 1);
klass = mono_class_get (acfg->image, token);
+ if (!klass) {
+ mono_loader_clear_error ();
+ continue;
+ }
+
if (klass->delegate && klass != mono_defaults.delegate_class && klass != mono_defaults.multicastdelegate_class && !klass->generic_container) {
method = mono_get_delegate_invoke (klass);
token = MONO_TOKEN_TYPE_DEF | (i + 1);
klass = mono_class_get (acfg->image, token);
+ if (!klass) {
+ mono_loader_clear_error ();
+ continue;
+ }
+
if (klass->valuetype && !klass->generic_container && can_marshal_struct (klass)) {
add_method (acfg, mono_marshal_get_struct_to_ptr (klass));
add_method (acfg, mono_marshal_get_ptr_to_struct (klass));
add_generic_class_with_depth (acfg, klass, 0);
}
+static gboolean
+check_type_depth (MonoType *t, int depth)
+{
+ int i;
+
+ if (depth > 8)
+ return TRUE;
+
+ switch (t->type) {
+ case MONO_TYPE_GENERICINST: {
+ MonoGenericClass *gklass = t->data.generic_class;
+ MonoGenericInst *ginst = gklass->context.class_inst;
+
+ if (ginst) {
+ for (i = 0; i < ginst->type_argc; ++i) {
+ if (check_type_depth (ginst->type_argv [i], depth + 1))
+ return TRUE;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
/*
* add_generic_class:
*
if (!klass->generic_class && !klass->rank)
return;
+ if (check_type_depth (&klass->byval_arg, 0))
+ return;
+
iter = NULL;
while ((method = mono_class_get_methods (klass, &iter))) {
if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE))
* FIXME: Instances which are referenced by these methods are not added,
* for example Array.Resize<int> for List<int>.Add ().
*/
- add_extra_method_with_depth (acfg, method, depth);
+ add_extra_method_with_depth (acfg, method, depth + 1);
}
if (klass->delegate) {
token = MONO_TOKEN_TYPE_SPEC | (i + 1);
klass = mono_class_get (acfg->image, token);
- if (!klass || klass->rank)
+ if (!klass || klass->rank) {
+ mono_loader_clear_error ();
continue;
+ }
add_generic_class (acfg, klass, FALSE);
}
/* Add types of args/locals */
for (i = 0; i < acfg->methods->len; ++i) {
- int j;
+ int j, depth;
method = g_ptr_array_index (acfg->methods, i);
+ depth = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_depth, method));
+
sig = mono_method_signature (method);
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]), FALSE);
+ add_generic_class_with_depth (acfg, mono_class_from_mono_type (sig->params [j]), depth + 1);
}
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]), FALSE);
+ add_generic_class_with_depth (acfg, mono_class_from_mono_type (header->locals [j]), depth + 1);
}
}
break;
case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
+ case MONO_PATCH_INFO_CASTCLASS_CACHE:
break;
case MONO_PATCH_INFO_METHOD_REL:
encode_value ((gint)patch_info->data.offset, p, &p);
MonoMethod *method;
GList *l;
int pindex, buf_size, n_patches;
- guint8 *code;
GPtrArray *patches;
MonoJumpInfo *patch_info;
MonoMethodHeader *header;
guint32 first_got_offset;
method = cfg->orig_method;
- code = cfg->native_code;
header = mono_method_get_header (method);
method_index = get_method_index (acfg, method);
seq_points = cfg->seq_point_info;
- buf_size = header->num_clauses * 256 + debug_info_size + 1024 + (seq_points ? (seq_points->len * 64) : 0) + cfg->gc_map_size;
+ buf_size = header->num_clauses * 256 + debug_info_size + 2048 + (seq_points ? (seq_points->len * 64) : 0) + cfg->gc_map_size;
p = buf = g_malloc (buf_size);
#ifdef MONO_ARCH_HAVE_XP_UNWIND
gpointer iter = NULL;
if (!klass) {
+ mono_loader_clear_error ();
+
buf_size = 16;
p = buf = g_malloc (buf_size);
emit_trampolines (MonoAotCompile *acfg)
{
char symbol [256];
+ char end_symbol [256];
int i, tramp_got_offset;
MonoAotTrampoline ntype;
#ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
int tramp_type;
- guint8 *code;
#endif
if (!acfg->aot_opts.full_aot)
emit_trampoline (acfg, acfg->got_offset, info);
/* Emit the exception related code pieces */
- code = mono_arch_get_restore_context (&info, TRUE);
+ mono_arch_get_restore_context (&info, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
- code = mono_arch_get_call_filter (&info, TRUE);
+ mono_arch_get_call_filter (&info, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
- code = mono_arch_get_throw_exception (&info, TRUE);
+ mono_arch_get_throw_exception (&info, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
- code = mono_arch_get_rethrow_exception (&info, TRUE);
+ mono_arch_get_rethrow_exception (&info, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
- code = mono_arch_get_throw_corlib_exception (&info, TRUE);
+ mono_arch_get_throw_corlib_exception (&info, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
#if defined(MONO_ARCH_HAVE_GET_TRAMPOLINES)
int offset;
offset = MONO_RGCTX_SLOT_MAKE_RGCTX (i);
- code = mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE);
+ mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
offset = MONO_RGCTX_SLOT_MAKE_MRGCTX (i);
- code = mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE);
+ mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
}
g_assert_not_reached ();
}
+ sprintf (end_symbol, "%s_e", symbol);
+
+ if (acfg->aot_opts.write_symbols)
+ emit_local_symbol (acfg, symbol, end_symbol, TRUE);
+
emit_alignment (acfg, AOT_FUNC_ALIGNMENT);
emit_label (acfg, symbol);
acfg->trampoline_size [ntype] = tramp_size;
}
}
+
+ emit_label (acfg, end_symbol);
}
/* Reserve some entries at the end of the GOT for our use */
return TRUE;
else
return FALSE;
+ case MONO_WRAPPER_CASTCLASS:
+ if (!strcmp (method->name, "__castclass_with_cache"))
+ return TRUE;
+ else if (!strcmp (method->name, "__isinst_with_cache"))
+ return TRUE;
+ else
+ return FALSE;
default:
//printf ("Skip (wrapper call): %d -> %s\n", patch_info->type, mono_method_full_name (patch_info->data.method, TRUE));
return FALSE;
return;
}
if (cfg->exception_type != MONO_EXCEPTION_NONE) {
+ //printf ("E: %s\n", mono_method_full_name (method, TRUE));
/* Let the exception happen at runtime */
return;
}
int file_index, res, method_index, i;
char ver [256];
guint32 token;
- GList *unordered;
+ GList *unordered, *l;
+ gboolean found;
file_index = 0;
while (TRUE) {
token = mono_method_get_token (method);
method_index = mono_metadata_token_index (token) - 1;
- if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (method_index))) {
- acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (method_index));
+ found = FALSE;
+ for (i = 0; i < acfg->method_order->len; ++i) {
+ if (g_ptr_array_index (acfg->method_order, i) == GUINT_TO_POINTER (method_index)) {
+ found = TRUE;
+ break;
+ }
}
+ if (!found)
+ g_ptr_array_add (acfg->method_order, GUINT_TO_POINTER (method_index));
} else {
//printf ("No method found matching '%s'.\n", name);
}
/* Add missing methods */
unordered = NULL;
- for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
- if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (i)))
- unordered = g_list_prepend (unordered, GUINT_TO_POINTER (i));
+ for (method_index = 0; method_index < acfg->image->tables [MONO_TABLE_METHOD].rows; ++method_index) {
+ found = FALSE;
+ for (i = 0; i < acfg->method_order->len; ++i) {
+ if (g_ptr_array_index (acfg->method_order, i) == GUINT_TO_POINTER (method_index)) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found)
+ unordered = g_list_prepend (unordered, GUINT_TO_POINTER (method_index));
}
unordered = g_list_reverse (unordered);
- if (acfg->method_order)
- g_list_last (acfg->method_order)->next = unordered;
- else
- acfg->method_order = unordered;
+ for (l = unordered; l; l = l->next)
+ g_ptr_array_add (acfg->method_order, l->data);
}
/* Used by the LLVM backend */
* then removing tailcallelim + the global opts, and adding a second gvn.
*/
opts = g_strdup ("-instcombine -simplifycfg");
- opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -prune-eh -inline -functionattrs -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loopsimplify -domfrontier -loopsimplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loopsimplify -lcssa -iv-users -indvars -loop-deletion -loopsimplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify");
+ opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -prune-eh -inline -functionattrs -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);
printf ("Executing opt: %s\n", command);
static void
emit_code (MonoAotCompile *acfg)
{
- int i;
+ int oindex, i;
char symbol [256];
char end_symbol [256];
- GList *l;
#if defined(TARGET_POWERPC64)
sprintf (symbol, ".Lgot_addr");
emit_bytes (acfg, pad_buffer, kPaddingSize);
}
#endif
-
- for (l = acfg->method_order; l != NULL; l = l->next) {
+ for (oindex = 0; oindex < acfg->method_order->len; ++oindex) {
MonoCompile *cfg;
MonoMethod *method;
- i = GPOINTER_TO_UINT (l->data);
+ i = GPOINTER_TO_UINT (g_ptr_array_index (acfg->method_order, oindex));
cfg = acfg->cfgs [i];
/* Emit unbox trampoline */
if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
- char call_target [256];
-
if (!method->wrapper_type && !method->is_inflated) {
g_assert (method->token);
sprintf (symbol, "ut_%d", mono_metadata_token_index (method->token) - 1);
emit_label (acfg, symbol);
- sprintf (call_target, "%s", cfg->asm_symbol);
-
- arch_emit_unbox_trampoline (acfg, cfg, cfg->orig_method, call_target);
+ arch_emit_unbox_trampoline (acfg, cfg, cfg->orig_method, cfg->asm_symbol);
}
if (cfg->compile_llvm)
static void
emit_info (MonoAotCompile *acfg)
{
- int i;
+ int oindex, i;
char symbol [256];
- GList *l;
gint32 *offsets;
offsets = g_new0 (gint32, acfg->nmethods);
- for (l = acfg->method_order; l != NULL; l = l->next) {
- i = GPOINTER_TO_UINT (l->data);
+ for (oindex = 0; oindex < acfg->method_order->len; ++oindex) {
+ i = GPOINTER_TO_UINT (g_ptr_array_index (acfg->method_order, oindex));
if (acfg->cfgs [i]) {
emit_method_info (acfg, acfg->cfgs [i]);
return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
case MONO_TYPE_GENERICINST:
return ((hash << 5) - hash) ^ 0;
+ default:
+ return hash;
}
- return hash;
}
/*
for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
token = MONO_TOKEN_TYPE_DEF | (i + 1);
klass = mono_class_get (acfg->image, token);
- if (!klass)
+ if (!klass) {
+ mono_loader_clear_error ();
continue;
+ }
full_name = mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_FULL_NAME);
hash = mono_metadata_str_hash (full_name) % table_size;
g_free (full_name);
acfg->unwind_info_offsets = g_hash_table_new (NULL, NULL);
acfg->unwind_ops = g_ptr_array_new ();
acfg->method_label_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ acfg->method_order = g_ptr_array_new ();
InitializeCriticalSection (&acfg->mutex);
return acfg;
emit_mem_end (acfg);
+ if (acfg->need_pt_gnu_stack) {
+ /* This is required so the .so doesn't have an executable stack */
+ /* The bin writer already emits this */
+ if (!acfg->use_bin_writer)
+ fprintf (acfg->fp, "\n.section .note.GNU-stack,\"\",@progbits\n");
+ }
+
TV_GETTIME (btv);
acfg->stats.gen_time = TV_ELAPSED (atv, btv);