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 #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT)
73 
74 // Use MSVC toolchain, Clang for MSVC using MSVC codegen and linker, when compiling for AMD64
75 // targeting WIN32 platforms running AOT compiler on WIN32 platform with VS installation.
76 #if defined(TARGET_AMD64) && defined(TARGET_WIN32) && defined(HOST_WIN32) && defined(_MSC_VER)
77 #define TARGET_X86_64_WIN32_MSVC
78 #endif
79 
80 #if defined(TARGET_X86_64_WIN32_MSVC)
81 #define TARGET_WIN32_MSVC
82 #endif
83 
84 // Emit native unwind info on Windows platforms (different from DWARF). Emitted unwind info
85 // works when using the MSVC toolchain using Clang for MSVC codegen and linker. Only supported when
86 // compiling for AMD64 (Windows x64 platforms).
87 #if defined(TARGET_WIN32_MSVC) && defined(MONO_ARCH_HAVE_UNWIND_TABLE)
88 #define EMIT_WIN32_UNWIND_INFO
89 #endif
90 
91 #if defined(__linux__)
92 #define RODATA_SECT ".rodata"
93 #elif defined(TARGET_MACH)
94 #define RODATA_SECT ".section __TEXT, __const"
95 #elif defined(TARGET_WIN32_MSVC)
96 #define RODATA_SECT ".rdata"
97 #else
98 #define RODATA_SECT ".text"
99 #endif
100 
101 #define TV_DECLARE(name) gint64 name
102 #define TV_GETTIME(tv) tv = mono_100ns_ticks ()
103 #define TV_ELAPSED(start,end) (((end) - (start)) / 10)
104 
105 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
106 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
107 #define ROUND_DOWN(VALUE,SIZE)	((VALUE) & ~((SIZE) - 1))
108 
109 typedef struct {
110 	char *name;
111 	MonoImage *image;
112 } ImageProfileData;
113 
114 typedef struct ClassProfileData ClassProfileData;
115 
116 typedef struct {
117 	int argc;
118 	ClassProfileData **argv;
119 	MonoGenericInst *inst;
120 } GInstProfileData;
121 
122 struct ClassProfileData {
123 	ImageProfileData *image;
124 	char *ns, *name;
125 	GInstProfileData *inst;
126 	MonoClass *klass;
127 };
128 
129 typedef struct {
130 	ClassProfileData *klass;
131 	int id;
132 	char *name;
133 	int param_count;
134 	char *signature;
135 	GInstProfileData *inst;
136 	MonoMethod *method;
137 } MethodProfileData;
138 
139 typedef struct {
140 	GHashTable *images, *classes, *ginsts, *methods;
141 } ProfileData;
142 
143 /* predefined values for static readonly fields without needed to run the .cctor */
144 typedef struct _ReadOnlyValue ReadOnlyValue;
145 struct _ReadOnlyValue {
146 	ReadOnlyValue *next;
147 	char *name;
148 	int type; /* to be used later for typechecking to prevent user errors */
149 	union {
150 		guint8 i1;
151 		guint16 i2;
152 		guint32 i4;
153 		guint64 i8;
154 		gpointer ptr;
155 	} value;
156 };
157 static ReadOnlyValue *readonly_values;
158 
159 typedef struct MonoAotOptions {
160 	char *outfile;
161 	char *llvm_outfile;
162 	char *data_outfile;
163 	GList *profile_files;
164 	gboolean save_temps;
165 	gboolean write_symbols;
166 	gboolean metadata_only;
167 	gboolean bind_to_runtime_version;
168 	MonoAotMode mode;
169 	gboolean no_dlsym;
170 	gboolean static_link;
171 	gboolean asm_only;
172 	gboolean asm_writer;
173 	gboolean nodebug;
174 	gboolean dwarf_debug;
175 	gboolean soft_debug;
176 	gboolean log_generics;
177 	gboolean log_instances;
178 	gboolean gen_msym_dir;
179 	char *gen_msym_dir_path;
180 	gboolean direct_pinvoke;
181 	gboolean direct_icalls;
182 	gboolean no_direct_calls;
183 	gboolean use_trampolines_page;
184 	gboolean no_instances;
185 	// We are collecting inflated methods and emitting non-inflated
186 	gboolean dedup;
187 	// The name of the assembly for which the AOT module is going to have all deduped methods moved to.
188 	// When set, we are emitting inflated methods only
189 	char *dedup_include;
190 	gboolean gnu_asm;
191 	gboolean llvm;
192 	gboolean llvm_only;
193 	int nthreads;
194 	int ntrampolines;
195 	int nrgctx_trampolines;
196 	int nimt_trampolines;
197 	int ngsharedvt_arg_trampolines;
198 	int nrgctx_fetch_trampolines;
199 	gboolean print_skipped_methods;
200 	gboolean stats;
201 	gboolean verbose;
202 	char *tool_prefix;
203 	char *ld_flags;
204 	char *mtriple;
205 	char *llvm_path;
206 	char *temp_path;
207 	char *instances_logfile_path;
208 	char *logfile;
209 	gboolean dump_json;
210 	gboolean profile_only;
211 } MonoAotOptions;
212 
213 typedef enum {
214 	METHOD_CAT_NORMAL,
215 	METHOD_CAT_GSHAREDVT,
216 	METHOD_CAT_INST,
217 	METHOD_CAT_WRAPPER,
218 	METHOD_CAT_NUM
219 } MethodCategory;
220 
221 typedef struct MonoAotStats {
222 	int ccount, mcount, lmfcount, abscount, gcount, ocount, genericcount;
223 	gint64 code_size, info_size, ex_info_size, unwind_info_size, got_size, class_info_size, got_info_size, plt_size;
224 	int methods_without_got_slots, direct_calls, all_calls, llvm_count;
225 	int got_slots, offsets_size;
226 	int method_categories [METHOD_CAT_NUM];
227 	int got_slot_types [MONO_PATCH_INFO_NUM];
228 	int got_slot_info_sizes [MONO_PATCH_INFO_NUM];
229 	int jit_time, gen_time, link_time;
230 } MonoAotStats;
231 
232 typedef struct GotInfo {
233 	GHashTable *patch_to_got_offset;
234 	GHashTable **patch_to_got_offset_by_type;
235 	GPtrArray *got_patches;
236 } GotInfo;
237 
238 #ifdef EMIT_WIN32_UNWIND_INFO
239 typedef struct _UnwindInfoSectionCacheItem {
240 	char *xdata_section_label;
241 	PUNWIND_INFO unwind_info;
242 	gboolean xdata_section_emitted;
243 } UnwindInfoSectionCacheItem;
244 #endif
245 
246 typedef struct MonoAotCompile {
247 	MonoImage *image;
248 	GPtrArray *methods;
249 	GHashTable *method_indexes;
250 	GHashTable *method_depth;
251 	MonoCompile **cfgs;
252 	int cfgs_size;
253 	GHashTable **patch_to_plt_entry;
254 	GHashTable *plt_offset_to_entry;
255 	//GHashTable *patch_to_got_offset;
256 	//GHashTable **patch_to_got_offset_by_type;
257 	//GPtrArray *got_patches;
258 	GotInfo got_info, llvm_got_info;
259 	GHashTable *image_hash;
260 	GHashTable *method_to_cfg;
261 	GHashTable *token_info_hash;
262 	GHashTable *method_to_pinvoke_import;
263 	GPtrArray *extra_methods;
264 	GPtrArray *image_table;
265 	GPtrArray *globals;
266 	GPtrArray *method_order;
267 	GHashTable *dedup_stats;
268 	GHashTable *dedup_cache;
269 	gboolean dedup_cache_changed;
270 	GHashTable *export_names;
271 	/* Maps MonoClass* -> blob offset */
272 	GHashTable *klass_blob_hash;
273 	/* Maps MonoMethod* -> blob offset */
274 	GHashTable *method_blob_hash;
275 	GHashTable *gsharedvt_in_signatures;
276 	GHashTable *gsharedvt_out_signatures;
277 	guint32 *plt_got_info_offsets;
278 	guint32 got_offset, llvm_got_offset, plt_offset, plt_got_offset_base, nshared_got_entries;
279 	/* Number of GOT entries reserved for trampolines */
280 	guint32 num_trampoline_got_entries;
281 	guint32 tramp_page_size;
282 
283 	guint32 table_offsets [MONO_AOT_TABLE_NUM];
284 	guint32 num_trampolines [MONO_AOT_TRAMP_NUM];
285 	guint32 trampoline_got_offset_base [MONO_AOT_TRAMP_NUM];
286 	guint32 trampoline_size [MONO_AOT_TRAMP_NUM];
287 	guint32 tramp_page_code_offsets [MONO_AOT_TRAMP_NUM];
288 
289 	MonoAotOptions aot_opts;
290 	guint32 nmethods;
291 	guint32 opts;
292 	guint32 simd_opts;
293 	MonoMemPool *mempool;
294 	MonoAotStats stats;
295 	int method_index;
296 	char *static_linking_symbol;
297 	mono_mutex_t mutex;
298 	gboolean gas_line_numbers;
299 	/* Whenever to emit an object file directly from llc */
300 	gboolean llvm_owriter;
301 	gboolean llvm_owriter_supported;
302 	MonoImageWriter *w;
303 	MonoDwarfWriter *dwarf;
304 	FILE *fp;
305 	char *tmpbasename;
306 	char *tmpfname;
307 	char *llvm_sfile;
308 	char *llvm_ofile;
309 	GSList *cie_program;
310 	GHashTable *unwind_info_offsets;
311 	GPtrArray *unwind_ops;
312 	guint32 unwind_info_offset;
313 	char *global_prefix;
314 	char *got_symbol;
315 	char *llvm_got_symbol;
316 	char *plt_symbol;
317 	char *llvm_eh_frame_symbol;
318 	GHashTable *method_label_hash;
319 	const char *temp_prefix;
320 	const char *user_symbol_prefix;
321 	const char *llvm_label_prefix;
322 	const char *inst_directive;
323 	int align_pad_value;
324 	guint32 label_generator;
325 	gboolean llvm;
326 	gboolean has_jitted_code;
327 	gboolean is_full_aot;
328 	MonoAotFileFlags flags;
329 	MonoDynamicStream blob;
330 	gboolean blob_closed;
331 	GHashTable *typespec_classes;
332 	GString *llc_args;
333 	GString *as_args;
334 	char *assembly_name_sym;
335 	GHashTable *plt_entry_debug_sym_cache;
336 	gboolean thumb_mixed, need_no_dead_strip, need_pt_gnu_stack;
337 	GHashTable *ginst_hash;
338 	GHashTable *dwarf_ln_filenames;
339 	gboolean global_symbols;
340 	int objc_selector_index, objc_selector_index_2;
341 	GPtrArray *objc_selectors;
342 	GHashTable *objc_selector_to_index;
343 	GList *profile_data;
344 	GHashTable *profile_methods;
345 #ifdef EMIT_WIN32_UNWIND_INFO
346 	GList *unwind_info_section_cache;
347 #endif
348 	FILE *logfile;
349 	FILE *instances_logfile;
350 	FILE *data_outfile;
351 	int datafile_offset;
352 	int gc_name_offset;
353 	// In this mode, we are emitting dedupable methods that we encounter
354 	gboolean dedup_emit_mode;
355 } MonoAotCompile;
356 
357 typedef struct {
358 	int plt_offset;
359 	char *symbol, *llvm_symbol, *debug_sym;
360 	MonoJumpInfo *ji;
361 	gboolean jit_used, llvm_used;
362 } MonoPltEntry;
363 
364 #define mono_acfg_lock(acfg) mono_os_mutex_lock (&((acfg)->mutex))
365 #define mono_acfg_unlock(acfg) mono_os_mutex_unlock (&((acfg)->mutex))
366 
367 /* This points to the current acfg in LLVM mode */
368 static MonoAotCompile *llvm_acfg;
369 
370 #ifdef HAVE_ARRAY_ELEM_INIT
371 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
372 #define MSGSTRFIELD1(line) str##line
373 static const struct msgstr_t {
374 #define PATCH_INFO(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
375 #include "patch-info.h"
376 #undef PATCH_INFO
377 } opstr = {
378 #define PATCH_INFO(a,b) b,
379 #include "patch-info.h"
380 #undef PATCH_INFO
381 };
382 static const gint16 opidx [] = {
383 #define PATCH_INFO(a,b) [MONO_PATCH_INFO_ ## a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
384 #include "patch-info.h"
385 #undef PATCH_INFO
386 };
387 
388 static G_GNUC_UNUSED const char*
get_patch_name(int info)389 get_patch_name (int info)
390 {
391 	return (const char*)&opstr + opidx [info];
392 }
393 
394 #else
395 #define PATCH_INFO(a,b) b,
396 static const char* const
397 patch_types [MONO_PATCH_INFO_NUM + 1] = {
398 #include "patch-info.h"
399 	NULL
400 };
401 
402 static G_GNUC_UNUSED const char*
get_patch_name(int info)403 get_patch_name (int info)
404 {
405 	return patch_types [info];
406 }
407 
408 #endif
409 
410 static void
411 mono_flush_method_cache (MonoAotCompile *acfg);
412 
413 static void
414 mono_read_method_cache (MonoAotCompile *acfg);
415 
416 static guint32
417 get_unwind_info_offset (MonoAotCompile *acfg, guint8 *encoded, guint32 encoded_len);
418 
419 static char*
420 get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache);
421 
422 static void
423 add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean gsharedvt_in, gboolean gsharedvt_out);
424 
425 static void
426 add_profile_instances (MonoAotCompile *acfg, ProfileData *data);
427 
428 static inline gboolean
ignore_cfg(MonoCompile * cfg)429 ignore_cfg (MonoCompile *cfg)
430 {
431 	return !cfg || cfg->skip;
432 }
433 
434 static void
aot_printf(MonoAotCompile * acfg,const gchar * format,...)435 aot_printf (MonoAotCompile *acfg, const gchar *format, ...)
436 {
437 	FILE *output;
438 	va_list args;
439 
440 	if (acfg->logfile)
441 		output = acfg->logfile;
442 	else
443 		output = stdout;
444 
445 	va_start (args, format);
446 	vfprintf (output, format, args);
447 	va_end (args);
448 }
449 
450 static void
aot_printerrf(MonoAotCompile * acfg,const gchar * format,...)451 aot_printerrf (MonoAotCompile *acfg, const gchar *format, ...)
452 {
453 	FILE *output;
454 	va_list args;
455 
456 	if (acfg->logfile)
457 		output = acfg->logfile;
458 	else
459 		output = stderr;
460 
461 	va_start (args, format);
462 	vfprintf (output, format, args);
463 	va_end (args);
464 }
465 
466 static void
report_loader_error(MonoAotCompile * acfg,MonoError * error,gboolean fatal,const char * format,...)467 report_loader_error (MonoAotCompile *acfg, MonoError *error, gboolean fatal, const char *format, ...)
468 {
469 	FILE *output;
470 	va_list args;
471 
472 	if (mono_error_ok (error))
473 		return;
474 
475 	if (acfg->logfile)
476 		output = acfg->logfile;
477 	else
478 		output = stderr;
479 
480 	va_start (args, format);
481 	vfprintf (output, format, args);
482 	va_end (args);
483 	mono_error_cleanup (error);
484 
485 	if (acfg->is_full_aot && fatal) {
486 		fprintf (output, "FullAOT cannot continue if there are loader errors.\n");
487 		exit (1);
488 	}
489 }
490 
491 /* Wrappers around the image writer functions */
492 
493 #define MAX_SYMBOL_SIZE 256
494 
495 static inline const char *
mangle_symbol(const char * symbol,char * mangled_symbol,gsize length)496 mangle_symbol (const char * symbol, char * mangled_symbol, gsize length)
497 {
498 	gsize needed_size = length;
499 
500 	g_assert (NULL != symbol);
501 	g_assert (NULL != mangled_symbol);
502 	g_assert (0 != length);
503 
504 #if defined(TARGET_WIN32) && defined(TARGET_X86)
505 	if (symbol && '_' != symbol [0]) {
506 		needed_size = g_snprintf (mangled_symbol, length, "_%s", symbol);
507 	} else {
508 		needed_size = g_snprintf (mangled_symbol, length, "%s", symbol);
509 	}
510 #else
511 	needed_size = g_snprintf (mangled_symbol, length, "%s", symbol);
512 #endif
513 
514 	g_assert (0 <= needed_size && needed_size < length);
515 	return mangled_symbol;
516 }
517 
518 static inline char *
mangle_symbol_alloc(const char * symbol)519 mangle_symbol_alloc (const char * symbol)
520 {
521 	g_assert (NULL != symbol);
522 
523 #if defined(TARGET_WIN32) && defined(TARGET_X86)
524 	if (symbol && '_' != symbol [0]) {
525 		return g_strdup_printf ("_%s", symbol);
526 	}
527 	else {
528 		return g_strdup_printf ("%s", symbol);
529 	}
530 #else
531 	return g_strdup_printf ("%s", symbol);
532 #endif
533 }
534 
535 static inline void
emit_section_change(MonoAotCompile * acfg,const char * section_name,int subsection_index)536 emit_section_change (MonoAotCompile *acfg, const char *section_name, int subsection_index)
537 {
538 	mono_img_writer_emit_section_change (acfg->w, section_name, subsection_index);
539 }
540 
541 #if defined(TARGET_WIN32) && defined(TARGET_X86)
542 
543 static inline void
emit_local_symbol(MonoAotCompile * acfg,const char * name,const char * end_label,gboolean func)544 emit_local_symbol (MonoAotCompile *acfg, const char *name, const char *end_label, gboolean func)
545 {
546 	const char * mangled_symbol_name = name;
547 	char * mangled_symbol_name_alloc = NULL;
548 
549 	if (TRUE == func) {
550 		mangled_symbol_name_alloc = mangle_symbol_alloc (name);
551 		mangled_symbol_name = mangled_symbol_name_alloc;
552 	}
553 
554 	if (name != mangled_symbol_name && 0 != g_strcasecmp (name, mangled_symbol_name)) {
555 		mono_img_writer_emit_label (acfg->w, mangled_symbol_name);
556 	}
557 	mono_img_writer_emit_local_symbol (acfg->w, mangled_symbol_name, end_label, func);
558 
559 	if (NULL != mangled_symbol_name_alloc) {
560 		g_free (mangled_symbol_name_alloc);
561 	}
562 }
563 
564 #else
565 
566 static inline void
emit_local_symbol(MonoAotCompile * acfg,const char * name,const char * end_label,gboolean func)567 emit_local_symbol (MonoAotCompile *acfg, const char *name, const char *end_label, gboolean func)
568 {
569 	mono_img_writer_emit_local_symbol (acfg->w, name, end_label, func);
570 }
571 
572 #endif
573 
574 static inline void
emit_label(MonoAotCompile * acfg,const char * name)575 emit_label (MonoAotCompile *acfg, const char *name)
576 {
577 	mono_img_writer_emit_label (acfg->w, name);
578 }
579 
580 static inline void
emit_bytes(MonoAotCompile * acfg,const guint8 * buf,int size)581 emit_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
582 {
583 	mono_img_writer_emit_bytes (acfg->w, buf, size);
584 }
585 
586 static inline void
emit_string(MonoAotCompile * acfg,const char * value)587 emit_string (MonoAotCompile *acfg, const char *value)
588 {
589 	mono_img_writer_emit_string (acfg->w, value);
590 }
591 
592 static inline void
emit_line(MonoAotCompile * acfg)593 emit_line (MonoAotCompile *acfg)
594 {
595 	mono_img_writer_emit_line (acfg->w);
596 }
597 
598 static inline void
emit_alignment(MonoAotCompile * acfg,int size)599 emit_alignment (MonoAotCompile *acfg, int size)
600 {
601 	mono_img_writer_emit_alignment (acfg->w, size);
602 }
603 
604 static inline void
emit_alignment_code(MonoAotCompile * acfg,int size)605 emit_alignment_code (MonoAotCompile *acfg, int size)
606 {
607 	if (acfg->align_pad_value)
608 		mono_img_writer_emit_alignment_fill (acfg->w, size, acfg->align_pad_value);
609 	else
610 		mono_img_writer_emit_alignment (acfg->w, size);
611 }
612 
613 static inline void
emit_padding(MonoAotCompile * acfg,int size)614 emit_padding (MonoAotCompile *acfg, int size)
615 {
616 	int i;
617 	guint8 buf [16];
618 
619 	if (acfg->align_pad_value) {
620 		for (i = 0; i < 16; ++i)
621 			buf [i] = acfg->align_pad_value;
622 	} else {
623 		memset (buf, 0, sizeof (buf));
624 	}
625 
626 	for (i = 0; i < size; i += 16) {
627 		if (size - i < 16)
628 			emit_bytes (acfg, buf, size - i);
629 		else
630 			emit_bytes (acfg, buf, 16);
631 	}
632 }
633 
634 static inline void
emit_pointer(MonoAotCompile * acfg,const char * target)635 emit_pointer (MonoAotCompile *acfg, const char *target)
636 {
637 	mono_img_writer_emit_pointer (acfg->w, target);
638 }
639 
640 static inline void
emit_pointer_2(MonoAotCompile * acfg,const char * prefix,const char * target)641 emit_pointer_2 (MonoAotCompile *acfg, const char *prefix, const char *target)
642 {
643 	if (prefix [0] != '\0') {
644 		char *s = g_strdup_printf ("%s%s", prefix, target);
645 		mono_img_writer_emit_pointer (acfg->w, s);
646 		g_free (s);
647 	} else {
648 		mono_img_writer_emit_pointer (acfg->w, target);
649 	}
650 }
651 
652 static inline void
emit_int16(MonoAotCompile * acfg,int value)653 emit_int16 (MonoAotCompile *acfg, int value)
654 {
655 	mono_img_writer_emit_int16 (acfg->w, value);
656 }
657 
658 static inline void
emit_int32(MonoAotCompile * acfg,int value)659 emit_int32 (MonoAotCompile *acfg, int value)
660 {
661 	mono_img_writer_emit_int32 (acfg->w, value);
662 }
663 
664 static inline void
emit_symbol_diff(MonoAotCompile * acfg,const char * end,const char * start,int offset)665 emit_symbol_diff (MonoAotCompile *acfg, const char *end, const char* start, int offset)
666 {
667 	mono_img_writer_emit_symbol_diff (acfg->w, end, start, offset);
668 }
669 
670 static inline void
emit_zero_bytes(MonoAotCompile * acfg,int num)671 emit_zero_bytes (MonoAotCompile *acfg, int num)
672 {
673 	mono_img_writer_emit_zero_bytes (acfg->w, num);
674 }
675 
676 static inline void
emit_byte(MonoAotCompile * acfg,guint8 val)677 emit_byte (MonoAotCompile *acfg, guint8 val)
678 {
679 	mono_img_writer_emit_byte (acfg->w, val);
680 }
681 
682 #if defined(TARGET_WIN32) && defined(TARGET_X86)
683 
684 static G_GNUC_UNUSED void
emit_global_inner(MonoAotCompile * acfg,const char * name,gboolean func)685 emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
686 {
687 	const char * mangled_symbol_name = name;
688 	char * mangled_symbol_name_alloc = NULL;
689 
690 	mangled_symbol_name_alloc = mangle_symbol_alloc (name);
691 	mangled_symbol_name = mangled_symbol_name_alloc;
692 
693 	if (0 != g_strcasecmp (name, mangled_symbol_name)) {
694 		mono_img_writer_emit_label (acfg->w, mangled_symbol_name);
695 	}
696 	mono_img_writer_emit_global (acfg->w, mangled_symbol_name, func);
697 
698 	if (NULL != mangled_symbol_name_alloc) {
699 		g_free (mangled_symbol_name_alloc);
700 	}
701 }
702 
703 #else
704 
705 static G_GNUC_UNUSED void
emit_global_inner(MonoAotCompile * acfg,const char * name,gboolean func)706 emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
707 {
708 	mono_img_writer_emit_global (acfg->w, name, func);
709 }
710 
711 #endif
712 
713 static inline gboolean
link_shared_library(MonoAotCompile * acfg)714 link_shared_library (MonoAotCompile *acfg)
715 {
716 	return !acfg->aot_opts.static_link && !acfg->aot_opts.asm_only;
717 }
718 
719 static inline gboolean
add_to_global_symbol_table(MonoAotCompile * acfg)720 add_to_global_symbol_table (MonoAotCompile *acfg)
721 {
722 #ifdef TARGET_WIN32_MSVC
723 	return acfg->aot_opts.no_dlsym || link_shared_library (acfg);
724 #else
725 	return acfg->aot_opts.no_dlsym;
726 #endif
727 }
728 
729 static void
emit_global(MonoAotCompile * acfg,const char * name,gboolean func)730 emit_global (MonoAotCompile *acfg, const char *name, gboolean func)
731 {
732 	if (add_to_global_symbol_table (acfg))
733 		g_ptr_array_add (acfg->globals, g_strdup (name));
734 
735 	if (acfg->aot_opts.no_dlsym) {
736 		mono_img_writer_emit_local_symbol (acfg->w, name, NULL, func);
737 	} else {
738 		emit_global_inner (acfg, name, func);
739 	}
740 }
741 
742 static void
emit_symbol_size(MonoAotCompile * acfg,const char * name,const char * end_label)743 emit_symbol_size (MonoAotCompile *acfg, const char *name, const char *end_label)
744 {
745 	mono_img_writer_emit_symbol_size (acfg->w, name, end_label);
746 }
747 
748 /* Emit a symbol which is referenced by the MonoAotFileInfo structure */
749 static void
emit_info_symbol(MonoAotCompile * acfg,const char * name)750 emit_info_symbol (MonoAotCompile *acfg, const char *name)
751 {
752 	char symbol [MAX_SYMBOL_SIZE];
753 
754 	if (acfg->llvm) {
755 		emit_label (acfg, name);
756 		/* LLVM generated code references this */
757 		sprintf (symbol, "%s%s%s", acfg->user_symbol_prefix, acfg->global_prefix, name);
758 		emit_label (acfg, symbol);
759 		emit_global_inner (acfg, symbol, FALSE);
760 	} else {
761 		emit_label (acfg, name);
762 	}
763 }
764 
765 static void
emit_string_symbol(MonoAotCompile * acfg,const char * name,const char * value)766 emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
767 {
768 	if (acfg->llvm) {
769 		mono_llvm_emit_aot_data (name, (guint8*)value, strlen (value) + 1);
770 		return;
771 	}
772 
773 	mono_img_writer_emit_section_change (acfg->w, RODATA_SECT, 1);
774 #ifdef TARGET_MACH
775 	/* On apple, all symbols need to be aligned to avoid warnings from ld */
776 	emit_alignment (acfg, 4);
777 #endif
778 	mono_img_writer_emit_label (acfg->w, name);
779 	mono_img_writer_emit_string (acfg->w, value);
780 }
781 
782 static G_GNUC_UNUSED void
emit_uleb128(MonoAotCompile * acfg,guint32 value)783 emit_uleb128 (MonoAotCompile *acfg, guint32 value)
784 {
785 	do {
786 		guint8 b = value & 0x7f;
787 		value >>= 7;
788 		if (value != 0) /* more bytes to come */
789 			b |= 0x80;
790 		emit_byte (acfg, b);
791 	} while (value);
792 }
793 
794 static G_GNUC_UNUSED void
emit_sleb128(MonoAotCompile * acfg,gint64 value)795 emit_sleb128 (MonoAotCompile *acfg, gint64 value)
796 {
797 	gboolean more = 1;
798 	gboolean negative = (value < 0);
799 	guint32 size = 64;
800 	guint8 byte;
801 
802 	while (more) {
803 		byte = value & 0x7f;
804 		value >>= 7;
805 		/* the following is unnecessary if the
806 		 * implementation of >>= uses an arithmetic rather
807 		 * than logical shift for a signed left operand
808 		 */
809 		if (negative)
810 			/* sign extend */
811 			value |= - ((gint64)1 <<(size - 7));
812 		/* sign bit of byte is second high order bit (0x40) */
813 		if ((value == 0 && !(byte & 0x40)) ||
814 			(value == -1 && (byte & 0x40)))
815 			more = 0;
816 		else
817 			byte |= 0x80;
818 		emit_byte (acfg, byte);
819 	}
820 }
821 
822 static G_GNUC_UNUSED void
encode_uleb128(guint32 value,guint8 * buf,guint8 ** endbuf)823 encode_uleb128 (guint32 value, guint8 *buf, guint8 **endbuf)
824 {
825 	guint8 *p = buf;
826 
827 	do {
828 		guint8 b = value & 0x7f;
829 		value >>= 7;
830 		if (value != 0) /* more bytes to come */
831 			b |= 0x80;
832 		*p ++ = b;
833 	} while (value);
834 
835 	*endbuf = p;
836 }
837 
838 static G_GNUC_UNUSED void
encode_sleb128(gint32 value,guint8 * buf,guint8 ** endbuf)839 encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
840 {
841 	gboolean more = 1;
842 	gboolean negative = (value < 0);
843 	guint32 size = 32;
844 	guint8 byte;
845 	guint8 *p = buf;
846 
847 	while (more) {
848 		byte = value & 0x7f;
849 		value >>= 7;
850 		/* the following is unnecessary if the
851 		 * implementation of >>= uses an arithmetic rather
852 		 * than logical shift for a signed left operand
853 		 */
854 		if (negative)
855 			/* sign extend */
856 			value |= - (1 <<(size - 7));
857 		/* sign bit of byte is second high order bit (0x40) */
858 		if ((value == 0 && !(byte & 0x40)) ||
859 			(value == -1 && (byte & 0x40)))
860 			more = 0;
861 		else
862 			byte |= 0x80;
863 		*p ++= byte;
864 	}
865 
866 	*endbuf = p;
867 }
868 
869 static void
encode_int(gint32 val,guint8 * buf,guint8 ** endbuf)870 encode_int (gint32 val, guint8 *buf, guint8 **endbuf)
871 {
872 	// FIXME: Big-endian
873 	buf [0] = (val >> 0) & 0xff;
874 	buf [1] = (val >> 8) & 0xff;
875 	buf [2] = (val >> 16) & 0xff;
876 	buf [3] = (val >> 24) & 0xff;
877 
878 	*endbuf = buf + 4;
879 }
880 
881 static void
encode_int16(guint16 val,guint8 * buf,guint8 ** endbuf)882 encode_int16 (guint16 val, guint8 *buf, guint8 **endbuf)
883 {
884 	buf [0] = (val >> 0) & 0xff;
885 	buf [1] = (val >> 8) & 0xff;
886 
887 	*endbuf = buf + 2;
888 }
889 
890 static void
encode_string(const char * s,guint8 * buf,guint8 ** endbuf)891 encode_string (const char *s, guint8 *buf, guint8 **endbuf)
892 {
893 	int len = strlen (s);
894 
895 	memcpy (buf, s, len + 1);
896 	*endbuf = buf + len + 1;
897 }
898 
899 static void
emit_unset_mode(MonoAotCompile * acfg)900 emit_unset_mode (MonoAotCompile *acfg)
901 {
902 	mono_img_writer_emit_unset_mode (acfg->w);
903 }
904 
905 static G_GNUC_UNUSED void
emit_set_thumb_mode(MonoAotCompile * acfg)906 emit_set_thumb_mode (MonoAotCompile *acfg)
907 {
908 	emit_unset_mode (acfg);
909 	fprintf (acfg->fp, ".code 16\n");
910 }
911 
912 static G_GNUC_UNUSED void
emit_set_arm_mode(MonoAotCompile * acfg)913 emit_set_arm_mode (MonoAotCompile *acfg)
914 {
915 	emit_unset_mode (acfg);
916 	fprintf (acfg->fp, ".code 32\n");
917 }
918 
919 static inline void
emit_code_bytes(MonoAotCompile * acfg,const guint8 * buf,int size)920 emit_code_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
921 {
922 #ifdef TARGET_ARM64
923 	int i;
924 
925 	g_assert (size % 4 == 0);
926 	emit_unset_mode (acfg);
927 	for (i = 0; i < size; i += 4)
928 		fprintf (acfg->fp, "%s 0x%x\n", acfg->inst_directive, *(guint32*)(buf + i));
929 #else
930 	emit_bytes (acfg, buf, size);
931 #endif
932 }
933 
934 /* ARCHITECTURE SPECIFIC CODE */
935 
936 #if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_POWERPC) || defined(TARGET_ARM64)
937 #define EMIT_DWARF_INFO 1
938 #endif
939 
940 #ifdef TARGET_WIN32_MSVC
941 #undef EMIT_DWARF_INFO
942 #define EMIT_WIN32_CODEVIEW_INFO
943 #endif
944 
945 #ifdef EMIT_WIN32_UNWIND_INFO
946 static UnwindInfoSectionCacheItem *
947 get_cached_unwind_info_section_item_win32 (MonoAotCompile *acfg, const char *function_start, const char *function_end, GSList *unwind_ops);
948 
949 static void
950 free_unwind_info_section_cache_win32 (MonoAotCompile *acfg);
951 
952 static void
953 emit_unwind_info_data_win32 (MonoAotCompile *acfg, PUNWIND_INFO unwind_info);
954 
955 static void
956 emit_unwind_info_sections_win32 (MonoAotCompile *acfg, const char *function_start, const char *function_end, GSList *unwind_ops);
957 #endif
958 
959 static void
arch_free_unwind_info_section_cache(MonoAotCompile * acfg)960 arch_free_unwind_info_section_cache (MonoAotCompile *acfg)
961 {
962 #ifdef EMIT_WIN32_UNWIND_INFO
963 	free_unwind_info_section_cache_win32 (acfg);
964 #endif
965 }
966 
967 static void
arch_emit_unwind_info_sections(MonoAotCompile * acfg,const char * function_start,const char * function_end,GSList * unwind_ops)968 arch_emit_unwind_info_sections (MonoAotCompile *acfg, const char *function_start, const char *function_end, GSList *unwind_ops)
969 {
970 #ifdef EMIT_WIN32_UNWIND_INFO
971 	gboolean own_unwind_ops = FALSE;
972 	if (!unwind_ops) {
973 		unwind_ops = mono_unwind_get_cie_program ();
974 		own_unwind_ops = TRUE;
975 	}
976 
977 	emit_unwind_info_sections_win32 (acfg, function_start, function_end, unwind_ops);
978 
979 	if (own_unwind_ops)
980 		mono_free_unwind_info (unwind_ops);
981 #endif
982 }
983 
984 #if defined(TARGET_ARM)
985 #define AOT_FUNC_ALIGNMENT 4
986 #else
987 #define AOT_FUNC_ALIGNMENT 16
988 #endif
989 
990 #if defined(TARGET_POWERPC64) && !defined(__mono_ilp32__)
991 #define PPC_LD_OP "ld"
992 #define PPC_LDX_OP "ldx"
993 #else
994 #define PPC_LD_OP "lwz"
995 #define PPC_LDX_OP "lwzx"
996 #endif
997 
998 #ifdef TARGET_X86_64_WIN32_MSVC
999 #define AOT_TARGET_STR "AMD64 (WIN32) (MSVC codegen)"
1000 #elif TARGET_AMD64
1001 #define AOT_TARGET_STR "AMD64"
1002 #endif
1003 
1004 #ifdef TARGET_ARM
1005 #ifdef TARGET_MACH
1006 #define AOT_TARGET_STR "ARM (MACH)"
1007 #else
1008 #define AOT_TARGET_STR "ARM (!MACH)"
1009 #endif
1010 #endif
1011 
1012 #ifdef TARGET_ARM64
1013 #ifdef TARGET_MACH
1014 #define AOT_TARGET_STR "ARM64 (MACH)"
1015 #else
1016 #define AOT_TARGET_STR "ARM64 (!MACH)"
1017 #endif
1018 #endif
1019 
1020 #ifdef TARGET_POWERPC64
1021 #ifdef __mono_ilp32__
1022 #define AOT_TARGET_STR "POWERPC64 (mono ilp32)"
1023 #else
1024 #define AOT_TARGET_STR "POWERPC64 (!mono ilp32)"
1025 #endif
1026 #else
1027 #ifdef TARGET_POWERPC
1028 #ifdef __mono_ilp32__
1029 #define AOT_TARGET_STR "POWERPC (mono ilp32)"
1030 #else
1031 #define AOT_TARGET_STR "POWERPC (!mono ilp32)"
1032 #endif
1033 #endif
1034 #endif
1035 
1036 #ifdef TARGET_X86
1037 #ifdef TARGET_WIN32
1038 #define AOT_TARGET_STR "X86 (WIN32)"
1039 #else
1040 #define AOT_TARGET_STR "X86"
1041 #endif
1042 #endif
1043 
1044 #ifndef AOT_TARGET_STR
1045 #define AOT_TARGET_STR ""
1046 #endif
1047 
1048 static void
arch_init(MonoAotCompile * acfg)1049 arch_init (MonoAotCompile *acfg)
1050 {
1051 	acfg->llc_args = g_string_new ("");
1052 	acfg->as_args = g_string_new ("");
1053 	acfg->llvm_owriter_supported = TRUE;
1054 
1055 	/*
1056 	 * The prefix LLVM likes to put in front of symbol names on darwin.
1057 	 * The mach-os specs require this for globals, but LLVM puts them in front of all
1058 	 * symbols. We need to handle this, since we need to refer to LLVM generated
1059 	 * symbols.
1060 	 */
1061 	acfg->llvm_label_prefix = "";
1062 	acfg->user_symbol_prefix = "";
1063 
1064 #if defined(TARGET_X86)
1065 	g_string_append (acfg->llc_args, " -march=x86 -mattr=sse4.1");
1066 #endif
1067 
1068 #if defined(TARGET_AMD64)
1069 	g_string_append (acfg->llc_args, " -march=x86-64 -mattr=sse4.1");
1070 	/* NOP */
1071 	acfg->align_pad_value = 0x90;
1072 #endif
1073 
1074 #ifdef TARGET_ARM
1075 	if (acfg->aot_opts.mtriple && strstr (acfg->aot_opts.mtriple, "darwin")) {
1076 		g_string_append (acfg->llc_args, "-mattr=+v6");
1077 	} else {
1078 #if defined(ARM_FPU_VFP_HARD)
1079 		g_string_append (acfg->llc_args, " -mattr=+vfp2,-neon,+d16 -float-abi=hard");
1080 		g_string_append (acfg->as_args, " -mfpu=vfp3");
1081 #elif defined(ARM_FPU_VFP)
1082 		g_string_append (acfg->llc_args, " -mattr=+vfp2,-neon,+d16");
1083 		g_string_append (acfg->as_args, " -mfpu=vfp3");
1084 #else
1085 		g_string_append (acfg->llc_args, " -soft-float");
1086 #endif
1087 	}
1088 	if (acfg->aot_opts.mtriple && strstr (acfg->aot_opts.mtriple, "thumb"))
1089 		acfg->thumb_mixed = TRUE;
1090 
1091 	if (acfg->aot_opts.mtriple)
1092 		mono_arch_set_target (acfg->aot_opts.mtriple);
1093 #endif
1094 
1095 #ifdef TARGET_ARM64
1096 	acfg->inst_directive = ".inst";
1097 	if (acfg->aot_opts.mtriple)
1098 		mono_arch_set_target (acfg->aot_opts.mtriple);
1099 #endif
1100 
1101 #ifdef TARGET_MACH
1102 	acfg->user_symbol_prefix = "_";
1103 	acfg->llvm_label_prefix = "_";
1104 	acfg->inst_directive = ".word";
1105 	acfg->need_no_dead_strip = TRUE;
1106 	acfg->aot_opts.gnu_asm = TRUE;
1107 #endif
1108 
1109 #if defined(__linux__) && !defined(TARGET_ARM)
1110 	acfg->need_pt_gnu_stack = TRUE;
1111 #endif
1112 
1113 #ifdef MONOTOUCH
1114 	acfg->global_symbols = TRUE;
1115 #endif
1116 
1117 #ifdef TARGET_ANDROID
1118 	acfg->llvm_owriter_supported = FALSE;
1119 #endif
1120 }
1121 
1122 #ifdef TARGET_ARM64
1123 
1124 
1125 /* Load the contents of GOT_SLOT into dreg, clobbering ip0 */
1126 static void
arm64_emit_load_got_slot(MonoAotCompile * acfg,int dreg,int got_slot)1127 arm64_emit_load_got_slot (MonoAotCompile *acfg, int dreg, int got_slot)
1128 {
1129 	int offset;
1130 
1131 	g_assert (acfg->fp);
1132 	emit_unset_mode (acfg);
1133 	/* r16==ip0 */
1134 	offset = (int)(got_slot * sizeof (gpointer));
1135 #ifdef TARGET_MACH
1136 	/* clang's integrated assembler */
1137 	fprintf (acfg->fp, "adrp x16, %s@PAGE+%d\n", acfg->got_symbol, offset & 0xfffff000);
1138 	fprintf (acfg->fp, "add x16, x16, %s@PAGEOFF\n", acfg->got_symbol);
1139 	fprintf (acfg->fp, "ldr x%d, [x16, #%d]\n", dreg, offset & 0xfff);
1140 #else
1141 	/* Linux GAS */
1142 	fprintf (acfg->fp, "adrp x16, %s+%d\n", acfg->got_symbol, offset & 0xfffff000);
1143 	fprintf (acfg->fp, "add x16, x16, :lo12:%s\n", acfg->got_symbol);
1144 	fprintf (acfg->fp, "ldr x%d, [x16, %d]\n", dreg, offset & 0xfff);
1145 #endif
1146 }
1147 
1148 static void
arm64_emit_objc_selector_ref(MonoAotCompile * acfg,guint8 * code,int index,int * code_size)1149 arm64_emit_objc_selector_ref (MonoAotCompile *acfg, guint8 *code, int index, int *code_size)
1150 {
1151 	int reg;
1152 
1153 	g_assert (acfg->fp);
1154 	emit_unset_mode (acfg);
1155 
1156 	/* ldr rt, target */
1157 	reg = arm_get_ldr_lit_reg (code);
1158 
1159 	fprintf (acfg->fp, "adrp x%d, L_OBJC_SELECTOR_REFERENCES_%d@PAGE\n", reg, index);
1160 	fprintf (acfg->fp, "add x%d, x%d, L_OBJC_SELECTOR_REFERENCES_%d@PAGEOFF\n", reg, reg, index);
1161 	fprintf (acfg->fp, "ldr x%d, [x%d]\n", reg, reg);
1162 
1163 	*code_size = 12;
1164 }
1165 
1166 static void
arm64_emit_direct_call(MonoAotCompile * acfg,const char * target,gboolean external,gboolean thumb,MonoJumpInfo * ji,int * call_size)1167 arm64_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, gboolean thumb, MonoJumpInfo *ji, int *call_size)
1168 {
1169 	g_assert (acfg->fp);
1170 	emit_unset_mode (acfg);
1171 	if (ji && ji->relocation == MONO_R_ARM64_B) {
1172 		fprintf (acfg->fp, "b %s\n", target);
1173 	} else {
1174 		if (ji)
1175 			g_assert (ji->relocation == MONO_R_ARM64_BL);
1176 		fprintf (acfg->fp, "bl %s\n", target);
1177 	}
1178 	*call_size = 4;
1179 }
1180 
1181 static void
arm64_emit_got_access(MonoAotCompile * acfg,guint8 * code,int got_slot,int * code_size)1182 arm64_emit_got_access (MonoAotCompile *acfg, guint8 *code, int got_slot, int *code_size)
1183 {
1184 	int reg;
1185 
1186 	/* ldr rt, target */
1187 	reg = arm_get_ldr_lit_reg (code);
1188 	arm64_emit_load_got_slot (acfg, reg, got_slot);
1189 	*code_size = 12;
1190 }
1191 
1192 static void
arm64_emit_plt_entry(MonoAotCompile * acfg,const char * got_symbol,int offset,int info_offset)1193 arm64_emit_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offset, int info_offset)
1194 {
1195 	arm64_emit_load_got_slot (acfg, ARMREG_R16, offset / sizeof (gpointer));
1196 	fprintf (acfg->fp, "br x16\n");
1197 	/* Used by mono_aot_get_plt_info_offset () */
1198 	fprintf (acfg->fp, "%s %d\n", acfg->inst_directive, info_offset);
1199 }
1200 
1201 static void
arm64_emit_tramp_page_common_code(MonoAotCompile * acfg,int pagesize,int arg_reg,int * size)1202 arm64_emit_tramp_page_common_code (MonoAotCompile *acfg, int pagesize, int arg_reg, int *size)
1203 {
1204 	guint8 buf [256];
1205 	guint8 *code;
1206 	int imm;
1207 
1208 	/* The common code */
1209 	code = buf;
1210 	imm = pagesize;
1211 	/* The trampoline address is in IP0 */
1212 	arm_movzx (code, ARMREG_IP1, imm & 0xffff, 0);
1213 	arm_movkx (code, ARMREG_IP1, (imm >> 16) & 0xffff, 16);
1214 	/* Compute the data slot address */
1215 	arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
1216 	/* Trampoline argument */
1217 	arm_ldrx (code, arg_reg, ARMREG_IP0, 0);
1218 	/* Address */
1219 	arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 8);
1220 	arm_brx (code, ARMREG_IP0);
1221 
1222 	/* Emit it */
1223 	emit_code_bytes (acfg, buf, code - buf);
1224 
1225 	*size = code - buf;
1226 }
1227 
1228 static void
arm64_emit_tramp_page_specific_code(MonoAotCompile * acfg,int pagesize,int common_tramp_size,int specific_tramp_size)1229 arm64_emit_tramp_page_specific_code (MonoAotCompile *acfg, int pagesize, int common_tramp_size, int specific_tramp_size)
1230 {
1231 	guint8 buf [256];
1232 	guint8 *code;
1233 	int i, count;
1234 
1235 	count = (pagesize - common_tramp_size) / specific_tramp_size;
1236 	for (i = 0; i < count; ++i) {
1237 		code = buf;
1238 		arm_adrx (code, ARMREG_IP0, code);
1239 		/* Branch to the generic code */
1240 		arm_b (code, code - 4 - (i * specific_tramp_size) - common_tramp_size);
1241 		/* This has to be 2 pointers long */
1242 		arm_nop (code);
1243 		arm_nop (code);
1244 		g_assert (code - buf == specific_tramp_size);
1245 		emit_code_bytes (acfg, buf, code - buf);
1246 	}
1247 }
1248 
1249 static void
arm64_emit_specific_trampoline_pages(MonoAotCompile * acfg)1250 arm64_emit_specific_trampoline_pages (MonoAotCompile *acfg)
1251 {
1252 	guint8 buf [128];
1253 	guint8 *code;
1254 	guint8 *labels [16];
1255 	int common_tramp_size;
1256 	int specific_tramp_size = 2 * 8;
1257 	int imm, pagesize;
1258 	char symbol [128];
1259 
1260 	if (!acfg->aot_opts.use_trampolines_page)
1261 		return;
1262 
1263 #ifdef TARGET_MACH
1264 	/* Have to match the target pagesize */
1265 	pagesize = 16384;
1266 #else
1267 	pagesize = mono_pagesize ();
1268 #endif
1269 	acfg->tramp_page_size = pagesize;
1270 
1271 	/* The specific trampolines */
1272 	sprintf (symbol, "%sspecific_trampolines_page", acfg->user_symbol_prefix);
1273 	emit_alignment (acfg, pagesize);
1274 	emit_global (acfg, symbol, TRUE);
1275 	emit_label (acfg, symbol);
1276 
1277 	/* The common code */
1278 	arm64_emit_tramp_page_common_code (acfg, pagesize, ARMREG_IP1, &common_tramp_size);
1279 	acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_SPECIFIC] = common_tramp_size;
1280 
1281 	arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
1282 
1283 	/* The rgctx trampolines */
1284 	/* These are the same as the specific trampolines, but they load the argument into MONO_ARCH_RGCTX_REG */
1285 	sprintf (symbol, "%srgctx_trampolines_page", acfg->user_symbol_prefix);
1286 	emit_alignment (acfg, pagesize);
1287 	emit_global (acfg, symbol, TRUE);
1288 	emit_label (acfg, symbol);
1289 
1290 	/* The common code */
1291 	arm64_emit_tramp_page_common_code (acfg, pagesize, MONO_ARCH_RGCTX_REG, &common_tramp_size);
1292 	acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = common_tramp_size;
1293 
1294 	arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
1295 
1296 	/* The gsharedvt arg trampolines */
1297 	/* These are the same as the specific trampolines */
1298 	sprintf (symbol, "%sgsharedvt_arg_trampolines_page", acfg->user_symbol_prefix);
1299 	emit_alignment (acfg, pagesize);
1300 	emit_global (acfg, symbol, TRUE);
1301 	emit_label (acfg, symbol);
1302 
1303 	arm64_emit_tramp_page_common_code (acfg, pagesize, ARMREG_IP1, &common_tramp_size);
1304 	acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = common_tramp_size;
1305 
1306 	arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
1307 
1308 	/* The IMT trampolines */
1309 	sprintf (symbol, "%simt_trampolines_page", acfg->user_symbol_prefix);
1310 	emit_alignment (acfg, pagesize);
1311 	emit_global (acfg, symbol, TRUE);
1312 	emit_label (acfg, symbol);
1313 
1314 	code = buf;
1315 	imm = pagesize;
1316 	/* The trampoline address is in IP0 */
1317 	arm_movzx (code, ARMREG_IP1, imm & 0xffff, 0);
1318 	arm_movkx (code, ARMREG_IP1, (imm >> 16) & 0xffff, 16);
1319 	/* Compute the data slot address */
1320 	arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1);
1321 	/* Trampoline argument */
1322 	arm_ldrx (code, ARMREG_IP1, ARMREG_IP0, 0);
1323 
1324 	/* Same as arch_emit_imt_trampoline () */
1325 	labels [0] = code;
1326 	arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 0);
1327 	arm_cmpx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
1328 	labels [1] = code;
1329 	arm_bcc (code, ARMCOND_EQ, 0);
1330 
1331 	/* End-of-loop check */
1332 	labels [2] = code;
1333 	arm_cbzx (code, ARMREG_IP0, 0);
1334 
1335 	/* Loop footer */
1336 	arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 2 * 8);
1337 	arm_b (code, labels [0]);
1338 
1339 	/* Match */
1340 	mono_arm_patch (labels [1], code, MONO_R_ARM64_BCC);
1341 	/* Load vtable slot addr */
1342 	arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8);
1343 	/* Load vtable slot */
1344 	arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0);
1345 	arm_brx (code, ARMREG_IP0);
1346 
1347 	/* No match */
1348 	mono_arm_patch (labels [2], code, MONO_R_ARM64_CBZ);
1349 	/* Load fail addr */
1350 	arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8);
1351 	arm_brx (code, ARMREG_IP0);
1352 
1353 	emit_code_bytes (acfg, buf, code - buf);
1354 
1355 	common_tramp_size = code - buf;
1356 	acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT] = common_tramp_size;
1357 
1358 	arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
1359 }
1360 
1361 static void
arm64_emit_specific_trampoline(MonoAotCompile * acfg,int offset,int * tramp_size)1362 arm64_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
1363 {
1364 	/* Load argument from second GOT slot */
1365 	arm64_emit_load_got_slot (acfg, ARMREG_R17, offset + 1);
1366 	/* Load generic trampoline address from first GOT slot */
1367 	arm64_emit_load_got_slot (acfg, ARMREG_R16, offset);
1368 	fprintf (acfg->fp, "br x16\n");
1369 	*tramp_size = 7 * 4;
1370 }
1371 
1372 static void
arm64_emit_unbox_trampoline(MonoAotCompile * acfg,MonoCompile * cfg,MonoMethod * method,const char * call_target)1373 arm64_emit_unbox_trampoline (MonoAotCompile *acfg, MonoCompile *cfg, MonoMethod *method, const char *call_target)
1374 {
1375 	emit_unset_mode (acfg);
1376 	fprintf (acfg->fp, "add x0, x0, %d\n", (int)(sizeof (MonoObject)));
1377 	fprintf (acfg->fp, "b %s\n", call_target);
1378 }
1379 
1380 static void
arm64_emit_static_rgctx_trampoline(MonoAotCompile * acfg,int offset,int * tramp_size)1381 arm64_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
1382 {
1383 	/* Similar to the specific trampolines, but use the rgctx reg instead of ip1 */
1384 
1385 	/* Load argument from first GOT slot */
1386 	arm64_emit_load_got_slot (acfg, MONO_ARCH_RGCTX_REG, offset);
1387 	/* Load generic trampoline address from second GOT slot */
1388 	arm64_emit_load_got_slot (acfg, ARMREG_R16, offset + 1);
1389 	fprintf (acfg->fp, "br x16\n");
1390 	*tramp_size = 7 * 4;
1391 }
1392 
1393 static void
arm64_emit_imt_trampoline(MonoAotCompile * acfg,int offset,int * tramp_size)1394 arm64_emit_imt_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
1395 {
1396 	guint8 buf [128];
1397 	guint8 *code, *labels [16];
1398 
1399 	/* Load parameter from GOT slot into ip1 */
1400 	arm64_emit_load_got_slot (acfg, ARMREG_R17, offset);
1401 
1402 	code = buf;
1403 	labels [0] = code;
1404 	arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 0);
1405 	arm_cmpx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
1406 	labels [1] = code;
1407 	arm_bcc (code, ARMCOND_EQ, 0);
1408 
1409 	/* End-of-loop check */
1410 	labels [2] = code;
1411 	arm_cbzx (code, ARMREG_IP0, 0);
1412 
1413 	/* Loop footer */
1414 	arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 2 * 8);
1415 	arm_b (code, labels [0]);
1416 
1417 	/* Match */
1418 	mono_arm_patch (labels [1], code, MONO_R_ARM64_BCC);
1419 	/* Load vtable slot addr */
1420 	arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8);
1421 	/* Load vtable slot */
1422 	arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0);
1423 	arm_brx (code, ARMREG_IP0);
1424 
1425 	/* No match */
1426 	mono_arm_patch (labels [2], code, MONO_R_ARM64_CBZ);
1427 	/* Load fail addr */
1428 	arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8);
1429 	arm_brx (code, ARMREG_IP0);
1430 
1431 	emit_code_bytes (acfg, buf, code - buf);
1432 
1433 	*tramp_size = code - buf + (3 * 4);
1434 }
1435 
1436 static void
arm64_emit_gsharedvt_arg_trampoline(MonoAotCompile * acfg,int offset,int * tramp_size)1437 arm64_emit_gsharedvt_arg_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
1438 {
1439 	/* Similar to the specific trampolines, but the address is in the second slot */
1440 	/* Load argument from first GOT slot */
1441 	arm64_emit_load_got_slot (acfg, ARMREG_R17, offset);
1442 	/* Load generic trampoline address from second GOT slot */
1443 	arm64_emit_load_got_slot (acfg, ARMREG_R16, offset + 1);
1444 	fprintf (acfg->fp, "br x16\n");
1445 	*tramp_size = 7 * 4;
1446 }
1447 
1448 
1449 #endif
1450 
1451 #ifdef MONO_ARCH_AOT_SUPPORTED
1452 /*
1453  * arch_emit_direct_call:
1454  *
1455  *   Emit a direct call to the symbol TARGET. CALL_SIZE is set to the size of the
1456  * calling code.
1457  */
1458 static void
arch_emit_direct_call(MonoAotCompile * acfg,const char * target,gboolean external,gboolean thumb,MonoJumpInfo * ji,int * call_size)1459 arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, gboolean thumb, MonoJumpInfo *ji, int *call_size)
1460 {
1461 #if defined(TARGET_X86) || defined(TARGET_AMD64)
1462 	/* Need to make sure this is exactly 5 bytes long */
1463 	emit_unset_mode (acfg);
1464 	fprintf (acfg->fp, "call %s\n", target);
1465 	*call_size = 5;
1466 #elif defined(TARGET_ARM)
1467 	emit_unset_mode (acfg);
1468 	if (thumb)
1469 		fprintf (acfg->fp, "blx %s\n", target);
1470 	else
1471 		fprintf (acfg->fp, "bl %s\n", target);
1472 	*call_size = 4;
1473 #elif defined(TARGET_ARM64)
1474 	arm64_emit_direct_call (acfg, target, external, thumb, ji, call_size);
1475 #elif defined(TARGET_POWERPC)
1476 	emit_unset_mode (acfg);
1477 	fprintf (acfg->fp, "bl %s\n", target);
1478 	*call_size = 4;
1479 #else
1480 	g_assert_not_reached ();
1481 #endif
1482 }
1483 #endif
1484 
1485 /*
1486  * PPC32 design:
1487  * - we use an approach similar to the x86 abi: reserve a register (r30) to hold
1488  *   the GOT pointer.
1489  * - The full-aot trampolines need access to the GOT of mscorlib, so we store
1490  *   in in the 2. slot of every GOT, and require every method to place the GOT
1491  *   address in r30, even when it doesn't access the GOT otherwise. This way,
1492  *   the trampolines can compute the mscorlib GOT address by loading 4(r30).
1493  */
1494 
1495 /*
1496  * PPC64 design:
1497  * PPC64 uses function descriptors which greatly complicate all code, since
1498  * these are used very inconsistently in the runtime. Some functions like
1499  * mono_compile_method () return ftn descriptors, while others like the
1500  * trampoline creation functions do not.
1501  * We assume that all GOT slots contain function descriptors, and create
1502  * descriptors in aot-runtime.c when needed.
1503  * The ppc64 abi uses r2 to hold the address of the TOC/GOT, which is loaded
1504  * from function descriptors, we could do the same, but it would require
1505  * rewriting all the ppc/aot code to handle function descriptors properly.
1506  * So instead, we use the same approach as on PPC32.
1507  * This is a horrible mess, but fixing it would probably lead to an even bigger
1508  * one.
1509  */
1510 
1511 /*
1512  * X86 design:
1513  * - similar to the PPC32 design, we reserve EBX to hold the GOT pointer.
1514  */
1515 
1516 #ifdef MONO_ARCH_AOT_SUPPORTED
1517 /*
1518  * arch_emit_got_offset:
1519  *
1520  *   The memory pointed to by CODE should hold native code for computing the GOT
1521  * address (OP_LOAD_GOTADDR). Emit this code while patching it with the offset
1522  * between code and the GOT. CODE_SIZE is set to the number of bytes emitted.
1523  */
1524 static void
arch_emit_got_offset(MonoAotCompile * acfg,guint8 * code,int * code_size)1525 arch_emit_got_offset (MonoAotCompile *acfg, guint8 *code, int *code_size)
1526 {
1527 #if defined(TARGET_POWERPC64)
1528 	emit_unset_mode (acfg);
1529 	/*
1530 	 * The ppc32 code doesn't seem to work on ppc64, the assembler complains about
1531 	 * unsupported relocations. So we store the got address into the .Lgot_addr
1532 	 * symbol which is in the text segment, compute its address, and load it.
1533 	 */
1534 	fprintf (acfg->fp, ".L%d:\n", acfg->label_generator);
1535 	fprintf (acfg->fp, "lis 0, (.Lgot_addr + 4 - .L%d)@h\n", acfg->label_generator);
1536 	fprintf (acfg->fp, "ori 0, 0, (.Lgot_addr + 4 - .L%d)@l\n", acfg->label_generator);
1537 	fprintf (acfg->fp, "add 30, 30, 0\n");
1538 	fprintf (acfg->fp, "%s 30, 0(30)\n", PPC_LD_OP);
1539 	acfg->label_generator ++;
1540 	*code_size = 16;
1541 #elif defined(TARGET_POWERPC)
1542 	emit_unset_mode (acfg);
1543 	fprintf (acfg->fp, ".L%d:\n", acfg->label_generator);
1544 	fprintf (acfg->fp, "lis 0, (%s + 4 - .L%d)@h\n", acfg->got_symbol, acfg->label_generator);
1545 	fprintf (acfg->fp, "ori 0, 0, (%s + 4 - .L%d)@l\n", acfg->got_symbol, acfg->label_generator);
1546 	acfg->label_generator ++;
1547 	*code_size = 8;
1548 #else
1549 	guint32 offset = mono_arch_get_patch_offset (code);
1550 	emit_bytes (acfg, code, offset);
1551 	emit_symbol_diff (acfg, acfg->got_symbol, ".", offset);
1552 
1553 	*code_size = offset + 4;
1554 #endif
1555 }
1556 
1557 /*
1558  * arch_emit_got_access:
1559  *
1560  *   The memory pointed to by CODE should hold native code for loading a GOT
1561  * slot (OP_AOTCONST/OP_GOT_ENTRY). Emit this code while patching it so it accesses the
1562  * GOT slot GOT_SLOT. CODE_SIZE is set to the number of bytes emitted.
1563  */
1564 static void
arch_emit_got_access(MonoAotCompile * acfg,const char * got_symbol,guint8 * code,int got_slot,int * code_size)1565 arch_emit_got_access (MonoAotCompile *acfg, const char *got_symbol, guint8 *code, int got_slot, int *code_size)
1566 {
1567 #ifdef TARGET_AMD64
1568 	/* mov reg, got+offset(%rip) */
1569 	if (acfg->llvm) {
1570 		/* The GOT symbol is in the LLVM module, the clang assembler has problems emitting symbol diffs for it */
1571 		int dreg;
1572 		int rex_r;
1573 
1574 		/* Decode reg, see amd64_mov_reg_membase () */
1575 		rex_r = code [0] & AMD64_REX_R;
1576 		g_assert (code [0] == 0x49 + rex_r);
1577 		g_assert (code [1] == 0x8b);
1578 		dreg = ((code [2] >> 3) & 0x7) + (rex_r ? 8 : 0);
1579 
1580 		emit_unset_mode (acfg);
1581 		fprintf (acfg->fp, "mov %s+%d(%%rip), %s\n", got_symbol, (unsigned int) ((got_slot * sizeof (gpointer))), mono_arch_regname (dreg));
1582 		*code_size = 7;
1583 	} else {
1584 		emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
1585 		emit_symbol_diff (acfg, got_symbol, ".", (unsigned int) ((got_slot * sizeof (gpointer)) - 4));
1586 		*code_size = mono_arch_get_patch_offset (code) + 4;
1587 	}
1588 #elif defined(TARGET_X86)
1589 	emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
1590 	emit_int32 (acfg, (unsigned int) ((got_slot * sizeof (gpointer))));
1591 	*code_size = mono_arch_get_patch_offset (code) + 4;
1592 #elif defined(TARGET_ARM)
1593 	emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
1594 	emit_symbol_diff (acfg, got_symbol, ".", (unsigned int) ((got_slot * sizeof (gpointer))) - 12);
1595 	*code_size = mono_arch_get_patch_offset (code) + 4;
1596 #elif defined(TARGET_ARM64)
1597 	emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
1598 	arm64_emit_got_access (acfg, code, got_slot, code_size);
1599 #elif defined(TARGET_POWERPC)
1600 	{
1601 		guint8 buf [32];
1602 
1603 		emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
1604 		code = buf;
1605 		ppc_load32 (code, ppc_r0, got_slot * sizeof (gpointer));
1606 		g_assert (code - buf == 8);
1607 		emit_bytes (acfg, buf, code - buf);
1608 		*code_size = code - buf;
1609 	}
1610 #else
1611 	g_assert_not_reached ();
1612 #endif
1613 }
1614 
1615 #endif
1616 
1617 #ifdef MONO_ARCH_AOT_SUPPORTED
1618 /*
1619  * arch_emit_objc_selector_ref:
1620  *
1621  *   Emit the implementation of OP_OBJC_GET_SELECTOR, which itself implements @selector(foo:) in objective-c.
1622  */
1623 static void
arch_emit_objc_selector_ref(MonoAotCompile * acfg,guint8 * code,int index,int * code_size)1624 arch_emit_objc_selector_ref (MonoAotCompile *acfg, guint8 *code, int index, int *code_size)
1625 {
1626 #if defined(TARGET_ARM)
1627 	char symbol1 [MAX_SYMBOL_SIZE];
1628 	char symbol2 [MAX_SYMBOL_SIZE];
1629 	int lindex = acfg->objc_selector_index_2 ++;
1630 
1631 	/* Emit ldr.imm/b */
1632 	emit_bytes (acfg, code, 8);
1633 
1634 	sprintf (symbol1, "L_OBJC_SELECTOR_%d", lindex);
1635 	sprintf (symbol2, "L_OBJC_SELECTOR_REFERENCES_%d", index);
1636 
1637 	emit_label (acfg, symbol1);
1638 	mono_img_writer_emit_unset_mode (acfg->w);
1639 	fprintf (acfg->fp, ".long %s-(%s+12)", symbol2, symbol1);
1640 
1641 	*code_size = 12;
1642 #elif defined(TARGET_ARM64)
1643 	arm64_emit_objc_selector_ref (acfg, code, index, code_size);
1644 #else
1645 	g_assert_not_reached ();
1646 #endif
1647 }
1648 #endif
1649 
1650 /*
1651  * arch_emit_plt_entry:
1652  *
1653  *   Emit code for the PLT entry.
1654  * The plt entry should look like this:
1655  * <indirect jump to GOT_SYMBOL + OFFSET>
1656  * <INFO_OFFSET embedded into the instruction stream>
1657  */
1658 static void
arch_emit_plt_entry(MonoAotCompile * acfg,const char * got_symbol,int offset,int info_offset)1659 arch_emit_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offset, int info_offset)
1660 {
1661 #if defined(TARGET_X86)
1662 		/* jmp *<offset>(%ebx) */
1663 		emit_byte (acfg, 0xff);
1664 		emit_byte (acfg, 0xa3);
1665 		emit_int32 (acfg, offset);
1666 		/* Used by mono_aot_get_plt_info_offset */
1667 		emit_int32 (acfg, info_offset);
1668 #elif defined(TARGET_AMD64)
1669 		emit_unset_mode (acfg);
1670 		fprintf (acfg->fp, "jmp *%s+%d(%%rip)\n", got_symbol, offset);
1671 		/* Used by mono_aot_get_plt_info_offset */
1672 		emit_int32 (acfg, info_offset);
1673 		acfg->stats.plt_size += 10;
1674 #elif defined(TARGET_ARM)
1675 		guint8 buf [256];
1676 		guint8 *code;
1677 
1678 		code = buf;
1679 		ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
1680 		ARM_LDR_REG_REG (code, ARMREG_PC, ARMREG_PC, ARMREG_IP);
1681 		emit_bytes (acfg, buf, code - buf);
1682 		emit_symbol_diff (acfg, got_symbol, ".", offset - 4);
1683 		/* Used by mono_aot_get_plt_info_offset */
1684 		emit_int32 (acfg, info_offset);
1685 #elif defined(TARGET_ARM64)
1686 		arm64_emit_plt_entry (acfg, got_symbol, offset, info_offset);
1687 #elif defined(TARGET_POWERPC)
1688 		/* The GOT address is guaranteed to be in r30 by OP_LOAD_GOTADDR */
1689 		emit_unset_mode (acfg);
1690 		fprintf (acfg->fp, "lis 11, %d@h\n", offset);
1691 		fprintf (acfg->fp, "ori 11, 11, %d@l\n", offset);
1692 		fprintf (acfg->fp, "add 11, 11, 30\n");
1693 		fprintf (acfg->fp, "%s 11, 0(11)\n", PPC_LD_OP);
1694 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
1695 		fprintf (acfg->fp, "%s 2, %d(11)\n", PPC_LD_OP, (int)sizeof (gpointer));
1696 		fprintf (acfg->fp, "%s 11, 0(11)\n", PPC_LD_OP);
1697 #endif
1698 		fprintf (acfg->fp, "mtctr 11\n");
1699 		fprintf (acfg->fp, "bctr\n");
1700 		emit_int32 (acfg, info_offset);
1701 #else
1702 		g_assert_not_reached ();
1703 #endif
1704 }
1705 
1706 /*
1707  * arch_emit_llvm_plt_entry:
1708  *
1709  *   Same as arch_emit_plt_entry, but handles calls from LLVM generated code.
1710  * This is only needed on arm to handle thumb interop.
1711  */
1712 static void
arch_emit_llvm_plt_entry(MonoAotCompile * acfg,const char * got_symbol,int offset,int info_offset)1713 arch_emit_llvm_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offset, int info_offset)
1714 {
1715 #if defined(TARGET_ARM)
1716 	/* LLVM calls the PLT entries using bl, so these have to be thumb2 */
1717 	/* The caller already transitioned to thumb */
1718 	/* The code below should be 12 bytes long */
1719 	/* clang has trouble encoding these instructions, so emit the binary */
1720 #if 0
1721 	fprintf (acfg->fp, "ldr ip, [pc, #8]\n");
1722 	/* thumb can't encode ld pc, [pc, ip] */
1723 	fprintf (acfg->fp, "add ip, pc, ip\n");
1724 	fprintf (acfg->fp, "ldr ip, [ip, #0]\n");
1725 	fprintf (acfg->fp, "bx ip\n");
1726 #endif
1727 	emit_set_thumb_mode (acfg);
1728 	fprintf (acfg->fp, ".4byte 0xc008f8df\n");
1729 	fprintf (acfg->fp, ".2byte 0x44fc\n");
1730 	fprintf (acfg->fp, ".4byte 0xc000f8dc\n");
1731 	fprintf (acfg->fp, ".2byte 0x4760\n");
1732 	emit_symbol_diff (acfg, got_symbol, ".", offset + 4);
1733 	emit_int32 (acfg, info_offset);
1734 	emit_unset_mode (acfg);
1735 	emit_set_arm_mode (acfg);
1736 #else
1737 	g_assert_not_reached ();
1738 #endif
1739 }
1740 
1741 /* Save unwind_info in the module and emit the offset to the information at symbol */
save_unwind_info(MonoAotCompile * acfg,char * symbol,GSList * unwind_ops)1742 static void save_unwind_info (MonoAotCompile *acfg, char *symbol, GSList *unwind_ops)
1743 {
1744 	guint32 uw_offset, encoded_len;
1745 	guint8 *encoded;
1746 
1747 	emit_section_change (acfg, RODATA_SECT, 0);
1748 	emit_global (acfg, symbol, FALSE);
1749 	emit_label (acfg, symbol);
1750 
1751 	encoded = mono_unwind_ops_encode (unwind_ops, &encoded_len);
1752 	uw_offset = get_unwind_info_offset (acfg, encoded, encoded_len);
1753 	g_free (encoded);
1754 	emit_int32 (acfg, uw_offset);
1755 }
1756 
1757 /*
1758  * arch_emit_specific_trampoline_pages:
1759  *
1760  * Emits a page full of trampolines: each trampoline uses its own address to
1761  * lookup both the generic trampoline code and the data argument.
1762  * This page can be remapped in process multiple times so we can get an
1763  * unlimited number of trampolines.
1764  * Specifically this implementation uses the following trick: two memory pages
1765  * are allocated, with the first containing the data and the second containing the trampolines.
1766  * To reduce trampoline size, each trampoline jumps at the start of the page where a common
1767  * implementation does all the lifting.
1768  * Note that the ARM single trampoline size is 8 bytes, exactly like the data that needs to be stored
1769  * on the arm 32 bit system.
1770  */
1771 static void
arch_emit_specific_trampoline_pages(MonoAotCompile * acfg)1772 arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
1773 {
1774 #if defined(TARGET_ARM)
1775 	guint8 buf [128];
1776 	guint8 *code;
1777 	guint8 *loop_start, *loop_branch_back, *loop_end_check, *imt_found_check;
1778 	int i;
1779 	int pagesize = MONO_AOT_TRAMP_PAGE_SIZE;
1780 	GSList *unwind_ops = NULL;
1781 #define COMMON_TRAMP_SIZE 16
1782 	int count = (pagesize - COMMON_TRAMP_SIZE) / 8;
1783 	int imm8, rot_amount;
1784 	char symbol [128];
1785 
1786 	if (!acfg->aot_opts.use_trampolines_page)
1787 		return;
1788 
1789 	acfg->tramp_page_size = pagesize;
1790 
1791 	sprintf (symbol, "%sspecific_trampolines_page", acfg->user_symbol_prefix);
1792 	emit_alignment (acfg, pagesize);
1793 	emit_global (acfg, symbol, TRUE);
1794 	emit_label (acfg, symbol);
1795 
1796 	/* emit the generic code first, the trampoline address + 8 is in the lr register */
1797 	code = buf;
1798 	imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
1799 	ARM_SUB_REG_IMM (code, ARMREG_LR, ARMREG_LR, imm8, rot_amount);
1800 	ARM_LDR_IMM (code, ARMREG_R1, ARMREG_LR, -8);
1801 	ARM_LDR_IMM (code, ARMREG_PC, ARMREG_LR, -4);
1802 	ARM_NOP (code);
1803 	g_assert (code - buf == COMMON_TRAMP_SIZE);
1804 
1805 	/* Emit it */
1806 	emit_bytes (acfg, buf, code - buf);
1807 
1808 	for (i = 0; i < count; ++i) {
1809 		code = buf;
1810 		ARM_PUSH (code, 0x5fff);
1811 		ARM_BL (code, 0);
1812 		arm_patch (code - 4, code - COMMON_TRAMP_SIZE - 8 * (i + 1));
1813 		g_assert (code - buf == 8);
1814 		emit_bytes (acfg, buf, code - buf);
1815 	}
1816 
1817 	/* now the rgctx trampolines: each specific trampolines puts in the ip register
1818 	 * the instruction pointer address, so the generic trampoline at the start of the page
1819 	 * subtracts 4096 to get to the data page and loads the values
1820 	 * We again fit the generic trampiline in 16 bytes.
1821 	 */
1822 	sprintf (symbol, "%srgctx_trampolines_page", acfg->user_symbol_prefix);
1823 	emit_global (acfg, symbol, TRUE);
1824 	emit_label (acfg, symbol);
1825 	code = buf;
1826 	imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
1827 	ARM_SUB_REG_IMM (code, ARMREG_IP, ARMREG_IP, imm8, rot_amount);
1828 	ARM_LDR_IMM (code, MONO_ARCH_RGCTX_REG, ARMREG_IP, -8);
1829 	ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, -4);
1830 	ARM_NOP (code);
1831 	g_assert (code - buf == COMMON_TRAMP_SIZE);
1832 
1833 	/* Emit it */
1834 	emit_bytes (acfg, buf, code - buf);
1835 
1836 	for (i = 0; i < count; ++i) {
1837 		code = buf;
1838 		ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_PC);
1839 		ARM_B (code, 0);
1840 		arm_patch (code - 4, code - COMMON_TRAMP_SIZE - 8 * (i + 1));
1841 		g_assert (code - buf == 8);
1842 		emit_bytes (acfg, buf, code - buf);
1843 	}
1844 
1845 	/*
1846 	 * gsharedvt arg trampolines: see arch_emit_gsharedvt_arg_trampoline ()
1847 	 */
1848 	sprintf (symbol, "%sgsharedvt_arg_trampolines_page", acfg->user_symbol_prefix);
1849 	emit_global (acfg, symbol, TRUE);
1850 	emit_label (acfg, symbol);
1851 	code = buf;
1852 	ARM_PUSH (code, (1 << ARMREG_R0) | (1 << ARMREG_R1) | (1 << ARMREG_R2) | (1 << ARMREG_R3));
1853 	imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
1854 	ARM_SUB_REG_IMM (code, ARMREG_IP, ARMREG_IP, imm8, rot_amount);
1855 	ARM_LDR_IMM (code, ARMREG_R0, ARMREG_IP, -8);
1856 	ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, -4);
1857 	g_assert (code - buf == COMMON_TRAMP_SIZE);
1858 	/* Emit it */
1859 	emit_bytes (acfg, buf, code - buf);
1860 
1861 	for (i = 0; i < count; ++i) {
1862 		code = buf;
1863 		ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_PC);
1864 		ARM_B (code, 0);
1865 		arm_patch (code - 4, code - COMMON_TRAMP_SIZE - 8 * (i + 1));
1866 		g_assert (code - buf == 8);
1867 		emit_bytes (acfg, buf, code - buf);
1868 	}
1869 
1870 	/* now the imt trampolines: each specific trampolines puts in the ip register
1871 	 * the instruction pointer address, so the generic trampoline at the start of the page
1872 	 * subtracts 4096 to get to the data page and loads the values
1873 	 */
1874 #define IMT_TRAMP_SIZE 72
1875 	sprintf (symbol, "%simt_trampolines_page", acfg->user_symbol_prefix);
1876 	emit_global (acfg, symbol, TRUE);
1877 	emit_label (acfg, symbol);
1878 	code = buf;
1879 	/* Need at least two free registers, plus a slot for storing the pc */
1880 	ARM_PUSH (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_R2));
1881 
1882 	imm8 = mono_arm_is_rotated_imm8 (pagesize, &rot_amount);
1883 	ARM_SUB_REG_IMM (code, ARMREG_IP, ARMREG_IP, imm8, rot_amount);
1884 	ARM_LDR_IMM (code, ARMREG_R0, ARMREG_IP, -8);
1885 
1886 	/* The IMT method is in v5, r0 has the imt array address */
1887 
1888 	loop_start = code;
1889 	ARM_LDR_IMM (code, ARMREG_R1, ARMREG_R0, 0);
1890 	ARM_CMP_REG_REG (code, ARMREG_R1, ARMREG_V5);
1891 	imt_found_check = code;
1892 	ARM_B_COND (code, ARMCOND_EQ, 0);
1893 
1894 	/* End-of-loop check */
1895 	ARM_CMP_REG_IMM (code, ARMREG_R1, 0, 0);
1896 	loop_end_check = code;
1897 	ARM_B_COND (code, ARMCOND_EQ, 0);
1898 
1899 	/* Loop footer */
1900 	ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (gpointer) * 2);
1901 	loop_branch_back = code;
1902 	ARM_B (code, 0);
1903 	arm_patch (loop_branch_back, loop_start);
1904 
1905 	/* Match */
1906 	arm_patch (imt_found_check, code);
1907 	ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 4);
1908 	ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 0);
1909 	/* Save it to the third stack slot */
1910 	ARM_STR_IMM (code, ARMREG_R0, ARMREG_SP, 8);
1911 	/* Restore the registers and branch */
1912 	ARM_POP (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_PC));
1913 
1914 	/* No match */
1915 	arm_patch (loop_end_check, code);
1916 	ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 4);
1917 	ARM_STR_IMM (code, ARMREG_R0, ARMREG_SP, 8);
1918 	ARM_POP (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_PC));
1919 	ARM_NOP (code);
1920 
1921 	/* Emit it */
1922 	g_assert (code - buf == IMT_TRAMP_SIZE);
1923 	emit_bytes (acfg, buf, code - buf);
1924 
1925 	for (i = 0; i < count; ++i) {
1926 		code = buf;
1927 		ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_PC);
1928 		ARM_B (code, 0);
1929 		arm_patch (code - 4, code - IMT_TRAMP_SIZE - 8 * (i + 1));
1930 		g_assert (code - buf == 8);
1931 		emit_bytes (acfg, buf, code - buf);
1932 	}
1933 
1934 	acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_SPECIFIC] = 16;
1935 	acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = 16;
1936 	acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT] = 72;
1937 	acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = 16;
1938 
1939 	/* Unwind info for specifc trampolines */
1940 	sprintf (symbol, "%sspecific_trampolines_page_gen_p", acfg->user_symbol_prefix);
1941 	/* We unwind to the original caller, from the stack, since lr is clobbered */
1942 	mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 14 * sizeof (mgreg_t));
1943 	mono_add_unwind_op_offset (unwind_ops, 0, 0, ARMREG_LR, -4);
1944 	save_unwind_info (acfg, symbol, unwind_ops);
1945 	mono_free_unwind_info (unwind_ops);
1946 
1947 	sprintf (symbol, "%sspecific_trampolines_page_sp_p", acfg->user_symbol_prefix);
1948 	mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
1949 	mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 14 * sizeof (mgreg_t));
1950 	save_unwind_info (acfg, symbol, unwind_ops);
1951 	mono_free_unwind_info (unwind_ops);
1952 
1953 	/* Unwind info for rgctx trampolines */
1954 	sprintf (symbol, "%srgctx_trampolines_page_gen_p", acfg->user_symbol_prefix);
1955 	mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
1956 	save_unwind_info (acfg, symbol, unwind_ops);
1957 
1958 	sprintf (symbol, "%srgctx_trampolines_page_sp_p", acfg->user_symbol_prefix);
1959 	save_unwind_info (acfg, symbol, unwind_ops);
1960 	mono_free_unwind_info (unwind_ops);
1961 
1962 	/* Unwind info for gsharedvt trampolines */
1963 	sprintf (symbol, "%sgsharedvt_trampolines_page_gen_p", acfg->user_symbol_prefix);
1964 	mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
1965 	mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 4 * sizeof (mgreg_t));
1966 	save_unwind_info (acfg, symbol, unwind_ops);
1967 	mono_free_unwind_info (unwind_ops);
1968 
1969 	sprintf (symbol, "%sgsharedvt_trampolines_page_sp_p", acfg->user_symbol_prefix);
1970 	mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
1971 	save_unwind_info (acfg, symbol, unwind_ops);
1972 	mono_free_unwind_info (unwind_ops);
1973 
1974 	/* Unwind info for imt trampolines */
1975 	sprintf (symbol, "%simt_trampolines_page_gen_p", acfg->user_symbol_prefix);
1976 	mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
1977 	mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 3 * sizeof (mgreg_t));
1978 	save_unwind_info (acfg, symbol, unwind_ops);
1979 	mono_free_unwind_info (unwind_ops);
1980 
1981 	sprintf (symbol, "%simt_trampolines_page_sp_p", acfg->user_symbol_prefix);
1982 	mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
1983 	save_unwind_info (acfg, symbol, unwind_ops);
1984 	mono_free_unwind_info (unwind_ops);
1985 #elif defined(TARGET_ARM64)
1986 	arm64_emit_specific_trampoline_pages (acfg);
1987 #endif
1988 }
1989 
1990 /*
1991  * arch_emit_specific_trampoline:
1992  *
1993  *   Emit code for a specific trampoline. OFFSET is the offset of the first of
1994  * two GOT slots which contain the generic trampoline address and the trampoline
1995  * argument. TRAMP_SIZE is set to the size of the emitted trampoline.
1996  */
1997 static void
arch_emit_specific_trampoline(MonoAotCompile * acfg,int offset,int * tramp_size)1998 arch_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
1999 {
2000 	/*
2001 	 * The trampolines created here are variations of the specific
2002 	 * trampolines created in mono_arch_create_specific_trampoline (). The
2003 	 * differences are:
2004 	 * - the generic trampoline address is taken from a got slot.
2005 	 * - the offset of the got slot where the trampoline argument is stored
2006 	 *   is embedded in the instruction stream, and the generic trampoline
2007 	 *   can load the argument by loading the offset, adding it to the
2008 	 *   address of the trampoline to get the address of the got slot, and
2009 	 *   loading the argument from there.
2010 	 * - all the trampolines should be of the same length.
2011 	 */
2012 #if defined(TARGET_AMD64)
2013 	/* This should be exactly 8 bytes long */
2014 	*tramp_size = 8;
2015 	/* call *<offset>(%rip) */
2016 	if (acfg->llvm) {
2017 		emit_unset_mode (acfg);
2018 		fprintf (acfg->fp, "call *%s+%d(%%rip)\n", acfg->got_symbol, (int)(offset * sizeof (gpointer)));
2019 		emit_zero_bytes (acfg, 2);
2020 	} else {
2021 		emit_byte (acfg, '\x41');
2022 		emit_byte (acfg, '\xff');
2023 		emit_byte (acfg, '\x15');
2024 		emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) - 4);
2025 		emit_zero_bytes (acfg, 1);
2026 	}
2027 #elif defined(TARGET_ARM)
2028 	guint8 buf [128];
2029 	guint8 *code;
2030 
2031 	/* This should be exactly 20 bytes long */
2032 	*tramp_size = 20;
2033 	code = buf;
2034 	ARM_PUSH (code, 0x5fff);
2035 	ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 4);
2036 	/* Load the value from the GOT */
2037 	ARM_LDR_REG_REG (code, ARMREG_R1, ARMREG_PC, ARMREG_R1);
2038 	/* Branch to it */
2039 	ARM_BLX_REG (code, ARMREG_R1);
2040 
2041 	g_assert (code - buf == 16);
2042 
2043 	/* Emit it */
2044 	emit_bytes (acfg, buf, code - buf);
2045 	/*
2046 	 * Only one offset is needed, since the second one would be equal to the
2047 	 * first one.
2048 	 */
2049 	emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) - 4 + 4);
2050 	//emit_symbol_diff (acfg, acfg->got_symbol, ".", ((offset + 1) * sizeof (gpointer)) - 4 + 8);
2051 #elif defined(TARGET_ARM64)
2052 	arm64_emit_specific_trampoline (acfg, offset, tramp_size);
2053 #elif defined(TARGET_POWERPC)
2054 	guint8 buf [128];
2055 	guint8 *code;
2056 
2057 	*tramp_size = 4;
2058 	code = buf;
2059 
2060 	/*
2061 	 * PPC has no ip relative addressing, so we need to compute the address
2062 	 * of the mscorlib got. That is slow and complex, so instead, we store it
2063 	 * in the second got slot of every aot image. The caller already computed
2064 	 * the address of its got and placed it into r30.
2065 	 */
2066 	emit_unset_mode (acfg);
2067 	/* Load mscorlib got address */
2068 	fprintf (acfg->fp, "%s 0, %d(30)\n", PPC_LD_OP, (int)sizeof (gpointer));
2069 	/* Load generic trampoline address */
2070 	fprintf (acfg->fp, "lis 11, %d@h\n", (int)(offset * sizeof (gpointer)));
2071 	fprintf (acfg->fp, "ori 11, 11, %d@l\n", (int)(offset * sizeof (gpointer)));
2072 	fprintf (acfg->fp, "%s 11, 11, 0\n", PPC_LDX_OP);
2073 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
2074 	fprintf (acfg->fp, "%s 11, 0(11)\n", PPC_LD_OP);
2075 #endif
2076 	fprintf (acfg->fp, "mtctr 11\n");
2077 	/* Load trampoline argument */
2078 	/* On ppc, we pass it normally to the generic trampoline */
2079 	fprintf (acfg->fp, "lis 11, %d@h\n", (int)((offset + 1) * sizeof (gpointer)));
2080 	fprintf (acfg->fp, "ori 11, 11, %d@l\n", (int)((offset + 1) * sizeof (gpointer)));
2081 	fprintf (acfg->fp, "%s 0, 11, 0\n", PPC_LDX_OP);
2082 	/* Branch to generic trampoline */
2083 	fprintf (acfg->fp, "bctr\n");
2084 
2085 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
2086 	*tramp_size = 10 * 4;
2087 #else
2088 	*tramp_size = 9 * 4;
2089 #endif
2090 #elif defined(TARGET_X86)
2091 	guint8 buf [128];
2092 	guint8 *code;
2093 
2094 	/* Similar to the PPC code above */
2095 
2096 	/* FIXME: Could this clobber the register needed by get_vcall_slot () ? */
2097 
2098 	code = buf;
2099 	/* Load mscorlib got address */
2100 	x86_mov_reg_membase (code, X86_ECX, MONO_ARCH_GOT_REG, sizeof (gpointer), 4);
2101 	/* Push trampoline argument */
2102 	x86_push_membase (code, X86_ECX, (offset + 1) * sizeof (gpointer));
2103 	/* Load generic trampoline address */
2104 	x86_mov_reg_membase (code, X86_ECX, X86_ECX, offset * sizeof (gpointer), 4);
2105 	/* Branch to generic trampoline */
2106 	x86_jump_reg (code, X86_ECX);
2107 
2108 	emit_bytes (acfg, buf, code - buf);
2109 
2110 	*tramp_size = 17;
2111 	g_assert (code - buf == *tramp_size);
2112 #else
2113 	g_assert_not_reached ();
2114 #endif
2115 }
2116 
2117 /*
2118  * arch_emit_unbox_trampoline:
2119  *
2120  *   Emit code for the unbox trampoline for METHOD used in the full-aot case.
2121  * CALL_TARGET is the symbol pointing to the native code of METHOD.
2122  */
2123 static void
arch_emit_unbox_trampoline(MonoAotCompile * acfg,MonoCompile * cfg,MonoMethod * method,const char * call_target)2124 arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoCompile *cfg, MonoMethod *method, const char *call_target)
2125 {
2126 #if defined(TARGET_AMD64)
2127 	guint8 buf [32];
2128 	guint8 *code;
2129 	int this_reg;
2130 
2131 	this_reg = mono_arch_get_this_arg_reg (NULL);
2132 	code = buf;
2133 	amd64_alu_reg_imm (code, X86_ADD, this_reg, sizeof (MonoObject));
2134 
2135 	emit_bytes (acfg, buf, code - buf);
2136 	/* jump <method> */
2137 	if (acfg->llvm) {
2138 		emit_unset_mode (acfg);
2139 		fprintf (acfg->fp, "jmp %s\n", call_target);
2140 	} else {
2141 		emit_byte (acfg, '\xe9');
2142 		emit_symbol_diff (acfg, call_target, ".", -4);
2143 	}
2144 #elif defined(TARGET_X86)
2145 	guint8 buf [32];
2146 	guint8 *code;
2147 	int this_pos = 4;
2148 
2149 	code = buf;
2150 
2151 	x86_alu_membase_imm (code, X86_ADD, X86_ESP, this_pos, sizeof (MonoObject));
2152 
2153 	emit_bytes (acfg, buf, code - buf);
2154 
2155 	/* jump <method> */
2156 	emit_byte (acfg, '\xe9');
2157 	emit_symbol_diff (acfg, call_target, ".", -4);
2158 #elif defined(TARGET_ARM)
2159 	guint8 buf [128];
2160 	guint8 *code;
2161 
2162 	if (acfg->thumb_mixed && cfg->compile_llvm) {
2163 		fprintf (acfg->fp, "add r0, r0, #%d\n", (int)sizeof (MonoObject));
2164 		fprintf (acfg->fp, "b %s\n", call_target);
2165 		fprintf (acfg->fp, ".arm\n");
2166 		fprintf (acfg->fp, ".align 2\n");
2167 		return;
2168 	}
2169 
2170 	code = buf;
2171 
2172 	ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (MonoObject));
2173 
2174 	emit_bytes (acfg, buf, code - buf);
2175 	/* jump to method */
2176 	if (acfg->thumb_mixed && cfg->compile_llvm)
2177 		fprintf (acfg->fp, "\n\tbx %s\n", call_target);
2178 	else
2179 		fprintf (acfg->fp, "\n\tb %s\n", call_target);
2180 #elif defined(TARGET_ARM64)
2181 	arm64_emit_unbox_trampoline (acfg, cfg, method, call_target);
2182 #elif defined(TARGET_POWERPC)
2183 	int this_pos = 3;
2184 
2185 	fprintf (acfg->fp, "\n\taddi %d, %d, %d\n", this_pos, this_pos, (int)sizeof (MonoObject));
2186 	fprintf (acfg->fp, "\n\tb %s\n", call_target);
2187 #else
2188 	g_assert_not_reached ();
2189 #endif
2190 }
2191 
2192 /*
2193  * arch_emit_static_rgctx_trampoline:
2194  *
2195  *   Emit code for a static rgctx trampoline. OFFSET is the offset of the first of
2196  * two GOT slots which contain the rgctx argument, and the method to jump to.
2197  * TRAMP_SIZE is set to the size of the emitted trampoline.
2198  * These kinds of trampolines cannot be enumerated statically, since there could
2199  * be one trampoline per method instantiation, so we emit the same code for all
2200  * trampolines, and parameterize them using two GOT slots.
2201  */
2202 static void
arch_emit_static_rgctx_trampoline(MonoAotCompile * acfg,int offset,int * tramp_size)2203 arch_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
2204 {
2205 #if defined(TARGET_AMD64)
2206 	/* This should be exactly 13 bytes long */
2207 	*tramp_size = 13;
2208 
2209 	if (acfg->llvm) {
2210 		emit_unset_mode (acfg);
2211 		fprintf (acfg->fp, "mov %s+%d(%%rip), %%r10\n", acfg->got_symbol, (int)(offset * sizeof (gpointer)));
2212 		fprintf (acfg->fp, "jmp *%s+%d(%%rip)\n", acfg->got_symbol, (int)((offset + 1) * sizeof (gpointer)));
2213 	} else {
2214 		/* mov <OFFSET>(%rip), %r10 */
2215 		emit_byte (acfg, '\x4d');
2216 		emit_byte (acfg, '\x8b');
2217 		emit_byte (acfg, '\x15');
2218 		emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) - 4);
2219 
2220 		/* jmp *<offset>(%rip) */
2221 		emit_byte (acfg, '\xff');
2222 		emit_byte (acfg, '\x25');
2223 		emit_symbol_diff (acfg, acfg->got_symbol, ".", ((offset + 1) * sizeof (gpointer)) - 4);
2224 	}
2225 #elif defined(TARGET_ARM)
2226 	guint8 buf [128];
2227 	guint8 *code;
2228 
2229 	/* This should be exactly 24 bytes long */
2230 	*tramp_size = 24;
2231 	code = buf;
2232 	/* Load rgctx value */
2233 	ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 8);
2234 	ARM_LDR_REG_REG (code, MONO_ARCH_RGCTX_REG, ARMREG_PC, ARMREG_IP);
2235 	/* Load branch addr + branch */
2236 	ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 4);
2237 	ARM_LDR_REG_REG (code, ARMREG_PC, ARMREG_PC, ARMREG_IP);
2238 
2239 	g_assert (code - buf == 16);
2240 
2241 	/* Emit it */
2242 	emit_bytes (acfg, buf, code - buf);
2243 	emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) - 4 + 8);
2244 	emit_symbol_diff (acfg, acfg->got_symbol, ".", ((offset + 1) * sizeof (gpointer)) - 4 + 4);
2245 #elif defined(TARGET_ARM64)
2246 	arm64_emit_static_rgctx_trampoline (acfg, offset, tramp_size);
2247 #elif defined(TARGET_POWERPC)
2248 	guint8 buf [128];
2249 	guint8 *code;
2250 
2251 	*tramp_size = 4;
2252 	code = buf;
2253 
2254 	/*
2255 	 * PPC has no ip relative addressing, so we need to compute the address
2256 	 * of the mscorlib got. That is slow and complex, so instead, we store it
2257 	 * in the second got slot of every aot image. The caller already computed
2258 	 * the address of its got and placed it into r30.
2259 	 */
2260 	emit_unset_mode (acfg);
2261 	/* Load mscorlib got address */
2262 	fprintf (acfg->fp, "%s 0, %d(30)\n", PPC_LD_OP, (int)sizeof (gpointer));
2263 	/* Load rgctx */
2264 	fprintf (acfg->fp, "lis 11, %d@h\n", (int)(offset * sizeof (gpointer)));
2265 	fprintf (acfg->fp, "ori 11, 11, %d@l\n", (int)(offset * sizeof (gpointer)));
2266 	fprintf (acfg->fp, "%s %d, 11, 0\n", PPC_LDX_OP, MONO_ARCH_RGCTX_REG);
2267 	/* Load target address */
2268 	fprintf (acfg->fp, "lis 11, %d@h\n", (int)((offset + 1) * sizeof (gpointer)));
2269 	fprintf (acfg->fp, "ori 11, 11, %d@l\n", (int)((offset + 1) * sizeof (gpointer)));
2270 	fprintf (acfg->fp, "%s 11, 11, 0\n", PPC_LDX_OP);
2271 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
2272 	fprintf (acfg->fp, "%s 2, %d(11)\n", PPC_LD_OP, (int)sizeof (gpointer));
2273 	fprintf (acfg->fp, "%s 11, 0(11)\n", PPC_LD_OP);
2274 #endif
2275 	fprintf (acfg->fp, "mtctr 11\n");
2276 	/* Branch to the target address */
2277 	fprintf (acfg->fp, "bctr\n");
2278 
2279 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
2280 	*tramp_size = 11 * 4;
2281 #else
2282 	*tramp_size = 9 * 4;
2283 #endif
2284 
2285 #elif defined(TARGET_X86)
2286 	guint8 buf [128];
2287 	guint8 *code;
2288 
2289 	/* Similar to the PPC code above */
2290 
2291 	g_assert (MONO_ARCH_RGCTX_REG != X86_ECX);
2292 
2293 	code = buf;
2294 	/* Load mscorlib got address */
2295 	x86_mov_reg_membase (code, X86_ECX, MONO_ARCH_GOT_REG, sizeof (gpointer), 4);
2296 	/* Load arg */
2297 	x86_mov_reg_membase (code, MONO_ARCH_RGCTX_REG, X86_ECX, offset * sizeof (gpointer), 4);
2298 	/* Branch to the target address */
2299 	x86_jump_membase (code, X86_ECX, (offset + 1) * sizeof (gpointer));
2300 
2301 	emit_bytes (acfg, buf, code - buf);
2302 
2303 	*tramp_size = 15;
2304 	g_assert (code - buf == *tramp_size);
2305 #else
2306 	g_assert_not_reached ();
2307 #endif
2308 }
2309 
2310 /*
2311  * arch_emit_imt_trampoline:
2312  *
2313  *   Emit an IMT trampoline usable in full-aot mode. The trampoline uses 1 got slot which
2314  * points to an array of pointer pairs. The pairs of the form [key, ptr], where
2315  * key is the IMT key, and ptr holds the address of a memory location holding
2316  * the address to branch to if the IMT arg matches the key. The array is
2317  * terminated by a pair whose key is NULL, and whose ptr is the address of the
2318  * fail_tramp.
2319  * TRAMP_SIZE is set to the size of the emitted trampoline.
2320  */
2321 static void
arch_emit_imt_trampoline(MonoAotCompile * acfg,int offset,int * tramp_size)2322 arch_emit_imt_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
2323 {
2324 #if defined(TARGET_AMD64)
2325 	guint8 *buf, *code;
2326 	guint8 *labels [16];
2327 	guint8 mov_buf[3];
2328 	guint8 *mov_buf_ptr = mov_buf;
2329 
2330 	const int kSizeOfMove = 7;
2331 
2332 	code = buf = (guint8 *)g_malloc (256);
2333 
2334 	/* FIXME: Optimize this, i.e. use binary search etc. */
2335 	/* Maybe move the body into a separate function (slower, but much smaller) */
2336 
2337 	/* MONO_ARCH_IMT_SCRATCH_REG is a free register */
2338 
2339 	if (acfg->llvm) {
2340 		emit_unset_mode (acfg);
2341 		fprintf (acfg->fp, "mov %s+%d(%%rip), %s\n", acfg->got_symbol, (int)(offset * sizeof (gpointer)), mono_arch_regname (MONO_ARCH_IMT_SCRATCH_REG));
2342 	}
2343 
2344 	labels [0] = code;
2345 	amd64_alu_membase_imm (code, X86_CMP, MONO_ARCH_IMT_SCRATCH_REG, 0, 0);
2346 	labels [1] = code;
2347 	amd64_branch8 (code, X86_CC_Z, 0, FALSE);
2348 
2349 	/* Check key */
2350 	amd64_alu_membase_reg_size (code, X86_CMP, MONO_ARCH_IMT_SCRATCH_REG, 0, MONO_ARCH_IMT_REG, sizeof (gpointer));
2351 	labels [2] = code;
2352 	amd64_branch8 (code, X86_CC_Z, 0, FALSE);
2353 
2354 	/* Loop footer */
2355 	amd64_alu_reg_imm (code, X86_ADD, MONO_ARCH_IMT_SCRATCH_REG, 2 * sizeof (gpointer));
2356 	amd64_jump_code (code, labels [0]);
2357 
2358 	/* Match */
2359 	mono_amd64_patch (labels [2], code);
2360 	amd64_mov_reg_membase (code, MONO_ARCH_IMT_SCRATCH_REG, MONO_ARCH_IMT_SCRATCH_REG, sizeof (gpointer), sizeof (gpointer));
2361 	amd64_jump_membase (code, MONO_ARCH_IMT_SCRATCH_REG, 0);
2362 
2363 	/* No match */
2364 	mono_amd64_patch (labels [1], code);
2365 	/* Load fail tramp */
2366 	amd64_alu_reg_imm (code, X86_ADD, MONO_ARCH_IMT_SCRATCH_REG, sizeof (gpointer));
2367 	/* Check if there is a fail tramp */
2368 	amd64_alu_membase_imm (code, X86_CMP, MONO_ARCH_IMT_SCRATCH_REG, 0, 0);
2369 	labels [3] = code;
2370 	amd64_branch8 (code, X86_CC_Z, 0, FALSE);
2371 	/* Jump to fail tramp */
2372 	amd64_jump_membase (code, MONO_ARCH_IMT_SCRATCH_REG, 0);
2373 
2374 	/* Fail */
2375 	mono_amd64_patch (labels [3], code);
2376 	x86_breakpoint (code);
2377 
2378 	if (!acfg->llvm) {
2379 		/* mov <OFFSET>(%rip), MONO_ARCH_IMT_SCRATCH_REG */
2380 		amd64_emit_rex (mov_buf_ptr, sizeof(gpointer), MONO_ARCH_IMT_SCRATCH_REG, 0, AMD64_RIP);
2381 		*(mov_buf_ptr)++ = (unsigned char)0x8b; /* mov opcode */
2382 		x86_address_byte (mov_buf_ptr, 0, MONO_ARCH_IMT_SCRATCH_REG & 0x7, 5);
2383 		emit_bytes (acfg, mov_buf, mov_buf_ptr - mov_buf);
2384 		emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) - 4);
2385 	}
2386 	emit_bytes (acfg, buf, code - buf);
2387 
2388 	*tramp_size = code - buf + kSizeOfMove;
2389 
2390 	g_free (buf);
2391 
2392 #elif defined(TARGET_X86)
2393 	guint8 *buf, *code;
2394 	guint8 *labels [16];
2395 
2396 	code = buf = g_malloc (256);
2397 
2398 	/* Allocate a temporary stack slot */
2399 	x86_push_reg (code, X86_EAX);
2400 	/* Save EAX */
2401 	x86_push_reg (code, X86_EAX);
2402 
2403 	/* Load mscorlib got address */
2404 	x86_mov_reg_membase (code, X86_EAX, MONO_ARCH_GOT_REG, sizeof (gpointer), 4);
2405 	/* Load arg */
2406 	x86_mov_reg_membase (code, X86_EAX, X86_EAX, offset * sizeof (gpointer), 4);
2407 
2408 	labels [0] = code;
2409 	x86_alu_membase_imm (code, X86_CMP, X86_EAX, 0, 0);
2410 	labels [1] = code;
2411 	x86_branch8 (code, X86_CC_Z, FALSE, 0);
2412 
2413 	/* Check key */
2414 	x86_alu_membase_reg (code, X86_CMP, X86_EAX, 0, MONO_ARCH_IMT_REG);
2415 	labels [2] = code;
2416 	x86_branch8 (code, X86_CC_Z, FALSE, 0);
2417 
2418 	/* Loop footer */
2419 	x86_alu_reg_imm (code, X86_ADD, X86_EAX, 2 * sizeof (gpointer));
2420 	x86_jump_code (code, labels [0]);
2421 
2422 	/* Match */
2423 	mono_x86_patch (labels [2], code);
2424 	x86_mov_reg_membase (code, X86_EAX, X86_EAX, sizeof (gpointer), 4);
2425 	x86_mov_reg_membase (code, X86_EAX, X86_EAX, 0, 4);
2426 	/* Save the target address to the temporary stack location */
2427 	x86_mov_membase_reg (code, X86_ESP, 4, X86_EAX, 4);
2428 	/* Restore EAX */
2429 	x86_pop_reg (code, X86_EAX);
2430 	/* Jump to the target address */
2431 	x86_ret (code);
2432 
2433 	/* No match */
2434 	mono_x86_patch (labels [1], code);
2435 	/* Load fail tramp */
2436 	x86_mov_reg_membase (code, X86_EAX, X86_EAX, sizeof (gpointer), 4);
2437 	x86_alu_membase_imm (code, X86_CMP, X86_EAX, 0, 0);
2438 	labels [3] = code;
2439 	x86_branch8 (code, X86_CC_Z, FALSE, 0);
2440 	/* Jump to fail tramp */
2441 	x86_mov_membase_reg (code, X86_ESP, 4, X86_EAX, 4);
2442 	x86_pop_reg (code, X86_EAX);
2443 	x86_ret (code);
2444 
2445 	/* Fail */
2446 	mono_x86_patch (labels [3], code);
2447 	x86_breakpoint (code);
2448 
2449 	emit_bytes (acfg, buf, code - buf);
2450 
2451 	*tramp_size = code - buf;
2452 
2453 	g_free (buf);
2454 
2455 #elif defined(TARGET_ARM)
2456 	guint8 buf [128];
2457 	guint8 *code, *code2, *labels [16];
2458 
2459 	code = buf;
2460 
2461 	/* The IMT method is in v5 */
2462 
2463 	/* Need at least two free registers, plus a slot for storing the pc */
2464 	ARM_PUSH (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_R2));
2465 	labels [0] = code;
2466 	/* Load the parameter from the GOT */
2467 	ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0);
2468 	ARM_LDR_REG_REG (code, ARMREG_R0, ARMREG_PC, ARMREG_R0);
2469 
2470 	labels [1] = code;
2471 	ARM_LDR_IMM (code, ARMREG_R1, ARMREG_R0, 0);
2472 	ARM_CMP_REG_REG (code, ARMREG_R1, ARMREG_V5);
2473 	labels [2] = code;
2474 	ARM_B_COND (code, ARMCOND_EQ, 0);
2475 
2476 	/* End-of-loop check */
2477 	ARM_CMP_REG_IMM (code, ARMREG_R1, 0, 0);
2478 	labels [3] = code;
2479 	ARM_B_COND (code, ARMCOND_EQ, 0);
2480 
2481 	/* Loop footer */
2482 	ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (gpointer) * 2);
2483 	labels [4] = code;
2484 	ARM_B (code, 0);
2485 	arm_patch (labels [4], labels [1]);
2486 
2487 	/* Match */
2488 	arm_patch (labels [2], code);
2489 	ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 4);
2490 	ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 0);
2491 	/* Save it to the third stack slot */
2492 	ARM_STR_IMM (code, ARMREG_R0, ARMREG_SP, 8);
2493 	/* Restore the registers and branch */
2494 	ARM_POP (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_PC));
2495 
2496 	/* No match */
2497 	arm_patch (labels [3], code);
2498 	ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 4);
2499 	ARM_STR_IMM (code, ARMREG_R0, ARMREG_SP, 8);
2500 	ARM_POP (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_PC));
2501 
2502 	/* Fixup offset */
2503 	code2 = labels [0];
2504 	ARM_LDR_IMM (code2, ARMREG_R0, ARMREG_PC, (code - (labels [0] + 8)));
2505 
2506 	emit_bytes (acfg, buf, code - buf);
2507 	emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) + (code - (labels [0] + 8)) - 4);
2508 
2509 	*tramp_size = code - buf + 4;
2510 #elif defined(TARGET_ARM64)
2511 	arm64_emit_imt_trampoline (acfg, offset, tramp_size);
2512 #elif defined(TARGET_POWERPC)
2513 	guint8 buf [128];
2514 	guint8 *code, *labels [16];
2515 
2516 	code = buf;
2517 
2518 	/* Load the mscorlib got address */
2519 	ppc_ldptr (code, ppc_r12, sizeof (gpointer), ppc_r30);
2520 	/* Load the parameter from the GOT */
2521 	ppc_load (code, ppc_r0, offset * sizeof (gpointer));
2522 	ppc_ldptr_indexed (code, ppc_r12, ppc_r12, ppc_r0);
2523 
2524 	/* Load and check key */
2525 	labels [1] = code;
2526 	ppc_ldptr (code, ppc_r0, 0, ppc_r12);
2527 	ppc_cmp (code, 0, sizeof (gpointer) == 8 ? 1 : 0, ppc_r0, MONO_ARCH_IMT_REG);
2528 	labels [2] = code;
2529 	ppc_bc (code, PPC_BR_TRUE, PPC_BR_EQ, 0);
2530 
2531 	/* End-of-loop check */
2532 	ppc_cmpi (code, 0, sizeof (gpointer) == 8 ? 1 : 0, ppc_r0, 0);
2533 	labels [3] = code;
2534 	ppc_bc (code, PPC_BR_TRUE, PPC_BR_EQ, 0);
2535 
2536 	/* Loop footer */
2537 	ppc_addi (code, ppc_r12, ppc_r12, 2 * sizeof (gpointer));
2538 	labels [4] = code;
2539 	ppc_b (code, 0);
2540 	mono_ppc_patch (labels [4], labels [1]);
2541 
2542 	/* Match */
2543 	mono_ppc_patch (labels [2], code);
2544 	ppc_ldptr (code, ppc_r12, sizeof (gpointer), ppc_r12);
2545 	/* r12 now contains the value of the vtable slot */
2546 	/* this is not a function descriptor on ppc64 */
2547 	ppc_ldptr (code, ppc_r12, 0, ppc_r12);
2548 	ppc_mtctr (code, ppc_r12);
2549 	ppc_bcctr (code, PPC_BR_ALWAYS, 0);
2550 
2551 	/* Fail */
2552 	mono_ppc_patch (labels [3], code);
2553 	/* FIXME: */
2554 	ppc_break (code);
2555 
2556 	*tramp_size = code - buf;
2557 
2558 	emit_bytes (acfg, buf, code - buf);
2559 #else
2560 	g_assert_not_reached ();
2561 #endif
2562 }
2563 
2564 
2565 #if defined (TARGET_AMD64)
2566 
2567 static void
amd64_emit_load_got_slot(MonoAotCompile * acfg,int dreg,int got_slot)2568 amd64_emit_load_got_slot (MonoAotCompile *acfg, int dreg, int got_slot)
2569 {
2570 
2571 	g_assert (acfg->fp);
2572 	emit_unset_mode (acfg);
2573 
2574 	fprintf (acfg->fp, "mov %s+%d(%%rip), %s\n", acfg->got_symbol, (unsigned int) ((got_slot * sizeof (gpointer))), mono_arch_regname (dreg));
2575 }
2576 
2577 #endif
2578 
2579 
2580 /*
2581  * arch_emit_gsharedvt_arg_trampoline:
2582  *
2583  *   Emit code for a gsharedvt arg trampoline. OFFSET is the offset of the first of
2584  * two GOT slots which contain the argument, and the code to jump to.
2585  * TRAMP_SIZE is set to the size of the emitted trampoline.
2586  * These kinds of trampolines cannot be enumerated statically, since there could
2587  * be one trampoline per method instantiation, so we emit the same code for all
2588  * trampolines, and parameterize them using two GOT slots.
2589  */
2590 static void
arch_emit_gsharedvt_arg_trampoline(MonoAotCompile * acfg,int offset,int * tramp_size)2591 arch_emit_gsharedvt_arg_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
2592 {
2593 #if defined(TARGET_X86)
2594 	guint8 buf [128];
2595 	guint8 *code;
2596 
2597 	/* Similar to the PPC code above */
2598 
2599 	g_assert (MONO_ARCH_RGCTX_REG != X86_ECX);
2600 
2601 	code = buf;
2602 	/* Load mscorlib got address */
2603 	x86_mov_reg_membase (code, X86_ECX, MONO_ARCH_GOT_REG, sizeof (gpointer), 4);
2604 	/* Load arg */
2605 	x86_mov_reg_membase (code, X86_EAX, X86_ECX, offset * sizeof (gpointer), 4);
2606 	/* Branch to the target address */
2607 	x86_jump_membase (code, X86_ECX, (offset + 1) * sizeof (gpointer));
2608 
2609 	emit_bytes (acfg, buf, code - buf);
2610 
2611 	*tramp_size = 15;
2612 	g_assert (code - buf == *tramp_size);
2613 #elif defined(TARGET_ARM)
2614 	guint8 buf [128];
2615 	guint8 *code;
2616 
2617 	/* The same as mono_arch_get_gsharedvt_arg_trampoline (), but for AOT */
2618 	/* Similar to arch_emit_specific_trampoline () */
2619 	*tramp_size = 24;
2620 	code = buf;
2621 	ARM_PUSH (code, (1 << ARMREG_R0) | (1 << ARMREG_R1) | (1 << ARMREG_R2) | (1 << ARMREG_R3));
2622 	ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 8);
2623 	/* Load the arg value from the GOT */
2624 	ARM_LDR_REG_REG (code, ARMREG_R0, ARMREG_PC, ARMREG_R1);
2625 	/* Load the addr from the GOT */
2626 	ARM_LDR_REG_REG (code, ARMREG_R1, ARMREG_PC, ARMREG_R1);
2627 	/* Branch to it */
2628 	ARM_BX (code, ARMREG_R1);
2629 
2630 	g_assert (code - buf == 20);
2631 
2632 	/* Emit it */
2633 	emit_bytes (acfg, buf, code - buf);
2634 	emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) + 4);
2635 #elif defined(TARGET_ARM64)
2636 	arm64_emit_gsharedvt_arg_trampoline (acfg, offset, tramp_size);
2637 #elif defined (TARGET_AMD64)
2638 
2639 	amd64_emit_load_got_slot (acfg, AMD64_RAX, offset);
2640 	amd64_emit_load_got_slot (acfg, MONO_ARCH_IMT_SCRATCH_REG, offset + 1);
2641 	g_assert (AMD64_R11 == MONO_ARCH_IMT_SCRATCH_REG);
2642 	fprintf (acfg->fp, "jmp *%%r11\n");
2643 
2644 	*tramp_size = 0x11;
2645 #else
2646 	g_assert_not_reached ();
2647 #endif
2648 }
2649 
2650 /* END OF ARCH SPECIFIC CODE */
2651 
2652 static guint32
mono_get_field_token(MonoClassField * field)2653 mono_get_field_token (MonoClassField *field)
2654 {
2655 	MonoClass *klass = field->parent;
2656 	int i;
2657 
2658 	int fcount = mono_class_get_field_count (klass);
2659 	for (i = 0; i < fcount; ++i) {
2660 		if (field == &klass->fields [i])
2661 			return MONO_TOKEN_FIELD_DEF | (mono_class_get_first_field_idx (klass) + 1 + i);
2662 	}
2663 
2664 	g_assert_not_reached ();
2665 	return 0;
2666 }
2667 
2668 static inline void
encode_value(gint32 value,guint8 * buf,guint8 ** endbuf)2669 encode_value (gint32 value, guint8 *buf, guint8 **endbuf)
2670 {
2671 	guint8 *p = buf;
2672 
2673 	//printf ("ENCODE: %d 0x%x.\n", value, value);
2674 
2675 	/*
2676 	 * Same encoding as the one used in the metadata, extended to handle values
2677 	 * greater than 0x1fffffff.
2678 	 */
2679 	if ((value >= 0) && (value <= 127))
2680 		*p++ = value;
2681 	else if ((value >= 0) && (value <= 16383)) {
2682 		p [0] = 0x80 | (value >> 8);
2683 		p [1] = value & 0xff;
2684 		p += 2;
2685 	} else if ((value >= 0) && (value <= 0x1fffffff)) {
2686 		p [0] = (value >> 24) | 0xc0;
2687 		p [1] = (value >> 16) & 0xff;
2688 		p [2] = (value >> 8) & 0xff;
2689 		p [3] = value & 0xff;
2690 		p += 4;
2691 	}
2692 	else {
2693 		p [0] = 0xff;
2694 		p [1] = (value >> 24) & 0xff;
2695 		p [2] = (value >> 16) & 0xff;
2696 		p [3] = (value >> 8) & 0xff;
2697 		p [4] = value & 0xff;
2698 		p += 5;
2699 	}
2700 	if (endbuf)
2701 		*endbuf = p;
2702 }
2703 
2704 static void
stream_init(MonoDynamicStream * sh)2705 stream_init (MonoDynamicStream *sh)
2706 {
2707 	sh->index = 0;
2708 	sh->alloc_size = 4096;
2709 	sh->data = (char *)g_malloc (4096);
2710 
2711 	/* So offsets are > 0 */
2712 	sh->data [0] = 0;
2713 	sh->index ++;
2714 }
2715 
2716 static void
make_room_in_stream(MonoDynamicStream * stream,int size)2717 make_room_in_stream (MonoDynamicStream *stream, int size)
2718 {
2719 	if (size <= stream->alloc_size)
2720 		return;
2721 
2722 	while (stream->alloc_size <= size) {
2723 		if (stream->alloc_size < 4096)
2724 			stream->alloc_size = 4096;
2725 		else
2726 			stream->alloc_size *= 2;
2727 	}
2728 
2729 	stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
2730 }
2731 
2732 static guint32
add_stream_data(MonoDynamicStream * stream,const char * data,guint32 len)2733 add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
2734 {
2735 	guint32 idx;
2736 
2737 	make_room_in_stream (stream, stream->index + len);
2738 	memcpy (stream->data + stream->index, data, len);
2739 	idx = stream->index;
2740 	stream->index += len;
2741 	return idx;
2742 }
2743 
2744 /*
2745  * add_to_blob:
2746  *
2747  *   Add data to the binary blob inside the aot image. Returns the offset inside the
2748  * blob where the data was stored.
2749  */
2750 static guint32
add_to_blob(MonoAotCompile * acfg,const guint8 * data,guint32 data_len)2751 add_to_blob (MonoAotCompile *acfg, const guint8 *data, guint32 data_len)
2752 {
2753 	g_assert (!acfg->blob_closed);
2754 
2755 	if (acfg->blob.alloc_size == 0)
2756 		stream_init (&acfg->blob);
2757 
2758 	return add_stream_data (&acfg->blob, (char*)data, data_len);
2759 }
2760 
2761 static guint32
add_to_blob_aligned(MonoAotCompile * acfg,const guint8 * data,guint32 data_len,guint32 align)2762 add_to_blob_aligned (MonoAotCompile *acfg, const guint8 *data, guint32 data_len, guint32 align)
2763 {
2764 	char buf [4] = {0};
2765 	guint32 count;
2766 
2767 	if (acfg->blob.alloc_size == 0)
2768 		stream_init (&acfg->blob);
2769 
2770 	count = acfg->blob.index % align;
2771 
2772 	/* we assume the stream data will be aligned */
2773 	if (count)
2774 		add_stream_data (&acfg->blob, buf, 4 - count);
2775 
2776 	return add_stream_data (&acfg->blob, (char*)data, data_len);
2777 }
2778 
2779 /* Emit a table of data into the aot image */
2780 static void
emit_aot_data(MonoAotCompile * acfg,MonoAotFileTable table,const char * symbol,guint8 * data,int size)2781 emit_aot_data (MonoAotCompile *acfg, MonoAotFileTable table, const char *symbol, guint8 *data, int size)
2782 {
2783 	if (acfg->data_outfile) {
2784 		acfg->table_offsets [(int)table] = acfg->datafile_offset;
2785 		fwrite (data,1, size, acfg->data_outfile);
2786 		acfg->datafile_offset += size;
2787 		// align the data to 8 bytes. Put zeros in the file (so that every build results in consistent output).
2788 		int align = 8 - size % 8;
2789 		acfg->datafile_offset += align;
2790 		guint8 align_buf [16];
2791 		memset (&align_buf, 0, sizeof (align_buf));
2792 		fwrite (align_buf, align, 1, acfg->data_outfile);
2793 	} else if (acfg->llvm) {
2794 		mono_llvm_emit_aot_data (symbol, data, size);
2795 	} else {
2796 		emit_section_change (acfg, RODATA_SECT, 0);
2797 		emit_alignment (acfg, 8);
2798 		emit_label (acfg, symbol);
2799 		emit_bytes (acfg, data, size);
2800 	}
2801 }
2802 
2803 /*
2804  * emit_offset_table:
2805  *
2806  *   Emit a table of increasing offsets in a compact form using differential encoding.
2807  * There is an index entry for each GROUP_SIZE number of entries. The greater the
2808  * group size, the more compact the table becomes, but the slower it becomes to compute
2809  * a given entry. Returns the size of the table.
2810  */
2811 static guint32
emit_offset_table(MonoAotCompile * acfg,const char * symbol,MonoAotFileTable table,int noffsets,int group_size,gint32 * offsets)2812 emit_offset_table (MonoAotCompile *acfg, const char *symbol, MonoAotFileTable table, int noffsets, int group_size, gint32 *offsets)
2813 {
2814 	gint32 current_offset;
2815 	int i, buf_size, ngroups, index_entry_size;
2816 	guint8 *p, *buf;
2817 	guint8 *data_p, *data_buf;
2818 	guint32 *index_offsets;
2819 
2820 	ngroups = (noffsets + (group_size - 1)) / group_size;
2821 
2822 	index_offsets = g_new0 (guint32, ngroups);
2823 
2824 	buf_size = noffsets * 4;
2825 	p = buf = (guint8 *)g_malloc0 (buf_size);
2826 
2827 	current_offset = 0;
2828 	for (i = 0; i < noffsets; ++i) {
2829 		//printf ("D: %d -> %d\n", i, offsets [i]);
2830 		if ((i % group_size) == 0) {
2831 			index_offsets [i / group_size] = p - buf;
2832 			/* Emit the full value for these entries */
2833 			encode_value (offsets [i], p, &p);
2834 		} else {
2835 			/* The offsets are allowed to be non-increasing */
2836 			//g_assert (offsets [i] >= current_offset);
2837 			encode_value (offsets [i] - current_offset, p, &p);
2838 		}
2839 		current_offset = offsets [i];
2840 	}
2841 	data_buf = buf;
2842 	data_p = p;
2843 
2844 	if (ngroups && index_offsets [ngroups - 1] < 65000)
2845 		index_entry_size = 2;
2846 	else
2847 		index_entry_size = 4;
2848 
2849 	buf_size = (data_p - data_buf) + (ngroups * 4) + 16;
2850 	p = buf = (guint8 *)g_malloc0 (buf_size);
2851 
2852 	/* Emit the header */
2853 	encode_int (noffsets, p, &p);
2854 	encode_int (group_size, p, &p);
2855 	encode_int (ngroups, p, &p);
2856 	encode_int (index_entry_size, p, &p);
2857 
2858 	/* Emit the index */
2859 	for (i = 0; i < ngroups; ++i) {
2860 		if (index_entry_size == 2)
2861 			encode_int16 (index_offsets [i], p, &p);
2862 		else
2863 			encode_int (index_offsets [i], p, &p);
2864 	}
2865 	/* Emit the data */
2866 	memcpy (p, data_buf, data_p - data_buf);
2867 	p += data_p - data_buf;
2868 
2869 	g_assert (p - buf <= buf_size);
2870 
2871 	emit_aot_data (acfg, table, symbol, buf, p - buf);
2872 
2873 	g_free (buf);
2874 	g_free (data_buf);
2875 
2876     return (int)(p - buf);
2877 }
2878 
2879 static guint32
get_image_index(MonoAotCompile * cfg,MonoImage * image)2880 get_image_index (MonoAotCompile *cfg, MonoImage *image)
2881 {
2882 	guint32 index;
2883 
2884 	index = GPOINTER_TO_UINT (g_hash_table_lookup (cfg->image_hash, image));
2885 	if (index)
2886 		return index - 1;
2887 	else {
2888 		index = g_hash_table_size (cfg->image_hash);
2889 		g_hash_table_insert (cfg->image_hash, image, GUINT_TO_POINTER (index + 1));
2890 		g_ptr_array_add (cfg->image_table, image);
2891 		return index;
2892 	}
2893 }
2894 
2895 static guint32
find_typespec_for_class(MonoAotCompile * acfg,MonoClass * klass)2896 find_typespec_for_class (MonoAotCompile *acfg, MonoClass *klass)
2897 {
2898 	int i;
2899 	int len = acfg->image->tables [MONO_TABLE_TYPESPEC].rows;
2900 
2901 	/* FIXME: Search referenced images as well */
2902 	if (!acfg->typespec_classes) {
2903 		acfg->typespec_classes = g_hash_table_new (NULL, NULL);
2904 		for (i = 0; i < len; i++) {
2905 			MonoError error;
2906 			int typespec = MONO_TOKEN_TYPE_SPEC | (i + 1);
2907 			MonoClass *klass_key = mono_class_get_and_inflate_typespec_checked (acfg->image, typespec, NULL, &error);
2908 			if (!is_ok (&error)) {
2909 				mono_error_cleanup (&error);
2910 				continue;
2911 			}
2912 			g_hash_table_insert (acfg->typespec_classes, klass_key, GINT_TO_POINTER (typespec));
2913 		}
2914 	}
2915 	return GPOINTER_TO_INT (g_hash_table_lookup (acfg->typespec_classes, klass));
2916 }
2917 
2918 static void
2919 encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 **endbuf);
2920 
2921 static void
2922 encode_klass_ref (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, guint8 **endbuf);
2923 
2924 static void
2925 encode_ginst (MonoAotCompile *acfg, MonoGenericInst *inst, guint8 *buf, guint8 **endbuf);
2926 
2927 static void
2928 encode_type (MonoAotCompile *acfg, MonoType *t, guint8 *buf, guint8 **endbuf);
2929 
2930 static void
encode_klass_ref_inner(MonoAotCompile * acfg,MonoClass * klass,guint8 * buf,guint8 ** endbuf)2931 encode_klass_ref_inner (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, guint8 **endbuf)
2932 {
2933 	guint8 *p = buf;
2934 
2935 	/*
2936 	 * The encoding begins with one of the MONO_AOT_TYPEREF values, followed by additional
2937 	 * information.
2938 	 */
2939 
2940 	if (mono_class_is_ginst (klass)) {
2941 		guint32 token;
2942 		g_assert (klass->type_token);
2943 
2944 		/* Find a typespec for a class if possible */
2945 		token = find_typespec_for_class (acfg, klass);
2946 		if (token) {
2947 			encode_value (MONO_AOT_TYPEREF_TYPESPEC_TOKEN, p, &p);
2948 			encode_value (token, p, &p);
2949 		} else {
2950 			MonoClass *gclass = mono_class_get_generic_class (klass)->container_class;
2951 			MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
2952 			static int count = 0;
2953 			guint8 *p1 = p;
2954 
2955 			encode_value (MONO_AOT_TYPEREF_GINST, p, &p);
2956 			encode_klass_ref (acfg, gclass, p, &p);
2957 			encode_ginst (acfg, inst, p, &p);
2958 
2959 			count += p - p1;
2960 		}
2961 	} else if (klass->type_token) {
2962 		int iindex = get_image_index (acfg, klass->image);
2963 
2964 		g_assert (mono_metadata_token_code (klass->type_token) == MONO_TOKEN_TYPE_DEF);
2965 		if (iindex == 0) {
2966 			encode_value (MONO_AOT_TYPEREF_TYPEDEF_INDEX, p, &p);
2967 			encode_value (klass->type_token - MONO_TOKEN_TYPE_DEF, p, &p);
2968 		} else {
2969 			encode_value (MONO_AOT_TYPEREF_TYPEDEF_INDEX_IMAGE, p, &p);
2970 			encode_value (klass->type_token - MONO_TOKEN_TYPE_DEF, p, &p);
2971 			encode_value (get_image_index (acfg, klass->image), p, &p);
2972 		}
2973 	} else if ((klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR)) {
2974 		MonoGenericContainer *container = mono_type_get_generic_param_owner (&klass->byval_arg);
2975 		MonoGenericParam *par = klass->byval_arg.data.generic_param;
2976 
2977 		encode_value (MONO_AOT_TYPEREF_VAR, p, &p);
2978 
2979 		encode_value (par->gshared_constraint ? 1 : 0, p, &p);
2980 		if (par->gshared_constraint) {
2981 			MonoGSharedGenericParam *gpar = (MonoGSharedGenericParam*)par;
2982 			encode_type (acfg, par->gshared_constraint, p, &p);
2983 			encode_klass_ref (acfg, mono_class_from_generic_parameter_internal (gpar->parent), p, &p);
2984 		} else {
2985 			encode_value (klass->byval_arg.type, p, &p);
2986 			encode_value (mono_type_get_generic_param_num (&klass->byval_arg), p, &p);
2987 
2988 			encode_value (container->is_anonymous ? 0 : 1, p, &p);
2989 
2990 			if (!container->is_anonymous) {
2991 				encode_value (container->is_method, p, &p);
2992 				if (container->is_method)
2993 					encode_method_ref (acfg, container->owner.method, p, &p);
2994 				else
2995 					encode_klass_ref (acfg, container->owner.klass, p, &p);
2996 			}
2997 		}
2998 	} else if (klass->byval_arg.type == MONO_TYPE_PTR) {
2999 		encode_value (MONO_AOT_TYPEREF_PTR, p, &p);
3000 		encode_type (acfg, &klass->byval_arg, p, &p);
3001 	} else {
3002 		/* Array class */
3003 		g_assert (klass->rank > 0);
3004 		encode_value (MONO_AOT_TYPEREF_ARRAY, p, &p);
3005 		encode_value (klass->rank, p, &p);
3006 		encode_klass_ref (acfg, klass->element_class, p, &p);
3007 	}
3008 	*endbuf = p;
3009 }
3010 
3011 /*
3012  * encode_klass_ref:
3013  *
3014  *   Encode a reference to KLASS. We use our home-grown encoding instead of the
3015  * standard metadata encoding.
3016  */
3017 static void
encode_klass_ref(MonoAotCompile * acfg,MonoClass * klass,guint8 * buf,guint8 ** endbuf)3018 encode_klass_ref (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, guint8 **endbuf)
3019 {
3020 	gboolean shared = FALSE;
3021 
3022 	/*
3023 	 * The encoding of generic instances is large so emit them only once.
3024 	 */
3025 	if (mono_class_is_ginst (klass)) {
3026 		guint32 token;
3027 		g_assert (klass->type_token);
3028 
3029 		/* Find a typespec for a class if possible */
3030 		token = find_typespec_for_class (acfg, klass);
3031 		if (!token)
3032 			shared = TRUE;
3033 	} else if ((klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR)) {
3034 		shared = TRUE;
3035 	}
3036 
3037 	if (shared) {
3038 		guint offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->klass_blob_hash, klass));
3039 		guint8 *buf2, *p;
3040 
3041 		if (!offset) {
3042 			buf2 = (guint8 *)g_malloc (1024);
3043 			p = buf2;
3044 
3045 			encode_klass_ref_inner (acfg, klass, p, &p);
3046 			g_assert (p - buf2 < 1024);
3047 
3048 			offset = add_to_blob (acfg, buf2, p - buf2);
3049 			g_free (buf2);
3050 
3051 			g_hash_table_insert (acfg->klass_blob_hash, klass, GUINT_TO_POINTER (offset + 1));
3052 		} else {
3053 			offset --;
3054 		}
3055 
3056 		p = buf;
3057 		encode_value (MONO_AOT_TYPEREF_BLOB_INDEX, p, &p);
3058 		encode_value (offset, p, &p);
3059 		*endbuf = p;
3060 		return;
3061 	}
3062 
3063 	encode_klass_ref_inner (acfg, klass, buf, endbuf);
3064 }
3065 
3066 static void
encode_field_info(MonoAotCompile * cfg,MonoClassField * field,guint8 * buf,guint8 ** endbuf)3067 encode_field_info (MonoAotCompile *cfg, MonoClassField *field, guint8 *buf, guint8 **endbuf)
3068 {
3069 	guint32 token = mono_get_field_token (field);
3070 	guint8 *p = buf;
3071 
3072 	encode_klass_ref (cfg, field->parent, p, &p);
3073 	g_assert (mono_metadata_token_code (token) == MONO_TOKEN_FIELD_DEF);
3074 	encode_value (token - MONO_TOKEN_FIELD_DEF, p, &p);
3075 	*endbuf = p;
3076 }
3077 
3078 static void
encode_ginst(MonoAotCompile * acfg,MonoGenericInst * inst,guint8 * buf,guint8 ** endbuf)3079 encode_ginst (MonoAotCompile *acfg, MonoGenericInst *inst, guint8 *buf, guint8 **endbuf)
3080 {
3081 	guint8 *p = buf;
3082 	int i;
3083 
3084 	encode_value (inst->type_argc, p, &p);
3085 	for (i = 0; i < inst->type_argc; ++i)
3086 		encode_klass_ref (acfg, mono_class_from_mono_type (inst->type_argv [i]), p, &p);
3087 	*endbuf = p;
3088 }
3089 
3090 static void
encode_generic_context(MonoAotCompile * acfg,MonoGenericContext * context,guint8 * buf,guint8 ** endbuf)3091 encode_generic_context (MonoAotCompile *acfg, MonoGenericContext *context, guint8 *buf, guint8 **endbuf)
3092 {
3093 	guint8 *p = buf;
3094 	MonoGenericInst *inst;
3095 
3096 	inst = context->class_inst;
3097 	if (inst) {
3098 		g_assert (inst->type_argc);
3099 		encode_ginst (acfg, inst, p, &p);
3100 	} else {
3101 		encode_value (0, p, &p);
3102 	}
3103 	inst = context->method_inst;
3104 	if (inst) {
3105 		g_assert (inst->type_argc);
3106 		encode_ginst (acfg, inst, p, &p);
3107 	} else {
3108 		encode_value (0, p, &p);
3109 	}
3110 	*endbuf = p;
3111 }
3112 
3113 static void
encode_type(MonoAotCompile * acfg,MonoType * t,guint8 * buf,guint8 ** endbuf)3114 encode_type (MonoAotCompile *acfg, MonoType *t, guint8 *buf, guint8 **endbuf)
3115 {
3116 	guint8 *p = buf;
3117 
3118 	g_assert (t->num_mods == 0);
3119 	/* t->attrs can be ignored */
3120 	//g_assert (t->attrs == 0);
3121 
3122 	if (t->pinned) {
3123 		*p = MONO_TYPE_PINNED;
3124 		++p;
3125 	}
3126 	if (t->byref) {
3127 		*p = MONO_TYPE_BYREF;
3128 		++p;
3129 	}
3130 
3131 	*p = t->type;
3132 	p ++;
3133 
3134 	switch (t->type) {
3135 	case MONO_TYPE_VOID:
3136 	case MONO_TYPE_BOOLEAN:
3137 	case MONO_TYPE_CHAR:
3138 	case MONO_TYPE_I1:
3139 	case MONO_TYPE_U1:
3140 	case MONO_TYPE_I2:
3141 	case MONO_TYPE_U2:
3142 	case MONO_TYPE_I4:
3143 	case MONO_TYPE_U4:
3144 	case MONO_TYPE_I8:
3145 	case MONO_TYPE_U8:
3146 	case MONO_TYPE_R4:
3147 	case MONO_TYPE_R8:
3148 	case MONO_TYPE_I:
3149 	case MONO_TYPE_U:
3150 	case MONO_TYPE_STRING:
3151 	case MONO_TYPE_OBJECT:
3152 	case MONO_TYPE_TYPEDBYREF:
3153 		break;
3154 	case MONO_TYPE_VALUETYPE:
3155 	case MONO_TYPE_CLASS:
3156 		encode_klass_ref (acfg, mono_class_from_mono_type (t), p, &p);
3157 		break;
3158 	case MONO_TYPE_SZARRAY:
3159 		encode_klass_ref (acfg, t->data.klass, p, &p);
3160 		break;
3161 	case MONO_TYPE_PTR:
3162 		encode_type (acfg, t->data.type, p, &p);
3163 		break;
3164 	case MONO_TYPE_GENERICINST: {
3165 		MonoClass *gclass = t->data.generic_class->container_class;
3166 		MonoGenericInst *inst = t->data.generic_class->context.class_inst;
3167 
3168 		encode_klass_ref (acfg, gclass, p, &p);
3169 		encode_ginst (acfg, inst, p, &p);
3170 		break;
3171 	}
3172 	case MONO_TYPE_ARRAY: {
3173 		MonoArrayType *array = t->data.array;
3174 		int i;
3175 
3176 		encode_klass_ref (acfg, array->eklass, p, &p);
3177 		encode_value (array->rank, p, &p);
3178 		encode_value (array->numsizes, p, &p);
3179 		for (i = 0; i < array->numsizes; ++i)
3180 			encode_value (array->sizes [i], p, &p);
3181 		encode_value (array->numlobounds, p, &p);
3182 		for (i = 0; i < array->numlobounds; ++i)
3183 			encode_value (array->lobounds [i], p, &p);
3184 		break;
3185 	}
3186 	case MONO_TYPE_VAR:
3187 	case MONO_TYPE_MVAR:
3188 		encode_klass_ref (acfg, mono_class_from_mono_type (t), p, &p);
3189 		break;
3190 	default:
3191 		g_assert_not_reached ();
3192 	}
3193 
3194 	*endbuf = p;
3195 }
3196 
3197 static void
encode_signature(MonoAotCompile * acfg,MonoMethodSignature * sig,guint8 * buf,guint8 ** endbuf)3198 encode_signature (MonoAotCompile *acfg, MonoMethodSignature *sig, guint8 *buf, guint8 **endbuf)
3199 {
3200 	guint8 *p = buf;
3201 	guint32 flags = 0;
3202 	int i;
3203 
3204 	/* Similar to the metadata encoding */
3205 	if (sig->generic_param_count)
3206 		flags |= 0x10;
3207 	if (sig->hasthis)
3208 		flags |= 0x20;
3209 	if (sig->explicit_this)
3210 		flags |= 0x40;
3211 	flags |= (sig->call_convention & 0x0F);
3212 
3213 	*p = flags;
3214 	++p;
3215 	if (sig->generic_param_count)
3216 		encode_value (sig->generic_param_count, p, &p);
3217 	encode_value (sig->param_count, p, &p);
3218 
3219 	encode_type (acfg, sig->ret, p, &p);
3220 	for (i = 0; i < sig->param_count; ++i) {
3221 		if (sig->sentinelpos == i) {
3222 			*p = MONO_TYPE_SENTINEL;
3223 			++p;
3224 		}
3225 		encode_type (acfg, sig->params [i], p, &p);
3226 	}
3227 
3228 	*endbuf = p;
3229 }
3230 
3231 #define MAX_IMAGE_INDEX 250
3232 
3233 static void
encode_method_ref(MonoAotCompile * acfg,MonoMethod * method,guint8 * buf,guint8 ** endbuf)3234 encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 **endbuf)
3235 {
3236 	guint32 image_index = get_image_index (acfg, method->klass->image);
3237 	guint32 token = method->token;
3238 	MonoJumpInfoToken *ji;
3239 	guint8 *p = buf;
3240 
3241 	/*
3242 	 * The encoding for most methods is as follows:
3243 	 * - image index encoded as a leb128
3244 	 * - token index encoded as a leb128
3245 	 * Values of image index >= MONO_AOT_METHODREF_MIN are used to mark additional
3246 	 * types of method encodings.
3247 	 */
3248 
3249 	/* Mark methods which can't use aot trampolines because they need the further
3250 	 * processing in mono_magic_trampoline () which requires a MonoMethod*.
3251 	 */
3252 	if ((method->is_generic && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) ||
3253 		(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED))
3254 		encode_value ((MONO_AOT_METHODREF_NO_AOT_TRAMPOLINE << 24), p, &p);
3255 
3256 	if (method->wrapper_type) {
3257 		WrapperInfo *info = mono_marshal_get_wrapper_info (method);
3258 
3259 		encode_value ((MONO_AOT_METHODREF_WRAPPER << 24), p, &p);
3260 
3261 		encode_value (method->wrapper_type, p, &p);
3262 
3263 		switch (method->wrapper_type) {
3264 		case MONO_WRAPPER_REMOTING_INVOKE:
3265 		case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
3266 		case MONO_WRAPPER_XDOMAIN_INVOKE: {
3267 			MonoMethod *m;
3268 
3269 			m = mono_marshal_method_from_wrapper (method);
3270 			g_assert (m);
3271 			encode_method_ref (acfg, m, p, &p);
3272 			break;
3273 		}
3274 		case MONO_WRAPPER_PROXY_ISINST:
3275 		case MONO_WRAPPER_LDFLD:
3276 		case MONO_WRAPPER_LDFLDA:
3277 		case MONO_WRAPPER_STFLD: {
3278 			g_assert (info);
3279 			encode_klass_ref (acfg, info->d.proxy.klass, p, &p);
3280 			break;
3281 		}
3282 		case MONO_WRAPPER_ALLOC: {
3283 			/* The GC name is saved once in MonoAotFileInfo */
3284 			g_assert (info->d.alloc.alloc_type != -1);
3285 			encode_value (info->d.alloc.alloc_type, p, &p);
3286 			break;
3287 		}
3288 		case MONO_WRAPPER_WRITE_BARRIER: {
3289 			g_assert (info);
3290 			break;
3291 		}
3292 		case MONO_WRAPPER_STELEMREF: {
3293 			g_assert (info);
3294 			encode_value (info->subtype, p, &p);
3295 			if (info->subtype == WRAPPER_SUBTYPE_VIRTUAL_STELEMREF)
3296 				encode_value (info->d.virtual_stelemref.kind, p, &p);
3297 			break;
3298 		}
3299 		case MONO_WRAPPER_UNKNOWN: {
3300 			g_assert (info);
3301 			encode_value (info->subtype, p, &p);
3302 			if (info->subtype == WRAPPER_SUBTYPE_PTR_TO_STRUCTURE ||
3303 				info->subtype == WRAPPER_SUBTYPE_STRUCTURE_TO_PTR)
3304 				encode_klass_ref (acfg, method->klass, p, &p);
3305 			else if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER)
3306 				encode_method_ref (acfg, info->d.synchronized_inner.method, p, &p);
3307 			else if (info->subtype == WRAPPER_SUBTYPE_ARRAY_ACCESSOR)
3308 				encode_method_ref (acfg, info->d.array_accessor.method, p, &p);
3309 			else if (info->subtype == WRAPPER_SUBTYPE_INTERP_IN)
3310 				encode_signature (acfg, info->d.interp_in.sig, p, &p);
3311 			else if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG)
3312 				encode_signature (acfg, info->d.gsharedvt.sig, p, &p);
3313 			else if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG)
3314 				encode_signature (acfg, info->d.gsharedvt.sig, p, &p);
3315 			break;
3316 		}
3317 		case MONO_WRAPPER_MANAGED_TO_NATIVE: {
3318 			g_assert (info);
3319 			encode_value (info->subtype, p, &p);
3320 			if (info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
3321 				strcpy ((char*)p, method->name);
3322 				p += strlen (method->name) + 1;
3323 			} else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_AOT) {
3324 				encode_method_ref (acfg, info->d.managed_to_native.method, p, &p);
3325 			} else {
3326 				g_assert (info->subtype == WRAPPER_SUBTYPE_NONE || info->subtype == WRAPPER_SUBTYPE_PINVOKE);
3327 				encode_method_ref (acfg, info->d.managed_to_native.method, p, &p);
3328 			}
3329 			break;
3330 		}
3331 		case MONO_WRAPPER_SYNCHRONIZED: {
3332 			MonoMethod *m;
3333 
3334 			m = mono_marshal_method_from_wrapper (method);
3335 			g_assert (m);
3336 			g_assert (m != method);
3337 			encode_method_ref (acfg, m, p, &p);
3338 			break;
3339 		}
3340 		case MONO_WRAPPER_MANAGED_TO_MANAGED: {
3341 			g_assert (info);
3342 			encode_value (info->subtype, p, &p);
3343 
3344 			if (info->subtype == WRAPPER_SUBTYPE_ELEMENT_ADDR) {
3345 				encode_value (info->d.element_addr.rank, p, &p);
3346 				encode_value (info->d.element_addr.elem_size, p, &p);
3347 			} else if (info->subtype == WRAPPER_SUBTYPE_STRING_CTOR) {
3348 				encode_method_ref (acfg, info->d.string_ctor.method, p, &p);
3349 			} else {
3350 				g_assert_not_reached ();
3351 			}
3352 			break;
3353 		}
3354 		case MONO_WRAPPER_CASTCLASS: {
3355 			g_assert (info);
3356 			encode_value (info->subtype, p, &p);
3357 			break;
3358 		}
3359 		case MONO_WRAPPER_RUNTIME_INVOKE: {
3360 			g_assert (info);
3361 			encode_value (info->subtype, p, &p);
3362 			if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT || info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL)
3363 				encode_method_ref (acfg, info->d.runtime_invoke.method, p, &p);
3364 			else if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL)
3365 				encode_signature (acfg, info->d.runtime_invoke.sig, p, &p);
3366 			break;
3367 		}
3368 		case MONO_WRAPPER_DELEGATE_INVOKE:
3369 		case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE:
3370 		case MONO_WRAPPER_DELEGATE_END_INVOKE: {
3371 			if (method->is_inflated) {
3372 				/* These wrappers are identified by their class */
3373 				encode_value (1, p, &p);
3374 				encode_klass_ref (acfg, method->klass, p, &p);
3375 			} else {
3376 				MonoMethodSignature *sig = mono_method_signature (method);
3377 				WrapperInfo *info = mono_marshal_get_wrapper_info (method);
3378 
3379 				encode_value (0, p, &p);
3380 				if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE)
3381 					encode_value (info ? info->subtype : 0, p, &p);
3382 				encode_signature (acfg, sig, p, &p);
3383 			}
3384 			break;
3385 		}
3386 		case MONO_WRAPPER_NATIVE_TO_MANAGED: {
3387 			g_assert (info);
3388 			encode_method_ref (acfg, info->d.native_to_managed.method, p, &p);
3389 			encode_klass_ref (acfg, info->d.native_to_managed.klass, p, &p);
3390 			break;
3391 		}
3392 		default:
3393 			g_assert_not_reached ();
3394 		}
3395 	} else if (mono_method_signature (method)->is_inflated) {
3396 		/*
3397 		 * This is a generic method, find the original token which referenced it and
3398 		 * encode that.
3399 		 * Obtain the token from information recorded by the JIT.
3400 		 */
3401 		ji = (MonoJumpInfoToken *)g_hash_table_lookup (acfg->token_info_hash, method);
3402 		if (ji) {
3403 			image_index = get_image_index (acfg, ji->image);
3404 			g_assert (image_index < MAX_IMAGE_INDEX);
3405 			token = ji->token;
3406 
3407 			encode_value ((MONO_AOT_METHODREF_METHODSPEC << 24), p, &p);
3408 			encode_value (image_index, p, &p);
3409 			encode_value (token, p, &p);
3410 		} else {
3411 			MonoMethod *declaring;
3412 			MonoGenericContext *context = mono_method_get_context (method);
3413 
3414 			g_assert (method->is_inflated);
3415 			declaring = ((MonoMethodInflated*)method)->declaring;
3416 
3417 			/*
3418 			 * This might be a non-generic method of a generic instance, which
3419 			 * doesn't have a token since the reference is generated by the JIT
3420 			 * like Nullable:Box/Unbox, or by generic sharing.
3421 			 */
3422 			encode_value ((MONO_AOT_METHODREF_GINST << 24), p, &p);
3423 			/* Encode the klass */
3424 			encode_klass_ref (acfg, method->klass, p, &p);
3425 			/* Encode the method */
3426 			image_index = get_image_index (acfg, method->klass->image);
3427 			g_assert (image_index < MAX_IMAGE_INDEX);
3428 			g_assert (declaring->token);
3429 			token = declaring->token;
3430 			g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
3431 			encode_value (image_index, p, &p);
3432 			encode_value (token, p, &p);
3433 			encode_generic_context (acfg, context, p, &p);
3434 		}
3435 	} else if (token == 0) {
3436 		/* This might be a method of a constructed type like int[,].Set */
3437 		/* Obtain the token from information recorded by the JIT */
3438 		ji = (MonoJumpInfoToken *)g_hash_table_lookup (acfg->token_info_hash, method);
3439 		if (ji) {
3440 			image_index = get_image_index (acfg, ji->image);
3441 			g_assert (image_index < MAX_IMAGE_INDEX);
3442 			token = ji->token;
3443 
3444 			encode_value ((MONO_AOT_METHODREF_METHODSPEC << 24), p, &p);
3445 			encode_value (image_index, p, &p);
3446 			encode_value (token, p, &p);
3447 		} else {
3448 			/* Array methods */
3449 			g_assert (method->klass->rank);
3450 
3451 			/* Encode directly */
3452 			encode_value ((MONO_AOT_METHODREF_ARRAY << 24), p, &p);
3453 			encode_klass_ref (acfg, method->klass, p, &p);
3454 			if (!strcmp (method->name, ".ctor") && mono_method_signature (method)->param_count == method->klass->rank)
3455 				encode_value (0, p, &p);
3456 			else if (!strcmp (method->name, ".ctor") && mono_method_signature (method)->param_count == method->klass->rank * 2)
3457 				encode_value (1, p, &p);
3458 			else if (!strcmp (method->name, "Get"))
3459 				encode_value (2, p, &p);
3460 			else if (!strcmp (method->name, "Address"))
3461 				encode_value (3, p, &p);
3462 			else if (!strcmp (method->name, "Set"))
3463 				encode_value (4, p, &p);
3464 			else
3465 				g_assert_not_reached ();
3466 		}
3467 	} else {
3468 		g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
3469 
3470 		if (image_index >= MONO_AOT_METHODREF_MIN) {
3471 			encode_value ((MONO_AOT_METHODREF_LARGE_IMAGE_INDEX << 24), p, &p);
3472 			encode_value (image_index, p, &p);
3473 			encode_value (mono_metadata_token_index (token), p, &p);
3474 		} else {
3475 			encode_value ((image_index << 24) | mono_metadata_token_index (token), p, &p);
3476 		}
3477 	}
3478 	*endbuf = p;
3479 }
3480 
3481 static gint
compare_patches(gconstpointer a,gconstpointer b)3482 compare_patches (gconstpointer a, gconstpointer b)
3483 {
3484 	int i, j;
3485 
3486 	i = (*(MonoJumpInfo**)a)->ip.i;
3487 	j = (*(MonoJumpInfo**)b)->ip.i;
3488 
3489 	if (i < j)
3490 		return -1;
3491 	else
3492 		if (i > j)
3493 			return 1;
3494 	else
3495 		return 0;
3496 }
3497 
3498 static G_GNUC_UNUSED char*
patch_to_string(MonoJumpInfo * patch_info)3499 patch_to_string (MonoJumpInfo *patch_info)
3500 {
3501 	GString *str;
3502 
3503 	str = g_string_new ("");
3504 
3505 	g_string_append_printf (str, "%s(", get_patch_name (patch_info->type));
3506 
3507 	switch (patch_info->type) {
3508 	case MONO_PATCH_INFO_VTABLE:
3509 		mono_type_get_desc (str, &patch_info->data.klass->byval_arg, TRUE);
3510 		break;
3511 	default:
3512 		break;
3513 	}
3514 	g_string_append_printf (str, ")");
3515 	return g_string_free (str, FALSE);
3516 }
3517 
3518 /*
3519  * is_plt_patch:
3520  *
3521  *   Return whenever PATCH_INFO refers to a direct call, and thus requires a
3522  * PLT entry.
3523  */
3524 static inline gboolean
is_plt_patch(MonoJumpInfo * patch_info)3525 is_plt_patch (MonoJumpInfo *patch_info)
3526 {
3527 	switch (patch_info->type) {
3528 	case MONO_PATCH_INFO_METHOD:
3529 	case MONO_PATCH_INFO_INTERNAL_METHOD:
3530 	case MONO_PATCH_INFO_JIT_ICALL_ADDR:
3531 	case MONO_PATCH_INFO_ICALL_ADDR_CALL:
3532 	case MONO_PATCH_INFO_RGCTX_FETCH:
3533 		return TRUE;
3534 	default:
3535 		return FALSE;
3536 	}
3537 }
3538 
3539 /*
3540  * get_plt_symbol:
3541  *
3542  *   Return the symbol identifying the plt entry PLT_OFFSET.
3543  */
3544 static char*
get_plt_symbol(MonoAotCompile * acfg,int plt_offset,MonoJumpInfo * patch_info)3545 get_plt_symbol (MonoAotCompile *acfg, int plt_offset, MonoJumpInfo *patch_info)
3546 {
3547 #ifdef TARGET_MACH
3548 	/*
3549 	 * The Apple linker reorganizes object files, so it doesn't like branches to local
3550 	 * labels, since those have no relocations.
3551 	 */
3552 	return g_strdup_printf ("%sp_%d", acfg->llvm_label_prefix, plt_offset);
3553 #else
3554 	return g_strdup_printf ("%sp_%d", acfg->temp_prefix, plt_offset);
3555 #endif
3556 }
3557 
3558 /*
3559  * get_plt_entry:
3560  *
3561  *   Return a PLT entry which belongs to the method identified by PATCH_INFO.
3562  */
3563 static MonoPltEntry*
get_plt_entry(MonoAotCompile * acfg,MonoJumpInfo * patch_info)3564 get_plt_entry (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
3565 {
3566 	MonoPltEntry *res;
3567 	gboolean synchronized = FALSE;
3568 	static int synchronized_symbol_idx;
3569 
3570 	if (!is_plt_patch (patch_info))
3571 		return NULL;
3572 
3573 	if (!acfg->patch_to_plt_entry [patch_info->type])
3574 		acfg->patch_to_plt_entry [patch_info->type] = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
3575 	res = (MonoPltEntry *)g_hash_table_lookup (acfg->patch_to_plt_entry [patch_info->type], patch_info);
3576 
3577 	if (!acfg->llvm && patch_info->type == MONO_PATCH_INFO_METHOD && (patch_info->data.method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
3578 		/*
3579 		 * Allocate a separate PLT slot for each such patch, since some plt
3580 		 * entries will refer to the method itself, and some will refer to the
3581 		 * wrapper.
3582 		 */
3583 		res = NULL;
3584 		synchronized = TRUE;
3585 	}
3586 
3587 	if (!res) {
3588 		MonoJumpInfo *new_ji;
3589 
3590 		new_ji = mono_patch_info_dup_mp (acfg->mempool, patch_info);
3591 
3592 		res = (MonoPltEntry *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoPltEntry));
3593 		res->plt_offset = acfg->plt_offset;
3594 		res->ji = new_ji;
3595 		res->symbol = get_plt_symbol (acfg, res->plt_offset, patch_info);
3596 		if (acfg->aot_opts.write_symbols)
3597 			res->debug_sym = get_plt_entry_debug_sym (acfg, res->ji, acfg->plt_entry_debug_sym_cache);
3598 		if (synchronized) {
3599 			/* Avoid duplicate symbols because we don't cache */
3600 			res->symbol = g_strdup_printf ("%s_%d", res->symbol, synchronized_symbol_idx);
3601 			if (res->debug_sym)
3602 				res->debug_sym = g_strdup_printf ("%s_%d", res->debug_sym, synchronized_symbol_idx);
3603 			synchronized_symbol_idx ++;
3604 		}
3605 		if (res->debug_sym)
3606 			res->llvm_symbol = g_strdup_printf ("%s_%s_llvm", res->symbol, res->debug_sym);
3607 		else
3608 			res->llvm_symbol = g_strdup_printf ("%s_llvm", res->symbol);
3609 
3610 		g_hash_table_insert (acfg->patch_to_plt_entry [new_ji->type], new_ji, res);
3611 
3612 		g_hash_table_insert (acfg->plt_offset_to_entry, GUINT_TO_POINTER (res->plt_offset), res);
3613 
3614 		//g_assert (mono_patch_info_equal (patch_info, new_ji));
3615 		//mono_print_ji (patch_info); printf ("\n");
3616 		//g_hash_table_print_stats (acfg->patch_to_plt_entry);
3617 
3618 		acfg->plt_offset ++;
3619 	}
3620 
3621 	return res;
3622 }
3623 
3624 /**
3625  * get_got_offset:
3626  *
3627  *   Returns the offset of the GOT slot where the runtime object resulting from resolving
3628  * JI could be found if it exists, otherwise allocates a new one.
3629  */
3630 static guint32
get_got_offset(MonoAotCompile * acfg,gboolean llvm,MonoJumpInfo * ji)3631 get_got_offset (MonoAotCompile *acfg, gboolean llvm, MonoJumpInfo *ji)
3632 {
3633 	guint32 got_offset;
3634 	GotInfo *info = llvm ? &acfg->llvm_got_info : &acfg->got_info;
3635 
3636 	got_offset = GPOINTER_TO_UINT (g_hash_table_lookup (info->patch_to_got_offset_by_type [ji->type], ji));
3637 	if (got_offset)
3638 		return got_offset - 1;
3639 
3640 	if (llvm) {
3641 		got_offset = acfg->llvm_got_offset;
3642 		acfg->llvm_got_offset ++;
3643 	} else {
3644 		got_offset = acfg->got_offset;
3645 		acfg->got_offset ++;
3646 	}
3647 
3648 	acfg->stats.got_slots ++;
3649 	acfg->stats.got_slot_types [ji->type] ++;
3650 
3651 	g_hash_table_insert (info->patch_to_got_offset, ji, GUINT_TO_POINTER (got_offset + 1));
3652 	g_hash_table_insert (info->patch_to_got_offset_by_type [ji->type], ji, GUINT_TO_POINTER (got_offset + 1));
3653 	g_ptr_array_add (info->got_patches, ji);
3654 
3655 	return got_offset;
3656 }
3657 
3658 /* Add a method to the list of methods which need to be emitted */
3659 static void
add_method_with_index(MonoAotCompile * acfg,MonoMethod * method,int index,gboolean extra)3660 add_method_with_index (MonoAotCompile *acfg, MonoMethod *method, int index, gboolean extra)
3661 {
3662 	g_assert (method);
3663 	if (!g_hash_table_lookup (acfg->method_indexes, method)) {
3664 		g_ptr_array_add (acfg->methods, method);
3665 		g_hash_table_insert (acfg->method_indexes, method, GUINT_TO_POINTER (index + 1));
3666 		acfg->nmethods = acfg->methods->len + 1;
3667 	}
3668 
3669 	if (method->wrapper_type || extra)
3670 		g_ptr_array_add (acfg->extra_methods, method);
3671 }
3672 
3673 static gboolean
prefer_gsharedvt_method(MonoAotCompile * acfg,MonoMethod * method)3674 prefer_gsharedvt_method (MonoAotCompile *acfg, MonoMethod *method)
3675 {
3676 	/* One instantiation with valuetypes is generated for each async method */
3677 	if (method->klass->image == mono_defaults.corlib && (!strcmp (method->klass->name, "AsyncMethodBuilderCore") || !strcmp (method->klass->name, "AsyncVoidMethodBuilder")))
3678 		return TRUE;
3679 	else
3680 		return FALSE;
3681 }
3682 
3683 static guint32
get_method_index(MonoAotCompile * acfg,MonoMethod * method)3684 get_method_index (MonoAotCompile *acfg, MonoMethod *method)
3685 {
3686 	int index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_indexes, method));
3687 
3688 	g_assert (index);
3689 
3690 	return index - 1;
3691 }
3692 
3693 static int
add_method_full(MonoAotCompile * acfg,MonoMethod * method,gboolean extra,int depth)3694 add_method_full (MonoAotCompile *acfg, MonoMethod *method, gboolean extra, int depth)
3695 {
3696 	int index;
3697 
3698 	index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_indexes, method));
3699 	if (index)
3700 		return index - 1;
3701 
3702 	index = acfg->method_index;
3703 	add_method_with_index (acfg, method, index, extra);
3704 
3705 	g_ptr_array_add (acfg->method_order, GUINT_TO_POINTER (index));
3706 
3707 	g_hash_table_insert (acfg->method_depth, method, GUINT_TO_POINTER (depth));
3708 
3709 	acfg->method_index ++;
3710 
3711 	return index;
3712 }
3713 
3714 static int
add_method(MonoAotCompile * acfg,MonoMethod * method)3715 add_method (MonoAotCompile *acfg, MonoMethod *method)
3716 {
3717 	return add_method_full (acfg, method, FALSE, 0);
3718 }
3719 
3720 static void
mono_dedup_cache_method(MonoAotCompile * acfg,MonoMethod * method)3721 mono_dedup_cache_method (MonoAotCompile *acfg, MonoMethod *method)
3722 {
3723 	g_assert (acfg->dedup_stats);
3724 
3725 	char *name = mono_aot_get_mangled_method_name (method);
3726 	g_assert (name);
3727 
3728 	// For stats
3729 	char *stats_name = g_strdup (name);
3730 
3731 	g_assert (acfg->dedup_cache);
3732 
3733 	if (!g_hash_table_lookup (acfg->dedup_cache, name)) {
3734 		// This AOTCompile owns this method
3735 		// We do this to decide whether to write it to disk
3736 		// during a dedup run (first phase, where we skip).
3737 		//
3738 		// If never changed, then maybe can avoid a recompile
3739 		// of the cache.
3740 		//
3741 		// Files not read in during last phase.
3742 		acfg->dedup_cache_changed = TRUE;
3743 
3744 		// owns name
3745 		g_hash_table_insert (acfg->dedup_cache, name, method);
3746 	} else {
3747 		// owns name
3748 		g_free (name);
3749 	}
3750 
3751 	guint count = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->dedup_stats, stats_name));
3752 	count++;
3753 	g_hash_table_insert (acfg->dedup_stats, stats_name, GUINT_TO_POINTER (count));
3754 }
3755 
3756 static void
add_extra_method_with_depth(MonoAotCompile * acfg,MonoMethod * method,int depth)3757 add_extra_method_with_depth (MonoAotCompile *acfg, MonoMethod *method, int depth)
3758 {
3759 	if (mono_method_is_generic_sharable_full (method, TRUE, TRUE, FALSE))
3760 		method = mini_get_shared_method (method);
3761 	else if ((acfg->opts & MONO_OPT_GSHAREDVT) && prefer_gsharedvt_method (acfg, method) && mono_method_is_generic_sharable_full (method, FALSE, FALSE, TRUE))
3762 		/* Use the gsharedvt version */
3763 		method = mini_get_shared_method_full (method, TRUE, TRUE);
3764 
3765 	if ((acfg->aot_opts.dedup || acfg->aot_opts.dedup_include) && mono_aot_can_dedup (method)) {
3766 		mono_dedup_cache_method (acfg, method);
3767 
3768 		if (!acfg->dedup_emit_mode)
3769 			return;
3770 	}
3771 
3772 	if (acfg->aot_opts.log_generics)
3773 		aot_printf (acfg, "%*sAdding method %s.\n", depth, "", mono_method_get_full_name (method));
3774 
3775 	add_method_full (acfg, method, TRUE, depth);
3776 }
3777 
3778 static void
add_extra_method(MonoAotCompile * acfg,MonoMethod * method)3779 add_extra_method (MonoAotCompile *acfg, MonoMethod *method)
3780 {
3781 	add_extra_method_with_depth (acfg, method, 0);
3782 }
3783 
3784 static void
add_jit_icall_wrapper(gpointer key,gpointer value,gpointer user_data)3785 add_jit_icall_wrapper (gpointer key, gpointer value, gpointer user_data)
3786 {
3787 	MonoAotCompile *acfg = (MonoAotCompile *)user_data;
3788 	MonoJitICallInfo *callinfo = (MonoJitICallInfo *)value;
3789 	MonoMethod *wrapper;
3790 	char *name;
3791 
3792 	if (!callinfo->sig)
3793 		return;
3794 
3795 	name = g_strdup_printf ("__icall_wrapper_%s", callinfo->name);
3796 	wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, TRUE);
3797 	g_free (name);
3798 
3799 	add_method (acfg, wrapper);
3800 }
3801 
3802 static MonoMethod*
get_runtime_invoke_sig(MonoMethodSignature * sig)3803 get_runtime_invoke_sig (MonoMethodSignature *sig)
3804 {
3805 	MonoMethodBuilder *mb;
3806 	MonoMethod *m;
3807 
3808 	mb = mono_mb_new (mono_defaults.object_class, "FOO", MONO_WRAPPER_NONE);
3809 	m = mono_mb_create_method (mb, sig, 16);
3810 	MonoMethod *invoke = mono_marshal_get_runtime_invoke (m, FALSE);
3811 	mono_mb_free (mb);
3812 	return invoke;
3813 }
3814 
3815 static MonoMethod*
get_runtime_invoke(MonoAotCompile * acfg,MonoMethod * method,gboolean virtual_)3816 get_runtime_invoke (MonoAotCompile *acfg, MonoMethod *method, gboolean virtual_)
3817 {
3818 	return mono_marshal_get_runtime_invoke (method, virtual_);
3819 }
3820 
3821 static gboolean
can_marshal_struct(MonoClass * klass)3822 can_marshal_struct (MonoClass *klass)
3823 {
3824 	MonoClassField *field;
3825 	gboolean can_marshal = TRUE;
3826 	gpointer iter = NULL;
3827 	MonoMarshalType *info;
3828 	int i;
3829 
3830 	if (mono_class_is_auto_layout (klass))
3831 		return FALSE;
3832 
3833 	info = mono_marshal_load_type_info (klass);
3834 
3835 	/* Only allow a few field types to avoid asserts in the marshalling code */
3836 	while ((field = mono_class_get_fields (klass, &iter))) {
3837 		if ((field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3838 			continue;
3839 
3840 		switch (field->type->type) {
3841 		case MONO_TYPE_I4:
3842 		case MONO_TYPE_U4:
3843 		case MONO_TYPE_I1:
3844 		case MONO_TYPE_U1:
3845 		case MONO_TYPE_BOOLEAN:
3846 		case MONO_TYPE_I2:
3847 		case MONO_TYPE_U2:
3848 		case MONO_TYPE_CHAR:
3849 		case MONO_TYPE_I8:
3850 		case MONO_TYPE_U8:
3851 		case MONO_TYPE_I:
3852 		case MONO_TYPE_U:
3853 		case MONO_TYPE_PTR:
3854 		case MONO_TYPE_R4:
3855 		case MONO_TYPE_R8:
3856 		case MONO_TYPE_STRING:
3857 			break;
3858 		case MONO_TYPE_VALUETYPE:
3859 			if (!mono_class_from_mono_type (field->type)->enumtype && !can_marshal_struct (mono_class_from_mono_type (field->type)))
3860 				can_marshal = FALSE;
3861 			break;
3862 		case MONO_TYPE_SZARRAY: {
3863 			gboolean has_mspec = FALSE;
3864 
3865 			if (info) {
3866 				for (i = 0; i < info->num_fields; ++i) {
3867 					if (info->fields [i].field == field && info->fields [i].mspec)
3868 						has_mspec = TRUE;
3869 				}
3870 			}
3871 			if (!has_mspec)
3872 				can_marshal = FALSE;
3873 			break;
3874 		}
3875 		default:
3876 			can_marshal = FALSE;
3877 			break;
3878 		}
3879 	}
3880 
3881 	/* Special cases */
3882 	/* Its hard to compute whenever these can be marshalled or not */
3883 	if (!strcmp (klass->name_space, "System.Net.NetworkInformation.MacOsStructs") && strcmp (klass->name, "sockaddr_dl"))
3884 		return TRUE;
3885 
3886 	return can_marshal;
3887 }
3888 
3889 static void
create_gsharedvt_inst(MonoAotCompile * acfg,MonoMethod * method,MonoGenericContext * ctx)3890 create_gsharedvt_inst (MonoAotCompile *acfg, MonoMethod *method, MonoGenericContext *ctx)
3891 {
3892 	/* Create a vtype instantiation */
3893 	MonoGenericContext shared_context;
3894 	MonoType **args;
3895 	MonoGenericInst *inst;
3896 	MonoGenericContainer *container;
3897 	MonoClass **constraints;
3898 	int i;
3899 
3900 	memset (ctx, 0, sizeof (MonoGenericContext));
3901 
3902 	if (mono_class_is_gtd (method->klass)) {
3903 		shared_context = mono_class_get_generic_container (method->klass)->context;
3904 		inst = shared_context.class_inst;
3905 
3906 		args = g_new0 (MonoType*, inst->type_argc);
3907 		for (i = 0; i < inst->type_argc; ++i) {
3908 			args [i] = &mono_defaults.int_class->byval_arg;
3909 		}
3910 		ctx->class_inst = mono_metadata_get_generic_inst (inst->type_argc, args);
3911 	}
3912 	if (method->is_generic) {
3913 		container = mono_method_get_generic_container (method);
3914 		shared_context = container->context;
3915 		inst = shared_context.method_inst;
3916 
3917 		args = g_new0 (MonoType*, inst->type_argc);
3918 		for (i = 0; i < container->type_argc; ++i) {
3919 			MonoGenericParamInfo *info = &container->type_params [i].info;
3920 			gboolean ref_only = FALSE;
3921 
3922 			if (info && info->constraints) {
3923 				constraints = info->constraints;
3924 
3925 				while (*constraints) {
3926 					MonoClass *cklass = *constraints;
3927 					if (!(cklass == mono_defaults.object_class || (cklass->image == mono_defaults.corlib && !strcmp (cklass->name, "ValueType"))))
3928 						/* Inflaring the method with our vtype would not be valid */
3929 						ref_only = TRUE;
3930 					constraints ++;
3931 				}
3932 			}
3933 
3934 			if (ref_only)
3935 				args [i] = &mono_defaults.object_class->byval_arg;
3936 			else
3937 				args [i] = &mono_defaults.int_class->byval_arg;
3938 		}
3939 		ctx->method_inst = mono_metadata_get_generic_inst (inst->type_argc, args);
3940 	}
3941 }
3942 
3943 static void
add_wrappers(MonoAotCompile * acfg)3944 add_wrappers (MonoAotCompile *acfg)
3945 {
3946 	MonoMethod *method, *m;
3947 	int i, j;
3948 	MonoMethodSignature *sig, *csig;
3949 	guint32 token;
3950 
3951 	/*
3952 	 * FIXME: Instead of AOTing all the wrappers, it might be better to redesign them
3953 	 * so there is only one wrapper of a given type, or inlining their contents into their
3954 	 * callers.
3955 	 */
3956 	for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
3957 		MonoError error;
3958 		MonoMethod *method;
3959 		guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
3960 		gboolean skip = FALSE;
3961 
3962 		method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
3963 		report_loader_error (acfg, &error, TRUE, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
3964 
3965 		if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
3966 			(method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
3967 			(method->flags & METHOD_ATTRIBUTE_ABSTRACT))
3968 			skip = TRUE;
3969 
3970 		/* Skip methods which can not be handled by get_runtime_invoke () */
3971 		sig = mono_method_signature (method);
3972 		if (!sig)
3973 			continue;
3974 		if ((sig->ret->type == MONO_TYPE_PTR) ||
3975 			(sig->ret->type == MONO_TYPE_TYPEDBYREF))
3976 			skip = TRUE;
3977 		if (mono_class_is_open_constructed_type (sig->ret))
3978 			skip = TRUE;
3979 
3980 		for (j = 0; j < sig->param_count; j++) {
3981 			if (sig->params [j]->type == MONO_TYPE_TYPEDBYREF)
3982 				skip = TRUE;
3983 			if (mono_class_is_open_constructed_type (sig->params [j]))
3984 				skip = TRUE;
3985 		}
3986 
3987 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
3988 		if (!mono_class_is_contextbound (method->klass)) {
3989 			MonoDynCallInfo *info = mono_arch_dyn_call_prepare (sig);
3990 			gboolean has_nullable = FALSE;
3991 
3992 			for (j = 0; j < sig->param_count; j++) {
3993 				if (sig->params [j]->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (sig->params [j])))
3994 					has_nullable = TRUE;
3995 			}
3996 
3997 			if (info && !has_nullable && !acfg->aot_opts.llvm_only) {
3998 				/* Supported by the dynamic runtime-invoke wrapper */
3999 				skip = TRUE;
4000 			}
4001 			if (info)
4002 				mono_arch_dyn_call_free (info);
4003 		}
4004 #endif
4005 
4006 		if (acfg->aot_opts.llvm_only)
4007 			/* Supported by the gsharedvt based runtime-invoke wrapper */
4008 			skip = TRUE;
4009 
4010 		if (!skip) {
4011 			//printf ("%s\n", mono_method_full_name (method, TRUE));
4012 			add_method (acfg, get_runtime_invoke (acfg, method, FALSE));
4013 		}
4014  	}
4015 
4016 	if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) {
4017 		int nallocators;
4018 
4019 		/* Runtime invoke wrappers */
4020 
4021 		/* void runtime-invoke () [.cctor] */
4022 		csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
4023 		csig->ret = &mono_defaults.void_class->byval_arg;
4024 		add_method (acfg, get_runtime_invoke_sig (csig));
4025 
4026 		/* void runtime-invoke () [Finalize] */
4027 		csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
4028 		csig->hasthis = 1;
4029 		csig->ret = &mono_defaults.void_class->byval_arg;
4030 		add_method (acfg, get_runtime_invoke_sig (csig));
4031 
4032 		/* void runtime-invoke (string) [exception ctor] */
4033 		csig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4034 		csig->hasthis = 1;
4035 		csig->ret = &mono_defaults.void_class->byval_arg;
4036 		csig->params [0] = &mono_defaults.string_class->byval_arg;
4037 		add_method (acfg, get_runtime_invoke_sig (csig));
4038 
4039 		/* void runtime-invoke (string, string) [exception ctor] */
4040 		csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
4041 		csig->hasthis = 1;
4042 		csig->ret = &mono_defaults.void_class->byval_arg;
4043 		csig->params [0] = &mono_defaults.string_class->byval_arg;
4044 		csig->params [1] = &mono_defaults.string_class->byval_arg;
4045 		add_method (acfg, get_runtime_invoke_sig (csig));
4046 
4047 		/* string runtime-invoke () [Exception.ToString ()] */
4048 		csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
4049 		csig->hasthis = 1;
4050 		csig->ret = &mono_defaults.string_class->byval_arg;
4051 		add_method (acfg, get_runtime_invoke_sig (csig));
4052 
4053 		/* void runtime-invoke (string, Exception) [exception ctor] */
4054 		csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
4055 		csig->hasthis = 1;
4056 		csig->ret = &mono_defaults.void_class->byval_arg;
4057 		csig->params [0] = &mono_defaults.string_class->byval_arg;
4058 		csig->params [1] = &mono_defaults.exception_class->byval_arg;
4059 		add_method (acfg, get_runtime_invoke_sig (csig));
4060 
4061 		/* Assembly runtime-invoke (string, Assembly, bool) [DoAssemblyResolve] */
4062 		csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
4063 		csig->hasthis = 1;
4064 		csig->ret = &(mono_class_load_from_name (
4065 											mono_defaults.corlib, "System.Reflection", "Assembly"))->byval_arg;
4066 		csig->params [0] = &mono_defaults.string_class->byval_arg;
4067 		csig->params [1] = &(mono_class_load_from_name (mono_defaults.corlib, "System.Reflection", "Assembly"))->byval_arg;
4068 		csig->params [2] = &mono_defaults.boolean_class->byval_arg;
4069 		add_method (acfg, get_runtime_invoke_sig (csig));
4070 
4071 		/* runtime-invoke used by finalizers */
4072 		add_method (acfg, get_runtime_invoke (acfg, mono_class_get_method_from_name_flags (mono_defaults.object_class, "Finalize", 0, 0), TRUE));
4073 
4074 		/* This is used by mono_runtime_capture_context () */
4075 		method = mono_get_context_capture_method ();
4076 		if (method)
4077 			add_method (acfg, get_runtime_invoke (acfg, method, FALSE));
4078 
4079 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
4080 		if (!acfg->aot_opts.llvm_only)
4081 			add_method (acfg, mono_marshal_get_runtime_invoke_dynamic ());
4082 #endif
4083 
4084 		/* These are used by mono_jit_runtime_invoke () to calls gsharedvt out wrappers */
4085 		if (acfg->aot_opts.llvm_only) {
4086 			int variants;
4087 
4088 			/* Create simplified signatures which match the signature used by the gsharedvt out wrappers */
4089 			for (variants = 0; variants < 4; ++variants) {
4090 				for (i = 0; i < 16; ++i) {
4091 					sig = mini_get_gsharedvt_out_sig_wrapper_signature ((variants & 1) > 0, (variants & 2) > 0, i);
4092 					add_extra_method (acfg, mono_marshal_get_runtime_invoke_for_sig (sig));
4093 
4094 					g_free (sig);
4095 				}
4096 			}
4097 		}
4098 
4099 		/* stelemref */
4100 		add_method (acfg, mono_marshal_get_stelemref ());
4101 
4102 		/* Managed Allocators */
4103 		nallocators = mono_gc_get_managed_allocator_types ();
4104 		for (i = 0; i < nallocators; ++i) {
4105 			if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_REGULAR)))
4106 				add_method (acfg, m);
4107 			if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_SLOW_PATH)))
4108 				add_method (acfg, m);
4109 			if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_PROFILER)))
4110 				add_method (acfg, m);
4111 		}
4112 
4113 		/* write barriers */
4114 		if (mono_gc_is_moving ()) {
4115 			add_method (acfg, mono_gc_get_specific_write_barrier (FALSE));
4116 			add_method (acfg, mono_gc_get_specific_write_barrier (TRUE));
4117 		}
4118 
4119 		/* Stelemref wrappers */
4120 		{
4121 			MonoMethod **wrappers;
4122 			int nwrappers;
4123 
4124 			wrappers = mono_marshal_get_virtual_stelemref_wrappers (&nwrappers);
4125 			for (i = 0; i < nwrappers; ++i)
4126 				add_method (acfg, wrappers [i]);
4127 			g_free (wrappers);
4128 		}
4129 
4130 		/* castclass_with_check wrapper */
4131 		add_method (acfg, mono_marshal_get_castclass_with_cache ());
4132 		/* isinst_with_check wrapper */
4133 		add_method (acfg, mono_marshal_get_isinst_with_cache ());
4134 
4135 		/* JIT icall wrappers */
4136 		/* FIXME: locking - this is "safe" as full-AOT threads don't mutate the icall hash*/
4137 		g_hash_table_foreach (mono_get_jit_icall_info (), add_jit_icall_wrapper, acfg);
4138 	}
4139 
4140 	/*
4141 	 * remoting-invoke-with-check wrappers are very frequent, so avoid emitting them,
4142 	 * we use the original method instead at runtime.
4143 	 * Since full-aot doesn't support remoting, this is not a problem.
4144 	 */
4145 #if 0
4146 	/* remoting-invoke wrappers */
4147 	for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
4148 		MonoError error;
4149 		MonoMethodSignature *sig;
4150 
4151 		token = MONO_TOKEN_METHOD_DEF | (i + 1);
4152 		method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
4153 		g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4154 
4155 		sig = mono_method_signature (method);
4156 
4157 		if (sig->hasthis && (method->klass->marshalbyref || method->klass == mono_defaults.object_class)) {
4158 			m = mono_marshal_get_remoting_invoke_with_check (method);
4159 
4160 			add_method (acfg, m);
4161 		}
4162 	}
4163 #endif
4164 
4165 	/* delegate-invoke wrappers */
4166 	for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
4167 		MonoError error;
4168 		MonoClass *klass;
4169 		MonoCustomAttrInfo *cattr;
4170 
4171 		token = MONO_TOKEN_TYPE_DEF | (i + 1);
4172 		klass = mono_class_get_checked (acfg->image, token, &error);
4173 
4174 		if (!klass) {
4175 			mono_error_cleanup (&error);
4176 			continue;
4177 		}
4178 
4179 		if (!klass->delegate || klass == mono_defaults.delegate_class || klass == mono_defaults.multicastdelegate_class)
4180 			continue;
4181 
4182 		if (!mono_class_is_gtd (klass)) {
4183 			method = mono_get_delegate_invoke (klass);
4184 
4185 			m = mono_marshal_get_delegate_invoke (method, NULL);
4186 
4187 			add_method (acfg, m);
4188 
4189 			method = mono_class_get_method_from_name_flags (klass, "BeginInvoke", -1, 0);
4190 			if (method)
4191 				add_method (acfg, mono_marshal_get_delegate_begin_invoke (method));
4192 
4193 			method = mono_class_get_method_from_name_flags (klass, "EndInvoke", -1, 0);
4194 			if (method)
4195 				add_method (acfg, mono_marshal_get_delegate_end_invoke (method));
4196 
4197 			cattr = mono_custom_attrs_from_class_checked (klass, &error);
4198 			if (!is_ok (&error)) {
4199 				mono_error_cleanup (&error);
4200 				continue;
4201 			}
4202 
4203 			if (cattr) {
4204 				int j;
4205 
4206 				for (j = 0; j < cattr->num_attrs; ++j)
4207 					if (cattr->attrs [j].ctor && (!strcmp (cattr->attrs [j].ctor->klass->name, "MonoNativeFunctionWrapperAttribute") || !strcmp (cattr->attrs [j].ctor->klass->name, "UnmanagedFunctionPointerAttribute")))
4208 						break;
4209 				if (j < cattr->num_attrs) {
4210 					MonoMethod *invoke;
4211 					MonoMethod *wrapper;
4212 					MonoMethod *del_invoke;
4213 
4214 					/* Add wrappers needed by mono_ftnptr_to_delegate () */
4215 					invoke = mono_get_delegate_invoke (klass);
4216 					wrapper = mono_marshal_get_native_func_wrapper_aot (klass);
4217 					del_invoke = mono_marshal_get_delegate_invoke_internal (invoke, FALSE, TRUE, wrapper);
4218 					add_method (acfg, wrapper);
4219 					add_method (acfg, del_invoke);
4220 				}
4221 			}
4222 		} else if ((acfg->opts & MONO_OPT_GSHAREDVT) && mono_class_is_gtd (klass)) {
4223 			MonoError error;
4224 			MonoGenericContext ctx;
4225 			MonoMethod *inst, *gshared;
4226 
4227 			/*
4228 			 * Emit gsharedvt versions of the generic delegate-invoke wrappers
4229 			 */
4230 			/* Invoke */
4231 			method = mono_get_delegate_invoke (klass);
4232 			create_gsharedvt_inst (acfg, method, &ctx);
4233 
4234 			inst = mono_class_inflate_generic_method_checked (method, &ctx, &error);
4235 			g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4236 
4237 			m = mono_marshal_get_delegate_invoke (inst, NULL);
4238 			g_assert (m->is_inflated);
4239 
4240 			gshared = mini_get_shared_method_full (m, FALSE, TRUE);
4241 			add_extra_method (acfg, gshared);
4242 
4243 			/* begin-invoke */
4244 			method = mono_get_delegate_begin_invoke (klass);
4245 			if (method) {
4246 				create_gsharedvt_inst (acfg, method, &ctx);
4247 
4248 				inst = mono_class_inflate_generic_method_checked (method, &ctx, &error);
4249 				g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4250 
4251 				m = mono_marshal_get_delegate_begin_invoke (inst);
4252 				g_assert (m->is_inflated);
4253 
4254 				gshared = mini_get_shared_method_full (m, FALSE, TRUE);
4255 				add_extra_method (acfg, gshared);
4256 			}
4257 
4258 			/* end-invoke */
4259 			method = mono_get_delegate_end_invoke (klass);
4260 			if (method) {
4261 				create_gsharedvt_inst (acfg, method, &ctx);
4262 
4263 				inst = mono_class_inflate_generic_method_checked (method, &ctx, &error);
4264 				g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4265 
4266 				m = mono_marshal_get_delegate_end_invoke (inst);
4267 				g_assert (m->is_inflated);
4268 
4269 				gshared = mini_get_shared_method_full (m, FALSE, TRUE);
4270 				add_extra_method (acfg, gshared);
4271 			}
4272 		}
4273 	}
4274 
4275 	/* array access wrappers */
4276 	for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
4277 		MonoError error;
4278 		MonoClass *klass;
4279 
4280 		token = MONO_TOKEN_TYPE_SPEC | (i + 1);
4281 		klass = mono_class_get_checked (acfg->image, token, &error);
4282 
4283 		if (!klass) {
4284 			mono_error_cleanup (&error);
4285 			continue;
4286 		}
4287 
4288 		if (klass->rank && MONO_TYPE_IS_PRIMITIVE (&klass->element_class->byval_arg)) {
4289 			MonoMethod *m, *wrapper;
4290 
4291 			/* Add runtime-invoke wrappers too */
4292 
4293 			m = mono_class_get_method_from_name (klass, "Get", -1);
4294 			g_assert (m);
4295 			wrapper = mono_marshal_get_array_accessor_wrapper (m);
4296 			add_extra_method (acfg, wrapper);
4297 			if (!acfg->aot_opts.llvm_only)
4298 				add_extra_method (acfg, get_runtime_invoke (acfg, wrapper, FALSE));
4299 
4300 			m = mono_class_get_method_from_name (klass, "Set", -1);
4301 			g_assert (m);
4302 			wrapper = mono_marshal_get_array_accessor_wrapper (m);
4303 			add_extra_method (acfg, wrapper);
4304 			if (!acfg->aot_opts.llvm_only)
4305 				add_extra_method (acfg, get_runtime_invoke (acfg, wrapper, FALSE));
4306 		}
4307 	}
4308 
4309 	/* Synchronized wrappers */
4310 	for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
4311 		MonoError error;
4312 		token = MONO_TOKEN_METHOD_DEF | (i + 1);
4313 		method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
4314 		report_loader_error (acfg, &error, TRUE, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
4315 
4316 		if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
4317 			if (method->is_generic) {
4318 				// FIXME:
4319 			} else if ((acfg->opts & MONO_OPT_GSHAREDVT) && mono_class_is_gtd (method->klass)) {
4320 				MonoError error;
4321 				MonoGenericContext ctx;
4322 				MonoMethod *inst, *gshared, *m;
4323 
4324 				/*
4325 				 * Create a generic wrapper for a generic instance, and AOT that.
4326 				 */
4327 				create_gsharedvt_inst (acfg, method, &ctx);
4328 				inst = mono_class_inflate_generic_method_checked (method, &ctx, &error);
4329 				g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4330 				m = mono_marshal_get_synchronized_wrapper (inst);
4331 				g_assert (m->is_inflated);
4332 				gshared = mini_get_shared_method_full (m, FALSE, TRUE);
4333 				add_method (acfg, gshared);
4334 			} else {
4335 				add_method (acfg, mono_marshal_get_synchronized_wrapper (method));
4336 			}
4337 		}
4338 	}
4339 
4340 	/* pinvoke wrappers */
4341 	for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
4342 		MonoError error;
4343 		MonoMethod *method;
4344 		guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
4345 
4346 		method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
4347 		report_loader_error (acfg, &error, TRUE, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
4348 
4349 		if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
4350 			(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
4351 			add_method (acfg, mono_marshal_get_native_wrapper (method, TRUE, TRUE));
4352 		}
4353 
4354 		if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
4355 			if (acfg->aot_opts.llvm_only) {
4356 				/* The wrappers have a different signature (hasthis is not set) so need to add this too */
4357 				add_gsharedvt_wrappers (acfg, mono_method_signature (method), FALSE, TRUE);
4358 			}
4359 		}
4360 	}
4361 
4362 	/* native-to-managed wrappers */
4363 	for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
4364 		MonoError error;
4365 		MonoMethod *method;
4366 		guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
4367 		MonoCustomAttrInfo *cattr;
4368 		int j;
4369 
4370 		method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
4371 		report_loader_error (acfg, &error, TRUE, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
4372 
4373 		/*
4374 		 * Only generate native-to-managed wrappers for methods which have an
4375 		 * attribute named MonoPInvokeCallbackAttribute. We search for the attribute by
4376 		 * name to avoid defining a new assembly to contain it.
4377 		 */
4378 		cattr = mono_custom_attrs_from_method_checked (method, &error);
4379 		if (!is_ok (&error)) {
4380 			char *name = mono_method_get_full_name (method);
4381 			report_loader_error (acfg, &error, TRUE, "Failed to load custom attributes from method %s due to %s\n", name, mono_error_get_message (&error));
4382 			g_free (name);
4383 		}
4384 
4385 		if (cattr) {
4386 			for (j = 0; j < cattr->num_attrs; ++j)
4387 				if (cattr->attrs [j].ctor && !strcmp (cattr->attrs [j].ctor->klass->name, "MonoPInvokeCallbackAttribute"))
4388 					break;
4389 			if (j < cattr->num_attrs) {
4390 				MonoCustomAttrEntry *e = &cattr->attrs [j];
4391 				MonoMethodSignature *sig = mono_method_signature (e->ctor);
4392 				const char *p = (const char*)e->data;
4393 				const char *named;
4394 				int slen, num_named, named_type;
4395 				char *n;
4396 				MonoType *t;
4397 				MonoClass *klass;
4398 				char *export_name = NULL;
4399 				MonoMethod *wrapper;
4400 
4401 				/* this cannot be enforced by the C# compiler so we must give the user some warning before aborting */
4402 				if (!(method->flags & METHOD_ATTRIBUTE_STATIC)) {
4403 					g_warning ("AOT restriction: Method '%s' must be static since it is decorated with [MonoPInvokeCallback]. See http://ios.xamarin.com/Documentation/Limitations#Reverse_Callbacks",
4404 						mono_method_full_name (method, TRUE));
4405 					exit (1);
4406 				}
4407 
4408 				g_assert (sig->param_count == 1);
4409 				g_assert (sig->params [0]->type == MONO_TYPE_CLASS && !strcmp (mono_class_from_mono_type (sig->params [0])->name, "Type"));
4410 
4411 				/*
4412 				 * Decode the cattr manually since we can't create objects
4413 				 * during aot compilation.
4414 				 */
4415 
4416 				/* Skip prolog */
4417 				p += 2;
4418 
4419 				/* From load_cattr_value () in reflection.c */
4420 				slen = mono_metadata_decode_value (p, &p);
4421 				n = (char *)g_memdup (p, slen + 1);
4422 				n [slen] = 0;
4423 				t = mono_reflection_type_from_name_checked (n, acfg->image, &error);
4424 				g_assert (t);
4425 				mono_error_assert_ok (&error);
4426 				g_free (n);
4427 
4428 				klass = mono_class_from_mono_type (t);
4429 				g_assert (klass->parent == mono_defaults.multicastdelegate_class);
4430 
4431 				p += slen;
4432 
4433 				num_named = read16 (p);
4434 				p += 2;
4435 
4436 				g_assert (num_named < 2);
4437 				if (num_named == 1) {
4438 					int name_len;
4439 					char *name;
4440 
4441 					/* parse ExportSymbol attribute */
4442 					named = p;
4443 					named_type = *named;
4444 					named += 1;
4445 					/* data_type = *named; */
4446 					named += 1;
4447 
4448 					name_len = mono_metadata_decode_blob_size (named, &named);
4449 					name = (char *)g_malloc (name_len + 1);
4450 					memcpy (name, named, name_len);
4451 					name [name_len] = 0;
4452 					named += name_len;
4453 
4454 					g_assert (named_type == 0x54);
4455 					g_assert (!strcmp (name, "ExportSymbol"));
4456 
4457 					/* load_cattr_value (), string case */
4458 					g_assert (*named != (char)0xff);
4459 					slen = mono_metadata_decode_value (named, &named);
4460 					export_name = (char *)g_malloc (slen + 1);
4461 					memcpy (export_name, named, slen);
4462 					export_name [slen] = 0;
4463 					named += slen;
4464 				}
4465 
4466 				wrapper = mono_marshal_get_managed_wrapper (method, klass, 0, &error);
4467 				mono_error_assert_ok (&error);
4468 
4469 				add_method (acfg, wrapper);
4470 				if (export_name)
4471 					g_hash_table_insert (acfg->export_names, wrapper, export_name);
4472 			}
4473 			g_free (cattr);
4474 		}
4475 
4476 		if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
4477 			(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
4478 			add_method (acfg, mono_marshal_get_native_wrapper (method, TRUE, TRUE));
4479 		}
4480 	}
4481 
4482 	/* StructureToPtr/PtrToStructure wrappers */
4483 	for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
4484 		MonoError error;
4485 		MonoClass *klass;
4486 
4487 		token = MONO_TOKEN_TYPE_DEF | (i + 1);
4488 		klass = mono_class_get_checked (acfg->image, token, &error);
4489 
4490 		if (!klass) {
4491 			mono_error_cleanup (&error);
4492 			continue;
4493 		}
4494 
4495 		if (klass->valuetype && !mono_class_is_gtd (klass) && can_marshal_struct (klass) &&
4496 			!(klass->nested_in && strstr (klass->nested_in->name, "<PrivateImplementationDetails>") == klass->nested_in->name)) {
4497 			add_method (acfg, mono_marshal_get_struct_to_ptr (klass));
4498 			add_method (acfg, mono_marshal_get_ptr_to_struct (klass));
4499 		}
4500 	}
4501 }
4502 
4503 static gboolean
has_type_vars(MonoClass * klass)4504 has_type_vars (MonoClass *klass)
4505 {
4506 	if ((klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
4507 		return TRUE;
4508 	if (klass->rank)
4509 		return has_type_vars (klass->element_class);
4510 	if (mono_class_is_ginst (klass)) {
4511 		MonoGenericContext *context = &mono_class_get_generic_class (klass)->context;
4512 		if (context->class_inst) {
4513 			int i;
4514 
4515 			for (i = 0; i < context->class_inst->type_argc; ++i)
4516 				if (has_type_vars (mono_class_from_mono_type (context->class_inst->type_argv [i])))
4517 					return TRUE;
4518 		}
4519 	}
4520 	if (mono_class_is_gtd (klass))
4521 		return TRUE;
4522 	return FALSE;
4523 }
4524 
4525 static gboolean
is_vt_inst(MonoGenericInst * inst)4526 is_vt_inst (MonoGenericInst *inst)
4527 {
4528 	int i;
4529 
4530 	for (i = 0; i < inst->type_argc; ++i) {
4531 		MonoType *t = inst->type_argv [i];
4532 		if (MONO_TYPE_ISSTRUCT (t) || t->type == MONO_TYPE_VALUETYPE)
4533 			return TRUE;
4534 	}
4535 	return FALSE;
4536 }
4537 
4538 static gboolean
method_has_type_vars(MonoMethod * method)4539 method_has_type_vars (MonoMethod *method)
4540 {
4541 	if (has_type_vars (method->klass))
4542 		return TRUE;
4543 
4544 	if (method->is_inflated) {
4545 		MonoGenericContext *context = mono_method_get_context (method);
4546 		if (context->method_inst) {
4547 			int i;
4548 
4549 			for (i = 0; i < context->method_inst->type_argc; ++i)
4550 				if (has_type_vars (mono_class_from_mono_type (context->method_inst->type_argv [i])))
4551 					return TRUE;
4552 		}
4553 	}
4554 	return FALSE;
4555 }
4556 
4557 static
mono_aot_mode_is_full(MonoAotOptions * opts)4558 gboolean mono_aot_mode_is_full (MonoAotOptions *opts)
4559 {
4560 	return opts->mode == MONO_AOT_MODE_FULL || opts->mode == MONO_AOT_MODE_INTERP;
4561 }
4562 
4563 static
mono_aot_mode_is_interp(MonoAotOptions * opts)4564 gboolean mono_aot_mode_is_interp (MonoAotOptions *opts)
4565 {
4566 	return opts->mode == MONO_AOT_MODE_INTERP;
4567 }
4568 
4569 static
mono_aot_mode_is_hybrid(MonoAotOptions * opts)4570 gboolean mono_aot_mode_is_hybrid (MonoAotOptions *opts)
4571 {
4572 	return opts->mode == MONO_AOT_MODE_HYBRID;
4573 }
4574 
4575 static void add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, const char *ref);
4576 
4577 static void
add_generic_class(MonoAotCompile * acfg,MonoClass * klass,gboolean force,const char * ref)4578 add_generic_class (MonoAotCompile *acfg, MonoClass *klass, gboolean force, const char *ref)
4579 {
4580 	/* This might lead to a huge code blowup so only do it if neccesary */
4581 	if (!mono_aot_mode_is_full (&acfg->aot_opts) && !mono_aot_mode_is_hybrid (&acfg->aot_opts) && !force)
4582 		return;
4583 
4584 	add_generic_class_with_depth (acfg, klass, 0, ref);
4585 }
4586 
4587 static gboolean
check_type_depth(MonoType * t,int depth)4588 check_type_depth (MonoType *t, int depth)
4589 {
4590 	int i;
4591 
4592 	if (depth > 8)
4593 		return TRUE;
4594 
4595 	switch (t->type) {
4596 	case MONO_TYPE_GENERICINST: {
4597 		MonoGenericClass *gklass = t->data.generic_class;
4598 		MonoGenericInst *ginst = gklass->context.class_inst;
4599 
4600 		if (ginst) {
4601 			for (i = 0; i < ginst->type_argc; ++i) {
4602 				if (check_type_depth (ginst->type_argv [i], depth + 1))
4603 					return TRUE;
4604 			}
4605 		}
4606 		break;
4607 	}
4608 	default:
4609 		break;
4610 	}
4611 
4612 	return FALSE;
4613 }
4614 
4615 static void
4616 add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method);
4617 
4618 /*
4619  * add_generic_class:
4620  *
4621  *   Add all methods of a generic class.
4622  */
4623 static void
add_generic_class_with_depth(MonoAotCompile * acfg,MonoClass * klass,int depth,const char * ref)4624 add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, const char *ref)
4625 {
4626 	MonoMethod *method;
4627 	MonoClassField *field;
4628 	gpointer iter;
4629 	gboolean use_gsharedvt = FALSE;
4630 
4631 	if (!acfg->ginst_hash)
4632 		acfg->ginst_hash = g_hash_table_new (NULL, NULL);
4633 
4634 	mono_class_init (klass);
4635 
4636 	if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open)
4637 		return;
4638 
4639 	if (has_type_vars (klass))
4640 		return;
4641 
4642 	if (!mono_class_is_ginst (klass) && !klass->rank)
4643 		return;
4644 
4645 	if (mono_class_has_failure (klass))
4646 		return;
4647 
4648 	if (!acfg->ginst_hash)
4649 		acfg->ginst_hash = g_hash_table_new (NULL, NULL);
4650 
4651 	if (g_hash_table_lookup (acfg->ginst_hash, klass))
4652 		return;
4653 
4654 	if (check_type_depth (&klass->byval_arg, 0))
4655 		return;
4656 
4657 	if (acfg->aot_opts.log_generics)
4658 		aot_printf (acfg, "%*sAdding generic instance %s [%s].\n", depth, "", mono_type_full_name (&klass->byval_arg), ref);
4659 
4660 	g_hash_table_insert (acfg->ginst_hash, klass, klass);
4661 
4662 	/*
4663 	 * Use gsharedvt for generic collections with vtype arguments to avoid code blowup.
4664 	 * Enable this only for some classes since gsharedvt might not support all methods.
4665 	 */
4666 	if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst && is_vt_inst (mono_class_get_generic_class (klass)->context.class_inst) &&
4667 		(!strcmp (klass->name, "Dictionary`2") || !strcmp (klass->name, "List`1") || !strcmp (klass->name, "ReadOnlyCollection`1")))
4668 		use_gsharedvt = TRUE;
4669 
4670 	iter = NULL;
4671 	while ((method = mono_class_get_methods (klass, &iter))) {
4672 		if ((acfg->opts & MONO_OPT_GSHAREDVT) && method->is_inflated && mono_method_get_context (method)->method_inst) {
4673 			/*
4674 			 * This is partial sharing, and we can't handle it yet
4675 			 */
4676 			continue;
4677 		}
4678 
4679 		if (mono_method_is_generic_sharable_full (method, FALSE, FALSE, use_gsharedvt)) {
4680 			/* Already added */
4681 			add_types_from_method_header (acfg, method);
4682 			continue;
4683 		}
4684 
4685 		if (method->is_generic)
4686 			/* FIXME: */
4687 			continue;
4688 
4689 		/*
4690 		 * FIXME: Instances which are referenced by these methods are not added,
4691 		 * for example Array.Resize<int> for List<int>.Add ().
4692 		 */
4693 		add_extra_method_with_depth (acfg, method, depth + 1);
4694 	}
4695 
4696 	iter = NULL;
4697 	while ((field = mono_class_get_fields (klass, &iter))) {
4698 		if (field->type->type == MONO_TYPE_GENERICINST)
4699 			add_generic_class_with_depth (acfg, mono_class_from_mono_type (field->type), depth + 1, "field");
4700 	}
4701 
4702 	if (klass->delegate) {
4703 		method = mono_get_delegate_invoke (klass);
4704 
4705 		method = mono_marshal_get_delegate_invoke (method, NULL);
4706 
4707 		if (acfg->aot_opts.log_generics)
4708 			aot_printf (acfg, "%*sAdding method %s.\n", depth, "", mono_method_get_full_name (method));
4709 
4710 		add_method (acfg, method);
4711 	}
4712 
4713 	/* Add superclasses */
4714 	if (klass->parent)
4715 		add_generic_class_with_depth (acfg, klass->parent, depth, "parent");
4716 
4717 	/*
4718 	 * For ICollection<T>, add instances of the helper methods
4719 	 * in Array, since a T[] could be cast to ICollection<T>.
4720 	 */
4721 	if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") &&
4722 		(!strcmp(klass->name, "ICollection`1") || !strcmp (klass->name, "IEnumerable`1") || !strcmp (klass->name, "IList`1") || !strcmp (klass->name, "IEnumerator`1") || !strcmp (klass->name, "IReadOnlyList`1"))) {
4723 		MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
4724 		MonoClass *array_class = mono_bounded_array_class_get (tclass, 1, FALSE);
4725 		gpointer iter;
4726 		char *name_prefix;
4727 
4728 		if (!strcmp (klass->name, "IEnumerator`1"))
4729 			name_prefix = g_strdup_printf ("%s.%s", klass->name_space, "IEnumerable`1");
4730 		else
4731 			name_prefix = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
4732 
4733 		/* Add the T[]/InternalEnumerator class */
4734 		if (!strcmp (klass->name, "IEnumerable`1") || !strcmp (klass->name, "IEnumerator`1")) {
4735 			MonoError error;
4736 			MonoClass *nclass;
4737 
4738 			iter = NULL;
4739 			while ((nclass = mono_class_get_nested_types (array_class->parent, &iter))) {
4740 				if (!strcmp (nclass->name, "InternalEnumerator`1"))
4741 					break;
4742 			}
4743 			g_assert (nclass);
4744 			nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (mono_class_get_generic_class (klass)), &error);
4745 			mono_error_assert_ok (&error); /* FIXME don't swallow the error */
4746 			add_generic_class (acfg, nclass, FALSE, "ICollection<T>");
4747 		}
4748 
4749 		iter = NULL;
4750 		while ((method = mono_class_get_methods (array_class, &iter))) {
4751 			if (strstr (method->name, name_prefix)) {
4752 				MonoMethod *m = mono_aot_get_array_helper_from_wrapper (method);
4753 
4754 				add_extra_method_with_depth (acfg, m, depth);
4755 			}
4756 		}
4757 
4758 		g_free (name_prefix);
4759 	}
4760 
4761 	/* Add an instance of GenericComparer<T> which is created dynamically by Comparer<T> */
4762 	if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
4763 		MonoError error;
4764 		MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
4765 		MonoClass *icomparable, *gcomparer, *icomparable_inst;
4766 		MonoGenericContext ctx;
4767 		MonoType *args [16];
4768 
4769 		memset (&ctx, 0, sizeof (ctx));
4770 
4771 		icomparable = mono_class_load_from_name (mono_defaults.corlib, "System", "IComparable`1");
4772 
4773 		args [0] = &tclass->byval_arg;
4774 		ctx.class_inst = mono_metadata_get_generic_inst (1, args);
4775 
4776 		icomparable_inst = mono_class_inflate_generic_class_checked (icomparable, &ctx, &error);
4777 		mono_error_assert_ok (&error); /* FIXME don't swallow the error */
4778 
4779 		if (mono_class_is_assignable_from (icomparable_inst, tclass)) {
4780 			MonoClass *gcomparer_inst;
4781 			gcomparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "GenericComparer`1");
4782 			gcomparer_inst = mono_class_inflate_generic_class_checked (gcomparer, &ctx, &error);
4783 			mono_error_assert_ok (&error); /* FIXME don't swallow the error */
4784 
4785 			add_generic_class (acfg, gcomparer_inst, FALSE, "Comparer<T>");
4786 		}
4787 	}
4788 
4789 	/* Add an instance of GenericEqualityComparer<T> which is created dynamically by EqualityComparer<T> */
4790 	if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
4791 		MonoError error;
4792 		MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
4793 		MonoClass *iface, *gcomparer, *iface_inst;
4794 		MonoGenericContext ctx;
4795 		MonoType *args [16];
4796 
4797 		memset (&ctx, 0, sizeof (ctx));
4798 
4799 		iface = mono_class_load_from_name (mono_defaults.corlib, "System", "IEquatable`1");
4800 		g_assert (iface);
4801 		args [0] = &tclass->byval_arg;
4802 		ctx.class_inst = mono_metadata_get_generic_inst (1, args);
4803 
4804 		iface_inst = mono_class_inflate_generic_class_checked (iface, &ctx, &error);
4805 		mono_error_assert_ok (&error); /* FIXME don't swallow the error */
4806 
4807 		if (mono_class_is_assignable_from (iface_inst, tclass)) {
4808 			MonoClass *gcomparer_inst;
4809 			MonoError error;
4810 
4811 			gcomparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "GenericEqualityComparer`1");
4812 			gcomparer_inst = mono_class_inflate_generic_class_checked (gcomparer, &ctx, &error);
4813 			mono_error_assert_ok (&error); /* FIXME don't swallow the error */
4814 			add_generic_class (acfg, gcomparer_inst, FALSE, "EqualityComparer<T>");
4815 		}
4816 	}
4817 
4818 	/* Add an instance of EnumComparer<T> which is created dynamically by EqualityComparer<T> for enums */
4819 	if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
4820 		MonoClass *enum_comparer;
4821 		MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
4822 		MonoGenericContext ctx;
4823 		MonoType *args [16];
4824 
4825 		if (mono_class_is_enum (tclass)) {
4826 			MonoClass *enum_comparer_inst;
4827 			MonoError error;
4828 
4829 			memset (&ctx, 0, sizeof (ctx));
4830 			args [0] = &tclass->byval_arg;
4831 			ctx.class_inst = mono_metadata_get_generic_inst (1, args);
4832 
4833 			enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "EnumEqualityComparer`1");
4834 			enum_comparer_inst = mono_class_inflate_generic_class_checked (enum_comparer, &ctx, &error);
4835 			mono_error_assert_ok (&error); /* FIXME don't swallow the error */
4836 			add_generic_class (acfg, enum_comparer_inst, FALSE, "EqualityComparer<T>");
4837 		}
4838 	}
4839 
4840 	/* Add an instance of ObjectComparer<T> which is created dynamically by Comparer<T> for enums */
4841 	if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
4842 		MonoClass *comparer;
4843 		MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
4844 		MonoGenericContext ctx;
4845 		MonoType *args [16];
4846 
4847 		if (mono_class_is_enum (tclass)) {
4848 			MonoClass *comparer_inst;
4849 			MonoError error;
4850 
4851 			memset (&ctx, 0, sizeof (ctx));
4852 			args [0] = &tclass->byval_arg;
4853 			ctx.class_inst = mono_metadata_get_generic_inst (1, args);
4854 
4855 			comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "ObjectComparer`1");
4856 			comparer_inst = mono_class_inflate_generic_class_checked (comparer, &ctx, &error);
4857 			mono_error_assert_ok (&error); /* FIXME don't swallow the error */
4858 			add_generic_class (acfg, comparer_inst, FALSE, "Comparer<T>");
4859 		}
4860 	}
4861 }
4862 
4863 static void
add_instances_of(MonoAotCompile * acfg,MonoClass * klass,MonoType ** insts,int ninsts,gboolean force)4864 add_instances_of (MonoAotCompile *acfg, MonoClass *klass, MonoType **insts, int ninsts, gboolean force)
4865 {
4866 	int i;
4867 	MonoGenericContext ctx;
4868 	MonoType *args [16];
4869 
4870 	if (acfg->aot_opts.no_instances)
4871 		return;
4872 
4873 	memset (&ctx, 0, sizeof (ctx));
4874 
4875 	for (i = 0; i < ninsts; ++i) {
4876 		MonoError error;
4877 		MonoClass *generic_inst;
4878 		args [0] = insts [i];
4879 		ctx.class_inst = mono_metadata_get_generic_inst (1, args);
4880 		generic_inst = mono_class_inflate_generic_class_checked (klass, &ctx, &error);
4881 		mono_error_assert_ok (&error); /* FIXME don't swallow the error */
4882 		add_generic_class (acfg, generic_inst, force, "");
4883 	}
4884 }
4885 
4886 static void
add_types_from_method_header(MonoAotCompile * acfg,MonoMethod * method)4887 add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method)
4888 {
4889 	MonoError error;
4890 	MonoMethodHeader *header;
4891 	MonoMethodSignature *sig;
4892 	int j, depth;
4893 
4894 	depth = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_depth, method));
4895 
4896 	sig = mono_method_signature (method);
4897 
4898 	if (sig) {
4899 		for (j = 0; j < sig->param_count; ++j)
4900 			if (sig->params [j]->type == MONO_TYPE_GENERICINST)
4901 				add_generic_class_with_depth (acfg, mono_class_from_mono_type (sig->params [j]), depth + 1, "arg");
4902 	}
4903 
4904 	header = mono_method_get_header_checked (method, &error);
4905 
4906 	if (header) {
4907 		for (j = 0; j < header->num_locals; ++j)
4908 			if (header->locals [j]->type == MONO_TYPE_GENERICINST)
4909 				add_generic_class_with_depth (acfg, mono_class_from_mono_type (header->locals [j]), depth + 1, "local");
4910 		mono_metadata_free_mh (header);
4911 	} else {
4912 		mono_error_cleanup (&error); /* FIXME report the error */
4913 	}
4914 
4915 }
4916 
4917 /*
4918  * add_generic_instances:
4919  *
4920  *   Add instances referenced by the METHODSPEC/TYPESPEC table.
4921  */
4922 static void
add_generic_instances(MonoAotCompile * acfg)4923 add_generic_instances (MonoAotCompile *acfg)
4924 {
4925 	int i;
4926 	guint32 token;
4927 	MonoMethod *method;
4928 	MonoGenericContext *context;
4929 
4930 	if (acfg->aot_opts.no_instances)
4931 		return;
4932 
4933 	for (i = 0; i < acfg->image->tables [MONO_TABLE_METHODSPEC].rows; ++i) {
4934 		MonoError error;
4935 		token = MONO_TOKEN_METHOD_SPEC | (i + 1);
4936 		method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
4937 
4938 		if (!method) {
4939 			aot_printerrf (acfg, "Failed to load methodspec 0x%x due to %s.\n", token, mono_error_get_message (&error));
4940 			aot_printerrf (acfg, "Run with MONO_LOG_LEVEL=debug for more information.\n");
4941 			mono_error_cleanup (&error);
4942 			continue;
4943 		}
4944 
4945 		if (method->klass->image != acfg->image)
4946 			continue;
4947 
4948 		context = mono_method_get_context (method);
4949 
4950 		if (context && ((context->class_inst && context->class_inst->is_open)))
4951 			continue;
4952 
4953 		/*
4954 		 * For open methods, create an instantiation which can be passed to the JIT.
4955 		 * FIXME: Handle class_inst as well.
4956 		 */
4957 		if (context && context->method_inst && context->method_inst->is_open) {
4958 			MonoError error;
4959 			MonoGenericContext shared_context;
4960 			MonoGenericInst *inst;
4961 			MonoType **type_argv;
4962 			int i;
4963 			MonoMethod *declaring_method;
4964 			gboolean supported = TRUE;
4965 
4966 			/* Check that the context doesn't contain open constructed types */
4967 			if (context->class_inst) {
4968 				inst = context->class_inst;
4969 				for (i = 0; i < inst->type_argc; ++i) {
4970 					if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
4971 						continue;
4972 					if (mono_class_is_open_constructed_type (inst->type_argv [i]))
4973 						supported = FALSE;
4974 				}
4975 			}
4976 			if (context->method_inst) {
4977 				inst = context->method_inst;
4978 				for (i = 0; i < inst->type_argc; ++i) {
4979 					if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
4980 						continue;
4981 					if (mono_class_is_open_constructed_type (inst->type_argv [i]))
4982 						supported = FALSE;
4983 				}
4984 			}
4985 
4986 			if (!supported)
4987 				continue;
4988 
4989 			memset (&shared_context, 0, sizeof (MonoGenericContext));
4990 
4991 			inst = context->class_inst;
4992 			if (inst) {
4993 				type_argv = g_new0 (MonoType*, inst->type_argc);
4994 				for (i = 0; i < inst->type_argc; ++i) {
4995 					if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
4996 						type_argv [i] = &mono_defaults.object_class->byval_arg;
4997 					else
4998 						type_argv [i] = inst->type_argv [i];
4999 				}
5000 
5001 				shared_context.class_inst = mono_metadata_get_generic_inst (inst->type_argc, type_argv);
5002 				g_free (type_argv);
5003 			}
5004 
5005 			inst = context->method_inst;
5006 			if (inst) {
5007 				type_argv = g_new0 (MonoType*, inst->type_argc);
5008 				for (i = 0; i < inst->type_argc; ++i) {
5009 					if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
5010 						type_argv [i] = &mono_defaults.object_class->byval_arg;
5011 					else
5012 						type_argv [i] = inst->type_argv [i];
5013 				}
5014 
5015 				shared_context.method_inst = mono_metadata_get_generic_inst (inst->type_argc, type_argv);
5016 				g_free (type_argv);
5017 			}
5018 
5019 			if (method->is_generic || mono_class_is_gtd (method->klass))
5020 				declaring_method = method;
5021 			else
5022 				declaring_method = mono_method_get_declaring_generic_method (method);
5023 
5024 			method = mono_class_inflate_generic_method_checked (declaring_method, &shared_context, &error);
5025 			g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5026 		}
5027 
5028 		/*
5029 		 * If the method is fully sharable, it was already added in place of its
5030 		 * generic definition.
5031 		 */
5032 		if (mono_method_is_generic_sharable_full (method, FALSE, FALSE, FALSE))
5033 			continue;
5034 
5035 		/*
5036 		 * FIXME: Partially shared methods are not shared here, so we end up with
5037 		 * many identical methods.
5038 		 */
5039 		add_extra_method (acfg, method);
5040 	}
5041 
5042 	for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
5043 		MonoError error;
5044 		MonoClass *klass;
5045 
5046 		token = MONO_TOKEN_TYPE_SPEC | (i + 1);
5047 
5048 		klass = mono_class_get_checked (acfg->image, token, &error);
5049 		if (!klass || klass->rank) {
5050 			mono_error_cleanup (&error);
5051 			continue;
5052 		}
5053 
5054 		add_generic_class (acfg, klass, FALSE, "typespec");
5055 	}
5056 
5057 	/* Add types of args/locals */
5058 	for (i = 0; i < acfg->methods->len; ++i) {
5059 		method = (MonoMethod *)g_ptr_array_index (acfg->methods, i);
5060 		add_types_from_method_header (acfg, method);
5061 	}
5062 
5063 	if (acfg->image == mono_defaults.corlib) {
5064 		MonoClass *klass;
5065 		MonoType *insts [256];
5066 		int ninsts = 0;
5067 
5068 		insts [ninsts ++] = &mono_defaults.byte_class->byval_arg;
5069 		insts [ninsts ++] = &mono_defaults.sbyte_class->byval_arg;
5070 		insts [ninsts ++] = &mono_defaults.int16_class->byval_arg;
5071 		insts [ninsts ++] = &mono_defaults.uint16_class->byval_arg;
5072 		insts [ninsts ++] = &mono_defaults.int32_class->byval_arg;
5073 		insts [ninsts ++] = &mono_defaults.uint32_class->byval_arg;
5074 		insts [ninsts ++] = &mono_defaults.int64_class->byval_arg;
5075 		insts [ninsts ++] = &mono_defaults.uint64_class->byval_arg;
5076 		insts [ninsts ++] = &mono_defaults.single_class->byval_arg;
5077 		insts [ninsts ++] = &mono_defaults.double_class->byval_arg;
5078 		insts [ninsts ++] = &mono_defaults.char_class->byval_arg;
5079 		insts [ninsts ++] = &mono_defaults.boolean_class->byval_arg;
5080 
5081 		/* Add GenericComparer<T> instances for primitive types for Enum.ToString () */
5082 		klass = mono_class_try_load_from_name (acfg->image, "System.Collections.Generic", "GenericComparer`1");
5083 		if (klass)
5084 			add_instances_of (acfg, klass, insts, ninsts, TRUE);
5085 		klass = mono_class_try_load_from_name (acfg->image, "System.Collections.Generic", "GenericEqualityComparer`1");
5086 		if (klass)
5087 			add_instances_of (acfg, klass, insts, ninsts, TRUE);
5088 
5089 		/* Add instances of EnumEqualityComparer which are created by EqualityComparer<T> for enums */
5090 		{
5091 			MonoClass *enum_comparer;
5092 			MonoType *insts [16];
5093 			int ninsts;
5094 
5095 			ninsts = 0;
5096 			insts [ninsts ++] = &mono_defaults.int32_class->byval_arg;
5097 			insts [ninsts ++] = &mono_defaults.uint32_class->byval_arg;
5098 			insts [ninsts ++] = &mono_defaults.uint16_class->byval_arg;
5099 			insts [ninsts ++] = &mono_defaults.byte_class->byval_arg;
5100 			enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "EnumEqualityComparer`1");
5101 			add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE);
5102 
5103 			ninsts = 0;
5104 			insts [ninsts ++] = &mono_defaults.int16_class->byval_arg;
5105 			enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "ShortEnumEqualityComparer`1");
5106 			add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE);
5107 
5108 			ninsts = 0;
5109 			insts [ninsts ++] = &mono_defaults.sbyte_class->byval_arg;
5110 			enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "SByteEnumEqualityComparer`1");
5111 			add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE);
5112 
5113 			enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "LongEnumEqualityComparer`1");
5114 			ninsts = 0;
5115 			insts [ninsts ++] = &mono_defaults.int64_class->byval_arg;
5116 			insts [ninsts ++] = &mono_defaults.uint64_class->byval_arg;
5117 			add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE);
5118 		}
5119 
5120 		/* Add instances of the array generic interfaces for primitive types */
5121 		/* This will add instances of the InternalArray_ helper methods in Array too */
5122 		klass = mono_class_try_load_from_name (acfg->image, "System.Collections.Generic", "ICollection`1");
5123 		if (klass)
5124 			add_instances_of (acfg, klass, insts, ninsts, TRUE);
5125 
5126 		klass = mono_class_try_load_from_name (acfg->image, "System.Collections.Generic", "IList`1");
5127 		if (klass)
5128 			add_instances_of (acfg, klass, insts, ninsts, TRUE);
5129 
5130 		klass = mono_class_try_load_from_name (acfg->image, "System.Collections.Generic", "IEnumerable`1");
5131 		if (klass)
5132 			add_instances_of (acfg, klass, insts, ninsts, TRUE);
5133 
5134 		/*
5135 		 * Add a managed-to-native wrapper of Array.GetGenericValueImpl<object>, which is
5136 		 * used for all instances of GetGenericValueImpl by the AOT runtime.
5137 		 */
5138 		{
5139 			MonoGenericContext ctx;
5140 			MonoType *args [16];
5141 			MonoMethod *get_method;
5142 			MonoClass *array_klass = mono_array_class_get (mono_defaults.object_class, 1)->parent;
5143 
5144 			get_method = mono_class_get_method_from_name (array_klass, "GetGenericValueImpl", 2);
5145 
5146 			if (get_method) {
5147 				MonoError error;
5148 				memset (&ctx, 0, sizeof (ctx));
5149 				args [0] = &mono_defaults.object_class->byval_arg;
5150 				ctx.method_inst = mono_metadata_get_generic_inst (1, args);
5151 				add_extra_method (acfg, mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (get_method, &ctx, &error), TRUE, TRUE));
5152 				g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5153 			}
5154 		}
5155 
5156 		/* Same for CompareExchange<T>/Exchange<T> */
5157 		{
5158 			MonoGenericContext ctx;
5159 			MonoType *args [16];
5160 			MonoMethod *m;
5161 			MonoClass *interlocked_klass = mono_class_load_from_name (mono_defaults.corlib, "System.Threading", "Interlocked");
5162 			gpointer iter = NULL;
5163 
5164 			while ((m = mono_class_get_methods (interlocked_klass, &iter))) {
5165 				if ((!strcmp (m->name, "CompareExchange") || !strcmp (m->name, "Exchange")) && m->is_generic) {
5166 					MonoError error;
5167 					memset (&ctx, 0, sizeof (ctx));
5168 					args [0] = &mono_defaults.object_class->byval_arg;
5169 					ctx.method_inst = mono_metadata_get_generic_inst (1, args);
5170 					add_extra_method (acfg, mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, &error), TRUE, TRUE));
5171 					g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5172 				}
5173 			}
5174 		}
5175 
5176 		/* Same for Volatile.Read/Write<T> */
5177 		{
5178 			MonoGenericContext ctx;
5179 			MonoType *args [16];
5180 			MonoMethod *m;
5181 			MonoClass *volatile_klass = mono_class_try_load_from_name (mono_defaults.corlib, "System.Threading", "Volatile");
5182 			gpointer iter = NULL;
5183 
5184 			if (volatile_klass) {
5185 				while ((m = mono_class_get_methods (volatile_klass, &iter))) {
5186 					if ((!strcmp (m->name, "Read") || !strcmp (m->name, "Write")) && m->is_generic) {
5187 						MonoError error;
5188 						memset (&ctx, 0, sizeof (ctx));
5189 						args [0] = &mono_defaults.object_class->byval_arg;
5190 						ctx.method_inst = mono_metadata_get_generic_inst (1, args);
5191 						add_extra_method (acfg, mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, &error), TRUE, TRUE));
5192 						g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5193 					}
5194 				}
5195 			}
5196 		}
5197 
5198 		/* object[] accessor wrappers. */
5199 		for (i = 1; i < 4; ++i) {
5200 			MonoClass *obj_array_class = mono_array_class_get (mono_defaults.object_class, i);
5201 			MonoMethod *m;
5202 
5203 			m = mono_class_get_method_from_name (obj_array_class, "Get", i);
5204 			g_assert (m);
5205 
5206 			m = mono_marshal_get_array_accessor_wrapper (m);
5207 			add_extra_method (acfg, m);
5208 
5209 			m = mono_class_get_method_from_name (obj_array_class, "Address", i);
5210 			g_assert (m);
5211 
5212 			m = mono_marshal_get_array_accessor_wrapper (m);
5213 			add_extra_method (acfg, m);
5214 
5215 			m = mono_class_get_method_from_name (obj_array_class, "Set", i + 1);
5216 			g_assert (m);
5217 
5218 			m = mono_marshal_get_array_accessor_wrapper (m);
5219 			add_extra_method (acfg, m);
5220 		}
5221 	}
5222 }
5223 
5224 /*
5225  * is_direct_callable:
5226  *
5227  *   Return whenever the method identified by JI is directly callable without
5228  * going through the PLT.
5229  */
5230 static gboolean
is_direct_callable(MonoAotCompile * acfg,MonoMethod * method,MonoJumpInfo * patch_info)5231 is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patch_info)
5232 {
5233 	if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == acfg->image)) {
5234 		MonoCompile *callee_cfg = (MonoCompile *)g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
5235 		if (callee_cfg) {
5236 			gboolean direct_callable = TRUE;
5237 
5238 			if (direct_callable && (acfg->aot_opts.dedup || acfg->aot_opts.dedup_include) && mono_aot_can_dedup (patch_info->data.method))
5239 				direct_callable = FALSE;
5240 
5241 			if (direct_callable && !(!callee_cfg->has_got_slots && mono_class_is_before_field_init (callee_cfg->method->klass)))
5242 				direct_callable = FALSE;
5243 			if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && (!method || method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED))
5244 				// FIXME: Maybe call the wrapper directly ?
5245 				direct_callable = FALSE;
5246 
5247 			if (acfg->aot_opts.soft_debug || acfg->aot_opts.no_direct_calls) {
5248 				/* Disable this so all calls go through load_method (), see the
5249 				 * mini_get_debug_options ()->load_aot_jit_info_eagerly = TRUE; line in
5250 				 * mono_debugger_agent_init ().
5251 				 */
5252 				direct_callable = FALSE;
5253 			}
5254 
5255 			if (callee_cfg->method->wrapper_type == MONO_WRAPPER_ALLOC)
5256 				/* sgen does some initialization when the allocator method is created */
5257 				direct_callable = FALSE;
5258 			if (callee_cfg->method->wrapper_type == MONO_WRAPPER_WRITE_BARRIER)
5259 				/* we don't know at compile time whether sgen is concurrent or not */
5260 				direct_callable = FALSE;
5261 
5262 			if (direct_callable)
5263 				return TRUE;
5264 		}
5265 	} else if ((patch_info->type == MONO_PATCH_INFO_ICALL_ADDR_CALL && patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
5266 		if (acfg->aot_opts.direct_pinvoke)
5267 			return TRUE;
5268 	} else if (patch_info->type == MONO_PATCH_INFO_ICALL_ADDR_CALL) {
5269 		if (acfg->aot_opts.direct_icalls)
5270 			return TRUE;
5271 		return FALSE;
5272 	}
5273 
5274 	return FALSE;
5275 }
5276 
5277 #ifdef MONO_ARCH_AOT_SUPPORTED
5278 static const char *
get_pinvoke_import(MonoAotCompile * acfg,MonoMethod * method)5279 get_pinvoke_import (MonoAotCompile *acfg, MonoMethod *method)
5280 {
5281 	MonoImage *image = method->klass->image;
5282 	MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *) method;
5283 	MonoTableInfo *tables = image->tables;
5284 	MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
5285 	MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
5286 	guint32 im_cols [MONO_IMPLMAP_SIZE];
5287 	char *import;
5288 
5289 	import = (char *)g_hash_table_lookup (acfg->method_to_pinvoke_import, method);
5290 	if (import != NULL)
5291 		return import;
5292 
5293 	if (!piinfo->implmap_idx || piinfo->implmap_idx > im->rows)
5294 		return NULL;
5295 
5296 	mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
5297 
5298 	if (!im_cols [MONO_IMPLMAP_SCOPE] || im_cols [MONO_IMPLMAP_SCOPE] > mr->rows)
5299 		return NULL;
5300 
5301 	import = g_strdup_printf ("%s", mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]));
5302 
5303 	g_hash_table_insert (acfg->method_to_pinvoke_import, method, import);
5304 
5305 	return import;
5306 }
5307 #else
5308 static const char *
get_pinvoke_import(MonoAotCompile * acfg,MonoMethod * method)5309 get_pinvoke_import (MonoAotCompile *acfg, MonoMethod *method)
5310 {
5311 	return NULL;
5312 }
5313 #endif
5314 
5315 static gint
compare_lne(MonoDebugLineNumberEntry * a,MonoDebugLineNumberEntry * b)5316 compare_lne (MonoDebugLineNumberEntry *a, MonoDebugLineNumberEntry *b)
5317 {
5318 	if (a->native_offset == b->native_offset)
5319 		return a->il_offset - b->il_offset;
5320 	else
5321 		return a->native_offset - b->native_offset;
5322 }
5323 
5324 /*
5325  * compute_line_numbers:
5326  *
5327  * Returns a sparse array of size CODE_SIZE containing MonoDebugSourceLocation* entries for the native offsets which have a corresponding line number
5328  * entry.
5329  */
5330 static MonoDebugSourceLocation**
compute_line_numbers(MonoMethod * method,int code_size,MonoDebugMethodJitInfo * debug_info)5331 compute_line_numbers (MonoMethod *method, int code_size, MonoDebugMethodJitInfo *debug_info)
5332 {
5333 	MonoDebugMethodInfo *minfo;
5334 	MonoDebugLineNumberEntry *ln_array;
5335 	MonoDebugSourceLocation *loc;
5336 	int i, prev_line, prev_il_offset;
5337 	int *native_to_il_offset = NULL;
5338 	MonoDebugSourceLocation **res;
5339 	gboolean first;
5340 
5341 	minfo = mono_debug_lookup_method (method);
5342 	if (!minfo)
5343 		return NULL;
5344 	// FIXME: This seems to happen when two methods have the same cfg->method_to_register
5345 	if (debug_info->code_size != code_size)
5346 		return NULL;
5347 
5348 	g_assert (code_size);
5349 
5350 	/* Compute the native->IL offset mapping */
5351 
5352 	ln_array = g_new0 (MonoDebugLineNumberEntry, debug_info->num_line_numbers);
5353 	memcpy (ln_array, debug_info->line_numbers, debug_info->num_line_numbers * sizeof (MonoDebugLineNumberEntry));
5354 
5355 	qsort (ln_array, debug_info->num_line_numbers, sizeof (MonoDebugLineNumberEntry), (int (*)(const void *, const void *))compare_lne);
5356 
5357 	native_to_il_offset = g_new0 (int, code_size + 1);
5358 
5359 	for (i = 0; i < debug_info->num_line_numbers; ++i) {
5360 		int j;
5361 		MonoDebugLineNumberEntry *lne = &ln_array [i];
5362 
5363 		if (i == 0) {
5364 			for (j = 0; j < lne->native_offset; ++j)
5365 				native_to_il_offset [j] = -1;
5366 		}
5367 
5368 		if (i < debug_info->num_line_numbers - 1) {
5369 			MonoDebugLineNumberEntry *lne_next = &ln_array [i + 1];
5370 
5371 			for (j = lne->native_offset; j < lne_next->native_offset; ++j)
5372 				native_to_il_offset [j] = lne->il_offset;
5373 		} else {
5374 			for (j = lne->native_offset; j < code_size; ++j)
5375 				native_to_il_offset [j] = lne->il_offset;
5376 		}
5377 	}
5378 	g_free (ln_array);
5379 
5380 	/* Compute the native->line number mapping */
5381 	res = g_new0 (MonoDebugSourceLocation*, code_size);
5382 	prev_il_offset = -1;
5383 	prev_line = -1;
5384 	first = TRUE;
5385 	for (i = 0; i < code_size; ++i) {
5386 		int il_offset = native_to_il_offset [i];
5387 
5388 		if (il_offset == -1 || il_offset == prev_il_offset)
5389 			continue;
5390 		prev_il_offset = il_offset;
5391 		loc = mono_debug_method_lookup_location (minfo, il_offset);
5392 		if (!(loc && loc->source_file))
5393 			continue;
5394 		if (loc->row == prev_line) {
5395 			mono_debug_free_source_location (loc);
5396 			continue;
5397 		}
5398 		prev_line = loc->row;
5399 		//printf ("D: %s:%d il=%x native=%x\n", loc->source_file, loc->row, il_offset, i);
5400 		if (first)
5401 			/* This will cover the prolog too */
5402 			res [0] = loc;
5403 		else
5404 			res [i] = loc;
5405 		first = FALSE;
5406 	}
5407 	return res;
5408 }
5409 
5410 static int
get_file_index(MonoAotCompile * acfg,const char * source_file)5411 get_file_index (MonoAotCompile *acfg, const char *source_file)
5412 {
5413 	int findex;
5414 
5415 	// FIXME: Free these
5416 	if (!acfg->dwarf_ln_filenames)
5417 		acfg->dwarf_ln_filenames = g_hash_table_new (g_str_hash, g_str_equal);
5418 	findex = GPOINTER_TO_INT (g_hash_table_lookup (acfg->dwarf_ln_filenames, source_file));
5419 	if (!findex) {
5420 		findex = g_hash_table_size (acfg->dwarf_ln_filenames) + 1;
5421 		g_hash_table_insert (acfg->dwarf_ln_filenames, g_strdup (source_file), GINT_TO_POINTER (findex));
5422 		emit_unset_mode (acfg);
5423 		fprintf (acfg->fp, ".file %d \"%s\"\n", findex, mono_dwarf_escape_path (source_file));
5424 	}
5425 	return findex;
5426 }
5427 
5428 #ifdef TARGET_ARM64
5429 #define INST_LEN 4
5430 #else
5431 #define INST_LEN 1
5432 #endif
5433 
5434 /*
5435  * emit_and_reloc_code:
5436  *
5437  *   Emit the native code in CODE, handling relocations along the way. If GOT_ONLY
5438  * is true, calls are made through the GOT too. This is used for emitting trampolines
5439  * in full-aot mode, since calls made from trampolines couldn't go through the PLT,
5440  * since trampolines are needed to make PTL work.
5441  */
5442 static void
emit_and_reloc_code(MonoAotCompile * acfg,MonoMethod * method,guint8 * code,guint32 code_len,MonoJumpInfo * relocs,gboolean got_only,MonoDebugMethodJitInfo * debug_info)5443 emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, guint32 code_len, MonoJumpInfo *relocs, gboolean got_only, MonoDebugMethodJitInfo *debug_info)
5444 {
5445 	int i, pindex, start_index;
5446 	GPtrArray *patches;
5447 	MonoJumpInfo *patch_info;
5448 	MonoDebugSourceLocation **locs = NULL;
5449 	gboolean skip, prologue_end = FALSE;
5450 #ifdef MONO_ARCH_AOT_SUPPORTED
5451 	gboolean direct_call, external_call;
5452 	guint32 got_slot;
5453 	const char *direct_call_target = 0;
5454 	const char *direct_pinvoke;
5455 #endif
5456 
5457 	if (acfg->gas_line_numbers && method && debug_info) {
5458 		locs = compute_line_numbers (method, code_len, debug_info);
5459 		if (!locs) {
5460 			int findex = get_file_index (acfg, "<unknown>");
5461 			emit_unset_mode (acfg);
5462 			fprintf (acfg->fp, ".loc %d %d 0\n", findex, 1);
5463 		}
5464 	}
5465 
5466 	/* Collect and sort relocations */
5467 	patches = g_ptr_array_new ();
5468 	for (patch_info = relocs; patch_info; patch_info = patch_info->next)
5469 		g_ptr_array_add (patches, patch_info);
5470 	g_ptr_array_sort (patches, compare_patches);
5471 
5472 	start_index = 0;
5473 	for (i = 0; i < code_len; i += INST_LEN) {
5474 		patch_info = NULL;
5475 		for (pindex = start_index; pindex < patches->len; ++pindex) {
5476 			patch_info = (MonoJumpInfo *)g_ptr_array_index (patches, pindex);
5477 			if (patch_info->ip.i >= i)
5478 				break;
5479 		}
5480 
5481 		if (locs && locs [i]) {
5482 			MonoDebugSourceLocation *loc = locs [i];
5483 			int findex;
5484 			const char *options;
5485 
5486 			findex = get_file_index (acfg, loc->source_file);
5487 			emit_unset_mode (acfg);
5488 			if (!prologue_end)
5489 				options = " prologue_end";
5490 			else
5491 				options = "";
5492 			prologue_end = TRUE;
5493 			fprintf (acfg->fp, ".loc %d %d 0%s\n", findex, loc->row, options);
5494 			mono_debug_free_source_location (loc);
5495 		}
5496 
5497 		skip = FALSE;
5498 #ifdef MONO_ARCH_AOT_SUPPORTED
5499 		if (patch_info && (patch_info->ip.i == i) && (pindex < patches->len)) {
5500 			start_index = pindex;
5501 
5502 			switch (patch_info->type) {
5503 			case MONO_PATCH_INFO_NONE:
5504 				break;
5505 			case MONO_PATCH_INFO_GOT_OFFSET: {
5506 				int code_size;
5507 
5508 				arch_emit_got_offset (acfg, code + i, &code_size);
5509 				i += code_size - INST_LEN;
5510 				skip = TRUE;
5511 				patch_info->type = MONO_PATCH_INFO_NONE;
5512 				break;
5513 			}
5514 			case MONO_PATCH_INFO_OBJC_SELECTOR_REF: {
5515 				int code_size, index;
5516 				char *selector = (char *)patch_info->data.target;
5517 
5518 				if (!acfg->objc_selector_to_index)
5519 					acfg->objc_selector_to_index = g_hash_table_new (g_str_hash, g_str_equal);
5520 				if (!acfg->objc_selectors)
5521 					acfg->objc_selectors = g_ptr_array_new ();
5522 				index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->objc_selector_to_index, selector));
5523 				if (index)
5524 					index --;
5525 				else {
5526 					index = acfg->objc_selector_index;
5527 					g_ptr_array_add (acfg->objc_selectors, (void*)patch_info->data.target);
5528 					g_hash_table_insert (acfg->objc_selector_to_index, selector, GUINT_TO_POINTER (index + 1));
5529 					acfg->objc_selector_index ++;
5530 				}
5531 
5532 				arch_emit_objc_selector_ref (acfg, code + i, index, &code_size);
5533 				i += code_size - INST_LEN;
5534 				skip = TRUE;
5535 				patch_info->type = MONO_PATCH_INFO_NONE;
5536 				break;
5537 			}
5538 			default: {
5539 				/*
5540 				 * If this patch is a call, try emitting a direct call instead of
5541 				 * through a PLT entry. This is possible if the called method is in
5542 				 * the same assembly and requires no initialization.
5543 				 */
5544 				direct_call = FALSE;
5545 				external_call = FALSE;
5546 				if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == acfg->image)) {
5547 					if (!got_only && is_direct_callable (acfg, method, patch_info)) {
5548 						MonoCompile *callee_cfg = (MonoCompile *)g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
5549 
5550 						// Don't compile inflated methods if we're doing dedup
5551 						if (acfg->aot_opts.dedup && !mono_aot_can_dedup (patch_info->data.method)) {
5552 							char *name = mono_aot_get_mangled_method_name (patch_info->data.method);
5553 							mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "DIRECT CALL: %s by %s", name, method ? mono_method_full_name (method, TRUE) : "");
5554 							g_free (name);
5555 
5556 							direct_call = TRUE;
5557 							direct_call_target = callee_cfg->asm_symbol;
5558 							patch_info->type = MONO_PATCH_INFO_NONE;
5559 							acfg->stats.direct_calls ++;
5560 						}
5561 					}
5562 
5563 					acfg->stats.all_calls ++;
5564 				} else if (patch_info->type == MONO_PATCH_INFO_ICALL_ADDR_CALL) {
5565 					if (!got_only && is_direct_callable (acfg, method, patch_info)) {
5566 						if (!(patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
5567 							direct_pinvoke = mono_lookup_icall_symbol (patch_info->data.method);
5568 						else
5569 							direct_pinvoke = get_pinvoke_import (acfg, patch_info->data.method);
5570 						if (direct_pinvoke) {
5571 							direct_call = TRUE;
5572 							g_assert (strlen (direct_pinvoke) < 1000);
5573 							direct_call_target = g_strdup_printf ("%s%s", acfg->user_symbol_prefix, direct_pinvoke);
5574 						}
5575 					}
5576 				} else if (patch_info->type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
5577 					const char *sym = mono_lookup_jit_icall_symbol (patch_info->data.name);
5578 					if (!got_only && sym && acfg->aot_opts.direct_icalls) {
5579 						/* Call to a C function implementing a jit icall */
5580 						direct_call = TRUE;
5581 						external_call = TRUE;
5582 						g_assert (strlen (sym) < 1000);
5583 						direct_call_target = g_strdup_printf ("%s%s", acfg->user_symbol_prefix, sym);
5584 					}
5585 				} else if (patch_info->type == MONO_PATCH_INFO_INTERNAL_METHOD) {
5586 					MonoJitICallInfo *info = mono_find_jit_icall_by_name (patch_info->data.name);
5587 					const char *sym = mono_lookup_jit_icall_symbol (patch_info->data.name);
5588 					if (!got_only && sym && acfg->aot_opts.direct_icalls && info->func == info->wrapper) {
5589 						/* Call to a jit icall without a wrapper */
5590 						direct_call = TRUE;
5591 						external_call = TRUE;
5592 						g_assert (strlen (sym) < 1000);
5593 						direct_call_target = g_strdup_printf ("%s%s", acfg->user_symbol_prefix, sym);
5594 					}
5595 				}
5596 
5597 				if (direct_call) {
5598 					patch_info->type = MONO_PATCH_INFO_NONE;
5599 					acfg->stats.direct_calls ++;
5600 				}
5601 
5602 				if (!got_only && !direct_call) {
5603 					MonoPltEntry *plt_entry = get_plt_entry (acfg, patch_info);
5604 					if (plt_entry) {
5605 						/* This patch has a PLT entry, so we must emit a call to the PLT entry */
5606 						direct_call = TRUE;
5607 						direct_call_target = plt_entry->symbol;
5608 
5609 						/* Nullify the patch */
5610 						patch_info->type = MONO_PATCH_INFO_NONE;
5611 						plt_entry->jit_used = TRUE;
5612 					}
5613 				}
5614 
5615 				if (direct_call) {
5616 					int call_size;
5617 
5618 					arch_emit_direct_call (acfg, direct_call_target, external_call, FALSE, patch_info, &call_size);
5619 					i += call_size - INST_LEN;
5620 				} else {
5621 					int code_size;
5622 
5623 					got_slot = get_got_offset (acfg, FALSE, patch_info);
5624 
5625 					arch_emit_got_access (acfg, acfg->got_symbol, code + i, got_slot, &code_size);
5626 					i += code_size - INST_LEN;
5627 				}
5628 				skip = TRUE;
5629 			}
5630 			}
5631 		}
5632 #endif /* MONO_ARCH_AOT_SUPPORTED */
5633 
5634 		if (!skip) {
5635 			/* Find next patch */
5636 			patch_info = NULL;
5637 			for (pindex = start_index; pindex < patches->len; ++pindex) {
5638 				patch_info = (MonoJumpInfo *)g_ptr_array_index (patches, pindex);
5639 				if (patch_info->ip.i >= i)
5640 					break;
5641 			}
5642 
5643 			/* Try to emit multiple bytes at once */
5644 			if (pindex < patches->len && patch_info->ip.i > i) {
5645 				int limit;
5646 
5647 				for (limit = i + INST_LEN; limit < patch_info->ip.i; limit += INST_LEN) {
5648 					if (locs && locs [limit])
5649 						break;
5650 				}
5651 
5652 				emit_code_bytes (acfg, code + i, limit - i);
5653 				i = limit - INST_LEN;
5654 			} else {
5655 				emit_code_bytes (acfg, code + i, INST_LEN);
5656 			}
5657 		}
5658 	}
5659 
5660 	g_ptr_array_free (patches, TRUE);
5661 	g_free (locs);
5662 }
5663 
5664 /*
5665  * sanitize_symbol:
5666  *
5667  *   Return a modified version of S which only includes characters permissible in symbols.
5668  */
5669 static char*
sanitize_symbol(MonoAotCompile * acfg,char * s)5670 sanitize_symbol (MonoAotCompile *acfg, char *s)
5671 {
5672 	gboolean process = FALSE;
5673 	int i, len;
5674 	GString *gs;
5675 	char *res;
5676 
5677 	if (!s)
5678 		return s;
5679 
5680 	len = strlen (s);
5681 	for (i = 0; i < len; ++i)
5682 		if (!(s [i] <= 0x7f && (isalnum (s [i]) || s [i] == '_')))
5683 			process = TRUE;
5684 	if (!process)
5685 		return s;
5686 
5687 	gs = g_string_sized_new (len);
5688 	for (i = 0; i < len; ++i) {
5689 		guint8 c = s [i];
5690 		if (c <= 0x7f && (isalnum (c) || c == '_')) {
5691 			g_string_append_c (gs, c);
5692 		} else if (c > 0x7f) {
5693 			/* multi-byte utf8 */
5694 			g_string_append_printf (gs, "_0x%x", c);
5695 			i ++;
5696 			c = s [i];
5697 			while (c >> 6 == 0x2) {
5698 				g_string_append_printf (gs, "%x", c);
5699 				i ++;
5700 				c = s [i];
5701 			}
5702 			g_string_append_printf (gs, "_");
5703 			i --;
5704 		} else {
5705 			g_string_append_c (gs, '_');
5706 		}
5707 	}
5708 
5709 	res = mono_mempool_strdup (acfg->mempool, gs->str);
5710 	g_string_free (gs, TRUE);
5711 	return res;
5712 }
5713 
5714 static char*
get_debug_sym(MonoMethod * method,const char * prefix,GHashTable * cache)5715 get_debug_sym (MonoMethod *method, const char *prefix, GHashTable *cache)
5716 {
5717 	char *name1, *name2, *cached;
5718 	int i, j, len, count;
5719 	MonoMethod *cached_method;
5720 
5721 	name1 = mono_method_full_name (method, TRUE);
5722 
5723 #ifdef TARGET_MACH
5724 	// This is so that we don't accidentally create a local symbol (which starts with 'L')
5725 	if ((!prefix || !*prefix) && name1 [0] == 'L')
5726 		prefix = "_";
5727 #endif
5728 
5729 #if defined(TARGET_WIN32) && defined(TARGET_X86)
5730 	char adjustedPrefix [MAX_SYMBOL_SIZE];
5731 	prefix = mangle_symbol (prefix, adjustedPrefix, G_N_ELEMENTS (adjustedPrefix));
5732 #endif
5733 
5734 	len = strlen (name1);
5735 	name2 = (char *)malloc (strlen (prefix) + len + 16);
5736 	memcpy (name2, prefix, strlen (prefix));
5737 	j = strlen (prefix);
5738 	for (i = 0; i < len; ++i) {
5739 		if (i == 0 && name1 [0] >= '0' && name1 [0] <= '9') {
5740 			name2 [j ++] = '_';
5741 		} else if (isalnum (name1 [i])) {
5742 			name2 [j ++] = name1 [i];
5743 		} else if (name1 [i] == ' ' && name1 [i + 1] == '(' && name1 [i + 2] == ')') {
5744 			i += 2;
5745 		} else if (name1 [i] == ',' && name1 [i + 1] == ' ') {
5746 			name2 [j ++] = '_';
5747 			i++;
5748 		} else if (name1 [i] == '(' || name1 [i] == ')' || name1 [i] == '>') {
5749 		} else
5750 			name2 [j ++] = '_';
5751 	}
5752 	name2 [j] = '\0';
5753 
5754 	g_free (name1);
5755 
5756 	count = 0;
5757 	while (TRUE) {
5758 		cached_method = (MonoMethod *)g_hash_table_lookup (cache, name2);
5759 		if (!(cached_method && cached_method != method))
5760 			break;
5761 		sprintf (name2 + j, "_%d", count);
5762 		count ++;
5763 	}
5764 
5765 	cached = g_strdup (name2);
5766 	g_hash_table_insert (cache, cached, method);
5767 
5768 	return name2;
5769 }
5770 
5771 static void
emit_method_code(MonoAotCompile * acfg,MonoCompile * cfg)5772 emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
5773 {
5774 	MonoMethod *method;
5775 	int method_index;
5776 	guint8 *code;
5777 	char *debug_sym = NULL;
5778 	char *symbol = NULL;
5779 	int func_alignment = AOT_FUNC_ALIGNMENT;
5780 	char *export_name;
5781 
5782 	g_assert (!ignore_cfg (cfg));
5783 
5784 	method = cfg->orig_method;
5785 	code = cfg->native_code;
5786 
5787 	method_index = get_method_index (acfg, method);
5788 	symbol = g_strdup_printf ("%sme_%x", acfg->temp_prefix, method_index);
5789 
5790 	/* Make the labels local */
5791 	emit_section_change (acfg, ".text", 0);
5792 	emit_alignment_code (acfg, func_alignment);
5793 
5794 	if (acfg->global_symbols && acfg->need_no_dead_strip)
5795 		fprintf (acfg->fp, "	.no_dead_strip %s\n", cfg->asm_symbol);
5796 
5797 	emit_label (acfg, cfg->asm_symbol);
5798 
5799 	if (acfg->aot_opts.write_symbols && !acfg->global_symbols && !acfg->llvm) {
5800 		/*
5801 		 * Write a C style symbol for every method, this has two uses:
5802 		 * - it works on platforms where the dwarf debugging info is not
5803 		 *   yet supported.
5804 		 * - it allows the setting of breakpoints of aot-ed methods.
5805 		 */
5806 
5807 		// Comment out to force dedup to link these symbols and forbid compiling
5808 		// in duplicated code. This is an "assert when linking if broken" trick.
5809 		/*if (mono_aot_can_dedup (method) && (acfg->aot_opts.dedup || acfg->aot_opts.dedup_include))*/
5810 			/*debug_sym = mono_aot_get_mangled_method_name (method);*/
5811 		/*else*/
5812 			debug_sym = get_debug_sym (method, "", acfg->method_label_hash);
5813 
5814 		cfg->asm_debug_symbol = g_strdup (debug_sym);
5815 
5816 		if (acfg->need_no_dead_strip)
5817 			fprintf (acfg->fp, "	.no_dead_strip %s\n", debug_sym);
5818 
5819 		// Comment out to force dedup to link these symbols and forbid compiling
5820 		// in duplicated code. This is an "assert when linking if broken" trick.
5821 		/*if (mono_aot_can_dedup (method) && (acfg->aot_opts.dedup || acfg->aot_opts.dedup_include))*/
5822 			/*emit_global_inner (acfg, debug_sym, TRUE);*/
5823 		/*else*/
5824 			emit_local_symbol (acfg, debug_sym, symbol, TRUE);
5825 
5826 		emit_label (acfg, debug_sym);
5827 	}
5828 
5829 	export_name = (char *)g_hash_table_lookup (acfg->export_names, method);
5830 	if (export_name) {
5831 		/* Emit a global symbol for the method */
5832 		emit_global_inner (acfg, export_name, TRUE);
5833 		emit_label (acfg, export_name);
5834 	}
5835 
5836 	if (cfg->verbose_level > 0 && !ignore_cfg (cfg))
5837 		g_print ("Method %s emitted as %s\n", mono_method_get_full_name (method), cfg->asm_symbol);
5838 
5839 	acfg->stats.code_size += cfg->code_len;
5840 
5841 	acfg->cfgs [method_index]->got_offset = acfg->got_offset;
5842 
5843 	emit_and_reloc_code (acfg, method, code, cfg->code_len, cfg->patch_info, FALSE, mono_debug_find_method (cfg->jit_info->d.method, mono_domain_get ()));
5844 
5845 	emit_line (acfg);
5846 
5847 	if (acfg->aot_opts.write_symbols) {
5848 		if (debug_sym)
5849 			emit_symbol_size (acfg, debug_sym, ".");
5850 		else
5851 			emit_symbol_size (acfg, cfg->asm_symbol, ".");
5852 		g_free (debug_sym);
5853 	}
5854 
5855 	emit_label (acfg, symbol);
5856 
5857 	arch_emit_unwind_info_sections (acfg, cfg->asm_symbol, symbol, cfg->unwind_ops);
5858 
5859 	g_free (symbol);
5860 }
5861 
5862 /**
5863  * encode_patch:
5864  *
5865  *  Encode PATCH_INFO into its disk representation.
5866  */
5867 static void
encode_patch(MonoAotCompile * acfg,MonoJumpInfo * patch_info,guint8 * buf,guint8 ** endbuf)5868 encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint8 **endbuf)
5869 {
5870 	guint8 *p = buf;
5871 
5872 	switch (patch_info->type) {
5873 	case MONO_PATCH_INFO_NONE:
5874 		break;
5875 	case MONO_PATCH_INFO_IMAGE:
5876 		encode_value (get_image_index (acfg, patch_info->data.image), p, &p);
5877 		break;
5878 	case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
5879 	case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
5880 	case MONO_PATCH_INFO_GC_NURSERY_START:
5881 	case MONO_PATCH_INFO_GC_NURSERY_BITS:
5882 		break;
5883 	case MONO_PATCH_INFO_CASTCLASS_CACHE:
5884 		encode_value (patch_info->data.index, p, &p);
5885 		break;
5886 	case MONO_PATCH_INFO_METHOD_REL:
5887 		encode_value ((gint)patch_info->data.offset, p, &p);
5888 		break;
5889 	case MONO_PATCH_INFO_SWITCH: {
5890 		gpointer *table = (gpointer *)patch_info->data.table->table;
5891 		int k;
5892 
5893 		encode_value (patch_info->data.table->table_size, p, &p);
5894 		for (k = 0; k < patch_info->data.table->table_size; k++)
5895 			encode_value ((int)(gssize)table [k], p, &p);
5896 		break;
5897 	}
5898 	case MONO_PATCH_INFO_METHODCONST:
5899 	case MONO_PATCH_INFO_METHOD:
5900 	case MONO_PATCH_INFO_METHOD_JUMP:
5901 	case MONO_PATCH_INFO_ICALL_ADDR:
5902 	case MONO_PATCH_INFO_ICALL_ADDR_CALL:
5903 	case MONO_PATCH_INFO_METHOD_RGCTX:
5904 	case MONO_PATCH_INFO_METHOD_CODE_SLOT:
5905 		encode_method_ref (acfg, patch_info->data.method, p, &p);
5906 		break;
5907 	case MONO_PATCH_INFO_AOT_JIT_INFO:
5908 	case MONO_PATCH_INFO_GET_TLS_TRAMP:
5909 	case MONO_PATCH_INFO_SET_TLS_TRAMP:
5910 		encode_value (patch_info->data.index, p, &p);
5911 		break;
5912 	case MONO_PATCH_INFO_INTERNAL_METHOD:
5913 	case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5914 	case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL: {
5915 		guint32 len = strlen (patch_info->data.name);
5916 
5917 		encode_value (len, p, &p);
5918 
5919 		memcpy (p, patch_info->data.name, len);
5920 		p += len;
5921 		*p++ = '\0';
5922 		break;
5923 	}
5924 	case MONO_PATCH_INFO_LDSTR: {
5925 		guint32 image_index = get_image_index (acfg, patch_info->data.token->image);
5926 		guint32 token = patch_info->data.token->token;
5927 		g_assert (mono_metadata_token_code (token) == MONO_TOKEN_STRING);
5928 		encode_value (image_index, p, &p);
5929 		encode_value (patch_info->data.token->token - MONO_TOKEN_STRING, p, &p);
5930 		break;
5931 	}
5932 	case MONO_PATCH_INFO_RVA:
5933 	case MONO_PATCH_INFO_DECLSEC:
5934 	case MONO_PATCH_INFO_LDTOKEN:
5935 	case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5936 		encode_value (get_image_index (acfg, patch_info->data.token->image), p, &p);
5937 		encode_value (patch_info->data.token->token, p, &p);
5938 		encode_value (patch_info->data.token->has_context, p, &p);
5939 		if (patch_info->data.token->has_context)
5940 			encode_generic_context (acfg, &patch_info->data.token->context, p, &p);
5941 		break;
5942 	case MONO_PATCH_INFO_EXC_NAME: {
5943 		MonoClass *ex_class;
5944 
5945 		ex_class =
5946 			mono_class_load_from_name (mono_defaults.exception_class->image,
5947 								  "System", (const char *)patch_info->data.target);
5948 		encode_klass_ref (acfg, ex_class, p, &p);
5949 		break;
5950 	}
5951 	case MONO_PATCH_INFO_R4:
5952 		encode_value (*((guint32 *)patch_info->data.target), p, &p);
5953 		break;
5954 	case MONO_PATCH_INFO_R8:
5955 		encode_value (((guint32 *)patch_info->data.target) [MINI_LS_WORD_IDX], p, &p);
5956 		encode_value (((guint32 *)patch_info->data.target) [MINI_MS_WORD_IDX], p, &p);
5957 		break;
5958 	case MONO_PATCH_INFO_VTABLE:
5959 	case MONO_PATCH_INFO_CLASS:
5960 	case MONO_PATCH_INFO_IID:
5961 	case MONO_PATCH_INFO_ADJUSTED_IID:
5962 		encode_klass_ref (acfg, patch_info->data.klass, p, &p);
5963 		break;
5964 	case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
5965 		encode_klass_ref (acfg, patch_info->data.del_tramp->klass, p, &p);
5966 		if (patch_info->data.del_tramp->method) {
5967 			encode_value (1, p, &p);
5968 			encode_method_ref (acfg, patch_info->data.del_tramp->method, p, &p);
5969 		} else {
5970 			encode_value (0, p, &p);
5971 		}
5972 		encode_value (patch_info->data.del_tramp->is_virtual, p, &p);
5973 		break;
5974 	case MONO_PATCH_INFO_FIELD:
5975 	case MONO_PATCH_INFO_SFLDA:
5976 		encode_field_info (acfg, patch_info->data.field, p, &p);
5977 		break;
5978 	case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
5979 		break;
5980 	case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT:
5981 		break;
5982 	case MONO_PATCH_INFO_RGCTX_FETCH:
5983 	case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
5984 		MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
5985 		guint32 offset;
5986 		guint8 *buf2, *p2;
5987 
5988 		/*
5989 		 * entry->method has a lenghtly encoding and multiple rgctx_fetch entries
5990 		 * reference the same method, so encode the method only once.
5991 		 */
5992 		offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_blob_hash, entry->method));
5993 		if (!offset) {
5994 			buf2 = (guint8 *)g_malloc (1024);
5995 			p2 = buf2;
5996 
5997 			encode_method_ref (acfg, entry->method, p2, &p2);
5998 			g_assert (p2 - buf2 < 1024);
5999 
6000 			offset = add_to_blob (acfg, buf2, p2 - buf2);
6001 			g_free (buf2);
6002 
6003 			g_hash_table_insert (acfg->method_blob_hash, entry->method, GUINT_TO_POINTER (offset + 1));
6004 		} else {
6005 			offset --;
6006 		}
6007 
6008 		encode_value (offset, p, &p);
6009 		g_assert ((int)entry->info_type < 256);
6010 		g_assert (entry->data->type < 256);
6011 		encode_value ((entry->in_mrgctx ? 1 : 0) | (entry->info_type << 1) | (entry->data->type << 9), p, &p);
6012 		encode_patch (acfg, entry->data, p, &p);
6013 		break;
6014 	}
6015 	case MONO_PATCH_INFO_SEQ_POINT_INFO:
6016 	case MONO_PATCH_INFO_AOT_MODULE:
6017 		break;
6018 	case MONO_PATCH_INFO_SIGNATURE:
6019 	case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
6020 		encode_signature (acfg, (MonoMethodSignature*)patch_info->data.target, p, &p);
6021 		break;
6022 	case MONO_PATCH_INFO_GSHAREDVT_CALL:
6023 		encode_signature (acfg, (MonoMethodSignature*)patch_info->data.gsharedvt->sig, p, &p);
6024 		encode_method_ref (acfg, patch_info->data.gsharedvt->method, p, &p);
6025 		break;
6026 	case MONO_PATCH_INFO_GSHAREDVT_METHOD: {
6027 		MonoGSharedVtMethodInfo *info = patch_info->data.gsharedvt_method;
6028 		int i;
6029 
6030 		encode_method_ref (acfg, info->method, p, &p);
6031 		encode_value (info->num_entries, p, &p);
6032 		for (i = 0; i < info->num_entries; ++i) {
6033 			MonoRuntimeGenericContextInfoTemplate *template_ = &info->entries [i];
6034 
6035 			encode_value (template_->info_type, p, &p);
6036 			switch (mini_rgctx_info_type_to_patch_info_type (template_->info_type)) {
6037 			case MONO_PATCH_INFO_CLASS:
6038 				encode_klass_ref (acfg, mono_class_from_mono_type ((MonoType *)template_->data), p, &p);
6039 				break;
6040 			case MONO_PATCH_INFO_FIELD:
6041 				encode_field_info (acfg, (MonoClassField *)template_->data, p, &p);
6042 				break;
6043 			default:
6044 				g_assert_not_reached ();
6045 				break;
6046 			}
6047 		}
6048 		break;
6049 	}
6050 	case MONO_PATCH_INFO_LDSTR_LIT: {
6051 		const char *s = (const char *)patch_info->data.target;
6052 		int len = strlen (s);
6053 
6054 		encode_value (len, p, &p);
6055 		memcpy (p, s, len + 1);
6056 		p += len + 1;
6057 		break;
6058 	}
6059 	case MONO_PATCH_INFO_VIRT_METHOD:
6060 		encode_klass_ref (acfg, patch_info->data.virt_method->klass, p, &p);
6061 		encode_method_ref (acfg, patch_info->data.virt_method->method, p, &p);
6062 		break;
6063 	case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
6064 	case MONO_PATCH_INFO_JIT_THREAD_ATTACH:
6065 		break;
6066 	default:
6067 		g_warning ("unable to handle jump info %d", patch_info->type);
6068 		g_assert_not_reached ();
6069 	}
6070 
6071 	*endbuf = p;
6072 }
6073 
6074 static void
encode_patch_list(MonoAotCompile * acfg,GPtrArray * patches,int n_patches,gboolean llvm,int first_got_offset,guint8 * buf,guint8 ** endbuf)6075 encode_patch_list (MonoAotCompile *acfg, GPtrArray *patches, int n_patches, gboolean llvm, int first_got_offset, guint8 *buf, guint8 **endbuf)
6076 {
6077 	guint8 *p = buf;
6078 	guint32 pindex, offset;
6079 	MonoJumpInfo *patch_info;
6080 
6081 	encode_value (n_patches, p, &p);
6082 
6083 	for (pindex = 0; pindex < patches->len; ++pindex) {
6084 		patch_info = (MonoJumpInfo *)g_ptr_array_index (patches, pindex);
6085 
6086 		if (patch_info->type == MONO_PATCH_INFO_NONE || patch_info->type == MONO_PATCH_INFO_BB)
6087 			/* Nothing to do */
6088 			continue;
6089 
6090 		offset = get_got_offset (acfg, llvm, patch_info);
6091 		encode_value (offset, p, &p);
6092 	}
6093 
6094 	*endbuf = p;
6095 }
6096 
6097 static void
emit_method_info(MonoAotCompile * acfg,MonoCompile * cfg)6098 emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
6099 {
6100 	MonoMethod *method;
6101 	int pindex, buf_size, n_patches;
6102 	GPtrArray *patches;
6103 	MonoJumpInfo *patch_info;
6104 	guint32 method_index;
6105 	guint8 *p, *buf;
6106 	guint32 first_got_offset;
6107 
6108 	method = cfg->orig_method;
6109 
6110 	method_index = get_method_index (acfg, method);
6111 
6112 	/* Sort relocations */
6113 	patches = g_ptr_array_new ();
6114 	for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next)
6115 		g_ptr_array_add (patches, patch_info);
6116 	g_ptr_array_sort (patches, compare_patches);
6117 
6118 	first_got_offset = acfg->cfgs [method_index]->got_offset;
6119 
6120 	/**********************/
6121 	/* Encode method info */
6122 	/**********************/
6123 
6124 	buf_size = (patches->len < 1000) ? 40960 : 40960 + (patches->len * 64);
6125 	p = buf = (guint8 *)g_malloc (buf_size);
6126 
6127 	if (mono_class_get_cctor (method->klass)) {
6128 		encode_value (1, p, &p);
6129 		encode_klass_ref (acfg, method->klass, p, &p);
6130 	} else {
6131 		/* Not needed when loading the method */
6132 		encode_value (0, p, &p);
6133 	}
6134 
6135 	g_assert (!(cfg->opt & MONO_OPT_SHARED));
6136 
6137 	n_patches = 0;
6138 	for (pindex = 0; pindex < patches->len; ++pindex) {
6139 		patch_info = (MonoJumpInfo *)g_ptr_array_index (patches, pindex);
6140 
6141 		if ((patch_info->type == MONO_PATCH_INFO_GOT_OFFSET) ||
6142 			(patch_info->type == MONO_PATCH_INFO_NONE)) {
6143 			patch_info->type = MONO_PATCH_INFO_NONE;
6144 			/* Nothing to do */
6145 			continue;
6146 		}
6147 
6148 		if ((patch_info->type == MONO_PATCH_INFO_IMAGE) && (patch_info->data.image == acfg->image)) {
6149 			/* Stored in a GOT slot initialized at module load time */
6150 			patch_info->type = MONO_PATCH_INFO_NONE;
6151 			continue;
6152 		}
6153 
6154 		if (patch_info->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR ||
6155 			patch_info->type == MONO_PATCH_INFO_GC_NURSERY_START ||
6156 			patch_info->type == MONO_PATCH_INFO_GC_NURSERY_BITS ||
6157 			patch_info->type == MONO_PATCH_INFO_AOT_MODULE) {
6158 			/* Stored in a GOT slot initialized at module load time */
6159 			patch_info->type = MONO_PATCH_INFO_NONE;
6160 			continue;
6161 		}
6162 
6163 		if (is_plt_patch (patch_info) && !(cfg->compile_llvm && acfg->aot_opts.llvm_only)) {
6164 			/* Calls are made through the PLT */
6165 			patch_info->type = MONO_PATCH_INFO_NONE;
6166 			continue;
6167 		}
6168 
6169 		n_patches ++;
6170 	}
6171 
6172 	if (n_patches)
6173 		g_assert (cfg->has_got_slots);
6174 
6175 	encode_patch_list (acfg, patches, n_patches, cfg->compile_llvm, first_got_offset, p, &p);
6176 
6177 	g_ptr_array_free (patches, TRUE);
6178 
6179 	acfg->stats.info_size += p - buf;
6180 
6181 	g_assert (p - buf < buf_size);
6182 
6183 	cfg->method_info_offset = add_to_blob (acfg, buf, p - buf);
6184 	g_free (buf);
6185 }
6186 
6187 static guint32
get_unwind_info_offset(MonoAotCompile * acfg,guint8 * encoded,guint32 encoded_len)6188 get_unwind_info_offset (MonoAotCompile *acfg, guint8 *encoded, guint32 encoded_len)
6189 {
6190 	guint32 cache_index;
6191 	guint32 offset;
6192 
6193 	/* Reuse the unwind module to canonize and store unwind info entries */
6194 	cache_index = mono_cache_unwind_info (encoded, encoded_len);
6195 
6196 	/* Use +/- 1 to distinguish 0s from missing entries */
6197 	offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->unwind_info_offsets, GUINT_TO_POINTER (cache_index + 1)));
6198 	if (offset)
6199 		return offset - 1;
6200 	else {
6201 		guint8 buf [16];
6202 		guint8 *p;
6203 
6204 		/*
6205 		 * It would be easier to use assembler symbols, but the caller needs an
6206 		 * offset now.
6207 		 */
6208 		offset = acfg->unwind_info_offset;
6209 		g_hash_table_insert (acfg->unwind_info_offsets, GUINT_TO_POINTER (cache_index + 1), GUINT_TO_POINTER (offset + 1));
6210 		g_ptr_array_add (acfg->unwind_ops, GUINT_TO_POINTER (cache_index));
6211 
6212 		p = buf;
6213 		encode_value (encoded_len, p, &p);
6214 
6215 		acfg->unwind_info_offset += encoded_len + (p - buf);
6216 		return offset;
6217 	}
6218 }
6219 
6220 static void
emit_exception_debug_info(MonoAotCompile * acfg,MonoCompile * cfg,gboolean store_seq_points)6221 emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg, gboolean store_seq_points)
6222 {
6223 	int i, k, buf_size;
6224 	guint32 debug_info_size, seq_points_size;
6225 	guint8 *code;
6226 	MonoMethodHeader *header;
6227 	guint8 *p, *buf, *debug_info;
6228 	MonoJitInfo *jinfo = cfg->jit_info;
6229 	guint32 flags;
6230 	gboolean use_unwind_ops = FALSE;
6231 	MonoSeqPointInfo *seq_points;
6232 
6233 	code = cfg->native_code;
6234 	header = cfg->header;
6235 
6236 	if (!acfg->aot_opts.nodebug) {
6237 		mono_debug_serialize_debug_info (cfg, &debug_info, &debug_info_size);
6238 	} else {
6239 		debug_info = NULL;
6240 		debug_info_size = 0;
6241 	}
6242 
6243 	seq_points = cfg->seq_point_info;
6244 	seq_points_size = (store_seq_points)? mono_seq_point_info_get_write_size (seq_points) : 0;
6245 
6246 	buf_size = header->num_clauses * 256 + debug_info_size + 2048 + seq_points_size + cfg->gc_map_size;
6247 	if (jinfo->has_try_block_holes) {
6248 		MonoTryBlockHoleTableJitInfo *table = mono_jit_info_get_try_block_hole_table_info (jinfo);
6249 		buf_size += table->num_holes * 16;
6250 	}
6251 
6252 	p = buf = (guint8 *)g_malloc (buf_size);
6253 
6254 	use_unwind_ops = cfg->unwind_ops != NULL;
6255 
6256 	flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0) | (header->num_clauses ? 4 : 0) | (seq_points_size ? 8 : 0) | (cfg->compile_llvm ? 16 : 0) | (jinfo->has_try_block_holes ? 32 : 0) | (cfg->gc_map ? 64 : 0) | (jinfo->has_arch_eh_info ? 128 : 0);
6257 
6258 	encode_value (flags, p, &p);
6259 
6260 	if (use_unwind_ops) {
6261 		guint32 encoded_len;
6262 		guint8 *encoded;
6263 		guint32 unwind_desc;
6264 
6265 		encoded = mono_unwind_ops_encode (cfg->unwind_ops, &encoded_len);
6266 
6267 		unwind_desc = get_unwind_info_offset (acfg, encoded, encoded_len);
6268 		encode_value (unwind_desc, p, &p);
6269 
6270 		g_free (encoded);
6271 	} else {
6272 		encode_value (jinfo->unwind_info, p, &p);
6273 	}
6274 
6275 	/*Encode the number of holes before the number of clauses to make decoding easier*/
6276 	if (jinfo->has_try_block_holes) {
6277 		MonoTryBlockHoleTableJitInfo *table = mono_jit_info_get_try_block_hole_table_info (jinfo);
6278 		encode_value (table->num_holes, p, &p);
6279 	}
6280 
6281 	if (jinfo->has_arch_eh_info) {
6282 		/*
6283 		 * In AOT mode, the code length is calculated from the address of the previous method,
6284 		 * which could include alignment padding, so calculating the start of the epilog as
6285 		 * code_len - epilog_size is correct any more. Save the real code len as a workaround.
6286 		 */
6287 		encode_value (jinfo->code_size, p, &p);
6288 	}
6289 
6290 	/* Exception table */
6291 	if (cfg->compile_llvm) {
6292 		/*
6293 		 * When using LLVM, we can't emit some data, like pc offsets, this reg/offset etc.,
6294 		 * since the information is only available to llc. Instead, we let llc save the data
6295 		 * into the LSDA, and read it from there at runtime.
6296 		 */
6297 		/* The assembly might be CIL stripped so emit the data ourselves */
6298 		if (header->num_clauses)
6299 			encode_value (header->num_clauses, p, &p);
6300 
6301 		for (k = 0; k < header->num_clauses; ++k) {
6302 			MonoExceptionClause *clause;
6303 
6304 			clause = &header->clauses [k];
6305 
6306 			encode_value (clause->flags, p, &p);
6307 			if (!(clause->flags == MONO_EXCEPTION_CLAUSE_FILTER || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
6308 				if (clause->data.catch_class) {
6309 					guint8 *buf2, *p2;
6310 					int len;
6311 
6312 					buf2 = (guint8 *)g_malloc (4096);
6313 					p2 = buf2;
6314 					encode_klass_ref (acfg, clause->data.catch_class, p2, &p2);
6315 					len = p2 - buf2;
6316 					g_assert (len < 4096);
6317 					encode_value (len, p, &p);
6318 					memcpy (p, buf2, len);
6319 					p += p2 - buf2;
6320 					g_free (buf2);
6321 				} else {
6322 					encode_value (0, p, &p);
6323 				}
6324 			}
6325 
6326 			/* Emit the IL ranges too, since they might not be available at runtime */
6327 			encode_value (clause->try_offset, p, &p);
6328 			encode_value (clause->try_len, p, &p);
6329 			encode_value (clause->handler_offset, p, &p);
6330 			encode_value (clause->handler_len, p, &p);
6331 
6332 			/* Emit a list of nesting clauses */
6333 			for (i = 0; i < header->num_clauses; ++i) {
6334 				gint32 cindex1 = k;
6335 				MonoExceptionClause *clause1 = &header->clauses [cindex1];
6336 				gint32 cindex2 = i;
6337 				MonoExceptionClause *clause2 = &header->clauses [cindex2];
6338 
6339 				if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset)
6340 					encode_value (i, p, &p);
6341 			}
6342 			encode_value (-1, p, &p);
6343 		}
6344 	} else {
6345 		if (jinfo->num_clauses)
6346 			encode_value (jinfo->num_clauses, p, &p);
6347 
6348 		for (k = 0; k < jinfo->num_clauses; ++k) {
6349 			MonoJitExceptionInfo *ei = &jinfo->clauses [k];
6350 
6351 			encode_value (ei->flags, p, &p);
6352 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
6353 			/* Not used for catch clauses */
6354 			if (ei->flags != MONO_EXCEPTION_CLAUSE_NONE)
6355 				encode_value (ei->exvar_offset, p, &p);
6356 #else
6357 			encode_value (ei->exvar_offset, p, &p);
6358 #endif
6359 
6360 			if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER || ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY)
6361 				encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
6362 			else {
6363 				if (ei->data.catch_class) {
6364 					guint8 *buf2, *p2;
6365 					int len;
6366 
6367 					buf2 = (guint8 *)g_malloc (4096);
6368 					p2 = buf2;
6369 					encode_klass_ref (acfg, ei->data.catch_class, p2, &p2);
6370 					len = p2 - buf2;
6371 					g_assert (len < 4096);
6372 					encode_value (len, p, &p);
6373 					memcpy (p, buf2, len);
6374 					p += p2 - buf2;
6375 					g_free (buf2);
6376 				} else {
6377 					encode_value (0, p, &p);
6378 				}
6379 			}
6380 
6381 			encode_value ((gint)((guint8*)ei->try_start - code), p, &p);
6382 			encode_value ((gint)((guint8*)ei->try_end - code), p, &p);
6383 			encode_value ((gint)((guint8*)ei->handler_start - code), p, &p);
6384 		}
6385 	}
6386 
6387 	if (jinfo->has_try_block_holes) {
6388 		MonoTryBlockHoleTableJitInfo *table = mono_jit_info_get_try_block_hole_table_info (jinfo);
6389 		for (i = 0; i < table->num_holes; ++i) {
6390 			MonoTryBlockHoleJitInfo *hole = &table->holes [i];
6391 			encode_value (hole->clause, p, &p);
6392 			encode_value (hole->length, p, &p);
6393 			encode_value (hole->offset, p, &p);
6394 		}
6395 	}
6396 
6397 	if (jinfo->has_arch_eh_info) {
6398 		MonoArchEHJitInfo *eh_info;
6399 
6400 		eh_info = mono_jit_info_get_arch_eh_info (jinfo);
6401 		encode_value (eh_info->stack_size, p, &p);
6402 		encode_value (eh_info->epilog_size, p, &p);
6403 	}
6404 
6405 	if (jinfo->has_generic_jit_info) {
6406 		MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (jinfo);
6407 		MonoGenericSharingContext* gsctx = gi->generic_sharing_context;
6408 		guint8 *buf2, *p2;
6409 		int len;
6410 
6411 		encode_value (gi->nlocs, p, &p);
6412 		if (gi->nlocs) {
6413 			for (i = 0; i < gi->nlocs; ++i) {
6414 				MonoDwarfLocListEntry *entry = &gi->locations [i];
6415 
6416 				encode_value (entry->is_reg ? 1 : 0, p, &p);
6417 				encode_value (entry->reg, p, &p);
6418 				if (!entry->is_reg)
6419 					encode_value (entry->offset, p, &p);
6420 				if (i == 0)
6421 					g_assert (entry->from == 0);
6422 				else
6423 					encode_value (entry->from, p, &p);
6424 				encode_value (entry->to, p, &p);
6425 			}
6426 		} else {
6427 			if (!cfg->compile_llvm) {
6428 				encode_value (gi->has_this ? 1 : 0, p, &p);
6429 				encode_value (gi->this_reg, p, &p);
6430 				encode_value (gi->this_offset, p, &p);
6431 			}
6432 		}
6433 
6434 		/*
6435 		 * Need to encode jinfo->method too, since it is not equal to 'method'
6436 		 * when using generic sharing.
6437 		 */
6438 		buf2 = (guint8 *)g_malloc (4096);
6439 		p2 = buf2;
6440 		encode_method_ref (acfg, jinfo->d.method, p2, &p2);
6441 		len = p2 - buf2;
6442 		g_assert (len < 4096);
6443 		encode_value (len, p, &p);
6444 		memcpy (p, buf2, len);
6445 		p += p2 - buf2;
6446 		g_free (buf2);
6447 
6448 		if (gsctx && gsctx->is_gsharedvt) {
6449 			encode_value (1, p, &p);
6450 		} else {
6451 			encode_value (0, p, &p);
6452 		}
6453 	}
6454 
6455 	if (seq_points_size)
6456 		p += mono_seq_point_info_write (seq_points, p);
6457 
6458 	g_assert (debug_info_size < buf_size);
6459 
6460 	encode_value (debug_info_size, p, &p);
6461 	if (debug_info_size) {
6462 		memcpy (p, debug_info, debug_info_size);
6463 		p += debug_info_size;
6464 		g_free (debug_info);
6465 	}
6466 
6467 	/* GC Map */
6468 	if (cfg->gc_map) {
6469 		encode_value (cfg->gc_map_size, p, &p);
6470 		/* The GC map requires 4 bytes of alignment */
6471 		while ((gsize)p % 4)
6472 			p ++;
6473 		memcpy (p, cfg->gc_map, cfg->gc_map_size);
6474 		p += cfg->gc_map_size;
6475 	}
6476 
6477 	acfg->stats.ex_info_size += p - buf;
6478 
6479 	g_assert (p - buf < buf_size);
6480 
6481 	/* Emit info */
6482 	/* The GC Map requires 4 byte alignment */
6483 	cfg->ex_info_offset = add_to_blob_aligned (acfg, buf, p - buf, cfg->gc_map ? 4 : 1);
6484 	g_free (buf);
6485 }
6486 
6487 static guint32
emit_klass_info(MonoAotCompile * acfg,guint32 token)6488 emit_klass_info (MonoAotCompile *acfg, guint32 token)
6489 {
6490 	MonoError error;
6491 	MonoClass *klass = mono_class_get_checked (acfg->image, token, &error);
6492 	guint8 *p, *buf;
6493 	int i, buf_size, res;
6494 	gboolean no_special_static, cant_encode;
6495 	gpointer iter = NULL;
6496 
6497 	if (!klass) {
6498 		mono_error_cleanup (&error);
6499 
6500 		buf_size = 16;
6501 
6502 		p = buf = (guint8 *)g_malloc (buf_size);
6503 
6504 		/* Mark as unusable */
6505 		encode_value (-1, p, &p);
6506 
6507 		res = add_to_blob (acfg, buf, p - buf);
6508 		g_free (buf);
6509 
6510 		return res;
6511 	}
6512 
6513 	buf_size = 10240 + (klass->vtable_size * 16);
6514 	p = buf = (guint8 *)g_malloc (buf_size);
6515 
6516 	g_assert (klass);
6517 
6518 	mono_class_init (klass);
6519 
6520 	mono_class_get_nested_types (klass, &iter);
6521 	g_assert (klass->nested_classes_inited);
6522 
6523 	mono_class_setup_vtable (klass);
6524 
6525 	/*
6526 	 * Emit all the information which is required for creating vtables so
6527 	 * the runtime does not need to create the MonoMethod structures which
6528 	 * take up a lot of space.
6529 	 */
6530 
6531 	no_special_static = !mono_class_has_special_static_fields (klass);
6532 
6533 	/* Check whenever we have enough info to encode the vtable */
6534 	cant_encode = FALSE;
6535 	for (i = 0; i < klass->vtable_size; ++i) {
6536 		MonoMethod *cm = klass->vtable [i];
6537 
6538 		if (cm && mono_method_signature (cm)->is_inflated && !g_hash_table_lookup (acfg->token_info_hash, cm))
6539 			cant_encode = TRUE;
6540 	}
6541 
6542 	mono_class_has_finalizer (klass);
6543 	if (mono_class_has_failure (klass))
6544 		cant_encode = TRUE;
6545 
6546 	if (mono_class_is_gtd (klass) || cant_encode) {
6547 		encode_value (-1, p, &p);
6548 	} else {
6549 		gboolean has_nested = mono_class_get_nested_classes_property (klass) != NULL;
6550 		encode_value (klass->vtable_size, p, &p);
6551 		encode_value ((klass->has_weak_fields << 9) | (mono_class_is_gtd (klass) ? (1 << 8) : 0) | (no_special_static << 7) | (klass->has_static_refs << 6) | (klass->has_references << 5) | ((klass->blittable << 4) | (has_nested ? 1 : 0) << 3) | (klass->has_cctor << 2) | (klass->has_finalize << 1) | klass->ghcimpl, p, &p);
6552 		if (klass->has_cctor)
6553 			encode_method_ref (acfg, mono_class_get_cctor (klass), p, &p);
6554 		if (klass->has_finalize)
6555 			encode_method_ref (acfg, mono_class_get_finalizer (klass), p, &p);
6556 
6557 		encode_value (klass->instance_size, p, &p);
6558 		encode_value (mono_class_data_size (klass), p, &p);
6559 		encode_value (klass->packing_size, p, &p);
6560 		encode_value (klass->min_align, p, &p);
6561 
6562 		for (i = 0; i < klass->vtable_size; ++i) {
6563 			MonoMethod *cm = klass->vtable [i];
6564 
6565 			if (cm)
6566 				encode_method_ref (acfg, cm, p, &p);
6567 			else
6568 				encode_value (0, p, &p);
6569 		}
6570 	}
6571 
6572 	acfg->stats.class_info_size += p - buf;
6573 
6574 	g_assert (p - buf < buf_size);
6575 	res = add_to_blob (acfg, buf, p - buf);
6576 	g_free (buf);
6577 
6578 	return res;
6579 }
6580 
6581 static char*
get_plt_entry_debug_sym(MonoAotCompile * acfg,MonoJumpInfo * ji,GHashTable * cache)6582 get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache)
6583 {
6584 	char *debug_sym = NULL;
6585 	char *prefix;
6586 
6587 	if (acfg->llvm && llvm_acfg->aot_opts.static_link) {
6588 		/* Need to add a prefix to create unique symbols */
6589 		prefix = g_strdup_printf ("plt_%s_", acfg->assembly_name_sym);
6590 	} else {
6591 #if defined(TARGET_WIN32) && defined(TARGET_X86)
6592 		prefix = mangle_symbol_alloc ("plt_");
6593 #else
6594 		prefix = g_strdup ("plt_");
6595 #endif
6596 	}
6597 
6598 	switch (ji->type) {
6599 	case MONO_PATCH_INFO_METHOD:
6600 		debug_sym = get_debug_sym (ji->data.method, prefix, cache);
6601 		break;
6602 	case MONO_PATCH_INFO_INTERNAL_METHOD:
6603 		debug_sym = g_strdup_printf ("%s_jit_icall_%s", prefix, ji->data.name);
6604 		break;
6605 	case MONO_PATCH_INFO_RGCTX_FETCH:
6606 		debug_sym = g_strdup_printf ("%s_rgctx_fetch_%d", prefix, acfg->label_generator ++);
6607 		break;
6608 	case MONO_PATCH_INFO_ICALL_ADDR:
6609 	case MONO_PATCH_INFO_ICALL_ADDR_CALL: {
6610 		char *s = get_debug_sym (ji->data.method, "", cache);
6611 
6612 		debug_sym = g_strdup_printf ("%s_icall_native_%s", prefix, s);
6613 		g_free (s);
6614 		break;
6615 	}
6616 	case MONO_PATCH_INFO_JIT_ICALL_ADDR:
6617 		debug_sym = g_strdup_printf ("%s_jit_icall_native_%s", prefix, ji->data.name);
6618 		break;
6619 	default:
6620 		break;
6621 	}
6622 
6623 	g_free (prefix);
6624 
6625 	return sanitize_symbol (acfg, debug_sym);
6626 }
6627 
6628 /*
6629  * Calls made from AOTed code are routed through a table of jumps similar to the
6630  * ELF PLT (Program Linkage Table). Initially the PLT entries jump to code which transfers
6631  * control to the AOT runtime through a trampoline.
6632  */
6633 static void
emit_plt(MonoAotCompile * acfg)6634 emit_plt (MonoAotCompile *acfg)
6635 {
6636 	int i;
6637 
6638 	if (acfg->aot_opts.llvm_only) {
6639 		g_assert (acfg->plt_offset == 1);
6640 		return;
6641 	}
6642 
6643 	emit_line (acfg);
6644 
6645 	emit_section_change (acfg, ".text", 0);
6646 	emit_alignment_code (acfg, 16);
6647 	emit_info_symbol (acfg, "plt");
6648 	emit_label (acfg, acfg->plt_symbol);
6649 
6650 	for (i = 0; i < acfg->plt_offset; ++i) {
6651 		char *debug_sym = NULL;
6652 		MonoPltEntry *plt_entry = NULL;
6653 
6654 		if (i == 0)
6655 			/*
6656 			 * The first plt entry is unused.
6657 			 */
6658 			continue;
6659 
6660 		plt_entry = (MonoPltEntry *)g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
6661 
6662 		debug_sym = plt_entry->debug_sym;
6663 
6664 		if (acfg->thumb_mixed && !plt_entry->jit_used)
6665 			/* Emit only a thumb version */
6666 			continue;
6667 
6668 		/* Skip plt entries not actually called */
6669 		if (!plt_entry->jit_used && !plt_entry->llvm_used)
6670 			continue;
6671 
6672 		if (acfg->llvm && !acfg->thumb_mixed) {
6673 			emit_label (acfg, plt_entry->llvm_symbol);
6674 			if (acfg->llvm) {
6675 				emit_global_inner (acfg, plt_entry->llvm_symbol, TRUE);
6676 #if defined(TARGET_MACH)
6677 				fprintf (acfg->fp, ".private_extern %s\n", plt_entry->llvm_symbol);
6678 #endif
6679 			}
6680 		}
6681 
6682 		if (debug_sym) {
6683 			if (acfg->need_no_dead_strip) {
6684 				emit_unset_mode (acfg);
6685 				fprintf (acfg->fp, "	.no_dead_strip %s\n", debug_sym);
6686 			}
6687 			emit_local_symbol (acfg, debug_sym, NULL, TRUE);
6688 			emit_label (acfg, debug_sym);
6689 		}
6690 
6691 		emit_label (acfg, plt_entry->symbol);
6692 
6693 		arch_emit_plt_entry (acfg, acfg->got_symbol, (acfg->plt_got_offset_base + i) * sizeof (gpointer), acfg->plt_got_info_offsets [i]);
6694 
6695 		if (debug_sym)
6696 			emit_symbol_size (acfg, debug_sym, ".");
6697 	}
6698 
6699 	if (acfg->thumb_mixed) {
6700 		/* Make sure the ARM symbols don't alias the thumb ones */
6701 		emit_zero_bytes (acfg, 16);
6702 
6703 		/*
6704 		 * Emit a separate set of PLT entries using thumb2 which is called by LLVM generated
6705 		 * code.
6706 		 */
6707 		for (i = 0; i < acfg->plt_offset; ++i) {
6708 			char *debug_sym = NULL;
6709 			MonoPltEntry *plt_entry = NULL;
6710 
6711 			if (i == 0)
6712 				continue;
6713 
6714 			plt_entry = (MonoPltEntry *)g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
6715 
6716 			/* Skip plt entries not actually called by LLVM code */
6717 			if (!plt_entry->llvm_used)
6718 				continue;
6719 
6720 			if (acfg->aot_opts.write_symbols) {
6721 				if (plt_entry->debug_sym)
6722 					debug_sym = g_strdup_printf ("%s_thumb", plt_entry->debug_sym);
6723 			}
6724 
6725 			if (debug_sym) {
6726 #if defined(TARGET_MACH)
6727 				fprintf (acfg->fp, "	.thumb_func %s\n", debug_sym);
6728 				fprintf (acfg->fp, "	.no_dead_strip %s\n", debug_sym);
6729 #endif
6730 				emit_local_symbol (acfg, debug_sym, NULL, TRUE);
6731 				emit_label (acfg, debug_sym);
6732 			}
6733 			fprintf (acfg->fp, "\n.thumb_func\n");
6734 
6735 			emit_label (acfg, plt_entry->llvm_symbol);
6736 
6737 			if (acfg->llvm)
6738 				emit_global_inner (acfg, plt_entry->llvm_symbol, TRUE);
6739 
6740 			arch_emit_llvm_plt_entry (acfg, acfg->got_symbol, (acfg->plt_got_offset_base + i) * sizeof (gpointer), acfg->plt_got_info_offsets [i]);
6741 
6742 			if (debug_sym) {
6743 				emit_symbol_size (acfg, debug_sym, ".");
6744 				g_free (debug_sym);
6745 			}
6746 		}
6747 	}
6748 
6749 	emit_symbol_size (acfg, acfg->plt_symbol, ".");
6750 
6751 	emit_info_symbol (acfg, "plt_end");
6752 
6753 	arch_emit_unwind_info_sections (acfg, "plt", "plt_end", NULL);
6754 }
6755 
6756 /*
6757  * emit_trampoline_full:
6758  *
6759  *   If EMIT_TINFO is TRUE, emit additional information which can be used to create a MonoJitInfo for this trampoline by
6760  * create_jit_info_for_trampoline ().
6761  */
6762 static G_GNUC_UNUSED void
emit_trampoline_full(MonoAotCompile * acfg,int got_offset,MonoTrampInfo * info,gboolean emit_tinfo)6763 emit_trampoline_full (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info, gboolean emit_tinfo)
6764 {
6765 	char start_symbol [MAX_SYMBOL_SIZE];
6766 	char end_symbol [MAX_SYMBOL_SIZE];
6767 	char symbol [MAX_SYMBOL_SIZE];
6768 	guint32 buf_size, info_offset;
6769 	MonoJumpInfo *patch_info;
6770 	guint8 *buf, *p;
6771 	GPtrArray *patches;
6772 	char *name;
6773 	guint8 *code;
6774 	guint32 code_size;
6775 	MonoJumpInfo *ji;
6776 	GSList *unwind_ops;
6777 
6778 	g_assert (info);
6779 
6780 	name = info->name;
6781 	code = info->code;
6782 	code_size = info->code_size;
6783 	ji = info->ji;
6784 	unwind_ops = info->unwind_ops;
6785 
6786 	/* Emit code */
6787 
6788 	sprintf (start_symbol, "%s%s", acfg->user_symbol_prefix, name);
6789 
6790 	emit_section_change (acfg, ".text", 0);
6791 	emit_global (acfg, start_symbol, TRUE);
6792 	emit_alignment_code (acfg, AOT_FUNC_ALIGNMENT);
6793 	emit_label (acfg, start_symbol);
6794 
6795 	sprintf (symbol, "%snamed_%s", acfg->temp_prefix, name);
6796 	emit_label (acfg, symbol);
6797 
6798 	/*
6799 	 * The code should access everything through the GOT, so we pass
6800 	 * TRUE here.
6801 	 */
6802 	emit_and_reloc_code (acfg, NULL, code, code_size, ji, TRUE, NULL);
6803 
6804 	emit_symbol_size (acfg, start_symbol, ".");
6805 
6806 	if (emit_tinfo) {
6807 		sprintf (end_symbol, "%snamede_%s", acfg->temp_prefix, name);
6808 		emit_label (acfg, end_symbol);
6809 	}
6810 
6811 	/* Emit info */
6812 
6813 	/* Sort relocations */
6814 	patches = g_ptr_array_new ();
6815 	for (patch_info = ji; patch_info; patch_info = patch_info->next)
6816 		if (patch_info->type != MONO_PATCH_INFO_NONE)
6817 			g_ptr_array_add (patches, patch_info);
6818 	g_ptr_array_sort (patches, compare_patches);
6819 
6820 	buf_size = patches->len * 128 + 128;
6821 	buf = (guint8 *)g_malloc (buf_size);
6822 	p = buf;
6823 
6824 	encode_patch_list (acfg, patches, patches->len, FALSE, got_offset, p, &p);
6825 	g_assert (p - buf < buf_size);
6826 	g_ptr_array_free (patches, TRUE);
6827 
6828 	sprintf (symbol, "%s%s_p", acfg->user_symbol_prefix, name);
6829 
6830 	info_offset = add_to_blob (acfg, buf, p - buf);
6831 
6832 	emit_section_change (acfg, RODATA_SECT, 0);
6833 	emit_global (acfg, symbol, FALSE);
6834 	emit_label (acfg, symbol);
6835 
6836 	emit_int32 (acfg, info_offset);
6837 
6838 	if (emit_tinfo) {
6839 		guint8 *encoded;
6840 		guint32 encoded_len;
6841 		guint32 uw_offset;
6842 
6843 		/*
6844 		 * Emit additional information which can be used to reconstruct a partial MonoTrampInfo.
6845 		 */
6846 		encoded = mono_unwind_ops_encode (info->unwind_ops, &encoded_len);
6847 		uw_offset = get_unwind_info_offset (acfg, encoded, encoded_len);
6848 		g_free (encoded);
6849 
6850 		emit_symbol_diff (acfg, end_symbol, start_symbol, 0);
6851 		emit_int32 (acfg, uw_offset);
6852 	}
6853 
6854 	/* Emit debug info */
6855 	if (unwind_ops) {
6856 		char symbol2 [MAX_SYMBOL_SIZE];
6857 
6858 		sprintf (symbol, "%s", name);
6859 		sprintf (symbol2, "%snamed_%s", acfg->temp_prefix, name);
6860 
6861 		arch_emit_unwind_info_sections (acfg, start_symbol, end_symbol, unwind_ops);
6862 
6863 		if (acfg->dwarf)
6864 			mono_dwarf_writer_emit_trampoline (acfg->dwarf, symbol, symbol2, NULL, NULL, code_size, unwind_ops);
6865 	}
6866 
6867 	g_free (buf);
6868 }
6869 
6870 static G_GNUC_UNUSED void
emit_trampoline(MonoAotCompile * acfg,int got_offset,MonoTrampInfo * info)6871 emit_trampoline (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info)
6872 {
6873 	emit_trampoline_full (acfg, got_offset, info, TRUE);
6874 }
6875 
6876 static void
emit_trampolines(MonoAotCompile * acfg)6877 emit_trampolines (MonoAotCompile *acfg)
6878 {
6879 	char symbol [MAX_SYMBOL_SIZE];
6880 	char end_symbol [MAX_SYMBOL_SIZE];
6881 	int i, tramp_got_offset;
6882 	int ntype;
6883 #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
6884 	int tramp_type;
6885 #endif
6886 
6887 	if (!mono_aot_mode_is_full (&acfg->aot_opts) || acfg->aot_opts.llvm_only)
6888 		return;
6889 
6890 	g_assert (acfg->image->assembly);
6891 
6892 	/* Currently, we emit most trampolines into the mscorlib AOT image. */
6893 	if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) {
6894 #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
6895 		MonoTrampInfo *info;
6896 
6897 		/*
6898 		 * Emit the generic trampolines.
6899 		 *
6900 		 * We could save some code by treating the generic trampolines as a wrapper
6901 		 * method, but that approach has its own complexities, so we choose the simpler
6902 		 * method.
6903 		 */
6904 		for (tramp_type = 0; tramp_type < MONO_TRAMPOLINE_NUM; ++tramp_type) {
6905 			/* we overload the boolean here to indicate the slightly different trampoline needed, see mono_arch_create_generic_trampoline() */
6906 #ifdef DISABLE_REMOTING
6907 			if (tramp_type == MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING)
6908 				continue;
6909 #endif
6910 			mono_arch_create_generic_trampoline ((MonoTrampolineType)tramp_type, &info, acfg->aot_opts.use_trampolines_page? 2: TRUE);
6911 			emit_trampoline (acfg, acfg->got_offset, info);
6912 			mono_tramp_info_free (info);
6913 		}
6914 
6915 		/* Emit the exception related code pieces */
6916 		mono_arch_get_restore_context (&info, TRUE);
6917 		emit_trampoline (acfg, acfg->got_offset, info);
6918 		mono_tramp_info_free (info);
6919 
6920 		mono_arch_get_call_filter (&info, TRUE);
6921 		emit_trampoline (acfg, acfg->got_offset, info);
6922 		mono_tramp_info_free (info);
6923 
6924 		mono_arch_get_throw_exception (&info, TRUE);
6925 		emit_trampoline (acfg, acfg->got_offset, info);
6926 		mono_tramp_info_free (info);
6927 
6928 		mono_arch_get_rethrow_exception (&info, TRUE);
6929 		emit_trampoline (acfg, acfg->got_offset, info);
6930 		mono_tramp_info_free (info);
6931 
6932 		mono_arch_get_throw_corlib_exception (&info, TRUE);
6933 		emit_trampoline (acfg, acfg->got_offset, info);
6934 		mono_tramp_info_free (info);
6935 
6936 #ifdef MONO_ARCH_HAVE_SDB_TRAMPOLINES
6937 		mono_arch_create_sdb_trampoline (TRUE, &info, TRUE);
6938 		emit_trampoline (acfg, acfg->got_offset, info);
6939 		mono_tramp_info_free (info);
6940 
6941 		mono_arch_create_sdb_trampoline (FALSE, &info, TRUE);
6942 		emit_trampoline (acfg, acfg->got_offset, info);
6943 		mono_tramp_info_free (info);
6944 #endif
6945 
6946 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
6947 		mono_arch_get_gsharedvt_trampoline (&info, TRUE);
6948 		if (info) {
6949 			emit_trampoline_full (acfg, acfg->got_offset, info, TRUE);
6950 
6951 			/* Create a separate out trampoline for more information in stack traces */
6952 			info->name = g_strdup ("gsharedvt_out_trampoline");
6953 			emit_trampoline_full (acfg, acfg->got_offset, info, TRUE);
6954 			mono_tramp_info_free (info);
6955 		}
6956 #endif
6957 
6958 #if defined(MONO_ARCH_HAVE_GET_TRAMPOLINES)
6959 		{
6960 			GSList *l = mono_arch_get_trampolines (TRUE);
6961 
6962 			while (l) {
6963 				MonoTrampInfo *info = (MonoTrampInfo *)l->data;
6964 
6965 				emit_trampoline (acfg, acfg->got_offset, info);
6966 				l = l->next;
6967 			}
6968 		}
6969 #endif
6970 
6971 		for (i = 0; i < acfg->aot_opts.nrgctx_fetch_trampolines; ++i) {
6972 			int offset;
6973 
6974 			offset = MONO_RGCTX_SLOT_MAKE_RGCTX (i);
6975 			mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE);
6976 			emit_trampoline (acfg, acfg->got_offset, info);
6977 			mono_tramp_info_free (info);
6978 
6979 			offset = MONO_RGCTX_SLOT_MAKE_MRGCTX (i);
6980 			mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE);
6981 			emit_trampoline (acfg, acfg->got_offset, info);
6982 			mono_tramp_info_free (info);
6983 		}
6984 
6985 #ifdef MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE
6986 		mono_arch_create_general_rgctx_lazy_fetch_trampoline (&info, TRUE);
6987 		emit_trampoline (acfg, acfg->got_offset, info);
6988 		mono_tramp_info_free (info);
6989 #endif
6990 
6991 		{
6992 			GSList *l;
6993 
6994 			/* delegate_invoke_impl trampolines */
6995 			l = mono_arch_get_delegate_invoke_impls ();
6996 			while (l) {
6997 				MonoTrampInfo *info = (MonoTrampInfo *)l->data;
6998 
6999 				emit_trampoline (acfg, acfg->got_offset, info);
7000 				l = l->next;
7001 			}
7002 		}
7003 
7004 		if (mono_aot_mode_is_interp (&acfg->aot_opts)) {
7005 			mono_arch_get_enter_icall_trampoline (&info);
7006 			emit_trampoline (acfg, acfg->got_offset, info);
7007 		}
7008 
7009 #endif /* #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES */
7010 
7011 		/* Emit trampolines which are numerous */
7012 
7013 		/*
7014 		 * These include the following:
7015 		 * - specific trampolines
7016 		 * - static rgctx invoke trampolines
7017 		 * - imt trampolines
7018 		 * These trampolines have the same code, they are parameterized by GOT
7019 		 * slots.
7020 		 * They are defined in this file, in the arch_... routines instead of
7021 		 * in tramp-<ARCH>.c, since it is easier to do it this way.
7022 		 */
7023 
7024 		/*
7025 		 * When running in aot-only mode, we can't create specific trampolines at
7026 		 * runtime, so we create a few, and save them in the AOT file.
7027 		 * Normal trampolines embed their argument as a literal inside the
7028 		 * trampoline code, we can't do that here, so instead we embed an offset
7029 		 * which needs to be added to the trampoline address to get the address of
7030 		 * the GOT slot which contains the argument value.
7031 		 * The generated trampolines jump to the generic trampolines using another
7032 		 * GOT slot, which will be setup by the AOT loader to point to the
7033 		 * generic trampoline code of the given type.
7034 		 */
7035 
7036 		/*
7037 		 * FIXME: Maybe we should use more specific trampolines (i.e. one class init for
7038 		 * each class).
7039 		 */
7040 
7041 		emit_section_change (acfg, ".text", 0);
7042 
7043 		tramp_got_offset = acfg->got_offset;
7044 
7045 		for (ntype = 0; ntype < MONO_AOT_TRAMP_NUM; ++ntype) {
7046 			switch (ntype) {
7047 			case MONO_AOT_TRAMP_SPECIFIC:
7048 				sprintf (symbol, "specific_trampolines");
7049 				break;
7050 			case MONO_AOT_TRAMP_STATIC_RGCTX:
7051 				sprintf (symbol, "static_rgctx_trampolines");
7052 				break;
7053 			case MONO_AOT_TRAMP_IMT:
7054 				sprintf (symbol, "imt_trampolines");
7055 				break;
7056 			case MONO_AOT_TRAMP_GSHAREDVT_ARG:
7057 				sprintf (symbol, "gsharedvt_arg_trampolines");
7058 				break;
7059 			default:
7060 				g_assert_not_reached ();
7061 			}
7062 
7063 			sprintf (end_symbol, "%s_e", symbol);
7064 
7065 			if (acfg->aot_opts.write_symbols)
7066 				emit_local_symbol (acfg, symbol, end_symbol, TRUE);
7067 
7068 			emit_alignment_code (acfg, AOT_FUNC_ALIGNMENT);
7069 			emit_info_symbol (acfg, symbol);
7070 
7071 			acfg->trampoline_got_offset_base [ntype] = tramp_got_offset;
7072 
7073 			for (i = 0; i < acfg->num_trampolines [ntype]; ++i) {
7074 				int tramp_size = 0;
7075 
7076 				switch (ntype) {
7077 				case MONO_AOT_TRAMP_SPECIFIC:
7078 					arch_emit_specific_trampoline (acfg, tramp_got_offset, &tramp_size);
7079 					tramp_got_offset += 2;
7080 				break;
7081 				case MONO_AOT_TRAMP_STATIC_RGCTX:
7082 					arch_emit_static_rgctx_trampoline (acfg, tramp_got_offset, &tramp_size);
7083 					tramp_got_offset += 2;
7084 					break;
7085 				case MONO_AOT_TRAMP_IMT:
7086 					arch_emit_imt_trampoline (acfg, tramp_got_offset, &tramp_size);
7087 					tramp_got_offset += 1;
7088 					break;
7089 				case MONO_AOT_TRAMP_GSHAREDVT_ARG:
7090 					arch_emit_gsharedvt_arg_trampoline (acfg, tramp_got_offset, &tramp_size);
7091 					tramp_got_offset += 2;
7092 					break;
7093 				default:
7094 					g_assert_not_reached ();
7095 				}
7096 				if (!acfg->trampoline_size [ntype]) {
7097 					g_assert (tramp_size);
7098 					acfg->trampoline_size [ntype] = tramp_size;
7099 				}
7100 			}
7101 
7102 			emit_label (acfg, end_symbol);
7103 			emit_int32 (acfg, 0);
7104 		}
7105 
7106 		arch_emit_specific_trampoline_pages (acfg);
7107 
7108 		/* Reserve some entries at the end of the GOT for our use */
7109 		acfg->num_trampoline_got_entries = tramp_got_offset - acfg->got_offset;
7110 	}
7111 
7112 	acfg->got_offset += acfg->num_trampoline_got_entries;
7113 }
7114 
7115 static gboolean
str_begins_with(const char * str1,const char * str2)7116 str_begins_with (const char *str1, const char *str2)
7117 {
7118 	int len = strlen (str2);
7119 	return strncmp (str1, str2, len) == 0;
7120 }
7121 
7122 void*
mono_aot_readonly_field_override(MonoClassField * field)7123 mono_aot_readonly_field_override (MonoClassField *field)
7124 {
7125 	ReadOnlyValue *rdv;
7126 	for (rdv = readonly_values; rdv; rdv = rdv->next) {
7127 		char *p = rdv->name;
7128 		int len;
7129 		len = strlen (field->parent->name_space);
7130 		if (strncmp (p, field->parent->name_space, len))
7131 			continue;
7132 		p += len;
7133 		if (*p++ != '.')
7134 			continue;
7135 		len = strlen (field->parent->name);
7136 		if (strncmp (p, field->parent->name, len))
7137 			continue;
7138 		p += len;
7139 		if (*p++ != '.')
7140 			continue;
7141 		if (strcmp (p, field->name))
7142 			continue;
7143 		switch (rdv->type) {
7144 		case MONO_TYPE_I1:
7145 			return &rdv->value.i1;
7146 		case MONO_TYPE_I2:
7147 			return &rdv->value.i2;
7148 		case MONO_TYPE_I4:
7149 			return &rdv->value.i4;
7150 		default:
7151 			break;
7152 		}
7153 	}
7154 	return NULL;
7155 }
7156 
7157 static void
add_readonly_value(MonoAotOptions * opts,const char * val)7158 add_readonly_value (MonoAotOptions *opts, const char *val)
7159 {
7160 	ReadOnlyValue *rdv;
7161 	const char *fval;
7162 	const char *tval;
7163 	/* the format of val is:
7164 	 * namespace.typename.fieldname=type/value
7165 	 * type can be i1 for uint8/int8/boolean, i2 for uint16/int16/char, i4 for uint32/int32
7166 	 */
7167 	fval = strrchr (val, '/');
7168 	if (!fval) {
7169 		fprintf (stderr, "AOT : invalid format for readonly field '%s', missing /.\n", val);
7170 		exit (1);
7171 	}
7172 	tval = strrchr (val, '=');
7173 	if (!tval) {
7174 		fprintf (stderr, "AOT : invalid format for readonly field '%s', missing =.\n", val);
7175 		exit (1);
7176 	}
7177 	rdv = g_new0 (ReadOnlyValue, 1);
7178 	rdv->name = (char *)g_malloc0 (tval - val + 1);
7179 	memcpy (rdv->name, val, tval - val);
7180 	tval++;
7181 	fval++;
7182 	if (strncmp (tval, "i1", 2) == 0) {
7183 		rdv->value.i1 = atoi (fval);
7184 		rdv->type = MONO_TYPE_I1;
7185 	} else if (strncmp (tval, "i2", 2) == 0) {
7186 		rdv->value.i2 = atoi (fval);
7187 		rdv->type = MONO_TYPE_I2;
7188 	} else if (strncmp (tval, "i4", 2) == 0) {
7189 		rdv->value.i4 = atoi (fval);
7190 		rdv->type = MONO_TYPE_I4;
7191 	} else {
7192 		fprintf (stderr, "AOT : unsupported type for readonly field '%s'.\n", tval);
7193 		exit (1);
7194 	}
7195 	rdv->next = readonly_values;
7196 	readonly_values = rdv;
7197 }
7198 
7199 static gchar *
clean_path(gchar * path)7200 clean_path (gchar * path)
7201 {
7202 	if (!path)
7203 		return NULL;
7204 
7205 	if (g_str_has_suffix (path, G_DIR_SEPARATOR_S))
7206 		return path;
7207 
7208 	gchar *clean = g_strconcat (path, G_DIR_SEPARATOR_S, NULL);
7209 	g_free (path);
7210 
7211 	return clean;
7212 }
7213 
7214 static gchar *
wrap_path(gchar * path)7215 wrap_path (gchar * path)
7216 {
7217 	int len;
7218 	if (!path)
7219 		return NULL;
7220 
7221 	// If the string contains no spaces, just return the original string.
7222 	if (strstr (path, " ") == NULL)
7223 		return path;
7224 
7225 	// If the string is already wrapped in quotes, return it.
7226 	len = strlen (path);
7227 	if (len >= 2 && path[0] == '\"' && path[len-1] == '\"')
7228 		return path;
7229 
7230 	// If the string contains spaces, then wrap it in quotes.
7231 	gchar *clean = g_strdup_printf ("\"%s\"", path);
7232 
7233 	return clean;
7234 }
7235 
7236 // Duplicate a char range and add it to a ptrarray, but only if it is nonempty
7237 static void
ptr_array_add_range_if_nonempty(GPtrArray * args,gchar const * start,gchar const * end)7238 ptr_array_add_range_if_nonempty(GPtrArray *args, gchar const *start, gchar const *end)
7239 {
7240 	ptrdiff_t len = end-start;
7241 	if (len > 0)
7242 		g_ptr_array_add (args, g_strndup (start, len));
7243 }
7244 
7245 static GPtrArray *
mono_aot_split_options(const char * aot_options)7246 mono_aot_split_options (const char *aot_options)
7247 {
7248 	enum MonoAotOptionState {
7249 		MONO_AOT_OPTION_STATE_DEFAULT,
7250 		MONO_AOT_OPTION_STATE_STRING,
7251 		MONO_AOT_OPTION_STATE_ESCAPE,
7252 	};
7253 
7254 	GPtrArray *args = g_ptr_array_new ();
7255 	enum MonoAotOptionState state = MONO_AOT_OPTION_STATE_DEFAULT;
7256 	gchar const *opt_start = aot_options;
7257 	gboolean end_of_string = FALSE;
7258 	gchar cur;
7259 
7260 	g_return_val_if_fail (aot_options != NULL, NULL);
7261 
7262 	while ((cur = *aot_options) != '\0') {
7263 		if (state == MONO_AOT_OPTION_STATE_ESCAPE)
7264 			goto next;
7265 
7266 		switch (cur) {
7267 		case '"':
7268 			// If we find a quote, then if we're in the default case then
7269 			// it means we've found the start of a string, if not then it
7270 			// means we've found the end of the string and should switch
7271 			// back to the default case.
7272 			switch (state) {
7273 			case MONO_AOT_OPTION_STATE_DEFAULT:
7274 				state = MONO_AOT_OPTION_STATE_STRING;
7275 				break;
7276 			case MONO_AOT_OPTION_STATE_STRING:
7277 				state = MONO_AOT_OPTION_STATE_DEFAULT;
7278 				break;
7279 			case MONO_AOT_OPTION_STATE_ESCAPE:
7280 				g_assert_not_reached ();
7281 				break;
7282 			}
7283 			break;
7284 		case '\\':
7285 			// If we've found an escaping operator, then this means we
7286 			// should not process the next character if inside a string.
7287 			if (state == MONO_AOT_OPTION_STATE_STRING)
7288 				state = MONO_AOT_OPTION_STATE_ESCAPE;
7289 			break;
7290 		case ',':
7291 			// If we're in the default state then this means we've found
7292 			// an option, store it for later processing.
7293 			if (state == MONO_AOT_OPTION_STATE_DEFAULT)
7294 				goto new_opt;
7295 			break;
7296 		}
7297 
7298 	next:
7299 		aot_options++;
7300 	restart:
7301 		// If the next character is end of string, then process the last option.
7302 		if (*(aot_options) == '\0') {
7303 			end_of_string = TRUE;
7304 			goto new_opt;
7305 		}
7306 		continue;
7307 
7308 	new_opt:
7309 		ptr_array_add_range_if_nonempty (args, opt_start, aot_options);
7310 		opt_start = ++aot_options;
7311 		if (end_of_string)
7312 			break;
7313 		goto restart; // Check for null and continue loop
7314 	}
7315 
7316 	return args;
7317 }
7318 
7319 static void
mono_aot_parse_options(const char * aot_options,MonoAotOptions * opts)7320 mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
7321 {
7322 	GPtrArray* args;
7323 
7324 	args = mono_aot_split_options (aot_options ? aot_options : "");
7325 	for (int i = 0; i < args->len; ++i) {
7326 		const char *arg = (const char *)g_ptr_array_index (args, i);
7327 
7328 		if (str_begins_with (arg, "outfile=")) {
7329 			opts->outfile = g_strdup (arg + strlen ("outfile="));
7330 		} else if (str_begins_with (arg, "llvm-outfile=")) {
7331 			opts->llvm_outfile = g_strdup (arg + strlen ("llvm-outfile="));
7332 		} else if (str_begins_with (arg, "temp-path=")) {
7333 			opts->temp_path = clean_path (g_strdup (arg + strlen ("temp-path=")));
7334 		} else if (str_begins_with (arg, "save-temps")) {
7335 			opts->save_temps = TRUE;
7336 		} else if (str_begins_with (arg, "keep-temps")) {
7337 			opts->save_temps = TRUE;
7338 		} else if (str_begins_with (arg, "write-symbols")) {
7339 			opts->write_symbols = TRUE;
7340 		} else if (str_begins_with (arg, "no-write-symbols")) {
7341 			opts->write_symbols = FALSE;
7342 		// Intentionally undocumented -- one-off experiment
7343 		} else if (str_begins_with (arg, "metadata-only")) {
7344 			opts->metadata_only = TRUE;
7345 		} else if (str_begins_with (arg, "bind-to-runtime-version")) {
7346 			opts->bind_to_runtime_version = TRUE;
7347 		} else if (str_begins_with (arg, "full")) {
7348 			opts->mode = MONO_AOT_MODE_FULL;
7349 		} else if (str_begins_with (arg, "hybrid")) {
7350 			opts->mode = MONO_AOT_MODE_HYBRID;
7351 		} else if (str_begins_with (arg, "interp")) {
7352 			opts->mode = MONO_AOT_MODE_INTERP;
7353 		} else if (str_begins_with (arg, "threads=")) {
7354 			opts->nthreads = atoi (arg + strlen ("threads="));
7355 		} else if (str_begins_with (arg, "static")) {
7356 			opts->static_link = TRUE;
7357 			opts->no_dlsym = TRUE;
7358 		} else if (str_begins_with (arg, "asmonly")) {
7359 			opts->asm_only = TRUE;
7360 		} else if (str_begins_with (arg, "asmwriter")) {
7361 			opts->asm_writer = TRUE;
7362 		} else if (str_begins_with (arg, "nodebug")) {
7363 			opts->nodebug = TRUE;
7364 		} else if (str_begins_with (arg, "dwarfdebug")) {
7365 			opts->dwarf_debug = TRUE;
7366 		// Intentionally undocumented -- No one remembers what this does. It appears to be ARM-only
7367 		} else if (str_begins_with (arg, "nopagetrampolines")) {
7368 			opts->use_trampolines_page = FALSE;
7369 		} else if (str_begins_with (arg, "ntrampolines=")) {
7370 			opts->ntrampolines = atoi (arg + strlen ("ntrampolines="));
7371 		} else if (str_begins_with (arg, "nrgctx-trampolines=")) {
7372 			opts->nrgctx_trampolines = atoi (arg + strlen ("nrgctx-trampolines="));
7373 		} else if (str_begins_with (arg, "nrgctx-fetch-trampolines=")) {
7374 			opts->nrgctx_fetch_trampolines = atoi (arg + strlen ("nrgctx-fetch-trampolines="));
7375 		} else if (str_begins_with (arg, "nimt-trampolines=")) {
7376 			opts->nimt_trampolines = atoi (arg + strlen ("nimt-trampolines="));
7377 		} else if (str_begins_with (arg, "ngsharedvt-trampolines=")) {
7378 			opts->ngsharedvt_arg_trampolines = atoi (arg + strlen ("ngsharedvt-trampolines="));
7379 		} else if (str_begins_with (arg, "tool-prefix=")) {
7380 			opts->tool_prefix = g_strdup (arg + strlen ("tool-prefix="));
7381 		} else if (str_begins_with (arg, "ld-flags=")) {
7382 			opts->ld_flags = g_strdup (arg + strlen ("ld-flags="));
7383 		} else if (str_begins_with (arg, "soft-debug")) {
7384 			opts->soft_debug = TRUE;
7385 		// Intentionally undocumented x2-- deprecated
7386 		} else if (str_begins_with (arg, "gen-seq-points-file=")) {
7387 			fprintf (stderr, "Mono Warning: aot option gen-seq-points-file= is deprecated.\n");
7388 		} else if (str_begins_with (arg, "gen-seq-points-file")) {
7389 			fprintf (stderr, "Mono Warning: aot option gen-seq-points-file is deprecated.\n");
7390 		} else if (str_begins_with (arg, "msym-dir=")) {
7391 			debug_options.no_seq_points_compact_data = FALSE;
7392 			opts->gen_msym_dir = TRUE;
7393 			opts->gen_msym_dir_path = g_strdup (arg + strlen ("msym_dir="));;
7394 		} else if (str_begins_with (arg, "direct-pinvoke")) {
7395 			opts->direct_pinvoke = TRUE;
7396 		} else if (str_begins_with (arg, "direct-icalls")) {
7397 			opts->direct_icalls = TRUE;
7398 		} else if (str_begins_with (arg, "no-direct-calls")) {
7399 			opts->no_direct_calls = TRUE;
7400 		} else if (str_begins_with (arg, "print-skipped")) {
7401 			opts->print_skipped_methods = TRUE;
7402 		} else if (str_begins_with (arg, "stats")) {
7403 			opts->stats = TRUE;
7404 		// Intentionally undocumented-- has no known function other than to debug the compiler
7405 		} else if (str_begins_with (arg, "no-instances")) {
7406 			opts->no_instances = TRUE;
7407 		// Intentionally undocumented x4-- Used for internal debugging of compiler
7408 		} else if (str_begins_with (arg, "log-generics")) {
7409 			opts->log_generics = TRUE;
7410 		} else if (str_begins_with (arg, "log-instances=")) {
7411 			opts->log_instances = TRUE;
7412 			opts->instances_logfile_path = g_strdup (arg + strlen ("log-instances="));
7413 		} else if (str_begins_with (arg, "log-instances")) {
7414 			opts->log_instances = TRUE;
7415 		} else if (str_begins_with (arg, "internal-logfile=")) {
7416 			opts->logfile = g_strdup (arg + strlen ("internal-logfile="));
7417 		} else if (str_begins_with (arg, "dedup-skip")) {
7418 			opts->dedup = TRUE;
7419 		} else if (str_begins_with (arg, "dedup-include=")) {
7420 			opts->dedup_include = g_strdup (arg + strlen ("dedup-include="));
7421 		} else if (str_begins_with (arg, "mtriple=")) {
7422 			opts->mtriple = g_strdup (arg + strlen ("mtriple="));
7423 		} else if (str_begins_with (arg, "llvm-path=")) {
7424 			opts->llvm_path = clean_path (g_strdup (arg + strlen ("llvm-path=")));
7425 		} else if (!strcmp (arg, "llvm")) {
7426 			opts->llvm = TRUE;
7427 		} else if (str_begins_with (arg, "readonly-value=")) {
7428 			add_readonly_value (opts, arg + strlen ("readonly-value="));
7429 		} else if (str_begins_with (arg, "info")) {
7430 			printf ("AOT target setup: %s.\n", AOT_TARGET_STR);
7431 			exit (0);
7432 		// Intentionally undocumented: Used for precise stack maps, which are not available yet
7433 		} else if (str_begins_with (arg, "gc-maps")) {
7434 			mini_gc_enable_gc_maps_for_aot ();
7435 		// Intentionally undocumented: Used for internal debugging
7436 		} else if (str_begins_with (arg, "dump")) {
7437 			opts->dump_json = TRUE;
7438 		} else if (str_begins_with (arg, "llvmonly")) {
7439 			opts->mode = MONO_AOT_MODE_FULL;
7440 			opts->llvm = TRUE;
7441 			opts->llvm_only = TRUE;
7442 		} else if (str_begins_with (arg, "data-outfile=")) {
7443 			opts->data_outfile = g_strdup (arg + strlen ("data-outfile="));
7444 		} else if (str_begins_with (arg, "profile=")) {
7445 			opts->profile_files = g_list_append (opts->profile_files, g_strdup (arg + strlen ("profile=")));
7446 		} else if (!strcmp (arg, "profile-only")) {
7447 			opts->profile_only = TRUE;
7448 		} else if (!strcmp (arg, "verbose")) {
7449 			opts->verbose = TRUE;
7450 		} else if (str_begins_with (arg, "help") || str_begins_with (arg, "?")) {
7451 			printf ("Supported options for --aot:\n");
7452 			printf ("    asmonly\n");
7453 			printf ("    bind-to-runtime-version\n");
7454 			printf ("    bitcode\n");
7455 			printf ("    data-outfile=\n");
7456 			printf ("    direct-icalls\n");
7457 			printf ("    direct-pinvoke\n");
7458 			printf ("    dwarfdebug\n");
7459 			printf ("    full\n");
7460 			printf ("    hybrid\n");
7461 			printf ("    info\n");
7462 			printf ("    keep-temps\n");
7463 			printf ("    llvm\n");
7464 			printf ("    llvmonly\n");
7465 			printf ("    llvm-outfile=\n");
7466 			printf ("    llvm-path=\n");
7467 			printf ("    msym-dir=\n");
7468 			printf ("    mtriple\n");
7469 			printf ("    nimt-trampolines=\n");
7470 			printf ("    nodebug\n");
7471 			printf ("    no-direct-calls\n");
7472 			printf ("    no-write-symbols\n");
7473 			printf ("    nrgctx-trampolines=\n");
7474 			printf ("    nrgctx-fetch-trampolines=\n");
7475 			printf ("    ngsharedvt-trampolines=\n");
7476 			printf ("    ntrampolines=\n");
7477 			printf ("    outfile=\n");
7478 			printf ("    profile=\n");
7479 			printf ("    profile-only\n");
7480 			printf ("    print-skipped-methods\n");
7481 			printf ("    readonly-value=\n");
7482 			printf ("    save-temps\n");
7483 			printf ("    soft-debug\n");
7484 			printf ("    static\n");
7485 			printf ("    stats\n");
7486 			printf ("    temp-path=\n");
7487 			printf ("    tool-prefix=\n");
7488 			printf ("    threads=\n");
7489 			printf ("    write-symbols\n");
7490 			printf ("    verbose\n");
7491 			printf ("    help/?\n");
7492 			exit (0);
7493 		} else {
7494 			fprintf (stderr, "AOT : Unknown argument '%s'.\n", arg);
7495 			exit (1);
7496 		}
7497 
7498 		g_free ((gpointer) arg);
7499 	}
7500 
7501 	if (opts->use_trampolines_page) {
7502 		opts->ntrampolines = 0;
7503 		opts->nrgctx_trampolines = 0;
7504 		opts->nimt_trampolines = 0;
7505 		opts->ngsharedvt_arg_trampolines = 0;
7506 	}
7507 
7508 	g_ptr_array_free (args, /*free_seg=*/TRUE);
7509 }
7510 
7511 static void
add_token_info_hash(gpointer key,gpointer value,gpointer user_data)7512 add_token_info_hash (gpointer key, gpointer value, gpointer user_data)
7513 {
7514 	MonoMethod *method = (MonoMethod*)key;
7515 	MonoJumpInfoToken *ji = (MonoJumpInfoToken*)value;
7516 	MonoAotCompile *acfg = (MonoAotCompile *)user_data;
7517 	MonoJumpInfoToken *new_ji;
7518 
7519 	new_ji = (MonoJumpInfoToken *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfoToken));
7520 	new_ji->image = ji->image;
7521 	new_ji->token = ji->token;
7522 	g_hash_table_insert (acfg->token_info_hash, method, new_ji);
7523 }
7524 
7525 static gboolean
can_encode_class(MonoAotCompile * acfg,MonoClass * klass)7526 can_encode_class (MonoAotCompile *acfg, MonoClass *klass)
7527 {
7528 	if (klass->type_token)
7529 		return TRUE;
7530 	if ((klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR) || (klass->byval_arg.type == MONO_TYPE_PTR))
7531 		return TRUE;
7532 	if (klass->rank)
7533 		return can_encode_class (acfg, klass->element_class);
7534 	return FALSE;
7535 }
7536 
7537 static gboolean
can_encode_method(MonoAotCompile * acfg,MonoMethod * method)7538 can_encode_method (MonoAotCompile *acfg, MonoMethod *method)
7539 {
7540 		if (method->wrapper_type) {
7541 			switch (method->wrapper_type) {
7542 			case MONO_WRAPPER_NONE:
7543 			case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
7544 			case MONO_WRAPPER_XDOMAIN_INVOKE:
7545 			case MONO_WRAPPER_STFLD:
7546 			case MONO_WRAPPER_LDFLD:
7547 			case MONO_WRAPPER_LDFLDA:
7548 			case MONO_WRAPPER_STELEMREF:
7549 			case MONO_WRAPPER_PROXY_ISINST:
7550 			case MONO_WRAPPER_ALLOC:
7551 			case MONO_WRAPPER_REMOTING_INVOKE:
7552 			case MONO_WRAPPER_UNKNOWN:
7553 			case MONO_WRAPPER_WRITE_BARRIER:
7554 			case MONO_WRAPPER_DELEGATE_INVOKE:
7555 			case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE:
7556 			case MONO_WRAPPER_DELEGATE_END_INVOKE:
7557 			case MONO_WRAPPER_SYNCHRONIZED:
7558 				break;
7559 			case MONO_WRAPPER_MANAGED_TO_MANAGED:
7560 			case MONO_WRAPPER_CASTCLASS: {
7561 				WrapperInfo *info = mono_marshal_get_wrapper_info (method);
7562 
7563 				if (info)
7564 					return TRUE;
7565 				else
7566 					return FALSE;
7567 				break;
7568 			}
7569 			default:
7570 				//printf ("Skip (wrapper call): %d -> %s\n", patch_info->type, mono_method_full_name (patch_info->data.method, TRUE));
7571 				return FALSE;
7572 			}
7573 		} else {
7574 			if (!method->token) {
7575 				/* The method is part of a constructed type like Int[,].Set (). */
7576 				if (!g_hash_table_lookup (acfg->token_info_hash, method)) {
7577 					if (method->klass->rank)
7578 						return TRUE;
7579 					return FALSE;
7580 				}
7581 			}
7582 		}
7583 		return TRUE;
7584 }
7585 
7586 static gboolean
can_encode_patch(MonoAotCompile * acfg,MonoJumpInfo * patch_info)7587 can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
7588 {
7589 	switch (patch_info->type) {
7590 	case MONO_PATCH_INFO_METHOD:
7591 	case MONO_PATCH_INFO_METHODCONST:
7592 	case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
7593 		MonoMethod *method = patch_info->data.method;
7594 
7595 		return can_encode_method (acfg, method);
7596 	}
7597 	case MONO_PATCH_INFO_VTABLE:
7598 	case MONO_PATCH_INFO_CLASS:
7599 	case MONO_PATCH_INFO_IID:
7600 	case MONO_PATCH_INFO_ADJUSTED_IID:
7601 		if (!can_encode_class (acfg, patch_info->data.klass)) {
7602 			//printf ("Skip: %s\n", mono_type_full_name (&patch_info->data.klass->byval_arg));
7603 			return FALSE;
7604 		}
7605 		break;
7606 	case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
7607 		if (!can_encode_class (acfg, patch_info->data.del_tramp->klass)) {
7608 			//printf ("Skip: %s\n", mono_type_full_name (&patch_info->data.klass->byval_arg));
7609 			return FALSE;
7610 		}
7611 		break;
7612 	}
7613 	case MONO_PATCH_INFO_RGCTX_FETCH:
7614 	case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
7615 		MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
7616 
7617 		if (!can_encode_method (acfg, entry->method))
7618 			return FALSE;
7619 		if (!can_encode_patch (acfg, entry->data))
7620 			return FALSE;
7621 		break;
7622 	}
7623 	default:
7624 		break;
7625 	}
7626 
7627 	return TRUE;
7628 }
7629 
7630 static gboolean
is_concrete_type(MonoType * t)7631 is_concrete_type (MonoType *t)
7632 {
7633 	MonoClass *klass;
7634 	int i;
7635 
7636 	if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR)
7637 		return FALSE;
7638 	if (t->type == MONO_TYPE_GENERICINST) {
7639 		MonoGenericContext *orig_ctx;
7640 		MonoGenericInst *inst;
7641 		MonoType *arg;
7642 
7643 		if (!MONO_TYPE_ISSTRUCT (t))
7644 			return TRUE;
7645 		klass = mono_class_from_mono_type (t);
7646 		orig_ctx = &mono_class_get_generic_class (klass)->context;
7647 
7648 		inst = orig_ctx->class_inst;
7649 		if (inst) {
7650 			for (i = 0; i < inst->type_argc; ++i) {
7651 				arg = mini_get_underlying_type (inst->type_argv [i]);
7652 				if (!is_concrete_type (arg))
7653 					return FALSE;
7654 			}
7655 		}
7656 		inst = orig_ctx->method_inst;
7657 		if (inst) {
7658 			for (i = 0; i < inst->type_argc; ++i) {
7659 				arg = mini_get_underlying_type (inst->type_argv [i]);
7660 				if (!is_concrete_type (arg))
7661 					return FALSE;
7662 			}
7663 		}
7664 	}
7665 	return TRUE;
7666 }
7667 
7668 /* LOCKING: Assumes the loader lock is held */
7669 static void
add_gsharedvt_wrappers(MonoAotCompile * acfg,MonoMethodSignature * sig,gboolean gsharedvt_in,gboolean gsharedvt_out)7670 add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean gsharedvt_in, gboolean gsharedvt_out)
7671 {
7672 	MonoMethod *wrapper;
7673 	gboolean concrete = TRUE;
7674 	gboolean add_in = gsharedvt_in;
7675 	gboolean add_out = gsharedvt_out;
7676 
7677 	if (gsharedvt_in && g_hash_table_lookup (acfg->gsharedvt_in_signatures, sig))
7678 		add_in = FALSE;
7679 	if (gsharedvt_out && g_hash_table_lookup (acfg->gsharedvt_out_signatures, sig))
7680 		add_out = FALSE;
7681 
7682 	if (!add_in && !add_out)
7683 		return;
7684 
7685 	if (mini_is_gsharedvt_variable_signature (sig))
7686 		return;
7687 
7688 	if (add_in)
7689 		g_hash_table_insert (acfg->gsharedvt_in_signatures, sig, sig);
7690 	if (add_out)
7691 		g_hash_table_insert (acfg->gsharedvt_out_signatures, sig, sig);
7692 
7693 	if (!sig->has_type_parameters) {
7694 		//printf ("%s\n", mono_signature_full_name (sig));
7695 
7696 		if (gsharedvt_in) {
7697 			wrapper = mini_get_gsharedvt_in_sig_wrapper (sig);
7698 			add_extra_method (acfg, wrapper);
7699 		}
7700 		if (gsharedvt_out) {
7701 			wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
7702 			add_extra_method (acfg, wrapper);
7703 		}
7704 	} else {
7705 		/* For signatures creared during generic sharing, convert them to a concrete signature if possible */
7706 		MonoMethodSignature *copy = mono_metadata_signature_dup (sig);
7707 		int i;
7708 
7709 		//printf ("%s\n", mono_signature_full_name (sig));
7710 
7711 		copy->ret = mini_get_underlying_type (sig->ret);
7712 		if (!is_concrete_type (copy->ret))
7713 			concrete = FALSE;
7714 		for (i = 0; i < sig->param_count; ++i) {
7715 			copy->params [i] = mini_get_underlying_type (sig->params [i]);
7716 			if (!is_concrete_type (copy->params [i]))
7717 				concrete = FALSE;
7718 		}
7719 		if (concrete) {
7720 			copy->has_type_parameters = 0;
7721 
7722 			if (gsharedvt_in) {
7723 				wrapper = mini_get_gsharedvt_in_sig_wrapper (copy);
7724 				add_extra_method (acfg, wrapper);
7725 			}
7726 
7727 			if (gsharedvt_out) {
7728 				wrapper = mini_get_gsharedvt_out_sig_wrapper (copy);
7729 				add_extra_method (acfg, wrapper);
7730 			}
7731 
7732 			//printf ("%s\n", mono_method_full_name (wrapper, 1));
7733 		}
7734 	}
7735 }
7736 
7737 /*
7738  * compile_method:
7739  *
7740  *   AOT compile a given method.
7741  * This function might be called by multiple threads, so it must be thread-safe.
7742  */
7743 static void
compile_method(MonoAotCompile * acfg,MonoMethod * method)7744 compile_method (MonoAotCompile *acfg, MonoMethod *method)
7745 {
7746 	MonoCompile *cfg;
7747 	MonoJumpInfo *patch_info;
7748 	gboolean skip;
7749 	int index, depth;
7750 	MonoMethod *wrapped;
7751 	GTimer *jit_timer;
7752 	JitFlags flags;
7753 
7754 	if (acfg->aot_opts.metadata_only)
7755 		return;
7756 
7757 	mono_acfg_lock (acfg);
7758 	index = get_method_index (acfg, method);
7759 	mono_acfg_unlock (acfg);
7760 
7761 	/* fixme: maybe we can also precompile wrapper methods */
7762 	if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7763 		(method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
7764 		(method->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
7765 		//printf ("Skip (impossible): %s\n", mono_method_full_name (method, TRUE));
7766 		return;
7767 	}
7768 
7769 	if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
7770 		return;
7771 
7772 	wrapped = mono_marshal_method_from_wrapper (method);
7773 	if (wrapped && (wrapped->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && wrapped->is_generic)
7774 		// FIXME: The wrapper should be generic too, but it is not
7775 		return;
7776 
7777 	if (method->wrapper_type == MONO_WRAPPER_COMINTEROP)
7778 		return;
7779 
7780 	if (acfg->aot_opts.profile_only && !method->is_inflated && !g_hash_table_lookup (acfg->profile_methods, method))
7781 		return;
7782 
7783 	mono_atomic_inc_i32 (&acfg->stats.mcount);
7784 
7785 #if 0
7786 	if (method->is_generic || mono_class_is_gtd (method->klass)) {
7787 		mono_atomic_inc_i32 (&acfg->stats.genericcount);
7788 		return;
7789 	}
7790 #endif
7791 
7792 	//acfg->aot_opts.print_skipped_methods = TRUE;
7793 
7794 	/*
7795 	 * Since these methods are the only ones which are compiled with
7796 	 * AOT support, and they are not used by runtime startup/shutdown code,
7797 	 * the runtime will not see AOT methods during AOT compilation,so it
7798 	 * does not need to support them by creating a fake GOT etc.
7799 	 */
7800 	flags = JIT_FLAG_AOT;
7801 	if (mono_aot_mode_is_full (&acfg->aot_opts))
7802 		flags = (JitFlags)(flags | JIT_FLAG_FULL_AOT);
7803 	if (acfg->llvm)
7804 		flags = (JitFlags)(flags | JIT_FLAG_LLVM);
7805 	if (acfg->aot_opts.llvm_only)
7806 		flags = (JitFlags)(flags | JIT_FLAG_LLVM_ONLY | JIT_FLAG_EXPLICIT_NULL_CHECKS);
7807 	if (acfg->aot_opts.no_direct_calls)
7808 		flags = (JitFlags)(flags | JIT_FLAG_NO_DIRECT_ICALLS);
7809 	if (acfg->aot_opts.direct_pinvoke)
7810 		flags = (JitFlags)(flags | JIT_FLAG_DIRECT_PINVOKE);
7811 
7812 	jit_timer = mono_time_track_start ();
7813 	cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), flags, 0, index);
7814 	mono_time_track_end (&mono_jit_stats.jit_time, jit_timer);
7815 
7816 	if (cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
7817 		if (acfg->aot_opts.print_skipped_methods)
7818 			printf ("Skip (gshared failure): %s (%s)\n", mono_method_get_full_name (method), cfg->exception_message);
7819 		mono_atomic_inc_i32 (&acfg->stats.genericcount);
7820 		return;
7821 	}
7822 	if (cfg->exception_type != MONO_EXCEPTION_NONE) {
7823 		/* Some instances cannot be JITted due to constraints etc. */
7824 		if (!method->is_inflated)
7825 			report_loader_error (acfg, &cfg->error, FALSE, "Unable to compile method '%s' due to: '%s'.\n", mono_method_get_full_name (method), mono_error_get_message (&cfg->error));
7826 		/* Let the exception happen at runtime */
7827 		return;
7828 	}
7829 
7830 	if (cfg->disable_aot) {
7831 		if (acfg->aot_opts.print_skipped_methods)
7832 			printf ("Skip (disabled): %s\n", mono_method_get_full_name (method));
7833 		mono_atomic_inc_i32 (&acfg->stats.ocount);
7834 		return;
7835 	}
7836 	cfg->method_index = index;
7837 
7838 	/* Nullify patches which need no aot processing */
7839 	for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
7840 		switch (patch_info->type) {
7841 		case MONO_PATCH_INFO_LABEL:
7842 		case MONO_PATCH_INFO_BB:
7843 			patch_info->type = MONO_PATCH_INFO_NONE;
7844 			break;
7845 		default:
7846 			break;
7847 		}
7848 	}
7849 
7850 	/* Collect method->token associations from the cfg */
7851 	mono_acfg_lock (acfg);
7852 	g_hash_table_foreach (cfg->token_info_hash, add_token_info_hash, acfg);
7853 	mono_acfg_unlock (acfg);
7854 	g_hash_table_destroy (cfg->token_info_hash);
7855 	cfg->token_info_hash = NULL;
7856 
7857 	/*
7858 	 * Check for absolute addresses.
7859 	 */
7860 	skip = FALSE;
7861 	for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
7862 		switch (patch_info->type) {
7863 		case MONO_PATCH_INFO_ABS:
7864 			/* unable to handle this */
7865 			skip = TRUE;
7866 			break;
7867 		default:
7868 			break;
7869 		}
7870 	}
7871 
7872 	if (skip) {
7873 		if (acfg->aot_opts.print_skipped_methods)
7874 			printf ("Skip (abs call): %s\n", mono_method_get_full_name (method));
7875 		mono_atomic_inc_i32 (&acfg->stats.abscount);
7876 		return;
7877 	}
7878 
7879 	/* Lock for the rest of the code */
7880 	mono_acfg_lock (acfg);
7881 
7882 	if (cfg->gsharedvt)
7883 		acfg->stats.method_categories [METHOD_CAT_GSHAREDVT] ++;
7884 	else if (cfg->gshared)
7885 		acfg->stats.method_categories [METHOD_CAT_INST] ++;
7886 	else if (cfg->method->wrapper_type)
7887 		acfg->stats.method_categories [METHOD_CAT_WRAPPER] ++;
7888 	else
7889 		acfg->stats.method_categories [METHOD_CAT_NORMAL] ++;
7890 
7891 	/*
7892 	 * Check for methods/klasses we can't encode.
7893 	 */
7894 	skip = FALSE;
7895 	for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
7896 		if (!can_encode_patch (acfg, patch_info))
7897 			skip = TRUE;
7898 	}
7899 
7900 	if (skip) {
7901 		if (acfg->aot_opts.print_skipped_methods)
7902 			printf ("Skip (patches): %s\n", mono_method_get_full_name (method));
7903 		acfg->stats.ocount++;
7904 		mono_acfg_unlock (acfg);
7905 		return;
7906 	}
7907 
7908 	if (!cfg->compile_llvm)
7909 		acfg->has_jitted_code = TRUE;
7910 
7911 	if (method->is_inflated && acfg->aot_opts.log_instances) {
7912 		if (acfg->instances_logfile)
7913 			fprintf (acfg->instances_logfile, "%s ### %d\n", mono_method_get_full_name (method), cfg->code_size);
7914 		else
7915 			printf ("%s ### %d\n", mono_method_get_full_name (method), cfg->code_size);
7916 	}
7917 
7918 	/* Adds generic instances referenced by this method */
7919 	/*
7920 	 * The depth is used to avoid infinite loops when generic virtual recursion is
7921 	 * encountered.
7922 	 */
7923 	depth = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_depth, method));
7924 	if (!acfg->aot_opts.no_instances && depth < 32 && (mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts))) {
7925 		for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
7926 			switch (patch_info->type) {
7927 			case MONO_PATCH_INFO_RGCTX_FETCH:
7928 			case MONO_PATCH_INFO_RGCTX_SLOT_INDEX:
7929 			case MONO_PATCH_INFO_METHOD:
7930 			case MONO_PATCH_INFO_METHOD_RGCTX: {
7931 				MonoMethod *m = NULL;
7932 
7933 				if (patch_info->type == MONO_PATCH_INFO_RGCTX_FETCH || patch_info->type == MONO_PATCH_INFO_RGCTX_SLOT_INDEX) {
7934 					MonoJumpInfoRgctxEntry *e = patch_info->data.rgctx_entry;
7935 
7936 					if (e->info_type == MONO_RGCTX_INFO_GENERIC_METHOD_CODE)
7937 						m = e->data->data.method;
7938 				} else {
7939 					m = patch_info->data.method;
7940 				}
7941 
7942 				if (!m)
7943 					break;
7944 				if (m->is_inflated && (mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts))) {
7945 					if (!(mono_class_generic_sharing_enabled (m->klass) &&
7946 						  mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE)) &&
7947 						(!method_has_type_vars (m) || mono_method_is_generic_sharable_full (m, TRUE, TRUE, FALSE))) {
7948 						if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7949 							if (mono_aot_mode_is_full (&acfg->aot_opts) && !method_has_type_vars (m))
7950 								add_extra_method_with_depth (acfg, mono_marshal_get_native_wrapper (m, TRUE, TRUE), depth + 1);
7951 						} else {
7952 							add_extra_method_with_depth (acfg, m, depth + 1);
7953 							add_types_from_method_header (acfg, m);
7954 						}
7955 					}
7956 					add_generic_class_with_depth (acfg, m->klass, depth + 5, "method");
7957 				}
7958 				if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
7959 					WrapperInfo *info = mono_marshal_get_wrapper_info (m);
7960 
7961 					if (info && info->subtype == WRAPPER_SUBTYPE_ELEMENT_ADDR)
7962 						add_extra_method_with_depth (acfg, m, depth + 1);
7963 				}
7964 				break;
7965 			}
7966 			case MONO_PATCH_INFO_VTABLE: {
7967 				MonoClass *klass = patch_info->data.klass;
7968 
7969 				if (mono_class_is_ginst (klass) && !mini_class_is_generic_sharable (klass))
7970 					add_generic_class_with_depth (acfg, klass, depth + 5, "vtable");
7971 				break;
7972 			}
7973 			case MONO_PATCH_INFO_SFLDA: {
7974 				MonoClass *klass = patch_info->data.field->parent;
7975 
7976 				/* The .cctor needs to run at runtime. */
7977 				if (mono_class_is_ginst (klass) && !mono_generic_context_is_sharable_full (&mono_class_get_generic_class (klass)->context, FALSE, FALSE) && mono_class_get_cctor (klass))
7978 					add_extra_method_with_depth (acfg, mono_class_get_cctor (klass), depth + 1);
7979 				break;
7980 			}
7981 			default:
7982 				break;
7983 			}
7984 		}
7985 	}
7986 
7987 	/* Determine whenever the method has GOT slots */
7988 	for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
7989 		switch (patch_info->type) {
7990 		case MONO_PATCH_INFO_GOT_OFFSET:
7991 		case MONO_PATCH_INFO_NONE:
7992 		case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
7993 		case MONO_PATCH_INFO_GC_NURSERY_START:
7994 		case MONO_PATCH_INFO_GC_NURSERY_BITS:
7995 			break;
7996 		case MONO_PATCH_INFO_IMAGE:
7997 			/* The assembly is stored in GOT slot 0 */
7998 			if (patch_info->data.image != acfg->image)
7999 				cfg->has_got_slots = TRUE;
8000 			break;
8001 		default:
8002 			if (!is_plt_patch (patch_info) || (cfg->compile_llvm && acfg->aot_opts.llvm_only))
8003 				cfg->has_got_slots = TRUE;
8004 			break;
8005 		}
8006 	}
8007 
8008 	if (!cfg->has_got_slots)
8009 		mono_atomic_inc_i32 (&acfg->stats.methods_without_got_slots);
8010 
8011 	/* Add gsharedvt wrappers for signatures used by the method */
8012 	if (acfg->aot_opts.llvm_only) {
8013 		GSList *l;
8014 
8015 		if (!cfg->method->wrapper_type || cfg->method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE)
8016 			/* These only need out wrappers */
8017 			add_gsharedvt_wrappers (acfg, mono_method_signature (cfg->method), FALSE, TRUE);
8018 
8019 		for (l = cfg->signatures; l; l = l->next) {
8020 			MonoMethodSignature *sig = mono_metadata_signature_dup ((MonoMethodSignature*)l->data);
8021 
8022 			/* These only need in wrappers */
8023 			add_gsharedvt_wrappers (acfg, sig, TRUE, FALSE);
8024 		}
8025 	}
8026 
8027 	/*
8028 	 * FIXME: Instead of this mess, allocate the patches from the aot mempool.
8029 	 */
8030 	/* Make a copy of the patch info which is in the mempool */
8031 	{
8032 		MonoJumpInfo *patches = NULL, *patches_end = NULL;
8033 
8034 		for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
8035 			MonoJumpInfo *new_patch_info = mono_patch_info_dup_mp (acfg->mempool, patch_info);
8036 
8037 			if (!patches)
8038 				patches = new_patch_info;
8039 			else
8040 				patches_end->next = new_patch_info;
8041 			patches_end = new_patch_info;
8042 		}
8043 		cfg->patch_info = patches;
8044 	}
8045 	/* Make a copy of the unwind info */
8046 	{
8047 		GSList *l, *unwind_ops;
8048 		MonoUnwindOp *op;
8049 
8050 		unwind_ops = NULL;
8051 		for (l = cfg->unwind_ops; l; l = l->next) {
8052 			op = (MonoUnwindOp *)mono_mempool_alloc (acfg->mempool, sizeof (MonoUnwindOp));
8053 			memcpy (op, l->data, sizeof (MonoUnwindOp));
8054 			unwind_ops = g_slist_prepend_mempool (acfg->mempool, unwind_ops, op);
8055 		}
8056 		cfg->unwind_ops = g_slist_reverse (unwind_ops);
8057 	}
8058 	/* Make a copy of the argument/local info */
8059 	{
8060 		MonoError error;
8061 		MonoInst **args, **locals;
8062 		MonoMethodSignature *sig;
8063 		MonoMethodHeader *header;
8064 		int i;
8065 
8066 		sig = mono_method_signature (method);
8067 		args = (MonoInst **)mono_mempool_alloc (acfg->mempool, sizeof (MonoInst*) * (sig->param_count + sig->hasthis));
8068 		for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
8069 			args [i] = (MonoInst *)mono_mempool_alloc (acfg->mempool, sizeof (MonoInst));
8070 			memcpy (args [i], cfg->args [i], sizeof (MonoInst));
8071 		}
8072 		cfg->args = args;
8073 
8074 		header = mono_method_get_header_checked (method, &error);
8075 		mono_error_assert_ok (&error); /* FIXME don't swallow the error */
8076 		locals = (MonoInst **)mono_mempool_alloc (acfg->mempool, sizeof (MonoInst*) * header->num_locals);
8077 		for (i = 0; i < header->num_locals; ++i) {
8078 			locals [i] = (MonoInst *)mono_mempool_alloc (acfg->mempool, sizeof (MonoInst));
8079 			memcpy (locals [i], cfg->locals [i], sizeof (MonoInst));
8080 		}
8081 		mono_metadata_free_mh (header);
8082 		cfg->locals = locals;
8083 	}
8084 
8085 	/* Free some fields used by cfg to conserve memory */
8086 	mono_empty_compile (cfg);
8087 
8088 	//printf ("Compile:           %s\n", mono_method_full_name (method, TRUE));
8089 
8090 	while (index >= acfg->cfgs_size) {
8091 		MonoCompile **new_cfgs;
8092 		int new_size;
8093 
8094 		new_size = acfg->cfgs_size * 2;
8095 		new_cfgs = g_new0 (MonoCompile*, new_size);
8096 		memcpy (new_cfgs, acfg->cfgs, sizeof (MonoCompile*) * acfg->cfgs_size);
8097 		g_free (acfg->cfgs);
8098 		acfg->cfgs = new_cfgs;
8099 		acfg->cfgs_size = new_size;
8100 	}
8101 	acfg->cfgs [index] = cfg;
8102 
8103 	g_hash_table_insert (acfg->method_to_cfg, cfg->orig_method, cfg);
8104 
8105 	/* Update global stats while holding a lock. */
8106 	mono_update_jit_stats (cfg);
8107 
8108 	/*
8109 	if (cfg->orig_method->wrapper_type)
8110 		g_ptr_array_add (acfg->extra_methods, cfg->orig_method);
8111 	*/
8112 
8113 	mono_acfg_unlock (acfg);
8114 
8115 	mono_atomic_inc_i32 (&acfg->stats.ccount);
8116 }
8117 
8118 static mono_thread_start_return_t WINAPI
compile_thread_main(gpointer user_data)8119 compile_thread_main (gpointer user_data)
8120 {
8121 	MonoAotCompile *acfg = ((MonoAotCompile **)user_data) [0];
8122 	GPtrArray *methods = ((GPtrArray **)user_data) [1];
8123 	int i;
8124 
8125 	MonoError error;
8126 	MonoInternalThread *internal = mono_thread_internal_current ();
8127 	MonoString *str = mono_string_new_checked (mono_domain_get (), "AOT compiler", &error);
8128 	mono_error_assert_ok (&error);
8129 	mono_thread_set_name_internal (internal, str, TRUE, FALSE, &error);
8130 	mono_error_assert_ok (&error);
8131 
8132 	for (i = 0; i < methods->len; ++i)
8133 		compile_method (acfg, (MonoMethod *)g_ptr_array_index (methods, i));
8134 
8135 	return 0;
8136 }
8137 
8138 /* Used by the LLVM backend */
8139 guint32
mono_aot_get_got_offset(MonoJumpInfo * ji)8140 mono_aot_get_got_offset (MonoJumpInfo *ji)
8141 {
8142 	return get_got_offset (llvm_acfg, TRUE, ji);
8143 }
8144 
8145 /*
8146  * mono_aot_is_shared_got_offset:
8147  *
8148  *   Return whenever OFFSET refers to a GOT slot which is preinitialized
8149  * when the AOT image is loaded.
8150  */
8151 gboolean
mono_aot_is_shared_got_offset(int offset)8152 mono_aot_is_shared_got_offset (int offset)
8153 {
8154 	return offset < llvm_acfg->nshared_got_entries;
8155 }
8156 
8157 char*
mono_aot_get_method_name(MonoCompile * cfg)8158 mono_aot_get_method_name (MonoCompile *cfg)
8159 {
8160 	if (llvm_acfg->aot_opts.static_link)
8161 		/* Include the assembly name too to avoid duplicate symbol errors */
8162 		return g_strdup_printf ("%s_%s", llvm_acfg->assembly_name_sym, get_debug_sym (cfg->orig_method, "", llvm_acfg->method_label_hash));
8163 	else
8164 		return get_debug_sym (cfg->orig_method, "", llvm_acfg->method_label_hash);
8165 }
8166 
8167 /*
8168  * mono_aot_is_linkonce_method:
8169  *
8170  *   Return whenever METHOD should be emitted with linkonce linkage,
8171  * eliminating duplicate copies when compiling in static mode.
8172  */
8173 gboolean
mono_aot_is_linkonce_method(MonoMethod * method)8174 mono_aot_is_linkonce_method (MonoMethod *method)
8175 {
8176 	return FALSE;
8177 #if 0
8178 	WrapperInfo *info;
8179 
8180 	// FIXME: Add more cases
8181 	if (method->wrapper_type != MONO_WRAPPER_UNKNOWN)
8182 		return FALSE;
8183 	info = mono_marshal_get_wrapper_info (method);
8184 	if ((info && (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG || info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG)))
8185 		return TRUE;
8186 	return FALSE;
8187 #endif
8188 }
8189 
8190 static gboolean
append_mangled_type(GString * s,MonoType * t)8191 append_mangled_type (GString *s, MonoType *t)
8192 {
8193 	if (t->byref)
8194 		g_string_append_printf (s, "b");
8195 	switch (t->type) {
8196 	case MONO_TYPE_VOID:
8197 		g_string_append_printf (s, "void_");
8198 		break;
8199 	case MONO_TYPE_I1:
8200 		g_string_append_printf (s, "i1");
8201 		break;
8202 	case MONO_TYPE_U1:
8203 		g_string_append_printf (s, "u1");
8204 		break;
8205 	case MONO_TYPE_I2:
8206 		g_string_append_printf (s, "i2");
8207 		break;
8208 	case MONO_TYPE_U2:
8209 		g_string_append_printf (s, "u2");
8210 		break;
8211 	case MONO_TYPE_I4:
8212 		g_string_append_printf (s, "i4");
8213 		break;
8214 	case MONO_TYPE_U4:
8215 		g_string_append_printf (s, "u4");
8216 		break;
8217 	case MONO_TYPE_I8:
8218 		g_string_append_printf (s, "i8");
8219 		break;
8220 	case MONO_TYPE_U8:
8221 		g_string_append_printf (s, "u8");
8222 		break;
8223 	case MONO_TYPE_I:
8224 		g_string_append_printf (s, "ii");
8225 		break;
8226 	case MONO_TYPE_U:
8227 		g_string_append_printf (s, "ui");
8228 		break;
8229 	case MONO_TYPE_R4:
8230 		g_string_append_printf (s, "fl");
8231 		break;
8232 	case MONO_TYPE_R8:
8233 		g_string_append_printf (s, "do");
8234 		break;
8235 	default: {
8236 		char *fullname = mono_type_full_name (t);
8237 		GString *temp;
8238 		char *temps;
8239 		int i, len;
8240 
8241 		/*
8242 		 * Have to create a mangled name which is:
8243 		 * - a valid symbol
8244 		 * - unique
8245 		 */
8246 		temp = g_string_new ("");
8247 		len = strlen (fullname);
8248 		for (i = 0; i < len; ++i) {
8249 			char c = fullname [i];
8250 			if (isalnum (c)) {
8251 				g_string_append_c (temp, c);
8252 			} else if (c == '_') {
8253 				g_string_append_c (temp, '_');
8254 				g_string_append_c (temp, '_');
8255 			} else {
8256 				g_string_append_c (temp, '_');
8257 				g_string_append_printf (temp, "%x", (int)c);
8258 			}
8259 		}
8260 		temps = g_string_free (temp, FALSE);
8261 		/* Include the length to avoid different length type names aliasing each other */
8262 		g_string_append_printf (s, "cl%x_%s_", strlen (temps), temps);
8263 		g_free (temps);
8264 	}
8265 	}
8266 	if (t->attrs)
8267 		g_string_append_printf (s, "_attrs_%d", t->attrs);
8268 	return TRUE;
8269 }
8270 
8271 static gboolean
append_mangled_signature(GString * s,MonoMethodSignature * sig)8272 append_mangled_signature (GString *s, MonoMethodSignature *sig)
8273 {
8274 	int i;
8275 	gboolean supported;
8276 
8277 	supported = append_mangled_type (s, sig->ret);
8278 	if (!supported)
8279 		return FALSE;
8280 	if (sig->hasthis)
8281 		g_string_append_printf (s, "this_");
8282 	if (sig->pinvoke)
8283 		g_string_append_printf (s, "pinvoke_");
8284 	for (i = 0; i < sig->param_count; ++i) {
8285 		supported = append_mangled_type (s, sig->params [i]);
8286 		if (!supported)
8287 			return FALSE;
8288 	}
8289 
8290 	return TRUE;
8291 }
8292 
8293 static void
append_mangled_wrapper_type(GString * s,guint32 wrapper_type)8294 append_mangled_wrapper_type (GString *s, guint32 wrapper_type)
8295 {
8296 	const char *label;
8297 
8298 	switch (wrapper_type) {
8299 	case MONO_WRAPPER_REMOTING_INVOKE:
8300 		label = "remoting_invoke";
8301 		break;
8302 	case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
8303 		label = "remoting_invoke_check";
8304 		break;
8305 	case MONO_WRAPPER_XDOMAIN_INVOKE:
8306 		label = "remoting_invoke_xdomain";
8307 		break;
8308 	case MONO_WRAPPER_PROXY_ISINST:
8309 		label = "proxy_isinst";
8310 		break;
8311 	case MONO_WRAPPER_LDFLD:
8312 		label = "ldfld";
8313 		break;
8314 	case MONO_WRAPPER_LDFLDA:
8315 		label = "ldflda";
8316 		break;
8317 	case MONO_WRAPPER_STFLD:
8318 		label = "stfld";
8319 		break;
8320 	case MONO_WRAPPER_ALLOC:
8321 		label = "alloc";
8322 		break;
8323 	case MONO_WRAPPER_WRITE_BARRIER:
8324 		label = "write_barrier";
8325 		break;
8326 	case MONO_WRAPPER_STELEMREF:
8327 		label = "stelemref";
8328 		break;
8329 	case MONO_WRAPPER_UNKNOWN:
8330 		label = "unknown";
8331 		break;
8332 	case MONO_WRAPPER_MANAGED_TO_NATIVE:
8333 		label = "man2native";
8334 		break;
8335 	case MONO_WRAPPER_SYNCHRONIZED:
8336 		label = "synch";
8337 		break;
8338 	case MONO_WRAPPER_MANAGED_TO_MANAGED:
8339 		label = "man2man";
8340 		break;
8341 	case MONO_WRAPPER_CASTCLASS:
8342 		label = "castclass";
8343 		break;
8344 	case MONO_WRAPPER_RUNTIME_INVOKE:
8345 		label = "run_invoke";
8346 		break;
8347 	case MONO_WRAPPER_DELEGATE_INVOKE:
8348 		label = "del_inv";
8349 		break;
8350 	case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE:
8351 		label = "del_beg_inv";
8352 		break;
8353 	case MONO_WRAPPER_DELEGATE_END_INVOKE:
8354 		label = "del_end_inv";
8355 		break;
8356 	case MONO_WRAPPER_NATIVE_TO_MANAGED:
8357 		label = "native2man";
8358 		break;
8359 	default:
8360 		g_assert_not_reached ();
8361 	}
8362 
8363 	g_string_append_printf (s, "%s_", label);
8364 }
8365 
8366 static void
append_mangled_wrapper_subtype(GString * s,WrapperSubtype subtype)8367 append_mangled_wrapper_subtype (GString *s, WrapperSubtype subtype)
8368 {
8369 	const char *label;
8370 
8371 	switch (subtype)
8372 	{
8373 	case WRAPPER_SUBTYPE_NONE:
8374 		return;
8375 	case WRAPPER_SUBTYPE_ELEMENT_ADDR:
8376 		label = "elem_addr";
8377 		break;
8378 	case WRAPPER_SUBTYPE_STRING_CTOR:
8379 		label = "str_ctor";
8380 		break;
8381 	case WRAPPER_SUBTYPE_VIRTUAL_STELEMREF:
8382 		label = "virt_stelem";
8383 		break;
8384 	case WRAPPER_SUBTYPE_FAST_MONITOR_ENTER:
8385 		label = "fast_mon_enter";
8386 		break;
8387 	case WRAPPER_SUBTYPE_FAST_MONITOR_ENTER_V4:
8388 		label = "fast_mon_enter_4";
8389 		break;
8390 	case WRAPPER_SUBTYPE_FAST_MONITOR_EXIT:
8391 		label = "fast_monitor_exit";
8392 		break;
8393 	case WRAPPER_SUBTYPE_PTR_TO_STRUCTURE:
8394 		label = "ptr2struct";
8395 		break;
8396 	case WRAPPER_SUBTYPE_STRUCTURE_TO_PTR:
8397 		label = "struct2ptr";
8398 		break;
8399 	case WRAPPER_SUBTYPE_CASTCLASS_WITH_CACHE:
8400 		label = "castclass_w_cache";
8401 		break;
8402 	case WRAPPER_SUBTYPE_ISINST_WITH_CACHE:
8403 		label = "isinst_w_cache";
8404 		break;
8405 	case WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL:
8406 		label = "run_inv_norm";
8407 		break;
8408 	case WRAPPER_SUBTYPE_RUNTIME_INVOKE_DYNAMIC:
8409 		label = "run_inv_dyn";
8410 		break;
8411 	case WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT:
8412 		label = "run_inv_dir";
8413 		break;
8414 	case WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL:
8415 		label = "run_inv_vir";
8416 		break;
8417 	case WRAPPER_SUBTYPE_ICALL_WRAPPER:
8418 		label = "icall";
8419 		break;
8420 	case WRAPPER_SUBTYPE_NATIVE_FUNC_AOT:
8421 		label = "native_func_aot";
8422 		break;
8423 	case WRAPPER_SUBTYPE_PINVOKE:
8424 		label = "pinvoke";
8425 		break;
8426 	case WRAPPER_SUBTYPE_SYNCHRONIZED_INNER:
8427 		label = "synch_inner";
8428 		break;
8429 	case WRAPPER_SUBTYPE_GSHAREDVT_IN:
8430 		label = "gshared_in";
8431 		break;
8432 	case WRAPPER_SUBTYPE_GSHAREDVT_OUT:
8433 		label = "gshared_out";
8434 		break;
8435 	case WRAPPER_SUBTYPE_ARRAY_ACCESSOR:
8436 		label = "array_acc";
8437 		break;
8438 	case WRAPPER_SUBTYPE_GENERIC_ARRAY_HELPER:
8439 		label = "generic_arry_help";
8440 		break;
8441 	case WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL:
8442 		label = "del_inv_virt";
8443 		break;
8444 	case WRAPPER_SUBTYPE_DELEGATE_INVOKE_BOUND:
8445 		label = "del_inv_bound";
8446 		break;
8447 	case WRAPPER_SUBTYPE_INTERP_IN:
8448 		label = "interp_in";
8449 		break;
8450 	case WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG:
8451 		label = "gsharedvt_in_sig";
8452 		break;
8453 	case WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG:
8454 		label = "gsharedvt_out_sig";
8455 		break;
8456 	default:
8457 		g_assert_not_reached ();
8458 	}
8459 
8460 	g_string_append_printf (s, "%s_", label);
8461 }
8462 
8463 static char *
sanitize_mangled_string(const char * input)8464 sanitize_mangled_string (const char *input)
8465 {
8466 	GString *s = g_string_new ("");
8467 
8468 	for (int i=0; input [i] != '\0'; i++) {
8469 		char c = input [i];
8470 		switch (c) {
8471 		case '.':
8472 			g_string_append (s, "_dot_");
8473 			break;
8474 		case ' ':
8475 			g_string_append (s, "_");
8476 			break;
8477 		case '`':
8478 			g_string_append (s, "_bt_");
8479 			break;
8480 		case '<':
8481 			g_string_append (s, "_le_");
8482 			break;
8483 		case '>':
8484 			g_string_append (s, "_gt_");
8485 			break;
8486 		case '/':
8487 			g_string_append (s, "_sl_");
8488 			break;
8489 		case '[':
8490 			g_string_append (s, "_lbrack_");
8491 			break;
8492 		case ']':
8493 			g_string_append (s, "_rbrack_");
8494 			break;
8495 		case '(':
8496 			g_string_append (s, "_lparen_");
8497 			break;
8498 		case '-':
8499 			g_string_append (s, "_dash_");
8500 			break;
8501 		case ')':
8502 			g_string_append (s, "_rparen_");
8503 			break;
8504 		case ',':
8505 			g_string_append (s, "_comma_");
8506 			break;
8507 		case ':':
8508 			g_string_append (s, "_colon_");
8509 			break;
8510 		default:
8511 			g_string_append_c (s, c);
8512 		}
8513 	}
8514 
8515 	return g_string_free (s, FALSE);
8516 }
8517 
8518 static gboolean
append_mangled_klass(GString * s,MonoClass * klass)8519 append_mangled_klass (GString *s, MonoClass *klass)
8520 {
8521 	char *klass_desc = mono_class_full_name (klass);
8522 	g_string_append_printf (s, "_%s_%s_", klass->name_space, klass_desc);
8523 	g_free (klass_desc);
8524 
8525 	// Success
8526 	return TRUE;
8527 }
8528 
8529 static gboolean
8530 append_mangled_method (GString *s, MonoMethod *method);
8531 
8532 static gboolean
append_mangled_wrapper(GString * s,MonoMethod * method)8533 append_mangled_wrapper (GString *s, MonoMethod *method)
8534 {
8535 	gboolean success = TRUE;
8536 	WrapperInfo *info = mono_marshal_get_wrapper_info (method);
8537 	g_string_append_printf (s, "wrapper_");
8538 	g_string_append_printf (s, "%s_", method->klass->image->assembly->aname.name);
8539 
8540 	append_mangled_wrapper_type (s, method->wrapper_type);
8541 
8542 	switch (method->wrapper_type) {
8543 	case MONO_WRAPPER_REMOTING_INVOKE:
8544 	case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
8545 	case MONO_WRAPPER_XDOMAIN_INVOKE: {
8546 		MonoMethod *m = mono_marshal_method_from_wrapper (method);
8547 		g_assert (m);
8548 		success = success && append_mangled_method (s, m);
8549 		break;
8550 	}
8551 	case MONO_WRAPPER_PROXY_ISINST:
8552 	case MONO_WRAPPER_LDFLD:
8553 	case MONO_WRAPPER_LDFLDA:
8554 	case MONO_WRAPPER_STFLD: {
8555 		g_assert (info);
8556 		success = success && append_mangled_klass (s, info->d.proxy.klass);
8557 		break;
8558 	}
8559 	case MONO_WRAPPER_ALLOC: {
8560 		/* The GC name is saved once in MonoAotFileInfo */
8561 		g_assert (info->d.alloc.alloc_type != -1);
8562 		g_string_append_printf (s, "%d_", info->d.alloc.alloc_type);
8563 		// SlowAlloc, etc
8564 		g_string_append_printf (s, "%s_", method->name);
8565 		break;
8566 	}
8567 	case MONO_WRAPPER_WRITE_BARRIER: {
8568 		g_string_append_printf (s, "%s_", method->name);
8569 		break;
8570 	}
8571 	case MONO_WRAPPER_STELEMREF: {
8572 		append_mangled_wrapper_subtype (s, info->subtype);
8573 		if (info->subtype == WRAPPER_SUBTYPE_VIRTUAL_STELEMREF)
8574 			g_string_append_printf (s, "%d", info->d.virtual_stelemref.kind);
8575 		break;
8576 	}
8577 	case MONO_WRAPPER_UNKNOWN: {
8578 		append_mangled_wrapper_subtype (s, info->subtype);
8579 		if (info->subtype == WRAPPER_SUBTYPE_PTR_TO_STRUCTURE ||
8580 			info->subtype == WRAPPER_SUBTYPE_STRUCTURE_TO_PTR)
8581 			success = success && append_mangled_klass (s, method->klass);
8582 		else if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER)
8583 			success = success && append_mangled_method (s, info->d.synchronized_inner.method);
8584 		else if (info->subtype == WRAPPER_SUBTYPE_ARRAY_ACCESSOR)
8585 			success = success && append_mangled_method (s, info->d.array_accessor.method);
8586 		else if (info->subtype == WRAPPER_SUBTYPE_INTERP_IN)
8587 			append_mangled_signature (s, info->d.interp_in.sig);
8588 		else if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG)
8589 			append_mangled_signature (s, info->d.gsharedvt.sig);
8590 		else if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG)
8591 			append_mangled_signature (s, info->d.gsharedvt.sig);
8592 		break;
8593 	}
8594 	case MONO_WRAPPER_MANAGED_TO_NATIVE: {
8595 		append_mangled_wrapper_subtype (s, info->subtype);
8596 		if (info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
8597 			g_string_append_printf (s, "%s", method->name);
8598 		} else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_AOT) {
8599 			success = success && append_mangled_method (s, info->d.managed_to_native.method);
8600 		} else {
8601 			g_assert (info->subtype == WRAPPER_SUBTYPE_NONE || info->subtype == WRAPPER_SUBTYPE_PINVOKE);
8602 			success = success && append_mangled_method (s, info->d.managed_to_native.method);
8603 		}
8604 		break;
8605 	}
8606 	case MONO_WRAPPER_SYNCHRONIZED: {
8607 		MonoMethod *m;
8608 
8609 		m = mono_marshal_method_from_wrapper (method);
8610 		g_assert (m);
8611 		g_assert (m != method);
8612 		success = success && append_mangled_method (s, m);
8613 		break;
8614 	}
8615 	case MONO_WRAPPER_MANAGED_TO_MANAGED: {
8616 		append_mangled_wrapper_subtype (s, info->subtype);
8617 
8618 		if (info->subtype == WRAPPER_SUBTYPE_ELEMENT_ADDR) {
8619 			g_string_append_printf (s, "%d_", info->d.element_addr.rank);
8620 			g_string_append_printf (s, "%d_", info->d.element_addr.elem_size);
8621 		} else if (info->subtype == WRAPPER_SUBTYPE_STRING_CTOR) {
8622 			success = success && append_mangled_method (s, info->d.string_ctor.method);
8623 		} else if (info->subtype == WRAPPER_SUBTYPE_GENERIC_ARRAY_HELPER) {
8624 			success = success && append_mangled_method (s, info->d.generic_array_helper.method);
8625 		} else {
8626 			success = FALSE;
8627 		}
8628 		break;
8629 	}
8630 	case MONO_WRAPPER_CASTCLASS: {
8631 		append_mangled_wrapper_subtype (s, info->subtype);
8632 		break;
8633 	}
8634 	case MONO_WRAPPER_RUNTIME_INVOKE: {
8635 		append_mangled_wrapper_subtype (s, info->subtype);
8636 		if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT || info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL)
8637 			success = success && append_mangled_method (s, info->d.runtime_invoke.method);
8638 		else if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL)
8639 			success = success && append_mangled_signature (s, info->d.runtime_invoke.sig);
8640 		break;
8641 	}
8642 	case MONO_WRAPPER_DELEGATE_INVOKE:
8643 	case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE:
8644 	case MONO_WRAPPER_DELEGATE_END_INVOKE: {
8645 		if (method->is_inflated) {
8646 			/* These wrappers are identified by their class */
8647 			g_string_append_printf (s, "i_");
8648 			success = success && append_mangled_klass (s, method->klass);
8649 		} else {
8650 			WrapperInfo *info = mono_marshal_get_wrapper_info (method);
8651 
8652 			g_string_append_printf (s, "u_");
8653 			if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE)
8654 				append_mangled_wrapper_subtype (s, info->subtype);
8655 			g_string_append_printf (s, "u_sigstart");
8656 		}
8657 		break;
8658 	}
8659 	case MONO_WRAPPER_NATIVE_TO_MANAGED: {
8660 		g_assert (info);
8661 		success = success && append_mangled_method (s, info->d.native_to_managed.method);
8662 		success = success && append_mangled_klass (s, method->klass);
8663 		break;
8664 	}
8665 	default:
8666 		g_assert_not_reached ();
8667 	}
8668 	return success && append_mangled_signature (s, mono_method_signature (method));
8669 }
8670 
8671 static void
append_mangled_ginst(GString * str,MonoGenericInst * ginst)8672 append_mangled_ginst (GString *str, MonoGenericInst *ginst)
8673 {
8674 	int i;
8675 
8676 	for (i = 0; i < ginst->type_argc; ++i) {
8677 		if (i > 0)
8678 			g_string_append (str, ", ");
8679 		MonoType *type = ginst->type_argv [i];
8680 		switch (type->type) {
8681 		case MONO_TYPE_VAR:
8682 		case MONO_TYPE_MVAR: {
8683 			MonoType *constraint = NULL;
8684 			if (type->data.generic_param)
8685 				constraint = type->data.generic_param->gshared_constraint;
8686 			if (constraint) {
8687 				g_assert (constraint->type != MONO_TYPE_VAR && constraint->type != MONO_TYPE_MVAR);
8688 				g_string_append (str, "gshared:");
8689 				mono_type_get_desc (str, constraint, TRUE);
8690 				break;
8691 			}
8692 			// Else falls through to common case
8693 		}
8694 		default:
8695 			mono_type_get_desc (str, type, TRUE);
8696 		}
8697 	}
8698 }
8699 
8700 static void
append_mangled_context(GString * str,MonoGenericContext * context)8701 append_mangled_context (GString *str, MonoGenericContext *context)
8702 {
8703 	GString *res = g_string_new ("");
8704 
8705 	g_string_append_printf (res, "gens_");
8706 	g_string_append (res, "00");
8707 
8708 	gboolean good = context->class_inst && context->class_inst->type_argc > 0;
8709 	good = good || (context->method_inst && context->method_inst->type_argc > 0);
8710 	g_assert (good);
8711 
8712 	if (context->class_inst)
8713 		append_mangled_ginst (res, context->class_inst);
8714 	if (context->method_inst) {
8715 		if (context->class_inst)
8716 			g_string_append (res, "11");
8717 		append_mangled_ginst (res, context->method_inst);
8718 	}
8719 	g_string_append_printf (str, "gens_%s", res->str);
8720 	g_free (res);
8721 }
8722 
8723 static gboolean
append_mangled_method(GString * s,MonoMethod * method)8724 append_mangled_method (GString *s, MonoMethod *method)
8725 {
8726 	if (method->wrapper_type)
8727 		return append_mangled_wrapper (s, method);
8728 
8729 	if (method->is_inflated) {
8730 		g_string_append_printf (s, "inflated_");
8731 		MonoMethodInflated *imethod = (MonoMethodInflated*) method;
8732 		g_assert (imethod->context.class_inst != NULL || imethod->context.method_inst != NULL);
8733 
8734 		append_mangled_context (s, &imethod->context);
8735 		g_string_append_printf (s, "_declared_by_");
8736 		append_mangled_method (s, imethod->declaring);
8737 	} else if (method->is_generic) {
8738 		g_string_append_printf (s, "%s_", method->klass->image->assembly->aname.name);
8739 
8740 		g_string_append_printf (s, "generic_");
8741 		append_mangled_klass (s, method->klass);
8742 		g_string_append_printf (s, "_%s_", method->name);
8743 
8744 		MonoGenericContainer *container = mono_method_get_generic_container (method);
8745 		g_string_append_printf (s, "_%s");
8746 		append_mangled_context (s, &container->context);
8747 
8748 		return append_mangled_signature (s, mono_method_signature (method));
8749 	} else {
8750 		g_string_append_printf (s, "_");
8751 		append_mangled_klass (s, method->klass);
8752 		g_string_append_printf (s, "_%s_", method->name);
8753 		if (!append_mangled_signature (s, mono_method_signature (method))) {
8754 			g_string_free (s, TRUE);
8755 			return FALSE;
8756 		}
8757 	}
8758 
8759 	return TRUE;
8760 }
8761 
8762 /*
8763  * mono_aot_get_mangled_method_name:
8764  *
8765  *   Return a unique mangled name for METHOD, or NULL.
8766  */
8767 char*
mono_aot_get_mangled_method_name(MonoMethod * method)8768 mono_aot_get_mangled_method_name (MonoMethod *method)
8769 {
8770 	// FIXME: use static cache (mempool?)
8771 	// We call this a *lot*
8772 
8773 	GString *s = g_string_new ("aot_");
8774 	if (!append_mangled_method (s, method)) {
8775 		g_string_free (s, TRUE);
8776 		return NULL;
8777 	} else {
8778 		char *out = g_string_free (s, FALSE);
8779 		// Scrub method and class names
8780 		char *cleaned = sanitize_mangled_string (out);
8781 		g_free (out);
8782 		return cleaned;
8783 	}
8784 }
8785 
8786 gboolean
mono_aot_is_direct_callable(MonoJumpInfo * patch_info)8787 mono_aot_is_direct_callable (MonoJumpInfo *patch_info)
8788 {
8789 	return is_direct_callable (llvm_acfg, NULL, patch_info);
8790 }
8791 
8792 void
mono_aot_mark_unused_llvm_plt_entry(MonoJumpInfo * patch_info)8793 mono_aot_mark_unused_llvm_plt_entry (MonoJumpInfo *patch_info)
8794 {
8795 	MonoPltEntry *plt_entry;
8796 
8797 	plt_entry = get_plt_entry (llvm_acfg, patch_info);
8798 	plt_entry->llvm_used = FALSE;
8799 }
8800 
8801 char*
mono_aot_get_direct_call_symbol(MonoJumpInfoType type,gconstpointer data)8802 mono_aot_get_direct_call_symbol (MonoJumpInfoType type, gconstpointer data)
8803 {
8804 	const char *sym = NULL;
8805 
8806 	if (llvm_acfg->aot_opts.direct_icalls) {
8807 		if (type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
8808 			/* Call to a C function implementing a jit icall */
8809 			sym = mono_lookup_jit_icall_symbol ((const char *)data);
8810 		} else if (type == MONO_PATCH_INFO_ICALL_ADDR_CALL) {
8811 			MonoMethod *method = (MonoMethod *)data;
8812 			if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
8813 				sym = mono_lookup_icall_symbol (method);
8814 			else if (llvm_acfg->aot_opts.direct_pinvoke)
8815 				sym = get_pinvoke_import (llvm_acfg, method);
8816 		}
8817 		if (sym)
8818 			return g_strdup (sym);
8819 	}
8820 	return NULL;
8821 }
8822 
8823 char*
mono_aot_get_plt_symbol(MonoJumpInfoType type,gconstpointer data)8824 mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
8825 {
8826 	MonoJumpInfo *ji = (MonoJumpInfo *)mono_mempool_alloc (llvm_acfg->mempool, sizeof (MonoJumpInfo));
8827 	MonoPltEntry *plt_entry;
8828 	const char *sym = NULL;
8829 
8830 	ji->type = type;
8831 	ji->data.target = data;
8832 
8833 	if (!can_encode_patch (llvm_acfg, ji))
8834 		return NULL;
8835 
8836 	if (llvm_acfg->aot_opts.direct_icalls) {
8837 		if (type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
8838 			/* Call to a C function implementing a jit icall */
8839 			sym = mono_lookup_jit_icall_symbol ((const char *)data);
8840 		} else if (type == MONO_PATCH_INFO_ICALL_ADDR_CALL) {
8841 			MonoMethod *method = (MonoMethod *)data;
8842 			if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
8843 				sym = mono_lookup_icall_symbol (method);
8844 		}
8845 		if (sym)
8846 			return g_strdup (sym);
8847 	}
8848 
8849 	plt_entry = get_plt_entry (llvm_acfg, ji);
8850 	plt_entry->llvm_used = TRUE;
8851 
8852 #if defined(TARGET_MACH)
8853 	return g_strdup_printf (plt_entry->llvm_symbol + strlen (llvm_acfg->llvm_label_prefix));
8854 #else
8855 	return g_strdup_printf (plt_entry->llvm_symbol);
8856 #endif
8857 }
8858 
8859 int
mono_aot_get_method_index(MonoMethod * method)8860 mono_aot_get_method_index (MonoMethod *method)
8861 {
8862 	g_assert (llvm_acfg);
8863 	return get_method_index (llvm_acfg, method);
8864 }
8865 
8866 MonoJumpInfo*
mono_aot_patch_info_dup(MonoJumpInfo * ji)8867 mono_aot_patch_info_dup (MonoJumpInfo* ji)
8868 {
8869 	MonoJumpInfo *res;
8870 
8871 	mono_acfg_lock (llvm_acfg);
8872 	res = mono_patch_info_dup_mp (llvm_acfg->mempool, ji);
8873 	mono_acfg_unlock (llvm_acfg);
8874 
8875 	return res;
8876 }
8877 
8878 static int
execute_system(const char * command)8879 execute_system (const char * command)
8880 {
8881 	int status = 0;
8882 
8883 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) && defined(HOST_WIN32)
8884 	// We need an extra set of quotes around the whole command to properly handle commands
8885 	// with spaces since internally the command is called through "cmd /c.
8886 	char * quoted_command = g_strdup_printf ("\"%s\"", command);
8887 
8888 	int size =  MultiByteToWideChar (CP_UTF8, 0 , quoted_command , -1, NULL , 0);
8889 	wchar_t* wstr = g_malloc (sizeof (wchar_t) * size);
8890 	MultiByteToWideChar (CP_UTF8, 0, quoted_command, -1, wstr , size);
8891 	status = _wsystem (wstr);
8892 	g_free (wstr);
8893 
8894 	g_free (quoted_command);
8895 #elif defined (HAVE_SYSTEM)
8896 	status = system (command);
8897 #else
8898 	g_assert_not_reached ();
8899 #endif
8900 
8901 	return status;
8902 }
8903 
8904 #ifdef ENABLE_LLVM
8905 
8906 /*
8907  * emit_llvm_file:
8908  *
8909  *   Emit the LLVM code into an LLVM bytecode file, and compile it using the LLVM
8910  * tools.
8911  */
8912 static gboolean
emit_llvm_file(MonoAotCompile * acfg)8913 emit_llvm_file (MonoAotCompile *acfg)
8914 {
8915 	char *command, *opts, *tempbc, *optbc, *output_fname;
8916 
8917 	if (acfg->aot_opts.llvm_only && acfg->aot_opts.asm_only) {
8918 		tempbc = g_strdup_printf ("%s.bc", acfg->tmpbasename);
8919 		optbc = g_strdup (acfg->aot_opts.llvm_outfile);
8920 	} else {
8921 		tempbc = g_strdup_printf ("%s.bc", acfg->tmpbasename);
8922 		optbc = g_strdup_printf ("%s.opt.bc", acfg->tmpbasename);
8923 	}
8924 
8925 	mono_llvm_emit_aot_module (tempbc, g_path_get_basename (acfg->image->name));
8926 
8927 	/*
8928 	 * FIXME: Experiment with adding optimizations, the -std-compile-opts set takes
8929 	 * a lot of time, and doesn't seem to save much space.
8930 	 * The following optimizations cannot be enabled:
8931 	 * - 'tailcallelim'
8932 	 * - 'jump-threading' changes our blockaddress references to int constants.
8933 	 * - 'basiccg' fails because it contains:
8934 	 * if (CS && !isa<IntrinsicInst>(II)) {
8935 	 * and isa<IntrinsicInst> is false for invokes to intrinsics (iltests.exe).
8936 	 * - 'prune-eh' and 'functionattrs' depend on 'basiccg'.
8937 	 * The opt list below was produced by taking the output of:
8938 	 * llvm-as < /dev/null | opt -O2 -disable-output -debug-pass=Arguments
8939 	 * then removing tailcallelim + the global opts.
8940 	 * strip-dead-prototypes deletes unused intrinsics definitions.
8941 	 */
8942 	/* The dse pass is disabled because of #13734 and #17616 */
8943 	/*
8944 	 * The dse bug is in DeadStoreElimination.cpp:isOverwrite ():
8945 	 * // If we have no DataLayout information around, then the size of the store
8946 	 *  // is inferrable from the pointee type.  If they are the same type, then
8947 	 * // we know that the store is safe.
8948 	 * if (AA.getDataLayout() == 0 &&
8949 	 * Later.Ptr->getType() == Earlier.Ptr->getType()) {
8950 	 * return OverwriteComplete;
8951 	 * Here, if 'Earlier' refers to a memset, and Later has no size info, it mistakenly thinks the memset is redundant.
8952 	 */
8953 	if (acfg->aot_opts.llvm_only)
8954 		// FIXME: This doesn't work yet
8955 		opts = g_strdup ("");
8956 	else
8957 #if LLVM_API_VERSION > 100
8958 		opts = g_strdup ("-O2 -disable-tail-calls");
8959 #else
8960 		opts = g_strdup ("-targetlibinfo -no-aa -basicaa -notti -instcombine -simplifycfg -inline-cost -inline -sroa -domtree -early-cse -lazy-value-info -correlated-propagation -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -indvars -loop-idiom -loop-deletion -loop-unroll -memdep -gvn -memdep -memcpyopt -sccp -instcombine -lazy-value-info -correlated-propagation -domtree -memdep -adce -simplifycfg -instcombine -strip-dead-prototypes -domtree -verify");
8961 #endif
8962 	command = g_strdup_printf ("\"%sopt\" -f %s -o \"%s\" \"%s\"", acfg->aot_opts.llvm_path, opts, optbc, tempbc);
8963 	aot_printf (acfg, "Executing opt: %s\n", command);
8964 	if (execute_system (command) != 0)
8965 		return FALSE;
8966 	g_free (opts);
8967 
8968 	if (acfg->aot_opts.llvm_only && acfg->aot_opts.asm_only)
8969 		/* Nothing else to do */
8970 		return TRUE;
8971 
8972 	if (acfg->aot_opts.llvm_only) {
8973 		/* Use the stock clang from xcode */
8974 		// FIXME: arch
8975 		command = g_strdup_printf ("clang++ -fexceptions -march=x86-64 -fpic -msse -msse2 -msse3 -msse4 -O2 -fno-optimize-sibling-calls -Wno-override-module -c -o \"%s\" \"%s.opt.bc\"", acfg->llvm_ofile, acfg->tmpbasename);
8976 
8977 		aot_printf (acfg, "Executing clang: %s\n", command);
8978 		if (execute_system (command) != 0)
8979 			return FALSE;
8980 		return TRUE;
8981 	}
8982 
8983 	if (!acfg->llc_args)
8984 		acfg->llc_args = g_string_new ("");
8985 
8986 	/* Verbose asm slows down llc greatly */
8987 	g_string_append (acfg->llc_args, " -asm-verbose=false");
8988 
8989 	if (acfg->aot_opts.mtriple)
8990 		g_string_append_printf (acfg->llc_args, " -mtriple=%s", acfg->aot_opts.mtriple);
8991 
8992 	g_string_append (acfg->llc_args, " -disable-gnu-eh-frame -enable-mono-eh-frame");
8993 
8994 	g_string_append_printf (acfg->llc_args, " -mono-eh-frame-symbol=%s%s", acfg->user_symbol_prefix, acfg->llvm_eh_frame_symbol);
8995 
8996 #if LLVM_API_VERSION > 100
8997 	g_string_append_printf (acfg->llc_args, " -disable-tail-calls");
8998 #endif
8999 
9000 #if ( defined(TARGET_MACH) && defined(TARGET_ARM) ) || defined(TARGET_ORBIS)
9001 	/* ios requires PIC code now */
9002 	g_string_append_printf (acfg->llc_args, " -relocation-model=pic");
9003 #else
9004 	if (llvm_acfg->aot_opts.static_link)
9005 		g_string_append_printf (acfg->llc_args, " -relocation-model=static");
9006 	else
9007 		g_string_append_printf (acfg->llc_args, " -relocation-model=pic");
9008 #endif
9009 
9010 	if (acfg->llvm_owriter) {
9011 		/* Emit an object file directly */
9012 		output_fname = g_strdup_printf ("%s", acfg->llvm_ofile);
9013 		g_string_append_printf (acfg->llc_args, " -filetype=obj");
9014 	} else {
9015 		output_fname = g_strdup_printf ("%s", acfg->llvm_sfile);
9016 	}
9017 	command = g_strdup_printf ("\"%sllc\" %s -o \"%s\" \"%s.opt.bc\"", acfg->aot_opts.llvm_path, acfg->llc_args->str, output_fname, acfg->tmpbasename);
9018 	g_free (output_fname);
9019 
9020 	aot_printf (acfg, "Executing llc: %s\n", command);
9021 
9022 	if (execute_system (command) != 0)
9023 		return FALSE;
9024 	return TRUE;
9025 }
9026 #endif
9027 
9028 static void
emit_code(MonoAotCompile * acfg)9029 emit_code (MonoAotCompile *acfg)
9030 {
9031 	int oindex, i, prev_index;
9032 	gboolean saved_unbox_info = FALSE;
9033 	char symbol [MAX_SYMBOL_SIZE];
9034 
9035 	if (acfg->aot_opts.llvm_only)
9036 		return;
9037 
9038 #if defined(TARGET_POWERPC64)
9039 	sprintf (symbol, ".Lgot_addr");
9040 	emit_section_change (acfg, ".text", 0);
9041 	emit_alignment (acfg, 8);
9042 	emit_label (acfg, symbol);
9043 	emit_pointer (acfg, acfg->got_symbol);
9044 #endif
9045 
9046 	/*
9047 	 * This global symbol is used to compute the address of each method using the
9048 	 * code_offsets array. It is also used to compute the memory ranges occupied by
9049 	 * AOT code, so it must be equal to the address of the first emitted method.
9050 	 */
9051 	emit_section_change (acfg, ".text", 0);
9052 	emit_alignment_code (acfg, 8);
9053 	emit_info_symbol (acfg, "jit_code_start");
9054 
9055 	/*
9056 	 * Emit some padding so the local symbol for the first method doesn't have the
9057 	 * same address as 'methods'.
9058 	 */
9059 	emit_padding (acfg, 16);
9060 
9061 	for (oindex = 0; oindex < acfg->method_order->len; ++oindex) {
9062 		MonoCompile *cfg;
9063 		MonoMethod *method;
9064 
9065 		i = GPOINTER_TO_UINT (g_ptr_array_index (acfg->method_order, oindex));
9066 
9067 		cfg = acfg->cfgs [i];
9068 
9069 		if (!cfg)
9070 			continue;
9071 
9072 		method = cfg->orig_method;
9073 
9074 		gboolean dedup_collect = acfg->aot_opts.dedup || (acfg->aot_opts.dedup_include && !acfg->dedup_emit_mode);
9075 		gboolean dedupable = mono_aot_can_dedup (method);
9076 
9077 		// cfg->skip is vital for LLVM to work, can't just continue in this loop
9078 		if (dedupable && strcmp (method->name, "wbarrier_conc") && dedup_collect) {
9079 			mono_dedup_cache_method (acfg, method);
9080 
9081 			// Don't compile inflated methods if we're in first phase of
9082 			// dedup
9083 			//
9084 			// In second phase, we emit methods that
9085 			// are dedupable. We also emit later methods
9086 			// which are referenced by them and added later.
9087 			// For this reason, when in the dedup_include mode,
9088 			// we never set skip.
9089 			if (acfg->aot_opts.dedup)
9090 				cfg->skip = TRUE;
9091 		}
9092 
9093 		// Don't compile anything in this mode
9094 		if (acfg->aot_opts.dedup_include && !acfg->dedup_emit_mode)
9095 			cfg->skip = TRUE;
9096 
9097 		// Compile everything in this mode
9098 		if (acfg->aot_opts.dedup_include && acfg->dedup_emit_mode)
9099 			cfg->skip = FALSE;
9100 
9101 		/*if (dedup_collect) {*/
9102 			/*char *name = mono_aot_get_mangled_method_name (method);*/
9103 
9104 			/*if (ignore_cfg (cfg))*/
9105 				/*aot_printf (acfg, "Dedup Skipping %s\n", acfg->image->name, name);*/
9106 			/*else*/
9107 				/*aot_printf (acfg, "Dedup Keeping %s\n", acfg->image->name, name);*/
9108 
9109 			/*g_free (name);*/
9110 		/*}*/
9111 
9112 		if (ignore_cfg (cfg))
9113 			continue;
9114 
9115 		/* Emit unbox trampoline */
9116 		if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
9117 			sprintf (symbol, "ut_%d", get_method_index (acfg, method));
9118 
9119 			emit_section_change (acfg, ".text", 0);
9120 
9121 			if (acfg->thumb_mixed && cfg->compile_llvm) {
9122 				emit_set_thumb_mode (acfg);
9123 				fprintf (acfg->fp, "\n.thumb_func\n");
9124 			}
9125 
9126 			emit_label (acfg, symbol);
9127 
9128 			arch_emit_unbox_trampoline (acfg, cfg, cfg->orig_method, cfg->asm_symbol);
9129 
9130 			if (acfg->thumb_mixed && cfg->compile_llvm)
9131 				emit_set_arm_mode (acfg);
9132 
9133 			if (!saved_unbox_info) {
9134 				char user_symbol [128];
9135 				GSList *unwind_ops;
9136 				sprintf (user_symbol, "%sunbox_trampoline_p", acfg->user_symbol_prefix);
9137 
9138 				emit_label (acfg, "ut_end");
9139 
9140 				unwind_ops = mono_unwind_get_cie_program ();
9141 				save_unwind_info (acfg, user_symbol, unwind_ops);
9142 				mono_free_unwind_info (unwind_ops);
9143 
9144 				/* Save the unbox trampoline size */
9145 				emit_symbol_diff (acfg, "ut_end", symbol, 0);
9146 
9147 				saved_unbox_info = TRUE;
9148 			}
9149 		}
9150 
9151 		if (cfg->compile_llvm) {
9152 			acfg->stats.llvm_count ++;
9153 		} else {
9154 			emit_method_code (acfg, cfg);
9155 		}
9156 	}
9157 
9158 	emit_section_change (acfg, ".text", 0);
9159 	emit_alignment_code (acfg, 8);
9160 	emit_info_symbol (acfg, "jit_code_end");
9161 
9162 	/* To distinguish it from the next symbol */
9163 	emit_padding (acfg, 4);
9164 
9165 	/*
9166 	 * Add .no_dead_strip directives for all LLVM methods to prevent the OSX linker
9167 	 * from optimizing them away, since it doesn't see that code_offsets references them.
9168 	 * JITted methods don't need this since they are referenced using assembler local
9169 	 * symbols.
9170 	 * FIXME: This is why write-symbols doesn't work on OSX ?
9171 	 */
9172 	if (acfg->llvm && acfg->need_no_dead_strip) {
9173 		fprintf (acfg->fp, "\n");
9174 		for (i = 0; i < acfg->nmethods; ++i) {
9175 			if (acfg->cfgs [i] && acfg->cfgs [i]->compile_llvm)
9176 				fprintf (acfg->fp, ".no_dead_strip %s\n", acfg->cfgs [i]->asm_symbol);
9177 		}
9178 	}
9179 
9180 	/*
9181 	 * To work around linker issues, we emit a table of branches, and disassemble them at runtime.
9182 	 * This is PIE code, and the linker can update it if needed.
9183 	 */
9184 
9185 	sprintf (symbol, "method_addresses");
9186 	emit_section_change (acfg, ".text", 1);
9187 	emit_alignment_code (acfg, 8);
9188 	emit_info_symbol (acfg, symbol);
9189 	if (acfg->aot_opts.write_symbols)
9190 		emit_local_symbol (acfg, symbol, "method_addresses_end", TRUE);
9191 	emit_unset_mode (acfg);
9192 	if (acfg->need_no_dead_strip)
9193 		fprintf (acfg->fp, "	.no_dead_strip %s\n", symbol);
9194 
9195 	for (i = 0; i < acfg->nmethods; ++i) {
9196 #ifdef MONO_ARCH_AOT_SUPPORTED
9197 		int call_size;
9198 
9199 		if (!ignore_cfg (acfg->cfgs [i])) {
9200 			arch_emit_direct_call (acfg, acfg->cfgs [i]->asm_symbol, FALSE, acfg->thumb_mixed && acfg->cfgs [i]->compile_llvm, NULL, &call_size);
9201 		} else {
9202 			arch_emit_direct_call (acfg, symbol, FALSE, FALSE, NULL, &call_size);
9203 		}
9204 #endif
9205 	}
9206 
9207 	sprintf (symbol, "method_addresses_end");
9208 	emit_label (acfg, symbol);
9209 	emit_line (acfg);
9210 
9211 	/* Emit a sorted table mapping methods to the index of their unbox trampolines */
9212 	sprintf (symbol, "unbox_trampolines");
9213 	emit_section_change (acfg, RODATA_SECT, 0);
9214 	emit_alignment (acfg, 8);
9215 	emit_info_symbol (acfg, symbol);
9216 
9217 	prev_index = -1;
9218 	for (i = 0; i < acfg->nmethods; ++i) {
9219 		MonoCompile *cfg;
9220 		MonoMethod *method;
9221 		int index;
9222 
9223 		cfg = acfg->cfgs [i];
9224 		if (ignore_cfg (cfg))
9225 			continue;
9226 
9227 		method = cfg->orig_method;
9228 
9229 		if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
9230 			index = get_method_index (acfg, method);
9231 
9232 			emit_int32 (acfg, index);
9233 			/* Make sure the table is sorted by index */
9234 			g_assert (index > prev_index);
9235 			prev_index = index;
9236 		}
9237 	}
9238 	sprintf (symbol, "unbox_trampolines_end");
9239 	emit_info_symbol (acfg, symbol);
9240 	emit_int32 (acfg, 0);
9241 
9242 	/* Emit a separate table with the trampoline addresses/offsets */
9243 	sprintf (symbol, "unbox_trampoline_addresses");
9244 	emit_section_change (acfg, ".text", 0);
9245 	emit_alignment_code (acfg, 8);
9246 	emit_info_symbol (acfg, symbol);
9247 
9248 	for (i = 0; i < acfg->nmethods; ++i) {
9249 		MonoCompile *cfg;
9250 		MonoMethod *method;
9251 		int index;
9252 
9253 		cfg = acfg->cfgs [i];
9254 		if (ignore_cfg (cfg))
9255 			continue;
9256 
9257 		method = cfg->orig_method;
9258 
9259 		if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
9260 #ifdef MONO_ARCH_AOT_SUPPORTED
9261 			int call_size;
9262 
9263 			index = get_method_index (acfg, method);
9264 			sprintf (symbol, "ut_%d", index);
9265 
9266 			arch_emit_direct_call (acfg, symbol, FALSE, acfg->thumb_mixed && cfg->compile_llvm, NULL, &call_size);
9267 #endif
9268 		}
9269 	}
9270 	emit_int32 (acfg, 0);
9271 }
9272 
9273 static void
emit_info(MonoAotCompile * acfg)9274 emit_info (MonoAotCompile *acfg)
9275 {
9276 	int oindex, i;
9277 	gint32 *offsets;
9278 
9279 	offsets = g_new0 (gint32, acfg->nmethods);
9280 
9281 	for (oindex = 0; oindex < acfg->method_order->len; ++oindex) {
9282 		i = GPOINTER_TO_UINT (g_ptr_array_index (acfg->method_order, oindex));
9283 
9284 		if (acfg->cfgs [i]) {
9285 			emit_method_info (acfg, acfg->cfgs [i]);
9286 			offsets [i] = acfg->cfgs [i]->method_info_offset;
9287 		} else {
9288 			offsets [i] = 0;
9289 		}
9290 	}
9291 
9292 	acfg->stats.offsets_size += emit_offset_table (acfg, "method_info_offsets", MONO_AOT_TABLE_METHOD_INFO_OFFSETS, acfg->nmethods, 10, offsets);
9293 
9294 	g_free (offsets);
9295 }
9296 
9297 #endif /* #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT) */
9298 
9299 #define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
9300 #define mix(a,b,c) { \
9301 	a -= c;  a ^= rot(c, 4);  c += b; \
9302 	b -= a;  b ^= rot(a, 6);  a += c; \
9303 	c -= b;  c ^= rot(b, 8);  b += a; \
9304 	a -= c;  a ^= rot(c,16);  c += b; \
9305 	b -= a;  b ^= rot(a,19);  a += c; \
9306 	c -= b;  c ^= rot(b, 4);  b += a; \
9307 }
9308 #define final(a,b,c) { \
9309 	c ^= b; c -= rot(b,14); \
9310 	a ^= c; a -= rot(c,11); \
9311 	b ^= a; b -= rot(a,25); \
9312 	c ^= b; c -= rot(b,16); \
9313 	a ^= c; a -= rot(c,4);  \
9314 	b ^= a; b -= rot(a,14); \
9315 	c ^= b; c -= rot(b,24); \
9316 }
9317 
9318 static guint
mono_aot_type_hash(MonoType * t1)9319 mono_aot_type_hash (MonoType *t1)
9320 {
9321 	guint hash = t1->type;
9322 
9323 	hash |= t1->byref << 6; /* do not collide with t1->type values */
9324 	switch (t1->type) {
9325 	case MONO_TYPE_VALUETYPE:
9326 	case MONO_TYPE_CLASS:
9327 	case MONO_TYPE_SZARRAY:
9328 		/* check if the distribution is good enough */
9329 		return ((hash << 5) - hash) ^ mono_metadata_str_hash (t1->data.klass->name);
9330 	case MONO_TYPE_PTR:
9331 		return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
9332 	case MONO_TYPE_ARRAY:
9333 		return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
9334 	case MONO_TYPE_GENERICINST:
9335 		return ((hash << 5) - hash) ^ 0;
9336 	default:
9337 		return hash;
9338 	}
9339 }
9340 
9341 /*
9342  * mono_aot_method_hash:
9343  *
9344  *   Return a hash code for methods which only depends on metadata.
9345  */
9346 guint32
mono_aot_method_hash(MonoMethod * method)9347 mono_aot_method_hash (MonoMethod *method)
9348 {
9349 	MonoMethodSignature *sig;
9350 	MonoClass *klass;
9351 	int i, hindex;
9352 	int hashes_count;
9353 	guint32 *hashes_start, *hashes;
9354 	guint32 a, b, c;
9355 	MonoGenericInst *class_ginst = NULL;
9356 	MonoGenericInst *ginst = NULL;
9357 
9358 	/* Similar to the hash in mono_method_get_imt_slot () */
9359 
9360 	sig = mono_method_signature (method);
9361 
9362 	if (mono_class_is_ginst (method->klass))
9363 		class_ginst = mono_class_get_generic_class (method->klass)->context.class_inst;
9364 	if (method->is_inflated)
9365 		ginst = ((MonoMethodInflated*)method)->context.method_inst;
9366 
9367 	hashes_count = sig->param_count + 5 + (class_ginst ? class_ginst->type_argc : 0) + (ginst ? ginst->type_argc : 0);
9368 	hashes_start = (guint32 *)g_malloc0 (hashes_count * sizeof (guint32));
9369 	hashes = hashes_start;
9370 
9371 	/* Some wrappers are assigned to random classes */
9372 	if (!method->wrapper_type || method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
9373 		klass = method->klass;
9374 	else
9375 		klass = mono_defaults.object_class;
9376 
9377 	if (!method->wrapper_type) {
9378 		char *full_name;
9379 
9380 		if (mono_class_is_ginst (klass))
9381 			full_name = mono_type_full_name (&mono_class_get_generic_class (klass)->container_class->byval_arg);
9382 		else
9383 			full_name = mono_type_full_name (&klass->byval_arg);
9384 
9385 		hashes [0] = mono_metadata_str_hash (full_name);
9386 		hashes [1] = 0;
9387 		g_free (full_name);
9388 	} else {
9389 		hashes [0] = mono_metadata_str_hash (klass->name);
9390 		hashes [1] = mono_metadata_str_hash (klass->name_space);
9391 	}
9392 	if (method->wrapper_type == MONO_WRAPPER_STFLD || method->wrapper_type == MONO_WRAPPER_LDFLD || method->wrapper_type == MONO_WRAPPER_LDFLDA)
9393 		/* The method name includes a stringified pointer */
9394 		hashes [2] = 0;
9395 	else
9396 		hashes [2] = mono_metadata_str_hash (method->name);
9397 	hashes [3] = method->wrapper_type;
9398 	hashes [4] = mono_aot_type_hash (sig->ret);
9399 	hindex = 5;
9400 	for (i = 0; i < sig->param_count; i++) {
9401 		hashes [hindex ++] = mono_aot_type_hash (sig->params [i]);
9402 	}
9403 	if (class_ginst) {
9404 		for (i = 0; i < class_ginst->type_argc; ++i)
9405 			hashes [hindex ++] = mono_aot_type_hash (class_ginst->type_argv [i]);
9406 	}
9407 	if (ginst) {
9408 		for (i = 0; i < ginst->type_argc; ++i)
9409 			hashes [hindex ++] = mono_aot_type_hash (ginst->type_argv [i]);
9410 	}
9411 	g_assert (hindex == hashes_count);
9412 
9413 	/* Setup internal state */
9414 	a = b = c = 0xdeadbeef + (((guint32)hashes_count)<<2);
9415 
9416 	/* Handle most of the hashes */
9417 	while (hashes_count > 3) {
9418 		a += hashes [0];
9419 		b += hashes [1];
9420 		c += hashes [2];
9421 		mix (a,b,c);
9422 		hashes_count -= 3;
9423 		hashes += 3;
9424 	}
9425 
9426 	/* Handle the last 3 hashes (all the case statements fall through) */
9427 	switch (hashes_count) {
9428 	case 3 : c += hashes [2];
9429 	case 2 : b += hashes [1];
9430 	case 1 : a += hashes [0];
9431 		final (a,b,c);
9432 	case 0: /* nothing left to add */
9433 		break;
9434 	}
9435 
9436 	g_free (hashes_start);
9437 
9438 	return c;
9439 }
9440 #undef rot
9441 #undef mix
9442 #undef final
9443 
9444 /*
9445  * mono_aot_get_array_helper_from_wrapper;
9446  *
9447  * Get the helper method in Array called by an array wrapper method.
9448  */
9449 MonoMethod*
mono_aot_get_array_helper_from_wrapper(MonoMethod * method)9450 mono_aot_get_array_helper_from_wrapper (MonoMethod *method)
9451 {
9452 	MonoMethod *m;
9453 	const char *prefix;
9454 	MonoGenericContext ctx;
9455 	MonoType *args [16];
9456 	char *mname, *iname, *s, *s2, *helper_name = NULL;
9457 
9458 	prefix = "System.Collections.Generic";
9459 	s = g_strdup_printf ("%s", method->name + strlen (prefix) + 1);
9460 	s2 = strstr (s, "`1.");
9461 	g_assert (s2);
9462 	s2 [0] = '\0';
9463 	iname = s;
9464 	mname = s2 + 3;
9465 
9466 	//printf ("X: %s %s\n", iname, mname);
9467 
9468 	if (!strcmp (iname, "IList"))
9469 		helper_name = g_strdup_printf ("InternalArray__%s", mname);
9470 	else
9471 		helper_name = g_strdup_printf ("InternalArray__%s_%s", iname, mname);
9472 	m = mono_class_get_method_from_name (mono_defaults.array_class, helper_name, mono_method_signature (method)->param_count);
9473 	g_assert (m);
9474 	g_free (helper_name);
9475 	g_free (s);
9476 
9477 	if (m->is_generic) {
9478 		MonoError error;
9479 		memset (&ctx, 0, sizeof (ctx));
9480 		args [0] = &method->klass->element_class->byval_arg;
9481 		ctx.method_inst = mono_metadata_get_generic_inst (1, args);
9482 		m = mono_class_inflate_generic_method_checked (m, &ctx, &error);
9483 		g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
9484 	}
9485 
9486 	return m;
9487 }
9488 
9489 #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT)
9490 
9491 typedef struct HashEntry {
9492     guint32 key, value, index;
9493 	struct HashEntry *next;
9494 } HashEntry;
9495 
9496 /*
9497  * emit_extra_methods:
9498  *
9499  * Emit methods which are not in the METHOD table, like wrappers.
9500  */
9501 static void
emit_extra_methods(MonoAotCompile * acfg)9502 emit_extra_methods (MonoAotCompile *acfg)
9503 {
9504 	int i, table_size, buf_size;
9505 	guint8 *p, *buf;
9506 	guint32 *info_offsets;
9507 	guint32 hash;
9508 	GPtrArray *table;
9509 	HashEntry *entry, *new_entry;
9510 	int nmethods, max_chain_length;
9511 	int *chain_lengths;
9512 
9513 	info_offsets = g_new0 (guint32, acfg->extra_methods->len);
9514 
9515 	/* Emit method info */
9516 	nmethods = 0;
9517 	for (i = 0; i < acfg->extra_methods->len; ++i) {
9518 		MonoMethod *method = (MonoMethod *)g_ptr_array_index (acfg->extra_methods, i);
9519 		MonoCompile *cfg = (MonoCompile *)g_hash_table_lookup (acfg->method_to_cfg, method);
9520 
9521 		if (ignore_cfg (cfg))
9522 			continue;
9523 
9524 		buf_size = 10240;
9525 		p = buf = (guint8 *)g_malloc (buf_size);
9526 
9527 		nmethods ++;
9528 
9529 		method = cfg->method_to_register;
9530 
9531 		encode_method_ref (acfg, method, p, &p);
9532 
9533 		g_assert ((p - buf) < buf_size);
9534 
9535 		info_offsets [i] = add_to_blob (acfg, buf, p - buf);
9536 		g_free (buf);
9537 	}
9538 
9539 	/*
9540 	 * Construct a chained hash table for mapping indexes in extra_method_info to
9541 	 * method indexes.
9542 	 */
9543 	table_size = g_spaced_primes_closest ((int)(nmethods * 1.5));
9544 	table = g_ptr_array_sized_new (table_size);
9545 	for (i = 0; i < table_size; ++i)
9546 		g_ptr_array_add (table, NULL);
9547 	chain_lengths = g_new0 (int, table_size);
9548 	max_chain_length = 0;
9549 	for (i = 0; i < acfg->extra_methods->len; ++i) {
9550 		MonoMethod *method = (MonoMethod *)g_ptr_array_index (acfg->extra_methods, i);
9551 		MonoCompile *cfg = (MonoCompile *)g_hash_table_lookup (acfg->method_to_cfg, method);
9552 		guint32 key, value;
9553 
9554 		if (ignore_cfg (cfg))
9555 			continue;
9556 
9557 		key = info_offsets [i];
9558 		value = get_method_index (acfg, method);
9559 
9560 		hash = mono_aot_method_hash (method) % table_size;
9561 		//printf ("X: %s %x\n", mono_method_get_full_name (method), mono_aot_method_hash (method));
9562 
9563 		chain_lengths [hash] ++;
9564 		max_chain_length = MAX (max_chain_length, chain_lengths [hash]);
9565 
9566 		new_entry = (HashEntry *)mono_mempool_alloc0 (acfg->mempool, sizeof (HashEntry));
9567 		new_entry->key = key;
9568 		new_entry->value = value;
9569 
9570 		entry = (HashEntry *)g_ptr_array_index (table, hash);
9571 		if (entry == NULL) {
9572 			new_entry->index = hash;
9573 			g_ptr_array_index (table, hash) = new_entry;
9574 		} else {
9575 			while (entry->next)
9576 				entry = entry->next;
9577 
9578 			entry->next = new_entry;
9579 			new_entry->index = table->len;
9580 			g_ptr_array_add (table, new_entry);
9581 		}
9582 	}
9583 	g_free (chain_lengths);
9584 
9585 	//printf ("MAX: %d\n", max_chain_length);
9586 
9587 	buf_size = table->len * 12 + 4;
9588 	p = buf = (guint8 *)g_malloc (buf_size);
9589 	encode_int (table_size, p, &p);
9590 
9591 	for (i = 0; i < table->len; ++i) {
9592 		HashEntry *entry = (HashEntry *)g_ptr_array_index (table, i);
9593 
9594 		if (entry == NULL) {
9595 			encode_int (0, p, &p);
9596 			encode_int (0, p, &p);
9597 			encode_int (0, p, &p);
9598 		} else {
9599 			//g_assert (entry->key > 0);
9600 			encode_int (entry->key, p, &p);
9601 			encode_int (entry->value, p, &p);
9602 			if (entry->next)
9603 				encode_int (entry->next->index, p, &p);
9604 			else
9605 				encode_int (0, p, &p);
9606 		}
9607 	}
9608 	g_assert (p - buf <= buf_size);
9609 
9610 	/* Emit the table */
9611 	emit_aot_data (acfg, MONO_AOT_TABLE_EXTRA_METHOD_TABLE, "extra_method_table", buf, p - buf);
9612 
9613 	g_free (buf);
9614 
9615 	/*
9616 	 * Emit a table reverse mapping method indexes to their index in extra_method_info.
9617 	 * This is used by mono_aot_find_jit_info ().
9618 	 */
9619 	buf_size = acfg->extra_methods->len * 8 + 4;
9620 	p = buf = (guint8 *)g_malloc (buf_size);
9621 	encode_int (acfg->extra_methods->len, p, &p);
9622 	for (i = 0; i < acfg->extra_methods->len; ++i) {
9623 		MonoMethod *method = (MonoMethod *)g_ptr_array_index (acfg->extra_methods, i);
9624 
9625 		encode_int (get_method_index (acfg, method), p, &p);
9626 		encode_int (info_offsets [i], p, &p);
9627 	}
9628 	emit_aot_data (acfg, MONO_AOT_TABLE_EXTRA_METHOD_INFO_OFFSETS, "extra_method_info_offsets", buf, p - buf);
9629 
9630 	g_free (buf);
9631 	g_free (info_offsets);
9632 	g_ptr_array_free (table, TRUE);
9633 }
9634 
9635 static void
generate_aotid(guint8 * aotid)9636 generate_aotid (guint8* aotid)
9637 {
9638 	gpointer rand_handle;
9639 	MonoError error;
9640 
9641 	mono_rand_open ();
9642 	rand_handle = mono_rand_init (NULL, 0);
9643 
9644 	mono_rand_try_get_bytes (&rand_handle, aotid, 16, &error);
9645 	mono_error_assert_ok (&error);
9646 
9647 	mono_rand_close (rand_handle);
9648 }
9649 
9650 static void
emit_exception_info(MonoAotCompile * acfg)9651 emit_exception_info (MonoAotCompile *acfg)
9652 {
9653 	int i;
9654 	gint32 *offsets;
9655 	SeqPointData sp_data;
9656 	gboolean seq_points_to_file = FALSE;
9657 
9658 	offsets = g_new0 (gint32, acfg->nmethods);
9659 	for (i = 0; i < acfg->nmethods; ++i) {
9660 		if (acfg->cfgs [i]) {
9661 			MonoCompile *cfg = acfg->cfgs [i];
9662 
9663 			// By design aot-runtime decode_exception_debug_info is not able to load sequence point debug data from a file.
9664 			// As it is not possible to load debug data from a file its is also not possible to store it in a file.
9665 			gboolean method_seq_points_to_file = acfg->aot_opts.gen_msym_dir &&
9666 				cfg->gen_seq_points && !cfg->gen_sdb_seq_points;
9667 			gboolean method_seq_points_to_binary = cfg->gen_seq_points && !method_seq_points_to_file;
9668 
9669 			emit_exception_debug_info (acfg, cfg, method_seq_points_to_binary);
9670 			offsets [i] = cfg->ex_info_offset;
9671 
9672 			if (method_seq_points_to_file) {
9673 				if (!seq_points_to_file) {
9674 					mono_seq_point_data_init (&sp_data, acfg->nmethods);
9675 					seq_points_to_file = TRUE;
9676 				}
9677 				mono_seq_point_data_add (&sp_data, cfg->method->token, cfg->method_index, cfg->seq_point_info);
9678 			}
9679 		} else {
9680 			offsets [i] = 0;
9681 		}
9682 	}
9683 
9684 	if (seq_points_to_file) {
9685 		char *aotid = mono_guid_to_string_minimal (acfg->image->aotid);
9686 		char *dir = g_build_filename (acfg->aot_opts.gen_msym_dir_path, aotid, NULL);
9687 		char *image_basename = g_path_get_basename (acfg->image->name);
9688 		char *aot_file = g_strdup_printf("%s%s", image_basename, SEQ_POINT_AOT_EXT);
9689 		char *aot_file_path = g_build_filename (dir, aot_file, NULL);
9690 
9691 		if (g_ensure_directory_exists (aot_file_path) == FALSE) {
9692 			fprintf (stderr, "AOT : failed to create msym directory: %s\n", aot_file_path);
9693 			exit (1);
9694 		}
9695 
9696 		mono_seq_point_data_write (&sp_data, aot_file_path);
9697 		mono_seq_point_data_free (&sp_data);
9698 
9699 		g_free (aotid);
9700 		g_free (dir);
9701 		g_free (image_basename);
9702 		g_free (aot_file);
9703 		g_free (aot_file_path);
9704 	}
9705 
9706 	acfg->stats.offsets_size += emit_offset_table (acfg, "ex_info_offsets", MONO_AOT_TABLE_EX_INFO_OFFSETS, acfg->nmethods, 10, offsets);
9707 	g_free (offsets);
9708 }
9709 
9710 static void
emit_unwind_info(MonoAotCompile * acfg)9711 emit_unwind_info (MonoAotCompile *acfg)
9712 {
9713 	int i;
9714 	char symbol [128];
9715 
9716 	if (acfg->aot_opts.llvm_only) {
9717 		g_assert (acfg->unwind_ops->len == 0);
9718 		return;
9719 	}
9720 
9721 	/*
9722 	 * The unwind info contains a lot of duplicates so we emit each unique
9723 	 * entry once, and only store the offset from the start of the table in the
9724 	 * exception info.
9725 	 */
9726 
9727 	sprintf (symbol, "unwind_info");
9728 	emit_section_change (acfg, RODATA_SECT, 1);
9729 	emit_alignment (acfg, 8);
9730 	emit_info_symbol (acfg, symbol);
9731 
9732 	for (i = 0; i < acfg->unwind_ops->len; ++i) {
9733 		guint32 index = GPOINTER_TO_UINT (g_ptr_array_index (acfg->unwind_ops, i));
9734 		guint8 *unwind_info;
9735 		guint32 unwind_info_len;
9736 		guint8 buf [16];
9737 		guint8 *p;
9738 
9739 		unwind_info = mono_get_cached_unwind_info (index, &unwind_info_len);
9740 
9741 		p = buf;
9742 		encode_value (unwind_info_len, p, &p);
9743 		emit_bytes (acfg, buf, p - buf);
9744 		emit_bytes (acfg, unwind_info, unwind_info_len);
9745 
9746 		acfg->stats.unwind_info_size += (p - buf) + unwind_info_len;
9747 	}
9748 }
9749 
9750 static void
emit_class_info(MonoAotCompile * acfg)9751 emit_class_info (MonoAotCompile *acfg)
9752 {
9753 	int i;
9754 	gint32 *offsets;
9755 
9756 	offsets = g_new0 (gint32, acfg->image->tables [MONO_TABLE_TYPEDEF].rows);
9757 	for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i)
9758 		offsets [i] = emit_klass_info (acfg, MONO_TOKEN_TYPE_DEF | (i + 1));
9759 
9760 	acfg->stats.offsets_size += emit_offset_table (acfg, "class_info_offsets", MONO_AOT_TABLE_CLASS_INFO_OFFSETS, acfg->image->tables [MONO_TABLE_TYPEDEF].rows, 10, offsets);
9761 	g_free (offsets);
9762 }
9763 
9764 typedef struct ClassNameTableEntry {
9765 	guint32 token, index;
9766 	struct ClassNameTableEntry *next;
9767 } ClassNameTableEntry;
9768 
9769 static void
emit_class_name_table(MonoAotCompile * acfg)9770 emit_class_name_table (MonoAotCompile *acfg)
9771 {
9772 	int i, table_size, buf_size;
9773 	guint32 token, hash;
9774 	MonoClass *klass;
9775 	GPtrArray *table;
9776 	char *full_name;
9777 	guint8 *buf, *p;
9778 	ClassNameTableEntry *entry, *new_entry;
9779 
9780 	/*
9781 	 * Construct a chained hash table for mapping class names to typedef tokens.
9782 	 */
9783 	table_size = g_spaced_primes_closest ((int)(acfg->image->tables [MONO_TABLE_TYPEDEF].rows * 1.5));
9784 	table = g_ptr_array_sized_new (table_size);
9785 	for (i = 0; i < table_size; ++i)
9786 		g_ptr_array_add (table, NULL);
9787 	for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
9788 		MonoError error;
9789 		token = MONO_TOKEN_TYPE_DEF | (i + 1);
9790 		klass = mono_class_get_checked (acfg->image, token, &error);
9791 		if (!klass) {
9792 			mono_error_cleanup (&error);
9793 			continue;
9794 		}
9795 		full_name = mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_FULL_NAME);
9796 		hash = mono_metadata_str_hash (full_name) % table_size;
9797 		g_free (full_name);
9798 
9799 		/* FIXME: Allocate from the mempool */
9800 		new_entry = g_new0 (ClassNameTableEntry, 1);
9801 		new_entry->token = token;
9802 
9803 		entry = (ClassNameTableEntry *)g_ptr_array_index (table, hash);
9804 		if (entry == NULL) {
9805 			new_entry->index = hash;
9806 			g_ptr_array_index (table, hash) = new_entry;
9807 		} else {
9808 			while (entry->next)
9809 				entry = entry->next;
9810 
9811 			entry->next = new_entry;
9812 			new_entry->index = table->len;
9813 			g_ptr_array_add (table, new_entry);
9814 		}
9815 	}
9816 
9817 	/* Emit the table */
9818 	buf_size = table->len * 4 + 4;
9819 	p = buf = (guint8 *)g_malloc0 (buf_size);
9820 
9821 	/* FIXME: Optimize memory usage */
9822 	g_assert (table_size < 65000);
9823 	encode_int16 (table_size, p, &p);
9824 	g_assert (table->len < 65000);
9825 	for (i = 0; i < table->len; ++i) {
9826 		ClassNameTableEntry *entry = (ClassNameTableEntry *)g_ptr_array_index (table, i);
9827 
9828 		if (entry == NULL) {
9829 			encode_int16 (0, p, &p);
9830 			encode_int16 (0, p, &p);
9831 		} else {
9832 			encode_int16 (mono_metadata_token_index (entry->token), p, &p);
9833 			if (entry->next)
9834 				encode_int16 (entry->next->index, p, &p);
9835 			else
9836 				encode_int16 (0, p, &p);
9837 		}
9838 		g_free (entry);
9839 	}
9840 	g_assert (p - buf <= buf_size);
9841 	g_ptr_array_free (table, TRUE);
9842 
9843 	emit_aot_data (acfg, MONO_AOT_TABLE_CLASS_NAME, "class_name_table", buf, p - buf);
9844 
9845 	g_free (buf);
9846 }
9847 
9848 static void
emit_image_table(MonoAotCompile * acfg)9849 emit_image_table (MonoAotCompile *acfg)
9850 {
9851 	int i, buf_size;
9852 	guint8 *buf, *p;
9853 
9854 	/*
9855 	 * The image table is small but referenced in a lot of places.
9856 	 * So we emit it at once, and reference its elements by an index.
9857 	 */
9858 	buf_size = acfg->image_table->len * 28 + 4;
9859 	for (i = 0; i < acfg->image_table->len; i++) {
9860 		MonoImage *image = (MonoImage*)g_ptr_array_index (acfg->image_table, i);
9861 		MonoAssemblyName *aname = &image->assembly->aname;
9862 
9863 		buf_size += strlen (image->assembly_name) + strlen (image->guid) + (aname->culture ? strlen (aname->culture) : 1) + strlen ((char*)aname->public_key_token) + 4;
9864 	}
9865 
9866 	buf = p = (guint8 *)g_malloc0 (buf_size);
9867 	encode_int (acfg->image_table->len, p, &p);
9868 	for (i = 0; i < acfg->image_table->len; i++) {
9869 		MonoImage *image = (MonoImage*)g_ptr_array_index (acfg->image_table, i);
9870 		MonoAssemblyName *aname = &image->assembly->aname;
9871 
9872 		/* FIXME: Support multi-module assemblies */
9873 		g_assert (image->assembly->image == image);
9874 
9875 		encode_string (image->assembly_name, p, &p);
9876 		encode_string (image->guid, p, &p);
9877 		encode_string (aname->culture ? aname->culture : "", p, &p);
9878 		encode_string ((const char*)aname->public_key_token, p, &p);
9879 
9880 		while (GPOINTER_TO_UINT (p) % 8 != 0)
9881 			p ++;
9882 
9883 		encode_int (aname->flags, p, &p);
9884 		encode_int (aname->major, p, &p);
9885 		encode_int (aname->minor, p, &p);
9886 		encode_int (aname->build, p, &p);
9887 		encode_int (aname->revision, p, &p);
9888 	}
9889 	g_assert (p - buf <= buf_size);
9890 
9891 	emit_aot_data (acfg, MONO_AOT_TABLE_IMAGE_TABLE, "image_table", buf, p - buf);
9892 
9893 	g_free (buf);
9894 }
9895 
9896 static void
emit_weak_field_indexes(MonoAotCompile * acfg)9897 emit_weak_field_indexes (MonoAotCompile *acfg)
9898 {
9899 	GHashTable *indexes;
9900 	GHashTableIter iter;
9901 	gpointer key, value;
9902 	int buf_size;
9903 	guint8 *buf, *p;
9904 
9905 	/* Emit a table of weak field indexes, since computing these at runtime is expensive */
9906 	mono_assembly_init_weak_fields (acfg->image);
9907 	indexes = acfg->image->weak_field_indexes;
9908 	g_assert (indexes);
9909 
9910 	buf_size = (g_hash_table_size (indexes) + 1) * 4;
9911 	buf = p = (guint8 *)g_malloc0 (buf_size);
9912 
9913 	encode_int (g_hash_table_size (indexes), p, &p);
9914 	g_hash_table_iter_init (&iter, indexes);
9915 	while (g_hash_table_iter_next (&iter, &key, &value)) {
9916 		guint32 index = GPOINTER_TO_UINT (key);
9917 		encode_int (index, p, &p);
9918 	}
9919 	g_assert (p - buf <= buf_size);
9920 
9921 	emit_aot_data (acfg, MONO_AOT_TABLE_WEAK_FIELD_INDEXES, "weak_field_indexes", buf, p - buf);
9922 
9923 	g_free (buf);
9924 }
9925 
9926 static void
emit_got_info(MonoAotCompile * acfg,gboolean llvm)9927 emit_got_info (MonoAotCompile *acfg, gboolean llvm)
9928 {
9929 	int i, first_plt_got_patch = 0, buf_size;
9930 	guint8 *p, *buf;
9931 	guint32 *got_info_offsets;
9932 	GotInfo *info = llvm ? &acfg->llvm_got_info : &acfg->got_info;
9933 
9934 	/* Add the patches needed by the PLT to the GOT */
9935 	if (!llvm) {
9936 		acfg->plt_got_offset_base = acfg->got_offset;
9937 		first_plt_got_patch = info->got_patches->len;
9938 		for (i = 1; i < acfg->plt_offset; ++i) {
9939 			MonoPltEntry *plt_entry = (MonoPltEntry *)g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
9940 
9941 			g_ptr_array_add (info->got_patches, plt_entry->ji);
9942 
9943 			acfg->stats.got_slot_types [plt_entry->ji->type] ++;
9944 		}
9945 
9946 		acfg->got_offset += acfg->plt_offset;
9947 	}
9948 
9949 	/**
9950 	 * FIXME:
9951 	 * - optimize offsets table.
9952 	 * - reduce number of exported symbols.
9953 	 * - emit info for a klass only once.
9954 	 * - determine when a method uses a GOT slot which is guaranteed to be already
9955 	 *   initialized.
9956 	 * - clean up and document the code.
9957 	 * - use String.Empty in class libs.
9958 	 */
9959 
9960 	/* Encode info required to decode shared GOT entries */
9961 	buf_size = info->got_patches->len * 128;
9962 	p = buf = (guint8 *)mono_mempool_alloc (acfg->mempool, buf_size);
9963 	got_info_offsets = (guint32 *)mono_mempool_alloc (acfg->mempool, info->got_patches->len * sizeof (guint32));
9964 	if (!llvm) {
9965 		acfg->plt_got_info_offsets = (guint32 *)mono_mempool_alloc (acfg->mempool, acfg->plt_offset * sizeof (guint32));
9966 		/* Unused */
9967 		if (acfg->plt_offset)
9968 			acfg->plt_got_info_offsets [0] = 0;
9969 	}
9970 	for (i = 0; i < info->got_patches->len; ++i) {
9971 		MonoJumpInfo *ji = (MonoJumpInfo *)g_ptr_array_index (info->got_patches, i);
9972 		guint8 *p2;
9973 
9974 		p = buf;
9975 
9976 		encode_value (ji->type, p, &p);
9977 		p2 = p;
9978 		encode_patch (acfg, ji, p, &p);
9979 		acfg->stats.got_slot_info_sizes [ji->type] += p - p2;
9980 		g_assert (p - buf <= buf_size);
9981 		got_info_offsets [i] = add_to_blob (acfg, buf, p - buf);
9982 
9983 		if (!llvm && i >= first_plt_got_patch)
9984 			acfg->plt_got_info_offsets [i - first_plt_got_patch + 1] = got_info_offsets [i];
9985 		acfg->stats.got_info_size += p - buf;
9986 	}
9987 
9988 	/* Emit got_info_offsets table */
9989 
9990 	/* No need to emit offsets for the got plt entries, the plt embeds them directly */
9991 	acfg->stats.offsets_size += emit_offset_table (acfg, llvm ? "llvm_got_info_offsets" : "got_info_offsets", llvm ? MONO_AOT_TABLE_LLVM_GOT_INFO_OFFSETS : MONO_AOT_TABLE_GOT_INFO_OFFSETS, llvm ? acfg->llvm_got_offset : first_plt_got_patch, 10, (gint32*)got_info_offsets);
9992 }
9993 
9994 static void
emit_got(MonoAotCompile * acfg)9995 emit_got (MonoAotCompile *acfg)
9996 {
9997 	char symbol [MAX_SYMBOL_SIZE];
9998 
9999 	if (acfg->aot_opts.llvm_only)
10000 		return;
10001 
10002 	/* Don't make GOT global so accesses to it don't need relocations */
10003 	sprintf (symbol, "%s", acfg->got_symbol);
10004 
10005 #ifdef TARGET_MACH
10006 	emit_unset_mode (acfg);
10007 	fprintf (acfg->fp, ".section __DATA, __bss\n");
10008 	emit_alignment (acfg, 8);
10009 	if (acfg->llvm)
10010 		emit_info_symbol (acfg, "jit_got");
10011 	fprintf (acfg->fp, ".lcomm %s, %d\n", acfg->got_symbol, (int)(acfg->got_offset * sizeof (gpointer)));
10012 #else
10013 	emit_section_change (acfg, ".bss", 0);
10014 	emit_alignment (acfg, 8);
10015 	if (acfg->aot_opts.write_symbols)
10016 		emit_local_symbol (acfg, symbol, "got_end", FALSE);
10017 	emit_label (acfg, symbol);
10018 	if (acfg->llvm)
10019 		emit_info_symbol (acfg, "jit_got");
10020 	if (acfg->got_offset > 0)
10021 		emit_zero_bytes (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
10022 #endif
10023 
10024 	sprintf (symbol, "got_end");
10025 	emit_label (acfg, symbol);
10026 }
10027 
10028 typedef struct GlobalsTableEntry {
10029 	guint32 value, index;
10030 	struct GlobalsTableEntry *next;
10031 } GlobalsTableEntry;
10032 
10033 #ifdef TARGET_WIN32_MSVC
10034 #define DLL_ENTRY_POINT "DllMain"
10035 
10036 static void
emit_library_info(MonoAotCompile * acfg)10037 emit_library_info (MonoAotCompile *acfg)
10038 {
10039 	// Only include for shared libraries linked directly from generated object.
10040 	if (link_shared_library (acfg)) {
10041 		char	*name = NULL;
10042 		char	symbol [MAX_SYMBOL_SIZE];
10043 
10044 		// Ask linker to export all global symbols.
10045 		emit_section_change (acfg, ".drectve", 0);
10046 		for (guint i = 0; i < acfg->globals->len; ++i) {
10047 			name = (char *)g_ptr_array_index (acfg->globals, i);
10048 			g_assert (name != NULL);
10049 			sprintf_s (symbol, MAX_SYMBOL_SIZE, " /EXPORT:%s", name);
10050 			emit_string (acfg, symbol);
10051 		}
10052 
10053 		// Emit DLLMain function, needed by MSVC linker for DLL's.
10054 		// NOTE, DllMain should not go into exports above.
10055 		emit_section_change (acfg, ".text", 0);
10056 		emit_global (acfg, DLL_ENTRY_POINT, TRUE);
10057 		emit_label (acfg, DLL_ENTRY_POINT);
10058 
10059 		// Simple implementation of DLLMain, just returning TRUE.
10060 		// For more information about DLLMain: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx
10061 		fprintf (acfg->fp, "movl $1, %%eax\n");
10062 		fprintf (acfg->fp, "ret\n");
10063 
10064 		// Inform linker about our dll entry function.
10065 		emit_section_change (acfg, ".drectve", 0);
10066 		emit_string (acfg, "/ENTRY:" DLL_ENTRY_POINT);
10067 		return;
10068 	}
10069 }
10070 
10071 #else
10072 
10073 static inline void
emit_library_info(MonoAotCompile * acfg)10074 emit_library_info (MonoAotCompile *acfg)
10075 {
10076 	return;
10077 }
10078 #endif
10079 
10080 static void
emit_globals(MonoAotCompile * acfg)10081 emit_globals (MonoAotCompile *acfg)
10082 {
10083 	int i, table_size;
10084 	guint32 hash;
10085 	GPtrArray *table;
10086 	char symbol [1024];
10087 	GlobalsTableEntry *entry, *new_entry;
10088 
10089 	if (!acfg->aot_opts.static_link)
10090 		return;
10091 
10092 	if (acfg->aot_opts.llvm_only) {
10093 		g_assert (acfg->globals->len == 0);
10094 		return;
10095 	}
10096 
10097 	/*
10098 	 * When static linking, we emit a table containing our globals.
10099 	 */
10100 
10101 	/*
10102 	 * Construct a chained hash table for mapping global names to their index in
10103 	 * the globals table.
10104 	 */
10105 	table_size = g_spaced_primes_closest ((int)(acfg->globals->len * 1.5));
10106 	table = g_ptr_array_sized_new (table_size);
10107 	for (i = 0; i < table_size; ++i)
10108 		g_ptr_array_add (table, NULL);
10109 	for (i = 0; i < acfg->globals->len; ++i) {
10110 		char *name = (char *)g_ptr_array_index (acfg->globals, i);
10111 
10112 		hash = mono_metadata_str_hash (name) % table_size;
10113 
10114 		/* FIXME: Allocate from the mempool */
10115 		new_entry = g_new0 (GlobalsTableEntry, 1);
10116 		new_entry->value = i;
10117 
10118 		entry = (GlobalsTableEntry *)g_ptr_array_index (table, hash);
10119 		if (entry == NULL) {
10120 			new_entry->index = hash;
10121 			g_ptr_array_index (table, hash) = new_entry;
10122 		} else {
10123 			while (entry->next)
10124 				entry = entry->next;
10125 
10126 			entry->next = new_entry;
10127 			new_entry->index = table->len;
10128 			g_ptr_array_add (table, new_entry);
10129 		}
10130 	}
10131 
10132 	/* Emit the table */
10133 	sprintf (symbol, ".Lglobals_hash");
10134 	emit_section_change (acfg, RODATA_SECT, 0);
10135 	emit_alignment (acfg, 8);
10136 	emit_label (acfg, symbol);
10137 
10138 	/* FIXME: Optimize memory usage */
10139 	g_assert (table_size < 65000);
10140 	emit_int16 (acfg, table_size);
10141 	for (i = 0; i < table->len; ++i) {
10142 		GlobalsTableEntry *entry = (GlobalsTableEntry *)g_ptr_array_index (table, i);
10143 
10144 		if (entry == NULL) {
10145 			emit_int16 (acfg, 0);
10146 			emit_int16 (acfg, 0);
10147 		} else {
10148 			emit_int16 (acfg, entry->value + 1);
10149 			if (entry->next)
10150 				emit_int16 (acfg, entry->next->index);
10151 			else
10152 				emit_int16 (acfg, 0);
10153 		}
10154 	}
10155 
10156 	/* Emit the names */
10157 	for (i = 0; i < acfg->globals->len; ++i) {
10158 		char *name = (char *)g_ptr_array_index (acfg->globals, i);
10159 
10160 		sprintf (symbol, "name_%d", i);
10161 		emit_section_change (acfg, RODATA_SECT, 1);
10162 #ifdef TARGET_MACH
10163 		emit_alignment (acfg, 4);
10164 #endif
10165 		emit_label (acfg, symbol);
10166 		emit_string (acfg, name);
10167 	}
10168 
10169 	/* Emit the globals table */
10170 	sprintf (symbol, "globals");
10171 	emit_section_change (acfg, ".data", 0);
10172 	/* This is not a global, since it is accessed by the init function */
10173 	emit_alignment (acfg, 8);
10174 	emit_info_symbol (acfg, symbol);
10175 
10176 	sprintf (symbol, "%sglobals_hash", acfg->temp_prefix);
10177 	emit_pointer (acfg, symbol);
10178 
10179 	for (i = 0; i < acfg->globals->len; ++i) {
10180 		char *name = (char *)g_ptr_array_index (acfg->globals, i);
10181 
10182 		sprintf (symbol, "name_%d", i);
10183 		emit_pointer (acfg, symbol);
10184 
10185 		g_assert (strlen (name) < sizeof (symbol));
10186 		sprintf (symbol, "%s", name);
10187 		emit_pointer (acfg, symbol);
10188 	}
10189 	/* Null terminate the table */
10190 	emit_int32 (acfg, 0);
10191 	emit_int32 (acfg, 0);
10192 }
10193 
10194 static void
emit_mem_end(MonoAotCompile * acfg)10195 emit_mem_end (MonoAotCompile *acfg)
10196 {
10197 	char symbol [128];
10198 
10199 	if (acfg->aot_opts.llvm_only)
10200 		return;
10201 
10202 	sprintf (symbol, "mem_end");
10203 	emit_section_change (acfg, ".text", 1);
10204 	emit_alignment_code (acfg, 8);
10205 	emit_label (acfg, symbol);
10206 }
10207 
10208 static void
init_aot_file_info(MonoAotCompile * acfg,MonoAotFileInfo * info)10209 init_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
10210 {
10211 	int i;
10212 
10213 	info->version = MONO_AOT_FILE_VERSION;
10214 	info->plt_got_offset_base = acfg->plt_got_offset_base;
10215 	info->got_size = acfg->got_offset * sizeof (gpointer);
10216 	info->plt_size = acfg->plt_offset;
10217 	info->nmethods = acfg->nmethods;
10218 	info->flags = acfg->flags;
10219 	info->opts = acfg->opts;
10220 	info->simd_opts = acfg->simd_opts;
10221 	info->gc_name_index = acfg->gc_name_offset;
10222 	info->datafile_size = acfg->datafile_offset;
10223 	for (i = 0; i < MONO_AOT_TABLE_NUM; ++i)
10224 		info->table_offsets [i] = acfg->table_offsets [i];
10225 	for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
10226 		info->num_trampolines [i] = acfg->num_trampolines [i];
10227 	for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
10228 		info->trampoline_got_offset_base [i] = acfg->trampoline_got_offset_base [i];
10229 	for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
10230 		info->trampoline_size [i] = acfg->trampoline_size [i];
10231 	info->num_rgctx_fetch_trampolines = acfg->aot_opts.nrgctx_fetch_trampolines;
10232 
10233 	info->double_align = MONO_ABI_ALIGNOF (double);
10234 	info->long_align = MONO_ABI_ALIGNOF (gint64);
10235 	info->generic_tramp_num = MONO_TRAMPOLINE_NUM;
10236 	info->tramp_page_size = acfg->tramp_page_size;
10237 	info->nshared_got_entries = acfg->nshared_got_entries;
10238 	for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
10239 		info->tramp_page_code_offsets [i] = acfg->tramp_page_code_offsets [i];
10240 
10241 	memcpy(&info->aotid, acfg->image->aotid, 16);
10242 }
10243 
10244 static void
emit_aot_file_info(MonoAotCompile * acfg,MonoAotFileInfo * info)10245 emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
10246 {
10247 	char symbol [MAX_SYMBOL_SIZE];
10248 	int i, sindex;
10249 	const char **symbols;
10250 
10251 	symbols = g_new0 (const char *, MONO_AOT_FILE_INFO_NUM_SYMBOLS);
10252 	sindex = 0;
10253 	symbols [sindex ++] = acfg->got_symbol;
10254 	if (acfg->llvm) {
10255 		symbols [sindex ++] = g_strdup_printf ("%s%s", acfg->user_symbol_prefix, acfg->llvm_got_symbol);
10256 		symbols [sindex ++] = acfg->llvm_eh_frame_symbol;
10257 	} else {
10258 		symbols [sindex ++] = NULL;
10259 		symbols [sindex ++] = NULL;
10260 	}
10261 	/* llvm_get_method */
10262 	symbols [sindex ++] = NULL;
10263 	/* llvm_get_unbox_tramp */
10264 	symbols [sindex ++] = NULL;
10265 	if (!acfg->aot_opts.llvm_only) {
10266 		symbols [sindex ++] = "jit_code_start";
10267 		symbols [sindex ++] = "jit_code_end";
10268 		symbols [sindex ++] = "method_addresses";
10269 	} else {
10270 		symbols [sindex ++] = NULL;
10271 		symbols [sindex ++] = NULL;
10272 		symbols [sindex ++] = NULL;
10273 	}
10274 
10275 	if (acfg->data_outfile) {
10276 		for (i = 0; i < MONO_AOT_TABLE_NUM; ++i)
10277 			symbols [sindex ++] = NULL;
10278 	} else {
10279 		symbols [sindex ++] = "blob";
10280 		symbols [sindex ++] = "class_name_table";
10281 		symbols [sindex ++] = "class_info_offsets";
10282 		symbols [sindex ++] = "method_info_offsets";
10283 		symbols [sindex ++] = "ex_info_offsets";
10284 		symbols [sindex ++] = "extra_method_info_offsets";
10285 		symbols [sindex ++] = "extra_method_table";
10286 		symbols [sindex ++] = "got_info_offsets";
10287 		if (acfg->llvm)
10288 			symbols [sindex ++] = "llvm_got_info_offsets";
10289 		else
10290 			symbols [sindex ++] = NULL;
10291 		symbols [sindex ++] = "image_table";
10292 		symbols [sindex ++] = "weak_field_indexes";
10293 	}
10294 
10295 	symbols [sindex ++] = "mem_end";
10296 	symbols [sindex ++] = "assembly_guid";
10297 	symbols [sindex ++] = "runtime_version";
10298 	if (acfg->num_trampoline_got_entries) {
10299 		symbols [sindex ++] = "specific_trampolines";
10300 		symbols [sindex ++] = "static_rgctx_trampolines";
10301 		symbols [sindex ++] = "imt_trampolines";
10302 		symbols [sindex ++] = "gsharedvt_arg_trampolines";
10303 	} else {
10304 		symbols [sindex ++] = NULL;
10305 		symbols [sindex ++] = NULL;
10306 		symbols [sindex ++] = NULL;
10307 		symbols [sindex ++] = NULL;
10308 	}
10309 	if (acfg->aot_opts.static_link) {
10310 		symbols [sindex ++] = "globals";
10311 	} else {
10312 		symbols [sindex ++] = NULL;
10313 	}
10314 	symbols [sindex ++] = "assembly_name";
10315 	symbols [sindex ++] = "plt";
10316 	symbols [sindex ++] = "plt_end";
10317 	symbols [sindex ++] = "unwind_info";
10318 	if (!acfg->aot_opts.llvm_only) {
10319 		symbols [sindex ++] = "unbox_trampolines";
10320 		symbols [sindex ++] = "unbox_trampolines_end";
10321 		symbols [sindex ++] = "unbox_trampoline_addresses";
10322 	} else {
10323 		symbols [sindex ++] = NULL;
10324 		symbols [sindex ++] = NULL;
10325 		symbols [sindex ++] = NULL;
10326 	}
10327 
10328 	g_assert (sindex == MONO_AOT_FILE_INFO_NUM_SYMBOLS);
10329 
10330 	sprintf (symbol, "%smono_aot_file_info", acfg->user_symbol_prefix);
10331 	emit_section_change (acfg, ".data", 0);
10332 	emit_alignment (acfg, 8);
10333 	emit_label (acfg, symbol);
10334 	if (!acfg->aot_opts.static_link)
10335 		emit_global (acfg, symbol, FALSE);
10336 
10337 	/* The data emitted here must match MonoAotFileInfo. */
10338 
10339 	emit_int32 (acfg, info->version);
10340 	emit_int32 (acfg, info->dummy);
10341 
10342 	/*
10343 	 * We emit pointers to our data structures instead of emitting global symbols which
10344 	 * point to them, to reduce the number of globals, and because using globals leads to
10345 	 * various problems (i.e. arm/thumb).
10346 	 */
10347 	for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i)
10348 		emit_pointer (acfg, symbols [i]);
10349 
10350 	emit_int32 (acfg, info->plt_got_offset_base);
10351 	emit_int32 (acfg, info->got_size);
10352 	emit_int32 (acfg, info->plt_size);
10353 	emit_int32 (acfg, info->nmethods);
10354 	emit_int32 (acfg, info->flags);
10355 	emit_int32 (acfg, info->opts);
10356 	emit_int32 (acfg, info->simd_opts);
10357 	emit_int32 (acfg, info->gc_name_index);
10358 	emit_int32 (acfg, info->num_rgctx_fetch_trampolines);
10359 	emit_int32 (acfg, info->double_align);
10360 	emit_int32 (acfg, info->long_align);
10361 	emit_int32 (acfg, info->generic_tramp_num);
10362 	emit_int32 (acfg, info->tramp_page_size);
10363 	emit_int32 (acfg, info->nshared_got_entries);
10364 	emit_int32 (acfg, info->datafile_size);
10365 
10366 	for (i = 0; i < MONO_AOT_TABLE_NUM; ++i)
10367 		emit_int32 (acfg, info->table_offsets [i]);
10368 	for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
10369 		emit_int32 (acfg, info->num_trampolines [i]);
10370 	for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
10371 		emit_int32 (acfg, info->trampoline_got_offset_base [i]);
10372 	for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
10373 		emit_int32 (acfg, info->trampoline_size [i]);
10374 	for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
10375 		emit_int32 (acfg, info->tramp_page_code_offsets [i]);
10376 
10377 	emit_bytes (acfg, info->aotid, 16);
10378 
10379 	if (acfg->aot_opts.static_link) {
10380 		emit_global_inner (acfg, acfg->static_linking_symbol, FALSE);
10381 		emit_alignment (acfg, sizeof (gpointer));
10382 		emit_label (acfg, acfg->static_linking_symbol);
10383 		emit_pointer_2 (acfg, acfg->user_symbol_prefix, "mono_aot_file_info");
10384 	}
10385 }
10386 
10387 /*
10388  * Emit a structure containing all the information not stored elsewhere.
10389  */
10390 static void
emit_file_info(MonoAotCompile * acfg)10391 emit_file_info (MonoAotCompile *acfg)
10392 {
10393 	char *build_info;
10394 	MonoAotFileInfo *info;
10395 
10396 	if (acfg->aot_opts.bind_to_runtime_version) {
10397 		build_info = mono_get_runtime_build_info ();
10398 		emit_string_symbol (acfg, "runtime_version", build_info);
10399 		g_free (build_info);
10400 	} else {
10401 		emit_string_symbol (acfg, "runtime_version", "");
10402 	}
10403 
10404 	emit_string_symbol (acfg, "assembly_guid" , acfg->image->guid);
10405 
10406 	/* Emit a string holding the assembly name */
10407 	emit_string_symbol (acfg, "assembly_name", acfg->image->assembly->aname.name);
10408 
10409 	info = g_new0 (MonoAotFileInfo, 1);
10410 	init_aot_file_info (acfg, info);
10411 
10412 	if (acfg->aot_opts.static_link) {
10413 		char symbol [MAX_SYMBOL_SIZE];
10414 		char *p;
10415 
10416 		/*
10417 		 * Emit a global symbol which can be passed by an embedding app to
10418 		 * mono_aot_register_module (). The symbol points to a pointer to the the file info
10419 		 * structure.
10420 		 */
10421 		sprintf (symbol, "%smono_aot_module_%s_info", acfg->user_symbol_prefix, acfg->image->assembly->aname.name);
10422 
10423 		/* Get rid of characters which cannot occur in symbols */
10424 		p = symbol;
10425 		for (p = symbol; *p; ++p) {
10426 			if (!(isalnum (*p) || *p == '_'))
10427 				*p = '_';
10428 		}
10429 		acfg->static_linking_symbol = g_strdup (symbol);
10430 	}
10431 
10432 	if (acfg->llvm)
10433 		mono_llvm_emit_aot_file_info (info, acfg->has_jitted_code);
10434 	else
10435 		emit_aot_file_info (acfg, info);
10436 }
10437 
10438 static void
emit_blob(MonoAotCompile * acfg)10439 emit_blob (MonoAotCompile *acfg)
10440 {
10441 	acfg->blob_closed = TRUE;
10442 
10443 	emit_aot_data (acfg, MONO_AOT_TABLE_BLOB, "blob", (guint8*)acfg->blob.data, acfg->blob.index);
10444 }
10445 
10446 static void
emit_objc_selectors(MonoAotCompile * acfg)10447 emit_objc_selectors (MonoAotCompile *acfg)
10448 {
10449 	int i;
10450 	char symbol [128];
10451 
10452 	if (!acfg->objc_selectors || acfg->objc_selectors->len == 0)
10453 		return;
10454 
10455 	/*
10456 	 * From
10457 	 * cat > foo.m << EOF
10458 	 * void *ret ()
10459 	 * {
10460 	 * return @selector(print:);
10461 	 * }
10462 	 * EOF
10463 	 */
10464 
10465 	mono_img_writer_emit_unset_mode (acfg->w);
10466 	g_assert (acfg->fp);
10467 	fprintf (acfg->fp, ".section	__DATA,__objc_selrefs,literal_pointers,no_dead_strip\n");
10468 	fprintf (acfg->fp, ".align	3\n");
10469 	for (i = 0; i < acfg->objc_selectors->len; ++i) {
10470 		sprintf (symbol, "L_OBJC_SELECTOR_REFERENCES_%d", i);
10471 		emit_label (acfg, symbol);
10472 		sprintf (symbol, "L_OBJC_METH_VAR_NAME_%d", i);
10473 		emit_pointer (acfg, symbol);
10474 
10475 	}
10476 	fprintf (acfg->fp, ".section	__TEXT,__cstring,cstring_literals\n");
10477 	for (i = 0; i < acfg->objc_selectors->len; ++i) {
10478 		fprintf (acfg->fp, "L_OBJC_METH_VAR_NAME_%d:\n", i);
10479 		fprintf (acfg->fp, ".asciz \"%s\"\n", (char*)g_ptr_array_index (acfg->objc_selectors, i));
10480 	}
10481 
10482 	fprintf (acfg->fp, ".section	__DATA,__objc_imageinfo,regular,no_dead_strip\n");
10483 	fprintf (acfg->fp, ".align	3\n");
10484 	fprintf (acfg->fp, "L_OBJC_IMAGE_INFO:\n");
10485 	fprintf (acfg->fp, ".long	0\n");
10486 	fprintf (acfg->fp, ".long	16\n");
10487 }
10488 
10489 static void
emit_dwarf_info(MonoAotCompile * acfg)10490 emit_dwarf_info (MonoAotCompile *acfg)
10491 {
10492 #ifdef EMIT_DWARF_INFO
10493 	int i;
10494 	char symbol2 [128];
10495 
10496 	/* DIEs for methods */
10497 	for (i = 0; i < acfg->nmethods; ++i) {
10498 		MonoCompile *cfg = acfg->cfgs [i];
10499 
10500 		if (ignore_cfg (cfg))
10501 			continue;
10502 
10503 		// FIXME: LLVM doesn't define .Lme_...
10504 		if (cfg->compile_llvm)
10505 			continue;
10506 
10507 		sprintf (symbol2, "%sme_%x", acfg->temp_prefix, i);
10508 
10509 		mono_dwarf_writer_emit_method (acfg->dwarf, cfg, cfg->method, cfg->asm_symbol, symbol2, cfg->asm_debug_symbol, (guint8 *)cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, mono_debug_find_method (cfg->jit_info->d.method, mono_domain_get ()));
10510 	}
10511 #endif
10512 }
10513 
10514 #ifdef EMIT_WIN32_CODEVIEW_INFO
10515 typedef struct _CodeViewSubSectionData
10516 {
10517 	gchar *start_section;
10518 	gchar *end_section;
10519 	gchar *start_section_record;
10520 	gchar *end_section_record;
10521 	int section_type;
10522 	int section_record_type;
10523 	int section_id;
10524 } CodeViewSubsectionData;
10525 
10526 typedef struct _CodeViewCompilerVersion
10527 {
10528 	gint major;
10529 	gint minor;
10530 	gint revision;
10531 	gint patch;
10532 } CodeViewCompilerVersion;
10533 
10534 #define CODEVIEW_SUBSECTION_SYMBOL_TYPE 0xF1
10535 #define CODEVIEW_SUBSECTION_RECORD_COMPILER_TYPE 0x113c
10536 #define CODEVIEW_SUBSECTION_RECORD_FUNCTION_START_TYPE 0x1147
10537 #define CODEVIEW_SUBSECTION_RECORD_FUNCTION_END_TYPE 0x114F
10538 #define CODEVIEW_CSHARP_LANGUAGE_TYPE 0x0A
10539 #define CODEVIEW_CPU_TYPE 0x0
10540 #define CODEVIEW_MAGIC_HEADER 0x4
10541 
10542 static void
codeview_clear_subsection_data(CodeViewSubsectionData * section_data)10543 codeview_clear_subsection_data (CodeViewSubsectionData *section_data)
10544 {
10545 	g_free (section_data->start_section);
10546 	g_free (section_data->end_section);
10547 	g_free (section_data->start_section_record);
10548 	g_free (section_data->end_section_record);
10549 
10550 	memset (section_data, 0, sizeof (CodeViewSubsectionData));
10551 }
10552 
10553 static void
codeview_parse_compiler_version(gchar * version,CodeViewCompilerVersion * data)10554 codeview_parse_compiler_version (gchar *version, CodeViewCompilerVersion *data)
10555 {
10556 	gint values[4] = { 0 };
10557 	gint *value = values;
10558 
10559 	while (*version && (value < values + G_N_ELEMENTS (values))) {
10560 		if (isdigit (*version)) {
10561 			*value *= 10;
10562 			*value += *version - '0';
10563 		}
10564 		else if (*version == '.') {
10565 			value++;
10566 		}
10567 
10568 		version++;
10569 	}
10570 
10571 	data->major = values[0];
10572 	data->minor = values[1];
10573 	data->revision = values[2];
10574 	data->patch = values[3];
10575 }
10576 
10577 static void
emit_codeview_start_subsection(MonoAotCompile * acfg,int section_id,int section_type,int section_record_type,CodeViewSubsectionData * section_data)10578 emit_codeview_start_subsection (MonoAotCompile *acfg, int section_id, int section_type, int section_record_type, CodeViewSubsectionData *section_data)
10579 {
10580 	// Starting a new subsection, clear old data.
10581 	codeview_clear_subsection_data (section_data);
10582 
10583 	// Keep subsection data.
10584 	section_data->section_id = section_id;
10585 	section_data->section_type = section_type;
10586 	section_data->section_record_type = section_record_type;
10587 
10588 	// Allocate all labels used in subsection.
10589 	section_data->start_section = g_strdup_printf ("%scvs_%d", acfg->temp_prefix, section_data->section_id);
10590 	section_data->end_section = g_strdup_printf ("%scvse_%d", acfg->temp_prefix, section_data->section_id);
10591 	section_data->start_section_record = g_strdup_printf ("%scvsr_%d", acfg->temp_prefix, section_data->section_id);
10592 	section_data->end_section_record = g_strdup_printf ("%scvsre_%d", acfg->temp_prefix, section_data->section_id);
10593 
10594 	// Subsection type, function symbol.
10595 	emit_int32 (acfg, section_data->section_type);
10596 
10597 	// Subsection size.
10598 	emit_symbol_diff (acfg, section_data->end_section, section_data->start_section, 0);
10599 	emit_label (acfg, section_data->start_section);
10600 
10601 	// Subsection record size.
10602 	fprintf (acfg->fp, "\t.word %s - %s\n", section_data->end_section_record, section_data->start_section_record);
10603 	emit_label (acfg, section_data->start_section_record);
10604 
10605 	// Subsection record type.
10606 	emit_int16 (acfg, section_record_type);
10607 }
10608 
10609 static void
emit_codeview_end_subsection(MonoAotCompile * acfg,CodeViewSubsectionData * section_data,int * section_id)10610 emit_codeview_end_subsection (MonoAotCompile *acfg, CodeViewSubsectionData *section_data, int *section_id)
10611 {
10612 	g_assert (section_data->start_section);
10613 	g_assert (section_data->end_section);
10614 	g_assert (section_data->start_section_record);
10615 	g_assert (section_data->end_section_record);
10616 
10617 	emit_label (acfg, section_data->end_section_record);
10618 
10619 	if (section_data->section_record_type == CODEVIEW_SUBSECTION_RECORD_FUNCTION_START_TYPE) {
10620 		// Emit record length.
10621 		emit_int16 (acfg, 2);
10622 
10623 		// Emit specific record type end.
10624 		emit_int16 (acfg, CODEVIEW_SUBSECTION_RECORD_FUNCTION_END_TYPE);
10625 	}
10626 
10627 	emit_label (acfg, section_data->end_section);
10628 
10629 	// Next subsection needs to be 4 byte aligned.
10630 	emit_alignment (acfg, 4);
10631 
10632 	*section_id = section_data->section_id + 1;
10633 	codeview_clear_subsection_data (section_data);
10634 }
10635 
10636 inline static void
emit_codeview_start_symbol_subsection(MonoAotCompile * acfg,int section_id,int section_record_type,CodeViewSubsectionData * section_data)10637 emit_codeview_start_symbol_subsection (MonoAotCompile *acfg, int section_id, int section_record_type, CodeViewSubsectionData *section_data)
10638 {
10639 	emit_codeview_start_subsection (acfg, section_id, CODEVIEW_SUBSECTION_SYMBOL_TYPE, section_record_type, section_data);
10640 }
10641 
10642 inline static void
emit_codeview_end_symbol_subsection(MonoAotCompile * acfg,CodeViewSubsectionData * section_data,int * section_id)10643 emit_codeview_end_symbol_subsection (MonoAotCompile *acfg, CodeViewSubsectionData *section_data, int *section_id)
10644 {
10645 	emit_codeview_end_subsection (acfg, section_data, section_id);
10646 }
10647 
10648 static void
emit_codeview_compiler_info(MonoAotCompile * acfg,int * section_id)10649 emit_codeview_compiler_info (MonoAotCompile *acfg, int *section_id)
10650 {
10651 	CodeViewSubsectionData section_data = { 0 };
10652 	CodeViewCompilerVersion compiler_version = { 0 };
10653 
10654 	// Start new compiler record subsection.
10655 	emit_codeview_start_symbol_subsection (acfg, *section_id, CODEVIEW_SUBSECTION_RECORD_COMPILER_TYPE, &section_data);
10656 
10657 	emit_int32 (acfg, CODEVIEW_CSHARP_LANGUAGE_TYPE);
10658 	emit_int16 (acfg, CODEVIEW_CPU_TYPE);
10659 
10660 	// Get compiler version information.
10661 	codeview_parse_compiler_version (VERSION, &compiler_version);
10662 
10663 	// Compiler frontend version, 4 digits.
10664 	emit_int16 (acfg, compiler_version.major);
10665 	emit_int16 (acfg, compiler_version.minor);
10666 	emit_int16 (acfg, compiler_version.revision);
10667 	emit_int16 (acfg, compiler_version.patch);
10668 
10669 	// Compiler backend version, 4 digits (currently same as frontend).
10670 	emit_int16 (acfg, compiler_version.major);
10671 	emit_int16 (acfg, compiler_version.minor);
10672 	emit_int16 (acfg, compiler_version.revision);
10673 	emit_int16 (acfg, compiler_version.patch);
10674 
10675 	// Compiler string.
10676 	emit_string (acfg, "Mono AOT compiler");
10677 
10678 	// Done with section.
10679 	emit_codeview_end_symbol_subsection (acfg, &section_data, section_id);
10680 }
10681 
10682 static void
emit_codeview_function_info(MonoAotCompile * acfg,MonoMethod * method,int * section_id,gchar * symbol,gchar * symbol_start,gchar * symbol_end)10683 emit_codeview_function_info (MonoAotCompile *acfg, MonoMethod *method, int *section_id, gchar *symbol, gchar *symbol_start, gchar *symbol_end)
10684 {
10685 	CodeViewSubsectionData section_data = { 0 };
10686 	gchar *full_method_name = NULL;
10687 
10688 	// Start new function record subsection.
10689 	emit_codeview_start_symbol_subsection (acfg, *section_id, CODEVIEW_SUBSECTION_RECORD_FUNCTION_START_TYPE, &section_data);
10690 
10691 	// Emit 3 int 0 byte padding, currently not used.
10692 	emit_zero_bytes (acfg, sizeof (int) * 3);
10693 
10694 	// Emit size of function.
10695 	emit_symbol_diff (acfg, symbol_end, symbol_start, 0);
10696 
10697 	// Emit 3 int 0 byte padding, currently not used.
10698 	emit_zero_bytes (acfg, sizeof (int) * 3);
10699 
10700 	// Emit reallocation info.
10701 	fprintf (acfg->fp, "\t.secrel32 %s\n", symbol);
10702 	fprintf (acfg->fp, "\t.secidx %s\n", symbol);
10703 
10704 	// Emit flag, currently not used.
10705 	emit_zero_bytes (acfg, 1);
10706 
10707 	// Emit function name, exclude signature since it should be described by own metadata.
10708 	full_method_name = mono_method_full_name (method, FALSE);
10709 	emit_string (acfg, full_method_name ? full_method_name : "");
10710 	g_free (full_method_name);
10711 
10712 	// Done with section.
10713 	emit_codeview_end_symbol_subsection (acfg, &section_data, section_id);
10714 }
10715 
10716 static void
emit_codeview_info(MonoAotCompile * acfg)10717 emit_codeview_info (MonoAotCompile *acfg)
10718 {
10719 	int i;
10720 	int section_id = 0;
10721 	gchar symbol_buffer[MAX_SYMBOL_SIZE];
10722 
10723 	// Emit codeview debug info section
10724 	emit_section_change (acfg, ".debug$S", 0);
10725 
10726 	// Emit magic header.
10727 	emit_int32 (acfg, CODEVIEW_MAGIC_HEADER);
10728 
10729 	emit_codeview_compiler_info (acfg, &section_id);
10730 
10731 	for (i = 0; i < acfg->nmethods; ++i) {
10732 		MonoCompile *cfg = acfg->cfgs[i];
10733 
10734 		if (!cfg)
10735 			continue;
10736 
10737 		int ret = g_snprintf (symbol_buffer, G_N_ELEMENTS (symbol_buffer), "%sme_%x", acfg->temp_prefix, i);
10738 		if (ret > 0 && ret < G_N_ELEMENTS (symbol_buffer))
10739 			emit_codeview_function_info (acfg, cfg->method, &section_id, cfg->asm_debug_symbol, cfg->asm_symbol, symbol_buffer);
10740 	}
10741 }
10742 #else
10743 static void
emit_codeview_info(MonoAotCompile * acfg)10744 emit_codeview_info (MonoAotCompile *acfg)
10745 {
10746 }
10747 #endif /* EMIT_WIN32_CODEVIEW_INFO */
10748 
10749 #ifdef EMIT_WIN32_UNWIND_INFO
10750 static UnwindInfoSectionCacheItem *
get_cached_unwind_info_section_item_win32(MonoAotCompile * acfg,const char * function_start,const char * function_end,GSList * unwind_ops)10751 get_cached_unwind_info_section_item_win32 (MonoAotCompile *acfg, const char *function_start, const char *function_end, GSList *unwind_ops)
10752 {
10753 	UnwindInfoSectionCacheItem *item = NULL;
10754 
10755 	if (!acfg->unwind_info_section_cache)
10756 		acfg->unwind_info_section_cache = g_list_alloc ();
10757 
10758 	PUNWIND_INFO unwind_info = mono_arch_unwindinfo_alloc_unwind_info (unwind_ops);
10759 
10760 	// Search for unwind info in cache.
10761 	GList *list = acfg->unwind_info_section_cache;
10762 	int list_size = 0;
10763 	while (list && list->data) {
10764 		item = (UnwindInfoSectionCacheItem*)list->data;
10765 		if (!memcmp (unwind_info, item->unwind_info, sizeof (UNWIND_INFO))) {
10766 			// Cache hit, return cached item.
10767 			return item;
10768 		}
10769 		list = list->next;
10770 		list_size++;
10771 	}
10772 
10773 	// Add to cache.
10774 	if (acfg->unwind_info_section_cache) {
10775 		item = g_new0 (UnwindInfoSectionCacheItem, 1);
10776 		if (item) {
10777 			// Format .xdata section label for function, used to get unwind info address RVA.
10778 			// Since the unwind info is similar for most functions, the symbol will be reused.
10779 			item->xdata_section_label = g_strdup_printf ("%sunwind_%d", acfg->temp_prefix, list_size);
10780 
10781 			// Cache unwind info data, used when checking cache for matching unwind info. NOTE, cache takes
10782 			//over ownership of unwind info.
10783 			item->unwind_info = unwind_info;
10784 
10785 			// Needs to be emitted once.
10786 			item->xdata_section_emitted = FALSE;
10787 
10788 			// Prepend to beginning of list to speed up inserts.
10789 			acfg->unwind_info_section_cache = g_list_prepend (acfg->unwind_info_section_cache, (gpointer)item);
10790 		}
10791 	}
10792 
10793 	return item;
10794 }
10795 
10796 static void
free_unwind_info_section_cache_win32(MonoAotCompile * acfg)10797 free_unwind_info_section_cache_win32 (MonoAotCompile *acfg)
10798 {
10799 	GList *list = acfg->unwind_info_section_cache;
10800 
10801 	while (list) {
10802 		UnwindInfoSectionCacheItem *item = (UnwindInfoSectionCacheItem *)list->data;
10803 		if (item) {
10804 			g_free (item->xdata_section_label);
10805 			mono_arch_unwindinfo_free_unwind_info (item->unwind_info);
10806 
10807 			g_free (item);
10808 			list->data = NULL;
10809 		}
10810 
10811 		list = list->next;
10812 	}
10813 
10814 	g_list_free (acfg->unwind_info_section_cache);
10815 	acfg->unwind_info_section_cache = NULL;
10816 }
10817 
10818 static void
emit_unwind_info_data_win32(MonoAotCompile * acfg,PUNWIND_INFO unwind_info)10819 emit_unwind_info_data_win32 (MonoAotCompile *acfg, PUNWIND_INFO unwind_info)
10820 {
10821 	// Emit the unwind info struct.
10822 	emit_bytes (acfg, (guint8*)unwind_info, sizeof (UNWIND_INFO) - (sizeof (UNWIND_CODE) * MONO_MAX_UNWIND_CODES));
10823 
10824 	// Emit all unwind codes encoded in unwind info struct.
10825 	PUNWIND_CODE current_unwind_node = &unwind_info->UnwindCode[MONO_MAX_UNWIND_CODES - unwind_info->CountOfCodes];
10826 	PUNWIND_CODE last_unwind_node = &unwind_info->UnwindCode[MONO_MAX_UNWIND_CODES];
10827 
10828 	while (current_unwind_node < last_unwind_node) {
10829 		guint8 node_count = 0;
10830 		switch (current_unwind_node->UnwindOp) {
10831 		case UWOP_PUSH_NONVOL:
10832 		case UWOP_ALLOC_SMALL:
10833 		case UWOP_SET_FPREG:
10834 		case UWOP_PUSH_MACHFRAME:
10835 			node_count = 1;
10836 			break;
10837 		case UWOP_SAVE_NONVOL:
10838 		case UWOP_SAVE_XMM128:
10839 			node_count = 2;
10840 			break;
10841 		case UWOP_SAVE_NONVOL_FAR:
10842 		case UWOP_SAVE_XMM128_FAR:
10843 			node_count = 3;
10844 			break;
10845 		case UWOP_ALLOC_LARGE:
10846 			if (current_unwind_node->OpInfo == 0)
10847 				node_count = 2;
10848 			else
10849 				node_count = 3;
10850 			break;
10851 		default:
10852 			g_assert (!"Unknown unwind opcode.");
10853 		}
10854 
10855 		while (node_count > 0) {
10856 			g_assert (current_unwind_node < last_unwind_node);
10857 
10858 			//Emit current node.
10859 			emit_bytes (acfg, (guint8*)current_unwind_node, sizeof (UNWIND_CODE));
10860 
10861 			node_count--;
10862 			current_unwind_node++;
10863 		}
10864 	}
10865 }
10866 
10867 // Emit unwind info sections for each function. Unwind info on Windows x64 is emitted into two different sections.
10868 // .pdata includes the serialized DWORD aligned RVA's of function start, end and address of serialized
10869 // UNWIND_INFO struct emitted into .xdata, see https://msdn.microsoft.com/en-us/library/ft9x1kdx.aspx.
10870 // .xdata section includes DWORD aligned serialized version of UNWIND_INFO struct, https://msdn.microsoft.com/en-us/library/ddssxxy8.aspx.
10871 static void
emit_unwind_info_sections_win32(MonoAotCompile * acfg,const char * function_start,const char * function_end,GSList * unwind_ops)10872 emit_unwind_info_sections_win32 (MonoAotCompile *acfg, const char *function_start, const char *function_end, GSList *unwind_ops)
10873 {
10874 	char *pdata_section_label = NULL;
10875 
10876 	int temp_prefix_len = (acfg->temp_prefix != NULL) ? strlen (acfg->temp_prefix) : 0;
10877 	if (strncmp (function_start, acfg->temp_prefix, temp_prefix_len)) {
10878 		temp_prefix_len = 0;
10879 	}
10880 
10881 	// Format .pdata section label for function.
10882 	pdata_section_label = g_strdup_printf ("%spdata_%s", acfg->temp_prefix, function_start + temp_prefix_len);
10883 
10884 	UnwindInfoSectionCacheItem *cache_item = get_cached_unwind_info_section_item_win32 (acfg, function_start, function_end, unwind_ops);
10885 	g_assert (cache_item && cache_item->xdata_section_label && cache_item->unwind_info);
10886 
10887 	// Emit .pdata section.
10888 	emit_section_change (acfg, ".pdata", 0);
10889 	emit_alignment (acfg, sizeof (DWORD));
10890 	emit_label (acfg, pdata_section_label);
10891 
10892 	// Emit function start address RVA.
10893 	fprintf (acfg->fp, "\t.long %s@IMGREL\n", function_start);
10894 
10895 	// Emit function end address RVA.
10896 	fprintf (acfg->fp, "\t.long %s@IMGREL\n", function_end);
10897 
10898 	// Emit unwind info address RVA.
10899 	fprintf (acfg->fp, "\t.long %s@IMGREL\n", cache_item->xdata_section_label);
10900 
10901 	if (!cache_item->xdata_section_emitted) {
10902 		// Emit .xdata section.
10903 		emit_section_change (acfg, ".xdata", 0);
10904 		emit_alignment (acfg, sizeof (DWORD));
10905 		emit_label (acfg, cache_item->xdata_section_label);
10906 
10907 		// Emit unwind info into .xdata section.
10908 		emit_unwind_info_data_win32 (acfg, cache_item->unwind_info);
10909 		cache_item->xdata_section_emitted = TRUE;
10910 	}
10911 
10912 	g_free (pdata_section_label);
10913 }
10914 #endif
10915 
10916 static gboolean
collect_methods(MonoAotCompile * acfg)10917 collect_methods (MonoAotCompile *acfg)
10918 {
10919 	int mindex, i;
10920 	MonoImage *image = acfg->image;
10921 
10922 	/* Collect methods */
10923 	for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
10924 		MonoError error;
10925 		MonoMethod *method;
10926 		guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
10927 
10928 		method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
10929 
10930 		if (!method) {
10931 			aot_printerrf (acfg, "Failed to load method 0x%x from '%s' due to %s.\n", token, image->name, mono_error_get_message (&error));
10932 			aot_printerrf (acfg, "Run with MONO_LOG_LEVEL=debug for more information.\n");
10933 			mono_error_cleanup (&error);
10934 			return FALSE;
10935 		}
10936 
10937 		/* Load all methods eagerly to skip the slower lazy loading code */
10938 		mono_class_setup_methods (method->klass);
10939 
10940 		if (mono_aot_mode_is_full (&acfg->aot_opts) && method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10941 			/* Compile the wrapper instead */
10942 			/* We do this here instead of add_wrappers () because it is easy to do it here */
10943 			MonoMethod *wrapper = mono_marshal_get_native_wrapper (method, TRUE, TRUE);
10944 			method = wrapper;
10945 		}
10946 
10947 		/* FIXME: Some mscorlib methods don't have debug info */
10948 		/*
10949 		if (acfg->aot_opts.soft_debug && !method->wrapper_type) {
10950 			if (!((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10951 				  (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
10952 				  (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
10953 				  (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))) {
10954 				if (!mono_debug_lookup_method (method)) {
10955 					fprintf (stderr, "Method %s has no debug info, probably the .mdb file for the assembly is missing.\n", mono_method_get_full_name (method));
10956 					exit (1);
10957 				}
10958 			}
10959 		}
10960 		*/
10961 
10962 		if (method->is_generic || mono_class_is_gtd (method->klass))
10963 			/* Compile the ref shared version instead */
10964 			method = mini_get_shared_method (method);
10965 
10966 		/* Since we add the normal methods first, their index will be equal to their zero based token index */
10967 		add_method_with_index (acfg, method, i, FALSE);
10968 		acfg->method_index ++;
10969 	}
10970 
10971 	/* gsharedvt methods */
10972 	for (mindex = 0; mindex < image->tables [MONO_TABLE_METHOD].rows; ++mindex) {
10973 		MonoError error;
10974 		MonoMethod *method;
10975 		guint32 token = MONO_TOKEN_METHOD_DEF | (mindex + 1);
10976 
10977 		if (!(acfg->opts & MONO_OPT_GSHAREDVT))
10978 			continue;
10979 
10980 		method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
10981 		report_loader_error (acfg, &error, TRUE, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
10982 
10983 		if (method->is_generic || mono_class_is_gtd (method->klass)) {
10984 			MonoMethod *gshared;
10985 
10986 			gshared = mini_get_shared_method_full (method, TRUE, TRUE);
10987 			add_extra_method (acfg, gshared);
10988 		}
10989 	}
10990 
10991 	if (mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts))
10992 		add_generic_instances (acfg);
10993 
10994 	if (mono_aot_mode_is_full (&acfg->aot_opts))
10995 		add_wrappers (acfg);
10996 	return TRUE;
10997 }
10998 
10999 static void
compile_methods(MonoAotCompile * acfg)11000 compile_methods (MonoAotCompile *acfg)
11001 {
11002 	int i, methods_len;
11003 
11004 	if (acfg->aot_opts.nthreads > 0) {
11005 		GPtrArray *frag;
11006 		int len, j;
11007 		GPtrArray *threads;
11008 		MonoThreadHandle *thread_handle;
11009 		gpointer *user_data;
11010 		MonoMethod **methods;
11011 
11012 		methods_len = acfg->methods->len;
11013 
11014 		len = acfg->methods->len / acfg->aot_opts.nthreads;
11015 		g_assert (len > 0);
11016 		/*
11017 		 * Partition the list of methods into fragments, and hand it to threads to
11018 		 * process.
11019 		 */
11020 		threads = g_ptr_array_new ();
11021 		/* Make a copy since acfg->methods is modified by compile_method () */
11022 		methods = g_new0 (MonoMethod*, methods_len);
11023 		//memcpy (methods, g_ptr_array_index (acfg->methods, 0), sizeof (MonoMethod*) * methods_len);
11024 		for (i = 0; i < methods_len; ++i)
11025 			methods [i] = (MonoMethod *)g_ptr_array_index (acfg->methods, i);
11026 		i = 0;
11027 		while (i < methods_len) {
11028 			MonoError error;
11029 			MonoInternalThread *thread;
11030 
11031 			frag = g_ptr_array_new ();
11032 			for (j = 0; j < len; ++j) {
11033 				if (i < methods_len) {
11034 					g_ptr_array_add (frag, methods [i]);
11035 					i ++;
11036 				}
11037 			}
11038 
11039 			user_data = g_new0 (gpointer, 3);
11040 			user_data [0] = acfg;
11041 			user_data [1] = frag;
11042 
11043 			thread = mono_thread_create_internal (mono_domain_get (), compile_thread_main, (gpointer) user_data, MONO_THREAD_CREATE_FLAGS_NONE, &error);
11044 			mono_error_assert_ok (&error);
11045 
11046 			thread_handle = mono_threads_open_thread_handle (thread->handle);
11047 			g_ptr_array_add (threads, thread_handle);
11048 		}
11049 		g_free (methods);
11050 
11051 		for (i = 0; i < threads->len; ++i) {
11052 			mono_thread_info_wait_one_handle (g_ptr_array_index (threads, i), MONO_INFINITE_WAIT, FALSE);
11053 			mono_threads_close_thread_handle (g_ptr_array_index (threads, i));
11054 		}
11055 	} else {
11056 		methods_len = 0;
11057 	}
11058 
11059 	/* Compile methods added by compile_method () or all methods if nthreads == 0 */
11060 	for (i = methods_len; i < acfg->methods->len; ++i) {
11061 		/* This can add new methods to acfg->methods */
11062 		compile_method (acfg, (MonoMethod *)g_ptr_array_index (acfg->methods, i));
11063 	}
11064 }
11065 
11066 static int
compile_asm(MonoAotCompile * acfg)11067 compile_asm (MonoAotCompile *acfg)
11068 {
11069 	char *command, *objfile;
11070 	char *outfile_name, *tmp_outfile_name, *llvm_ofile;
11071 	const char *tool_prefix = acfg->aot_opts.tool_prefix ? acfg->aot_opts.tool_prefix : "";
11072 	char *ld_flags = acfg->aot_opts.ld_flags ? acfg->aot_opts.ld_flags : g_strdup("");
11073 
11074 #ifdef TARGET_WIN32_MSVC
11075 #define AS_OPTIONS "-c -x assembler"
11076 #elif defined(TARGET_AMD64) && !defined(TARGET_MACH)
11077 #define AS_OPTIONS "--64"
11078 #elif defined(TARGET_POWERPC64)
11079 #define AS_OPTIONS "-a64 -mppc64"
11080 #elif defined(sparc) && SIZEOF_VOID_P == 8
11081 #define AS_OPTIONS "-xarch=v9"
11082 #elif defined(TARGET_X86) && defined(TARGET_MACH)
11083 #define AS_OPTIONS "-arch i386"
11084 #else
11085 #define AS_OPTIONS ""
11086 #endif
11087 
11088 #if defined(TARGET_OSX)
11089 #define AS_NAME "clang"
11090 #elif defined(TARGET_WIN32_MSVC)
11091 #define AS_NAME "clang.exe"
11092 #else
11093 #define AS_NAME "as"
11094 #endif
11095 
11096 #ifdef TARGET_WIN32_MSVC
11097 #define AS_OBJECT_FILE_SUFFIX "obj"
11098 #else
11099 #define AS_OBJECT_FILE_SUFFIX "o"
11100 #endif
11101 
11102 #if defined(sparc)
11103 #define LD_NAME "ld"
11104 #define LD_OPTIONS "-shared -G"
11105 #elif defined(__ppc__) && defined(TARGET_MACH)
11106 #define LD_NAME "gcc"
11107 #define LD_OPTIONS "-dynamiclib"
11108 #elif defined(TARGET_AMD64) && defined(TARGET_MACH)
11109 #define LD_NAME "clang"
11110 #define LD_OPTIONS "--shared"
11111 #elif defined(TARGET_WIN32_MSVC)
11112 #define LD_NAME "link.exe"
11113 #define LD_OPTIONS "/DLL /MACHINE:X64 /NOLOGO /INCREMENTAL:NO"
11114 #define LD_DEBUG_OPTIONS LD_OPTIONS " /DEBUG"
11115 #elif defined(TARGET_WIN32) && !defined(TARGET_ANDROID)
11116 #define LD_NAME "gcc"
11117 #define LD_OPTIONS "-shared"
11118 #elif defined(TARGET_X86) && defined(TARGET_MACH)
11119 #define LD_NAME "clang"
11120 #define LD_OPTIONS "-m32 -dynamiclib"
11121 #elif defined(TARGET_ARM) && !defined(TARGET_ANDROID)
11122 #define LD_NAME "gcc"
11123 #define LD_OPTIONS "--shared"
11124 #elif defined(TARGET_POWERPC64)
11125 #define LD_OPTIONS "-m elf64ppc"
11126 #endif
11127 
11128 #ifndef LD_OPTIONS
11129 #define LD_OPTIONS ""
11130 #endif
11131 
11132 	if (acfg->aot_opts.asm_only) {
11133 		aot_printf (acfg, "Output file: '%s'.\n", acfg->tmpfname);
11134 		if (acfg->aot_opts.static_link)
11135 			aot_printf (acfg, "Linking symbol: '%s'.\n", acfg->static_linking_symbol);
11136 		if (acfg->llvm)
11137 			aot_printf (acfg, "LLVM output file: '%s'.\n", acfg->llvm_sfile);
11138 		return 0;
11139 	}
11140 
11141 	if (acfg->aot_opts.static_link) {
11142 		if (acfg->aot_opts.outfile)
11143 			objfile = g_strdup_printf ("%s", acfg->aot_opts.outfile);
11144 		else
11145 			objfile = g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->image->name);
11146 	} else {
11147 		objfile = g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname);
11148 	}
11149 
11150 #ifdef TARGET_OSX
11151 	g_string_append (acfg->as_args, "-c -x assembler");
11152 #endif
11153 
11154 	command = g_strdup_printf ("\"%s%s\" %s %s -o %s %s", tool_prefix, AS_NAME, AS_OPTIONS,
11155 			acfg->as_args ? acfg->as_args->str : "",
11156 			wrap_path (objfile), wrap_path (acfg->tmpfname));
11157 	aot_printf (acfg, "Executing the native assembler: %s\n", command);
11158 	if (execute_system (command) != 0) {
11159 		g_free (command);
11160 		g_free (objfile);
11161 		return 1;
11162 	}
11163 
11164 	if (acfg->llvm && !acfg->llvm_owriter) {
11165 		command = g_strdup_printf ("\"%s%s\" %s %s -o %s %s", tool_prefix, AS_NAME, AS_OPTIONS,
11166 			acfg->as_args ? acfg->as_args->str : "",
11167 			wrap_path (acfg->llvm_ofile), wrap_path (acfg->llvm_sfile));
11168 		aot_printf (acfg, "Executing the native assembler: %s\n", command);
11169 		if (execute_system (command) != 0) {
11170 			g_free (command);
11171 			g_free (objfile);
11172 			return 1;
11173 		}
11174 	}
11175 
11176 	g_free (command);
11177 
11178 	if (acfg->aot_opts.static_link) {
11179 		aot_printf (acfg, "Output file: '%s'.\n", objfile);
11180 		aot_printf (acfg, "Linking symbol: '%s'.\n", acfg->static_linking_symbol);
11181 		g_free (objfile);
11182 		return 0;
11183 	}
11184 
11185 	if (acfg->aot_opts.outfile)
11186 		outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
11187 	else
11188 		outfile_name = g_strdup_printf ("%s%s", acfg->image->name, MONO_SOLIB_EXT);
11189 
11190 	tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
11191 
11192 	if (acfg->llvm) {
11193 		llvm_ofile = g_strdup_printf ("\"%s\"", acfg->llvm_ofile);
11194 	} else {
11195 		llvm_ofile = g_strdup ("");
11196 	}
11197 
11198 	/* replace the ; flags separators with spaces */
11199 	g_strdelimit (ld_flags, ";", ' ');
11200 
11201 	if (acfg->aot_opts.llvm_only)
11202 		ld_flags = g_strdup_printf ("%s %s", ld_flags, "-lstdc++");
11203 
11204 #ifdef TARGET_WIN32_MSVC
11205 	g_assert (tmp_outfile_name != NULL);
11206 	g_assert (objfile != NULL);
11207 	command = g_strdup_printf ("\"%s%s\" %s %s /OUT:\"%s\" \"%s\"", tool_prefix, LD_NAME,
11208 			acfg->aot_opts.nodebug ? LD_OPTIONS : LD_DEBUG_OPTIONS, ld_flags, tmp_outfile_name, objfile);
11209 #elif defined(LD_NAME)
11210 	command = g_strdup_printf ("%s%s %s -o %s %s %s %s", tool_prefix, LD_NAME, LD_OPTIONS,
11211 		wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
11212 		wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname)), ld_flags);
11213 #else
11214 	// Default (linux)
11215 	if (acfg->aot_opts.tool_prefix) {
11216 		/* Cross compiling */
11217 		command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS,
11218 								   wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
11219 								   wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname)), ld_flags);
11220 	} else {
11221 		char *args = g_strdup_printf ("%s -shared -o %s %s %s %s", LD_OPTIONS,
11222 									  wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
11223 									  wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname)), ld_flags);
11224 
11225 		if (acfg->aot_opts.llvm_only) {
11226 			command = g_strdup_printf ("clang++ %s", args);
11227 		} else {
11228 			command = g_strdup_printf ("\"%sld\" %s", tool_prefix, args);
11229 		}
11230 		g_free (args);
11231 	}
11232 #endif
11233 	aot_printf (acfg, "Executing the native linker: %s\n", command);
11234 	if (execute_system (command) != 0) {
11235 		g_free (tmp_outfile_name);
11236 		g_free (outfile_name);
11237 		g_free (command);
11238 		g_free (objfile);
11239 		g_free (ld_flags);
11240 		return 1;
11241 	}
11242 
11243 	g_free (command);
11244 
11245 	/*com = g_strdup_printf ("strip --strip-unneeded %s%s", acfg->image->name, MONO_SOLIB_EXT);
11246 	printf ("Stripping the binary: %s\n", com);
11247 	execute_system (com);
11248 	g_free (com);*/
11249 
11250 #if defined(TARGET_ARM) && !defined(TARGET_MACH)
11251 	/*
11252 	 * gas generates 'mapping symbols' each time code and data is mixed, which
11253 	 * happens a lot in emit_and_reloc_code (), so we need to get rid of them.
11254 	 */
11255 	command = g_strdup_printf ("\"%sstrip\" --strip-symbol=\\$a --strip-symbol=\\$d %s", wrap_path(tool_prefix), wrap_path(tmp_outfile_name));
11256 	aot_printf (acfg, "Stripping the binary: %s\n", command);
11257 	if (execute_system (command) != 0) {
11258 		g_free (tmp_outfile_name);
11259 		g_free (outfile_name);
11260 		g_free (command);
11261 		g_free (objfile);
11262 		return 1;
11263 	}
11264 #endif
11265 
11266 	if (0 != rename (tmp_outfile_name, outfile_name)) {
11267 		if (G_FILE_ERROR_EXIST == g_file_error_from_errno (errno)) {
11268 			/* Since we are rebuilding the module we need to be able to replace any old copies. Remove old file and retry rename operation. */
11269 			unlink (outfile_name);
11270 			rename (tmp_outfile_name, outfile_name);
11271 		}
11272 	}
11273 
11274 #if defined(TARGET_MACH)
11275 	command = g_strdup_printf ("dsymutil \"%s\"", outfile_name);
11276 	aot_printf (acfg, "Executing dsymutil: %s\n", command);
11277 	if (execute_system (command) != 0) {
11278 		return 1;
11279 	}
11280 #endif
11281 
11282 	if (!acfg->aot_opts.save_temps)
11283 		unlink (objfile);
11284 
11285 	g_free (tmp_outfile_name);
11286 	g_free (outfile_name);
11287 	g_free (objfile);
11288 
11289 	if (acfg->aot_opts.save_temps)
11290 		aot_printf (acfg, "Retained input file.\n");
11291 	else
11292 		unlink (acfg->tmpfname);
11293 
11294 	return 0;
11295 }
11296 
11297 static guint8
profread_byte(FILE * infile)11298 profread_byte (FILE *infile)
11299 {
11300 	guint8 i;
11301 	int res;
11302 
11303 	res = fread (&i, 1, 1, infile);
11304 	g_assert (res == 1);
11305 	return i;
11306 }
11307 
11308 static int
profread_int(FILE * infile)11309 profread_int (FILE *infile)
11310 {
11311 	int i, res;
11312 
11313 	res = fread (&i, 4, 1, infile);
11314 	g_assert (res == 1);
11315 	return i;
11316 }
11317 
11318 static char*
profread_string(FILE * infile)11319 profread_string (FILE *infile)
11320 {
11321 	int len, res;
11322 	char buf [1024];
11323 	char *pbuf;
11324 
11325 	len = profread_int (infile);
11326 	if (len + 1 > 1024)
11327 		pbuf = g_malloc (len + 1);
11328 	else
11329 		pbuf = buf;
11330 	res = fread (pbuf, 1, len, infile);
11331 	g_assert (res == len);
11332 	pbuf [len] = '\0';
11333 	if (pbuf == buf)
11334 		return g_strdup (buf);
11335 	else
11336 		return pbuf;
11337 }
11338 
11339 static void
load_profile_file(MonoAotCompile * acfg,char * filename)11340 load_profile_file (MonoAotCompile *acfg, char *filename)
11341 {
11342 	FILE *infile;
11343 	char buf [1024];
11344 	int res, len, version;
11345 	char magic [32];
11346 
11347 	infile = fopen (filename, "r");
11348 	if (!infile) {
11349 		fprintf (stderr, "Unable to open file '%s': %s.\n", filename, strerror (errno));
11350 		exit (1);
11351 	}
11352 
11353 	printf ("Using profile data file '%s'\n", filename);
11354 
11355 	sprintf (magic, AOT_PROFILER_MAGIC);
11356 	len = strlen (magic);
11357 	res = fread (buf, 1, len, infile);
11358 	magic [len] = '\0';
11359 	buf [len] = '\0';
11360 	if ((res != len) || strcmp (buf, magic) != 0) {
11361 		printf ("Profile file has wrong header: '%s'.\n", buf);
11362 		fclose (infile);
11363 		exit (1);
11364 	}
11365 	guint32 expected_version = (AOT_PROFILER_MAJOR_VERSION << 16) | AOT_PROFILER_MINOR_VERSION;
11366 	version = profread_int (infile);
11367 	if (version != expected_version) {
11368 		printf ("Profile file has wrong version 0x%4x, expected 0x%4x.\n", version, expected_version);
11369 		fclose (infile);
11370 		exit (1);
11371 	}
11372 
11373 	ProfileData *data = g_new0 (ProfileData, 1);
11374 	data->images = g_hash_table_new (NULL, NULL);
11375 	data->classes = g_hash_table_new (NULL, NULL);
11376 	data->ginsts = g_hash_table_new (NULL, NULL);
11377 	data->methods = g_hash_table_new (NULL, NULL);
11378 
11379 	while (TRUE) {
11380 		int type = profread_byte (infile);
11381 		int id = profread_int (infile);
11382 
11383 		if (type == AOTPROF_RECORD_NONE)
11384 			break;
11385 
11386 		switch (type) {
11387 		case AOTPROF_RECORD_IMAGE: {
11388 			ImageProfileData *idata = g_new0 (ImageProfileData, 1);
11389 			idata->name = profread_string (infile);
11390 			char *mvid = profread_string (infile);
11391 			g_free (mvid);
11392 			g_hash_table_insert (data->images, GINT_TO_POINTER (id), idata);
11393 			break;
11394 		}
11395 		case AOTPROF_RECORD_GINST: {
11396 			int i;
11397 			int len = profread_int (infile);
11398 
11399 			GInstProfileData *gdata = g_new0 (GInstProfileData, 1);
11400 			gdata->argc = len;
11401 			gdata->argv = g_new0 (ClassProfileData*, len);
11402 
11403 			for (i = 0; i < len; ++i) {
11404 				int class_id = profread_int (infile);
11405 
11406 				gdata->argv [i] = g_hash_table_lookup (data->classes, GINT_TO_POINTER (class_id));
11407 				g_assert (gdata->argv [i]);
11408 			}
11409 			g_hash_table_insert (data->ginsts, GINT_TO_POINTER (id), gdata);
11410 			break;
11411 		}
11412 		case AOTPROF_RECORD_TYPE: {
11413 			int type = profread_byte (infile);
11414 
11415 			switch (type) {
11416 			case MONO_TYPE_CLASS: {
11417 				int image_id = profread_int (infile);
11418 				int ginst_id = profread_int (infile);
11419 				char *class_name = profread_string (infile);
11420 
11421 				ImageProfileData *image = g_hash_table_lookup (data->images, GINT_TO_POINTER (image_id));
11422 				g_assert (image);
11423 
11424 				char *p = strrchr (class_name, '.');
11425 				g_assert (p);
11426 				*p = '\0';
11427 
11428 				ClassProfileData *cdata = g_new0 (ClassProfileData, 1);
11429 				cdata->image = image;
11430 				cdata->ns = g_strdup (class_name);
11431 				cdata->name = g_strdup (p + 1);
11432 
11433 				if (ginst_id != -1) {
11434 					cdata->inst = g_hash_table_lookup (data->ginsts, GINT_TO_POINTER (ginst_id));
11435 					g_assert (cdata->inst);
11436 				}
11437 				g_free (class_name);
11438 
11439 				g_hash_table_insert (data->classes, GINT_TO_POINTER (id), cdata);
11440 				break;
11441 			}
11442 #if 0
11443 			case MONO_TYPE_SZARRAY: {
11444 				int elem_id = profread_int (infile);
11445 				// FIXME:
11446 				break;
11447 			}
11448 #endif
11449 			default:
11450 				g_assert_not_reached ();
11451 				break;
11452 			}
11453 			break;
11454 		}
11455 		case AOTPROF_RECORD_METHOD: {
11456 			int class_id = profread_int (infile);
11457 			int ginst_id = profread_int (infile);
11458 			int param_count = profread_int (infile);
11459 			char *method_name = profread_string (infile);
11460 			char *sig = profread_string (infile);
11461 
11462 			ClassProfileData *klass = g_hash_table_lookup (data->classes, GINT_TO_POINTER (class_id));
11463 			g_assert (klass);
11464 
11465 			MethodProfileData *mdata = g_new0 (MethodProfileData, 1);
11466 			mdata->id = id;
11467 			mdata->klass = klass;
11468 			mdata->name = method_name;
11469 			mdata->signature = sig;
11470 			mdata->param_count = param_count;
11471 
11472 			if (ginst_id != -1) {
11473 				mdata->inst = g_hash_table_lookup (data->ginsts, GINT_TO_POINTER (ginst_id));
11474 				g_assert (mdata->inst);
11475 			}
11476 			g_hash_table_insert (data->methods, GINT_TO_POINTER (id), mdata);
11477 			break;
11478 		}
11479 		default:
11480 			printf ("%d\n", type);
11481 			g_assert_not_reached ();
11482 			break;
11483 		}
11484 	}
11485 
11486 	fclose (infile);
11487 	acfg->profile_data = g_list_append (acfg->profile_data, data);
11488 }
11489 
11490 static void
11491 resolve_class (ClassProfileData *cdata);
11492 
11493 static void
resolve_ginst(GInstProfileData * inst_data)11494 resolve_ginst (GInstProfileData *inst_data)
11495 {
11496 	int i;
11497 
11498 	if (inst_data->inst)
11499 		return;
11500 
11501 	for (i = 0; i < inst_data->argc; ++i) {
11502 		resolve_class (inst_data->argv [i]);
11503 		if (!inst_data->argv [i]->klass)
11504 			return;
11505 	}
11506 	MonoType **args = g_new0 (MonoType*, inst_data->argc);
11507 	for (i = 0; i < inst_data->argc; ++i)
11508 		args [i] = &inst_data->argv [i]->klass->byval_arg;
11509 
11510 	inst_data->inst = mono_metadata_get_generic_inst (inst_data->argc, args);
11511 }
11512 
11513 static void
resolve_class(ClassProfileData * cdata)11514 resolve_class (ClassProfileData *cdata)
11515 {
11516 	MonoError error;
11517 	MonoClass *klass;
11518 
11519 	if (!cdata->image->image)
11520 		return;
11521 
11522 	klass = mono_class_from_name_checked (cdata->image->image, cdata->ns, cdata->name, &error);
11523 	if (!klass) {
11524 		//printf ("[%s] %s.%s\n", cdata->image->name, cdata->ns, cdata->name);
11525 		return;
11526 	}
11527 	if (cdata->inst) {
11528 		resolve_ginst (cdata->inst);
11529 		if (!cdata->inst->inst)
11530 			return;
11531 		MonoGenericContext ctx;
11532 
11533 		memset (&ctx, 0, sizeof (ctx));
11534 		ctx.class_inst = cdata->inst->inst;
11535 		cdata->klass = mono_class_inflate_generic_class_checked (klass, &ctx, &error);
11536 	} else {
11537 		cdata->klass = klass;
11538 	}
11539 }
11540 
11541 /*
11542  * Resolve the profile data to the corresponding loaded classes/methods etc. if possible.
11543  */
11544 static void
resolve_profile_data(MonoAotCompile * acfg,ProfileData * data)11545 resolve_profile_data (MonoAotCompile *acfg, ProfileData *data)
11546 {
11547 	GHashTableIter iter;
11548 	gpointer key, value;
11549 	int i;
11550 
11551 	if (!data)
11552 		return;
11553 
11554 	/* Images */
11555 	GPtrArray *assemblies = mono_domain_get_assemblies (mono_get_root_domain (), FALSE);
11556 	g_hash_table_iter_init (&iter, data->images);
11557 	while (g_hash_table_iter_next (&iter, &key, &value)) {
11558 		ImageProfileData *idata = (ImageProfileData*)value;
11559 
11560 		for (i = 0; i < assemblies->len; ++i) {
11561 			MonoAssembly *ass = g_ptr_array_index (assemblies, i);
11562 
11563 			if (!strcmp (ass->aname.name, idata->name)) {
11564 				idata->image = ass->image;
11565 				break;
11566 			}
11567 		}
11568 	}
11569 	g_ptr_array_free (assemblies, TRUE);
11570 
11571 	/* Classes */
11572 	g_hash_table_iter_init (&iter, data->classes);
11573 	while (g_hash_table_iter_next (&iter, &key, &value)) {
11574 		ClassProfileData *cdata = (ClassProfileData*)value;
11575 
11576 		if (!cdata->image->image) {
11577 			if (acfg->aot_opts.verbose)
11578 				printf ("Unable to load class '%s.%s' because its image '%s' is not loaded.\n", cdata->ns, cdata->name, cdata->image->name);
11579 			continue;
11580 		}
11581 
11582 		resolve_class (cdata);
11583 		/*
11584 		if (cdata->klass)
11585 			printf ("%s %s %s\n", cdata->ns, cdata->name, mono_class_full_name (cdata->klass));
11586 		*/
11587 	}
11588 
11589 	/* Methods */
11590 	g_hash_table_iter_init (&iter, data->methods);
11591 	while (g_hash_table_iter_next (&iter, &key, &value)) {
11592 		MethodProfileData *mdata = (MethodProfileData*)value;
11593 		MonoClass *klass;
11594 		MonoMethod *m;
11595 		gpointer miter;
11596 
11597 		resolve_class (mdata->klass);
11598 		klass = mdata->klass->klass;
11599 		if (!klass) {
11600 			if (acfg->aot_opts.verbose)
11601 				printf ("Unable to load method '%s' because its class '%s.%s' is not loaded.\n", mdata->name, mdata->klass->ns, mdata->klass->name);
11602 			continue;
11603 		}
11604 		miter = NULL;
11605 		while ((m = mono_class_get_methods (klass, &miter))) {
11606 			MonoError error;
11607 
11608 			if (strcmp (m->name, mdata->name))
11609 				continue;
11610 			MonoMethodSignature *sig = mono_method_signature (m);
11611 			if (!sig)
11612 				continue;
11613 			if (sig->param_count != mdata->param_count)
11614 				continue;
11615 			if (mdata->inst) {
11616 				resolve_ginst (mdata->inst);
11617 				if (!mdata->inst->inst)
11618 					continue;
11619 				MonoGenericContext ctx;
11620 
11621 				memset (&ctx, 0, sizeof (ctx));
11622 				ctx.method_inst = mdata->inst->inst;
11623 
11624 				m = mono_class_inflate_generic_method_checked (m, &ctx, &error);
11625 				if (!m)
11626 					continue;
11627 				sig = mono_method_signature_checked (m, &error);
11628 				if (!is_ok (&error)) {
11629 					mono_error_cleanup (&error);
11630 					continue;
11631 				}
11632 			}
11633 			char *sig_str = mono_signature_full_name (sig);
11634 			gboolean match = !strcmp (sig_str, mdata->signature);
11635 			g_free (sig_str);
11636 			if (!match)
11637 
11638 				continue;
11639 			//printf ("%s\n", mono_method_full_name (m, 1));
11640 			mdata->method = m;
11641 			break;
11642 		}
11643 		if (!mdata->method) {
11644 			if (acfg->aot_opts.verbose)
11645 				printf ("Unable to load method '%s' from class '%s', not found.\n", mdata->name, mono_class_full_name (klass));
11646 		}
11647 	}
11648 }
11649 
11650 static gboolean
inst_references_image(MonoGenericInst * inst,MonoImage * image)11651 inst_references_image (MonoGenericInst *inst, MonoImage *image)
11652 {
11653 	int i;
11654 
11655 	for (i = 0; i < inst->type_argc; ++i) {
11656 		MonoClass *k = mono_class_from_mono_type (inst->type_argv [i]);
11657 		if (k->image == image)
11658 			return TRUE;
11659 		if (mono_class_is_ginst (k)) {
11660 			MonoGenericInst *kinst = mono_class_get_context (k)->class_inst;
11661 			if (inst_references_image (kinst, image))
11662 				return TRUE;
11663 		}
11664 	}
11665 	return FALSE;
11666 }
11667 
11668 static gboolean
is_local_inst(MonoGenericInst * inst,MonoImage * image)11669 is_local_inst (MonoGenericInst *inst, MonoImage *image)
11670 {
11671 	int i;
11672 
11673 	for (i = 0; i < inst->type_argc; ++i) {
11674 		MonoClass *k = mono_class_from_mono_type (inst->type_argv [i]);
11675 		if (!MONO_TYPE_IS_PRIMITIVE (inst->type_argv [i]) && k->image != image)
11676 			return FALSE;
11677 	}
11678 	return TRUE;
11679 }
11680 
11681 static void
add_profile_instances(MonoAotCompile * acfg,ProfileData * data)11682 add_profile_instances (MonoAotCompile *acfg, ProfileData *data)
11683 {
11684 	GHashTableIter iter;
11685 	gpointer key, value;
11686 	int count = 0;
11687 
11688 	if (!data)
11689 		return;
11690 
11691 	if (acfg->aot_opts.profile_only) {
11692 		/* Add methods referenced by the profile */
11693 		g_hash_table_iter_init (&iter, data->methods);
11694 		while (g_hash_table_iter_next (&iter, &key, &value)) {
11695 			MethodProfileData *mdata = (MethodProfileData*)value;
11696 			MonoMethod *m = mdata->method;
11697 
11698 			if (!m)
11699 				continue;
11700 			if (m->is_inflated)
11701 				continue;
11702 			add_extra_method (acfg, m);
11703 			g_hash_table_insert (acfg->profile_methods, m, m);
11704 			count ++;
11705 		}
11706 	}
11707 
11708 	/*
11709 	 * Add method instances 'related' to this assembly to the AOT image.
11710 	 */
11711 	g_hash_table_iter_init (&iter, data->methods);
11712 	while (g_hash_table_iter_next (&iter, &key, &value)) {
11713 		MethodProfileData *mdata = (MethodProfileData*)value;
11714 		MonoMethod *m = mdata->method;
11715 		MonoGenericContext *ctx;
11716 
11717 		if (!m)
11718 			continue;
11719 		if (!m->is_inflated)
11720 			continue;
11721 
11722 		ctx = mono_method_get_context (m);
11723 		/* For simplicity, add instances which reference the assembly we are compiling */
11724 		if (((ctx->class_inst && inst_references_image (ctx->class_inst, acfg->image)) ||
11725 			 (ctx->method_inst && inst_references_image (ctx->method_inst, acfg->image))) &&
11726 			!mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE)) {
11727 			//printf ("%s\n", mono_method_full_name (m, TRUE));
11728 			add_extra_method (acfg, m);
11729 			count ++;
11730 		} else if (m->klass->image == acfg->image &&
11731 			((ctx->class_inst && is_local_inst (ctx->class_inst, acfg->image)) ||
11732 			 (ctx->method_inst && is_local_inst (ctx->method_inst, acfg->image))) &&
11733 			!mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE))  {
11734 			/* Add instances where the gtd is in the assembly and its inflated with types from this assembly or corlib */
11735 			//printf ("%s\n", mono_method_full_name (m, TRUE));
11736 			add_extra_method (acfg, m);
11737 			count ++;
11738 		}
11739 		/*
11740 		 * FIXME: We might skip some instances, for example:
11741 		 * Foo<Bar> won't be compiled when compiling Foo's assembly since it doesn't match the first case,
11742 		 * and it won't be compiled when compiling Bar's assembly if Foo's assembly is not loaded.
11743 		 */
11744 	}
11745 
11746 	printf ("Added %d methods from profile.\n", count);
11747 }
11748 
11749 static void
init_got_info(GotInfo * info)11750 init_got_info (GotInfo *info)
11751 {
11752 	int i;
11753 
11754 	info->patch_to_got_offset = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
11755 	info->patch_to_got_offset_by_type = g_new0 (GHashTable*, MONO_PATCH_INFO_NUM);
11756 	for (i = 0; i < MONO_PATCH_INFO_NUM; ++i)
11757 		info->patch_to_got_offset_by_type [i] = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
11758 	info->got_patches = g_ptr_array_new ();
11759 }
11760 
11761 static MonoAotCompile*
acfg_create(MonoAssembly * ass,guint32 opts)11762 acfg_create (MonoAssembly *ass, guint32 opts)
11763 {
11764 	MonoImage *image = ass->image;
11765 	MonoAotCompile *acfg;
11766 
11767 	acfg = g_new0 (MonoAotCompile, 1);
11768 	acfg->methods = g_ptr_array_new ();
11769 	acfg->method_indexes = g_hash_table_new (NULL, NULL);
11770 	acfg->method_depth = g_hash_table_new (NULL, NULL);
11771 	acfg->plt_offset_to_entry = g_hash_table_new (NULL, NULL);
11772 	acfg->patch_to_plt_entry = g_new0 (GHashTable*, MONO_PATCH_INFO_NUM);
11773 	acfg->method_to_cfg = g_hash_table_new (NULL, NULL);
11774 	acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, NULL);
11775 	acfg->method_to_pinvoke_import = g_hash_table_new_full (NULL, NULL, NULL, g_free);
11776 	acfg->image_hash = g_hash_table_new (NULL, NULL);
11777 	acfg->image_table = g_ptr_array_new ();
11778 	acfg->globals = g_ptr_array_new ();
11779 	acfg->image = image;
11780 	acfg->opts = opts;
11781 	/* TODO: Write out set of SIMD instructions used, rather than just those available */
11782 	acfg->simd_opts = mono_arch_cpu_enumerate_simd_versions ();
11783 	acfg->mempool = mono_mempool_new ();
11784 	acfg->extra_methods = g_ptr_array_new ();
11785 	acfg->unwind_info_offsets = g_hash_table_new (NULL, NULL);
11786 	acfg->unwind_ops = g_ptr_array_new ();
11787 	acfg->method_label_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
11788 	acfg->method_order = g_ptr_array_new ();
11789 	acfg->export_names = g_hash_table_new (NULL, NULL);
11790 	acfg->klass_blob_hash = g_hash_table_new (NULL, NULL);
11791 	acfg->method_blob_hash = g_hash_table_new (NULL, NULL);
11792 	acfg->plt_entry_debug_sym_cache = g_hash_table_new (g_str_hash, g_str_equal);
11793 	acfg->gsharedvt_in_signatures = g_hash_table_new ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal);
11794 	acfg->gsharedvt_out_signatures = g_hash_table_new ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal);
11795 	acfg->profile_methods = g_hash_table_new (NULL, NULL);
11796 	mono_os_mutex_init_recursive (&acfg->mutex);
11797 
11798 	init_got_info (&acfg->got_info);
11799 	init_got_info (&acfg->llvm_got_info);
11800 
11801 	return acfg;
11802 }
11803 
11804 static void
got_info_free(GotInfo * info)11805 got_info_free (GotInfo *info)
11806 {
11807 	int i;
11808 
11809 	for (i = 0; i < MONO_PATCH_INFO_NUM; ++i)
11810 		g_hash_table_destroy (info->patch_to_got_offset_by_type [i]);
11811 	g_free (info->patch_to_got_offset_by_type);
11812 	g_hash_table_destroy (info->patch_to_got_offset);
11813 	g_ptr_array_free (info->got_patches, TRUE);
11814 }
11815 
11816 static void
acfg_free(MonoAotCompile * acfg)11817 acfg_free (MonoAotCompile *acfg)
11818 {
11819 	int i;
11820 
11821 	mono_img_writer_destroy (acfg->w);
11822 	for (i = 0; i < acfg->nmethods; ++i)
11823 		if (acfg->cfgs [i])
11824 			mono_destroy_compile (acfg->cfgs [i]);
11825 
11826 	g_free (acfg->cfgs);
11827 
11828 	g_free (acfg->static_linking_symbol);
11829 	g_free (acfg->got_symbol);
11830 	g_free (acfg->plt_symbol);
11831 	g_ptr_array_free (acfg->methods, TRUE);
11832 	g_ptr_array_free (acfg->image_table, TRUE);
11833 	g_ptr_array_free (acfg->globals, TRUE);
11834 	g_ptr_array_free (acfg->unwind_ops, TRUE);
11835 	g_hash_table_destroy (acfg->method_indexes);
11836 	g_hash_table_destroy (acfg->method_depth);
11837 	g_hash_table_destroy (acfg->plt_offset_to_entry);
11838 	for (i = 0; i < MONO_PATCH_INFO_NUM; ++i) {
11839 		if (acfg->patch_to_plt_entry [i])
11840 			g_hash_table_destroy (acfg->patch_to_plt_entry [i]);
11841 	}
11842 	g_free (acfg->patch_to_plt_entry);
11843 	g_hash_table_destroy (acfg->method_to_cfg);
11844 	g_hash_table_destroy (acfg->token_info_hash);
11845 	g_hash_table_destroy (acfg->method_to_pinvoke_import);
11846 	g_hash_table_destroy (acfg->image_hash);
11847 	g_hash_table_destroy (acfg->unwind_info_offsets);
11848 	g_hash_table_destroy (acfg->method_label_hash);
11849 	if (acfg->typespec_classes)
11850 		g_hash_table_destroy (acfg->typespec_classes);
11851 	g_hash_table_destroy (acfg->export_names);
11852 	g_hash_table_destroy (acfg->plt_entry_debug_sym_cache);
11853 	g_hash_table_destroy (acfg->klass_blob_hash);
11854 	g_hash_table_destroy (acfg->method_blob_hash);
11855 	got_info_free (&acfg->got_info);
11856 	got_info_free (&acfg->llvm_got_info);
11857 	arch_free_unwind_info_section_cache (acfg);
11858 	mono_mempool_destroy (acfg->mempool);
11859 	g_free (acfg);
11860 }
11861 
11862 #define WRAPPER(e,n) n,
11863 static const char* const
11864 wrapper_type_names [MONO_WRAPPER_NUM + 1] = {
11865 #include "mono/metadata/wrapper-types.h"
11866 	NULL
11867 };
11868 
11869 static G_GNUC_UNUSED const char*
get_wrapper_type_name(int type)11870 get_wrapper_type_name (int type)
11871 {
11872 	return wrapper_type_names [type];
11873 }
11874 
11875 //#define DUMP_PLT
11876 //#define DUMP_GOT
11877 
aot_dump(MonoAotCompile * acfg)11878 static void aot_dump (MonoAotCompile *acfg)
11879 {
11880 	FILE *dumpfile;
11881 	char * dumpname;
11882 
11883 	JsonWriter writer;
11884 	mono_json_writer_init (&writer);
11885 
11886 	mono_json_writer_object_begin(&writer);
11887 
11888 	// Methods
11889 	mono_json_writer_indent (&writer);
11890 	mono_json_writer_object_key(&writer, "methods");
11891 	mono_json_writer_array_begin (&writer);
11892 
11893 	int i;
11894 	for (i = 0; i < acfg->nmethods; ++i) {
11895 		MonoCompile *cfg;
11896 		MonoMethod *method;
11897 		MonoClass *klass;
11898 
11899 		cfg = acfg->cfgs [i];
11900 		if (ignore_cfg (cfg))
11901 			continue;
11902 
11903 		method = cfg->orig_method;
11904 
11905 		mono_json_writer_indent (&writer);
11906 		mono_json_writer_object_begin(&writer);
11907 
11908 		mono_json_writer_indent (&writer);
11909 		mono_json_writer_object_key(&writer, "name");
11910 		mono_json_writer_printf (&writer, "\"%s\",\n", method->name);
11911 
11912 		mono_json_writer_indent (&writer);
11913 		mono_json_writer_object_key(&writer, "signature");
11914 		mono_json_writer_printf (&writer, "\"%s\",\n", mono_method_get_full_name (method));
11915 
11916 		mono_json_writer_indent (&writer);
11917 		mono_json_writer_object_key(&writer, "code_size");
11918 		mono_json_writer_printf (&writer, "\"%d\",\n", cfg->code_size);
11919 
11920 		klass = method->klass;
11921 
11922 		mono_json_writer_indent (&writer);
11923 		mono_json_writer_object_key(&writer, "class");
11924 		mono_json_writer_printf (&writer, "\"%s\",\n", klass->name);
11925 
11926 		mono_json_writer_indent (&writer);
11927 		mono_json_writer_object_key(&writer, "namespace");
11928 		mono_json_writer_printf (&writer, "\"%s\",\n", klass->name_space);
11929 
11930 		mono_json_writer_indent (&writer);
11931 		mono_json_writer_object_key(&writer, "wrapper_type");
11932 		mono_json_writer_printf (&writer, "\"%s\",\n", get_wrapper_type_name(method->wrapper_type));
11933 
11934 		mono_json_writer_indent_pop (&writer);
11935 		mono_json_writer_indent (&writer);
11936 		mono_json_writer_object_end (&writer);
11937 		mono_json_writer_printf (&writer, ",\n");
11938 	}
11939 
11940 	mono_json_writer_indent_pop (&writer);
11941 	mono_json_writer_indent (&writer);
11942 	mono_json_writer_array_end (&writer);
11943 	mono_json_writer_printf (&writer, ",\n");
11944 
11945 	// PLT entries
11946 #ifdef DUMP_PLT
11947 	mono_json_writer_indent_push (&writer);
11948 	mono_json_writer_indent (&writer);
11949 	mono_json_writer_object_key(&writer, "plt");
11950 	mono_json_writer_array_begin (&writer);
11951 
11952 	for (i = 0; i < acfg->plt_offset; ++i) {
11953 		MonoPltEntry *plt_entry = NULL;
11954 		MonoJumpInfo *ji;
11955 
11956 		if (i == 0)
11957 			/*
11958 			 * The first plt entry is unused.
11959 			 */
11960 			continue;
11961 
11962 		plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
11963 		ji = plt_entry->ji;
11964 
11965 		mono_json_writer_indent (&writer);
11966 		mono_json_writer_printf (&writer, "{ ");
11967 		mono_json_writer_object_key(&writer, "symbol");
11968 		mono_json_writer_printf (&writer, "\"%s\" },\n", plt_entry->symbol);
11969 	}
11970 
11971 	mono_json_writer_indent_pop (&writer);
11972 	mono_json_writer_indent (&writer);
11973 	mono_json_writer_array_end (&writer);
11974 	mono_json_writer_printf (&writer, ",\n");
11975 #endif
11976 
11977 	// GOT entries
11978 #ifdef DUMP_GOT
11979 	mono_json_writer_indent_push (&writer);
11980 	mono_json_writer_indent (&writer);
11981 	mono_json_writer_object_key(&writer, "got");
11982 	mono_json_writer_array_begin (&writer);
11983 
11984 	mono_json_writer_indent_push (&writer);
11985 	for (i = 0; i < acfg->got_info.got_patches->len; ++i) {
11986 		MonoJumpInfo *ji = g_ptr_array_index (acfg->got_info.got_patches, i);
11987 
11988 		mono_json_writer_indent (&writer);
11989 		mono_json_writer_printf (&writer, "{ ");
11990 		mono_json_writer_object_key(&writer, "patch_name");
11991 		mono_json_writer_printf (&writer, "\"%s\" },\n", get_patch_name (ji->type));
11992 	}
11993 
11994 	mono_json_writer_indent_pop (&writer);
11995 	mono_json_writer_indent (&writer);
11996 	mono_json_writer_array_end (&writer);
11997 	mono_json_writer_printf (&writer, ",\n");
11998 #endif
11999 
12000 	mono_json_writer_indent_pop (&writer);
12001 	mono_json_writer_indent (&writer);
12002 	mono_json_writer_object_end (&writer);
12003 
12004 	dumpname = g_strdup_printf ("%s.json", g_path_get_basename (acfg->image->name));
12005 	dumpfile = fopen (dumpname, "w+");
12006 	g_free (dumpname);
12007 
12008 	fprintf (dumpfile, "%s", writer.text->str);
12009 	fclose (dumpfile);
12010 
12011 	mono_json_writer_destroy (&writer);
12012 }
12013 
12014 static const char *preinited_jit_icalls[] = {
12015 	"mono_aot_init_llvm_method",
12016 	"mono_aot_init_gshared_method_this",
12017 	"mono_aot_init_gshared_method_mrgctx",
12018 	"mono_aot_init_gshared_method_vtable",
12019 	"mono_llvm_throw_corlib_exception",
12020 	"mono_init_vtable_slot",
12021 	"mono_helper_ldstr_mscorlib"
12022 };
12023 
12024 static void
add_preinit_got_slots(MonoAotCompile * acfg)12025 add_preinit_got_slots (MonoAotCompile *acfg)
12026 {
12027 	MonoJumpInfo *ji;
12028 	int i;
12029 
12030 	/*
12031 	 * Allocate the first few GOT entries to information which is needed frequently, or it is needed
12032 	 * during method initialization etc.
12033 	 */
12034 
12035 	ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
12036 	ji->type = MONO_PATCH_INFO_IMAGE;
12037 	ji->data.image = acfg->image;
12038 	get_got_offset (acfg, FALSE, ji);
12039 	get_got_offset (acfg, TRUE, ji);
12040 
12041 	ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
12042 	ji->type = MONO_PATCH_INFO_MSCORLIB_GOT_ADDR;
12043 	get_got_offset (acfg, FALSE, ji);
12044 	get_got_offset (acfg, TRUE, ji);
12045 
12046 	ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
12047 	ji->type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
12048 	get_got_offset (acfg, FALSE, ji);
12049 	get_got_offset (acfg, TRUE, ji);
12050 
12051 	ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
12052 	ji->type = MONO_PATCH_INFO_GC_NURSERY_START;
12053 	get_got_offset (acfg, FALSE, ji);
12054 	get_got_offset (acfg, TRUE, ji);
12055 
12056 	ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
12057 	ji->type = MONO_PATCH_INFO_AOT_MODULE;
12058 	get_got_offset (acfg, FALSE, ji);
12059 	get_got_offset (acfg, TRUE, ji);
12060 
12061 	ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
12062 	ji->type = MONO_PATCH_INFO_GC_NURSERY_BITS;
12063 	get_got_offset (acfg, FALSE, ji);
12064 	get_got_offset (acfg, TRUE, ji);
12065 
12066 	for (i = 0; i < TLS_KEY_NUM; i++) {
12067 		ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
12068 		ji->type = MONO_PATCH_INFO_GET_TLS_TRAMP;
12069 		ji->data.index = i;
12070 		get_got_offset (acfg, FALSE, ji);
12071 		get_got_offset (acfg, TRUE, ji);
12072 
12073 		ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
12074 		ji->type = MONO_PATCH_INFO_SET_TLS_TRAMP;
12075 		ji->data.index = i;
12076 		get_got_offset (acfg, FALSE, ji);
12077 		get_got_offset (acfg, TRUE, ji);
12078 	}
12079 
12080 	ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
12081 	ji->type = MONO_PATCH_INFO_JIT_THREAD_ATTACH;
12082 	get_got_offset (acfg, FALSE, ji);
12083 	get_got_offset (acfg, TRUE, ji);
12084 
12085 	/* Called by native-to-managed wrappers on possibly unattached threads */
12086 	ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
12087 	ji->type = MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL;
12088 	ji->data.name = "mono_threads_attach_coop";
12089 	get_got_offset (acfg, FALSE, ji);
12090 	get_got_offset (acfg, TRUE, ji);
12091 
12092 	for (i = 0; i < sizeof (preinited_jit_icalls) / sizeof (char*); ++i) {
12093 		ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
12094 		ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
12095 		ji->data.name = preinited_jit_icalls [i];
12096 		get_got_offset (acfg, FALSE, ji);
12097 		get_got_offset (acfg, TRUE, ji);
12098 	}
12099 
12100 	acfg->nshared_got_entries = acfg->got_offset;
12101 }
12102 
12103 static void
mono_dedup_log_stats(MonoAotCompile * acfg)12104 mono_dedup_log_stats (MonoAotCompile *acfg)
12105 {
12106 	GHashTableIter iter;
12107 	g_assert (acfg->dedup_stats);
12108 
12109 	// If dedup_emit_mode, acfg is the dummy dedup module that consolidates
12110 	// deduped modules
12111 	g_hash_table_iter_init (&iter, acfg->method_to_cfg);
12112 	MonoCompile *dcfg = NULL;
12113 	MonoMethod *method = NULL;
12114 
12115 	size_t wrappers_size_saved = 0;
12116 	size_t inflated_size_saved = 0;
12117 	size_t copied_singles = 0;
12118 
12119 	while (g_hash_table_iter_next (&iter, (gpointer *) &method, (gpointer *)&dcfg)) {
12120 		gchar *dedup_name = mono_aot_get_mangled_method_name (method);
12121 		guint count = GPOINTER_TO_UINT(g_hash_table_lookup (acfg->dedup_stats, dedup_name));
12122 
12123 		if (count == 0)
12124 			continue;
12125 
12126 		if (acfg->dedup_emit_mode) {
12127 			// Size *saved* is the size due to things not emitted.
12128 			if (count < 2) {
12129 				// Just moved, didn't save space / dedup
12130 				copied_singles += dcfg->code_len;
12131 			} else if (method->wrapper_type != MONO_WRAPPER_NONE) {
12132 				wrappers_size_saved += dcfg->code_len * (count - 1);
12133 			} else {
12134 				inflated_size_saved += dcfg->code_len * (count - 1);
12135 			}
12136 		}
12137 	  if (acfg->aot_opts.dedup) {
12138 			if (method->wrapper_type != MONO_WRAPPER_NONE) {
12139 				wrappers_size_saved += dcfg->code_len * count;
12140 			} else {
12141 				inflated_size_saved += dcfg->code_len * count;
12142 			}
12143 		}
12144 	}
12145 
12146 	aot_printf (acfg, "Dedup Pass: Size Saved From Deduped Wrappers:\t%zu bytes\n", wrappers_size_saved);
12147 	aot_printf (acfg, "Dedup Pass: Size Saved From Inflated Methods:\t%zu bytes\n", inflated_size_saved);
12148 	if (acfg->dedup_emit_mode)
12149 		aot_printf (acfg, "Dedup Pass: Size of Moved But Not Deduped (only 1 copy) Methods:\t%zu bytes\n", copied_singles);
12150 
12151 	g_hash_table_destroy (acfg->dedup_stats);
12152 	acfg->dedup_stats = NULL;
12153 }
12154 
12155 // Flush the cache to tell future calls what to skip
12156 static void
mono_flush_method_cache(MonoAotCompile * acfg)12157 mono_flush_method_cache (MonoAotCompile *acfg)
12158 {
12159 	GHashTable *method_cache = acfg->dedup_cache;
12160 	char *filename = g_strdup_printf ("%s.dedup", acfg->image->name);
12161 	if (!acfg->dedup_cache_changed || !acfg->aot_opts.dedup) {
12162 		g_free (filename);
12163 		return;
12164 	}
12165 
12166 	acfg->dedup_cache = NULL;
12167 
12168 	FILE *cache = fopen (filename, "w");
12169 
12170 	if (!cache)
12171 		g_error ("Could not create cache at %s because of error: %s\n", filename, strerror (errno));
12172 
12173 	GHashTableIter iter;
12174 	gchar *name = NULL;
12175 	g_hash_table_iter_init (&iter, method_cache);
12176 	gboolean cont = TRUE;
12177 	while (cont && g_hash_table_iter_next (&iter, (gpointer *) &name, NULL)) {
12178 		int res = fprintf (cache, "%s\n", name);
12179 		cont = res >= 0;
12180 	}
12181 	// FIXME: don't assert if error when flushing
12182 	g_assert (cont);
12183 
12184 	fclose (cache);
12185 	g_free (filename);
12186 
12187 	// The keys are all in the imageset, nothing to free
12188 	// Values are just pointers to memory owned elsewhere, or sentinels
12189 	g_hash_table_destroy (method_cache);
12190 }
12191 
12192 // Read in what has been emitted by previous invocations,
12193 // what can be skipped
12194 static void
mono_read_method_cache(MonoAotCompile * acfg)12195 mono_read_method_cache (MonoAotCompile *acfg)
12196 {
12197 	char *filename = g_strdup_printf ("%s.dedup", acfg->image->name);
12198 	// Only do once, when dedup_cache is null
12199 	if (acfg->dedup_cache)
12200 		goto early_exit;
12201 
12202 	if (acfg->aot_opts.dedup_include || acfg->aot_opts.dedup)
12203 		g_assert (acfg->dedup_stats);
12204 
12205 	// only in skip mode
12206 	if (!acfg->aot_opts.dedup)
12207 		goto early_exit;
12208 
12209 	g_assert (acfg->dedup_cache);
12210 
12211 	FILE *cache = fopen (filename, "r");
12212 	if (!cache)
12213 		goto early_exit;
12214 
12215 	// Since we do pointer comparisons, and it can't be allocated at
12216 	// the address 0x1 due to alignment, we use this as a sentinel
12217 	gpointer other_acfg_sentinel = GINT_TO_POINTER (0x1);
12218 
12219 	if (fseek (cache, 0L, SEEK_END))
12220 		goto cleanup;
12221 
12222 	size_t fileLength = ftell (cache);
12223 	g_assert (fileLength > 0);
12224 
12225 	if (fseek (cache, 0L, SEEK_SET))
12226 		goto cleanup;
12227 
12228 	// Avoid thousands of new malloc entries
12229 	// FIXME: allocate into imageset, so we don't need to free.
12230 	// put the other mangled names there too.
12231 	char *bulk = g_malloc0 (fileLength * sizeof (char));
12232 	size_t offset = 0;
12233 
12234 	while (fgets (&bulk [offset], fileLength - offset, cache)) {
12235 		// strip newline
12236 		char *line = &bulk [offset];
12237 		size_t len = strlen (line);
12238 		if (len == 0)
12239 			break;
12240 
12241 		if (len >= 0 && line [len] == '\n')
12242 			line [len] = '\0';
12243 		offset += strlen (line) + 1;
12244 		g_assert (fileLength >= offset);
12245 
12246 		g_hash_table_insert (acfg->dedup_cache, line, other_acfg_sentinel);
12247 	}
12248 
12249 cleanup:
12250 	fclose (cache);
12251 
12252 early_exit:
12253 	g_free (filename);
12254 	return;
12255 }
12256 
12257 typedef struct {
12258 	GHashTable *cache;
12259 	GHashTable *stats;
12260 	gboolean emit_inflated_methods;
12261 	MonoAssembly *inflated_assembly;
12262 } MonoAotState;
12263 
12264 static MonoAotState *
alloc_aot_state(void)12265 alloc_aot_state (void)
12266 {
12267 	MonoAotState *state = g_malloc (sizeof (MonoAotState));
12268 	// FIXME: Should this own the memory?
12269 	state->cache = g_hash_table_new (g_str_hash, g_str_equal);
12270 	state->stats = g_hash_table_new (g_str_hash, g_str_equal);
12271 	// Start in "collect mode"
12272 	state->emit_inflated_methods = FALSE;
12273 	state->inflated_assembly = NULL;
12274 	return state;
12275 }
12276 
12277 static void
free_aot_state(MonoAotState * astate)12278 free_aot_state (MonoAotState *astate)
12279 {
12280 	g_hash_table_destroy (astate->cache);
12281 	g_free (astate);
12282 }
12283 
12284 static void
mono_add_deferred_extra_methods(MonoAotCompile * acfg,MonoAotState * astate)12285 mono_add_deferred_extra_methods (MonoAotCompile *acfg, MonoAotState *astate)
12286 {
12287 	GHashTableIter iter;
12288 	gchar *name = NULL;
12289 	MonoMethod *method = NULL;
12290 
12291 	acfg->dedup_emit_mode = TRUE;
12292 
12293 	g_hash_table_iter_init (&iter, astate->cache);
12294 	while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &method)) {
12295 		add_method_full (acfg, method, TRUE, 0);
12296 	}
12297 	return;
12298 }
12299 
12300 static void
mono_setup_dedup_state(MonoAotCompile * acfg,MonoAotState ** global_aot_state,MonoAssembly * ass,MonoAotState ** astate,gboolean * is_dedup_dummy)12301 mono_setup_dedup_state (MonoAotCompile *acfg, MonoAotState **global_aot_state, MonoAssembly *ass, MonoAotState **astate, gboolean *is_dedup_dummy)
12302 {
12303 	if (!acfg->aot_opts.dedup_include && !acfg->aot_opts.dedup)
12304 		return;
12305 
12306 	if (global_aot_state && *global_aot_state && acfg->aot_opts.dedup_include) {
12307 	// Thread the state through when making the inflate pass
12308 		*astate = *global_aot_state;
12309 	}
12310 
12311 	if (!*astate) {
12312 		*astate = alloc_aot_state ();
12313 		*global_aot_state = *astate;
12314 	}
12315 
12316 	acfg->dedup_cache = (*astate)->cache;
12317 	acfg->dedup_stats = (*astate)->stats;
12318 
12319 	// fills out acfg->dedup_cache
12320 	if (acfg->aot_opts.dedup)
12321 		mono_read_method_cache (acfg);
12322 
12323 	if (!(*astate)->inflated_assembly && acfg->aot_opts.dedup_include) {
12324 		gchar **asm_path = g_strsplit (ass->image->name, G_DIR_SEPARATOR_S, 0);
12325 		gchar *asm_file = NULL;
12326 
12327 		// Get the last part of the path, the filename
12328 		for (int i=0; asm_path [i] != NULL; i++)
12329 			asm_file = asm_path [i];
12330 
12331 		if (!strcmp (acfg->aot_opts.dedup_include, asm_file)) {
12332 			// Save
12333 			*is_dedup_dummy = TRUE;
12334 			(*astate)->inflated_assembly = ass;
12335 		}
12336 		g_strfreev (asm_path);
12337 	} else if ((*astate)->inflated_assembly) {
12338 		*is_dedup_dummy = (ass == (*astate)->inflated_assembly);
12339 	}
12340 }
12341 
12342 int
mono_compile_deferred_assemblies(guint32 opts,const char * aot_options,gpointer ** aot_state)12343 mono_compile_deferred_assemblies (guint32 opts, const char *aot_options, gpointer **aot_state)
12344 {
12345 	// create assembly, loop and add extra_methods
12346 	// in add_generic_instances , rip out what's in that for loop
12347 	// and apply that to this aot_state inside of mono_compile_assembly
12348 	MonoAotState *astate;
12349 	astate = *(MonoAotState **)aot_state;
12350 	g_assert (astate);
12351 
12352 	// FIXME: allow suffixes?
12353 	if (!astate->inflated_assembly) {
12354 		char *inflate = strstr (aot_options, "dedup-inflate");
12355 		if (!inflate)
12356 			return 0;
12357 		else
12358 			g_error ("Error: mono was not given an assembly with the provided inflate name\n");
12359 	}
12360 
12361 	// Switch modes
12362 	astate->emit_inflated_methods = TRUE;
12363 
12364 	int res = mono_compile_assembly (astate->inflated_assembly, opts, aot_options, aot_state);
12365 
12366 	*aot_state = NULL;
12367 	free_aot_state (astate);
12368 
12369 	return res;
12370 }
12371 
12372 static const char* interp_in_static_sigs[] = {
12373 	"bool ptr int32 ptr&",
12374 	"bool ptr ptr&",
12375 	"int32 int32 ptr&",
12376 	"int32 int32 ptr ptr&",
12377 	"int32 ptr int32 ptr",
12378 	"int32 ptr int32 ptr&",
12379 	"int32 ptr ptr&",
12380 	"object object ptr ptr ptr",
12381 	"ptr int32 ptr&",
12382 	"ptr ptr int32 ptr ptr ptr&",
12383 	"ptr ptr int32 ptr ptr&",
12384 	"ptr ptr int32 ptr&",
12385 	"ptr ptr ptr int32 ptr&",
12386 	"ptr ptr ptr ptr& ptr&",
12387 	"ptr ptr ptr ptr&",
12388 	"ptr ptr ptr&",
12389 	"ptr ptr uint32 ptr&",
12390 	"ptr uint32 ptr&",
12391 	"void object ptr ptr ptr",
12392 	"void ptr ptr int32 ptr ptr& ptr ptr&",
12393 	"void ptr ptr int32 ptr ptr&",
12394 	"void ptr ptr ptr&",
12395 	"void ptr ptr&",
12396 	"void ptr",
12397 	"void int32 ptr&",
12398 	"void uint32 ptr&",
12399 };
12400 
12401 int
mono_compile_assembly(MonoAssembly * ass,guint32 opts,const char * aot_options,gpointer ** global_aot_state)12402 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options, gpointer **global_aot_state)
12403 {
12404 	MonoImage *image = ass->image;
12405 	int i, res;
12406 	gint64 all_sizes;
12407 	MonoAotCompile *acfg;
12408 	char *outfile_name, *tmp_outfile_name, *p;
12409 	char llvm_stats_msg [256];
12410 	TV_DECLARE (atv);
12411 	TV_DECLARE (btv);
12412 
12413 	acfg = acfg_create (ass, opts);
12414 
12415 	memset (&acfg->aot_opts, 0, sizeof (acfg->aot_opts));
12416 	acfg->aot_opts.write_symbols = TRUE;
12417 	acfg->aot_opts.ntrampolines = 4096;
12418 	acfg->aot_opts.nrgctx_trampolines = 4096;
12419 	acfg->aot_opts.nimt_trampolines = 512;
12420 	acfg->aot_opts.nrgctx_fetch_trampolines = 128;
12421 	acfg->aot_opts.ngsharedvt_arg_trampolines = 512;
12422 	acfg->aot_opts.llvm_path = g_strdup ("");
12423 	acfg->aot_opts.temp_path = g_strdup ("");
12424 #ifdef MONOTOUCH
12425 	acfg->aot_opts.use_trampolines_page = TRUE;
12426 #endif
12427 
12428 	mono_aot_parse_options (aot_options, &acfg->aot_opts);
12429 
12430 	// start dedup
12431 	MonoAotState *astate = NULL;
12432 	gboolean is_dedup_dummy = FALSE;
12433 	mono_setup_dedup_state (acfg, (MonoAotState **) global_aot_state, ass, &astate, &is_dedup_dummy);
12434 
12435 	// Process later
12436 	if (is_dedup_dummy && astate && !astate->emit_inflated_methods)
12437 		return 0;
12438 
12439 	// end dedup
12440 
12441 	if (acfg->aot_opts.logfile) {
12442 		acfg->logfile = fopen (acfg->aot_opts.logfile, "a+");
12443 	}
12444 
12445 	if (acfg->aot_opts.data_outfile) {
12446 		acfg->data_outfile = fopen (acfg->aot_opts.data_outfile, "w+");
12447 		if (!acfg->data_outfile) {
12448 			aot_printerrf (acfg, "Unable to create file '%s': %s\n", acfg->aot_opts.data_outfile, strerror (errno));
12449 			return 1;
12450 		}
12451 		acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_SEPARATE_DATA);
12452 	}
12453 
12454 	//acfg->aot_opts.print_skipped_methods = TRUE;
12455 
12456 #if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
12457 	if (acfg->opts & MONO_OPT_GSHAREDVT) {
12458 		aot_printerrf (acfg, "-O=gsharedvt not supported on this platform.\n");
12459 		return 1;
12460 	}
12461 	if (acfg->aot_opts.llvm_only) {
12462 		aot_printerrf (acfg, "--aot=llvmonly requires a runtime that supports gsharedvt.\n");
12463 		return 1;
12464 	}
12465 #else
12466 	if (acfg->aot_opts.llvm_only || mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts))
12467 		acfg->opts |= MONO_OPT_GSHAREDVT;
12468 #endif
12469 
12470 #if !defined(ENABLE_LLVM)
12471 	if (acfg->aot_opts.llvm_only) {
12472 		aot_printerrf (acfg, "--aot=llvmonly requires a runtime compiled with llvm support.\n");
12473 		return 1;
12474 	}
12475 #endif
12476 
12477 	if (acfg->opts & MONO_OPT_GSHAREDVT)
12478 		mono_set_generic_sharing_vt_supported (TRUE);
12479 
12480 	aot_printf (acfg, "Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
12481 
12482 	generate_aotid ((guint8*) &acfg->image->aotid);
12483 
12484 	char *aotid = mono_guid_to_string (acfg->image->aotid);
12485 	aot_printf (acfg, "AOTID %s\n", aotid);
12486 	g_free (aotid);
12487 
12488 #ifndef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
12489 	if (mono_aot_mode_is_full (&acfg->aot_opts)) {
12490 		aot_printerrf (acfg, "--aot=full is not supported on this platform.\n");
12491 		return 1;
12492 	}
12493 #endif
12494 
12495 	if (acfg->aot_opts.direct_pinvoke && !acfg->aot_opts.static_link) {
12496 		aot_printerrf (acfg, "The 'direct-pinvoke' AOT option also requires the 'static' AOT option.\n");
12497 		return 1;
12498 	}
12499 
12500 	if (acfg->aot_opts.static_link)
12501 		acfg->aot_opts.asm_writer = TRUE;
12502 
12503 	if (acfg->aot_opts.soft_debug) {
12504 		MonoDebugOptions *opt = mini_get_debug_options ();
12505 
12506 		opt->mdb_optimizations = TRUE;
12507 		opt->gen_sdb_seq_points = TRUE;
12508 
12509 		if (!mono_debug_enabled ()) {
12510 			aot_printerrf (acfg, "The soft-debug AOT option requires the --debug option.\n");
12511 			return 1;
12512 		}
12513 		acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_DEBUG);
12514 	}
12515 
12516 	if (mono_use_llvm || acfg->aot_opts.llvm) {
12517 		acfg->llvm = TRUE;
12518 		acfg->aot_opts.asm_writer = TRUE;
12519 		acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_WITH_LLVM);
12520 
12521 		if (acfg->aot_opts.soft_debug) {
12522 			aot_printerrf (acfg, "The 'soft-debug' option is not supported when compiling with LLVM.\n");
12523 			return 1;
12524 		}
12525 
12526 		mini_llvm_init ();
12527 
12528 		if (acfg->aot_opts.asm_only && !acfg->aot_opts.llvm_outfile) {
12529 			aot_printerrf (acfg, "Compiling with LLVM and the asm-only option requires the llvm-outfile= option.\n");
12530 			return 1;
12531 		}
12532 	}
12533 
12534 	if (mono_aot_mode_is_full (&acfg->aot_opts)) {
12535 		acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_FULL_AOT);
12536 		acfg->is_full_aot = TRUE;
12537 	}
12538 
12539 	if (mono_threads_is_coop_enabled ())
12540 		acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_SAFEPOINTS);
12541 
12542 	// The methods in dedup-emit amodules must be available on runtime startup
12543 	// Note: Only one such amodule can have this attribute
12544 	if (astate && astate->emit_inflated_methods)
12545 		acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_EAGER_LOAD);
12546 
12547 
12548 	if (acfg->aot_opts.instances_logfile_path) {
12549 		acfg->instances_logfile = fopen (acfg->aot_opts.instances_logfile_path, "w");
12550 		if (!acfg->instances_logfile) {
12551 			aot_printerrf (acfg, "Unable to create logfile: '%s'.\n", acfg->aot_opts.instances_logfile_path);
12552 			return 1;
12553 		}
12554 	}
12555 
12556 	if (acfg->aot_opts.profile_files) {
12557 		GList *l;
12558 
12559 		for (l = acfg->aot_opts.profile_files; l; l = l->next) {
12560 			load_profile_file (acfg, (char*)l->data);
12561 		}
12562 	}
12563 
12564 	if (!mono_aot_mode_is_interp (&acfg->aot_opts)) {
12565 		int method_index;
12566 
12567        for (method_index = 0; method_index < acfg->image->tables [MONO_TABLE_METHOD].rows; ++method_index) {
12568 		   g_ptr_array_add (acfg->method_order,GUINT_TO_POINTER (method_index));
12569        }
12570 	}
12571 
12572 	acfg->num_trampolines [MONO_AOT_TRAMP_SPECIFIC] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.ntrampolines : 0;
12573 #ifdef MONO_ARCH_GSHARED_SUPPORTED
12574 	acfg->num_trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nrgctx_trampolines : 0;
12575 #endif
12576 	acfg->num_trampolines [MONO_AOT_TRAMP_IMT] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nimt_trampolines : 0;
12577 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
12578 	if (acfg->opts & MONO_OPT_GSHAREDVT)
12579 		acfg->num_trampolines [MONO_AOT_TRAMP_GSHAREDVT_ARG] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.ngsharedvt_arg_trampolines : 0;
12580 #endif
12581 
12582 	acfg->temp_prefix = mono_img_writer_get_temp_label_prefix (NULL);
12583 
12584 	arch_init (acfg);
12585 
12586 	if (mono_use_llvm || acfg->aot_opts.llvm) {
12587 
12588 		/*
12589 		 * Emit all LLVM code into a separate assembly/object file and link with it
12590 		 * normally.
12591 		 */
12592 		if (!acfg->aot_opts.asm_only && acfg->llvm_owriter_supported) {
12593 			acfg->llvm_owriter = TRUE;
12594 		} else if (acfg->aot_opts.llvm_outfile) {
12595 			int len = strlen (acfg->aot_opts.llvm_outfile);
12596 
12597 			if (len >= 2 && acfg->aot_opts.llvm_outfile [len - 2] == '.' && acfg->aot_opts.llvm_outfile [len - 1] == 'o')
12598 				acfg->llvm_owriter = TRUE;
12599 		}
12600 	}
12601 
12602 	if (acfg->llvm && acfg->thumb_mixed)
12603 		acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_LLVM_THUMB);
12604 	if (acfg->aot_opts.llvm_only)
12605 		acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_LLVM_ONLY);
12606 
12607 	acfg->assembly_name_sym = g_strdup (acfg->image->assembly->aname.name);
12608 	/* Get rid of characters which cannot occur in symbols */
12609 	for (p = acfg->assembly_name_sym; *p; ++p) {
12610 		if (!(isalnum (*p) || *p == '_'))
12611 			*p = '_';
12612 	}
12613 
12614 	acfg->global_prefix = g_strdup_printf ("mono_aot_%s", acfg->assembly_name_sym);
12615 	acfg->plt_symbol = g_strdup_printf ("%s_plt", acfg->global_prefix);
12616 	acfg->got_symbol = g_strdup_printf ("%s_got", acfg->global_prefix);
12617  	if (acfg->llvm) {
12618 		acfg->llvm_got_symbol = g_strdup_printf ("%s_llvm_got", acfg->global_prefix);
12619 		acfg->llvm_eh_frame_symbol = g_strdup_printf ("%s_eh_frame", acfg->global_prefix);
12620 	}
12621 
12622 	acfg->method_index = 1;
12623 
12624 	if (mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts))
12625 		mono_set_partial_sharing_supported (TRUE);
12626 
12627 	if (!mono_aot_mode_is_interp (&acfg->aot_opts)) {
12628 		res = collect_methods (acfg);
12629 
12630 		if (!res)
12631 			return 1;
12632 	}
12633 
12634 	// If we're emitting all of the inflated methods into a dummy
12635 	// Assembly, then after extra_methods is set up, we're done
12636 	// in this function.
12637 	if (astate && astate->emit_inflated_methods)
12638 		mono_add_deferred_extra_methods (acfg, astate);
12639 
12640 	{
12641 		GList *l;
12642 
12643 		for (l = acfg->profile_data; l; l = l->next)
12644 			resolve_profile_data (acfg, (ProfileData*)l->data);
12645 		for (l = acfg->profile_data; l; l = l->next)
12646 			add_profile_instances (acfg, (ProfileData*)l->data);
12647 	}
12648 
12649 	acfg->cfgs_size = acfg->methods->len + 32;
12650 	acfg->cfgs = g_new0 (MonoCompile*, acfg->cfgs_size);
12651 
12652 	/* PLT offset 0 is reserved for the PLT trampoline */
12653 	acfg->plt_offset = 1;
12654 	add_preinit_got_slots (acfg);
12655 
12656 #ifdef ENABLE_LLVM
12657 	if (acfg->llvm) {
12658 		llvm_acfg = acfg;
12659 		mono_llvm_create_aot_module (acfg->image->assembly, acfg->global_prefix, acfg->nshared_got_entries, TRUE, acfg->aot_opts.static_link, acfg->aot_opts.llvm_only);
12660 	}
12661 #endif
12662 
12663 	if (mono_aot_mode_is_interp (&acfg->aot_opts)) {
12664 		for (int i = 0; i < sizeof (interp_in_static_sigs) / sizeof (const char *); i++) {
12665 			MonoMethodSignature *sig = mono_create_icall_signature (interp_in_static_sigs [i]);
12666 			MonoMethod *wrapper = mini_get_interp_in_wrapper (sig);
12667 			add_method (acfg, wrapper);
12668 		}
12669 	}
12670 
12671 	TV_GETTIME (atv);
12672 
12673 	compile_methods (acfg);
12674 
12675 	TV_GETTIME (btv);
12676 
12677 	acfg->stats.jit_time = TV_ELAPSED (atv, btv);
12678 
12679 	TV_GETTIME (atv);
12680 
12681 #ifdef ENABLE_LLVM
12682 	if (acfg->llvm) {
12683 		if (acfg->aot_opts.asm_only) {
12684 			if (acfg->aot_opts.outfile) {
12685 				acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
12686 				acfg->tmpbasename = g_strdup (acfg->tmpfname);
12687 			} else {
12688 				acfg->tmpbasename = g_strdup_printf ("%s", acfg->image->name);
12689 				acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
12690 			}
12691 			g_assert (acfg->aot_opts.llvm_outfile);
12692 			acfg->llvm_sfile = g_strdup (acfg->aot_opts.llvm_outfile);
12693 			if (acfg->llvm_owriter)
12694 				acfg->llvm_ofile = g_strdup (acfg->aot_opts.llvm_outfile);
12695 			else
12696 				acfg->llvm_sfile = g_strdup (acfg->aot_opts.llvm_outfile);
12697 		} else {
12698 			acfg->tmpbasename = (strcmp (acfg->aot_opts.temp_path, "") == 0) ?
12699 				g_strdup_printf ("%s", "temp") :
12700 				g_build_filename (acfg->aot_opts.temp_path, "temp", NULL);
12701 
12702 			acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
12703 			acfg->llvm_sfile = g_strdup_printf ("%s-llvm.s", acfg->tmpbasename);
12704 			acfg->llvm_ofile = g_strdup_printf ("%s-llvm.o", acfg->tmpbasename);
12705 		}
12706 	}
12707 #endif
12708 
12709 	if (acfg->aot_opts.asm_only && !acfg->aot_opts.llvm_only) {
12710 		if (acfg->aot_opts.outfile)
12711 			acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
12712 		else
12713 			acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
12714 		acfg->fp = fopen (acfg->tmpfname, "w+");
12715 	} else {
12716 		if (strcmp (acfg->aot_opts.temp_path, "") == 0) {
12717 			int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
12718 			acfg->fp = fdopen (i, "w+");
12719 		} else {
12720 			acfg->tmpbasename = g_build_filename (acfg->aot_opts.temp_path, "temp", NULL);
12721 			acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
12722 			acfg->fp = fopen (acfg->tmpfname, "w+");
12723 		}
12724 	}
12725 	if (acfg->fp == 0 && !acfg->aot_opts.llvm_only) {
12726 		aot_printerrf (acfg, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno));
12727 		return 1;
12728 	}
12729 	if (acfg->fp)
12730 		acfg->w = mono_img_writer_create (acfg->fp, FALSE);
12731 
12732 	tmp_outfile_name = NULL;
12733 	outfile_name = NULL;
12734 
12735 	/* Compute symbols for methods */
12736 	for (i = 0; i < acfg->nmethods; ++i) {
12737 		if (acfg->cfgs [i]) {
12738 			MonoCompile *cfg = acfg->cfgs [i];
12739 			int method_index = get_method_index (acfg, cfg->orig_method);
12740 
12741 			if (COMPILE_LLVM (cfg))
12742 				cfg->asm_symbol = g_strdup_printf ("%s%s", acfg->llvm_label_prefix, cfg->llvm_method_name);
12743 			else if (acfg->global_symbols || acfg->llvm)
12744 				cfg->asm_symbol = get_debug_sym (cfg->orig_method, "", acfg->method_label_hash);
12745 			else
12746 				cfg->asm_symbol = g_strdup_printf ("%s%sm_%x", acfg->temp_prefix, acfg->llvm_label_prefix, method_index);
12747 			cfg->asm_debug_symbol = cfg->asm_symbol;
12748 		}
12749 	}
12750 
12751 	if (acfg->aot_opts.dwarf_debug && acfg->aot_opts.gnu_asm) {
12752 		/*
12753 		 * CLANG supports GAS .file/.loc directives, so emit line number information this way
12754 		 */
12755 		acfg->gas_line_numbers = TRUE;
12756 	}
12757 
12758 #ifdef EMIT_DWARF_INFO
12759 	if ((!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) && acfg->has_jitted_code) {
12760 		if (acfg->aot_opts.dwarf_debug && !mono_debug_enabled ()) {
12761 			aot_printerrf (acfg, "The dwarf AOT option requires the --debug option.\n");
12762 			return 1;
12763 		}
12764 		acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, !acfg->gas_line_numbers);
12765 	}
12766 #endif /* EMIT_DWARF_INFO */
12767 
12768 	if (acfg->w)
12769 		mono_img_writer_emit_start (acfg->w);
12770 
12771 	if (acfg->dwarf)
12772 		mono_dwarf_writer_emit_base_info (acfg->dwarf, g_path_get_basename (acfg->image->name), mono_unwind_get_cie_program ());
12773 
12774 	emit_code (acfg);
12775 	if (acfg->aot_opts.dedup)
12776 		mono_flush_method_cache (acfg);
12777 	if (acfg->aot_opts.dedup || acfg->dedup_emit_mode)
12778 		mono_dedup_log_stats (acfg);
12779 
12780 	emit_info (acfg);
12781 
12782 	emit_extra_methods (acfg);
12783 
12784 	if (acfg->aot_opts.dedup_include && !is_dedup_dummy)
12785 		return 0;
12786 
12787 	emit_trampolines (acfg);
12788 
12789 	emit_class_name_table (acfg);
12790 
12791 	emit_got_info (acfg, FALSE);
12792 	if (acfg->llvm)
12793 		emit_got_info (acfg, TRUE);
12794 
12795 	emit_exception_info (acfg);
12796 
12797 	emit_unwind_info (acfg);
12798 
12799 	emit_class_info (acfg);
12800 
12801 	emit_plt (acfg);
12802 
12803 	emit_image_table (acfg);
12804 
12805 	emit_weak_field_indexes (acfg);
12806 
12807 	emit_got (acfg);
12808 
12809 	{
12810 		/*
12811 		 * The managed allocators are GC specific, so can't use an AOT image created by one GC
12812 		 * in another.
12813 		 */
12814 		const char *gc_name = mono_gc_get_gc_name ();
12815 		acfg->gc_name_offset = add_to_blob (acfg, (guint8*)gc_name, strlen (gc_name) + 1);
12816 	}
12817 
12818 	emit_blob (acfg);
12819 
12820 	emit_objc_selectors (acfg);
12821 
12822 	emit_globals (acfg);
12823 
12824 	emit_file_info (acfg);
12825 
12826 	emit_library_info (acfg);
12827 
12828 	if (acfg->dwarf) {
12829 		emit_dwarf_info (acfg);
12830 		mono_dwarf_writer_close (acfg->dwarf);
12831 	} else {
12832 		if (!acfg->aot_opts.nodebug)
12833 			emit_codeview_info (acfg);
12834 	}
12835 
12836 	emit_mem_end (acfg);
12837 
12838 	if (acfg->need_pt_gnu_stack) {
12839 		/* This is required so the .so doesn't have an executable stack */
12840 		/* The bin writer already emits this */
12841 		fprintf (acfg->fp, "\n.section	.note.GNU-stack,\"\",@progbits\n");
12842 	}
12843 
12844 	if (acfg->aot_opts.data_outfile)
12845 		fclose (acfg->data_outfile);
12846 
12847 #ifdef ENABLE_LLVM
12848 	if (acfg->llvm) {
12849 		gboolean res;
12850 
12851 		res = emit_llvm_file (acfg);
12852 		if (!res)
12853 			return 1;
12854 	}
12855 #endif
12856 
12857 	TV_GETTIME (btv);
12858 
12859 	acfg->stats.gen_time = TV_ELAPSED (atv, btv);
12860 
12861 	if (acfg->llvm)
12862 		sprintf (llvm_stats_msg, ", LLVM: %d (%d%%)", acfg->stats.llvm_count, acfg->stats.mcount ? (acfg->stats.llvm_count * 100) / acfg->stats.mcount : 100);
12863 	else
12864 		strcpy (llvm_stats_msg, "");
12865 
12866 	all_sizes = acfg->stats.code_size + acfg->stats.info_size + acfg->stats.ex_info_size + acfg->stats.unwind_info_size + acfg->stats.class_info_size + acfg->stats.got_info_size + acfg->stats.offsets_size + acfg->stats.plt_size;
12867 
12868 	aot_printf (acfg, "Code: %d(%d%%) Info: %d(%d%%) Ex Info: %d(%d%%) Unwind Info: %d(%d%%) Class Info: %d(%d%%) PLT: %d(%d%%) GOT Info: %d(%d%%) Offsets: %d(%d%%) GOT: %d\n",
12869 				(int)acfg->stats.code_size, (int)(acfg->stats.code_size * 100 / all_sizes),
12870 				(int)acfg->stats.info_size, (int)(acfg->stats.info_size * 100 / all_sizes),
12871 				(int)acfg->stats.ex_info_size, (int)(acfg->stats.ex_info_size * 100 / all_sizes),
12872 				(int)acfg->stats.unwind_info_size, (int)(acfg->stats.unwind_info_size * 100 / all_sizes),
12873 				(int)acfg->stats.class_info_size, (int)(acfg->stats.class_info_size * 100 / all_sizes),
12874 				acfg->stats.plt_size ? (int)acfg->stats.plt_size : (int)acfg->plt_offset, acfg->stats.plt_size ? (int)(acfg->stats.plt_size * 100 / all_sizes) : 0,
12875 				(int)acfg->stats.got_info_size, (int)(acfg->stats.got_info_size * 100 / all_sizes),
12876 				(int)acfg->stats.offsets_size, (int)(acfg->stats.offsets_size * 100 / all_sizes),
12877 			(int)(acfg->got_offset * sizeof (gpointer)));
12878 	aot_printf (acfg, "Compiled: %d/%d (%d%%)%s, No GOT slots: %d (%d%%), Direct calls: %d (%d%%)\n",
12879 			acfg->stats.ccount, acfg->stats.mcount, acfg->stats.mcount ? (acfg->stats.ccount * 100) / acfg->stats.mcount : 100,
12880 			llvm_stats_msg,
12881 			acfg->stats.methods_without_got_slots, acfg->stats.mcount ? (acfg->stats.methods_without_got_slots * 100) / acfg->stats.mcount : 100,
12882 			acfg->stats.direct_calls, acfg->stats.all_calls ? (acfg->stats.direct_calls * 100) / acfg->stats.all_calls : 100);
12883 	if (acfg->stats.genericcount)
12884 		aot_printf (acfg, "%d methods are generic (%d%%)\n", acfg->stats.genericcount, acfg->stats.mcount ? (acfg->stats.genericcount * 100) / acfg->stats.mcount : 100);
12885 	if (acfg->stats.abscount)
12886 		aot_printf (acfg, "%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100);
12887 	if (acfg->stats.lmfcount)
12888 		aot_printf (acfg, "%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100);
12889 	if (acfg->stats.ocount)
12890 		aot_printf (acfg, "%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100);
12891 
12892 	TV_GETTIME (atv);
12893 	if (acfg->w) {
12894 		res = mono_img_writer_emit_writeout (acfg->w);
12895 		if (res != 0) {
12896 			acfg_free (acfg);
12897 			return res;
12898 		}
12899 		res = compile_asm (acfg);
12900 		if (res != 0) {
12901 			acfg_free (acfg);
12902 			return res;
12903 		}
12904 	}
12905 	TV_GETTIME (btv);
12906 	acfg->stats.link_time = TV_ELAPSED (atv, btv);
12907 
12908 	if (acfg->aot_opts.stats) {
12909 		int i;
12910 
12911 		aot_printf (acfg, "GOT slot distribution:\n");
12912 		for (i = 0; i < MONO_PATCH_INFO_NUM; ++i)
12913 			if (acfg->stats.got_slot_types [i])
12914 				aot_printf (acfg, "\t%s: %d (%d)\n", get_patch_name (i), acfg->stats.got_slot_types [i], acfg->stats.got_slot_info_sizes [i]);
12915 		aot_printf (acfg, "\nMethod stats:\n");
12916 		aot_printf (acfg, "\tNormal:    %d\n", acfg->stats.method_categories [METHOD_CAT_NORMAL]);
12917 		aot_printf (acfg, "\tInstance:  %d\n", acfg->stats.method_categories [METHOD_CAT_INST]);
12918 		aot_printf (acfg, "\tGSharedvt: %d\n", acfg->stats.method_categories [METHOD_CAT_GSHAREDVT]);
12919 		aot_printf (acfg, "\tWrapper:   %d\n", acfg->stats.method_categories [METHOD_CAT_WRAPPER]);
12920 	}
12921 
12922 	aot_printf (acfg, "JIT time: %d ms, Generation time: %d ms, Assembly+Link time: %d ms.\n", acfg->stats.jit_time / 1000, acfg->stats.gen_time / 1000, acfg->stats.link_time / 1000);
12923 
12924 	if (acfg->aot_opts.dump_json)
12925 		aot_dump (acfg);
12926 
12927 	acfg_free (acfg);
12928 
12929 	return 0;
12930 }
12931 
12932 #else
12933 
12934 /* AOT disabled */
12935 
12936 void*
mono_aot_readonly_field_override(MonoClassField * field)12937 mono_aot_readonly_field_override (MonoClassField *field)
12938 {
12939 	return NULL;
12940 }
12941 
12942 int
mono_compile_assembly(MonoAssembly * ass,guint32 opts,const char * aot_options,gpointer ** aot_state)12943 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options, gpointer **aot_state)
12944 {
12945 	return 0;
12946 }
12947 
12948 gboolean
mono_aot_is_shared_got_offset(int offset)12949 mono_aot_is_shared_got_offset (int offset)
12950 {
12951 	return FALSE;
12952 }
12953 
12954 int
mono_compile_deferred_assemblies(guint32 opts,const char * aot_options,gpointer ** aot_state)12955 mono_compile_deferred_assemblies (guint32 opts, const char *aot_options, gpointer **aot_state)
12956 {
12957 	g_assert_not_reached ();
12958 	return 0;
12959 }
12960 
12961 #endif
12962