- emit_unset_mode (acfg);
-#if (defined(__ppc__) && defined(__MACH__)) || defined(PLATFORM_WIN32)
- // mach-o always uses a '_' prefix.
- fprintf (acfg->fp, "_%s:\n", name);
-#else
- fprintf (acfg->fp, "%s:\n", name);
-#endif
-
-#if defined(PLATFORM_WIN32)
- /* Emit a normal label too */
- fprintf (acfg->fp, "%s:\n", name);
-#endif
-}
-
-static void
-emit_string (MonoAotCompile *acfg, const char *value)
-{
- emit_unset_mode (acfg);
- fprintf (acfg->fp, "\t%s \"%s\"\n", AS_STRING_DIRECTIVE, value);
-}
-
-static void
-emit_line (MonoAotCompile *acfg)
-{
- emit_unset_mode (acfg);
- fprintf (acfg->fp, "\n");
-}
-
-static void
-emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
-{
- emit_unset_mode (acfg);
- emit_section_change (acfg, ".text", 1);
- emit_global (acfg, name, FALSE);
- emit_label (acfg, name);
- emit_string (acfg, value);
-}
-
-static void
-emit_alignment (MonoAotCompile *acfg, int size)
-{
- emit_unset_mode (acfg);
-#if defined(__arm__)
- fprintf (acfg->fp, "\t.align %d\n", ilog2 (size));
-#elif defined(__ppc__) && defined(__MACH__)
- // the mach-o assembler specifies alignments as powers of 2.
- fprintf (acfg->fp, "\t.align %d\t; ilog2\n", ilog2(size));
-#elif defined(__powerpc__)
- /* ignore on linux/ppc */
-#else
- fprintf (acfg->fp, "\t.align %d\n", size);
-#endif
-}
-
-static void
-emit_pointer (MonoAotCompile *acfg, const char *target)
-{
- emit_unset_mode (acfg);
- emit_alignment (acfg, sizeof (gpointer));
-#if defined(__x86_64__)
- fprintf (acfg->fp, "\t.quad %s\n", target ? target : "0");
-#elif defined(sparc) && SIZEOF_VOID_P == 8
- fprintf (acfg->fp, "\t.xword %s\n", target ? target : "0");
-#else
- fprintf (acfg->fp, "\t.long %s\n", target ? target : "0");
-#endif
-}
-
-static char *byte_to_str;
-
-static void
-emit_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
-{
- int i;
- if (acfg->mode != EMIT_BYTE) {
- acfg->mode = EMIT_BYTE;
- acfg->col_count = 0;
- }
-
- if (byte_to_str == NULL) {
- byte_to_str = g_new0 (char, 256 * 8);
- for (i = 0; i < 256; ++i) {
- sprintf (byte_to_str + (i * 8), ",%d", i);
- }
- }
-
- for (i = 0; i < size; ++i, ++acfg->col_count) {
- if ((acfg->col_count % 32) == 0)
- fprintf (acfg->fp, "\n\t.byte %d", buf [i]);
- else
- fputs (byte_to_str + (buf [i] * 8), acfg->fp);
- }
-}
-
-static inline void
-emit_int16 (MonoAotCompile *acfg, int value)
-{
- if (acfg->mode != EMIT_WORD) {
- acfg->mode = EMIT_WORD;
- acfg->col_count = 0;
- }
- if ((acfg->col_count++ % 8) == 0)
-#if defined(__MACH__)
- fprintf (acfg->fp, "\n\t.short ");
-#elif defined(__arm__)
- /* FIXME: Use .hword on other archs as well */
- fprintf (acfg->fp, "\n\t.hword ");
-#else
- fprintf (acfg->fp, "\n\t.word ");
-#endif
- else
- fprintf (acfg->fp, ", ");
- fprintf (acfg->fp, "%d", value);
-}
-
-static inline void
-emit_int32 (MonoAotCompile *acfg, int value)
-{
- if (acfg->mode != EMIT_LONG) {
- acfg->mode = EMIT_LONG;
- acfg->col_count = 0;
- }
- if ((acfg->col_count++ % 8) == 0)
- fprintf (acfg->fp, "\n\t.long ");
- else
- fprintf (acfg->fp, ",");
- fprintf (acfg->fp, "%d", value);
-}
-
-static void
-emit_symbol_diff (MonoAotCompile *acfg, const char *end, const char* start, int offset)
-{
- if (acfg->mode != EMIT_LONG) {
- acfg->mode = EMIT_LONG;
- acfg->col_count = 0;
- }
- if ((acfg->col_count++ % 8) == 0)
- fprintf (acfg->fp, "\n\t.long ");
- else
- fprintf (acfg->fp, ",");
- if (offset > 0)
- fprintf (acfg->fp, "%s - %s + %d", end, start, offset);
- else if (offset < 0)
- fprintf (acfg->fp, "%s - %s %d", end, start, offset);
- else
- fprintf (acfg->fp, "%s - %s", end, start);
-}
-
-static void
-emit_zero_bytes (MonoAotCompile *acfg, int num)
-{
- emit_unset_mode (acfg);
-#if defined(__MACH__)
- fprintf (acfg->fp, "\t.space %d\n", num);
-#else
- fprintf (acfg->fp, "\t.skip %d\n", num);
-#endif
-}
-
-static int
-emit_writeout (MonoAotCompile *acfg)
-{
- char *command, *objfile;
- char *outfile_name, *tmp_outfile_name;
-
- fclose (acfg->fp);
-
-#if defined(__x86_64__)
-#define AS_OPTIONS "--64"
-#elif defined(sparc) && SIZEOF_VOID_P == 8
-#define AS_OPTIONS "-xarch=v9"
-#else
-#define AS_OPTIONS ""
-#endif
-
- if (acfg->aot_opts.asm_only) {
- printf ("Output file: '%s'.\n", acfg->tmpfname);
- if (acfg->aot_opts.static_link)
- printf ("Linking symbol: '%s'.\n", acfg->static_linking_symbol);
- return 0;
- }
-
- if (acfg->aot_opts.static_link) {
- if (acfg->aot_opts.outfile)
- objfile = g_strdup_printf ("%s", acfg->aot_opts.outfile);
- else
- objfile = g_strdup_printf ("%s.o", acfg->image->name);
- } else {
- objfile = g_strdup_printf ("%s.o", acfg->tmpfname);
- }
- command = g_strdup_printf ("as %s %s -o %s", AS_OPTIONS, acfg->tmpfname, objfile);
- printf ("Executing the native assembler: %s\n", command);
- if (system (command) != 0) {
- g_free (command);
- g_free (objfile);
- return 1;
- }
-
- g_free (command);
-
- if (acfg->aot_opts.static_link) {
- printf ("Output file: '%s'.\n", objfile);
- printf ("Linking symbol: '%s'.\n", acfg->static_linking_symbol);
- g_free (objfile);
- return 0;
- }
-
- if (acfg->aot_opts.outfile)
- outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
- else
- outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
-
- tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
-
-#if defined(sparc)
- command = g_strdup_printf ("ld -shared -G -o %s %s.o", outfile_name, acfg->tmpfname);
-#elif defined(__ppc__) && defined(__MACH__)
- command = g_strdup_printf ("gcc -dynamiclib -o %s %s.o", outfile_name, acfg->tmpfname);
-#elif defined(PLATFORM_WIN32)
- command = g_strdup_printf ("gcc -shared --dll -mno-cygwin -o %s %s.o", outfile_name, acfg->tmpfname);
-#else
- if (acfg->aot_opts.no_dlsym) {
- /*
- * Need to link using gcc so our ctor function gets called.
- */
- command = g_strdup_printf ("gcc -shared -o %s %s.o", outfile_name, acfg->tmpfname);
- } else {
- command = g_strdup_printf ("ld -shared -o %s %s.o", outfile_name, acfg->tmpfname);
- }
-#endif
- printf ("Executing the native linker: %s\n", command);
- if (system (command) != 0) {
- g_free (tmp_outfile_name);
- g_free (outfile_name);
- g_free (command);
- g_free (objfile);
- return 1;
- }
-
- 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);
- g_free (com);*/
-
- rename (tmp_outfile_name, outfile_name);
-
- g_free (tmp_outfile_name);
- g_free (outfile_name);
- g_free (objfile);
-
- if (acfg->aot_opts.save_temps)
- printf ("Retained input file.\n");
- else
- unlink (acfg->tmpfname);
-
- return 0;
-}
-
-#endif /* ASM_WRITER */
-
-static void
-emit_global (MonoAotCompile *acfg, const char *name, gboolean func)
-{
- if (acfg->aot_opts.no_dlsym) {
- g_ptr_array_add (acfg->globals, g_strdup (name));
- } else {
- emit_global_inner (acfg, name, func);
- }
-}
-
-static void
-emit_byte (MonoAotCompile *acfg, guint8 val)
-{
- emit_bytes (acfg, &val, 1);
-}
-
-static guint32
-mono_get_field_token (MonoClassField *field)
-{
- MonoClass *klass = field->parent;
- int i;
-
- for (i = 0; i < klass->field.count; ++i) {
- if (field == &klass->fields [i])
- return MONO_TOKEN_FIELD_DEF | (klass->field.first + 1 + i);
- }
-
- g_assert_not_reached ();
- return 0;
-}
-
-static inline void
-encode_value (gint32 value, guint8 *buf, guint8 **endbuf)
-{
- guint8 *p = buf;
-
- //printf ("ENCODE: %d 0x%x.\n", value, value);
-
- /*
- * Same encoding as the one used in the metadata, extended to handle values
- * greater than 0x1fffffff.
- */
- if ((value >= 0) && (value <= 127))
- *p++ = value;
- else if ((value >= 0) && (value <= 16383)) {
- p [0] = 0x80 | (value >> 8);
- p [1] = value & 0xff;
- p += 2;
- } else if ((value >= 0) && (value <= 0x1fffffff)) {
- p [0] = (value >> 24) | 0xc0;
- p [1] = (value >> 16) & 0xff;
- p [2] = (value >> 8) & 0xff;
- p [3] = value & 0xff;
- p += 4;
- }
- else {
- p [0] = 0xff;
- p [1] = (value >> 24) & 0xff;
- p [2] = (value >> 16) & 0xff;
- p [3] = (value >> 8) & 0xff;
- p [4] = value & 0xff;
- p += 5;
- }
- if (endbuf)
- *endbuf = p;
-}
-
-static guint32
-get_image_index (MonoAotCompile *cfg, MonoImage *image)
-{
- guint32 index;
-
- index = GPOINTER_TO_UINT (g_hash_table_lookup (cfg->image_hash, image));
- if (index)
- return index - 1;
- else {
- index = g_hash_table_size (cfg->image_hash);
- g_hash_table_insert (cfg->image_hash, image, GUINT_TO_POINTER (index + 1));
- g_ptr_array_add (cfg->image_table, image);
- return index;
- }
-}
-
-static guint32
-find_typespec_for_class (MonoAotCompile *acfg, MonoClass *klass)
-{
- int i;
- MonoClass *k = NULL;
-
- /* FIXME: Search referenced images as well */
- for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
- k = mono_class_get_full (acfg->image, MONO_TOKEN_TYPE_SPEC | (i + 1), NULL);
- if (k == klass)
- break;
- }
-
- if (i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows)
- return MONO_TOKEN_TYPE_SPEC | (i + 1);
- else
- return 0;
-}
-
-static void
-encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 **endbuf);
-
-/*
- * encode_klass_ref:
- *
- * Encode a reference to KLASS. We use our home-grown encoding instead of the
- * standard metadata encoding.
- */
-static void
-encode_klass_ref (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, guint8 **endbuf)
-{
- guint8 *p = buf;