gboolean soft_debug;
gboolean log_generics;
gboolean direct_pinvoke;
+ gboolean direct_icalls;
int nthreads;
int ntrampolines;
int nrgctx_trampolines;
MonoAotOptions aot_opts;
guint32 nmethods;
guint32 opts;
+ guint32 simd_opts;
MonoMemPool *mempool;
MonoAotStats stats;
int method_index;
{
#if defined(TARGET_X86) || defined(TARGET_AMD64)
/* Need to make sure this is exactly 5 bytes long */
- emit_byte (acfg, '\xe8');
- emit_symbol_diff (acfg, target, ".", -4);
+ if (FALSE && !acfg->use_bin_writer) {
+ img_writer_emit_unset_mode (acfg->w);
+ fprintf (acfg->fp, "call %s\n", target);
+ } else {
+ emit_byte (acfg, '\xe8');
+ emit_symbol_diff (acfg, target, ".", -4);
+ }
*call_size = 5;
#elif defined(TARGET_ARM)
if (acfg->use_bin_writer) {
#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);
if (info->subtype == WRAPPER_SUBTYPE_PTR_TO_STRUCTURE ||
info->subtype == WRAPPER_SUBTYPE_STRUCTURE_TO_PTR)
encode_klass_ref (acfg, method->klass, p, &p);
+ else if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER)
+ encode_method_ref (acfg, info->d.synchronized_inner.method, p, &p);
break;
}
case MONO_WRAPPER_MANAGED_TO_NATIVE: {
if (info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
strcpy ((char*)p, method->name);
p += strlen (method->name) + 1;
+ } else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_AOT) {
+ encode_method_ref (acfg, info->d.managed_to_native.method, p, &p);
} else {
g_assert (info->subtype == WRAPPER_SUBTYPE_NONE);
encode_method_ref (acfg, info->d.managed_to_native.method, p, &p);
/* delegate-invoke wrappers */
for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
MonoClass *klass;
+ MonoCustomAttrInfo *cattr;
token = MONO_TOKEN_TYPE_DEF | (i + 1);
klass = mono_class_get (acfg->image, token);
method = mono_class_get_method_from_name_flags (klass, "EndInvoke", -1, 0);
if (method)
add_method (acfg, mono_marshal_get_delegate_end_invoke (method));
+
+ cattr = mono_custom_attrs_from_class (klass);
+
+ if (cattr) {
+ int j;
+
+ for (j = 0; j < cattr->num_attrs; ++j)
+ if (cattr->attrs [j].ctor && !strcmp (cattr->attrs [j].ctor->klass->name, "MonoNativeFunctionWrapperAttribute"))
+ break;
+ if (j < cattr->num_attrs)
+ add_method (acfg, mono_marshal_get_native_func_wrapper_aot (klass));
+ }
}
}
add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, const char *ref)
{
MonoMethod *method;
+ MonoClassField *field;
gpointer iter;
if (!acfg->ginst_hash)
add_extra_method_with_depth (acfg, method, depth + 1);
}
+ iter = NULL;
+ while ((field = mono_class_get_fields (klass, &iter))) {
+ if (field->type->type == MONO_TYPE_GENERICINST)
+ add_generic_class_with_depth (acfg, mono_class_from_mono_type (field->type), depth + 1, "field");
+ }
+
if (klass->delegate) {
method = mono_get_delegate_invoke (klass);
}
}
+static void
+add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method)
+{
+ MonoMethodHeader *header;
+ MonoMethodSignature *sig;
+ int j, depth;
+
+ 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_with_depth (acfg, mono_class_from_mono_type (sig->params [j]), depth + 1, "arg");
+ }
+
+ 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_with_depth (acfg, mono_class_from_mono_type (header->locals [j]), depth + 1, "local");
+ }
+}
+
/*
* add_generic_instances:
*
int i;
guint32 token;
MonoMethod *method;
- MonoMethodHeader *header;
- MonoMethodSignature *sig;
MonoGenericContext *context;
for (i = 0; i < acfg->image->tables [MONO_TABLE_METHODSPEC].rows; ++i) {
/* Add types of args/locals */
for (i = 0; i < acfg->methods->len; ++i) {
- 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_with_depth (acfg, mono_class_from_mono_type (sig->params [j]), depth + 1, "arg");
- }
-
- 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_with_depth (acfg, mono_class_from_mono_type (header->locals [j]), depth + 1, "local");
- }
+ add_types_from_method_header (acfg, method);
}
if (acfg->image == mono_defaults.corlib) {
} else if ((patch_info->type == MONO_PATCH_INFO_ICALL_ADDR && patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
if (acfg->aot_opts.direct_pinvoke)
return TRUE;
+ } else if (patch_info->type == MONO_PATCH_INFO_ICALL_ADDR) {
+ if (acfg->aot_opts.direct_icalls)
+ return TRUE;
+ return FALSE;
}
return FALSE;
MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
guint32 im_cols [MONO_IMPLMAP_SIZE];
char *import;
- const char *prefix;
import = g_hash_table_lookup (acfg->method_to_pinvoke_import, method);
if (import != NULL)
if (!im_cols [MONO_IMPLMAP_SCOPE] || im_cols [MONO_IMPLMAP_SCOPE] > mr->rows)
return NULL;
-#if defined(__APPLE__)
- prefix = "_";
-#else
- prefix = "";
-#endif
-
- import = g_strdup_printf ("%s%s", prefix, mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]));
+ import = g_strdup_printf ("%s", mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]));
g_hash_table_insert (acfg->method_to_pinvoke_import, method, import);
direct_call = TRUE;
g_assert (strlen (callee_cfg->asm_symbol) < 1000);
sprintf (direct_call_target, "%s", callee_cfg->asm_symbol);
- patch_info->type = MONO_PATCH_INFO_NONE;
- acfg->stats.direct_calls ++;
}
acfg->stats.all_calls ++;
- } else if ((patch_info->type == MONO_PATCH_INFO_ICALL_ADDR) && (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
+ } else if (patch_info->type == MONO_PATCH_INFO_ICALL_ADDR) {
if (!got_only && is_direct_callable (acfg, method, patch_info)) {
- direct_call = TRUE;
- direct_pinvoke = get_pinvoke_import (acfg, patch_info->data.method);
- g_assert (strlen (direct_pinvoke) < 1000);
- sprintf (direct_call_target, "%s", direct_pinvoke);
- patch_info->type = MONO_PATCH_INFO_NONE;
- acfg->stats.direct_calls ++;
+ if (!(patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
+ direct_pinvoke = mono_lookup_icall_symbol (patch_info->data.method);
+ else
+ direct_pinvoke = get_pinvoke_import (acfg, patch_info->data.method);
+ if (direct_pinvoke) {
+ const char*prefix;
+#if defined(__APPLE__)
+ prefix = "_";
+#else
+ prefix = "";
+#endif
+ direct_call = TRUE;
+ g_assert (strlen (direct_pinvoke) < 1000);
+ sprintf (direct_call_target, "%s%s", prefix, direct_pinvoke);
+ }
}
}
+ if (direct_call) {
+ patch_info->type = MONO_PATCH_INFO_NONE;
+ acfg->stats.direct_calls ++;
+ }
+
if (!got_only && !direct_call) {
MonoPltEntry *plt_entry = get_plt_entry (acfg, patch_info);
if (plt_entry) {
if (ji && is_direct_callable (acfg, NULL, ji) && !acfg->use_bin_writer) {
MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, ji->data.method);
- if (acfg->thumb_mixed && !callee_cfg->compile_llvm) {
- /* LLVM calls the PLT entries using bl, so emit a stub */
- fprintf (acfg->fp, "\n.thumb_func\n");
- emit_label (acfg, plt_entry->llvm_symbol);
- fprintf (acfg->fp, "bx pc\n");
- fprintf (acfg->fp, "nop\n");
- fprintf (acfg->fp, ".arm\n");
- fprintf (acfg->fp, "b %s\n", callee_cfg->asm_symbol);
- } else {
- fprintf (acfg->fp, "\n.set %s, %s\n", plt_entry->llvm_symbol, callee_cfg->asm_symbol);
+ if (callee_cfg) {
+ if (acfg->thumb_mixed && !callee_cfg->compile_llvm) {
+ /* LLVM calls the PLT entries using bl, so emit a stub */
+ fprintf (acfg->fp, "\n.thumb_func\n");
+ emit_label (acfg, plt_entry->llvm_symbol);
+ fprintf (acfg->fp, "bx pc\n");
+ fprintf (acfg->fp, "nop\n");
+ fprintf (acfg->fp, ".arm\n");
+ fprintf (acfg->fp, "b %s\n", callee_cfg->asm_symbol);
+ } else {
+ fprintf (acfg->fp, "\n.set %s, %s\n", plt_entry->llvm_symbol, callee_cfg->asm_symbol);
+ }
+ continue;
}
- continue;
}
}
opts->soft_debug = TRUE;
} else if (str_begins_with (arg, "direct-pinvoke")) {
opts->direct_pinvoke = TRUE;
+ } else if (str_begins_with (arg, "direct-icalls")) {
+ opts->direct_icalls = TRUE;
} else if (str_begins_with (arg, "print-skipped")) {
opts->print_skipped_methods = TRUE;
} else if (str_begins_with (arg, "stats")) {
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);
+ add_types_from_method_header (acfg, m);
}
}
add_generic_class_with_depth (acfg, m->klass, depth + 5, "method");
emit_int32 (acfg, acfg->nmethods);
emit_int32 (acfg, acfg->flags);
emit_int32 (acfg, acfg->opts);
+ emit_int32 (acfg, acfg->simd_opts);
emit_int32 (acfg, gc_name_offset);
for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
}
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);
rename (tmp_outfile_name, outfile_name);
+#if defined(__APPLE__)
+ 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);
acfg->globals = g_ptr_array_new ();
acfg->image = image;
acfg->opts = opts;
+ /* TODO: Write out set of SIMD instructions used, rather than just those available */
+ acfg->simd_opts = mono_arch_cpu_enumerate_simd_versions ();
acfg->mempool = mono_mempool_new ();
acfg->extra_methods = g_ptr_array_new ();
acfg->unwind_info_offsets = g_hash_table_new (NULL, NULL);