#define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
-typedef struct MonoAotMethod {
- MonoJitInfo *info;
- MonoJumpInfo *patch_info;
- MonoDomain *domain;
-} MonoAotMethod;
-
typedef struct MonoAotModule {
char *aot_name;
/* Optimization flags used to compile the module */
guint32 opts;
- /* Maps MonoMethods to MonoAotMethodInfos */
- GHashTable *methods;
/* Pointer to the Global Offset Table */
gpointer *got;
guint32 got_size;
guint32 *code_offsets;
guint8 *method_infos;
guint32 *method_info_offsets;
+ guint8 *class_infos;
+ guint32 *class_info_offsets;
} MonoAotModule;
+typedef struct MonoAotOptions {
+ char *outfile;
+ gboolean save_temps;
+ gboolean write_symbols;
+} MonoAotOptions;
+
typedef struct MonoAotCompile {
+ MonoImage *image;
FILE *fp;
- GHashTable *ref_hash;
GHashTable *icall_hash;
GPtrArray *icall_table;
GHashTable *image_hash;
GPtrArray *image_table;
guint32 got_offset;
guint32 *method_got_offsets;
+ MonoAotOptions aot_opts;
} MonoAotCompile;
-typedef struct MonoAotOptions {
- char *outfile;
-} MonoAotOptions;
-
static GHashTable *aot_modules;
static CRITICAL_SECTION aot_mutex;
return mono_class_get_field (klass, token);
}
+static inline MonoImage*
+decode_method_ref (MonoAotModule *module, guint32 *token, char *buf, char **endbuf)
+{
+ guint32 image_index, value;
+ MonoImage *image;
+
+ value = decode_value (buf, &buf);
+ *endbuf = buf;
+ image_index = value >> 24;
+ *token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
+
+ image = load_image (module, image_index);
+ if (!image)
+ return NULL;
+ else
+ return image;
+}
+
G_GNUC_UNUSED
static void
make_writable (guint8* addr, guint32 len)
info = g_new0 (MonoAotModule, 1);
info->aot_name = aot_name;
- info->methods = g_hash_table_new (NULL, NULL);
#ifdef MONO_ARCH_HAVE_PIC_AOT
info->got = got;
info->got_size = *got_size_ptr;
g_module_symbol (assembly->aot_module, "methods", (gpointer*)&info->code);
g_module_symbol (assembly->aot_module, "method_info_offsets", (gpointer*)&info->method_info_offsets);
g_module_symbol (assembly->aot_module, "method_infos", (gpointer*)&info->method_infos);
+ g_module_symbol (assembly->aot_module, "class_infos", (gpointer*)&info->class_infos);
+ g_module_symbol (assembly->aot_module, "class_info_offsets", (gpointer*)&info->class_info_offsets);
EnterCriticalSection (&aot_mutex);
g_hash_table_insert (aot_modules, assembly, info);
if (getenv ("MONO_AOT_CACHE"))
use_aot_cache = TRUE;
}
+
+static gboolean
+decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, char *buf, char **endbuf)
+{
+ guint32 flags;
+
+ info->vtable_size = decode_value (buf, &buf);
+ flags = decode_value (buf, &buf);
+ info->ghcimpl = (flags >> 0) & 0x1;
+ info->has_finalize = (flags >> 1) & 0x1;
+ info->has_cctor = (flags >> 2) & 0x1;
+ if (info->has_cctor) {
+ MonoImage *cctor_image = decode_method_ref (module, &info->cctor_token, buf, &buf);
+ if (!cctor_image)
+ return FALSE;
+ }
+ if (info->has_finalize) {
+ info->finalize_image = decode_method_ref (module, &info->finalize_token, buf, &buf);
+ if (!info->finalize_image)
+ return FALSE;
+ }
+
+ *endbuf = buf;
+
+ return TRUE;
+}
+
+gboolean
+mono_aot_init_vtable (MonoVTable *vtable)
+{
+ int i;
+ MonoAotModule *aot_module;
+ MonoClass *klass = vtable->klass;
+ guint8 *info;
+ MonoCachedClassInfo class_info;
+ char *p;
+ gboolean err;
+
+ if (MONO_CLASS_IS_INTERFACE (klass) || klass->rank || !klass->image->assembly->aot_module)
+ return FALSE;
+
+ EnterCriticalSection (&aot_mutex);
+
+ aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, klass->image->assembly);
+ if (!aot_module) {
+ LeaveCriticalSection (&aot_mutex);
+ return FALSE;
+ }
+
+ info = &aot_module->class_infos [aot_module->class_info_offsets [mono_metadata_token_index (klass->type_token) - 1]];
+ p = (char*)info;
+
+ err = decode_cached_class_info (aot_module, &class_info, p, &p);
+ if (!err) {
+ LeaveCriticalSection (&aot_mutex);
+ return FALSE;
+ }
+
+ //printf ("VT0: %s.%s %d\n", klass->name_space, klass->name, vtable_size);
+ for (i = 0; i < class_info.vtable_size; ++i) {
+ guint32 image_index, token, value;
+ MonoImage *image;
+ MonoMethod *m;
+
+ vtable->vtable [i] = 0;
+
+ value = decode_value (p, &p);
+ if (!value)
+ continue;
+
+ image_index = value >> 24;
+ token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
+
+ image = load_image (aot_module, image_index);
+ if (!image) {
+ LeaveCriticalSection (&aot_mutex);
+ return FALSE;
+ }
+
+#ifdef MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN
+ vtable->vtable [i] = mono_create_jit_trampoline_from_token (image, token);
+#else
+ m = mono_get_method (image, token, NULL);
+ g_assert (m);
+
+ //printf ("M: %d %p %s\n", i, &(vtable->vtable [i]), mono_method_full_name (m, TRUE));
+ vtable->vtable [i] = mono_create_jit_trampoline (m);
+#endif
+ }
+
+ LeaveCriticalSection (&aot_mutex);
+
+ return TRUE;
+}
+
+gboolean
+mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
+{
+ MonoAotModule *aot_module;
+ char *p;
+ gboolean err;
+
+ if (MONO_CLASS_IS_INTERFACE (klass) || klass->rank || !klass->image->assembly->aot_module)
+ return FALSE;
+
+ EnterCriticalSection (&aot_mutex);
+
+ aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, klass->image->assembly);
+ if (!aot_module) {
+ LeaveCriticalSection (&aot_mutex);
+ return FALSE;
+ }
+
+ p = &aot_module->class_infos [aot_module->class_info_offsets [mono_metadata_token_index (klass->type_token) - 1]];
+
+ err = decode_cached_class_info (aot_module, res, p, &p);
+ if (!err) {
+ LeaveCriticalSection (&aot_mutex);
+ return FALSE;
+ }
+
+ LeaveCriticalSection (&aot_mutex);
+
+ return TRUE;
+}
static MonoJitInfo *
mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
guint8 *code = NULL;
guint8 *info;
MonoAotModule *aot_module;
- MonoAotMethod *minfo;
- MonoJitInfo *jinfo;
- MonoMethodHeader *header;
if (!module)
return NULL;
(method->flags & METHOD_ATTRIBUTE_ABSTRACT))
return NULL;
- header = mono_method_get_header (method);
-
aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, ass);
g_assert (klass->inited);
/* Non shared AOT code can't be used in other appdomains */
return NULL;
- minfo = g_hash_table_lookup (aot_module->methods, method);
- /* Can't use code from non-root domains since they can be unloaded */
- if (minfo && (minfo->domain == mono_get_root_domain ())) {
- /* This method was already loaded in another appdomain */
-
- /* Duplicate jinfo */
- jinfo = mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo));
- memcpy (jinfo, minfo->info, sizeof (MonoJitInfo));
- if (jinfo->clauses) {
- jinfo->clauses =
- mono_mempool_alloc0 (domain->mp, sizeof (MonoJitExceptionInfo) * header->num_clauses);
- memcpy (jinfo->clauses, minfo->info->clauses, sizeof (MonoJitExceptionInfo) * header->num_clauses);
- }
-
- return jinfo;
- }
-
if (aot_module->out_of_date)
return NULL;
if (aot_module->code_offsets [mono_metadata_token_index (method->token) - 1] == 0xffffffff) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT NOT FOUND: %s.\n", mono_method_full_name (method, TRUE));
+ if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
+ char *full_name = mono_method_full_name (method, TRUE);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT NOT FOUND: %s.\n", full_name);
+ g_free (full_name);
+ }
return NULL;
}
MonoClass *klass = method->klass;
MonoJumpInfo *patch_info = NULL;
guint code_len, used_int_regs, used_strings;
- MonoAotMethod *minfo;
MonoJitInfo *jinfo;
- MonoMethodHeader *header = mono_method_get_header (method);
MonoMemPool *mp;
GPtrArray *patches;
int i, pindex, got_index;
gboolean non_got_patches, keep_patches = TRUE;
+ gboolean has_clauses;
char *p;
- minfo = g_new0 (MonoAotMethod, 1);
-
- minfo->domain = domain;
- jinfo = mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo));
-
p = (char*)info;
code_len = decode_value (p, &p);
used_int_regs = decode_value (p, &p);
code = code2;
}
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND AOT compiled code for %s %p - %p %p\n", mono_method_full_name (method, TRUE), code, code + code_len, info);
+ if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
+ char *full_name = mono_method_full_name (method, TRUE);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND AOT compiled code for %s %p - %p %p\n", full_name, code, code + code_len, info);
+ g_free (full_name);
+ }
/* Exception table */
- if (header->num_clauses) {
- jinfo->clauses =
- mono_mempool_alloc0 (domain->mp, sizeof (MonoJitExceptionInfo) * header->num_clauses);
+ has_clauses = decode_value (p, &p);
+ if (has_clauses) {
+ MonoMethodHeader *header = mono_method_get_header (method);
+ jinfo =
+ mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo) + (sizeof (MonoJitExceptionInfo) * header->num_clauses));
jinfo->num_clauses = header->num_clauses;
- jinfo->exvar_offset = decode_value (p, &p);
-
for (i = 0; i < header->num_clauses; ++i) {
MonoExceptionClause *ec = &header->clauses [i];
MonoJitExceptionInfo *ei = &jinfo->clauses [i];
ei->flags = ec->flags;
+ ei->exvar_offset = decode_value (p, &p);
+
if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
ei->data.filter = code + decode_value (p, &p);
else
ei->handler_start = code + decode_value (p, &p);
}
}
+ else
+ jinfo = mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo));
if (aot_module->opts & MONO_OPT_SHARED)
used_strings = decode_value (p, &p);
}
case MONO_WRAPPER_LDFLD:
case MONO_WRAPPER_STFLD:
+ case MONO_WRAPPER_LDFLD_REMOTE:
+ case MONO_WRAPPER_STFLD_REMOTE:
case MONO_WRAPPER_ISINST: {
MonoClass *klass = decode_klass_info (aot_module, p, &p);
if (!klass)
ji->data.method = mono_marshal_get_ldfld_wrapper (&klass->byval_arg);
else if (wrapper_type == MONO_WRAPPER_STFLD)
ji->data.method = mono_marshal_get_stfld_wrapper (&klass->byval_arg);
+ else if (wrapper_type == MONO_WRAPPER_LDFLD_REMOTE)
+ ji->data.method = mono_marshal_get_ldfld_remote_wrapper (klass);
else
ji->data.method = mono_marshal_get_isinst (klass);
break;
case MONO_PATCH_INFO_INTERNAL_METHOD:
ji->data.name = aot_module->icall_table [decode_value (p, &p)];
g_assert (ji->data.name);
- //printf ("A: %s.\n", ji->data.name);
break;
case MONO_PATCH_INFO_SWITCH:
ji->data.table = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoBBTable));
for (i = 0; i < ji->data.table->table_size; i++)
table [i] = (gpointer)(gssize)decode_value (p, &p);
break;
- case MONO_PATCH_INFO_R4:
- ji->data.target = mono_mempool_alloc0 (mp, sizeof (float));
+ case MONO_PATCH_INFO_R4: {
guint32 val;
+ ji->data.target = mono_mempool_alloc0 (mp, sizeof (float));
val = decode_value (p, &p);
*(float*)ji->data.target = *(float*)&val;
break;
+ }
case MONO_PATCH_INFO_R8: {
- ji->data.target = mono_mempool_alloc0 (mp, sizeof (double));
guint32 val [2];
+ ji->data.target = mono_mempool_alloc0 (mp, sizeof (double));
+
val [0] = decode_value (p, &p);
val [1] = decode_value (p, &p);
*(double*)ji->data.target = *(double*)val;
goto cleanup;
ji->data.token = mono_jump_info_token_new (mp, image, MONO_TOKEN_STRING + decode_value (p, &p));
break;
+ case MONO_PATCH_INFO_DECLSEC:
case MONO_PATCH_INFO_LDTOKEN:
case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
image = load_image (aot_module, decode_value (p, &p));
jinfo->domain_neutral = (aot_module->opts & MONO_OPT_SHARED) != 0;
#endif
- minfo->info = jinfo;
- g_hash_table_insert (aot_module->methods, method, minfo);
-
return jinfo;
}
{
#if defined(__ppc__) && defined(__MACH__)
// mach-o always uses a '_' prefix.
- fprintf (fp, ".globl _%s\n", name);
+ fprintf (fp, "\t.globl _%s\n", name);
#else
- fprintf (fp, ".globl %s\n", name);
+ fprintf (fp, "\t.globl %s\n", name);
#endif
emit_symbol_type (fp, name, func);
*endbuf = buf;
}
+static void
+encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, char *buf, char **endbuf)
+{
+ guint32 image_index = get_image_index (acfg, method->klass->image);
+ guint32 token = method->token;
+ g_assert (image_index < 256);
+ g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
+
+ encode_value ((image_index << 24) + (mono_metadata_token_index (token)), buf, &buf);
+ *endbuf = buf;
+}
+
static gint
compare_patches (gconstpointer a, gconstpointer b)
{
{
MonoMethod *method;
FILE *tmpfp;
- int i, j, pindex;
+ int i, j, pindex, byte_index;
guint8 *code, *mname, *mname_p;
int func_alignment = 16;
GPtrArray *patches;
code = cfg->native_code;
header = mono_method_get_header (method);
- emit_section_change (tmpfp, ".text", 0);
-
/* Make the labels local */
mname = g_strdup_printf (".Lm_%x", mono_metadata_token_index (method->token));
mname_p = g_strdup_printf ("%s_p", mname);
emit_alignment(tmpfp, func_alignment);
emit_label(tmpfp, mname);
+ if (acfg->aot_opts.write_symbols)
+ emit_global (tmpfp, mname, TRUE);
if (cfg->verbose_level > 0)
- g_print ("Emitted as %s\n", mname);
+ g_print ("Method %s emitted as %s\n", mono_method_full_name (method, TRUE), mname);
/* Sort relocations */
patches = g_ptr_array_new ();
#ifdef MONO_ARCH_HAVE_PIC_AOT
acfg->method_got_offsets [mono_metadata_token_index (method->token)] = acfg->got_offset;
+ byte_index = 0;
for (i = 0; i < cfg->code_len; i++) {
patch_info = NULL;
for (pindex = 0; pindex < patches->len; ++pindex) {
break;
case MONO_PATCH_INFO_GOT_OFFSET: {
guint32 offset = mono_arch_get_patch_offset (code + i);
+ fprintf (tmpfp, "\n.byte ");
for (j = 0; j < offset; ++j)
- fprintf (tmpfp, ".byte 0x%x\n", (unsigned int) code [i + j]);
- fprintf (tmpfp, ".int got - . + %d\n", offset);
+ fprintf (tmpfp, "%s0x%x", (j == 0) ? "" : ",", (unsigned int) code [i + j]);
+ fprintf (tmpfp, "\n.int got - . + %d", offset);
i += offset + 4 - 1;
skip = TRUE;
if (!is_got_patch (patch_info->type))
break;
+ fprintf (tmpfp, "\n.byte ");
for (j = 0; j < mono_arch_get_patch_offset (code + i); ++j)
- fprintf (tmpfp, ".byte 0x%x\n", (unsigned int) code [i + j]);
+ fprintf (tmpfp, "%s0x%x", (j == 0) ? "" : ",", (unsigned int) code [i + j]);
#ifdef __x86_64__
- fprintf (tmpfp, ".int got - . + %d\n", (unsigned int) ((acfg->got_offset * sizeof (gpointer)) - 4));
+ fprintf (tmpfp, "\n.int got - . + %d", (unsigned int) ((acfg->got_offset * sizeof (gpointer)) - 4));
#elif defined(__i386__)
- fprintf (tmpfp, ".int %d\n", (unsigned int) ((acfg->got_offset * sizeof (gpointer))));
+ fprintf (tmpfp, "\n.int %d\n", (unsigned int) ((acfg->got_offset * sizeof (gpointer))));
#endif
acfg->got_offset ++;
}
}
- if (!skip)
- fprintf (tmpfp, ".byte 0x%x\n", (unsigned int) code [i]);
+ if (!skip) {
+ if (byte_index == 0)
+ fprintf (tmpfp, "\n.byte ");
+ fprintf (tmpfp, "%s0x%x", (byte_index == 0) ? "" : ",", (unsigned int) code [i]);
+ byte_index = (byte_index + 1) % 32;
+ }
+ else
+ byte_index = 0;
}
#else
for (i = 0; i < cfg->code_len; i++) {
fprintf (tmpfp, ".byte 0x%x\n", (unsigned int) code [i]);
}
#endif
+ fprintf (tmpfp, "\n");
}
static void
code = cfg->native_code;
header = mono_method_get_header (method);
- emit_section_change (tmpfp, ".text", 0);
-
/* Make the labels local */
mname = g_strdup_printf (".Lm_%x", mono_metadata_token_index (method->token));
mname_p = g_strdup_printf ("%s_p", mname);
encode_value (cfg->used_int_regs, p, &p);
/* Exception table */
+ encode_value (header->num_clauses ? 1 : 0, p, &p);
if (header->num_clauses) {
MonoJitInfo *jinfo = cfg->jit_info;
- encode_value (jinfo->exvar_offset, p, &p);
-
for (k = 0; k < header->num_clauses; ++k) {
MonoJitExceptionInfo *ei = &jinfo->clauses [k];
+ encode_value (ei->exvar_offset, p, &p);
+
if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
}
case MONO_PATCH_INFO_METHODCONST:
case MONO_PATCH_INFO_METHOD:
- case MONO_PATCH_INFO_METHOD_JUMP: {
- guint32 image_index = get_image_index (acfg, patch_info->data.method->klass->image);
- guint32 token = patch_info->data.method->token;
- g_assert (image_index < 256);
- g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
-
- encode_value ((image_index << 24) + (mono_metadata_token_index (token)), p, &p);
+ case MONO_PATCH_INFO_METHOD_JUMP:
+ encode_method_ref (acfg, patch_info->data.method, p, &p);
break;
- }
case MONO_PATCH_INFO_INTERNAL_METHOD: {
guint32 icall_index;
encode_value (patch_info->data.token->token - MONO_TOKEN_STRING, p, &p);
break;
}
+ case MONO_PATCH_INFO_DECLSEC:
case MONO_PATCH_INFO_LDTOKEN:
case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
encode_value (get_image_index (acfg, patch_info->data.token->image), p, &p);
case MONO_WRAPPER_PROXY_ISINST:
case MONO_WRAPPER_LDFLD:
case MONO_WRAPPER_STFLD:
+ case MONO_WRAPPER_LDFLD_REMOTE:
+ case MONO_WRAPPER_STFLD_REMOTE:
case MONO_WRAPPER_ISINST: {
MonoClass *proxy_class = (MonoClass*)mono_marshal_method_from_wrapper (patch_info->data.method);
encode_klass_info (acfg, proxy_class, p, &p);
/* Emit method info */
- emit_section_change (tmpfp, ".text", 1);
emit_label (tmpfp, mname_p);
g_assert (p - buf < buf_size);
- for (i = 0; i < p - buf; ++i)
- fprintf (tmpfp, ".byte %d\n", (unsigned int) buf [i]);
+ for (i = 0; i < p - buf; ++i) {
+ if ((i % 32) == 0)
+ fprintf (tmpfp, "\n.byte ");
+ fprintf (tmpfp, "%s%d", ((i % 32) == 0) ? "" : ",", (unsigned int) buf [i]);
+ }
+ fprintf (tmpfp, "\n");
g_free (buf);
g_free (mname);
g_free (mname_p);
}
+static void
+emit_klass_info (MonoAotCompile *acfg, guint32 token)
+{
+ MonoClass *klass = mono_class_get (acfg->image, token);
+ char *p, *buf;
+ int i, buf_size;
+ char *label;
+ FILE *tmpfp = acfg->fp;
+
+ buf_size = 10240;
+ p = buf = g_malloc (buf_size);
+
+ g_assert (klass);
+
+ mono_class_init (klass);
+
+ /*
+ * Emit all the information which is required for creating vtables so
+ * the runtime does not need to create the MonoMethod structures which
+ * take up a lot of space.
+ */
+
+ if (!MONO_CLASS_IS_INTERFACE (klass)) {
+ encode_value (klass->vtable_size, p, &p);
+ encode_value ((klass->has_cctor << 2) | (klass->has_finalize << 1) | klass->ghcimpl, p, &p);
+ if (klass->has_cctor)
+ encode_method_ref (acfg, mono_class_get_cctor (klass), p, &p);
+ if (klass->has_finalize)
+ encode_method_ref (acfg, mono_class_get_finalizer (klass), p, &p);
+
+ for (i = 0; i < klass->vtable_size; ++i) {
+ MonoMethod *cm = klass->vtable [i];
+
+ if (cm)
+ encode_method_ref (acfg, cm, p, &p);
+ else
+ encode_value (0, p, &p);
+ }
+ }
+
+ /* Emit the info */
+ label = g_strdup_printf (".LK_I_%x", token - MONO_TOKEN_TYPE_DEF - 1);
+ emit_label (tmpfp, label);
+
+ g_assert (p - buf < buf_size);
+ for (i = 0; i < p - buf; ++i) {
+ if ((i % 32) == 0)
+ fprintf (tmpfp, "\n.byte ");
+ fprintf (tmpfp, "%s%d", ((i % 32) == 0) ? "" : ",", (unsigned int) buf [i]);
+ }
+ fprintf (tmpfp, "\n");
+ g_free (buf);
+}
+
static gboolean
str_begins_with (const char *str1, const char *str2)
{
if (str_begins_with (arg, "outfile=")) {
opts->outfile = g_strdup (arg + strlen ("outfile="));
- }
- else {
+ } else if (str_begins_with (arg, "save-temps")) {
+ opts->save_temps = TRUE;
+ } else if (str_begins_with (arg, "write-symbols")) {
+ opts->write_symbols = TRUE;
+ } else {
fprintf (stderr, "AOT : Unknown argument '%s'.\n", arg);
exit (1);
}
int i;
guint8 *symbol;
int ccount = 0, mcount = 0, lmfcount = 0, abscount = 0, wrappercount = 0, ocount = 0;
- GHashTable *ref_hash;
MonoAotCompile *acfg;
MonoCompile **cfgs;
- MonoAotOptions aot_opts;
char *outfile_name, *tmp_outfile_name;
printf ("Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
- mono_aot_parse_options (aot_options, &aot_opts);
-
- i = g_file_open_tmp ("mono_aot_XXXXXX", &tmpfname, NULL);
- tmpfp = fdopen (i, "w+");
- g_assert (tmpfp);
-
- ref_hash = g_hash_table_new (NULL, NULL);
-
acfg = g_new0 (MonoAotCompile, 1);
- acfg->fp = tmpfp;
- acfg->ref_hash = ref_hash;
acfg->icall_hash = g_hash_table_new (NULL, NULL);
acfg->icall_table = g_ptr_array_new ();
acfg->image_hash = g_hash_table_new (NULL, NULL);
acfg->image_table = g_ptr_array_new ();
+ acfg->image = image;
+
+ mono_aot_parse_options (aot_options, &acfg->aot_opts);
+
+ i = g_file_open_tmp ("mono_aot_XXXXXX", &tmpfname, NULL);
+ tmpfp = fdopen (i, "w+");
+ acfg->fp = tmpfp;
+ g_assert (tmpfp);
emit_string_symbol (tmpfp, "mono_assembly_guid" , image->guid);
g_assert (cfg);
if (cfg->disable_aot) {
- printf ("Skip (other): %s\n", mono_method_full_name (method, TRUE));
+ //printf ("Skip (other): %s\n", mono_method_full_name (method, TRUE));
ocount++;
continue;
}
case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
case MONO_WRAPPER_STFLD:
case MONO_WRAPPER_LDFLD:
+ case MONO_WRAPPER_LDFLD_REMOTE:
+ case MONO_WRAPPER_STFLD_REMOTE:
case MONO_WRAPPER_STELEMREF:
case MONO_WRAPPER_ISINST:
case MONO_WRAPPER_PROXY_ISINST:
}
/* Emit code */
+ emit_section_change (tmpfp, ".text", 0);
for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
if (cfgs [i])
emit_method_code (acfg, cfgs [i]);
}
/* Emit method info */
+ emit_section_change (tmpfp, ".text", 1);
for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
if (cfgs [i])
emit_method_info (acfg, cfgs [i]);
}
+ /* Emit class info */
+
+ symbol = g_strdup_printf ("class_infos");
+ emit_section_change (tmpfp, ".text", 1);
+ emit_global (tmpfp, symbol, FALSE);
+ emit_alignment (tmpfp, 8);
+ emit_label (tmpfp, symbol);
+
+ for (i = 0; i < image->tables [MONO_TABLE_TYPEDEF].rows; ++i)
+ emit_klass_info (acfg, MONO_TOKEN_TYPE_DEF | (i + 1));
+
+ symbol = g_strdup_printf ("class_info_offsets");
+ emit_section_change (tmpfp, ".text", 1);
+ emit_global (tmpfp, symbol, FALSE);
+ emit_alignment (tmpfp, 8);
+ emit_label(tmpfp, symbol);
+
+ for (i = 0; i < image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
+ const char *sep;
+ if ((i % 32) == 0) {
+ fprintf (tmpfp, "\n.long ");
+ sep = "";
+ }
+ else
+ sep = ",";
+
+ symbol = g_strdup_printf (".LK_I_%x", i);
+ fprintf (tmpfp, "%s%s - class_infos", sep, symbol);
+ }
+ fprintf (tmpfp, "\n");
+
/*
* The icall and image tables are small but referenced in a lot of places.
* So we emit them at once, and reference their elements by an index.
emit_global (tmpfp, symbol, FALSE);
emit_alignment (tmpfp, 8);
emit_label(tmpfp, symbol);
- fprintf (tmpfp, ".long %d\n", acfg->got_offset * sizeof (gpointer));
+ fprintf (tmpfp, ".long %d\n", (int)(acfg->got_offset * sizeof (gpointer)));
#endif
symbol = g_strdup_printf ("method_offsets");
emit_label(tmpfp, symbol);
for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+ const char *sep;
+ if ((i % 32) == 0) {
+ fprintf (tmpfp, "\n.long ");
+ sep = "";
+ }
+ else
+ sep = ",";
if (cfgs [i]) {
symbol = g_strdup_printf (".Lm_%x", i + 1);
- fprintf (tmpfp, ".long %s - methods\n", symbol);
+ fprintf (tmpfp, "%s%s-methods", sep, symbol);
}
else
- fprintf (tmpfp, ".long 0xffffffff\n");
+ fprintf (tmpfp, "%s0xffffffff", sep);
}
+ fprintf (tmpfp, "\n");
symbol = g_strdup_printf ("method_info_offsets");
emit_section_change (tmpfp, ".text", 1);
emit_label(tmpfp, symbol);
for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+ const char *sep;
+ if ((i % 32) == 0) {
+ fprintf (tmpfp, "\n.long ");
+ sep = "";
+ }
+ else
+ sep = ",";
if (cfgs [i]) {
symbol = g_strdup_printf (".Lm_%x_p", i + 1);
- fprintf (tmpfp, ".long %s - method_infos\n", symbol);
+ fprintf (tmpfp, "%s%s - method_infos", sep, symbol);
}
else
- fprintf (tmpfp, ".long 0\n");
+ fprintf (tmpfp, "%s0", sep);
}
+ fprintf (tmpfp, "\n");
fclose (tmpfp);
g_free (com);
- if (aot_opts.outfile)
- outfile_name = g_strdup_printf ("%s", aot_opts.outfile);
+ if (acfg->aot_opts.outfile)
+ outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
else
outfile_name = g_strdup_printf ("%s%s", image->name, SHARED_EXT);
printf ("%d methods contain wrapper references (%d%%)\n", wrappercount, mcount ? (wrappercount*100)/mcount : 100);
printf ("%d methods contain lmf pointers (%d%%)\n", lmfcount, mcount ? (lmfcount*100)/mcount : 100);
printf ("%d methods have other problems (%d%%)\n", ocount, mcount ? (ocount*100)/mcount : 100);
- //printf ("Retained input file.\n");
- unlink (tmpfname);
+ if (acfg->aot_opts.save_temps)
+ printf ("Retained input file.\n");
+ else
+ unlink (tmpfname);
return 0;
}