"Fossies" - the Fresh Open Source Software Archive

Member "mono-6.12.0.122/mono/mini/aot-compiler.c" (22 Feb 2021, 436383 Bytes) of package /linux/misc/mono-sources/mono/mono-6.12.0.122.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "aot-compiler.c": 6.10.0.104_vs_6.12.0.90.

    1 /**
    2  * \file
    3  * mono Ahead of Time compiler
    4  *
    5  * Author:
    6  *   Dietmar Maurer (dietmar@ximian.com)
    7  *   Zoltan Varga (vargaz@gmail.com)
    8  *   Johan Lorensson (lateralusx.github@gmail.com)
    9  *
   10  * (C) 2002 Ximian, Inc.
   11  * Copyright 2003-2011 Novell, Inc 
   12  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
   13  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
   14  */
   15 
   16 #include "config.h"
   17 #include <sys/types.h>
   18 #ifdef HAVE_UNISTD_H
   19 #include <unistd.h>
   20 #endif
   21 #ifdef HAVE_STDINT_H
   22 #include <stdint.h>
   23 #endif
   24 #include <fcntl.h>
   25 #include <ctype.h>
   26 #include <string.h>
   27 #ifndef HOST_WIN32
   28 #include <sys/time.h>
   29 #else
   30 #include <winsock2.h>
   31 #include <windows.h>
   32 #endif
   33 
   34 #include <errno.h>
   35 #include <sys/stat.h>
   36 
   37 #include <mono/metadata/abi-details.h>
   38 #include <mono/metadata/tabledefs.h>
   39 #include <mono/metadata/class.h>
   40 #include <mono/metadata/object.h>
   41 #include <mono/metadata/tokentype.h>
   42 #include <mono/metadata/appdomain.h>
   43 #include <mono/metadata/debug-helpers.h>
   44 #include <mono/metadata/assembly.h>
   45 #include <mono/metadata/metadata-internals.h>
   46 #include <mono/metadata/reflection-internals.h>
   47 #include <mono/metadata/marshal.h>
   48 #include <mono/metadata/gc-internals.h>
   49 #include <mono/metadata/mempool-internals.h>
   50 #include <mono/metadata/mono-endian.h>
   51 #include <mono/metadata/threads-types.h>
   52 #include <mono/metadata/custom-attrs-internals.h>
   53 #include <mono/utils/mono-logger-internals.h>
   54 #include <mono/utils/mono-compiler.h>
   55 #include <mono/utils/mono-time.h>
   56 #include <mono/utils/mono-mmap.h>
   57 #include <mono/utils/mono-rand.h>
   58 #include <mono/utils/json.h>
   59 #include <mono/utils/mono-threads-coop.h>
   60 #include <mono/profiler/aot.h>
   61 #include <mono/utils/w32api.h>
   62 
   63 #include "aot-compiler.h"
   64 #include "aot-runtime.h"
   65 #include "seq-points.h"
   66 #include "image-writer.h"
   67 #include "dwarfwriter.h"
   68 #include "mini-gc.h"
   69 #include "mini-llvm.h"
   70 #include "mini-runtime.h"
   71 
   72 static MonoMethod*
   73 try_get_method_nofail (MonoClass *klass, const char *method_name, int param_count, int flags)
   74 {
   75     MonoMethod *result;
   76     ERROR_DECL (error);
   77     result = mono_class_get_method_from_name_checked (klass, method_name, param_count, flags, error);
   78     mono_error_assert_ok (error);
   79     return result;
   80 }
   81 
   82 // FIXME Consolidate the multiple functions named get_method_nofail.
   83 static MonoMethod*
   84 get_method_nofail (MonoClass *klass, const char *method_name, int param_count, int flags)
   85 {
   86     MonoMethod *result = try_get_method_nofail (klass, method_name, param_count, flags);
   87     g_assertf (result, "Expected to find method %s in klass %s", method_name, m_class_get_name (klass));
   88     return result;
   89 }
   90 
   91 #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT)
   92 
   93 // Use MSVC toolchain, Clang for MSVC using MSVC codegen and linker, when compiling for AMD64
   94 // targeting WIN32 platforms running AOT compiler on WIN32 platform with VS installation.
   95 #if defined(TARGET_AMD64) && defined(TARGET_WIN32) && defined(HOST_WIN32) && defined(_MSC_VER)
   96 #define TARGET_X86_64_WIN32_MSVC
   97 #endif
   98 
   99 #if defined(TARGET_X86_64_WIN32_MSVC)
  100 #define TARGET_WIN32_MSVC
  101 #endif
  102 
  103 // Emit native unwind info on Windows platforms (different from DWARF). Emitted unwind info
  104 // works when using the MSVC toolchain using Clang for MSVC codegen and linker. Only supported when
  105 // compiling for AMD64 (Windows x64 platforms).
  106 #if defined(TARGET_WIN32_MSVC) && defined(MONO_ARCH_HAVE_UNWIND_TABLE)
  107 #define EMIT_WIN32_UNWIND_INFO
  108 #endif
  109 
  110 #if defined(TARGET_ANDROID) || defined(__linux__)
  111 #define RODATA_REL_SECT ".data.rel.ro"
  112 #else
  113 #define RODATA_REL_SECT ".text"
  114 #endif
  115 
  116 #if defined(__linux__)
  117 #define RODATA_SECT ".rodata"
  118 #elif defined(TARGET_MACH)
  119 #define RODATA_SECT ".section __TEXT, __const"
  120 #elif defined(TARGET_WIN32_MSVC)
  121 #define RODATA_SECT ".rdata"
  122 #else
  123 #define RODATA_SECT ".text"
  124 #endif
  125 
  126 #define TV_DECLARE(name) gint64 name
  127 #define TV_GETTIME(tv) tv = mono_100ns_ticks ()
  128 #define TV_ELAPSED(start,end) (((end) - (start)) / 10)
  129 
  130 #define ROUND_DOWN(VALUE,SIZE)  ((VALUE) & ~((SIZE) - 1))
  131 
  132 typedef struct {
  133     char *name;
  134     MonoImage *image;
  135 } ImageProfileData;
  136 
  137 typedef struct ClassProfileData ClassProfileData;
  138 
  139 typedef struct {
  140     int argc;
  141     ClassProfileData **argv;
  142     MonoGenericInst *inst;
  143 } GInstProfileData;
  144 
  145 struct ClassProfileData {
  146     ImageProfileData *image;
  147     char *ns, *name;
  148     GInstProfileData *inst;
  149     MonoClass *klass;
  150 };
  151 
  152 typedef struct {
  153     ClassProfileData *klass;
  154     int id;
  155     char *name;
  156     int param_count;
  157     char *signature;
  158     GInstProfileData *inst;
  159     MonoMethod *method;
  160 } MethodProfileData;
  161 
  162 typedef struct {
  163     GHashTable *images, *classes, *ginsts, *methods;
  164 } ProfileData;
  165 
  166 /* predefined values for static readonly fields without needed to run the .cctor */
  167 typedef struct _ReadOnlyValue ReadOnlyValue;
  168 struct _ReadOnlyValue {
  169     ReadOnlyValue *next;
  170     char *name;
  171     int type; /* to be used later for typechecking to prevent user errors */
  172     union {
  173         guint8 i1;
  174         guint16 i2;
  175         guint32 i4;
  176         guint64 i8;
  177         gpointer ptr;
  178     } value;
  179 };
  180 static ReadOnlyValue *readonly_values;
  181 
  182 typedef struct MonoAotOptions {
  183     char *outfile;
  184     char *llvm_outfile;
  185     char *data_outfile;
  186     GList *profile_files;
  187     gboolean save_temps;
  188     gboolean write_symbols;
  189     gboolean metadata_only;
  190     gboolean bind_to_runtime_version;
  191     MonoAotMode mode;
  192     gboolean interp;
  193     gboolean no_dlsym;
  194     gboolean static_link;
  195     gboolean asm_only;
  196     gboolean asm_writer;
  197     gboolean nodebug;
  198     gboolean dwarf_debug;
  199     gboolean soft_debug;
  200     gboolean log_generics;
  201     gboolean log_instances;
  202     gboolean gen_msym_dir;
  203     char *gen_msym_dir_path;
  204     gboolean direct_pinvoke;
  205     gboolean direct_icalls;
  206     gboolean direct_extern_calls;
  207     gboolean no_direct_calls;
  208     gboolean use_trampolines_page;
  209     gboolean no_instances;
  210     // We are collecting inflated methods and emitting non-inflated
  211     gboolean dedup; 
  212     // The name of the assembly for which the AOT module is going to have all deduped methods moved to. 
  213     // When set, we are emitting inflated methods only
  214     char *dedup_include; 
  215     gboolean gnu_asm;
  216     gboolean try_llvm;
  217     gboolean llvm;
  218     gboolean llvm_only;
  219     gboolean llvm_disable_self_init;
  220     int nthreads;
  221     int ntrampolines;
  222     int nrgctx_trampolines;
  223     int nimt_trampolines;
  224     int ngsharedvt_arg_trampolines;
  225     int nftnptr_arg_trampolines;
  226     int nrgctx_fetch_trampolines;
  227     int nunbox_arbitrary_trampolines;
  228     gboolean print_skipped_methods;
  229     gboolean stats;
  230     gboolean verbose;
  231     gboolean deterministic;
  232     char *tool_prefix;
  233     char *ld_flags;
  234     char *ld_name;
  235     char *mtriple;
  236     char *llvm_path;
  237     char *temp_path;
  238     char *instances_logfile_path;
  239     char *logfile;
  240     char *llvm_opts;
  241     char *llvm_llc;
  242     char *llvm_cpu_attr;
  243     gboolean use_current_cpu;
  244     gboolean dump_json;
  245     gboolean profile_only;
  246     gboolean no_opt;
  247     char *clangxx;
  248     char *depfile;
  249 } MonoAotOptions;
  250 
  251 typedef enum {
  252     METHOD_CAT_NORMAL,
  253     METHOD_CAT_GSHAREDVT,
  254     METHOD_CAT_INST,
  255     METHOD_CAT_WRAPPER,
  256     METHOD_CAT_NUM
  257 } MethodCategory;
  258 
  259 typedef struct MonoAotStats {
  260     int ccount, mcount, lmfcount, abscount, gcount, ocount, genericcount;
  261     gint64 code_size, method_info_size, ex_info_size, unwind_info_size, got_size, class_info_size, got_info_size, plt_size, blob_size;
  262     int methods_without_got_slots, direct_calls, all_calls, llvm_count;
  263     int got_slots, offsets_size;
  264     int method_categories [METHOD_CAT_NUM];
  265     int got_slot_types [MONO_PATCH_INFO_NUM];
  266     int got_slot_info_sizes [MONO_PATCH_INFO_NUM];
  267     int jit_time, gen_time, link_time;
  268     int method_ref_count, method_ref_size;
  269     int class_ref_count, class_ref_size;
  270     int ginst_count, ginst_size;
  271 } MonoAotStats;
  272 
  273 typedef struct GotInfo {
  274     GHashTable *patch_to_got_offset;
  275     GHashTable **patch_to_got_offset_by_type;
  276     GPtrArray *got_patches;
  277 } GotInfo;
  278 
  279 #ifdef EMIT_WIN32_UNWIND_INFO
  280 typedef struct _UnwindInfoSectionCacheItem {
  281     char *xdata_section_label;
  282     PUNWIND_INFO unwind_info;
  283     gboolean xdata_section_emitted;
  284 } UnwindInfoSectionCacheItem;
  285 #endif
  286 
  287 typedef struct MonoAotCompile {
  288     MonoImage *image;
  289     GPtrArray *methods;
  290     GHashTable *method_indexes;
  291     GHashTable *method_depth;
  292     MonoCompile **cfgs;
  293     int cfgs_size;
  294     GHashTable **patch_to_plt_entry;
  295     GHashTable *plt_offset_to_entry;
  296     //GHashTable *patch_to_got_offset;
  297     //GHashTable **patch_to_got_offset_by_type;
  298     //GPtrArray *got_patches;
  299     GotInfo got_info, llvm_got_info;
  300     GHashTable *image_hash;
  301     GHashTable *method_to_cfg;
  302     GHashTable *token_info_hash;
  303     GHashTable *method_to_pinvoke_import;
  304     GHashTable *method_to_external_icall_symbol_name;
  305     GPtrArray *extra_methods;
  306     GPtrArray *image_table;
  307     GPtrArray *globals;
  308     GPtrArray *method_order;
  309     GHashTable *dedup_stats;
  310     GHashTable *dedup_cache;
  311     gboolean dedup_cache_changed;
  312     GHashTable *export_names;
  313     /* Maps MonoClass* -> blob offset */
  314     GHashTable *klass_blob_hash;
  315     /* Maps MonoMethod* -> blob offset */
  316     GHashTable *method_blob_hash;
  317     /* Maps MonoGenericInst* -> blob offset */
  318     GHashTable *ginst_blob_hash;
  319     GHashTable *gsharedvt_in_signatures;
  320     GHashTable *gsharedvt_out_signatures;
  321     guint32 *plt_got_info_offsets;
  322     guint32 got_offset, llvm_got_offset, plt_offset, plt_got_offset_base, nshared_got_entries;
  323     /* Number of GOT entries reserved for trampolines */
  324     guint32 num_trampoline_got_entries;
  325     guint32 tramp_page_size;
  326 
  327     guint32 table_offsets [MONO_AOT_TABLE_NUM];
  328     guint32 num_trampolines [MONO_AOT_TRAMP_NUM];
  329     guint32 trampoline_got_offset_base [MONO_AOT_TRAMP_NUM];
  330     guint32 trampoline_size [MONO_AOT_TRAMP_NUM];
  331     guint32 tramp_page_code_offsets [MONO_AOT_TRAMP_NUM];
  332 
  333     MonoAotOptions aot_opts;
  334     guint32 nmethods;
  335     int call_table_entry_size;
  336     guint32 nextra_methods;
  337     guint32 opts;
  338     guint32 simd_opts;
  339     MonoMemPool *mempool;
  340     MonoAotStats stats;
  341     int method_index;
  342     char *static_linking_symbol;
  343     mono_mutex_t mutex;
  344     gboolean gas_line_numbers;
  345     /* Whenever to emit an object file directly from llc */
  346     gboolean llvm_owriter;
  347     gboolean llvm_owriter_supported;
  348     MonoImageWriter *w;
  349     MonoDwarfWriter *dwarf;
  350     FILE *fp;
  351     char *tmpbasename;
  352     char *tmpfname;
  353     char *temp_dir_to_delete;
  354     char *llvm_sfile;
  355     char *llvm_ofile;
  356     GSList *cie_program;
  357     GHashTable *unwind_info_offsets;
  358     GPtrArray *unwind_ops;
  359     guint32 unwind_info_offset;
  360     char *global_prefix;
  361     char *got_symbol;
  362     char *llvm_got_symbol;
  363     char *plt_symbol;
  364     char *llvm_eh_frame_symbol;
  365     GHashTable *method_label_hash;
  366     const char *temp_prefix;
  367     const char *user_symbol_prefix;
  368     const char *llvm_label_prefix;
  369     const char *inst_directive;
  370     int align_pad_value;
  371     guint32 label_generator;
  372     gboolean llvm;
  373     gboolean has_jitted_code;
  374     gboolean is_full_aot;
  375     gboolean dedup_collect_only;
  376     MonoAotFileFlags flags;
  377     MonoDynamicStream blob;
  378     gboolean blob_closed;
  379     GHashTable *typespec_classes;
  380     GString *llc_args;
  381     GString *as_args;
  382     char *assembly_name_sym;
  383     GHashTable *plt_entry_debug_sym_cache;
  384     gboolean thumb_mixed, need_no_dead_strip, need_pt_gnu_stack;
  385     GHashTable *ginst_hash;
  386     GHashTable *dwarf_ln_filenames;
  387     gboolean global_symbols;
  388     int objc_selector_index, objc_selector_index_2;
  389     GPtrArray *objc_selectors;
  390     GHashTable *objc_selector_to_index;
  391     GList *profile_data;
  392     GHashTable *profile_methods;
  393 #ifdef EMIT_WIN32_UNWIND_INFO
  394     GList *unwind_info_section_cache;
  395 #endif
  396     FILE *logfile;
  397     FILE *instances_logfile;
  398     FILE *data_outfile;
  399     int datafile_offset;
  400     int gc_name_offset;
  401     // In this mode, we are emitting dedupable methods that we encounter
  402     gboolean dedup_emit_mode;
  403 } MonoAotCompile;
  404 
  405 typedef struct {
  406     int plt_offset;
  407     char *symbol, *llvm_symbol, *debug_sym;
  408     MonoJumpInfo *ji;
  409     gboolean jit_used, llvm_used;
  410 } MonoPltEntry;
  411 
  412 #define mono_acfg_lock(acfg) mono_os_mutex_lock (&((acfg)->mutex))
  413 #define mono_acfg_unlock(acfg) mono_os_mutex_unlock (&((acfg)->mutex))
  414 
  415 /* This points to the current acfg in LLVM mode */
  416 static MonoAotCompile *llvm_acfg;
  417 static MonoAotCompile *current_acfg;
  418 
  419 /* Cache of decoded method external icall symbol names. */
  420 /* Owned by acfg, but kept in this static as well since it is */
  421 /* accessed by code paths not having access to acfg. */
  422 static GHashTable *method_to_external_icall_symbol_name;
  423 
  424 // This, instead of an array of pointers, to optimize away a pointer and a relocation per string.
  425 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
  426 #define MSGSTRFIELD1(line) str##line
  427 static const struct msgstr_t {
  428 #define PATCH_INFO(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
  429 #include "patch-info.h"
  430 #undef PATCH_INFO
  431 } opstr = {
  432 #define PATCH_INFO(a,b) b,
  433 #include "patch-info.h"
  434 #undef PATCH_INFO
  435 };
  436 static const gint16 opidx [] = {
  437 #define PATCH_INFO(a,b) offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
  438 #include "patch-info.h"
  439 #undef PATCH_INFO
  440 };
  441 
  442 static G_GNUC_UNUSED const char*
  443 get_patch_name (int info)
  444 {
  445     return (const char*)&opstr + opidx [info];
  446 }
  447 
  448 static int
  449 emit_aot_image (MonoAotCompile *acfg);
  450 
  451 static void 
  452 mono_flush_method_cache (MonoAotCompile *acfg);
  453 
  454 static void 
  455 mono_read_method_cache (MonoAotCompile *acfg);
  456 
  457 static guint32
  458 get_unwind_info_offset (MonoAotCompile *acfg, guint8 *encoded, guint32 encoded_len);
  459 
  460 static char*
  461 get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache);
  462 
  463 static void
  464 add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean gsharedvt_in, gboolean gsharedvt_out, gboolean interp_in);
  465 
  466 static void
  467 add_profile_instances (MonoAotCompile *acfg, ProfileData *data);
  468 
  469 static gboolean
  470 ignore_cfg (MonoCompile *cfg)
  471 {
  472     return !cfg || cfg->skip;
  473 }
  474 
  475 static void
  476 aot_printf (MonoAotCompile *acfg, const gchar *format, ...)
  477 {
  478     FILE *output;
  479     va_list args;
  480 
  481     if (acfg->logfile)
  482         output = acfg->logfile;
  483     else
  484         output = stdout;
  485 
  486     va_start (args, format);
  487     vfprintf (output, format, args);
  488     va_end (args);
  489 }
  490 
  491 static void
  492 aot_printerrf (MonoAotCompile *acfg, const gchar *format, ...)
  493 {
  494     FILE *output;
  495     va_list args;
  496 
  497     if (acfg->logfile)
  498         output = acfg->logfile;
  499     else
  500         output = stderr;
  501 
  502     va_start (args, format);
  503     vfprintf (output, format, args);
  504     va_end (args);
  505 }
  506 
  507 static void
  508 report_loader_error (MonoAotCompile *acfg, MonoError *error, gboolean fatal, const char *format, ...)
  509 {
  510     FILE *output;
  511     va_list args;
  512 
  513     if (is_ok (error))
  514         return;
  515 
  516     if (acfg->logfile)
  517         output = acfg->logfile;
  518     else
  519         output = stderr;
  520 
  521     va_start (args, format);
  522     vfprintf (output, format, args);
  523     va_end (args);
  524     mono_error_cleanup (error);
  525 
  526     if (acfg->is_full_aot && fatal) {
  527         fprintf (output, "FullAOT cannot continue if there are loader errors.\n");
  528         exit (1);
  529     }
  530 }
  531 
  532 /* Wrappers around the image writer functions */
  533 
  534 #define MAX_SYMBOL_SIZE 256
  535 
  536 #if defined(TARGET_WIN32) && defined(TARGET_X86)
  537 static const char *
  538 mangle_symbol (const char * symbol, char * mangled_symbol, gsize length)
  539 {
  540     gsize needed_size = length;
  541 
  542     g_assert (NULL != symbol);
  543     g_assert (NULL != mangled_symbol);
  544     g_assert (0 != length);
  545 
  546     if (symbol && '_' != symbol [0]) {
  547         needed_size = g_snprintf (mangled_symbol, length, "_%s", symbol);
  548     } else {
  549         needed_size = g_snprintf (mangled_symbol, length, "%s", symbol);
  550     }
  551 
  552     g_assert (0 <= needed_size && needed_size < length);
  553     return mangled_symbol;
  554 }
  555 
  556 static char *
  557 mangle_symbol_alloc (const char * symbol)
  558 {
  559     g_assert (NULL != symbol);
  560 
  561     if (symbol && '_' != symbol [0]) {
  562         return g_strdup_printf ("_%s", symbol);
  563     }
  564     else {
  565         return g_strdup_printf ("%s", symbol);
  566     }
  567 }
  568 #endif
  569 
  570 static void
  571 emit_section_change (MonoAotCompile *acfg, const char *section_name, int subsection_index)
  572 {
  573     mono_img_writer_emit_section_change (acfg->w, section_name, subsection_index);
  574 }
  575 
  576 #if defined(TARGET_WIN32) && defined(TARGET_X86)
  577 
  578 static void
  579 emit_local_symbol (MonoAotCompile *acfg, const char *name, const char *end_label, gboolean func)
  580 {
  581     const char * mangled_symbol_name = name;
  582     char * mangled_symbol_name_alloc = NULL;
  583 
  584     if (TRUE == func) {
  585         mangled_symbol_name_alloc = mangle_symbol_alloc (name);
  586         mangled_symbol_name = mangled_symbol_name_alloc;
  587     }
  588 
  589     if (name != mangled_symbol_name && 0 != g_strcasecmp (name, mangled_symbol_name)) {
  590         mono_img_writer_emit_label (acfg->w, mangled_symbol_name);
  591     }
  592     mono_img_writer_emit_local_symbol (acfg->w, mangled_symbol_name, end_label, func);
  593 
  594     if (NULL != mangled_symbol_name_alloc) {
  595         g_free (mangled_symbol_name_alloc);
  596     }
  597 }
  598 
  599 #else
  600 
  601 static void
  602 emit_local_symbol (MonoAotCompile *acfg, const char *name, const char *end_label, gboolean func) 
  603 { 
  604     mono_img_writer_emit_local_symbol (acfg->w, name, end_label, func);
  605 }
  606 
  607 #endif
  608 
  609 static void
  610 emit_label (MonoAotCompile *acfg, const char *name) 
  611 { 
  612     mono_img_writer_emit_label (acfg->w, name); 
  613 }
  614 
  615 static void
  616 emit_bytes (MonoAotCompile *acfg, const guint8* buf, int size) 
  617 { 
  618     mono_img_writer_emit_bytes (acfg->w, buf, size); 
  619 }
  620 
  621 static void
  622 emit_string (MonoAotCompile *acfg, const char *value) 
  623 { 
  624     mono_img_writer_emit_string (acfg->w, value); 
  625 }
  626 
  627 static void
  628 emit_line (MonoAotCompile *acfg) 
  629 { 
  630     mono_img_writer_emit_line (acfg->w); 
  631 }
  632 
  633 static void
  634 emit_alignment (MonoAotCompile *acfg, int size)
  635 { 
  636     mono_img_writer_emit_alignment (acfg->w, size);
  637 }
  638 
  639 static void
  640 emit_alignment_code (MonoAotCompile *acfg, int size)
  641 {
  642     if (acfg->align_pad_value)
  643         mono_img_writer_emit_alignment_fill (acfg->w, size, acfg->align_pad_value);
  644     else
  645         mono_img_writer_emit_alignment (acfg->w, size);
  646 }
  647 
  648 static void
  649 emit_padding (MonoAotCompile *acfg, int size)
  650 {
  651     int i;
  652     guint8 buf [16];
  653 
  654     if (acfg->align_pad_value) {
  655         for (i = 0; i < 16; ++i)
  656             buf [i] = acfg->align_pad_value;
  657     } else {
  658         memset (buf, 0, sizeof (buf));
  659     }
  660 
  661     for (i = 0; i < size; i += 16) {
  662         if (size - i < 16)
  663             emit_bytes (acfg, buf, size - i);
  664         else
  665             emit_bytes (acfg, buf, 16);
  666     }
  667 }
  668 
  669 static void
  670 emit_pointer (MonoAotCompile *acfg, const char *target) 
  671 { 
  672     mono_img_writer_emit_pointer (acfg->w, target); 
  673 }
  674 
  675 static void
  676 emit_pointer_2 (MonoAotCompile *acfg, const char *prefix, const char *target) 
  677 { 
  678     if (prefix [0] != '\0') {
  679         char *s = g_strdup_printf ("%s%s", prefix, target);
  680         mono_img_writer_emit_pointer (acfg->w, s);
  681         g_free (s);
  682     } else {
  683         mono_img_writer_emit_pointer (acfg->w, target);
  684     }
  685 }
  686 
  687 static void
  688 emit_int16 (MonoAotCompile *acfg, int value) 
  689 { 
  690     mono_img_writer_emit_int16 (acfg->w, value); 
  691 }
  692 
  693 static void
  694 emit_int32 (MonoAotCompile *acfg, int value) 
  695 { 
  696     mono_img_writer_emit_int32 (acfg->w, value); 
  697 }
  698 
  699 static void
  700 emit_symbol_diff (MonoAotCompile *acfg, const char *end, const char* start, int offset) 
  701 { 
  702     mono_img_writer_emit_symbol_diff (acfg->w, end, start, offset); 
  703 }
  704 
  705 static void
  706 emit_zero_bytes (MonoAotCompile *acfg, int num) 
  707 { 
  708     mono_img_writer_emit_zero_bytes (acfg->w, num); 
  709 }
  710 
  711 static void
  712 emit_byte (MonoAotCompile *acfg, guint8 val) 
  713 { 
  714     mono_img_writer_emit_byte (acfg->w, val); 
  715 }
  716 
  717 #if defined(TARGET_WIN32) && defined(TARGET_X86)
  718 
  719 static G_GNUC_UNUSED void
  720 emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
  721 {
  722     const char * mangled_symbol_name = name;
  723     char * mangled_symbol_name_alloc = NULL;
  724 
  725     mangled_symbol_name_alloc = mangle_symbol_alloc (name);
  726     mangled_symbol_name = mangled_symbol_name_alloc;
  727     
  728     if (0 != g_strcasecmp (name, mangled_symbol_name)) {
  729         mono_img_writer_emit_label (acfg->w, mangled_symbol_name);
  730     }
  731     mono_img_writer_emit_global (acfg->w, mangled_symbol_name, func);
  732 
  733     if (NULL != mangled_symbol_name_alloc) {
  734         g_free (mangled_symbol_name_alloc);
  735     }
  736 }
  737 
  738 #else
  739 
  740 static G_GNUC_UNUSED void
  741 emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
  742 {
  743     mono_img_writer_emit_global (acfg->w, name, func);
  744 }
  745 
  746 #endif
  747 
  748 #ifdef TARGET_WIN32_MSVC
  749 static gboolean
  750 link_shared_library (MonoAotCompile *acfg)
  751 {
  752     return !acfg->aot_opts.static_link && !acfg->aot_opts.asm_only;
  753 }
  754 #endif
  755 
  756 static gboolean
  757 add_to_global_symbol_table (MonoAotCompile *acfg)
  758 {
  759 #ifdef TARGET_WIN32_MSVC
  760     return acfg->aot_opts.no_dlsym || link_shared_library (acfg);
  761 #else
  762     return acfg->aot_opts.no_dlsym;
  763 #endif
  764 }
  765 
  766 static void
  767 emit_global (MonoAotCompile *acfg, const char *name, gboolean func)
  768 {
  769     if (add_to_global_symbol_table (acfg))
  770         g_ptr_array_add (acfg->globals, g_strdup (name));
  771 
  772     if (acfg->aot_opts.no_dlsym) {
  773         mono_img_writer_emit_local_symbol (acfg->w, name, NULL, func);
  774     } else {
  775         emit_global_inner (acfg, name, func);
  776     }
  777 }
  778 
  779 static void
  780 emit_symbol_size (MonoAotCompile *acfg, const char *name, const char *end_label)
  781 {
  782     mono_img_writer_emit_symbol_size (acfg->w, name, end_label);
  783 }
  784 
  785 /* Emit a symbol which is referenced by the MonoAotFileInfo structure */
  786 static void
  787 emit_info_symbol (MonoAotCompile *acfg, const char *name, gboolean func)
  788 {
  789     char symbol [MAX_SYMBOL_SIZE];
  790 
  791     if (acfg->llvm) {
  792         emit_label (acfg, name);
  793         /* LLVM generated code references this */
  794         sprintf (symbol, "%s%s%s", acfg->user_symbol_prefix, acfg->global_prefix, name);
  795         emit_label (acfg, symbol);
  796 
  797 #ifndef TARGET_WIN32_MSVC
  798         emit_global_inner (acfg, symbol, FALSE);
  799 #else
  800         emit_global_inner (acfg, symbol, func);
  801 #endif
  802     } else {
  803         emit_label (acfg, name);
  804     }
  805 }
  806 
  807 static void
  808 emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
  809 {
  810     if (acfg->llvm) {
  811         mono_llvm_emit_aot_data (name, (guint8*)value, strlen (value) + 1);
  812         return;
  813     }
  814 
  815     mono_img_writer_emit_section_change (acfg->w, RODATA_SECT, 1);
  816 #ifdef TARGET_MACH
  817     /* On apple, all symbols need to be aligned to avoid warnings from ld */
  818     emit_alignment (acfg, 4);
  819 #endif
  820     mono_img_writer_emit_label (acfg->w, name);
  821     mono_img_writer_emit_string (acfg->w, value);
  822 }
  823 
  824 static G_GNUC_UNUSED void
  825 emit_uleb128 (MonoAotCompile *acfg, guint32 value)
  826 {
  827     do {
  828         guint8 b = value & 0x7f;
  829         value >>= 7;
  830         if (value != 0) /* more bytes to come */
  831             b |= 0x80;
  832         emit_byte (acfg, b);
  833     } while (value);
  834 }
  835 
  836 static G_GNUC_UNUSED void
  837 emit_sleb128 (MonoAotCompile *acfg, gint64 value)
  838 {
  839     gboolean more = 1;
  840     gboolean negative = (value < 0);
  841     guint32 size = 64;
  842     guint8 byte;
  843 
  844     while (more) {
  845         byte = value & 0x7f;
  846         value >>= 7;
  847         /* the following is unnecessary if the
  848          * implementation of >>= uses an arithmetic rather
  849          * than logical shift for a signed left operand
  850          */
  851         if (negative)
  852             /* sign extend */
  853             value |= - ((gint64)1 <<(size - 7));
  854         /* sign bit of byte is second high order bit (0x40) */
  855         if ((value == 0 && !(byte & 0x40)) ||
  856             (value == -1 && (byte & 0x40)))
  857             more = 0;
  858         else
  859             byte |= 0x80;
  860         emit_byte (acfg, byte);
  861     }
  862 }
  863 
  864 static G_GNUC_UNUSED void
  865 encode_uleb128 (guint32 value, guint8 *buf, guint8 **endbuf)
  866 {
  867     guint8 *p = buf;
  868 
  869     do {
  870         guint8 b = value & 0x7f;
  871         value >>= 7;
  872         if (value != 0) /* more bytes to come */
  873             b |= 0x80;
  874         *p ++ = b;
  875     } while (value);
  876 
  877     *endbuf = p;
  878 }
  879 
  880 static G_GNUC_UNUSED void
  881 encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
  882 {
  883     gboolean more = 1;
  884     gboolean negative = (value < 0);
  885     guint32 size = 32;
  886     guint8 byte;
  887     guint8 *p = buf;
  888 
  889     while (more) {
  890         byte = value & 0x7f;
  891         value >>= 7;
  892         /* the following is unnecessary if the
  893          * implementation of >>= uses an arithmetic rather
  894          * than logical shift for a signed left operand
  895          */
  896         if (negative)
  897             /* sign extend */
  898             value |= - (1 <<(size - 7));
  899         /* sign bit of byte is second high order bit (0x40) */
  900         if ((value == 0 && !(byte & 0x40)) ||
  901             (value == -1 && (byte & 0x40)))
  902             more = 0;
  903         else
  904             byte |= 0x80;
  905         *p ++= byte;
  906     }
  907 
  908     *endbuf = p;
  909 }
  910 
  911 static void
  912 encode_int (gint32 val, guint8 *buf, guint8 **endbuf)
  913 {
  914     // FIXME: Big-endian
  915     buf [0] = (val >> 0) & 0xff;
  916     buf [1] = (val >> 8) & 0xff;
  917     buf [2] = (val >> 16) & 0xff;
  918     buf [3] = (val >> 24) & 0xff;
  919 
  920     *endbuf = buf + 4;
  921 }
  922 
  923 static void
  924 encode_int16 (guint16 val, guint8 *buf, guint8 **endbuf)
  925 {
  926     buf [0] = (val >> 0) & 0xff;
  927     buf [1] = (val >> 8) & 0xff;
  928 
  929     *endbuf = buf + 2;
  930 }
  931 
  932 static void
  933 encode_string (const char *s, guint8 *buf, guint8 **endbuf)
  934 {
  935     int len = strlen (s);
  936 
  937     memcpy (buf, s, len + 1);
  938     *endbuf = buf + len + 1;
  939 }
  940 
  941 static void
  942 emit_unset_mode (MonoAotCompile *acfg)
  943 {
  944     mono_img_writer_emit_unset_mode (acfg->w);
  945 }
  946 
  947 static G_GNUC_UNUSED void
  948 emit_set_thumb_mode (MonoAotCompile *acfg)
  949 {
  950     emit_unset_mode (acfg);
  951     fprintf (acfg->fp, ".code 16\n");
  952 }
  953 
  954 static G_GNUC_UNUSED void
  955 emit_set_arm_mode (MonoAotCompile *acfg)
  956 {
  957     emit_unset_mode (acfg);
  958     fprintf (acfg->fp, ".code 32\n");
  959 }
  960 
  961 static void
  962 emit_code_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
  963 {
  964 #ifdef TARGET_ARM64
  965     int i;
  966 
  967     g_assert (size % 4 == 0);
  968     emit_unset_mode (acfg);
  969     for (i = 0; i < size; i += 4)
  970         fprintf (acfg->fp, "%s 0x%x\n", acfg->inst_directive, *(guint32*)(buf + i));
  971 #else
  972     emit_bytes (acfg, buf, size);
  973 #endif
  974 }
  975 
  976 /* ARCHITECTURE SPECIFIC CODE */
  977 
  978 #if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_POWERPC) || defined(TARGET_ARM64) || defined (TARGET_RISCV)
  979 #define EMIT_DWARF_INFO 1
  980 #endif
  981 
  982 #ifdef TARGET_WIN32_MSVC
  983 #undef EMIT_DWARF_INFO
  984 #define EMIT_WIN32_CODEVIEW_INFO
  985 #endif
  986 
  987 #ifdef EMIT_WIN32_UNWIND_INFO
  988 static UnwindInfoSectionCacheItem *
  989 get_cached_unwind_info_section_item_win32 (MonoAotCompile *acfg, const char *function_start, const char *function_end, GSList *unwind_ops);
  990 
  991 static void
  992 free_unwind_info_section_cache_win32 (MonoAotCompile *acfg);
  993 
  994 static void
  995 emit_unwind_info_data_win32 (MonoAotCompile *acfg, PUNWIND_INFO unwind_info);
  996 
  997 static void
  998 emit_unwind_info_sections_win32 (MonoAotCompile *acfg, const char *function_start, const char *function_end, GSList *unwind_ops);
  999 #endif
 1000 
 1001 static void
 1002 arch_free_unwind_info_section_cache (MonoAotCompile *acfg)
 1003 {
 1004 #ifdef EMIT_WIN32_UNWIND_INFO
 1005     free_unwind_info_section_cache_win32 (acfg);
 1006 #endif
 1007 }
 1008 
 1009 static void
 1010 arch_emit_unwind_info_sections (MonoAotCompile *acfg, const char *function_start, const char *function_end, GSList *unwind_ops)
 1011 {
 1012 #ifdef EMIT_WIN32_UNWIND_INFO
 1013     gboolean own_unwind_ops = FALSE;
 1014     if (!unwind_ops) {
 1015         unwind_ops = mono_unwind_get_cie_program ();
 1016         own_unwind_ops = TRUE;
 1017     }
 1018 
 1019     emit_unwind_info_sections_win32 (acfg, function_start, function_end, unwind_ops);
 1020 
 1021     if (own_unwind_ops)
 1022         mono_free_unwind_info (unwind_ops);
 1023 #endif
 1024 }
 1025 
 1026 #if defined(TARGET_ARM)
 1027 #define AOT_FUNC_ALIGNMENT 4
 1028 #else
 1029 #define AOT_FUNC_ALIGNMENT 16
 1030 #endif
 1031  
 1032 #if defined(TARGET_POWERPC64) && !defined(MONO_ARCH_ILP32)
 1033 #define PPC_LD_OP "ld"
 1034 #define PPC_LDX_OP "ldx"
 1035 #else
 1036 #define PPC_LD_OP "lwz"
 1037 #define PPC_LDX_OP "lwzx"
 1038 #endif
 1039 
 1040 #ifdef TARGET_X86_64_WIN32_MSVC
 1041 #define AOT_TARGET_STR "AMD64 (WIN32) (MSVC codegen)"
 1042 #elif TARGET_AMD64
 1043 #define AOT_TARGET_STR "AMD64"
 1044 #endif
 1045 
 1046 #ifdef TARGET_ARM
 1047 #ifdef TARGET_MACH
 1048 #define AOT_TARGET_STR "ARM (MACH)"
 1049 #else
 1050 #define AOT_TARGET_STR "ARM (!MACH)"
 1051 #endif
 1052 #endif
 1053 
 1054 #ifdef TARGET_ARM64
 1055 #ifdef TARGET_MACH
 1056 #define AOT_TARGET_STR "ARM64 (MACH)"
 1057 #else
 1058 #define AOT_TARGET_STR "ARM64 (!MACH)"
 1059 #endif
 1060 #endif
 1061 
 1062 #ifdef TARGET_POWERPC64
 1063 #ifdef MONO_ARCH_ILP32
 1064 #define AOT_TARGET_STR "POWERPC64 (mono ilp32)"
 1065 #else
 1066 #define AOT_TARGET_STR "POWERPC64 (!mono ilp32)"
 1067 #endif
 1068 #else
 1069 #ifdef TARGET_POWERPC
 1070 #ifdef MONO_ARCH_ILP32
 1071 #define AOT_TARGET_STR "POWERPC (mono ilp32)"
 1072 #else
 1073 #define AOT_TARGET_STR "POWERPC (!mono ilp32)"
 1074 #endif
 1075 #endif
 1076 #endif
 1077 
 1078 #ifdef TARGET_RISCV32
 1079 #define AOT_TARGET_STR "RISCV32"
 1080 #endif
 1081 
 1082 #ifdef TARGET_RISCV64
 1083 #define AOT_TARGET_STR "RISCV64"
 1084 #endif
 1085 
 1086 #ifdef TARGET_X86
 1087 #ifdef TARGET_WIN32
 1088 #define AOT_TARGET_STR "X86 (WIN32)"
 1089 #else
 1090 #define AOT_TARGET_STR "X86"
 1091 #endif
 1092 #endif
 1093 
 1094 #ifndef AOT_TARGET_STR
 1095 #define AOT_TARGET_STR ""
 1096 #endif
 1097 
 1098 static void
 1099 arch_init (MonoAotCompile *acfg)
 1100 {
 1101     acfg->llc_args = g_string_new ("");
 1102     acfg->as_args = g_string_new ("");
 1103     acfg->llvm_owriter_supported = TRUE;
 1104 
 1105     /*
 1106      * The prefix LLVM likes to put in front of symbol names on darwin.
 1107      * The mach-os specs require this for globals, but LLVM puts them in front of all
 1108      * symbols. We need to handle this, since we need to refer to LLVM generated
 1109      * symbols.
 1110      */
 1111     acfg->llvm_label_prefix = "";
 1112     acfg->user_symbol_prefix = "";
 1113 
 1114 #if TARGET_X86 || TARGET_AMD64
 1115     const gboolean has_custom_args = !!acfg->aot_opts.llvm_llc || acfg->aot_opts.use_current_cpu;
 1116 #endif
 1117 
 1118 #if defined(TARGET_X86)
 1119     g_string_append_printf (acfg->llc_args, " -march=x86 %s", has_custom_args ? "" : "-mcpu=generic");
 1120 #endif
 1121 
 1122 #if defined(TARGET_AMD64)
 1123     g_string_append_printf (acfg->llc_args, " -march=x86-64 %s", has_custom_args ? "" : "-mcpu=generic");
 1124     /* NOP */
 1125     acfg->align_pad_value = 0x90;
 1126 #endif
 1127     g_string_append (acfg->llc_args, " -enable-implicit-null-checks -disable-fault-maps");
 1128 
 1129     if (mono_use_fast_math) {
 1130         // same parameters are passed to opt and LLVM JIT
 1131         g_string_append (acfg->llc_args, " -fp-contract=fast -enable-no-infs-fp-math -enable-no-nans-fp-math -enable-no-signed-zeros-fp-math -enable-no-trapping-fp-math -enable-unsafe-fp-math");
 1132     }
 1133 
 1134 #ifdef TARGET_ARM
 1135     if (acfg->aot_opts.mtriple && strstr (acfg->aot_opts.mtriple, "darwin")) {
 1136         g_string_append (acfg->llc_args, "-mattr=+v6");
 1137     } else {
 1138         if (!acfg->aot_opts.mtriple) {
 1139             g_string_append (acfg->llc_args, " -march=arm");
 1140         } else {
 1141             /* arch will be defined via mtriple, e.g. armv7s-ios or thumb. */
 1142 
 1143             if (strstr (acfg->aot_opts.mtriple, "ios")) {
 1144                 g_string_append (acfg->llc_args, " -mattr=+v7");
 1145                 g_string_append (acfg->llc_args, " -exception-model=dwarf -disable-fp-elim");
 1146             }
 1147         }
 1148 
 1149 #if defined(ARM_FPU_VFP_HARD)
 1150         g_string_append (acfg->llc_args, " -mattr=+vfp2,-neon,+d16 -float-abi=hard");
 1151         g_string_append (acfg->as_args, " -mfpu=vfp3");
 1152 #elif defined(ARM_FPU_VFP)
 1153         g_string_append (acfg->llc_args, " -mattr=+vfp2,-neon,+d16");
 1154         g_string_append (acfg->as_args, " -mfpu=vfp3");
 1155 #else
 1156         g_string_append (acfg->llc_args, " -mattr=+soft-float");
 1157 #endif
 1158     }
 1159     if (acfg->aot_opts.mtriple && strstr (acfg->aot_opts.mtriple, "thumb"))
 1160         acfg->thumb_mixed = TRUE;
 1161 
 1162     if (acfg->aot_opts.mtriple)
 1163         mono_arch_set_target (acfg->aot_opts.mtriple);
 1164 #endif
 1165 
 1166 #ifdef TARGET_ARM64
 1167     g_string_append (acfg->llc_args, " -march=aarch64");
 1168     acfg->inst_directive = ".inst";
 1169     if (acfg->aot_opts.mtriple)
 1170         mono_arch_set_target (acfg->aot_opts.mtriple);
 1171 #endif
 1172 
 1173 #ifdef TARGET_MACH
 1174     acfg->user_symbol_prefix = "_";
 1175     acfg->llvm_label_prefix = "_";
 1176     acfg->inst_directive = ".word";
 1177     acfg->need_no_dead_strip = TRUE;
 1178     acfg->aot_opts.gnu_asm = TRUE;
 1179 #endif
 1180 
 1181 #if defined(__linux__) && !defined(TARGET_ARM)
 1182     acfg->need_pt_gnu_stack = TRUE;
 1183 #endif
 1184 
 1185 #ifdef TARGET_RISCV
 1186     if (acfg->aot_opts.mtriple)
 1187         mono_arch_set_target (acfg->aot_opts.mtriple);
 1188 
 1189 #ifdef TARGET_RISCV64
 1190 
 1191     g_string_append (acfg->as_args, " -march=rv64i ");
 1192 #ifdef RISCV_FPABI_DOUBLE
 1193     g_string_append (acfg->as_args, " -mabi=lp64d");
 1194 #else
 1195     g_string_append (acfg->as_args, " -mabi=lp64");
 1196 #endif
 1197 
 1198 #else
 1199 
 1200     g_string_append (acfg->as_args, " -march=rv32i ");
 1201 #ifdef RISCV_FPABI_DOUBLE
 1202     g_string_append (acfg->as_args, " -mabi=ilp32d ");
 1203 #else
 1204     g_string_append (acfg->as_args, " -mabi=ilp32 ");
 1205 #endif
 1206 
 1207 #endif
 1208 
 1209 #endif
 1210 
 1211 #ifdef MONOTOUCH
 1212     acfg->global_symbols = TRUE;
 1213 #endif
 1214 
 1215 #ifdef TARGET_ANDROID
 1216     acfg->llvm_owriter_supported = FALSE;
 1217 #endif
 1218 }
 1219 
 1220 #ifdef TARGET_ARM64
 1221 
 1222 
 1223 /* Load the contents of GOT_SLOT into dreg, clobbering ip0 */
 1224 /* Must emit 12 bytes of instructions */
 1225 static void
 1226 arm64_emit_load_got_slot (MonoAotCompile *acfg, int dreg, int got_slot)
 1227 {
 1228     int offset;
 1229 
 1230     g_assert (acfg->fp);
 1231     emit_unset_mode (acfg);
 1232     /* r16==ip0 */
 1233     offset = (int)(got_slot * TARGET_SIZEOF_VOID_P);
 1234 #ifdef TARGET_MACH
 1235     /* clang's integrated assembler */
 1236     fprintf (acfg->fp, "adrp x16, %s@PAGE+%d\n", acfg->got_symbol, offset & 0xfffff000);
 1237 #ifdef MONO_ARCH_ILP32
 1238     fprintf (acfg->fp, "add x16, x16, %s@PAGEOFF+%d\n", acfg->got_symbol, offset & 0xfff);
 1239     fprintf (acfg->fp, "ldr w%d, [x16, #%d]\n", dreg, 0);
 1240 #else
 1241     fprintf (acfg->fp, "add x16, x16, %s@PAGEOFF\n", acfg->got_symbol);
 1242     fprintf (acfg->fp, "ldr x%d, [x16, #%d]\n", dreg, offset & 0xfff);
 1243 #endif
 1244 #else
 1245     /* Linux GAS */
 1246     fprintf (acfg->fp, "adrp x16, %s+%d\n", acfg->got_symbol, offset & 0xfffff000);
 1247     fprintf (acfg->fp, "add x16, x16, :lo12:%s\n", acfg->got_symbol);
 1248     fprintf (acfg->fp, "ldr x%d, [x16, %d]\n", dreg, offset & 0xfff);
 1249 #endif
 1250 }
 1251 
 1252 static void
 1253 arm64_emit_objc_selector_ref (MonoAotCompile *acfg, guint8 *code, int index, int *code_size)
 1254 {
 1255     int reg;
 1256 
 1257     g_assert (acfg->fp);
 1258     emit_unset_mode (acfg);
 1259 
 1260     /* ldr rt, target */
 1261     reg = arm_get_ldr_lit_reg (code);
 1262 
 1263     fprintf (acfg->fp, "adrp x%d, L_OBJC_SELECTOR_REFERENCES_%d@PAGE\n", reg, index);
 1264     fprintf (acfg->fp, "add x%d, x%d, L_OBJC_SELECTOR_REFERENCES_%d@PAGEOFF\n", reg, reg, index);
 1265     fprintf (acfg->fp, "ldr x%d, [x%d]\n", reg, reg);
 1266 
 1267     *code_size = 12;
 1268 }
 1269 
 1270 static void
 1271 arm64_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, gboolean thumb, MonoJumpInfo *ji, int *call_size)
 1272 {
 1273     g_assert (acfg->fp);
 1274     emit_unset_mode (acfg);
 1275     if (ji && ji->relocation == MONO_R_ARM64_B) {
 1276         fprintf (acfg->fp, "b %s\n", target);
 1277     } else {
 1278         if (ji)
 1279             g_assert (ji->relocation == MONO_R_ARM64_BL);
 1280         fprintf (acfg->fp, "bl %s\n", target);
 1281     }
 1282     *call_size = 4;
 1283 }
 1284 
 1285 static void
 1286 arm64_emit_got_access (MonoAotCompile *acfg, guint8 *code, int got_slot, int *code_size)
 1287 {
 1288     int reg;
 1289 
 1290     /* ldr rt, target */
 1291     reg = arm_get_ldr_lit_reg (code);
 1292     arm64_emit_load_got_slot (acfg, reg, got_slot);
 1293     *code_size = 12;
 1294 }
 1295 
 1296 static void
 1297 arm64_emit_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offset, int info_offset)
 1298 {
 1299     arm64_emit_load_got_slot (acfg, ARMREG_R16, offset / sizeof (target_mgreg_t));
 1300     fprintf (acfg->fp, "br x16\n");
 1301     /* Used by mono_aot_get_plt_info_offset () */
 1302     fprintf (acfg->fp, "%s %d\n", acfg->inst_directive, info_offset);
 1303 }
 1304 
 1305 static void
 1306 arm64_emit_tramp_page_common_code (MonoAotCompile *acfg, int pagesize, int arg_reg, int *size)
 1307 {
 1308     guint8 buf [256];
 1309     guint8 *code;
 1310     int imm;
 1311 
 1312     /* The common code */
 1313     code = buf;
 1314     imm = pagesize;
 1315     /* The trampoline address is in IP0 */
 1316     arm_movzx (code, ARMREG_IP1, imm & 0xffff, 0);
 1317     arm_movkx (code, ARMREG_IP1, (imm >> 16) & 0xffff, 16);
 1318     /* Compute the data slot address */
 1319     arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
 1320     /* Trampoline argument */
 1321     arm_ldrp (code, arg_reg, ARMREG_IP0, 0);
 1322     /* Address */
 1323     arm_ldrp (code, ARMREG_IP0, ARMREG_IP0, TARGET_SIZEOF_VOID_P);
 1324     arm_brx (code, ARMREG_IP0);
 1325 
 1326     /* Emit it */
 1327     emit_code_bytes (acfg, buf, code - buf);
 1328 
 1329     *size = code - buf;
 1330 }
 1331 
 1332 static void
 1333 arm64_emit_tramp_page_specific_code (MonoAotCompile *acfg, int pagesize, int common_tramp_size, int specific_tramp_size)
 1334 {
 1335     guint8 buf [256];
 1336     guint8 *code;
 1337     int i, count;
 1338 
 1339     count = (pagesize - common_tramp_size) / specific_tramp_size;
 1340     for (i = 0; i < count; ++i) {
 1341         code = buf;
 1342         arm_adrx (code, ARMREG_IP0, code);
 1343         /* Branch to the generic code */
 1344         arm_b (code, code - 4 - (i * specific_tramp_size) - common_tramp_size);
 1345 #ifndef MONO_ARCH_ILP32
 1346         /* This has to be 2 pointers long */
 1347         arm_nop (code);
 1348         arm_nop (code);
 1349 #endif
 1350         g_assert (code - buf == specific_tramp_size);
 1351         emit_code_bytes (acfg, buf, code - buf);
 1352     }
 1353 }
 1354 
 1355 static void
 1356 arm64_emit_specific_trampoline_pages (MonoAotCompile *acfg)
 1357 {
 1358     guint8 buf [128];
 1359     guint8 *code;
 1360     guint8 *labels [16];
 1361     int common_tramp_size;
 1362     int specific_tramp_size = 2 * TARGET_SIZEOF_VOID_P;
 1363     int imm, pagesize;
 1364     char symbol [128];
 1365 
 1366     if (!acfg->aot_opts.use_trampolines_page)
 1367         return;
 1368 
 1369 #ifdef TARGET_MACH
 1370     /* Have to match the target pagesize */
 1371     pagesize = 16384;
 1372 #else
 1373     pagesize = mono_pagesize ();
 1374 #endif
 1375     acfg->tramp_page_size = pagesize;
 1376 
 1377     /* The specific trampolines */
 1378     sprintf (symbol, "%sspecific_trampolines_page", acfg->user_symbol_prefix);
 1379     emit_alignment (acfg, pagesize);
 1380     emit_global (acfg, symbol, TRUE);
 1381     emit_label (acfg, symbol);
 1382 
 1383     /* The common code */
 1384     arm64_emit_tramp_page_common_code (acfg, pagesize, ARMREG_IP1, &common_tramp_size);
 1385     acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_SPECIFIC] = common_tramp_size;
 1386 
 1387     arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
 1388 
 1389     /* The rgctx trampolines */
 1390     /* These are the same as the specific trampolines, but they load the argument into MONO_ARCH_RGCTX_REG */
 1391     sprintf (symbol, "%srgctx_trampolines_page", acfg->user_symbol_prefix);
 1392     emit_alignment (acfg, pagesize);
 1393     emit_global (acfg, symbol, TRUE);
 1394     emit_label (acfg, symbol);
 1395 
 1396     /* The common code */
 1397     arm64_emit_tramp_page_common_code (acfg, pagesize, MONO_ARCH_RGCTX_REG, &common_tramp_size);
 1398     acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = common_tramp_size;
 1399 
 1400     arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
 1401 
 1402     /* The gsharedvt arg trampolines */
 1403     /* These are the same as the specific trampolines */
 1404     sprintf (symbol, "%sgsharedvt_arg_trampolines_page", acfg->user_symbol_prefix);
 1405     emit_alignment (acfg, pagesize);
 1406     emit_global (acfg, symbol, TRUE);
 1407     emit_label (acfg, symbol);
 1408 
 1409     arm64_emit_tramp_page_common_code (acfg, pagesize, ARMREG_IP1, &common_tramp_size);
 1410     acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = common_tramp_size;
 1411 
 1412     arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
 1413 
 1414     /* Unbox arbitrary trampolines */
 1415     sprintf (symbol, "%sunbox_arbitrary_trampolines_page", acfg->user_symbol_prefix);
 1416     emit_alignment (acfg, pagesize);
 1417     emit_global (acfg, symbol, TRUE);
 1418     emit_label (acfg, symbol);
 1419 
 1420     code = buf;
 1421     imm = pagesize;
 1422 
 1423     /* Unbox this arg */
 1424     arm_addx_imm (code, ARMREG_R0, ARMREG_R0, MONO_ABI_SIZEOF (MonoObject));
 1425 
 1426     /* The trampoline address is in IP0 */
 1427     arm_movzx (code, ARMREG_IP1, imm & 0xffff, 0);
 1428     arm_movkx (code, ARMREG_IP1, (imm >> 16) & 0xffff, 16);
 1429     /* Compute the data slot address */
 1430     arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
 1431     /* Address */
 1432     arm_ldrp (code, ARMREG_IP0, ARMREG_IP0, 0);
 1433     arm_brx (code, ARMREG_IP0);
 1434 
 1435     /* Emit it */
 1436     emit_code_bytes (acfg, buf, code - buf);
 1437 
 1438     common_tramp_size = code - buf;
 1439     acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_UNBOX_ARBITRARY] = common_tramp_size;
 1440 
 1441     arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
 1442 
 1443     /* The IMT trampolines */
 1444     sprintf (symbol, "%simt_trampolines_page", acfg->user_symbol_prefix);
 1445     emit_alignment (acfg, pagesize);
 1446     emit_global (acfg, symbol, TRUE);
 1447     emit_label (acfg, symbol);
 1448 
 1449     code = buf;
 1450     imm = pagesize;
 1451     /* The trampoline address is in IP0 */
 1452     arm_movzx (code, ARMREG_IP1, imm & 0xffff, 0);
 1453     arm_movkx (code, ARMREG_IP1, (imm >> 16) & 0xffff, 16);
 1454     /* Compute the data slot address */
 1455     arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
 1456     /* Trampoline argument */
 1457     arm_ldrp (code, ARMREG_IP1, ARMREG_IP0, 0);
 1458 
 1459     /* Same as arch_emit_imt_trampoline () */
 1460     labels [0] = code;
 1461     arm_ldrp (code, ARMREG_IP0, ARMREG_IP1, 0);
 1462     arm_cmpp (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
 1463     labels [1] = code;
 1464     arm_bcc (code, ARMCOND_EQ, 0);
 1465 
 1466     /* End-of-loop check */
 1467     labels [2] = code;
 1468     arm_cbzx (code, ARMREG_IP0, 0);
 1469 
 1470     /* Loop footer */
 1471     arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 2 * TARGET_SIZEOF_VOID_P);
 1472     arm_b (code, labels [0]);
 1473 
 1474     /* Match */
 1475     mono_arm_patch (labels [1], code, MONO_R_ARM64_BCC);
 1476     /* Load vtable slot addr */
 1477     arm_ldrp (code, ARMREG_IP0, ARMREG_IP1, TARGET_SIZEOF_VOID_P);
 1478     /* Load vtable slot */
 1479     arm_ldrp (code, ARMREG_IP0, ARMREG_IP0, 0);
 1480     arm_brx (code, ARMREG_IP0);
 1481 
 1482     /* No match */
 1483     mono_arm_patch (labels [2], code, MONO_R_ARM64_CBZ);
 1484     /* Load fail addr */
 1485     arm_ldrp (code, ARMREG_IP0, ARMREG_IP1, TARGET_SIZEOF_VOID_P);
 1486     arm_brx (code, ARMREG_IP0);
 1487 
 1488     emit_code_bytes (acfg, buf, code - buf);
 1489 
 1490     common_tramp_size = code - buf;
 1491     acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT] = common_tramp_size;
 1492 
 1493     arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
 1494 }
 1495 
 1496 static void
 1497 arm64_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 1498 {
 1499     /* Load argument from second GOT slot */
 1500     arm64_emit_load_got_slot (acfg, ARMREG_R17, offset + 1);
 1501     /* Load generic trampoline address from first GOT slot */
 1502     arm64_emit_load_got_slot (acfg, ARMREG_R16, offset);
 1503     fprintf (acfg->fp, "br x16\n");
 1504     *tramp_size = 7 * 4;
 1505 }
 1506 
 1507 static void
 1508 arm64_emit_unbox_trampoline (MonoAotCompile *acfg, MonoCompile *cfg, MonoMethod *method, const char *call_target)
 1509 {
 1510     emit_unset_mode (acfg);
 1511     fprintf (acfg->fp, "add x0, x0, %d\n", (int)(MONO_ABI_SIZEOF (MonoObject)));
 1512     fprintf (acfg->fp, "b %s\n", call_target);
 1513 }
 1514 
 1515 static void
 1516 arm64_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 1517 {
 1518     /* Similar to the specific trampolines, but use the rgctx reg instead of ip1 */
 1519 
 1520     /* Load argument from first GOT slot */
 1521     arm64_emit_load_got_slot (acfg, MONO_ARCH_RGCTX_REG, offset);
 1522     /* Load generic trampoline address from second GOT slot */
 1523     arm64_emit_load_got_slot (acfg, ARMREG_R16, offset + 1);
 1524     fprintf (acfg->fp, "br x16\n");
 1525     *tramp_size = 7 * 4;
 1526 }
 1527 
 1528 static void
 1529 arm64_emit_imt_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 1530 {
 1531     guint8 buf [128];
 1532     guint8 *code, *labels [16];
 1533 
 1534     /* Load parameter from GOT slot into ip1 */
 1535     arm64_emit_load_got_slot (acfg, ARMREG_R17, offset);
 1536 
 1537     code = buf;
 1538     labels [0] = code;
 1539     arm_ldrp (code, ARMREG_IP0, ARMREG_IP1, 0);
 1540     arm_cmpp (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
 1541     labels [1] = code;
 1542     arm_bcc (code, ARMCOND_EQ, 0);
 1543 
 1544     /* End-of-loop check */
 1545     labels [2] = code;
 1546     arm_cbzx (code, ARMREG_IP0, 0);
 1547 
 1548     /* Loop footer */
 1549     arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 2 * 8);
 1550     arm_b (code, labels [0]);
 1551 
 1552     /* Match */
 1553     mono_arm_patch (labels [1], code, MONO_R_ARM64_BCC);
 1554     /* Load vtable slot addr */
 1555     arm_ldrp (code, ARMREG_IP0, ARMREG_IP1, TARGET_SIZEOF_VOID_P);
 1556     /* Load vtable slot */
 1557     arm_ldrp (code, ARMREG_IP0, ARMREG_IP0, 0);
 1558     arm_brx (code, ARMREG_IP0);
 1559 
 1560     /* No match */
 1561     mono_arm_patch (labels [2], code, MONO_R_ARM64_CBZ);
 1562     /* Load fail addr */
 1563     arm_ldrp (code, ARMREG_IP0, ARMREG_IP1, TARGET_SIZEOF_VOID_P);
 1564     arm_brx (code, ARMREG_IP0);
 1565 
 1566     emit_code_bytes (acfg, buf, code - buf);
 1567 
 1568     *tramp_size = code - buf + (3 * 4);
 1569 }
 1570 
 1571 static void
 1572 arm64_emit_gsharedvt_arg_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 1573 {
 1574     /* Similar to the specific trampolines, but the address is in the second slot */
 1575     /* Load argument from first GOT slot */
 1576     arm64_emit_load_got_slot (acfg, ARMREG_R17, offset);
 1577     /* Load generic trampoline address from second GOT slot */
 1578     arm64_emit_load_got_slot (acfg, ARMREG_R16, offset + 1);
 1579     fprintf (acfg->fp, "br x16\n");
 1580     *tramp_size = 7 * 4;
 1581 }
 1582 
 1583 
 1584 #endif
 1585 
 1586 #ifdef MONO_ARCH_AOT_SUPPORTED
 1587 /*
 1588  * arch_emit_direct_call:
 1589  *
 1590  *   Emit a direct call to the symbol TARGET. CALL_SIZE is set to the size of the
 1591  * calling code.
 1592  */
 1593 static void
 1594 arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, gboolean thumb, MonoJumpInfo *ji, int *call_size)
 1595 {
 1596 #if defined(TARGET_X86) || defined(TARGET_AMD64)
 1597     /* Need to make sure this is exactly 5 bytes long */
 1598     emit_unset_mode (acfg);
 1599     fprintf (acfg->fp, "call %s\n", target);
 1600     *call_size = 5;
 1601 #elif defined(TARGET_ARM)
 1602     emit_unset_mode (acfg);
 1603     if (thumb)
 1604         fprintf (acfg->fp, "blx %s\n", target);
 1605     else
 1606         fprintf (acfg->fp, "bl %s\n", target);
 1607     *call_size = 4;
 1608 #elif defined(TARGET_ARM64)
 1609     arm64_emit_direct_call (acfg, target, external, thumb, ji, call_size);
 1610 #elif defined(TARGET_POWERPC)
 1611     emit_unset_mode (acfg);
 1612     fprintf (acfg->fp, "bl %s\n", target);
 1613     *call_size = 4;
 1614 #else
 1615     g_assert_not_reached ();
 1616 #endif
 1617 }
 1618 
 1619 static void
 1620 arch_emit_label_address (MonoAotCompile *acfg, const char *target, gboolean external_call, gboolean thumb, MonoJumpInfo *ji, int *call_size)
 1621 {
 1622 #if defined(TARGET_ARM) && defined(TARGET_ANDROID)
 1623     /* binutils ld does not support branch islands on arm32 */
 1624     if (!thumb) {
 1625         emit_unset_mode (acfg);
 1626         fprintf (acfg->fp, "ldr pc,=%s\n", target);
 1627         fprintf (acfg->fp, ".ltorg\n");
 1628         *call_size = 8;
 1629     } else
 1630 #endif
 1631     arch_emit_direct_call (acfg, target, external_call, thumb, ji, call_size);
 1632 }
 1633 #endif
 1634 
 1635 /*
 1636  * PPC32 design:
 1637  * - we use an approach similar to the x86 abi: reserve a register (r30) to hold 
 1638  *   the GOT pointer.
 1639  * - The full-aot trampolines need access to the GOT of mscorlib, so we store
 1640  *   in in the 2. slot of every GOT, and require every method to place the GOT
 1641  *   address in r30, even when it doesn't access the GOT otherwise. This way,
 1642  *   the trampolines can compute the mscorlib GOT address by loading 4(r30).
 1643  */
 1644 
 1645 /*
 1646  * PPC64 design:
 1647  * PPC64 uses function descriptors which greatly complicate all code, since
 1648  * these are used very inconsistently in the runtime. Some functions like 
 1649  * mono_compile_method () return ftn descriptors, while others like the
 1650  * trampoline creation functions do not.
 1651  * We assume that all GOT slots contain function descriptors, and create 
 1652  * descriptors in aot-runtime.c when needed.
 1653  * The ppc64 abi uses r2 to hold the address of the TOC/GOT, which is loaded
 1654  * from function descriptors, we could do the same, but it would require 
 1655  * rewriting all the ppc/aot code to handle function descriptors properly.
 1656  * So instead, we use the same approach as on PPC32.
 1657  * This is a horrible mess, but fixing it would probably lead to an even bigger
 1658  * one.
 1659  */
 1660 
 1661 /*
 1662  * X86 design:
 1663  * - similar to the PPC32 design, we reserve EBX to hold the GOT pointer.
 1664  */
 1665 
 1666 #ifdef MONO_ARCH_AOT_SUPPORTED
 1667 /*
 1668  * arch_emit_got_offset:
 1669  *
 1670  *   The memory pointed to by CODE should hold native code for computing the GOT
 1671  * address (OP_LOAD_GOTADDR). Emit this code while patching it with the offset
 1672  * between code and the GOT. CODE_SIZE is set to the number of bytes emitted.
 1673  */
 1674 static void
 1675 arch_emit_got_offset (MonoAotCompile *acfg, guint8 *code, int *code_size)
 1676 {
 1677 #if defined(TARGET_POWERPC64)
 1678     emit_unset_mode (acfg);
 1679     /* 
 1680      * The ppc32 code doesn't seem to work on ppc64, the assembler complains about
 1681      * unsupported relocations. So we store the got address into the .Lgot_addr
 1682      * symbol which is in the text segment, compute its address, and load it.
 1683      */
 1684     fprintf (acfg->fp, ".L%d:\n", acfg->label_generator);
 1685     fprintf (acfg->fp, "lis 0, (.Lgot_addr + 4 - .L%d)@h\n", acfg->label_generator);
 1686     fprintf (acfg->fp, "ori 0, 0, (.Lgot_addr + 4 - .L%d)@l\n", acfg->label_generator);
 1687     fprintf (acfg->fp, "add 30, 30, 0\n");
 1688     fprintf (acfg->fp, "%s 30, 0(30)\n", PPC_LD_OP);
 1689     acfg->label_generator ++;
 1690     *code_size = 16;
 1691 #elif defined(TARGET_POWERPC)
 1692     emit_unset_mode (acfg);
 1693     fprintf (acfg->fp, ".L%d:\n", acfg->label_generator);
 1694     fprintf (acfg->fp, "lis 0, (%s + 4 - .L%d)@h\n", acfg->got_symbol, acfg->label_generator);
 1695     fprintf (acfg->fp, "ori 0, 0, (%s + 4 - .L%d)@l\n", acfg->got_symbol, acfg->label_generator);
 1696     acfg->label_generator ++;
 1697     *code_size = 8;
 1698 #else
 1699     guint32 offset = mono_arch_get_patch_offset (code);
 1700     emit_bytes (acfg, code, offset);
 1701     emit_symbol_diff (acfg, acfg->got_symbol, ".", offset);
 1702 
 1703     *code_size = offset + 4;
 1704 #endif
 1705 }
 1706 
 1707 /*
 1708  * arch_emit_got_access:
 1709  *
 1710  *   The memory pointed to by CODE should hold native code for loading a GOT
 1711  * slot (OP_AOTCONST/OP_GOT_ENTRY). Emit this code while patching it so it accesses the
 1712  * GOT slot GOT_SLOT. CODE_SIZE is set to the number of bytes emitted.
 1713  */
 1714 static void
 1715 arch_emit_got_access (MonoAotCompile *acfg, const char *got_symbol, guint8 *code, int got_slot, int *code_size)
 1716 {
 1717 #ifdef TARGET_AMD64
 1718     /* mov reg, got+offset(%rip) */
 1719     if (acfg->llvm) {
 1720         /* The GOT symbol is in the LLVM module, the clang assembler has problems emitting symbol diffs for it */
 1721         int dreg;
 1722         int rex_r;
 1723 
 1724         /* Decode reg, see amd64_mov_reg_membase () */
 1725         rex_r = code [0] & AMD64_REX_R;
 1726         g_assert (code [0] == 0x49 + rex_r);
 1727         g_assert (code [1] == 0x8b);
 1728         dreg = ((code [2] >> 3) & 0x7) + (rex_r ? 8 : 0);
 1729 
 1730         emit_unset_mode (acfg);
 1731         fprintf (acfg->fp, "mov %s+%d(%%rip), %s\n", got_symbol, (unsigned int) ((got_slot * sizeof (target_mgreg_t))), mono_arch_regname (dreg));
 1732         *code_size = 7;
 1733     } else {
 1734         emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
 1735         emit_symbol_diff (acfg, got_symbol, ".", (unsigned int) ((got_slot * sizeof (target_mgreg_t)) - 4));
 1736         *code_size = mono_arch_get_patch_offset (code) + 4;
 1737     }
 1738 #elif defined(TARGET_X86)
 1739     emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
 1740     emit_int32 (acfg, (unsigned int) ((got_slot * sizeof (target_mgreg_t))));
 1741     *code_size = mono_arch_get_patch_offset (code) + 4;
 1742 #elif defined(TARGET_ARM)
 1743     emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
 1744     emit_symbol_diff (acfg, got_symbol, ".", (unsigned int) ((got_slot * sizeof (target_mgreg_t))) - 12);
 1745     *code_size = mono_arch_get_patch_offset (code) + 4;
 1746 #elif defined(TARGET_ARM64)
 1747     emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
 1748     arm64_emit_got_access (acfg, code, got_slot, code_size);
 1749 #elif defined(TARGET_POWERPC)
 1750     {
 1751         guint8 buf [32];
 1752 
 1753         emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
 1754         code = buf;
 1755         ppc_load32 (code, ppc_r0, got_slot * sizeof (target_mgreg_t));
 1756         g_assert (code - buf == 8);
 1757         emit_bytes (acfg, buf, code - buf);
 1758         *code_size = code - buf;
 1759     }
 1760 #else
 1761     g_assert_not_reached ();
 1762 #endif
 1763 }
 1764 
 1765 #endif
 1766 
 1767 #ifdef MONO_ARCH_AOT_SUPPORTED
 1768 /*
 1769  * arch_emit_objc_selector_ref:
 1770  *
 1771  *   Emit the implementation of OP_OBJC_GET_SELECTOR, which itself implements @selector(foo:) in objective-c.
 1772  */
 1773 static void
 1774 arch_emit_objc_selector_ref (MonoAotCompile *acfg, guint8 *code, int index, int *code_size)
 1775 {
 1776 #if defined(TARGET_ARM)
 1777     char symbol1 [MAX_SYMBOL_SIZE];
 1778     char symbol2 [MAX_SYMBOL_SIZE];
 1779     int lindex = acfg->objc_selector_index_2 ++;
 1780 
 1781     /* Emit ldr.imm/b */
 1782     emit_bytes (acfg, code, 8);
 1783 
 1784     sprintf (symbol1, "L_OBJC_SELECTOR_%d", lindex);
 1785     sprintf (symbol2, "L_OBJC_SELECTOR_REFERENCES_%d", index);
 1786 
 1787     emit_label (acfg, symbol1);
 1788     mono_img_writer_emit_unset_mode (acfg->w);
 1789     fprintf (acfg->fp, ".long %s-(%s+12)", symbol2, symbol1);
 1790 
 1791     *code_size = 12;
 1792 #elif defined(TARGET_ARM64)
 1793     arm64_emit_objc_selector_ref (acfg, code, index, code_size);
 1794 #else
 1795     g_assert_not_reached ();
 1796 #endif
 1797 }
 1798 #endif
 1799 
 1800 /*
 1801  * arch_emit_plt_entry:
 1802  *
 1803  *   Emit code for the PLT entry.
 1804  * The plt entry should look like this:
 1805  * <indirect jump to GOT_SYMBOL + OFFSET>
 1806  * <INFO_OFFSET embedded into the instruction stream>
 1807  */
 1808 static void
 1809 arch_emit_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offset, int info_offset)
 1810 {
 1811 #if defined(TARGET_X86)
 1812         /* jmp *<offset>(%ebx) */
 1813         emit_byte (acfg, 0xff);
 1814         emit_byte (acfg, 0xa3);
 1815         emit_int32 (acfg, offset);
 1816         /* Used by mono_aot_get_plt_info_offset */
 1817         emit_int32 (acfg, info_offset);
 1818 #elif defined(TARGET_AMD64)
 1819         emit_unset_mode (acfg);
 1820         fprintf (acfg->fp, "jmp *%s+%d(%%rip)\n", got_symbol, offset);
 1821         /* Used by mono_aot_get_plt_info_offset */
 1822         emit_int32 (acfg, info_offset);
 1823         acfg->stats.plt_size += 10;
 1824 #elif defined(TARGET_ARM)
 1825         guint8 buf [256];
 1826         guint8 *code;
 1827 
 1828         code = buf;
 1829         ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
 1830         ARM_LDR_REG_REG (code, ARMREG_PC, ARMREG_PC, ARMREG_IP);
 1831         emit_bytes (acfg, buf, code - buf);
 1832         emit_symbol_diff (acfg, got_symbol, ".", offset - 4);
 1833         /* Used by mono_aot_get_plt_info_offset */
 1834         emit_int32 (acfg, info_offset);
 1835 #elif defined(TARGET_ARM64)
 1836         arm64_emit_plt_entry (acfg, got_symbol, offset, info_offset);
 1837 #elif defined(TARGET_POWERPC)
 1838         /* The GOT address is guaranteed to be in r30 by OP_LOAD_GOTADDR */
 1839         emit_unset_mode (acfg);
 1840         fprintf (acfg->fp, "lis 11, %d@h\n", offset);
 1841         fprintf (acfg->fp, "ori 11, 11, %d@l\n", offset);
 1842         fprintf (acfg->fp, "add 11, 11, 30\n");
 1843         fprintf (acfg->fp, "%s 11, 0(11)\n", PPC_LD_OP);
 1844 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
 1845         fprintf (acfg->fp, "%s 2, %d(11)\n", PPC_LD_OP, (int)sizeof (target_mgreg_t));
 1846         fprintf (acfg->fp, "%s 11, 0(11)\n", PPC_LD_OP);
 1847 #endif
 1848         fprintf (acfg->fp, "mtctr 11\n");
 1849         fprintf (acfg->fp, "bctr\n");
 1850         emit_int32 (acfg, info_offset);
 1851 #else
 1852         g_assert_not_reached ();
 1853 #endif
 1854 }
 1855 
 1856 /*
 1857  * arch_emit_llvm_plt_entry:
 1858  *
 1859  *   Same as arch_emit_plt_entry, but handles calls from LLVM generated code.
 1860  * This is only needed on arm to handle thumb interop.
 1861  */
 1862 static void
 1863 arch_emit_llvm_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offset, int info_offset)
 1864 {
 1865 #if defined(TARGET_ARM)
 1866     /* LLVM calls the PLT entries using bl, so these have to be thumb2 */
 1867     /* The caller already transitioned to thumb */
 1868     /* The code below should be 12 bytes long */
 1869     /* clang has trouble encoding these instructions, so emit the binary */
 1870 #if 0
 1871     fprintf (acfg->fp, "ldr ip, [pc, #8]\n");
 1872     /* thumb can't encode ld pc, [pc, ip] */
 1873     fprintf (acfg->fp, "add ip, pc, ip\n");
 1874     fprintf (acfg->fp, "ldr ip, [ip, #0]\n");
 1875     fprintf (acfg->fp, "bx ip\n");
 1876 #endif
 1877     emit_set_thumb_mode (acfg);
 1878     fprintf (acfg->fp, ".4byte 0xc008f8df\n");
 1879     fprintf (acfg->fp, ".2byte 0x44fc\n");
 1880     fprintf (acfg->fp, ".4byte 0xc000f8dc\n");
 1881     fprintf (acfg->fp, ".2byte 0x4760\n");
 1882     emit_symbol_diff (acfg, got_symbol, ".", offset + 4);
 1883     emit_int32 (acfg, info_offset);
 1884     emit_unset_mode (acfg);
 1885     emit_set_arm_mode (acfg);
 1886 #else
 1887     g_assert_not_reached ();
 1888 #endif
 1889 }
 1890 
 1891 /* Save unwind_info in the module and emit the offset to the information at symbol */
 1892 static void save_unwind_info (MonoAotCompile *acfg, char *symbol, GSList *unwind_ops)
 1893 {
 1894     guint32 uw_offset, encoded_len;
 1895     guint8 *encoded;
 1896 
 1897     emit_section_change (acfg, RODATA_SECT, 0);
 1898     emit_global (acfg, symbol, FALSE);
 1899     emit_label (acfg, symbol);
 1900 
 1901     encoded = mono_unwind_ops_encode (unwind_ops, &encoded_len);
 1902     uw_offset = get_unwind_info_offset (acfg, encoded, encoded_len);
 1903     g_free (encoded);
 1904     emit_int32 (acfg, uw_offset);
 1905 }
 1906 
 1907 /*
 1908  * arch_emit_specific_trampoline_pages:
 1909  *
 1910  * Emits a page full of trampolines: each trampoline uses its own address to
 1911  * lookup both the generic trampoline code and the data argument.
 1912  * This page can be remapped in process multiple times so we can get an
 1913  * unlimited number of trampolines.
 1914  * Specifically this implementation uses the following trick: two memory pages
 1915  * are allocated, with the first containing the data and the second containing the trampolines.
 1916  * To reduce trampoline size, each trampoline jumps at the start of the page where a common
 1917  * implementation does all the lifting.
 1918  * Note that the ARM single trampoline size is 8 bytes, exactly like the data that needs to be stored
 1919  * on the arm 32 bit system.
 1920  */
 1921 static void
 1922 arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
 1923 {
 1924 #if defined(TARGET_ARM)
 1925     guint8 buf [128];
 1926     guint8 *code;
 1927     guint8 *loop_start, *loop_branch_back, *loop_end_check, *imt_found_check;
 1928     int i;
 1929     int pagesize = MONO_AOT_TRAMP_PAGE_SIZE;
 1930     GSList *unwind_ops = NULL;
 1931 #define COMMON_TRAMP_SIZE 16
 1932     int count = (pagesize - COMMON_TRAMP_SIZE) / 8;
 1933     int imm8, rot_amount;
 1934     char symbol [128];
 1935 
 1936     if (!acfg->aot_opts.use_trampolines_page)
 1937         return;
 1938 
 1939     acfg->tramp_page_size = pagesize;
 1940 
 1941     sprintf (symbol, "%sspecific_trampolines_page", acfg->user_symbol_prefix);
 1942     emit_alignment (acfg, pagesize);
 1943     emit_global (acfg, symbol, TRUE);
 1944     emit_label (acfg, symbol);
 1945 
 1946     /* emit the generic code first, the trampoline address + 8 is in the lr register */
 1947     code = buf;
 1948     imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
 1949     ARM_SUB_REG_IMM (code, ARMREG_LR, ARMREG_LR, imm8, rot_amount);
 1950     ARM_LDR_IMM (code, ARMREG_R1, ARMREG_LR, -8);
 1951     ARM_LDR_IMM (code, ARMREG_PC, ARMREG_LR, -4);
 1952     ARM_NOP (code);
 1953     g_assert (code - buf == COMMON_TRAMP_SIZE);
 1954 
 1955     /* Emit it */
 1956     emit_bytes (acfg, buf, code - buf);
 1957 
 1958     for (i = 0; i < count; ++i) {
 1959         code = buf;
 1960         ARM_PUSH (code, 0x5fff);
 1961         ARM_BL (code, 0);
 1962         arm_patch (code - 4, code - COMMON_TRAMP_SIZE - 8 * (i + 1));
 1963         g_assert (code - buf == 8);
 1964         emit_bytes (acfg, buf, code - buf);
 1965     }
 1966 
 1967     /* now the rgctx trampolines: each specific trampolines puts in the ip register
 1968      * the instruction pointer address, so the generic trampoline at the start of the page
 1969      * subtracts 4096 to get to the data page and loads the values
 1970      * We again fit the generic trampiline in 16 bytes.
 1971      */
 1972     sprintf (symbol, "%srgctx_trampolines_page", acfg->user_symbol_prefix);
 1973     emit_global (acfg, symbol, TRUE);
 1974     emit_label (acfg, symbol);
 1975     code = buf;
 1976     imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
 1977     ARM_SUB_REG_IMM (code, ARMREG_IP, ARMREG_IP, imm8, rot_amount);
 1978     ARM_LDR_IMM (code, MONO_ARCH_RGCTX_REG, ARMREG_IP, -8);
 1979     ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, -4);
 1980     ARM_NOP (code);
 1981     g_assert (code - buf == COMMON_TRAMP_SIZE);
 1982 
 1983     /* Emit it */
 1984     emit_bytes (acfg, buf, code - buf);
 1985 
 1986     for (i = 0; i < count; ++i) {
 1987         code = buf;
 1988         ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_PC);
 1989         ARM_B (code, 0);
 1990         arm_patch (code - 4, code - COMMON_TRAMP_SIZE - 8 * (i + 1));
 1991         g_assert (code - buf == 8);
 1992         emit_bytes (acfg, buf, code - buf);
 1993     }
 1994 
 1995     /*
 1996      * gsharedvt arg trampolines: see arch_emit_gsharedvt_arg_trampoline ()
 1997      */
 1998     sprintf (symbol, "%sgsharedvt_arg_trampolines_page", acfg->user_symbol_prefix);
 1999     emit_global (acfg, symbol, TRUE);
 2000     emit_label (acfg, symbol);
 2001     code = buf;
 2002     ARM_PUSH (code, (1 << ARMREG_R0) | (1 << ARMREG_R1) | (1 << ARMREG_R2) | (1 << ARMREG_R3));
 2003     imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
 2004     ARM_SUB_REG_IMM (code, ARMREG_IP, ARMREG_IP, imm8, rot_amount);
 2005     ARM_LDR_IMM (code, ARMREG_R0, ARMREG_IP, -8);
 2006     ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, -4);
 2007     g_assert (code - buf == COMMON_TRAMP_SIZE);
 2008     /* Emit it */
 2009     emit_bytes (acfg, buf, code - buf);
 2010 
 2011     for (i = 0; i < count; ++i) {
 2012         code = buf;
 2013         ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_PC);
 2014         ARM_B (code, 0);
 2015         arm_patch (code - 4, code - COMMON_TRAMP_SIZE - 8 * (i + 1));
 2016         g_assert (code - buf == 8);
 2017         emit_bytes (acfg, buf, code - buf);
 2018     }
 2019 
 2020     /* now the unbox arbitrary trampolines: each specific trampolines puts in the ip register
 2021      * the instruction pointer address, so the generic trampoline at the start of the page
 2022      * subtracts 4096 to get to the data page and loads the target addr.
 2023      * We again fit the generic trampoline in 16 bytes.
 2024      */
 2025     sprintf (symbol, "%sunbox_arbitrary_trampolines_page", acfg->user_symbol_prefix);
 2026     emit_global (acfg, symbol, TRUE);
 2027     emit_label (acfg, symbol);
 2028     code = buf;
 2029 
 2030     ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, MONO_ABI_SIZEOF (MonoObject));
 2031     imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
 2032     ARM_SUB_REG_IMM (code, ARMREG_IP, ARMREG_IP, imm8, rot_amount);
 2033     ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, -4);
 2034     ARM_NOP (code);
 2035     g_assert (code - buf == COMMON_TRAMP_SIZE);
 2036 
 2037     /* Emit it */
 2038     emit_bytes (acfg, buf, code - buf);
 2039 
 2040     for (i = 0; i < count; ++i) {
 2041         code = buf;
 2042         ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_PC);
 2043         ARM_B (code, 0);
 2044         arm_patch (code - 4, code - COMMON_TRAMP_SIZE - 8 * (i + 1));
 2045         g_assert (code - buf == 8);
 2046         emit_bytes (acfg, buf, code - buf);
 2047     }
 2048 
 2049     /* now the imt trampolines: each specific trampolines puts in the ip register
 2050      * the instruction pointer address, so the generic trampoline at the start of the page
 2051      * subtracts 4096 to get to the data page and loads the values
 2052      */
 2053 #define IMT_TRAMP_SIZE 72
 2054     sprintf (symbol, "%simt_trampolines_page", acfg->user_symbol_prefix);
 2055     emit_global (acfg, symbol, TRUE);
 2056     emit_label (acfg, symbol);
 2057     code = buf;
 2058     /* Need at least two free registers, plus a slot for storing the pc */
 2059     ARM_PUSH (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_R2));
 2060 
 2061     imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
 2062     ARM_SUB_REG_IMM (code, ARMREG_IP, ARMREG_IP, imm8, rot_amount);
 2063     ARM_LDR_IMM (code, ARMREG_R0, ARMREG_IP, -8);
 2064 
 2065     /* The IMT method is in v5, r0 has the imt array address */
 2066 
 2067     loop_start = code;
 2068     ARM_LDR_IMM (code, ARMREG_R1, ARMREG_R0, 0);
 2069     ARM_CMP_REG_REG (code, ARMREG_R1, ARMREG_V5);
 2070     imt_found_check = code;
 2071     ARM_B_COND (code, ARMCOND_EQ, 0);
 2072 
 2073     /* End-of-loop check */
 2074     ARM_CMP_REG_IMM (code, ARMREG_R1, 0, 0);
 2075     loop_end_check = code;
 2076     ARM_B_COND (code, ARMCOND_EQ, 0);
 2077 
 2078     /* Loop footer */
 2079     ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (target_mgreg_t) * 2);
 2080     loop_branch_back = code;
 2081     ARM_B (code, 0);
 2082     arm_patch (loop_branch_back, loop_start);
 2083 
 2084     /* Match */
 2085     arm_patch (imt_found_check, code);
 2086     ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 4);
 2087     ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 0);
 2088     /* Save it to the third stack slot */
 2089     ARM_STR_IMM (code, ARMREG_R0, ARMREG_SP, 8);
 2090     /* Restore the registers and branch */
 2091     ARM_POP (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_PC));
 2092 
 2093     /* No match */
 2094     arm_patch (loop_end_check, code);
 2095     ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 4);
 2096     ARM_STR_IMM (code, ARMREG_R0, ARMREG_SP, 8);
 2097     ARM_POP (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_PC));
 2098     ARM_NOP (code);
 2099 
 2100     /* Emit it */
 2101     g_assert (code - buf == IMT_TRAMP_SIZE);
 2102     emit_bytes (acfg, buf, code - buf);
 2103 
 2104     for (i = 0; i < count; ++i) {
 2105         code = buf;
 2106         ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_PC);
 2107         ARM_B (code, 0);
 2108         arm_patch (code - 4, code - IMT_TRAMP_SIZE - 8 * (i + 1));
 2109         g_assert (code - buf == 8);
 2110         emit_bytes (acfg, buf, code - buf);
 2111     }
 2112 
 2113     acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_SPECIFIC] = 16;
 2114     acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = 16;
 2115     acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT] = 72;
 2116     acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = 16;
 2117     acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_UNBOX_ARBITRARY] = 16;
 2118 
 2119     /* Unwind info for specifc trampolines */
 2120     sprintf (symbol, "%sspecific_trampolines_page_gen_p", acfg->user_symbol_prefix);
 2121     /* We unwind to the original caller, from the stack, since lr is clobbered */
 2122     mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 14 * sizeof (target_mgreg_t));
 2123     mono_add_unwind_op_offset (unwind_ops, 0, 0, ARMREG_LR, -4);
 2124     save_unwind_info (acfg, symbol, unwind_ops);
 2125     mono_free_unwind_info (unwind_ops);
 2126 
 2127     sprintf (symbol, "%sspecific_trampolines_page_sp_p", acfg->user_symbol_prefix);
 2128     mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
 2129     mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 14 * sizeof (target_mgreg_t));
 2130     save_unwind_info (acfg, symbol, unwind_ops);
 2131     mono_free_unwind_info (unwind_ops);
 2132 
 2133     /* Unwind info for rgctx trampolines */
 2134     sprintf (symbol, "%srgctx_trampolines_page_gen_p", acfg->user_symbol_prefix);
 2135     mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
 2136     save_unwind_info (acfg, symbol, unwind_ops);
 2137 
 2138     sprintf (symbol, "%srgctx_trampolines_page_sp_p", acfg->user_symbol_prefix);
 2139     save_unwind_info (acfg, symbol, unwind_ops);
 2140     mono_free_unwind_info (unwind_ops);
 2141 
 2142     /* Unwind info for gsharedvt trampolines */
 2143     sprintf (symbol, "%sgsharedvt_trampolines_page_gen_p", acfg->user_symbol_prefix);
 2144     mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
 2145     mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 4 * sizeof (target_mgreg_t));
 2146     save_unwind_info (acfg, symbol, unwind_ops);
 2147     mono_free_unwind_info (unwind_ops);
 2148 
 2149     sprintf (symbol, "%sgsharedvt_trampolines_page_sp_p", acfg->user_symbol_prefix);
 2150     mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
 2151     save_unwind_info (acfg, symbol, unwind_ops);
 2152     mono_free_unwind_info (unwind_ops);
 2153 
 2154     /* Unwind info for unbox arbitrary trampolines */
 2155     sprintf (symbol, "%sunbox_arbitrary_trampolines_page_gen_p", acfg->user_symbol_prefix);
 2156     mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
 2157     save_unwind_info (acfg, symbol, unwind_ops);
 2158 
 2159     sprintf (symbol, "%sunbox_arbitrary_trampolines_page_sp_p", acfg->user_symbol_prefix);
 2160     save_unwind_info (acfg, symbol, unwind_ops);
 2161     mono_free_unwind_info (unwind_ops);
 2162 
 2163     /* Unwind info for imt trampolines */
 2164     sprintf (symbol, "%simt_trampolines_page_gen_p", acfg->user_symbol_prefix);
 2165     mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
 2166     mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 3 * sizeof (target_mgreg_t));
 2167     save_unwind_info (acfg, symbol, unwind_ops);
 2168     mono_free_unwind_info (unwind_ops);
 2169 
 2170     sprintf (symbol, "%simt_trampolines_page_sp_p", acfg->user_symbol_prefix);
 2171     mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
 2172     save_unwind_info (acfg, symbol, unwind_ops);
 2173     mono_free_unwind_info (unwind_ops);
 2174 #elif defined(TARGET_ARM64)
 2175     arm64_emit_specific_trampoline_pages (acfg);
 2176 #endif
 2177 }
 2178 
 2179 /*
 2180  * arch_emit_specific_trampoline:
 2181  *
 2182  *   Emit code for a specific trampoline. OFFSET is the offset of the first of
 2183  * two GOT slots which contain the generic trampoline address and the trampoline
 2184  * argument. TRAMP_SIZE is set to the size of the emitted trampoline.
 2185  */
 2186 static void
 2187 arch_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 2188 {
 2189     /*
 2190      * The trampolines created here are variations of the specific 
 2191      * trampolines created in mono_arch_create_specific_trampoline (). The 
 2192      * differences are:
 2193      * - the generic trampoline address is taken from a got slot.
 2194      * - the offset of the got slot where the trampoline argument is stored
 2195      *   is embedded in the instruction stream, and the generic trampoline
 2196      *   can load the argument by loading the offset, adding it to the
 2197      *   address of the trampoline to get the address of the got slot, and
 2198      *   loading the argument from there.
 2199      * - all the trampolines should be of the same length.
 2200      */
 2201 #if defined(TARGET_AMD64)
 2202     /* This should be exactly 8 bytes long */
 2203     *tramp_size = 8;
 2204     /* call *<offset>(%rip) */
 2205     if (acfg->llvm) {
 2206         emit_unset_mode (acfg);
 2207         fprintf (acfg->fp, "call *%s+%d(%%rip)\n", acfg->got_symbol, (int)(offset * sizeof (target_mgreg_t)));
 2208         emit_zero_bytes (acfg, 2);
 2209     } else {
 2210         emit_byte (acfg, '\x41');
 2211         emit_byte (acfg, '\xff');
 2212         emit_byte (acfg, '\x15');
 2213         emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (target_mgreg_t)) - 4);
 2214         emit_zero_bytes (acfg, 1);
 2215     }
 2216 #elif defined(TARGET_ARM)
 2217     guint8 buf [128];
 2218     guint8 *code;
 2219 
 2220     /* This should be exactly 20 bytes long */
 2221     *tramp_size = 20;
 2222     code = buf;
 2223     ARM_PUSH (code, 0x5fff);
 2224     ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 4);
 2225     /* Load the value from the GOT */
 2226     ARM_LDR_REG_REG (code, ARMREG_R1, ARMREG_PC, ARMREG_R1);
 2227     /* Branch to it */
 2228     ARM_BLX_REG (code, ARMREG_R1);
 2229 
 2230     g_assert (code - buf == 16);
 2231 
 2232     /* Emit it */
 2233     emit_bytes (acfg, buf, code - buf);
 2234     /* 
 2235      * Only one offset is needed, since the second one would be equal to the
 2236      * first one.
 2237      */
 2238     emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (target_mgreg_t)) - 4 + 4);
 2239     //emit_symbol_diff (acfg, acfg->got_symbol, ".", ((offset + 1) * sizeof (target_mgreg_t)) - 4 + 8);
 2240 #elif defined(TARGET_ARM64)
 2241     arm64_emit_specific_trampoline (acfg, offset, tramp_size);
 2242 #elif defined(TARGET_POWERPC)
 2243     guint8 buf [128];
 2244     guint8 *code;
 2245 
 2246     *tramp_size = 4;
 2247     code = buf;
 2248 
 2249     /*
 2250      * PPC has no ip relative addressing, so we need to compute the address
 2251      * of the mscorlib got. That is slow and complex, so instead, we store it
 2252      * in the second got slot of every aot image. The caller already computed
 2253      * the address of its got and placed it into r30.
 2254      */
 2255     emit_unset_mode (acfg);
 2256     /* Load mscorlib got address */
 2257     fprintf (acfg->fp, "%s 0, %d(30)\n", PPC_LD_OP, (int)sizeof (target_mgreg_t));
 2258     /* Load generic trampoline address */
 2259     fprintf (acfg->fp, "lis 11, %d@h\n", (int)(offset * sizeof (target_mgreg_t)));
 2260     fprintf (acfg->fp, "ori 11, 11, %d@l\n", (int)(offset * sizeof (target_mgreg_t)));
 2261     fprintf (acfg->fp, "%s 11, 11, 0\n", PPC_LDX_OP);
 2262 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
 2263     fprintf (acfg->fp, "%s 11, 0(11)\n", PPC_LD_OP);
 2264 #endif
 2265     fprintf (acfg->fp, "mtctr 11\n");
 2266     /* Load trampoline argument */
 2267     /* On ppc, we pass it normally to the generic trampoline */
 2268     fprintf (acfg->fp, "lis 11, %d@h\n", (int)((offset + 1) * sizeof (target_mgreg_t)));
 2269     fprintf (acfg->fp, "ori 11, 11, %d@l\n", (int)((offset + 1) * sizeof (target_mgreg_t)));
 2270     fprintf (acfg->fp, "%s 0, 11, 0\n", PPC_LDX_OP);
 2271     /* Branch to generic trampoline */
 2272     fprintf (acfg->fp, "bctr\n");
 2273 
 2274 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
 2275     *tramp_size = 10 * 4;
 2276 #else
 2277     *tramp_size = 9 * 4;
 2278 #endif
 2279 #elif defined(TARGET_X86)
 2280     guint8 buf [128];
 2281     guint8 *code;
 2282 
 2283     /* Similar to the PPC code above */
 2284 
 2285     /* FIXME: Could this clobber the register needed by get_vcall_slot () ? */
 2286 
 2287     code = buf;
 2288     /* Load mscorlib got address */
 2289     x86_mov_reg_membase (code, X86_ECX, MONO_ARCH_GOT_REG, sizeof (target_mgreg_t), 4);
 2290     /* Push trampoline argument */
 2291     x86_push_membase (code, X86_ECX, (offset + 1) * sizeof (target_mgreg_t));
 2292     /* Load generic trampoline address */
 2293     x86_mov_reg_membase (code, X86_ECX, X86_ECX, offset * sizeof (target_mgreg_t), 4);
 2294     /* Branch to generic trampoline */
 2295     x86_jump_reg (code, X86_ECX);
 2296 
 2297     emit_bytes (acfg, buf, code - buf);
 2298 
 2299     *tramp_size = 17;
 2300     g_assert (code - buf == *tramp_size);
 2301 #else
 2302     g_assert_not_reached ();
 2303 #endif
 2304 }
 2305 
 2306 /*
 2307  * arch_emit_unbox_trampoline:
 2308  *
 2309  *   Emit code for the unbox trampoline for METHOD used in the full-aot case.
 2310  * CALL_TARGET is the symbol pointing to the native code of METHOD.
 2311  *
 2312  * See mono_aot_get_unbox_trampoline.
 2313  */
 2314 static void
 2315 arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoCompile *cfg, MonoMethod *method, const char *call_target)
 2316 {
 2317 #if defined(TARGET_AMD64)
 2318     guint8 buf [32];
 2319     guint8 *code;
 2320     int this_reg;
 2321 
 2322     this_reg = mono_arch_get_this_arg_reg (NULL);
 2323     code = buf;
 2324     amd64_alu_reg_imm (code, X86_ADD, this_reg, MONO_ABI_SIZEOF (MonoObject));
 2325 
 2326     emit_bytes (acfg, buf, code - buf);
 2327     /* jump <method> */
 2328     if (acfg->llvm) {
 2329         emit_unset_mode (acfg);
 2330         fprintf (acfg->fp, "jmp %s\n", call_target);
 2331     } else {
 2332         emit_byte (acfg, '\xe9');
 2333         emit_symbol_diff (acfg, call_target, ".", -4);
 2334     }
 2335 #elif defined(TARGET_X86)
 2336     guint8 buf [32];
 2337     guint8 *code;
 2338     int this_pos = 4;
 2339 
 2340     code = buf;
 2341 
 2342     x86_alu_membase_imm (code, X86_ADD, X86_ESP, this_pos, MONO_ABI_SIZEOF (MonoObject));
 2343 
 2344     emit_bytes (acfg, buf, code - buf);
 2345 
 2346     /* jump <method> */
 2347     emit_byte (acfg, '\xe9');
 2348     emit_symbol_diff (acfg, call_target, ".", -4);
 2349 #elif defined(TARGET_ARM)
 2350     guint8 buf [128];
 2351     guint8 *code;
 2352 
 2353     if (acfg->thumb_mixed && cfg->compile_llvm) {
 2354         fprintf (acfg->fp, "add r0, r0, #%d\n", (int)MONO_ABI_SIZEOF (MonoObject));
 2355         fprintf (acfg->fp, "b %s\n", call_target);
 2356         fprintf (acfg->fp, ".arm\n");
 2357         fprintf (acfg->fp, ".align 2\n");
 2358         return;
 2359     }
 2360 
 2361     code = buf;
 2362 
 2363     ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, MONO_ABI_SIZEOF (MonoObject));
 2364 
 2365     emit_bytes (acfg, buf, code - buf);
 2366     /* jump to method */
 2367     if (acfg->thumb_mixed && cfg->compile_llvm)
 2368         fprintf (acfg->fp, "\n\tbx %s\n", call_target);
 2369     else
 2370         fprintf (acfg->fp, "\n\tb %s\n", call_target);
 2371 #elif defined(TARGET_ARM64)
 2372     arm64_emit_unbox_trampoline (acfg, cfg, method, call_target);
 2373 #elif defined(TARGET_POWERPC)
 2374     int this_pos = 3;
 2375 
 2376     fprintf (acfg->fp, "\n\taddi %d, %d, %d\n", this_pos, this_pos, (int)MONO_ABI_SIZEOF (MonoObject));
 2377     fprintf (acfg->fp, "\n\tb %s\n", call_target);
 2378 #else
 2379     g_assert_not_reached ();
 2380 #endif
 2381 }
 2382 
 2383 /*
 2384  * arch_emit_static_rgctx_trampoline:
 2385  *
 2386  *   Emit code for a static rgctx trampoline. OFFSET is the offset of the first of
 2387  * two GOT slots which contain the rgctx argument, and the method to jump to.
 2388  * TRAMP_SIZE is set to the size of the emitted trampoline.
 2389  * These kinds of trampolines cannot be enumerated statically, since there could
 2390  * be one trampoline per method instantiation, so we emit the same code for all
 2391  * trampolines, and parameterize them using two GOT slots.
 2392  */
 2393 static void
 2394 arch_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 2395 {
 2396 #if defined(TARGET_AMD64)
 2397     /* This should be exactly 13 bytes long */
 2398     *tramp_size = 13;
 2399 
 2400     if (acfg->llvm) {
 2401         emit_unset_mode (acfg);
 2402         fprintf (acfg->fp, "mov %s+%d(%%rip), %%r10\n", acfg->got_symbol, (int)(offset * sizeof (target_mgreg_t)));
 2403         fprintf (acfg->fp, "jmp *%s+%d(%%rip)\n", acfg->got_symbol, (int)((offset + 1) * sizeof (target_mgreg_t)));
 2404     } else {
 2405         /* mov <OFFSET>(%rip), %r10 */
 2406         emit_byte (acfg, '\x4d');
 2407         emit_byte (acfg, '\x8b');
 2408         emit_byte (acfg, '\x15');
 2409         emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (target_mgreg_t)) - 4);
 2410 
 2411         /* jmp *<offset>(%rip) */
 2412         emit_byte (acfg, '\xff');
 2413         emit_byte (acfg, '\x25');
 2414         emit_symbol_diff (acfg, acfg->got_symbol, ".", ((offset + 1) * sizeof (target_mgreg_t)) - 4);
 2415     }
 2416 #elif defined(TARGET_ARM)
 2417     guint8 buf [128];
 2418     guint8 *code;
 2419 
 2420     /* This should be exactly 24 bytes long */
 2421     *tramp_size = 24;
 2422     code = buf;
 2423     /* Load rgctx value */
 2424     ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 8);
 2425     ARM_LDR_REG_REG (code, MONO_ARCH_RGCTX_REG, ARMREG_PC, ARMREG_IP);
 2426     /* Load branch addr + branch */
 2427     ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 4);
 2428     ARM_LDR_REG_REG (code, ARMREG_PC, ARMREG_PC, ARMREG_IP);
 2429 
 2430     g_assert (code - buf == 16);
 2431 
 2432     /* Emit it */
 2433     emit_bytes (acfg, buf, code - buf);
 2434     emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (target_mgreg_t)) - 4 + 8);
 2435     emit_symbol_diff (acfg, acfg->got_symbol, ".", ((offset + 1) * sizeof (target_mgreg_t)) - 4 + 4);
 2436 #elif defined(TARGET_ARM64)
 2437     arm64_emit_static_rgctx_trampoline (acfg, offset, tramp_size);
 2438 #elif defined(TARGET_POWERPC)
 2439     guint8 buf [128];
 2440     guint8 *code;
 2441 
 2442     *tramp_size = 4;
 2443     code = buf;
 2444 
 2445     /*
 2446      * PPC has no ip relative addressing, so we need to compute the address
 2447      * of the mscorlib got. That is slow and complex, so instead, we store it
 2448      * in the second got slot of every aot image. The caller already computed
 2449      * the address of its got and placed it into r30.
 2450      */
 2451     emit_unset_mode (acfg);
 2452     /* Load mscorlib got address */
 2453     fprintf (acfg->fp, "%s 0, %d(30)\n", PPC_LD_OP, (int)sizeof (target_mgreg_t));
 2454     /* Load rgctx */
 2455     fprintf (acfg->fp, "lis 11, %d@h\n", (int)(offset * sizeof (target_mgreg_t)));
 2456     fprintf (acfg->fp, "ori 11, 11, %d@l\n", (int)(offset * sizeof (target_mgreg_t)));
 2457     fprintf (acfg->fp, "%s %d, 11, 0\n", PPC_LDX_OP, MONO_ARCH_RGCTX_REG);
 2458     /* Load target address */
 2459     fprintf (acfg->fp, "lis 11, %d@h\n", (int)((offset + 1) * sizeof (target_mgreg_t)));
 2460     fprintf (acfg->fp, "ori 11, 11, %d@l\n", (int)((offset + 1) * sizeof (target_mgreg_t)));
 2461     fprintf (acfg->fp, "%s 11, 11, 0\n", PPC_LDX_OP);
 2462 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
 2463     fprintf (acfg->fp, "%s 2, %d(11)\n", PPC_LD_OP, (int)sizeof (target_mgreg_t));
 2464     fprintf (acfg->fp, "%s 11, 0(11)\n", PPC_LD_OP);
 2465 #endif
 2466     fprintf (acfg->fp, "mtctr 11\n");
 2467     /* Branch to the target address */
 2468     fprintf (acfg->fp, "bctr\n");
 2469 
 2470 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
 2471     *tramp_size = 11 * 4;
 2472 #else
 2473     *tramp_size = 9 * 4;
 2474 #endif
 2475 
 2476 #elif defined(TARGET_X86)
 2477     guint8 buf [128];
 2478     guint8 *code;
 2479 
 2480     /* Similar to the PPC code above */
 2481 
 2482     g_assert (MONO_ARCH_RGCTX_REG != X86_ECX);
 2483 
 2484     code = buf;
 2485     /* Load mscorlib got address */
 2486     x86_mov_reg_membase (code, X86_ECX, MONO_ARCH_GOT_REG, sizeof (target_mgreg_t), 4);
 2487     /* Load arg */
 2488     x86_mov_reg_membase (code, MONO_ARCH_RGCTX_REG, X86_ECX, offset * sizeof (target_mgreg_t), 4);
 2489     /* Branch to the target address */
 2490     x86_jump_membase (code, X86_ECX, (offset + 1) * sizeof (target_mgreg_t));
 2491 
 2492     emit_bytes (acfg, buf, code - buf);
 2493 
 2494     *tramp_size = 15;
 2495     g_assert (code - buf == *tramp_size);
 2496 #else
 2497     g_assert_not_reached ();
 2498 #endif
 2499 }   
 2500 
 2501 /*
 2502  * arch_emit_imt_trampoline:
 2503  *
 2504  *   Emit an IMT trampoline usable in full-aot mode. The trampoline uses 1 got slot which
 2505  * points to an array of pointer pairs. The pairs of the form [key, ptr], where
 2506  * key is the IMT key, and ptr holds the address of a memory location holding
 2507  * the address to branch to if the IMT arg matches the key. The array is 
 2508  * terminated by a pair whose key is NULL, and whose ptr is the address of the 
 2509  * fail_tramp.
 2510  * TRAMP_SIZE is set to the size of the emitted trampoline.
 2511  */
 2512 static void
 2513 arch_emit_imt_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 2514 {
 2515 #if defined(TARGET_AMD64)
 2516     guint8 *buf, *code;
 2517     guint8 *labels [16];
 2518     guint8 mov_buf[3];
 2519     guint8 *mov_buf_ptr = mov_buf;
 2520 
 2521     const int kSizeOfMove = 7;
 2522 
 2523     code = buf = (guint8 *)g_malloc (256);
 2524 
 2525     /* FIXME: Optimize this, i.e. use binary search etc. */
 2526     /* Maybe move the body into a separate function (slower, but much smaller) */
 2527 
 2528     /* MONO_ARCH_IMT_SCRATCH_REG is a free register */
 2529 
 2530     if (acfg->llvm) {
 2531         emit_unset_mode (acfg);
 2532         fprintf (acfg->fp, "mov %s+%d(%%rip), %s\n", acfg->got_symbol, (int)(offset * sizeof (target_mgreg_t)), mono_arch_regname (MONO_ARCH_IMT_SCRATCH_REG));
 2533     }
 2534 
 2535     labels [0] = code;
 2536     amd64_alu_membase_imm (code, X86_CMP, MONO_ARCH_IMT_SCRATCH_REG, 0, 0);
 2537     labels [1] = code;
 2538     amd64_branch8 (code, X86_CC_Z, 0, FALSE);
 2539 
 2540     /* Check key */
 2541     amd64_alu_membase_reg_size (code, X86_CMP, MONO_ARCH_IMT_SCRATCH_REG, 0, MONO_ARCH_IMT_REG, sizeof (target_mgreg_t));
 2542     labels [2] = code;
 2543     amd64_branch8 (code, X86_CC_Z, 0, FALSE);
 2544 
 2545     /* Loop footer */
 2546     amd64_alu_reg_imm (code, X86_ADD, MONO_ARCH_IMT_SCRATCH_REG, 2 * sizeof (target_mgreg_t));
 2547     amd64_jump_code (code, labels [0]);
 2548 
 2549     /* Match */
 2550     mono_amd64_patch (labels [2], code);
 2551     amd64_mov_reg_membase (code, MONO_ARCH_IMT_SCRATCH_REG, MONO_ARCH_IMT_SCRATCH_REG, sizeof (target_mgreg_t), sizeof (target_mgreg_t));
 2552     amd64_jump_membase (code, MONO_ARCH_IMT_SCRATCH_REG, 0);
 2553 
 2554     /* No match */
 2555     mono_amd64_patch (labels [1], code);
 2556     /* Load fail tramp */
 2557     amd64_alu_reg_imm (code, X86_ADD, MONO_ARCH_IMT_SCRATCH_REG, sizeof (target_mgreg_t));
 2558     /* Check if there is a fail tramp */
 2559     amd64_alu_membase_imm (code, X86_CMP, MONO_ARCH_IMT_SCRATCH_REG, 0, 0);
 2560     labels [3] = code;
 2561     amd64_branch8 (code, X86_CC_Z, 0, FALSE);
 2562     /* Jump to fail tramp */
 2563     amd64_jump_membase (code, MONO_ARCH_IMT_SCRATCH_REG, 0);
 2564 
 2565     /* Fail */
 2566     mono_amd64_patch (labels [3], code);
 2567     x86_breakpoint (code);
 2568 
 2569     if (!acfg->llvm) {
 2570         /* mov <OFFSET>(%rip), MONO_ARCH_IMT_SCRATCH_REG */
 2571         amd64_emit_rex (mov_buf_ptr, sizeof(gpointer), MONO_ARCH_IMT_SCRATCH_REG, 0, AMD64_RIP);
 2572         *(mov_buf_ptr)++ = (unsigned char)0x8b; /* mov opcode */
 2573         x86_address_byte (mov_buf_ptr, 0, MONO_ARCH_IMT_SCRATCH_REG & 0x7, 5);
 2574         emit_bytes (acfg, mov_buf, mov_buf_ptr - mov_buf);
 2575         emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (target_mgreg_t)) - 4);
 2576     }
 2577     emit_bytes (acfg, buf, code - buf);
 2578 
 2579     *tramp_size = code - buf + kSizeOfMove;
 2580 
 2581     g_free (buf);
 2582 
 2583 #elif defined(TARGET_X86)
 2584     guint8 *buf, *code;
 2585     guint8 *labels [16];
 2586 
 2587     code = buf = g_malloc (256);
 2588 
 2589     /* Allocate a temporary stack slot */
 2590     x86_push_reg (code, X86_EAX);
 2591     /* Save EAX */
 2592     x86_push_reg (code, X86_EAX);
 2593 
 2594     /* Load mscorlib got address */
 2595     x86_mov_reg_membase (code, X86_EAX, MONO_ARCH_GOT_REG, sizeof (target_mgreg_t), 4);
 2596     /* Load arg */
 2597     x86_mov_reg_membase (code, X86_EAX, X86_EAX, offset * sizeof (target_mgreg_t), 4);
 2598 
 2599     labels [0] = code;
 2600     x86_alu_membase_imm (code, X86_CMP, X86_EAX, 0, 0);
 2601     labels [1] = code;
 2602     x86_branch8 (code, X86_CC_Z, FALSE, 0);
 2603 
 2604     /* Check key */
 2605     x86_alu_membase_reg (code, X86_CMP, X86_EAX, 0, MONO_ARCH_IMT_REG);
 2606     labels [2] = code;
 2607     x86_branch8 (code, X86_CC_Z, FALSE, 0);
 2608 
 2609     /* Loop footer */
 2610     x86_alu_reg_imm (code, X86_ADD, X86_EAX, 2 * sizeof (target_mgreg_t));
 2611     x86_jump_code (code, labels [0]);
 2612 
 2613     /* Match */
 2614     mono_x86_patch (labels [2], code);
 2615     x86_mov_reg_membase (code, X86_EAX, X86_EAX, sizeof (target_mgreg_t), 4);
 2616     x86_mov_reg_membase (code, X86_EAX, X86_EAX, 0, 4);
 2617     /* Save the target address to the temporary stack location */
 2618     x86_mov_membase_reg (code, X86_ESP, 4, X86_EAX, 4);
 2619     /* Restore EAX */
 2620     x86_pop_reg (code, X86_EAX);
 2621     /* Jump to the target address */
 2622     x86_ret (code);
 2623 
 2624     /* No match */
 2625     mono_x86_patch (labels [1], code);
 2626     /* Load fail tramp */
 2627     x86_mov_reg_membase (code, X86_EAX, X86_EAX, sizeof (target_mgreg_t), 4);
 2628     x86_alu_membase_imm (code, X86_CMP, X86_EAX, 0, 0);
 2629     labels [3] = code;
 2630     x86_branch8 (code, X86_CC_Z, FALSE, 0);
 2631     /* Jump to fail tramp */
 2632     x86_mov_membase_reg (code, X86_ESP, 4, X86_EAX, 4);
 2633     x86_pop_reg (code, X86_EAX);
 2634     x86_ret (code);
 2635 
 2636     /* Fail */
 2637     mono_x86_patch (labels [3], code);
 2638     x86_breakpoint (code);
 2639 
 2640     emit_bytes (acfg, buf, code - buf);
 2641     
 2642     *tramp_size = code - buf;
 2643 
 2644     g_free (buf);
 2645 
 2646 #elif defined(TARGET_ARM)
 2647     guint8 buf [128];
 2648     guint8 *code, *code2, *labels [16];
 2649 
 2650     code = buf;
 2651 
 2652     /* The IMT method is in v5 */
 2653 
 2654     /* Need at least two free registers, plus a slot for storing the pc */
 2655     ARM_PUSH (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_R2));
 2656     labels [0] = code;
 2657     /* Load the parameter from the GOT */
 2658     ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0);
 2659     ARM_LDR_REG_REG (code, ARMREG_R0, ARMREG_PC, ARMREG_R0);
 2660 
 2661     labels [1] = code;
 2662     ARM_LDR_IMM (code, ARMREG_R1, ARMREG_R0, 0);
 2663     ARM_CMP_REG_REG (code, ARMREG_R1, ARMREG_V5);
 2664     labels [2] = code;
 2665     ARM_B_COND (code, ARMCOND_EQ, 0);
 2666 
 2667     /* End-of-loop check */
 2668     ARM_CMP_REG_IMM (code, ARMREG_R1, 0, 0);
 2669     labels [3] = code;
 2670     ARM_B_COND (code, ARMCOND_EQ, 0);
 2671 
 2672     /* Loop footer */
 2673     ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (target_mgreg_t) * 2);
 2674     labels [4] = code;
 2675     ARM_B (code, 0);
 2676     arm_patch (labels [4], labels [1]);
 2677 
 2678     /* Match */
 2679     arm_patch (labels [2], code);
 2680     ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 4);
 2681     ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 0);
 2682     /* Save it to the third stack slot */
 2683     ARM_STR_IMM (code, ARMREG_R0, ARMREG_SP, 8);
 2684     /* Restore the registers and branch */
 2685     ARM_POP (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_PC));
 2686 
 2687     /* No match */
 2688     arm_patch (labels [3], code);
 2689     ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 4);
 2690     ARM_STR_IMM (code, ARMREG_R0, ARMREG_SP, 8);
 2691     ARM_POP (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_PC));
 2692 
 2693     /* Fixup offset */
 2694     code2 = labels [0];
 2695     ARM_LDR_IMM (code2, ARMREG_R0, ARMREG_PC, (code - (labels [0] + 8)));
 2696 
 2697     emit_bytes (acfg, buf, code - buf);
 2698     emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (target_mgreg_t)) + (code - (labels [0] + 8)) - 4);
 2699 
 2700     *tramp_size = code - buf + 4;
 2701 #elif defined(TARGET_ARM64)
 2702     arm64_emit_imt_trampoline (acfg, offset, tramp_size);
 2703 #elif defined(TARGET_POWERPC)
 2704     guint8 buf [128];
 2705     guint8 *code, *labels [16];
 2706 
 2707     code = buf;
 2708 
 2709     /* Load the mscorlib got address */
 2710     ppc_ldptr (code, ppc_r12, sizeof (target_mgreg_t), ppc_r30);
 2711     /* Load the parameter from the GOT */
 2712     ppc_load (code, ppc_r0, offset * sizeof (target_mgreg_t));
 2713     ppc_ldptr_indexed (code, ppc_r12, ppc_r12, ppc_r0);
 2714 
 2715     /* Load and check key */
 2716     labels [1] = code;
 2717     ppc_ldptr (code, ppc_r0, 0, ppc_r12);
 2718     ppc_cmp (code, 0, sizeof (target_mgreg_t) == 8 ? 1 : 0, ppc_r0, MONO_ARCH_IMT_REG);
 2719     labels [2] = code;
 2720     ppc_bc (code, PPC_BR_TRUE, PPC_BR_EQ, 0);
 2721 
 2722     /* End-of-loop check */
 2723     ppc_cmpi (code, 0, sizeof (target_mgreg_t) == 8 ? 1 : 0, ppc_r0, 0);
 2724     labels [3] = code;
 2725     ppc_bc (code, PPC_BR_TRUE, PPC_BR_EQ, 0);
 2726 
 2727     /* Loop footer */
 2728     ppc_addi (code, ppc_r12, ppc_r12, 2 * sizeof (target_mgreg_t));
 2729     labels [4] = code;
 2730     ppc_b (code, 0);
 2731     mono_ppc_patch (labels [4], labels [1]);
 2732 
 2733     /* Match */
 2734     mono_ppc_patch (labels [2], code);
 2735     ppc_ldptr (code, ppc_r12, sizeof (target_mgreg_t), ppc_r12);
 2736     /* r12 now contains the value of the vtable slot */
 2737     /* this is not a function descriptor on ppc64 */
 2738     ppc_ldptr (code, ppc_r12, 0, ppc_r12);
 2739     ppc_mtctr (code, ppc_r12);
 2740     ppc_bcctr (code, PPC_BR_ALWAYS, 0);
 2741 
 2742     /* Fail */
 2743     mono_ppc_patch (labels [3], code);
 2744     /* FIXME: */
 2745     ppc_break (code);
 2746 
 2747     *tramp_size = code - buf;
 2748 
 2749     emit_bytes (acfg, buf, code - buf);
 2750 #else
 2751     g_assert_not_reached ();
 2752 #endif
 2753 }
 2754 
 2755 
 2756 #if defined (TARGET_AMD64)
 2757 
 2758 static void
 2759 amd64_emit_load_got_slot (MonoAotCompile *acfg, int dreg, int got_slot)
 2760 {
 2761 
 2762     g_assert (acfg->fp);
 2763     emit_unset_mode (acfg);
 2764 
 2765     fprintf (acfg->fp, "mov %s+%d(%%rip), %s\n", acfg->got_symbol, (unsigned int) ((got_slot * sizeof (target_mgreg_t))), mono_arch_regname (dreg));
 2766 }
 2767 
 2768 #endif
 2769 
 2770 
 2771 /*
 2772  * arch_emit_gsharedvt_arg_trampoline:
 2773  *
 2774  *   Emit code for a gsharedvt arg trampoline. OFFSET is the offset of the first of
 2775  * two GOT slots which contain the argument, and the code to jump to.
 2776  * TRAMP_SIZE is set to the size of the emitted trampoline.
 2777  * These kinds of trampolines cannot be enumerated statically, since there could
 2778  * be one trampoline per method instantiation, so we emit the same code for all
 2779  * trampolines, and parameterize them using two GOT slots.
 2780  */
 2781 static void
 2782 arch_emit_gsharedvt_arg_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 2783 {
 2784 #if defined(TARGET_X86)
 2785     guint8 buf [128];
 2786     guint8 *code;
 2787 
 2788     /* Similar to the PPC code above */
 2789 
 2790     g_assert (MONO_ARCH_RGCTX_REG != X86_ECX);
 2791 
 2792     code = buf;
 2793     /* Load mscorlib got address */
 2794     x86_mov_reg_membase (code, X86_ECX, MONO_ARCH_GOT_REG, sizeof (target_mgreg_t), 4);
 2795     /* Load arg */
 2796     x86_mov_reg_membase (code, X86_EAX, X86_ECX, offset * sizeof (target_mgreg_t), 4);
 2797     /* Branch to the target address */
 2798     x86_jump_membase (code, X86_ECX, (offset + 1) * sizeof (target_mgreg_t));
 2799 
 2800     emit_bytes (acfg, buf, code - buf);
 2801 
 2802     *tramp_size = 15;
 2803     g_assert (code - buf == *tramp_size);
 2804 #elif defined(TARGET_ARM)
 2805     guint8 buf [128];
 2806     guint8 *code;
 2807 
 2808     /* The same as mono_arch_get_gsharedvt_arg_trampoline (), but for AOT */
 2809     /* Similar to arch_emit_specific_trampoline () */
 2810     *tramp_size = 24;
 2811     code = buf;
 2812     ARM_PUSH (code, (1 << ARMREG_R0) | (1 << ARMREG_R1) | (1 << ARMREG_R2) | (1 << ARMREG_R3));
 2813     ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 8);
 2814     /* Load the arg value from the GOT */
 2815     ARM_LDR_REG_REG (code, ARMREG_R0, ARMREG_PC, ARMREG_R1);
 2816     /* Load the addr from the GOT */
 2817     ARM_LDR_REG_REG (code, ARMREG_R1, ARMREG_PC, ARMREG_R1);
 2818     /* Branch to it */
 2819     ARM_BX (code, ARMREG_R1);
 2820 
 2821     g_assert (code - buf == 20);
 2822 
 2823     /* Emit it */
 2824     emit_bytes (acfg, buf, code - buf);
 2825     emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (target_mgreg_t)) + 4);
 2826 #elif defined(TARGET_ARM64)
 2827     arm64_emit_gsharedvt_arg_trampoline (acfg, offset, tramp_size);
 2828 #elif defined (TARGET_AMD64)
 2829 
 2830     amd64_emit_load_got_slot (acfg, AMD64_RAX, offset);
 2831     amd64_emit_load_got_slot (acfg, MONO_ARCH_IMT_SCRATCH_REG, offset + 1);
 2832     g_assert (AMD64_R11 == MONO_ARCH_IMT_SCRATCH_REG);
 2833     fprintf (acfg->fp, "jmp *%%r11\n");
 2834 
 2835     *tramp_size = 0x11;
 2836 #else
 2837     g_assert_not_reached ();
 2838 #endif
 2839 }   
 2840 
 2841 static void
 2842 arch_emit_ftnptr_arg_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 2843 {
 2844 #if defined(TARGET_ARM)
 2845     guint8 buf [128];
 2846     guint8 *code;
 2847 
 2848     *tramp_size = 32;
 2849     code = buf;
 2850 
 2851     /* Load target address and push it on stack */
 2852     ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 16);
 2853     ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP);
 2854     ARM_PUSH (code, 1 << ARMREG_IP);
 2855     /* Load argument in ARMREG_IP */
 2856     ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 8);
 2857     ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP);
 2858     /* Branch */
 2859     ARM_POP (code, 1 << ARMREG_PC);
 2860 
 2861     g_assert (code - buf == 24);
 2862 
 2863     /* Emit it */
 2864     emit_bytes (acfg, buf, code - buf);
 2865     emit_symbol_diff (acfg, acfg->got_symbol, ".", ((offset + 1) * sizeof (target_mgreg_t)) + 12); // offset from ldr pc to addr
 2866     emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (target_mgreg_t)) + 4); // offset from ldr pc to arg
 2867 #else
 2868     g_assert_not_reached ();
 2869 #endif
 2870 }
 2871 
 2872 static void
 2873 arch_emit_unbox_arbitrary_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 2874 {
 2875 #if defined(TARGET_ARM64)
 2876     emit_unset_mode (acfg);
 2877     fprintf (acfg->fp, "add x0, x0, %d\n", (int)(MONO_ABI_SIZEOF (MonoObject)));
 2878     arm64_emit_load_got_slot (acfg, ARMREG_R17, offset);
 2879     fprintf (acfg->fp, "br x17\n");
 2880     *tramp_size = 5 * 4;
 2881 #elif defined (TARGET_AMD64)
 2882     guint8 buf [32];
 2883     guint8 *code;
 2884     int this_reg;
 2885 
 2886     this_reg = mono_arch_get_this_arg_reg (NULL);
 2887     code = buf;
 2888     amd64_alu_reg_imm (code, X86_ADD, this_reg, MONO_ABI_SIZEOF (MonoObject));
 2889     emit_bytes (acfg, buf, code - buf);
 2890 
 2891     amd64_emit_load_got_slot (acfg, AMD64_RAX, offset);
 2892     fprintf (acfg->fp, "jmp *%%rax\n");
 2893 
 2894     *tramp_size = 13;
 2895 #elif defined (TARGET_ARM)
 2896     guint8 buf [32];
 2897     guint8 *code, *label;
 2898 
 2899     code = buf;
 2900     /* Unbox */
 2901     ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, MONO_ABI_SIZEOF (MonoObject));
 2902 
 2903     label = code;
 2904     /* Calculate GOT slot */
 2905     ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
 2906     /* Load target addr into PC*/
 2907     ARM_LDR_REG_REG (code, ARMREG_PC, ARMREG_PC, ARMREG_IP);
 2908 
 2909     g_assert (code - buf == 12);
 2910 
 2911     /* Emit it */
 2912     emit_bytes (acfg, buf, code - buf);
 2913     emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (target_mgreg_t)) + (code - (label + 8)) - 4);
 2914     *tramp_size = 4 * 4;
 2915 #else
 2916     g_error ("NOT IMPLEMENTED: needed for AOT<>interp mixed mode transition");
 2917 #endif
 2918 }
 2919 
 2920 /* END OF ARCH SPECIFIC CODE */
 2921 
 2922 static guint32
 2923 mono_get_field_token (MonoClassField *field) 
 2924 {
 2925     MonoClass *klass = field->parent;
 2926     int i;
 2927 
 2928     int fcount = mono_class_get_field_count (klass);
 2929     MonoClassField *klass_fields = m_class_get_fields (klass);
 2930     for (i = 0; i < fcount; ++i) {
 2931         if (field == &klass_fields [i])
 2932             return MONO_TOKEN_FIELD_DEF | (mono_class_get_first_field_idx (klass) + 1 + i);
 2933     }
 2934 
 2935     g_assert_not_reached ();
 2936     return 0;
 2937 }
 2938 
 2939 static void
 2940 encode_value (gint32 value, guint8 *buf, guint8 **endbuf)
 2941 {
 2942     guint8 *p = buf;
 2943 
 2944     //printf ("ENCODE: %d 0x%x.\n", value, value);
 2945 
 2946     /* 
 2947      * Same encoding as the one used in the metadata, extended to handle values
 2948      * greater than 0x1fffffff.
 2949      */
 2950     if ((value >= 0) && (value <= 127))
 2951         *p++ = value;
 2952     else if ((value >= 0) && (value <= 16383)) {
 2953         p [0] = 0x80 | (value >> 8);
 2954         p [1] = value & 0xff;
 2955         p += 2;
 2956     } else if ((value >= 0) && (value <= 0x1fffffff)) {
 2957         p [0] = (value >> 24) | 0xc0;
 2958         p [1] = (value >> 16) & 0xff;
 2959         p [2] = (value >> 8) & 0xff;
 2960         p [3] = value & 0xff;
 2961         p += 4;
 2962     }
 2963     else {
 2964         p [0] = 0xff;
 2965         p [1] = (value >> 24) & 0xff;
 2966         p [2] = (value >> 16) & 0xff;
 2967         p [3] = (value >> 8) & 0xff;
 2968         p [4] = value & 0xff;
 2969         p += 5;
 2970     }
 2971     if (endbuf)
 2972         *endbuf = p;
 2973 }
 2974 
 2975 static void
 2976 stream_init (MonoDynamicStream *sh)
 2977 {
 2978     sh->index = 0;
 2979     sh->alloc_size = 4096;
 2980     sh->data = (char *)g_malloc (4096);
 2981 
 2982     /* So offsets are > 0 */
 2983     sh->data [0] = 0;
 2984     sh->index ++;
 2985 }
 2986 
 2987 static void
 2988 make_room_in_stream (MonoDynamicStream *stream, int size)
 2989 {
 2990     if (size <= stream->alloc_size)
 2991         return;
 2992     
 2993     while (stream->alloc_size <= size) {
 2994         if (stream->alloc_size < 4096)
 2995             stream->alloc_size = 4096;
 2996         else
 2997             stream->alloc_size *= 2;
 2998     }
 2999     
 3000     stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
 3001 }
 3002 
 3003 static guint32
 3004 add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
 3005 {
 3006     guint32 idx;
 3007     
 3008     make_room_in_stream (stream, stream->index + len);
 3009     memcpy (stream->data + stream->index, data, len);
 3010     idx = stream->index;
 3011     stream->index += len;
 3012     return idx;
 3013 }
 3014 
 3015 /*
 3016  * add_to_blob:
 3017  *
 3018  *   Add data to the binary blob inside the aot image. Returns the offset inside the
 3019  * blob where the data was stored.
 3020  */
 3021 static guint32
 3022 add_to_blob (MonoAotCompile *acfg, const guint8 *data, guint32 data_len)
 3023 {
 3024     g_assert (!acfg->blob_closed);
 3025 
 3026     if (acfg->blob.alloc_size == 0)
 3027         stream_init (&acfg->blob);
 3028 
 3029     acfg->stats.blob_size += data_len;
 3030 
 3031     return add_stream_data (&acfg->blob, (char*)data, data_len);
 3032 }
 3033 
 3034 static guint32
 3035 add_to_blob_aligned (MonoAotCompile *acfg, const guint8 *data, guint32 data_len, guint32 align)
 3036 {
 3037     char buf [4] = {0};
 3038     guint32 count;
 3039 
 3040     if (acfg->blob.alloc_size == 0)
 3041         stream_init (&acfg->blob);
 3042 
 3043     count = acfg->blob.index % align;
 3044 
 3045     /* we assume the stream data will be aligned */
 3046     if (count)
 3047         add_stream_data (&acfg->blob, buf, 4 - count);
 3048 
 3049     return add_stream_data (&acfg->blob, (char*)data, data_len);
 3050 }
 3051 
 3052 /* Emit a table of data into the aot image */
 3053 static void
 3054 emit_aot_data (MonoAotCompile *acfg, MonoAotFileTable table, const char *symbol, guint8 *data, int size)
 3055 {
 3056     if (acfg->data_outfile) {
 3057         acfg->table_offsets [(int)table] = acfg->datafile_offset;
 3058         fwrite (data,1, size, acfg->data_outfile);
 3059         acfg->datafile_offset += size;
 3060         // align the data to 8 bytes. Put zeros in the file (so that every build results in consistent output).
 3061         int align = 8 - size % 8;
 3062         acfg->datafile_offset += align;
 3063         guint8 align_buf [16];
 3064         memset (&align_buf, 0, sizeof (align_buf));
 3065         fwrite (align_buf, align, 1, acfg->data_outfile);
 3066     } else if (acfg->llvm) {
 3067         mono_llvm_emit_aot_data (symbol, data, size);
 3068     } else {
 3069         emit_section_change (acfg, RODATA_SECT, 0);
 3070         emit_alignment (acfg, 8);
 3071         emit_label (acfg, symbol);
 3072         emit_bytes (acfg, data, size);
 3073     }
 3074 }
 3075 
 3076 /*
 3077  * emit_offset_table:
 3078  *
 3079  *   Emit a table of increasing offsets in a compact form using differential encoding.
 3080  * There is an index entry for each GROUP_SIZE number of entries. The greater the
 3081  * group size, the more compact the table becomes, but the slower it becomes to compute
 3082  * a given entry. Returns the size of the table.
 3083  */
 3084 static guint32
 3085 emit_offset_table (MonoAotCompile *acfg, const char *symbol, MonoAotFileTable table, int noffsets, int group_size, gint32 *offsets)
 3086 {
 3087     gint32 current_offset;
 3088     int i, buf_size, ngroups, index_entry_size;
 3089     guint8 *p, *buf;
 3090     guint8 *data_p, *data_buf;
 3091     guint32 *index_offsets;
 3092 
 3093     ngroups = (noffsets + (group_size - 1)) / group_size;
 3094 
 3095     index_offsets = g_new0 (guint32, ngroups);
 3096 
 3097     buf_size = noffsets * 4;
 3098     p = buf = (guint8 *)g_malloc0 (buf_size);
 3099 
 3100     current_offset = 0;
 3101     for (i = 0; i < noffsets; ++i) {
 3102         //printf ("D: %d -> %d\n", i, offsets [i]);
 3103         if ((i % group_size) == 0) {
 3104             index_offsets [i / group_size] = p - buf;
 3105             /* Emit the full value for these entries */
 3106             encode_value (offsets [i], p, &p);
 3107         } else {
 3108             /* The offsets are allowed to be non-increasing */
 3109             //g_assert (offsets [i] >= current_offset);
 3110             encode_value (offsets [i] - current_offset, p, &p);
 3111         }
 3112         current_offset = offsets [i];
 3113     }
 3114     data_buf = buf;
 3115     data_p = p;
 3116 
 3117     if (ngroups && index_offsets [ngroups - 1] < 65000)
 3118         index_entry_size = 2;
 3119     else
 3120         index_entry_size = 4;
 3121 
 3122     buf_size = (data_p - data_buf) + (ngroups * 4) + 16;
 3123     p = buf = (guint8 *)g_malloc0 (buf_size);
 3124 
 3125     /* Emit the header */
 3126     encode_int (noffsets, p, &p);
 3127     encode_int (group_size, p, &p);
 3128     encode_int (ngroups, p, &p);
 3129     encode_int (index_entry_size, p, &p);
 3130 
 3131     /* Emit the index */
 3132     for (i = 0; i < ngroups; ++i) {
 3133         if (index_entry_size == 2)
 3134             encode_int16 (index_offsets [i], p, &p);
 3135         else
 3136             encode_int (index_offsets [i], p, &p);
 3137     }
 3138     /* Emit the data */
 3139     memcpy (p, data_buf, data_p - data_buf);
 3140     p += data_p - data_buf;
 3141 
 3142     g_assert (p - buf <= buf_size);
 3143 
 3144     emit_aot_data (acfg, table, symbol, buf, p - buf);
 3145 
 3146     g_free (buf);
 3147     g_free (data_buf);
 3148 
 3149     return (int)(p - buf);
 3150 }
 3151 
 3152 static guint32
 3153 get_image_index (MonoAotCompile *cfg, MonoImage *image)
 3154 {
 3155     guint32 index;
 3156 
 3157     index = GPOINTER_TO_UINT (g_hash_table_lookup (cfg->image_hash, image));
 3158     if (index)
 3159         return index - 1;
 3160     else {
 3161         index = g_hash_table_size (cfg->image_hash);
 3162         g_hash_table_insert (cfg->image_hash, image, GUINT_TO_POINTER (index + 1));
 3163         g_ptr_array_add (cfg->image_table, image);
 3164         return index;
 3165     }
 3166 }
 3167 
 3168 static guint32
 3169 find_typespec_for_class (MonoAotCompile *acfg, MonoClass *klass)
 3170 {
 3171     int i;
 3172     int len = acfg->image->tables [MONO_TABLE_TYPESPEC].rows;
 3173 
 3174     /* FIXME: Search referenced images as well */
 3175     if (!acfg->typespec_classes) {
 3176         acfg->typespec_classes = g_hash_table_new (NULL, NULL);
 3177         for (i = 0; i < len; i++) {
 3178             ERROR_DECL (error);
 3179             int typespec = MONO_TOKEN_TYPE_SPEC | (i + 1);
 3180             MonoClass *klass_key = mono_class_get_and_inflate_typespec_checked (acfg->image, typespec, NULL, error);
 3181             if (!is_ok (error)) {
 3182                 mono_error_cleanup (error);
 3183                 continue;
 3184             }
 3185             g_hash_table_insert (acfg->typespec_classes, klass_key, GINT_TO_POINTER (typespec));
 3186         }
 3187     }
 3188     return GPOINTER_TO_INT (g_hash_table_lookup (acfg->typespec_classes, klass));
 3189 }
 3190 
 3191 static void
 3192 encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 **endbuf);
 3193 
 3194 static void
 3195 encode_klass_ref (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, guint8 **endbuf);
 3196 
 3197 static void
 3198 encode_ginst (MonoAotCompile *acfg, MonoGenericInst *inst, guint8 *buf, guint8 **endbuf);
 3199 
 3200 static void
 3201 encode_type (MonoAotCompile *acfg, MonoType *t, guint8 *buf, guint8 **endbuf);
 3202 
 3203 static guint32
 3204 get_shared_ginst_ref (MonoAotCompile *acfg, MonoGenericInst *ginst);
 3205 
 3206 static void
 3207 encode_klass_ref_inner (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, guint8 **endbuf)
 3208 {
 3209     guint8 *p = buf;
 3210 
 3211     /*
 3212      * The encoding begins with one of the MONO_AOT_TYPEREF values, followed by additional
 3213      * information.
 3214      */
 3215 
 3216     if (mono_class_is_ginst (klass)) {
 3217         guint32 token;
 3218         g_assert (m_class_get_type_token (klass));
 3219 
 3220         /* Find a typespec for a class if possible */
 3221         token = find_typespec_for_class (acfg, klass);
 3222         if (token) {
 3223             encode_value (MONO_AOT_TYPEREF_TYPESPEC_TOKEN, p, &p);
 3224             encode_value (token, p, &p);
 3225         } else {
 3226             MonoClass *gclass = mono_class_get_generic_class (klass)->container_class;
 3227             MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
 3228             static int count = 0;
 3229             guint8 *p1 = p;
 3230 
 3231             encode_value (MONO_AOT_TYPEREF_GINST, p, &p);
 3232             encode_klass_ref (acfg, gclass, p, &p);
 3233             guint32 offset = get_shared_ginst_ref (acfg, inst);
 3234             encode_value (offset, p, &p);
 3235 
 3236             count += p - p1;
 3237         }
 3238     } else if (m_class_get_type_token (klass)) {
 3239         int iindex = get_image_index (acfg, m_class_get_image (klass));
 3240 
 3241         g_assert (mono_metadata_token_code (m_class_get_type_token (klass)) == MONO_TOKEN_TYPE_DEF);
 3242         if (iindex == 0) {
 3243             encode_value (MONO_AOT_TYPEREF_TYPEDEF_INDEX, p, &p);
 3244             encode_value (m_class_get_type_token (klass) - MONO_TOKEN_TYPE_DEF, p, &p);
 3245         } else {
 3246             encode_value (MONO_AOT_TYPEREF_TYPEDEF_INDEX_IMAGE, p, &p);
 3247             encode_value (m_class_get_type_token (klass) - MONO_TOKEN_TYPE_DEF, p, &p);
 3248             encode_value (get_image_index (acfg, m_class_get_image (klass)), p, &p);
 3249         }
 3250     } else if ((m_class_get_byval_arg (klass)->type == MONO_TYPE_VAR) || (m_class_get_byval_arg (klass)->type == MONO_TYPE_MVAR)) {
 3251         MonoGenericContainer *container = mono_type_get_generic_param_owner (m_class_get_byval_arg (klass));
 3252         MonoGenericParam *par = m_class_get_byval_arg (klass)->data.generic_param;
 3253 
 3254         encode_value (MONO_AOT_TYPEREF_VAR, p, &p);
 3255 
 3256         encode_value (par->gshared_constraint ? 1 : 0, p, &p);
 3257         if (par->gshared_constraint) {
 3258             MonoGSharedGenericParam *gpar = (MonoGSharedGenericParam*)par;
 3259             encode_type (acfg, par->gshared_constraint, p, &p);
 3260             encode_klass_ref (acfg, mono_class_create_generic_parameter (gpar->parent), p, &p);
 3261         } else {
 3262             encode_value (m_class_get_byval_arg (klass)->type, p, &p);
 3263             encode_value (mono_type_get_generic_param_num (m_class_get_byval_arg (klass)), p, &p);
 3264 
 3265             encode_value (container->is_anonymous ? 0 : 1, p, &p);
 3266 
 3267             if (!container->is_anonymous) {
 3268                 encode_value (container->is_method, p, &p);
 3269                 if (container->is_method)
 3270                     encode_method_ref (acfg, container->owner.method, p, &p);
 3271                 else
 3272                     encode_klass_ref (acfg, container->owner.klass, p, &p);
 3273             }
 3274         }
 3275     } else if (m_class_get_byval_arg (klass)->type == MONO_TYPE_PTR) {
 3276         encode_value (MONO_AOT_TYPEREF_PTR, p, &p);
 3277         encode_type (acfg, m_class_get_byval_arg (klass), p, &p);
 3278     } else {
 3279         /* Array class */
 3280         g_assert (m_class_get_rank (klass) > 0);
 3281         encode_value (MONO_AOT_TYPEREF_ARRAY, p, &p);
 3282         encode_value (m_class_get_rank (klass), p, &p);
 3283         encode_klass_ref (acfg, m_class_get_element_class (klass), p, &p);
 3284     }
 3285 
 3286     acfg->stats.class_ref_count++;
 3287     acfg->stats.class_ref_size += p - buf;
 3288 
 3289     *endbuf = p;
 3290 }
 3291 
 3292 static guint32
 3293 get_shared_klass_ref (MonoAotCompile *acfg, MonoClass *klass)
 3294 {
 3295     guint offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->klass_blob_hash, klass));
 3296     guint8 *buf2, *p;
 3297 
 3298     if (!offset) {
 3299         buf2 = (guint8 *)g_malloc (1024);
 3300         p = buf2;
 3301 
 3302         encode_klass_ref_inner (acfg, klass, p, &p);
 3303         g_assert (p - buf2 < 1024);
 3304 
 3305         offset = add_to_blob (acfg, buf2, p - buf2);
 3306         g_free (buf2);
 3307 
 3308         g_hash_table_insert (acfg->klass_blob_hash, klass, GUINT_TO_POINTER (offset + 1));
 3309     } else {
 3310         offset --;
 3311     }
 3312 
 3313     return offset;
 3314 }
 3315 
 3316 /*
 3317  * encode_klass_ref:
 3318  *
 3319  *   Encode a reference to KLASS. We use our home-grown encoding instead of the
 3320  * standard metadata encoding.
 3321  */
 3322 static void
 3323 encode_klass_ref (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, guint8 **endbuf)
 3324 {
 3325     gboolean shared = FALSE;
 3326 
 3327     /* 
 3328      * The encoding of generic instances is large so emit them only once.
 3329      */
 3330     if (mono_class_is_ginst (klass)) {
 3331         guint32 token;
 3332         g_assert (m_class_get_type_token (klass));
 3333 
 3334         /* Find a typespec for a class if possible */
 3335         token = find_typespec_for_class (acfg, klass);
 3336         if (!token)
 3337             shared = TRUE;
 3338     } else if ((m_class_get_byval_arg (klass)->type == MONO_TYPE_VAR) || (m_class_get_byval_arg (klass)->type == MONO_TYPE_MVAR)) {
 3339         shared = TRUE;
 3340     }
 3341 
 3342     if (shared) {
 3343         guint8 *p;
 3344         guint32 offset = get_shared_klass_ref (acfg, klass);
 3345 
 3346         p = buf;
 3347         encode_value (MONO_AOT_TYPEREF_BLOB_INDEX, p, &p);
 3348         encode_value (offset, p, &p);
 3349         *endbuf = p;
 3350         return;
 3351     }
 3352 
 3353     encode_klass_ref_inner (acfg, klass, buf, endbuf);
 3354 }
 3355 
 3356 static void
 3357 encode_field_info (MonoAotCompile *cfg, MonoClassField *field, guint8 *buf, guint8 **endbuf)
 3358 {
 3359     guint32 token = mono_get_field_token (field);
 3360     guint8 *p = buf;
 3361 
 3362     encode_klass_ref (cfg, field->parent, p, &p);
 3363     g_assert (mono_metadata_token_code (token) == MONO_TOKEN_FIELD_DEF);
 3364     encode_value (token - MONO_TOKEN_FIELD_DEF, p, &p);
 3365     *endbuf = p;
 3366 }
 3367 
 3368 static void
 3369 encode_ginst (MonoAotCompile *acfg, MonoGenericInst *inst, guint8 *buf, guint8 **endbuf)
 3370 {
 3371     guint8 *p = buf;
 3372     int i;
 3373 
 3374     encode_value (inst->type_argc, p, &p);
 3375     for (i = 0; i < inst->type_argc; ++i)
 3376         encode_klass_ref (acfg, mono_class_from_mono_type_internal (inst->type_argv [i]), p, &p);
 3377 
 3378     acfg->stats.ginst_count++;
 3379     acfg->stats.ginst_size += p - buf;
 3380 
 3381     *endbuf = p;
 3382 }
 3383 
 3384 static guint32
 3385 get_shared_ginst_ref (MonoAotCompile *acfg, MonoGenericInst *ginst)
 3386 {
 3387     guint32 offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->ginst_blob_hash, ginst));
 3388     if (!offset) {
 3389         guint8 *buf2, *p2;
 3390         int len;
 3391 
 3392         len = 1024 + (ginst->type_argc * 32);
 3393         buf2 = (guint8 *)g_malloc (len);
 3394         p2 = buf2;
 3395 
 3396         encode_ginst (acfg, ginst, p2, &p2);
 3397         g_assert (p2 - buf2 < len);
 3398 
 3399         offset = add_to_blob (acfg, buf2, p2 - buf2);
 3400         g_free (buf2);
 3401 
 3402         g_hash_table_insert (acfg->ginst_blob_hash, ginst, GUINT_TO_POINTER (offset + 1));
 3403     } else {
 3404         offset --;
 3405     }
 3406     return offset;
 3407 }
 3408 
 3409 static void
 3410 encode_generic_context (MonoAotCompile *acfg, MonoGenericContext *context, guint8 *buf, guint8 **endbuf)
 3411 {
 3412     guint8 *p = buf;
 3413     MonoGenericInst *inst;
 3414     guint32 flags = (context->class_inst ? 1 : 0) | (context->method_inst ? 2 : 0);
 3415 
 3416     g_assert (flags);
 3417 
 3418     encode_value (flags, p, &p);
 3419     inst = context->class_inst;
 3420     if (inst) {
 3421         guint32 offset = get_shared_ginst_ref (acfg, inst);
 3422         encode_value (offset, p, &p);
 3423     }
 3424     inst = context->method_inst;
 3425     if (inst) {
 3426         guint32 offset = get_shared_ginst_ref (acfg, inst);
 3427         encode_value (offset, p, &p);
 3428     }
 3429     *endbuf = p;
 3430 }
 3431 
 3432 static void
 3433 encode_type (MonoAotCompile *acfg, MonoType *t, guint8 *buf, guint8 **endbuf)
 3434 {
 3435     guint8 *p = buf;
 3436 
 3437     if (t->has_cmods) {
 3438         int count = mono_type_custom_modifier_count (t);
 3439 
 3440         *p = MONO_TYPE_CMOD_REQD;
 3441         ++p;
 3442 
 3443         encode_value (count, p, &p);
 3444         for (int i = 0; i < count; ++i) {
 3445             ERROR_DECL (error);
 3446             gboolean required;
 3447             MonoType *cmod_type = mono_type_get_custom_modifier (t, i, &required, error);
 3448             mono_error_assert_ok (error);
 3449             encode_value (required, p, &p);
 3450             encode_type (acfg, cmod_type, p, &p);
 3451         }
 3452     }
 3453 
 3454     /* t->attrs can be ignored */
 3455     //g_assert (t->attrs == 0);
 3456 
 3457     if (t->pinned) {
 3458         *p = MONO_TYPE_PINNED;
 3459         ++p;
 3460     }
 3461     if (t->byref) {
 3462         *p = MONO_TYPE_BYREF;
 3463         ++p;
 3464     }
 3465 
 3466     *p = t->type;
 3467     p ++;
 3468 
 3469     switch (t->type) {
 3470     case MONO_TYPE_VOID:
 3471     case MONO_TYPE_BOOLEAN:
 3472     case MONO_TYPE_CHAR:
 3473     case MONO_TYPE_I1:
 3474     case MONO_TYPE_U1:
 3475     case MONO_TYPE_I2:
 3476     case MONO_TYPE_U2:
 3477     case MONO_TYPE_I4:
 3478     case MONO_TYPE_U4:
 3479     case MONO_TYPE_I8:
 3480     case MONO_TYPE_U8:
 3481     case MONO_TYPE_R4:
 3482     case MONO_TYPE_R8:
 3483     case MONO_TYPE_I:
 3484     case MONO_TYPE_U:
 3485     case MONO_TYPE_STRING:
 3486     case MONO_TYPE_OBJECT:
 3487     case MONO_TYPE_TYPEDBYREF:
 3488         break;
 3489     case MONO_TYPE_VALUETYPE:
 3490     case MONO_TYPE_CLASS:
 3491         encode_klass_ref (acfg, mono_class_from_mono_type_internal (t), p, &p);
 3492         break;
 3493     case MONO_TYPE_SZARRAY:
 3494         encode_klass_ref (acfg, t->data.klass, p, &p);
 3495         break;
 3496     case MONO_TYPE_PTR:
 3497         encode_type (acfg, t->data.type, p, &p);
 3498         break;
 3499     case MONO_TYPE_GENERICINST: {
 3500         MonoClass *gclass = t->data.generic_class->container_class;
 3501         MonoGenericInst *inst = t->data.generic_class->context.class_inst;
 3502 
 3503         encode_klass_ref (acfg, gclass, p, &p);
 3504         encode_ginst (acfg, inst, p, &p);
 3505         break;
 3506     }
 3507     case MONO_TYPE_ARRAY: {
 3508         MonoArrayType *array = t->data.array;
 3509         int i;
 3510 
 3511         encode_klass_ref (acfg, array->eklass, p, &p);
 3512         encode_value (array->rank, p, &p);
 3513         encode_value (array->numsizes, p, &p);
 3514         for (i = 0; i < array->numsizes; ++i)
 3515             encode_value (array->sizes [i], p, &p);
 3516         encode_value (array->numlobounds, p, &p);
 3517         for (i = 0; i < array->numlobounds; ++i)
 3518             encode_value (array->lobounds [i], p, &p);
 3519         break;
 3520     }
 3521     case MONO_TYPE_VAR:
 3522     case MONO_TYPE_MVAR:
 3523         encode_klass_ref (acfg, mono_class_from_mono_type_internal (t), p, &p);
 3524         break;
 3525     default:
 3526         g_assert_not_reached ();
 3527     }
 3528 
 3529     *endbuf = p;
 3530 }
 3531 
 3532 static void
 3533 encode_signature (MonoAotCompile *acfg, MonoMethodSignature *sig, guint8 *buf, guint8 **endbuf)
 3534 {
 3535     guint8 *p = buf;
 3536     guint32 flags = 0;
 3537     int i;
 3538 
 3539     /* Similar to the metadata encoding */
 3540     if (sig->generic_param_count)
 3541         flags |= 0x10;
 3542     if (sig->hasthis)
 3543         flags |= 0x20;
 3544     if (sig->explicit_this)
 3545         flags |= 0x40;
 3546     flags |= (sig->call_convention & 0x0F);
 3547 
 3548     *p = flags;
 3549     ++p;
 3550     if (sig->generic_param_count)
 3551         encode_value (sig->generic_param_count, p, &p);
 3552     encode_value (sig->param_count, p, &p);
 3553 
 3554     encode_type (acfg, sig->ret, p, &p);
 3555     for (i = 0; i < sig->param_count; ++i) {
 3556         if (sig->sentinelpos == i) {
 3557             *p = MONO_TYPE_SENTINEL;
 3558             ++p;
 3559         }
 3560         encode_type (acfg, sig->params [i], p, &p);
 3561     }
 3562 
 3563     *endbuf = p;
 3564 }
 3565 
 3566 #define MAX_IMAGE_INDEX 250
 3567 
 3568 static void
 3569 encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 **endbuf)
 3570 {
 3571     guint32 image_index = get_image_index (acfg, m_class_get_image (method->klass));
 3572     guint32 token = method->token;
 3573     MonoJumpInfoToken *ji;
 3574     guint8 *p = buf;
 3575 
 3576     /*
 3577      * The encoding for most methods is as follows:
 3578      * - image index encoded as a leb128
 3579      * - token index encoded as a leb128
 3580      * Values of image index >= MONO_AOT_METHODREF_MIN are used to mark additional
 3581      * types of method encodings.
 3582      */
 3583 
 3584     /* Mark methods which can't use aot trampolines because they need the further 
 3585      * processing in mono_magic_trampoline () which requires a MonoMethod*.
 3586      */
 3587     if ((method->is_generic && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) ||
 3588         (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED))
 3589         encode_value ((MONO_AOT_METHODREF_NO_AOT_TRAMPOLINE << 24), p, &p);
 3590 
 3591     if (method->wrapper_type) {
 3592         WrapperInfo *info = mono_marshal_get_wrapper_info (method);
 3593 
 3594         encode_value ((MONO_AOT_METHODREF_WRAPPER << 24), p, &p);
 3595 
 3596         encode_value (method->wrapper_type, p, &p);
 3597 
 3598         switch (method->wrapper_type) {
 3599         case MONO_WRAPPER_REMOTING_INVOKE:
 3600         case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
 3601         case MONO_WRAPPER_XDOMAIN_INVOKE: {
 3602             MonoMethod *m;
 3603 
 3604             m = mono_marshal_method_from_wrapper (method);
 3605             g_assert (m);
 3606             encode_method_ref (acfg, m, p, &p);
 3607             break;
 3608         }
 3609         case MONO_WRAPPER_PROXY_ISINST:
 3610         case MONO_WRAPPER_LDFLD:
 3611         case MONO_WRAPPER_LDFLDA:
 3612         case MONO_WRAPPER_STFLD: {
 3613             g_assert (info);
 3614             encode_klass_ref (acfg, info->d.proxy.klass, p, &p);
 3615             break;
 3616         }
 3617         case MONO_WRAPPER_ALLOC: {
 3618             /* The GC name is saved once in MonoAotFileInfo */
 3619             g_assert (info->d.alloc.alloc_type != -1);
 3620             encode_value (info->d.alloc.alloc_type, p, &p);
 3621             break;
 3622         }
 3623         case MONO_WRAPPER_WRITE_BARRIER: {
 3624             g_assert (info);
 3625             break;
 3626         }
 3627         case MONO_WRAPPER_STELEMREF: {
 3628             g_assert (info);
 3629             encode_value (info->subtype, p, &p);
 3630             if (info->subtype == WRAPPER_SUBTYPE_VIRTUAL_STELEMREF)
 3631                 encode_value (info->d.virtual_stelemref.kind, p, &p);
 3632             break;
 3633         }
 3634         case MONO_WRAPPER_OTHER: {
 3635             g_assert (info);
 3636             encode_value (info->subtype, p, &p);
 3637             if (info->subtype == WRAPPER_SUBTYPE_PTR_TO_STRUCTURE ||
 3638                 info->subtype == WRAPPER_SUBTYPE_STRUCTURE_TO_PTR)
 3639                 encode_klass_ref (acfg, method->klass, p, &p);
 3640             else if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER)
 3641                 encode_method_ref (acfg, info->d.synchronized_inner.method, p, &p);
 3642             else if (info->subtype == WRAPPER_SUBTYPE_ARRAY_ACCESSOR)
 3643                 encode_method_ref (acfg, info->d.array_accessor.method, p, &p);
 3644             else if (info->subtype == WRAPPER_SUBTYPE_INTERP_IN)
 3645                 encode_signature (acfg, info->d.interp_in.sig, p, &p);
 3646             else if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG)
 3647                 encode_signature (acfg, info->d.gsharedvt.sig, p, &p);
 3648             else if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG)
 3649                 encode_signature (acfg, info->d.gsharedvt.sig, p, &p);
 3650             else if (info->subtype == WRAPPER_SUBTYPE_INTERP_LMF)
 3651                 encode_value (info->d.icall.jit_icall_id, p, &p);
 3652             else if (info->subtype == WRAPPER_SUBTYPE_AOT_INIT)
 3653                 encode_value (info->d.aot_init.subtype, p, &p);
 3654             else if (info->subtype == WRAPPER_SUBTYPE_LLVM_FUNC)
 3655                 encode_value (info->d.llvm_func.subtype, p, &p);
 3656             break;
 3657         }
 3658         case MONO_WRAPPER_MANAGED_TO_NATIVE: {
 3659             g_assert (info);
 3660             encode_value (info->subtype, p, &p);
 3661             if (info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
 3662                 encode_value (info->d.icall.jit_icall_id, p, &p);
 3663             } else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_AOT) {
 3664                 encode_method_ref (acfg, info->d.managed_to_native.method, p, &p);
 3665             } else {
 3666                 g_assert (info->subtype == WRAPPER_SUBTYPE_NONE || info->subtype == WRAPPER_SUBTYPE_PINVOKE);
 3667                 encode_method_ref (acfg, info->d.managed_to_native.method, p, &p);
 3668             }
 3669             break;
 3670         }
 3671         case MONO_WRAPPER_SYNCHRONIZED: {
 3672             MonoMethod *m;
 3673 
 3674             m = mono_marshal_method_from_wrapper (method);
 3675             g_assert (m);
 3676             g_assert (m != method);
 3677             encode_method_ref (acfg, m, p, &p);
 3678             break;
 3679         }
 3680         case MONO_WRAPPER_MANAGED_TO_MANAGED: {
 3681             g_assert (info);
 3682             encode_value (info->subtype, p, &p);
 3683 
 3684             if (info->subtype == WRAPPER_SUBTYPE_ELEMENT_ADDR) {
 3685                 encode_value (info->d.element_addr.rank, p, &p);
 3686                 encode_value (info->d.element_addr.elem_size, p, &p);
 3687             } else if (info->subtype == WRAPPER_SUBTYPE_STRING_CTOR) {
 3688                 encode_method_ref (acfg, info->d.string_ctor.method, p, &p);
 3689             } else {
 3690                 g_assert_not_reached ();
 3691             }
 3692             break;
 3693         }
 3694         case MONO_WRAPPER_CASTCLASS: {
 3695             g_assert (info);
 3696             encode_value (info->subtype, p, &p);
 3697             break;
 3698         }
 3699         case MONO_WRAPPER_RUNTIME_INVOKE: {
 3700             g_assert (info);
 3701             encode_value (info->subtype, p, &p);
 3702             if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT || info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL)
 3703                 encode_method_ref (acfg, info->d.runtime_invoke.method, p, &p);
 3704             else if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL)
 3705                 encode_signature (acfg, info->d.runtime_invoke.sig, p, &p);
 3706             break;
 3707         }
 3708         case MONO_WRAPPER_DELEGATE_INVOKE:
 3709         case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE:
 3710         case MONO_WRAPPER_DELEGATE_END_INVOKE: {
 3711             if (method->is_inflated) {
 3712                 /* These wrappers are identified by their class */
 3713                 encode_value (1, p, &p);
 3714                 encode_klass_ref (acfg, method->klass, p, &p);
 3715             } else {
 3716                 MonoMethodSignature *sig = mono_method_signature_internal (method);
 3717                 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
 3718 
 3719                 encode_value (0, p, &p);
 3720                 if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE)
 3721                     encode_value (info ? info->subtype : 0, p, &p);
 3722                 encode_signature (acfg, sig, p, &p);
 3723             }
 3724             break;
 3725         }
 3726         case MONO_WRAPPER_NATIVE_TO_MANAGED: {
 3727             g_assert (info);
 3728             encode_method_ref (acfg, info->d.native_to_managed.method, p, &p);
 3729             encode_klass_ref (acfg, info->d.native_to_managed.klass, p, &p);
 3730             break;
 3731         }
 3732         default:
 3733             g_assert_not_reached ();
 3734         }
 3735     } else if (mono_method_signature_internal (method)->is_inflated) {
 3736         /* 
 3737          * This is a generic method, find the original token which referenced it and
 3738          * encode that.
 3739          * Obtain the token from information recorded by the JIT.
 3740          */
 3741         ji = (MonoJumpInfoToken *)g_hash_table_lookup (acfg->token_info_hash, method);
 3742         if (ji) {
 3743             image_index = get_image_index (acfg, ji->image);
 3744             g_assert (image_index < MAX_IMAGE_INDEX);
 3745             token = ji->token;
 3746 
 3747             encode_value ((MONO_AOT_METHODREF_METHODSPEC << 24), p, &p);
 3748             encode_value (image_index, p, &p);
 3749             encode_value (token, p, &p);
 3750         } else if (g_hash_table_lookup (acfg->method_blob_hash, method)) {
 3751             /* Already emitted as part of an rgctx fetch */
 3752             guint32 offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_blob_hash, method));
 3753             offset --;
 3754 
 3755             encode_value ((MONO_AOT_METHODREF_BLOB_INDEX << 24), p, &p);
 3756             encode_value (offset, p, &p);
 3757         } else {
 3758             MonoMethod *declaring;
 3759             MonoGenericContext *context = mono_method_get_context (method);
 3760 
 3761             g_assert (method->is_inflated);
 3762             declaring = ((MonoMethodInflated*)method)->declaring;
 3763 
 3764             /*
 3765              * This might be a non-generic method of a generic instance, which 
 3766              * doesn't have a token since the reference is generated by the JIT 
 3767              * like Nullable:Box/Unbox, or by generic sharing.
 3768              */
 3769             encode_value ((MONO_AOT_METHODREF_GINST << 24), p, &p);
 3770             /* Encode the klass */
 3771             encode_klass_ref (acfg, method->klass, p, &p);
 3772             /* Encode the method */
 3773             image_index = get_image_index (acfg, m_class_get_image (method->klass));
 3774             g_assert (image_index < MAX_IMAGE_INDEX);
 3775             g_assert (declaring->token);
 3776             token = declaring->token;
 3777             g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
 3778             encode_value (image_index, p, &p);
 3779             encode_value (mono_metadata_token_index (token), p, &p);
 3780             encode_generic_context (acfg, context, p, &p);
 3781         }
 3782     } else if (token == 0) {
 3783         /* This might be a method of a constructed type like int[,].Set */
 3784         /* Obtain the token from information recorded by the JIT */
 3785         ji = (MonoJumpInfoToken *)g_hash_table_lookup (acfg->token_info_hash, method);
 3786         if (ji) {
 3787             image_index = get_image_index (acfg, ji->image);
 3788             g_assert (image_index < MAX_IMAGE_INDEX);
 3789             token = ji->token;
 3790 
 3791             encode_value ((MONO_AOT_METHODREF_METHODSPEC << 24), p, &p);
 3792             encode_value (image_index, p, &p);
 3793             encode_value (token, p, &p);
 3794         } else {
 3795             /* Array methods */
 3796             g_assert (m_class_get_rank (method->klass));
 3797 
 3798             /* Encode directly */
 3799             encode_value ((MONO_AOT_METHODREF_ARRAY << 24), p, &p);
 3800             encode_klass_ref (acfg, method->klass, p, &p);
 3801             if (!strcmp (method->name, ".ctor") && mono_method_signature_internal (method)->param_count == m_class_get_rank (method->klass))
 3802                 encode_value (0, p, &p);
 3803             else if (!strcmp (method->name, ".ctor") && mono_method_signature_internal (method)->param_count == m_class_get_rank (method->klass) * 2)
 3804                 encode_value (1, p, &p);
 3805             else if (!strcmp (method->name, "Get"))
 3806                 encode_value (2, p, &p);
 3807             else if (!strcmp (method->name, "Address"))
 3808                 encode_value (3, p, &p);
 3809             else if (!strcmp (method->name, "Set"))
 3810                 encode_value (4, p, &p);
 3811             else
 3812                 g_assert_not_reached ();
 3813         }
 3814     } else {
 3815         g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
 3816 
 3817         if (image_index >= MONO_AOT_METHODREF_MIN) {
 3818             encode_value ((MONO_AOT_METHODREF_LARGE_IMAGE_INDEX << 24), p, &p);
 3819             encode_value (image_index, p, &p);
 3820             encode_value (mono_metadata_token_index (token), p, &p);
 3821         } else {
 3822             encode_value ((image_index << 24) | mono_metadata_token_index (token), p, &p);
 3823         }
 3824     }
 3825 
 3826     acfg->stats.method_ref_count++;
 3827     acfg->stats.method_ref_size += p - buf;
 3828 
 3829     *endbuf = p;
 3830 }
 3831 
 3832 static guint32
 3833 get_shared_method_ref (MonoAotCompile *acfg, MonoMethod *method)
 3834 {
 3835     guint32 offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_blob_hash, method));
 3836     if (!offset) {
 3837         guint8 *buf2, *p2;
 3838 
 3839         buf2 = (guint8 *)g_malloc (1024);
 3840         p2 = buf2;
 3841 
 3842         encode_method_ref (acfg, method, p2, &p2);
 3843         g_assert (p2 - buf2 < 1024);
 3844 
 3845         offset = add_to_blob (acfg, buf2, p2 - buf2);
 3846         g_free (buf2);
 3847 
 3848         g_hash_table_insert (acfg->method_blob_hash, method, GUINT_TO_POINTER (offset + 1));
 3849     } else {
 3850         offset --;
 3851     }
 3852     return offset;
 3853 }
 3854 
 3855 static gint
 3856 compare_patches (gconstpointer a, gconstpointer b)
 3857 {
 3858     int i, j;
 3859 
 3860     i = (*(MonoJumpInfo**)a)->ip.i;
 3861     j = (*(MonoJumpInfo**)b)->ip.i;
 3862 
 3863     if (i < j)
 3864         return -1;
 3865     else
 3866         if (i > j)
 3867             return 1;
 3868     else
 3869         return 0;
 3870 }
 3871 
 3872 static G_GNUC_UNUSED char*
 3873 patch_to_string (MonoJumpInfo *patch_info)
 3874 {
 3875     GString *str;
 3876 
 3877     str = g_string_new ("");
 3878 
 3879     g_string_append_printf (str, "%s(", get_patch_name (patch_info->type));
 3880 
 3881     switch (patch_info->type) {
 3882     case MONO_PATCH_INFO_VTABLE:
 3883         mono_type_get_desc (str, m_class_get_byval_arg (patch_info->data.klass), TRUE);
 3884         break;
 3885     default:
 3886         break;
 3887     }
 3888     g_string_append_printf (str, ")");
 3889     return g_string_free (str, FALSE);
 3890 }
 3891 
 3892 /*
 3893  * is_plt_patch:
 3894  *
 3895  *   Return whenever PATCH_INFO refers to a direct call, and thus requires a
 3896  * PLT entry.
 3897  */
 3898 static gboolean
 3899 is_plt_patch (MonoJumpInfo *patch_info)
 3900 {
 3901     switch (patch_info->type) {
 3902     case MONO_PATCH_INFO_METHOD:
 3903     case MONO_PATCH_INFO_JIT_ICALL_ID:
 3904     case MONO_PATCH_INFO_JIT_ICALL_ADDR:
 3905     case MONO_PATCH_INFO_ICALL_ADDR_CALL:
 3906     case MONO_PATCH_INFO_RGCTX_FETCH:
 3907     case MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR:
 3908         return TRUE;
 3909     case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL:
 3910     default:
 3911         return FALSE;
 3912     }
 3913 }
 3914 
 3915 /*
 3916  * get_plt_symbol:
 3917  *
 3918  *   Return the symbol identifying the plt entry PLT_OFFSET.
 3919  */
 3920 static char*
 3921 get_plt_symbol (MonoAotCompile *acfg, int plt_offset, MonoJumpInfo *patch_info)
 3922 {
 3923 #ifdef TARGET_MACH
 3924     /* 
 3925      * The Apple linker reorganizes object files, so it doesn't like branches to local
 3926      * labels, since those have no relocations.
 3927      */
 3928     return g_strdup_printf ("%sp_%d", acfg->llvm_label_prefix, plt_offset);
 3929 #else
 3930     return g_strdup_printf ("%sp_%d", acfg->temp_prefix, plt_offset);
 3931 #endif
 3932 }
 3933 
 3934 /*
 3935  * get_plt_entry:
 3936  *
 3937  *   Return a PLT entry which belongs to the method identified by PATCH_INFO.
 3938  */
 3939 static MonoPltEntry*
 3940 get_plt_entry (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
 3941 {
 3942     MonoPltEntry *res;
 3943     gboolean synchronized = FALSE;
 3944     static int synchronized_symbol_idx;
 3945 
 3946     if (!is_plt_patch (patch_info))
 3947         return NULL;
 3948 
 3949     if (!acfg->patch_to_plt_entry [patch_info->type])
 3950         acfg->patch_to_plt_entry [patch_info->type] = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
 3951     res = (MonoPltEntry *)g_hash_table_lookup (acfg->patch_to_plt_entry [patch_info->type], patch_info);
 3952 
 3953     if (!acfg->llvm && patch_info->type == MONO_PATCH_INFO_METHOD && (patch_info->data.method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
 3954         /* 
 3955          * Allocate a separate PLT slot for each such patch, since some plt
 3956          * entries will refer to the method itself, and some will refer to the
 3957          * wrapper.
 3958          */
 3959         res = NULL;
 3960         synchronized = TRUE;
 3961     }
 3962 
 3963     if (!res) {
 3964         MonoJumpInfo *new_ji;
 3965 
 3966         new_ji = mono_patch_info_dup_mp (acfg->mempool, patch_info);
 3967 
 3968         res = (MonoPltEntry *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoPltEntry));
 3969         res->plt_offset = acfg->plt_offset;
 3970         res->ji = new_ji;
 3971         res->symbol = get_plt_symbol (acfg, res->plt_offset, patch_info);
 3972         if (acfg->aot_opts.write_symbols)
 3973             res->debug_sym = get_plt_entry_debug_sym (acfg, res->ji, acfg->plt_entry_debug_sym_cache);
 3974         if (synchronized) {
 3975             /* Avoid duplicate symbols because we don't cache */
 3976             res->symbol = g_strdup_printf ("%s_%d", res->symbol, synchronized_symbol_idx);
 3977             if (res->debug_sym)
 3978                 res->debug_sym = g_strdup_printf ("%s_%d", res->debug_sym, synchronized_symbol_idx);
 3979             synchronized_symbol_idx ++;
 3980         }
 3981 
 3982         if (res->debug_sym)
 3983             res->llvm_symbol = g_strdup_printf ("%s_%s_llvm", res->symbol, res->debug_sym);
 3984         else
 3985             res->llvm_symbol = g_strdup_printf ("%s_llvm", res->symbol);
 3986         if (strstr (res->llvm_symbol, acfg->temp_prefix) == res->llvm_symbol) {
 3987             /* The llvm symbol shouldn't be temporary, since the llvm generated object file references it */
 3988             char *tmp = res->llvm_symbol;
 3989             res->llvm_symbol = g_strdup (res->llvm_symbol + strlen (acfg->temp_prefix));
 3990             g_free (tmp);
 3991         }
 3992 
 3993         g_hash_table_insert (acfg->patch_to_plt_entry [new_ji->type], new_ji, res);
 3994 
 3995         g_hash_table_insert (acfg->plt_offset_to_entry, GUINT_TO_POINTER (res->plt_offset), res);
 3996 
 3997         //g_assert (mono_patch_info_equal (patch_info, new_ji));
 3998         //mono_print_ji (patch_info); printf ("\n");
 3999         //g_hash_table_print_stats (acfg->patch_to_plt_entry);
 4000 
 4001         acfg->plt_offset ++;
 4002     }
 4003 
 4004     return res;
 4005 }
 4006 
 4007 static guint32
 4008 lookup_got_offset (MonoAotCompile *acfg, gboolean llvm, MonoJumpInfo *ji)
 4009 {
 4010     guint32 got_offset;
 4011     GotInfo *info = llvm ? &acfg->llvm_got_info : &acfg->got_info;
 4012 
 4013     got_offset = GPOINTER_TO_UINT (g_hash_table_lookup (info->patch_to_got_offset_by_type [ji->type], ji));
 4014     if (got_offset)
 4015         return got_offset - 1;
 4016     g_assert_not_reached ();
 4017 }
 4018 
 4019 /**
 4020  * get_got_offset:
 4021  *
 4022  *   Returns the offset of the GOT slot where the runtime object resulting from resolving
 4023  * JI could be found if it exists, otherwise allocates a new one.
 4024  */
 4025 static guint32
 4026 get_got_offset (MonoAotCompile *acfg, gboolean llvm, MonoJumpInfo *ji)
 4027 {
 4028     guint32 got_offset;
 4029     GotInfo *info = llvm ? &acfg->llvm_got_info : &acfg->got_info;
 4030 
 4031     got_offset = GPOINTER_TO_UINT (g_hash_table_lookup (info->patch_to_got_offset_by_type [ji->type], ji));
 4032     if (got_offset)
 4033         return got_offset - 1;
 4034 
 4035     if (llvm) {
 4036         got_offset = acfg->llvm_got_offset;
 4037         acfg->llvm_got_offset ++;
 4038     } else {
 4039         got_offset = acfg->got_offset;
 4040         acfg->got_offset ++;
 4041     }
 4042 
 4043     acfg->stats.got_slots ++;
 4044     acfg->stats.got_slot_types [ji->type] ++;
 4045 
 4046     g_hash_table_insert (info->patch_to_got_offset, ji, GUINT_TO_POINTER (got_offset + 1));
 4047     g_hash_table_insert (info->patch_to_got_offset_by_type [ji->type], ji, GUINT_TO_POINTER (got_offset + 1));
 4048     g_ptr_array_add (info->got_patches, ji);
 4049 
 4050     return got_offset;
 4051 }
 4052 
 4053 /* Add a method to the list of methods which need to be emitted */
 4054 static void
 4055 add_method_with_index (MonoAotCompile *acfg, MonoMethod *method, int index, gboolean extra)
 4056 {
 4057     g_assert (method);
 4058     if (!g_hash_table_lookup (acfg->method_indexes, method)) {
 4059         g_ptr_array_add (acfg->methods, method);
 4060         g_hash_table_insert (acfg->method_indexes, method, GUINT_TO_POINTER (index + 1));
 4061         acfg->nmethods = acfg->methods->len + 1;
 4062     }
 4063 
 4064     if (method->wrapper_type || extra) {
 4065         int token = mono_metadata_token_index (method->token) - 1;
 4066         if (token < 0)
 4067             acfg->nextra_methods++;
 4068         g_ptr_array_add (acfg->extra_methods, method);
 4069     }
 4070 }
 4071 
 4072 static gboolean
 4073 prefer_gsharedvt_method (MonoAotCompile *acfg, MonoMethod *method)
 4074 {
 4075     /* One instantiation with valuetypes is generated for each async method */
 4076     if (m_class_get_image (method->klass) == mono_defaults.corlib && (!strcmp (m_class_get_name (method->klass), "AsyncMethodBuilderCore") || !strcmp (m_class_get_name (method->klass), "AsyncVoidMethodBuilder")))
 4077         return TRUE;
 4078     else
 4079         return FALSE;
 4080 }
 4081 
 4082 static guint32
 4083 get_method_index (MonoAotCompile *acfg, MonoMethod *method)
 4084 {
 4085     int index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_indexes, method));
 4086     
 4087     g_assert (index);
 4088 
 4089     return index - 1;
 4090 }
 4091 
 4092 static int
 4093 add_method_full (MonoAotCompile *acfg, MonoMethod *method, gboolean extra, int depth)
 4094 {
 4095     int index;
 4096 
 4097     index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_indexes, method));
 4098     if (index)
 4099         return index - 1;
 4100 
 4101     index = acfg->method_index;
 4102     add_method_with_index (acfg, method, index, extra);
 4103 
 4104     g_ptr_array_add (acfg->method_order, GUINT_TO_POINTER (index));
 4105 
 4106     g_hash_table_insert (acfg->method_depth, method, GUINT_TO_POINTER (depth));
 4107 
 4108     acfg->method_index ++;
 4109 
 4110     return index;
 4111 }
 4112 
 4113 static int
 4114 add_method (MonoAotCompile *acfg, MonoMethod *method)
 4115 {
 4116     return add_method_full (acfg, method, FALSE, 0);
 4117 }
 4118 
 4119 static void
 4120 mono_dedup_cache_method (MonoAotCompile *acfg, MonoMethod *method)
 4121 {
 4122     g_assert (acfg->dedup_stats);
 4123 
 4124     char *name = mono_aot_get_mangled_method_name (method);
 4125     g_assert (name);
 4126 
 4127     // For stats
 4128     char *stats_name = g_strdup (name);
 4129 
 4130     g_assert (acfg->dedup_cache);
 4131 
 4132     if (!g_hash_table_lookup (acfg->dedup_cache, name)) {
 4133         // This AOTCompile owns this method
 4134         // We do this to decide whether to write it to disk
 4135         // during a dedup run (first phase, where we skip).
 4136         //
 4137         // If never changed, then maybe can avoid a recompile
 4138         // of the cache.
 4139         //
 4140         // Files not read in during last phase.
 4141         acfg->dedup_cache_changed = TRUE;
 4142 
 4143         // owns name
 4144         g_hash_table_insert (acfg->dedup_cache, name, method);
 4145     } else {
 4146         // owns name
 4147         g_free (name);
 4148     }
 4149 
 4150     guint count = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->dedup_stats, stats_name));
 4151     count++;
 4152     g_hash_table_insert (acfg->dedup_stats, stats_name, GUINT_TO_POINTER (count));
 4153 }
 4154 
 4155 static void
 4156 add_extra_method_with_depth (MonoAotCompile *acfg, MonoMethod *method, int depth)
 4157 {
 4158     ERROR_DECL (error);
 4159 
 4160     if (mono_method_is_generic_sharable_full (method, TRUE, TRUE, FALSE)) {
 4161         method = mini_get_shared_method_full (method, SHARE_MODE_NONE, error);
 4162         if (!is_ok (error)) {
 4163             /* vtype constraint */
 4164             mono_error_cleanup (error);
 4165             return;
 4166         }
 4167     } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && prefer_gsharedvt_method (acfg, method) && mono_method_is_generic_sharable_full (method, FALSE, FALSE, TRUE)) {
 4168         /* Use the gsharedvt version */
 4169         method = mini_get_shared_method_full (method, SHARE_MODE_GSHAREDVT, error);
 4170         mono_error_assert_ok (error);
 4171     }
 4172 
 4173     if ((acfg->aot_opts.dedup || acfg->aot_opts.dedup_include) && mono_aot_can_dedup (method)) {
 4174         mono_dedup_cache_method (acfg, method);
 4175 
 4176         if (!acfg->dedup_emit_mode)
 4177             return;
 4178     }
 4179 
 4180     if (acfg->aot_opts.log_generics)
 4181         aot_printf (acfg, "%*sAdding method %s.\n", depth, "", mono_method_get_full_name (method));
 4182 
 4183     add_method_full (acfg, method, TRUE, depth);
 4184 }
 4185 
 4186 static void
 4187 add_extra_method (MonoAotCompile *acfg, MonoMethod *method)
 4188 {
 4189     add_extra_method_with_depth (acfg, method, 0);
 4190 }
 4191 
 4192 static void
 4193 add_jit_icall_wrapper (MonoAotCompile *acfg, MonoJitICallInfo *callinfo)
 4194 {
 4195     if (!callinfo->sig)
 4196         return;
 4197 
 4198     g_assert (callinfo->name && callinfo->func);
 4199 
 4200     add_method (acfg, mono_marshal_get_icall_wrapper (callinfo, TRUE));
 4201 }
 4202 
 4203 #if ENABLE_LLVM
 4204 
 4205 static void
 4206 add_lazy_init_wrappers (MonoAotCompile *acfg)
 4207 {
 4208     add_method (acfg, mono_marshal_get_aot_init_wrapper (AOT_INIT_METHOD));
 4209     add_method (acfg, mono_marshal_get_aot_init_wrapper (AOT_INIT_METHOD_GSHARED_MRGCTX));
 4210     add_method (acfg, mono_marshal_get_aot_init_wrapper (AOT_INIT_METHOD_GSHARED_VTABLE));
 4211     add_method (acfg, mono_marshal_get_aot_init_wrapper (AOT_INIT_METHOD_GSHARED_THIS));
 4212 }
 4213 
 4214 #endif
 4215 
 4216 static MonoMethod*
 4217 get_runtime_invoke_sig (MonoMethodSignature *sig)
 4218 {
 4219     MonoMethodBuilder *mb;
 4220     MonoMethod *m;
 4221 
 4222     mb = mono_mb_new (mono_defaults.object_class, "FOO", MONO_WRAPPER_NONE);
 4223     m = mono_mb_create_method (mb, sig, 16);
 4224     MonoMethod *invoke = mono_marshal_get_runtime_invoke (m, FALSE);
 4225     mono_mb_free (mb);
 4226     return invoke;
 4227 }
 4228 
 4229 static MonoMethod*
 4230 get_runtime_invoke (MonoAotCompile *acfg, MonoMethod *method, gboolean virtual_)
 4231 {
 4232     return mono_marshal_get_runtime_invoke (method, virtual_);
 4233 }
 4234 
 4235 static gboolean
 4236 can_marshal_struct (MonoClass *klass)
 4237 {
 4238     MonoClassField *field;
 4239     gboolean can_marshal = TRUE;
 4240     gpointer iter = NULL;
 4241     MonoMarshalType *info;
 4242     int i;
 4243 
 4244     if (mono_class_is_auto_layout (klass))
 4245         return FALSE;
 4246 
 4247     info = mono_marshal_load_type_info (klass);
 4248 
 4249     /* Only allow a few field types to avoid asserts in the marshalling code */
 4250     while ((field = mono_class_get_fields_internal (klass, &iter))) {
 4251         if ((field->type->attrs & FIELD_ATTRIBUTE_STATIC))
 4252             continue;
 4253 
 4254         switch (field->type->type) {
 4255         case MONO_TYPE_I4:
 4256         case MONO_TYPE_U4:
 4257         case MONO_TYPE_I1:
 4258         case MONO_TYPE_U1:
 4259         case MONO_TYPE_BOOLEAN:
 4260         case MONO_TYPE_I2:
 4261         case MONO_TYPE_U2:
 4262         case MONO_TYPE_CHAR:
 4263         case MONO_TYPE_I8:
 4264         case MONO_TYPE_U8:
 4265         case MONO_TYPE_I:
 4266         case MONO_TYPE_U:
 4267         case MONO_TYPE_PTR:
 4268         case MONO_TYPE_R4:
 4269         case MONO_TYPE_R8:
 4270         case MONO_TYPE_STRING:
 4271             break;
 4272         case MONO_TYPE_VALUETYPE:
 4273             if (!m_class_is_enumtype (mono_class_from_mono_type_internal (field->type)) && !can_marshal_struct (mono_class_from_mono_type_internal (field->type)))
 4274                 can_marshal = FALSE;
 4275             break;
 4276         case MONO_TYPE_SZARRAY: {
 4277             gboolean has_mspec = FALSE;
 4278 
 4279             if (info) {
 4280                 for (i = 0; i < info->num_fields; ++i) {
 4281                     if (info->fields [i].field == field && info->fields [i].mspec)
 4282                         has_mspec = TRUE;
 4283                 }
 4284             }
 4285             if (!has_mspec)
 4286                 can_marshal = FALSE;
 4287             break;
 4288         }
 4289         default:
 4290             can_marshal = FALSE;
 4291             break;
 4292         }
 4293     }
 4294 
 4295     /* Special cases */
 4296     /* Its hard to compute whenever these can be marshalled or not */
 4297     if (!strcmp (m_class_get_name_space (klass), "System.Net.NetworkInformation.MacOsStructs") && strcmp (m_class_get_name (klass), "sockaddr_dl"))
 4298         return TRUE;
 4299 
 4300     return can_marshal;
 4301 }
 4302 
 4303 static void
 4304 create_gsharedvt_inst (MonoAotCompile *acfg, MonoMethod *method, MonoGenericContext *ctx)
 4305 {
 4306     /* Create a vtype instantiation */
 4307     MonoGenericContext shared_context;
 4308     MonoType **args;
 4309     MonoGenericInst *inst;
 4310     MonoGenericContainer *container;
 4311     MonoClass **constraints;
 4312     int i;
 4313 
 4314     memset (ctx, 0, sizeof (MonoGenericContext));
 4315 
 4316     if (mono_class_is_gtd (method->klass)) {
 4317         shared_context = mono_class_get_generic_container (method->klass)->context;
 4318         inst = shared_context.class_inst;
 4319 
 4320         args = g_new0 (MonoType*, inst->type_argc);
 4321         for (i = 0; i < inst->type_argc; ++i) {
 4322             args [i] = mono_get_int_type ();
 4323         }
 4324         ctx->class_inst = mono_metadata_get_generic_inst (inst->type_argc, args);
 4325     }
 4326     if (method->is_generic) {
 4327         container = mono_method_get_generic_container (method);
 4328         g_assert (!container->is_anonymous && container->is_method);
 4329         shared_context = container->context;
 4330         inst = shared_context.method_inst;
 4331 
 4332         args = g_new0 (MonoType*, inst->type_argc);
 4333         for (i = 0; i < container->type_argc; ++i) {
 4334             MonoGenericParamInfo *info = mono_generic_param_info (&container->type_params [i]);
 4335             gboolean ref_only = FALSE;
 4336 
 4337             if (info && info->constraints) {
 4338                 constraints = info->constraints;
 4339 
 4340                 while (*constraints) {
 4341                     MonoClass *cklass = *constraints;
 4342                     if (!(cklass == mono_defaults.object_class || (m_class_get_image (cklass) == mono_defaults.corlib && !strcmp (m_class_get_name (cklass), "ValueType"))))
 4343                         /* Inflaring the method with our vtype would not be valid */
 4344                         ref_only = TRUE;
 4345                     constraints ++;
 4346                 }
 4347             }
 4348 
 4349             if (ref_only)
 4350                 args [i] = mono_get_object_type ();
 4351             else
 4352                 args [i] = mono_get_int_type ();
 4353         }
 4354         ctx->method_inst = mono_metadata_get_generic_inst (inst->type_argc, args);
 4355     }
 4356 }
 4357 
 4358 static void
 4359 add_gc_wrappers (MonoAotCompile *acfg)
 4360 {
 4361     MonoMethod *m;
 4362     /* Managed Allocators */
 4363     int nallocators = mono_gc_get_managed_allocator_types ();
 4364     for (int i = 0; i < nallocators; ++i) {
 4365         if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_REGULAR)))
 4366             add_method (acfg, m);
 4367         if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_SLOW_PATH)))
 4368             add_method (acfg, m);
 4369         if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_PROFILER)))
 4370             add_method (acfg, m);
 4371     }
 4372 
 4373     /* write barriers */
 4374     if (mono_gc_is_moving ()) {
 4375         add_method (acfg, mono_gc_get_specific_write_barrier (FALSE));
 4376         add_method (acfg, mono_gc_get_specific_write_barrier (TRUE));
 4377     }
 4378 }
 4379 
 4380 static gboolean
 4381 contains_disable_reflection_attribute (MonoCustomAttrInfo *cattr)
 4382 {
 4383     for (int i = 0; i < cattr->num_attrs; ++i) {
 4384         MonoCustomAttrEntry *attr = &cattr->attrs [i];
 4385 
 4386         if (!attr->ctor)
 4387             return FALSE;
 4388 
 4389         if (strcmp (m_class_get_name_space (attr->ctor->klass), "System.Runtime.CompilerServices"))
 4390             return FALSE;
 4391 
 4392         if (strcmp (m_class_get_name (attr->ctor->klass), "DisablePrivateReflectionAttribute"))
 4393             return FALSE;
 4394     }
 4395 
 4396     return TRUE;
 4397 }
 4398 
 4399 gboolean
 4400 mono_aot_can_specialize (MonoMethod *method)
 4401 {
 4402     if (!method)
 4403         return FALSE;
 4404 
 4405     if (method->wrapper_type != MONO_WRAPPER_NONE)
 4406         return FALSE;
 4407 
 4408     // If it's not private, we can't specialize
 4409     if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE)
 4410         return FALSE;
 4411 
 4412     // If it has the attribute disabling the specialization, we can't specialize
 4413     //
 4414     // Set by linker, indicates that the method can be found through reflection
 4415     // and that call-site specialization shouldn't be done.
 4416     //
 4417     // Important that this attribute is used for *nothing else*
 4418     //
 4419     // If future authors make use of it (to disable more optimizations),
 4420     // change this place to use a new attribute.
 4421     ERROR_DECL (cattr_error);
 4422     MonoCustomAttrInfo *cattr = mono_custom_attrs_from_class_checked (method->klass, cattr_error);
 4423 
 4424     if (!is_ok (cattr_error)) {
 4425         mono_error_cleanup (cattr_error);
 4426         goto cleanup_false;
 4427     } else if (cattr && contains_disable_reflection_attribute (cattr)) {
 4428         goto cleanup_true;
 4429     }
 4430 
 4431     cattr = mono_custom_attrs_from_method_checked (method, cattr_error);
 4432 
 4433     if (!is_ok (cattr_error)) {
 4434         mono_error_cleanup (cattr_error);
 4435         goto cleanup_false;
 4436     } else if (cattr && contains_disable_reflection_attribute (cattr)) {
 4437         goto cleanup_true;
 4438     } else {
 4439         goto cleanup_false;
 4440     }
 4441 
 4442 cleanup_false:
 4443     if (cattr)
 4444         mono_custom_attrs_free (cattr);
 4445     return FALSE;
 4446 
 4447 cleanup_true:
 4448     if (cattr)
 4449         mono_custom_attrs_free (cattr);
 4450     return TRUE;
 4451 }
 4452 
 4453 static gboolean
 4454 always_aot (MonoMethod *method)
 4455 {
 4456     /*
 4457      * Calls to these methods do not go through the normal call processing code so
 4458      * calling code cannot enter the interpreter. So always aot them even in profile guided aot mode.
 4459      */
 4460     if (method->klass == mono_get_string_class () && (strstr (method->name, "memcpy") || strstr (method->name, "bzero")))
 4461         return TRUE;
 4462     if (method->string_ctor)
 4463         return TRUE;
 4464     return FALSE;
 4465 }
 4466 
 4467 gboolean
 4468 mono_aot_can_enter_interp (MonoMethod *method)
 4469 {
 4470     MonoAotCompile *acfg = current_acfg;
 4471 
 4472     g_assert (acfg);
 4473     if (always_aot (method))
 4474         return FALSE;
 4475     if (acfg->aot_opts.profile_only && !g_hash_table_lookup (acfg->profile_methods, method))
 4476         return TRUE;
 4477     return FALSE;
 4478 }
 4479 
 4480 static void
 4481 add_wrappers (MonoAotCompile *acfg)
 4482 {
 4483     MonoMethod *method, *m;
 4484     int i, j;
 4485     MonoMethodSignature *sig, *csig;
 4486     guint32 token;
 4487 
 4488     /* 
 4489      * FIXME: Instead of AOTing all the wrappers, it might be better to redesign them
 4490      * so there is only one wrapper of a given type, or inlining their contents into their
 4491      * callers.
 4492      */
 4493     for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
 4494         ERROR_DECL (error);
 4495         MonoMethod *method;
 4496         guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
 4497         gboolean skip = FALSE;
 4498 
 4499         method = mono_get_method_checked (acfg->image, token, NULL, NULL, error);
 4500         report_loader_error (acfg, error, TRUE, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (error));
 4501 
 4502         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
 4503             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
 4504             (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
 4505             skip = TRUE;
 4506 
 4507         /* Skip methods which can not be handled by get_runtime_invoke () */
 4508         sig = mono_method_signature_internal (method);
 4509         if (!sig)
 4510             continue;
 4511         if ((sig->ret->type == MONO_TYPE_PTR) ||
 4512             (sig->ret->type == MONO_TYPE_TYPEDBYREF))
 4513             skip = TRUE;
 4514         if (mono_class_is_open_constructed_type (sig->ret))
 4515             skip = TRUE;
 4516 
 4517         for (j = 0; j < sig->param_count; j++) {
 4518             if (sig->params [j]->type == MONO_TYPE_TYPEDBYREF)
 4519                 skip = TRUE;
 4520             if (mono_class_is_open_constructed_type (sig->params [j]))
 4521                 skip = TRUE;
 4522         }
 4523 
 4524 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
 4525         if (!mono_class_is_contextbound (method->klass)) {
 4526             MonoDynCallInfo *info = mono_arch_dyn_call_prepare (sig);
 4527             gboolean has_nullable = FALSE;
 4528 
 4529             for (j = 0; j < sig->param_count; j++) {
 4530                 if (sig->params [j]->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type_internal (sig->params [j])))
 4531                     has_nullable = TRUE;
 4532             }
 4533 
 4534             if (info && !has_nullable && !acfg->aot_opts.llvm_only) {
 4535                 /* Supported by the dynamic runtime-invoke wrapper */
 4536                 skip = TRUE;
 4537             }
 4538             if (info)
 4539                 mono_arch_dyn_call_free (info);
 4540         }
 4541 #endif
 4542 
 4543         if (acfg->aot_opts.llvm_only)
 4544             /* Supported by the gsharedvt based runtime-invoke wrapper */
 4545             skip = TRUE;
 4546 
 4547         if (!skip) {
 4548             //printf ("%s\n", mono_method_full_name (method, TRUE));
 4549             add_method (acfg, get_runtime_invoke (acfg, method, FALSE));
 4550         }
 4551     }
 4552 
 4553     if (mono_is_corlib_image (acfg->image->assembly->image)) {
 4554         /* Runtime invoke wrappers */
 4555 
 4556         MonoType *void_type = mono_get_void_type ();
 4557         MonoType *string_type = m_class_get_byval_arg (mono_defaults.string_class);
 4558 
 4559         /* void runtime-invoke () [.cctor] */
 4560         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
 4561         csig->ret = void_type;
 4562         add_method (acfg, get_runtime_invoke_sig (csig));
 4563 
 4564         /* void runtime-invoke () [Finalize] */
 4565         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
 4566         csig->hasthis = 1;
 4567         csig->ret = void_type;
 4568         add_method (acfg, get_runtime_invoke_sig (csig));
 4569 
 4570         /* void runtime-invoke (string) [exception ctor] */
 4571         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
 4572         csig->hasthis = 1;
 4573         csig->ret = void_type;
 4574         csig->params [0] = string_type;
 4575         add_method (acfg, get_runtime_invoke_sig (csig));
 4576 
 4577         /* void runtime-invoke (string, string) [exception ctor] */
 4578         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
 4579         csig->hasthis = 1;
 4580         csig->ret = void_type;
 4581         csig->params [0] = string_type;
 4582         csig->params [1] = string_type;
 4583         add_method (acfg, get_runtime_invoke_sig (csig));
 4584 
 4585         /* string runtime-invoke () [Exception.ToString ()] */
 4586         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
 4587         csig->hasthis = 1;
 4588         csig->ret = string_type;
 4589         add_method (acfg, get_runtime_invoke_sig (csig));
 4590 
 4591         /* void runtime-invoke (string, Exception) [exception ctor] */
 4592         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
 4593         csig->hasthis = 1;
 4594         csig->ret = void_type;
 4595         csig->params [0] = string_type;
 4596         csig->params [1] = m_class_get_byval_arg (mono_defaults.exception_class);
 4597         add_method (acfg, get_runtime_invoke_sig (csig));
 4598 
 4599         /* Assembly runtime-invoke (string, Assembly, bool) [DoAssemblyResolve] */
 4600         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
 4601         csig->hasthis = 1;
 4602         csig->ret = m_class_get_byval_arg (mono_class_load_from_name (mono_defaults.corlib, "System.Reflection", "Assembly"));
 4603         csig->params [0] = string_type;
 4604         csig->params [1] = m_class_get_byval_arg (mono_class_load_from_name (mono_defaults.corlib, "System.Reflection", "Assembly"));
 4605         csig->params [2] = m_class_get_byval_arg (mono_defaults.boolean_class);
 4606         add_method (acfg, get_runtime_invoke_sig (csig));
 4607 
 4608         /* runtime-invoke used by finalizers */
 4609         add_method (acfg, get_runtime_invoke (acfg, get_method_nofail (mono_defaults.object_class, "Finalize", 0, 0), TRUE));
 4610 
 4611         /* This is used by mono_runtime_capture_context () */
 4612         method = mono_get_context_capture_method ();
 4613         if (method)
 4614             add_method (acfg, get_runtime_invoke (acfg, method, FALSE));
 4615 
 4616 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
 4617         if (!acfg->aot_opts.llvm_only)
 4618             add_method (acfg, mono_marshal_get_runtime_invoke_dynamic ());
 4619 #endif
 4620 
 4621         /* These are used by mono_jit_runtime_invoke () to calls gsharedvt out wrappers */
 4622         if (acfg->aot_opts.llvm_only) {
 4623             int variants;
 4624 
 4625             /* Create simplified signatures which match the signature used by the gsharedvt out wrappers */
 4626             for (variants = 0; variants < 4; ++variants) {
 4627                 for (i = 0; i < 40; ++i) {
 4628                     sig = mini_get_gsharedvt_out_sig_wrapper_signature ((variants & 1) > 0, (variants & 2) > 0, i);
 4629                     add_extra_method (acfg, mono_marshal_get_runtime_invoke_for_sig (sig));
 4630 
 4631                     g_free (sig);
 4632                 }
 4633             }
 4634         }
 4635 
 4636         /* stelemref */
 4637         add_method (acfg, mono_marshal_get_stelemref ());
 4638 
 4639         add_gc_wrappers (acfg);
 4640 
 4641         /* Stelemref wrappers */
 4642         {
 4643             MonoMethod **wrappers;
 4644             int nwrappers;
 4645 
 4646             wrappers = mono_marshal_get_virtual_stelemref_wrappers (&nwrappers);
 4647             for (i = 0; i < nwrappers; ++i)
 4648                 add_method (acfg, wrappers [i]);
 4649             g_free (wrappers);
 4650         }
 4651 
 4652         /* castclass_with_check wrapper */
 4653         add_method (acfg, mono_marshal_get_castclass_with_cache ());
 4654         /* isinst_with_check wrapper */
 4655         add_method (acfg, mono_marshal_get_isinst_with_cache ());
 4656 
 4657         /* JIT icall wrappers */
 4658         /* FIXME: locking - this is "safe" as full-AOT threads don't mutate the icall data */
 4659         for (int i = 0; i < MONO_JIT_ICALL_count; ++i)
 4660             add_jit_icall_wrapper (acfg, mono_find_jit_icall_info ((MonoJitICallId)i));
 4661     }
 4662 
 4663     /* 
 4664      * remoting-invoke-with-check wrappers are very frequent, so avoid emitting them,
 4665      * we use the original method instead at runtime.
 4666      * Since full-aot doesn't support remoting, this is not a problem.
 4667      */
 4668 #if 0
 4669     /* remoting-invoke wrappers */
 4670     for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
 4671         ERROR_DECL (error);
 4672         MonoMethodSignature *sig;
 4673         
 4674         token = MONO_TOKEN_METHOD_DEF | (i + 1);
 4675         method = mono_get_method_checked (acfg->image, token, NULL, NULL, error);
 4676         g_assert (is_ok (error)); /* FIXME don't swallow the error */
 4677 
 4678         sig = mono_method_signature_internal (method);
 4679 
 4680         if (sig->hasthis && (method->klass->marshalbyref || method->klass == mono_defaults.object_class)) {
 4681             m = mono_marshal_get_remoting_invoke_with_check (method);
 4682 
 4683             add_method (acfg, m);
 4684         }
 4685     }
 4686 #endif
 4687 
 4688     /* delegate-invoke wrappers */
 4689     for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
 4690         ERROR_DECL (error);
 4691         MonoClass *klass;
 4692         
 4693         token = MONO_TOKEN_TYPE_DEF | (i + 1);
 4694         klass = mono_class_get_checked (acfg->image, token, error);
 4695 
 4696         if (!klass) {
 4697             mono_error_cleanup (error);
 4698             continue;
 4699         }
 4700 
 4701         if (!m_class_is_delegate (klass) || klass == mono_defaults.delegate_class || klass == mono_defaults.multicastdelegate_class)
 4702             continue;
 4703 
 4704         if (!mono_class_is_gtd (klass)) {
 4705             method = mono_get_delegate_invoke_internal (klass);
 4706 
 4707             m = mono_marshal_get_delegate_invoke (method, NULL);
 4708 
 4709             add_method (acfg, m);
 4710 
 4711             method = try_get_method_nofail (klass, "BeginInvoke", -1, 0);
 4712             if (method)
 4713                 add_method (acfg, mono_marshal_get_delegate_begin_invoke (method));
 4714 
 4715             method = try_get_method_nofail (klass, "EndInvoke", -1, 0);
 4716             if (method)
 4717                 add_method (acfg, mono_marshal_get_delegate_end_invoke (method));
 4718 
 4719             MonoCustomAttrInfo *cattr;
 4720             cattr = mono_custom_attrs_from_class_checked (klass, error);
 4721             if (!is_ok (error)) {
 4722                 mono_error_cleanup (error);
 4723                 g_assert (!cattr);
 4724                 continue;
 4725             }
 4726 
 4727             if (cattr) {
 4728                 int j;
 4729 
 4730                 for (j = 0; j < cattr->num_attrs; ++j)
 4731                     if (cattr->attrs [j].ctor && (!strcmp (m_class_get_name (cattr->attrs [j].ctor->klass), "MonoNativeFunctionWrapperAttribute") || !strcmp (m_class_get_name (cattr->attrs [j].ctor->klass), "UnmanagedFunctionPointerAttribute")))
 4732                         break;
 4733                 if (j < cattr->num_attrs) {
 4734                     MonoMethod *invoke;
 4735                     MonoMethod *wrapper;
 4736                     MonoMethod *del_invoke;
 4737 
 4738                     /* Add wrappers needed by mono_ftnptr_to_delegate () */
 4739                     invoke = mono_get_delegate_invoke_internal (klass);
 4740                     wrapper = mono_marshal_get_native_func_wrapper_aot (klass);
 4741                     del_invoke = mono_marshal_get_delegate_invoke_internal (invoke, FALSE, TRUE, wrapper);
 4742                     add_method (acfg, wrapper);
 4743                     add_method (acfg, del_invoke);
 4744                 }
 4745                 mono_custom_attrs_free (cattr);
 4746             }
 4747         } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && mono_class_is_gtd (klass)) {
 4748             ERROR_DECL (error);
 4749             MonoGenericContext ctx;
 4750             MonoMethod *inst, *gshared;
 4751 
 4752             /*
 4753              * Emit gsharedvt versions of the generic delegate-invoke wrappers
 4754              */
 4755             /* Invoke */
 4756             method = mono_get_delegate_invoke_internal (klass);
 4757             create_gsharedvt_inst (acfg, method, &ctx);
 4758 
 4759             inst = mono_class_inflate_generic_method_checked (method, &ctx, error);
 4760             g_assert (is_ok (error)); /* FIXME don't swallow the error */
 4761 
 4762             m = mono_marshal_get_delegate_invoke (inst, NULL);
 4763             g_assert (m->is_inflated);
 4764 
 4765             gshared = mini_get_shared_method_full (m, SHARE_MODE_GSHAREDVT, error);
 4766             mono_error_assert_ok (error);
 4767 
 4768             add_extra_method (acfg, gshared);
 4769 
 4770             /* begin-invoke */
 4771             method = mono_get_delegate_begin_invoke_internal (klass);
 4772             if (method) {
 4773                 create_gsharedvt_inst (acfg, method, &ctx);
 4774 
 4775                 inst = mono_class_inflate_generic_method_checked (method, &ctx, error);
 4776                 g_assert (is_ok (error)); /* FIXME don't swallow the error */
 4777 
 4778                 m = mono_marshal_get_delegate_begin_invoke (inst);
 4779                 g_assert (m->is_inflated);
 4780 
 4781                 gshared = mini_get_shared_method_full (m, SHARE_MODE_GSHAREDVT, error);
 4782                 mono_error_assert_ok (error);
 4783 
 4784                 add_extra_method (acfg, gshared);
 4785             }
 4786 
 4787             /* end-invoke */
 4788             method = mono_get_delegate_end_invoke_internal (klass);
 4789             if (method) {
 4790                 create_gsharedvt_inst (acfg, method, &ctx);
 4791 
 4792                 inst = mono_class_inflate_generic_method_checked (method, &ctx, error);
 4793                 g_assert (is_ok (error)); /* FIXME don't swallow the error */
 4794 
 4795                 m = mono_marshal_get_delegate_end_invoke (inst);
 4796                 g_assert (m->is_inflated);
 4797 
 4798                 gshared = mini_get_shared_method_full (m, SHARE_MODE_GSHAREDVT, error);
 4799                 mono_error_assert_ok (error);
 4800 
 4801                 add_extra_method (acfg, gshared);
 4802             }
 4803         }
 4804     }
 4805 
 4806     /* array access wrappers */
 4807     for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
 4808         ERROR_DECL (error);
 4809         MonoClass *klass;
 4810         
 4811         token = MONO_TOKEN_TYPE_SPEC | (i + 1);
 4812         klass = mono_class_get_checked (acfg->image, token, error);
 4813 
 4814         if (!klass) {
 4815             mono_error_cleanup (error);
 4816             continue;
 4817         }
 4818 
 4819         if (m_class_get_rank (klass) && MONO_TYPE_IS_PRIMITIVE (m_class_get_byval_arg (m_class_get_element_class (klass)))) {
 4820             MonoMethod *m, *wrapper;
 4821 
 4822             /* Add runtime-invoke wrappers too */
 4823 
 4824             m = get_method_nofail (klass, "Get", -1, 0);
 4825             g_assert (m);
 4826             wrapper = mono_marshal_get_array_accessor_wrapper (m);
 4827             add_extra_method (acfg, wrapper);
 4828             if (!acfg->aot_opts.llvm_only)
 4829                 add_extra_method (acfg, get_runtime_invoke (acfg, wrapper, FALSE));
 4830 
 4831             m = get_method_nofail (klass, "Set", -1, 0);
 4832             g_assert (m);
 4833             wrapper = mono_marshal_get_array_accessor_wrapper (m);
 4834             add_extra_method (acfg, wrapper);
 4835             if (!acfg->aot_opts.llvm_only)
 4836                 add_extra_method (acfg, get_runtime_invoke (acfg, wrapper, FALSE));
 4837         }
 4838     }
 4839 
 4840     /* Synchronized wrappers */
 4841     for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
 4842         ERROR_DECL (error);
 4843         token = MONO_TOKEN_METHOD_DEF | (i + 1);
 4844         method = mono_get_method_checked (acfg->image, token, NULL, NULL, error);
 4845         report_loader_error (acfg, error, TRUE, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (error));
 4846 
 4847         if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
 4848             if (method->is_generic) {
 4849                 // FIXME:
 4850             } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && mono_class_is_gtd (method->klass)) {
 4851                 ERROR_DECL (error);
 4852                 MonoGenericContext ctx;
 4853                 MonoMethod *inst, *gshared, *m;
 4854 
 4855                 /*
 4856                  * Create a generic wrapper for a generic instance, and AOT that.
 4857                  */
 4858                 create_gsharedvt_inst (acfg, method, &ctx);
 4859                 inst = mono_class_inflate_generic_method_checked (method, &ctx, error);
 4860                 g_assert (is_ok (error)); /* FIXME don't swallow the error */
 4861                 m = mono_marshal_get_synchronized_wrapper (inst);
 4862                 g_assert (m->is_inflated);
 4863                 gshared = mini_get_shared_method_full (m, SHARE_MODE_GSHAREDVT, error);
 4864                 mono_error_assert_ok (error);
 4865 
 4866                 add_method (acfg, gshared);
 4867             } else {
 4868                 add_method (acfg, mono_marshal_get_synchronized_wrapper (method));
 4869             }
 4870         }
 4871     }
 4872 
 4873     /* pinvoke wrappers */
 4874     for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
 4875         ERROR_DECL (error);
 4876         MonoMethod *method;
 4877         guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
 4878 
 4879         method = mono_get_method_checked (acfg->image, token, NULL, NULL, error);
 4880         report_loader_error (acfg, error, TRUE, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (error));
 4881 
 4882         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
 4883             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
 4884             add_method (acfg, mono_marshal_get_native_wrapper (method, TRUE, TRUE));
 4885         }
 4886 
 4887         if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
 4888             if (acfg->aot_opts.llvm_only) {
 4889                 /* The wrappers have a different signature (hasthis is not set) so need to add this too */
 4890                 add_gsharedvt_wrappers (acfg, mono_method_signature_internal (method), FALSE, TRUE, FALSE);
 4891             }
 4892         }
 4893     }
 4894  
 4895     /* native-to-managed wrappers */
 4896     for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
 4897         ERROR_DECL (error);
 4898         MonoMethod *method;
 4899         guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
 4900         MonoCustomAttrInfo *cattr;
 4901         int j;
 4902 
 4903         method = mono_get_method_checked (acfg->image, token, NULL, NULL, error);
 4904         report_loader_error (acfg, error, TRUE, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (error));
 4905 
 4906         /* 
 4907          * Only generate native-to-managed wrappers for methods which have an
 4908          * attribute named MonoPInvokeCallbackAttribute. We search for the attribute by
 4909          * name to avoid defining a new assembly to contain it.
 4910          */
 4911         cattr = mono_custom_attrs_from_method_checked (method, error);
 4912         if (!is_ok (error)) {
 4913             char *name = mono_method_get_full_name (method);
 4914             report_loader_error (acfg, error, TRUE, "Failed to load custom attributes from method %s due to %s\n", name, mono_error_get_message (error));
 4915             g_free (name);
 4916         }
 4917 
 4918         if (cattr) {
 4919             for (j = 0; j < cattr->num_attrs; ++j)
 4920                 if (cattr->attrs [j].ctor && !strcmp (m_class_get_name (cattr->attrs [j].ctor->klass), "MonoPInvokeCallbackAttribute"))
 4921                     break;
 4922             if (j < cattr->num_attrs) {
 4923                 MonoCustomAttrEntry *e = &cattr->attrs [j];
 4924                 MonoMethodSignature *sig = mono_method_signature_internal (e->ctor);
 4925                 const char *p = (const char*)e->data;
 4926                 const char *named;
 4927                 int slen, num_named, named_type;
 4928                 char *n;
 4929                 MonoType *t;
 4930                 MonoClass *klass;
 4931                 char *export_name = NULL;
 4932                 MonoMethod *wrapper;
 4933 
 4934                 /* this cannot be enforced by the C# compiler so we must give the user some warning before aborting */
 4935                 if (!(method->flags & METHOD_ATTRIBUTE_STATIC)) {
 4936                     g_warning ("AOT restriction: Method '%s' must be static since it is decorated with [MonoPInvokeCallback]. See https://docs.microsoft.com/xamarin/ios/internals/limitations#reverse-callbacks",
 4937                         mono_method_full_name (method, TRUE));
 4938                     exit (1);
 4939                 }
 4940 
 4941                 g_assert (sig->param_count == 1);
 4942                 g_assert (sig->params [0]->type == MONO_TYPE_CLASS && !strcmp (m_class_get_name (mono_class_from_mono_type_internal (sig->params [0])), "Type"));
 4943 
 4944                 /* 
 4945                  * Decode the cattr manually since we can't create objects
 4946                  * during aot compilation.
 4947                  */
 4948                     
 4949                 /* Skip prolog */
 4950                 p += 2;
 4951 
 4952                 /* From load_cattr_value () in reflection.c */
 4953                 slen = mono_metadata_decode_value (p, &p);
 4954                 n = (char *)g_memdup (p, slen + 1);
 4955                 n [slen] = 0;
 4956                 t = mono_reflection_type_from_name_checked (n, mono_domain_ambient_alc (mono_domain_get ()), acfg->image, error);
 4957                 g_assert (t);
 4958                 mono_error_assert_ok (error);
 4959                 g_free (n);
 4960 
 4961                 klass = mono_class_from_mono_type_internal (t);
 4962                 g_assert (m_class_get_parent (klass) == mono_defaults.multicastdelegate_class);
 4963 
 4964                 p += slen;
 4965 
 4966                 num_named = read16 (p);
 4967                 p += 2;
 4968 
 4969                 g_assert (num_named < 2);
 4970                 if (num_named == 1) {
 4971                     int name_len;
 4972                     char *name;
 4973 
 4974                     /* parse ExportSymbol attribute */
 4975                     named = p;
 4976                     named_type = *named;
 4977                     named += 1;
 4978                     /* data_type = *named; */
 4979                     named += 1;
 4980 
 4981                     name_len = mono_metadata_decode_blob_size (named, &named);
 4982                     name = (char *)g_malloc (name_len + 1);
 4983                     memcpy (name, named, name_len);
 4984                     name [name_len] = 0;
 4985                     named += name_len;
 4986 
 4987                     g_assert (named_type == 0x54);
 4988                     g_assert (!strcmp (name, "ExportSymbol"));
 4989 
 4990                     /* load_cattr_value (), string case */
 4991 MONO_DISABLE_WARNING (4310) // cast truncates constant value
 4992                     g_assert (*named != (char)0xFF);
 4993 MONO_RESTORE_WARNING
 4994                     slen = mono_metadata_decode_value (named, &named);
 4995                     export_name = (char *)g_malloc (slen + 1);
 4996                     memcpy (export_name, named, slen);
 4997                     export_name [slen] = 0;
 4998                     named += slen;
 4999                 }
 5000 
 5001                 wrapper = mono_marshal_get_managed_wrapper (method, klass, 0, error);
 5002                 mono_error_assert_ok (error);
 5003 
 5004                 add_method (acfg, wrapper);
 5005                 if (export_name)
 5006                     g_hash_table_insert (acfg->export_names, wrapper, export_name);
 5007             }
 5008             g_free (cattr);
 5009         }
 5010 
 5011         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
 5012             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
 5013             add_method (acfg, mono_marshal_get_native_wrapper (method, TRUE, TRUE));
 5014         }
 5015     }
 5016 
 5017     /* StructureToPtr/PtrToStructure wrappers */
 5018     for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
 5019         ERROR_DECL (error);
 5020         MonoClass *klass;
 5021         
 5022         token = MONO_TOKEN_TYPE_DEF | (i + 1);
 5023         klass = mono_class_get_checked (acfg->image, token, error);
 5024 
 5025         if (!klass) {
 5026             mono_error_cleanup (error);
 5027             continue;
 5028         }
 5029 
 5030         if (m_class_is_valuetype (klass) && !mono_class_is_gtd (klass) && can_marshal_struct (klass) &&
 5031             !(m_class_get_nested_in (klass) && strstr (m_class_get_name (m_class_get_nested_in (klass)), "<PrivateImplementationDetails>") == m_class_get_name (m_class_get_nested_in (klass)))) {
 5032             add_method (acfg, mono_marshal_get_struct_to_ptr (klass));
 5033             add_method (acfg, mono_marshal_get_ptr_to_struct (klass));
 5034         }
 5035     }
 5036 }
 5037 
 5038 static gboolean
 5039 has_type_vars (MonoClass *klass)
 5040 {
 5041     if ((m_class_get_byval_arg (klass)->type == MONO_TYPE_VAR) || (m_class_get_byval_arg (klass)->type == MONO_TYPE_MVAR))
 5042         return TRUE;
 5043     if (m_class_get_rank (klass))
 5044         return has_type_vars (m_class_get_element_class (klass));
 5045     if (mono_class_is_ginst (klass)) {
 5046         MonoGenericContext *context = &mono_class_get_generic_class (klass)->context;
 5047         if (context->class_inst) {
 5048             int i;
 5049 
 5050             for (i = 0; i < context->class_inst->type_argc; ++i)
 5051                 if (has_type_vars (mono_class_from_mono_type_internal (context->class_inst->type_argv [i])))
 5052                     return TRUE;
 5053         }
 5054     }
 5055     if (mono_class_is_gtd (klass))
 5056         return TRUE;
 5057     return FALSE;
 5058 }
 5059 
 5060 static gboolean
 5061 is_vt_inst (MonoGenericInst *inst)
 5062 {
 5063     int i;
 5064 
 5065     for (i = 0; i < inst->type_argc; ++i) {
 5066         MonoType *t = inst->type_argv [i];
 5067         if (MONO_TYPE_ISSTRUCT (t) || t->type == MONO_TYPE_VALUETYPE)
 5068             return TRUE;
 5069     }
 5070     return FALSE;
 5071 }
 5072 
 5073 static gboolean
 5074 method_has_type_vars (MonoMethod *method)
 5075 {
 5076     if (has_type_vars (method->klass))
 5077         return TRUE;
 5078 
 5079     if (method->is_inflated) {
 5080         MonoGenericContext *context = mono_method_get_context (method);
 5081         if (context->method_inst) {
 5082             int i;
 5083 
 5084             for (i = 0; i < context->method_inst->type_argc; ++i)
 5085                 if (has_type_vars (mono_class_from_mono_type_internal (context->method_inst->type_argv [i])))
 5086                     return TRUE;
 5087         }
 5088     }
 5089     return FALSE;
 5090 }
 5091 
 5092 static
 5093 gboolean mono_aot_mode_is_full (MonoAotOptions *opts)
 5094 {
 5095     return opts->mode == MONO_AOT_MODE_FULL;
 5096 }
 5097 
 5098 static
 5099 gboolean mono_aot_mode_is_interp (MonoAotOptions *opts)
 5100 {
 5101     return opts->interp;
 5102 }
 5103 
 5104 static
 5105 gboolean mono_aot_mode_is_hybrid (MonoAotOptions *opts)
 5106 {
 5107     return opts->mode == MONO_AOT_MODE_HYBRID;
 5108 }
 5109 
 5110 static void add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, const char *ref);
 5111 
 5112 static void
 5113 add_generic_class (MonoAotCompile *acfg, MonoClass *klass, gboolean force, const char *ref)
 5114 {
 5115     /* This might lead to a huge code blowup so only do it if neccesary */
 5116     if (!mono_aot_mode_is_full (&acfg->aot_opts) && !mono_aot_mode_is_hybrid (&acfg->aot_opts) && !force)
 5117         return;
 5118 
 5119     add_generic_class_with_depth (acfg, klass, 0, ref);
 5120 }
 5121 
 5122 static gboolean
 5123 check_type_depth (MonoType *t, int depth)
 5124 {
 5125     int i;
 5126 
 5127     if (depth > 8)
 5128         return TRUE;
 5129 
 5130     switch (t->type) {
 5131     case MONO_TYPE_GENERICINST: {
 5132         MonoGenericClass *gklass = t->data.generic_class;
 5133         MonoGenericInst *ginst = gklass->context.class_inst;
 5134 
 5135         if (ginst) {
 5136             for (i = 0; i < ginst->type_argc; ++i) {
 5137                 if (check_type_depth (ginst->type_argv [i], depth + 1))
 5138                     return TRUE;
 5139             }
 5140         }
 5141         break;
 5142     }
 5143     default:
 5144         break;
 5145     }
 5146 
 5147     return FALSE;
 5148 }
 5149 
 5150 static void
 5151 add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method);
 5152 
 5153 /*
 5154  * add_generic_class:
 5155  *
 5156  *   Add all methods of a generic class.
 5157  */
 5158 static void
 5159 add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, const char *ref)
 5160 {
 5161     MonoMethod *method;
 5162     MonoClassField *field;
 5163     gpointer iter;
 5164     gboolean use_gsharedvt = FALSE;
 5165 
 5166     if (!acfg->ginst_hash)
 5167         acfg->ginst_hash = g_hash_table_new (NULL, NULL);
 5168 
 5169     mono_class_init_internal (klass);
 5170 
 5171     if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open)
 5172         return;
 5173 
 5174     if (has_type_vars (klass))
 5175         return;
 5176 
 5177     if (!mono_class_is_ginst (klass) && !m_class_get_rank (klass))
 5178         return;
 5179 
 5180     if (mono_class_has_failure (klass))
 5181         return;
 5182 
 5183     if (!acfg->ginst_hash)
 5184         acfg->ginst_hash = g_hash_table_new (NULL, NULL);
 5185 
 5186     if (g_hash_table_lookup (acfg->ginst_hash, klass))
 5187         return;
 5188 
 5189     if (check_type_depth (m_class_get_byval_arg (klass), 0))
 5190         return;
 5191 
 5192     if (acfg->aot_opts.log_generics) {
 5193         char *s = mono_type_full_name (m_class_get_byval_arg (klass));
 5194         aot_printf (acfg, "%*sAdding generic instance %s [%s].\n", depth, "", s, ref);
 5195         g_free (s);
 5196     }
 5197 
 5198     g_hash_table_insert (acfg->ginst_hash, klass, klass);
 5199 
 5200     /*
 5201      * Use gsharedvt for generic collections with vtype arguments to avoid code blowup.