gboolean soft_debug;
int nthreads;
int ntrampolines;
+ int nrgctx_trampolines;
gboolean print_skipped_methods;
gboolean stats;
char *tool_prefix;
typedef struct MonoAotStats {
int ccount, mcount, lmfcount, abscount, gcount, ocount, genericcount;
- int code_size, info_size, ex_info_size, unwind_info_size, got_size, class_info_size, got_info_size, got_info_offsets_size;
+ int code_size, info_size, ex_info_size, unwind_info_size, got_size, class_info_size, got_info_size;
int methods_without_got_slots, direct_calls, all_calls, llvm_count;
- int got_slots;
+ int got_slots, offsets_size;
int got_slot_types [MONO_PATCH_INFO_NONE];
int jit_time, gen_time, link_time;
} MonoAotStats;
guint32 label_generator;
gboolean llvm;
MonoAotFileFlags flags;
+ MonoDynamicStream blob;
} MonoAotCompile;
#define mono_acfg_lock(acfg) EnterCriticalSection (&((acfg)->mutex))
* We can't emit jumps because they are 32 bits only so they can't be patched.
* So we make indirect calls through GOT entries which are patched by the AOT
* loader to point to .Lpd entries.
- * An x86_64 plt entry is 10 bytes long, init_plt () depends on this.
*/
/* jmpq *<offset>(%rip) */
emit_byte (acfg, '\xff');
* - optimize OP_AOTCONST implementation
* - optimize the PLT entries
* - optimize SWITCH AOT implementation
- * - implement IMT support
*/
code = buf;
if (acfg->use_bin_writer && FALSE) {
#endif
}
+static void
+arch_emit_autoreg (MonoAotCompile *acfg, char *symbol)
+{
+#if defined(TARGET_POWERPC) && defined(__mono_ilp32__)
+ /* Based on code generated by gcc */
+ img_writer_emit_unset_mode (acfg->w);
+
+ fprintf (acfg->fp,
+#if defined(_MSC_VER) || defined(MONO_CROSS_COMPILE)
+ ".section .ctors,\"aw\",@progbits\n"
+ ".align 2\n"
+ ".globl %s\n"
+ ".long %s\n"
+ ".section .opd,\"aw\"\n"
+ ".align 2\n"
+ "%s:\n"
+ ".long .%s,.TOC.@tocbase32\n"
+ ".size %s,.-%s\n"
+ ".section .text\n"
+ ".type .%s,@function\n"
+ ".align 2\n"
+ ".%s:\n", symbol, symbol, symbol, symbol, symbol, symbol, symbol, symbol);
+#else
+ ".section .ctors,\"aw\",@progbits\n"
+ ".align 2\n"
+ ".globl %1$s\n"
+ ".long %1$s\n"
+ ".section .opd,\"aw\"\n"
+ ".align 2\n"
+ "%1$s:\n"
+ ".long .%1$s,.TOC.@tocbase32\n"
+ ".size %1$s,.-%1$s\n"
+ ".section .text\n"
+ ".type .%1$s,@function\n"
+ ".align 2\n"
+ ".%1$s:\n", symbol);
+#endif
+
+
+ fprintf (acfg->fp,
+ "stdu 1,-128(1)\n"
+ "mflr 0\n"
+ "std 31,120(1)\n"
+ "std 0,144(1)\n"
+
+ ".Lautoreg:\n"
+ "lis 3, .Lglobals@h\n"
+ "ori 3, 3, .Lglobals@l\n"
+ "bl .mono_aot_register_module\n"
+ "ld 11,0(1)\n"
+ "ld 0,16(11)\n"
+ "mtlr 0\n"
+ "ld 31,-8(11)\n"
+ "mr 1,11\n"
+ "blr\n"
+ );
+#if defined(_MSC_VER) || defined(MONO_CROSS_COMPILE)
+ fprintf (acfg->fp,
+ ".size .%s,.-.%s\n", symbol, symbol);
+#else
+ fprintf (acfg->fp,
+ ".size .%1$s,.-.%1$s\n", symbol);
+#endif
+#else
+#endif
+}
+
/*
* arch_get_cie_program:
*
*endbuf = p;
}
+static void
+stream_init (MonoDynamicStream *sh)
+{
+ sh->index = 0;
+ sh->alloc_size = 4096;
+ sh->data = g_malloc (4096);
+
+ /* So offsets are > 0 */
+ sh->index ++;
+}
+
+static void
+make_room_in_stream (MonoDynamicStream *stream, int size)
+{
+ if (size <= stream->alloc_size)
+ return;
+
+ while (stream->alloc_size <= size) {
+ if (stream->alloc_size < 4096)
+ stream->alloc_size = 4096;
+ else
+ stream->alloc_size *= 2;
+ }
+
+ stream->data = g_realloc (stream->data, stream->alloc_size);
+}
+
+static guint32
+add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
+{
+ guint32 idx;
+
+ make_room_in_stream (stream, stream->index + len);
+ memcpy (stream->data + stream->index, data, len);
+ idx = stream->index;
+ stream->index += len;
+ return idx;
+}
+
+/*
+ * add_to_blob:
+ *
+ * Add data to the binary blob inside the aot image. Returns the offset inside the
+ * blob where the data was stored.
+ */
+static guint32
+add_to_blob (MonoAotCompile *acfg, guint8 *data, guint32 data_len)
+{
+ if (acfg->blob.alloc_size == 0)
+ stream_init (&acfg->blob);
+
+ return add_stream_data (&acfg->blob, (char*)data, data_len);
+}
+
+/*
+ * emit_offset_table:
+ *
+ * Emit a table of increasing offsets in a compact form using differential encoding.
+ * There is an index entry for each GROUP_SIZE number of entries. The greater the
+ * group size, the more compact the table becomes, but the slower it becomes to compute
+ * a given entry. Returns the size of the table.
+ */
+static guint32
+emit_offset_table (MonoAotCompile *acfg, int noffsets, int group_size, gint32 *offsets)
+{
+ gint32 current_offset;
+ int i, buf_size, ngroups, index_entry_size;
+ guint8 *p, *buf;
+ guint32 *index_offsets;
+
+ ngroups = (noffsets + (group_size - 1)) / group_size;
+
+ index_offsets = g_new0 (guint32, ngroups);
+
+ buf_size = noffsets * 4;
+ p = buf = g_malloc0 (buf_size);
+
+ current_offset = 0;
+ for (i = 0; i < noffsets; ++i) {
+ //printf ("D: %d -> %d\n", i, offsets [i]);
+ if ((i % group_size) == 0) {
+ index_offsets [i / group_size] = p - buf;
+ /* Emit the full value for these entries */
+ encode_value (offsets [i], p, &p);
+ } else {
+ /* The offsets are allowed to be non-increasing */
+ //g_assert (offsets [i] >= current_offset);
+ encode_value (offsets [i] - current_offset, p, &p);
+ }
+ current_offset = offsets [i];
+ }
+
+ if (ngroups && index_offsets [ngroups - 1] < 65000)
+ index_entry_size = 2;
+ else
+ index_entry_size = 4;
+
+ /* Emit the header */
+ emit_int32 (acfg, noffsets);
+ emit_int32 (acfg, group_size);
+ emit_int32 (acfg, ngroups);
+ emit_int32 (acfg, index_entry_size);
+
+ /* Emit the index */
+ for (i = 0; i < ngroups; ++i) {
+ if (index_entry_size == 2)
+ emit_int16 (acfg, index_offsets [i]);
+ else
+ emit_int32 (acfg, index_offsets [i]);
+ }
+
+ /* Emit the data */
+ emit_bytes (acfg, buf, p - buf);
+
+ return (int)(p - buf) + (ngroups * 4);
+}
+
static guint32
get_image_index (MonoAotCompile *cfg, MonoImage *image)
{
#ifdef MONO_ARCH_DYN_CALL_SUPPORTED
if (!method->klass->contextbound) {
MonoDynCallInfo *info = mono_arch_dyn_call_prepare (sig);
+ gboolean has_nullable = FALSE;
+
+ for (j = 0; j < sig->param_count; j++) {
+ if (sig->params [j]->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (sig->params [j])))
+ has_nullable = TRUE;
+ }
- if (info) {
+ if (info && !has_nullable) {
/* Supported by the dynamic runtime-invoke wrapper */
skip = TRUE;
g_free (info);
token = MONO_TOKEN_METHOD_DEF | (i + 1);
method = mono_get_method (acfg->image, token, NULL);
- if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
+ if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED && !method->is_generic)
add_method (acfg, mono_marshal_get_synchronized_wrapper (method));
}
GList *l;
int pindex, buf_size, n_patches;
guint8 *code;
- char symbol [128];
GPtrArray *patches;
MonoJumpInfo *patch_info;
MonoMethodHeader *header;
method_index = get_method_index (acfg, method);
- /* Make the labels local */
- sprintf (symbol, "%sm_%x_p", acfg->temp_prefix, method_index);
-
/* Sort relocations */
patches = g_ptr_array_new ();
for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next)
acfg->stats.info_size += p - buf;
- /* Emit method info */
-
- emit_label (acfg, symbol);
-
g_assert (p - buf < buf_size);
- emit_bytes (acfg, buf, p - buf);
+
+ cfg->method_info_offset = add_to_blob (acfg, buf, p - buf);
g_free (buf);
}
int i, k, buf_size, method_index;
guint32 debug_info_size;
guint8 *code;
- char symbol [128];
MonoMethodHeader *header;
guint8 *p, *buf, *debug_info;
MonoJitInfo *jinfo = cfg->jit_info;
guint32 flags;
gboolean use_unwind_ops = FALSE;
- GPtrArray *seq_points;
+ MonoSeqPointInfo *seq_points;
method = cfg->orig_method;
code = cfg->native_code;
method_index = get_method_index (acfg, method);
- /* Make the labels local */
- sprintf (symbol, "%se_%x_p", acfg->temp_prefix, method_index);
-
if (!acfg->aot_opts.nodebug) {
mono_debug_serialize_debug_info (cfg, &debug_info, &debug_info_size);
} else {
debug_info_size = 0;
}
- buf_size = header->num_clauses * 256 + debug_info_size + 1024 + (cfg->seq_points ? (cfg->seq_points->len * 16) : 0);
+ seq_points = cfg->seq_point_info;
+
+ buf_size = header->num_clauses * 256 + debug_info_size + 1024 + (seq_points ? (seq_points->len * 64) : 0);
p = buf = g_malloc (buf_size);
#ifdef MONO_ARCH_HAVE_XP_UNWIND
use_unwind_ops = cfg->unwind_ops != NULL;
#endif
- seq_points = cfg->seq_points;
+ flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0) | (header->num_clauses ? 4 : 0) | (seq_points ? 8 : 0) | (cfg->compile_llvm ? 16 : 0);
- flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0) | (header->num_clauses ? 4 : 0) | (seq_points ? 8 : 0);
-
- if (cfg->compile_llvm) {
- /* Emitted by LLVM into the .eh_frame section */
- encode_value (0, p, &p);
- } else {
- encode_value (jinfo->code_size, p, &p);
- }
encode_value (flags, p, &p);
if (use_unwind_ops) {
}
if (seq_points) {
- int il_offset, native_offset, last_il_offset, last_native_offset;
+ int il_offset, native_offset, last_il_offset, last_native_offset, j;
encode_value (seq_points->len, p, &p);
last_il_offset = last_native_offset = 0;
- for (i = 0; i < seq_points->len; i += 2) {
- il_offset = GPOINTER_TO_INT (g_ptr_array_index (seq_points, i));
- native_offset = GPOINTER_TO_INT (g_ptr_array_index (seq_points, i + 1));
+ for (i = 0; i < seq_points->len; ++i) {
+ SeqPoint *sp = &seq_points->seq_points [i];
+ il_offset = sp->il_offset;
+ native_offset = sp->native_offset;
encode_value (il_offset - last_il_offset, p, &p);
encode_value (native_offset - last_native_offset, p, &p);
last_il_offset = il_offset;
last_native_offset = native_offset;
+
+ encode_value (sp->next_len, p, &p);
+ for (j = 0; j < sp->next_len; ++j)
+ encode_value (sp->next [j], p, &p);
}
}
acfg->stats.ex_info_size += p - buf;
- /* Emit info */
-
- emit_label (acfg, symbol);
-
g_assert (p - buf < buf_size);
- emit_bytes (acfg, buf, p - buf);
+
+ /* Emit info */
+ cfg->ex_info_offset = add_to_blob (acfg, buf, p - buf);
g_free (buf);
}
-static void
+static guint32
emit_klass_info (MonoAotCompile *acfg, guint32 token)
{
MonoClass *klass = mono_class_get (acfg->image, token);
guint8 *p, *buf;
- int i, buf_size;
- char symbol [128];
+ int i, buf_size, res;
gboolean no_special_static, cant_encode;
gpointer iter = NULL;
acfg->stats.class_info_size += p - buf;
- /* Emit the info */
- sprintf (symbol, "%sK_I_%x", acfg->temp_prefix, token - MONO_TOKEN_TYPE_DEF - 1);
- emit_label (acfg, symbol);
-
g_assert (p - buf < buf_size);
- emit_bytes (acfg, buf, p - buf);
+ res = add_to_blob (acfg, buf, p - buf);
g_free (buf);
+
+ return res;
}
/*
{
char start_symbol [256];
char symbol [256];
- guint32 buf_size;
+ guint32 buf_size, info_offset;
MonoJumpInfo *patch_info;
guint8 *buf, *p;
GPtrArray *patches;
sprintf (symbol, "%s_p", name);
+ info_offset = add_to_blob (acfg, buf, p - buf);
+
emit_section_change (acfg, ".text", 0);
emit_global (acfg, symbol, FALSE);
emit_label (acfg, symbol);
-
- emit_bytes (acfg, buf, p - buf);
+
+ emit_int32 (acfg, info_offset);
/* Emit debug info */
if (unwind_ops) {
opts->nodebug = TRUE;
} else if (str_begins_with (arg, "ntrampolines=")) {
opts->ntrampolines = atoi (arg + strlen ("ntrampolines="));
+ } else if (str_begins_with (arg, "nrgctx-trampolines=")) {
+ opts->nrgctx_trampolines = atoi (arg + strlen ("nrgctx-trampolines="));
} else if (str_begins_with (arg, "autoreg")) {
opts->autoreg = TRUE;
} else if (str_begins_with (arg, "tool-prefix=")) {
opts->tool_prefix = g_strdup (arg + strlen ("tool-prefix="));
- } else if (str_begins_with (arg, "autoreg")) {
- opts->autoreg = TRUE;
} else if (str_begins_with (arg, "soft-debug")) {
opts->soft_debug = TRUE;
} else if (str_begins_with (arg, "print-skipped")) {
* FIXME: Experiment with adding optimizations, the -std-compile-opts set takes
* a lot of time, and doesn't seem to save much space.
* The following optimizations cannot be enabled:
- * - 'globalopt', which seems to remove our methods, even though they have a global
- * alias pointing at them.
- * - 'constmerge'/'globaldce', which seems to remove our got symbol.
* - 'tailcallelim'
*/
opts = g_strdup ("-instcombine -simplifycfg");
#if 1
- command = g_strdup_printf ("opt -f %s -o temp.bc temp.bc", opts);
+ command = g_strdup_printf ("opt -f %s -o temp.opt.bc temp.bc", opts);
printf ("Executing opt: %s\n", command);
if (system (command) != 0) {
exit (1);
g_free (opts);
//command = g_strdup_printf ("llc -march=arm -mtriple=arm-linux-gnueabi -f -relocation-model=pic -unwind-tables temp.bc");
- command = g_strdup_printf ("llc -f -relocation-model=pic -unwind-tables -o temp.s temp.bc");
+ command = g_strdup_printf ("llc -f -relocation-model=pic -unwind-tables -o temp.s temp.opt.bc");
printf ("Executing llc: %s\n", command);
if (system (command) != 0) {
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
- sprintf (symbol, "method_offsets");
+ sprintf (symbol, "code_offsets");
emit_section_change (acfg, ".text", 1);
emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
+ acfg->stats.offsets_size += acfg->nmethods * 4;
+
for (i = 0; i < acfg->nmethods; ++i) {
if (acfg->cfgs [i]) {
sprintf (symbol, "%sm_%x", acfg->temp_prefix, i);
int i;
char symbol [256];
GList *l;
+ gint32 *offsets;
- /* Emit method info */
- sprintf (symbol, "method_info");
- emit_section_change (acfg, ".text", 1);
- emit_global (acfg, symbol, FALSE);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
-
- /* To reduce size of generated assembly code */
- sprintf (symbol, "mi");
- emit_label (acfg, symbol);
+ offsets = g_new0 (gint32, acfg->nmethods);
for (l = acfg->method_order; l != NULL; l = l->next) {
i = GPOINTER_TO_UINT (l->data);
- if (acfg->cfgs [i])
+ if (acfg->cfgs [i]) {
emit_method_info (acfg, acfg->cfgs [i]);
+ offsets [i] = acfg->cfgs [i]->method_info_offset;
+ } else {
+ offsets [i] = 0;
+ }
}
sprintf (symbol, "method_info_offsets");
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
- for (i = 0; i < acfg->nmethods; ++i) {
- if (acfg->cfgs [i]) {
- sprintf (symbol, "%sm_%x_p", acfg->temp_prefix, i);
- emit_symbol_diff (acfg, symbol, "mi", 0);
- } else {
- emit_int32 (acfg, 0);
- }
- }
- emit_line (acfg);
+ acfg->stats.offsets_size += emit_offset_table (acfg, acfg->nmethods, 10, offsets);
+
+ g_free (offsets);
}
#endif /* #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT) */
-/*
- * mono_aot_str_hash:
- *
- * Hash function for strings which we use to hash strings for things which are
- * saved in the AOT image, since g_str_hash () can change.
- */
-guint
-mono_aot_str_hash (gconstpointer v1)
-{
- /* Same as g_str_hash () in glib */
- char *p = (char *) v1;
- guint hash = *p;
-
- while (*p++) {
- if (*p)
- hash = (hash << 5) - hash + *p;
- }
-
- return hash;
-}
-
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
#define mix(a,b,c) { \
a -= c; a ^= rot(c, 4); c += b; \
case MONO_TYPE_CLASS:
case MONO_TYPE_SZARRAY:
/* check if the distribution is good enough */
- return ((hash << 5) - hash) ^ mono_aot_str_hash (t1->data.klass->name);
+ return ((hash << 5) - hash) ^ mono_metadata_str_hash (t1->data.klass->name);
case MONO_TYPE_PTR:
- return ((hash << 5) - hash) ^ mono_aot_type_hash (t1->data.type);
+ return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
case MONO_TYPE_ARRAY:
- return ((hash << 5) - hash) ^ mono_aot_type_hash (&t1->data.array->eklass->byval_arg);
+ return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
case MONO_TYPE_GENERICINST:
return ((hash << 5) - hash) ^ 0;
}
if (!method->wrapper_type) {
char *full_name = mono_type_full_name (&klass->byval_arg);
- hashes [0] = mono_aot_str_hash (full_name);
+ hashes [0] = mono_metadata_str_hash (full_name);
hashes [1] = 0;
g_free (full_name);
} else {
- hashes [0] = mono_aot_str_hash (klass->name);
- hashes [1] = mono_aot_str_hash (klass->name_space);
+ hashes [0] = mono_metadata_str_hash (klass->name);
+ hashes [1] = mono_metadata_str_hash (klass->name_space);
}
if (method->wrapper_type == MONO_WRAPPER_STFLD || method->wrapper_type == MONO_WRAPPER_LDFLD || method->wrapper_type == MONO_WRAPPER_LDFLDA)
/* The method name includes a stringified pointer */
hashes [2] = 0;
else
- hashes [2] = mono_aot_str_hash (method->name);
+ hashes [2] = mono_metadata_str_hash (method->name);
hashes [3] = method->wrapper_type;
hashes [4] = mono_aot_type_hash (sig->ret);
for (i = 0; i < sig->param_count; i++) {
info_offsets = g_new0 (guint32, acfg->extra_methods->len);
- buf_size = acfg->extra_methods->len * 256 + 256;
- p = buf = g_malloc (buf_size);
-
- /* Encode method info */
+ /* Emit method info */
nmethods = 0;
- /* So offsets are > 0 */
- *p = 0;
- p++;
for (i = 0; i < acfg->extra_methods->len; ++i) {
MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
MonoCompile *cfg = g_hash_table_lookup (acfg->method_to_cfg, method);
if (!cfg)
continue;
+ buf_size = 512;
+ p = buf = g_malloc (buf_size);
+
nmethods ++;
- info_offsets [i] = p - buf;
name = NULL;
if (method->wrapper_type) {
}
g_assert ((p - buf) < buf_size);
- }
- g_assert ((p - buf) < buf_size);
-
- /* Emit method info */
- sprintf (symbol, "extra_method_info");
- emit_section_change (acfg, ".text", 1);
- emit_global (acfg, symbol, FALSE);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
-
- emit_bytes (acfg, buf, p - buf);
-
- emit_line (acfg);
+ info_offsets [i] = add_to_blob (acfg, buf, p - buf);
+ g_free (buf);
+ }
/*
* Construct a chained hash table for mapping indexes in extra_method_info to
{
int i;
char symbol [256];
+ gint32 *offsets;
- sprintf (symbol, "ex_info");
- emit_section_change (acfg, ".text", 1);
- emit_global (acfg, symbol, FALSE);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
-
- /* To reduce size of generated assembly */
- sprintf (symbol, "ex");
- emit_label (acfg, symbol);
-
+ offsets = g_new0 (gint32, acfg->nmethods);
for (i = 0; i < acfg->nmethods; ++i) {
- if (acfg->cfgs [i])
+ if (acfg->cfgs [i]) {
emit_exception_debug_info (acfg, acfg->cfgs [i]);
+ offsets [i] = acfg->cfgs [i]->ex_info_offset;
+ } else {
+ offsets [i] = 0;
+ }
}
sprintf (symbol, "ex_info_offsets");
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
- for (i = 0; i < acfg->nmethods; ++i) {
- if (acfg->cfgs [i]) {
- sprintf (symbol, "%se_%x_p", acfg->temp_prefix, i);
- emit_symbol_diff (acfg, symbol, "ex", 0);
- } else {
- emit_int32 (acfg, 0);
- }
- }
- emit_line (acfg);
+ acfg->stats.offsets_size += emit_offset_table (acfg, acfg->nmethods, 10, offsets);
+ g_free (offsets);
}
static void
{
int i;
char symbol [256];
+ gint32 *offsets;
- sprintf (symbol, "class_info");
- emit_section_change (acfg, ".text", 1);
- emit_global (acfg, symbol, FALSE);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
-
+ offsets = g_new0 (gint32, acfg->image->tables [MONO_TABLE_TYPEDEF].rows);
for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i)
- emit_klass_info (acfg, MONO_TOKEN_TYPE_DEF | (i + 1));
+ offsets [i] = emit_klass_info (acfg, MONO_TOKEN_TYPE_DEF | (i + 1));
sprintf (symbol, "class_info_offsets");
emit_section_change (acfg, ".text", 1);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
- for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
- sprintf (symbol, "%sK_I_%x", acfg->temp_prefix, i);
- emit_symbol_diff (acfg, symbol, "class_info", 0);
- }
- emit_line (acfg);
+ acfg->stats.offsets_size += emit_offset_table (acfg, acfg->image->tables [MONO_TABLE_TYPEDEF].rows, 10, offsets);
+ g_free (offsets);
}
typedef struct ClassNameTableEntry {
token = MONO_TOKEN_TYPE_DEF | (i + 1);
klass = mono_class_get (acfg->image, token);
full_name = mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_FULL_NAME);
- hash = mono_aot_str_hash (full_name) % table_size;
+ hash = mono_metadata_str_hash (full_name) % table_size;
g_free (full_name);
/* FIXME: Allocate from the mempool */
for (i = 0; i < acfg->got_patches->len; ++i) {
MonoJumpInfo *ji = g_ptr_array_index (acfg->got_patches, i);
- got_info_offsets [i] = p - buf;
- if (i >= first_plt_got_patch)
- acfg->plt_got_info_offsets [i - first_plt_got_patch + 1] = got_info_offsets [i];
+ p = buf;
+
encode_value (ji->type, p, &p);
encode_patch (acfg, ji, p, &p);
- }
-
- g_assert (p - buf <= buf_size);
- acfg->stats.got_info_size = p - buf;
-
- /* Emit got_info table */
- sprintf (symbol, "got_info");
- emit_section_change (acfg, ".text", 1);
- emit_global (acfg, symbol, FALSE);
- emit_alignment (acfg, 8);
- emit_label (acfg, symbol);
+ g_assert (p - buf <= buf_size);
+ got_info_offsets [i] = add_to_blob (acfg, buf, p - buf);
- emit_bytes (acfg, buf, p - buf);
+ if (i >= first_plt_got_patch)
+ acfg->plt_got_info_offsets [i - first_plt_got_patch + 1] = got_info_offsets [i];
+ acfg->stats.got_info_size += p - buf;
+ }
/* Emit got_info_offsets table */
sprintf (symbol, "got_info_offsets");
emit_label (acfg, symbol);
/* No need to emit offsets for the got plt entries, the plt embeds them directly */
- for (i = 0; i < first_plt_got_patch; ++i)
- emit_int32 (acfg, got_info_offsets [i]);
-
- acfg->stats.got_info_offsets_size = acfg->got_patches->len * 4;
+ acfg->stats.offsets_size += emit_offset_table (acfg, first_plt_got_patch, 10, (gint32*)got_info_offsets);
}
static void
for (i = 0; i < acfg->globals->len; ++i) {
char *name = g_ptr_array_index (acfg->globals, i);
- hash = mono_aot_str_hash (name) % table_size;
+ hash = mono_metadata_str_hash (name) % table_size;
/* FIXME: Allocate from the mempool */
new_entry = g_new0 (GlobalsTableEntry, 1);
static void
emit_globals (MonoAotCompile *acfg)
{
- char *opts_str;
char *build_info;
emit_string_symbol (acfg, "mono_assembly_guid" , acfg->image->guid);
emit_string_symbol (acfg, "mono_aot_version", MONO_AOT_FILE_VERSION);
- opts_str = g_strdup_printf ("%d", acfg->opts);
- emit_string_symbol (acfg, "mono_aot_opt_flags", opts_str);
- g_free (opts_str);
-
- emit_string_symbol (acfg, "mono_aot_full_aot", acfg->aot_opts.full_aot ? "TRUE" : "FALSE");
-
if (acfg->aot_opts.bind_to_runtime_version) {
build_info = mono_get_runtime_build_info ();
emit_string_symbol (acfg, "mono_runtime_version", build_info);
symbol = g_strdup_printf ("_%s_autoreg", acfg->static_linking_symbol);
-#if defined(TARGET_POWERPC) && defined(__mono_ilp32__)
- /* Based on code generated by gcc */
- img_writer_emit_unset_mode (acfg->w);
-
- fprintf (acfg->fp,
-#ifdef _MSC_VER
- ".section .ctors,\"aw\",@progbits\n"
- ".align 2\n"
- ".globl %s\n"
- ".long %s\n"
- ".section .opd,\"aw\"\n"
- ".align 2\n"
- "%s:\n"
- ".long .%s,.TOC.@tocbase32\n"
- ".size %s,.-%s\n"
- ".section .text\n"
- ".type .%s,@function\n"
- ".%s:\n", symbol, symbol, symbol, symbol, symbol, symbol, symbol, symbol);
-#else
- ".section .ctors,\"aw\",@progbits\n"
- ".align 2\n"
- ".globl %1$s\n"
- ".long %1$s\n"
- ".section .opd,\"aw\"\n"
- ".align 2\n"
- "%1$s:\n"
- ".long .%1$s,.TOC.@tocbase32\n"
- ".size %1$s,.-%1$s\n"
- ".section .text\n"
- ".type .%1$s,@function\n"
- ".%1$s:\n", symbol);
-#endif
-
-
- fprintf (acfg->fp,
- "stdu 1,-128(1)\n"
- "mflr 0\n"
- "std 31,120(1)\n"
- "std 0,144(1)\n"
-
- ".Lautoreg:\n"
- "lis 3, .Lglobals@h\n"
- "ori 3, 3, .Lglobals@l\n"
- "bl .mono_aot_register_module\n"
- "ld 11,0(1)\n"
- "ld 0,16(11)\n"
- "mtlr 0\n"
- "ld 31,-8(11)\n"
- "mr 1,11\n"
- "blr\n"
- );
-#ifdef _MSC_VER
- fprintf (acfg->fp,
- ".size .%s,.-.%s\n", symbol, symbol);
-#else
- fprintf (acfg->fp,
- ".size .%1$s,.-.%1$s\n", symbol);
-#endif
-#else
-#endif
+ arch_emit_autoreg (acfg, symbol);
g_free (symbol);
}
emit_int32 (acfg, acfg->plt_offset);
emit_int32 (acfg, acfg->nmethods);
emit_int32 (acfg, acfg->flags);
+ emit_int32 (acfg, acfg->opts);
for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
emit_int32 (acfg, acfg->num_trampolines [i]);
emit_int32 (acfg, acfg->trampoline_size [i]);
}
+static void
+emit_blob (MonoAotCompile *acfg)
+{
+ char symbol [128];
+
+ sprintf (symbol, "blob");
+ emit_section_change (acfg, ".text", 1);
+ emit_global (acfg, symbol, FALSE);
+ emit_alignment (acfg, 8);
+ emit_label (acfg, symbol);
+
+ emit_bytes (acfg, (guint8*)acfg->blob.data, acfg->blob.index);
+}
+
static void
emit_dwarf_info (MonoAotCompile *acfg)
{
memset (&acfg->aot_opts, 0, sizeof (acfg->aot_opts));
acfg->aot_opts.write_symbols = TRUE;
acfg->aot_opts.ntrampolines = 1024;
+ acfg->aot_opts.nrgctx_trampolines = 1024;
mono_aot_parse_options (aot_options, &acfg->aot_opts);
acfg->flags |= MONO_AOT_FILE_FLAG_WITH_LLVM;
#endif
+ if (acfg->aot_opts.full_aot)
+ acfg->flags |= MONO_AOT_FILE_FLAG_FULL_AOT;
+
load_profile_files (acfg);
acfg->num_trampolines [MONO_AOT_TRAMP_SPECIFIC] = acfg->aot_opts.full_aot ? acfg->aot_opts.ntrampolines : 0;
#ifdef MONO_ARCH_HAVE_STATIC_RGCTX_TRAMPOLINE
- acfg->num_trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = acfg->aot_opts.full_aot ? 1024 : 0;
+ acfg->num_trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = acfg->aot_opts.full_aot ? acfg->aot_opts.nrgctx_trampolines : 0;
#endif
acfg->num_trampolines [MONO_AOT_TRAMP_IMT_THUNK] = acfg->aot_opts.full_aot ? 128 : 0;
emit_file_info (acfg);
+ emit_blob (acfg);
+
emit_globals (acfg);
emit_autoreg (acfg);
if (acfg->llvm)
g_assert (acfg->got_offset == acfg->final_got_size);
- printf ("Code: %d Info: %d Ex Info: %d Unwind Info: %d Class Info: %d PLT: %d GOT Info: %d GOT Info Offsets: %d GOT: %d Offsets: %d\n", acfg->stats.code_size, acfg->stats.info_size, acfg->stats.ex_info_size, acfg->stats.unwind_info_size, acfg->stats.class_info_size, acfg->plt_offset, acfg->stats.got_info_size, acfg->stats.got_info_offsets_size, (int)(acfg->got_offset * sizeof (gpointer)), (int)(acfg->nmethods * 3 * sizeof (gpointer)));
+ printf ("Code: %d Info: %d Ex Info: %d Unwind Info: %d Class Info: %d PLT: %d GOT Info: %d GOT: %d Offsets: %d\n", acfg->stats.code_size, acfg->stats.info_size, acfg->stats.ex_info_size, acfg->stats.unwind_info_size, acfg->stats.class_info_size, acfg->plt_offset, acfg->stats.got_info_size, (int)(acfg->got_offset * sizeof (gpointer)), acfg->stats.offsets_size);
TV_GETTIME (atv);
res = img_writer_emit_writeout (acfg->w);
* This could be called from inside gdb to flush the debugging information not yet
* registered with gdb.
*/
-static void
+void
mono_xdebug_flush (void)
{
if (xdebug_w)