[ci] Bump timeout in ms-test-suite
[mono-project.git] / mono / mini / mini-llvm.c
blobab6d21f92c5b40f7a7a84ea82daeed2c35051926
1 /*
2 * mini-llvm.c: llvm "Backend" for the mono JIT
4 * Copyright 2009-2011 Novell Inc (http://www.novell.com)
5 * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
6 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
7 */
9 #include "config.h"
11 #include <mono/metadata/debug-helpers.h>
12 #include <mono/metadata/debug-mono-symfile.h>
13 #include <mono/metadata/mempool-internals.h>
14 #include <mono/metadata/environment.h>
15 #include <mono/metadata/object-internals.h>
16 #include <mono/metadata/abi-details.h>
17 #include <mono/utils/mono-tls.h>
18 #include <mono/utils/mono-dl.h>
19 #include <mono/utils/mono-time.h>
20 #include <mono/utils/freebsd-dwarf.h>
22 #ifndef __STDC_LIMIT_MACROS
23 #define __STDC_LIMIT_MACROS
24 #endif
25 #ifndef __STDC_CONSTANT_MACROS
26 #define __STDC_CONSTANT_MACROS
27 #endif
29 #include "llvm-c/BitWriter.h"
30 #include "llvm-c/Analysis.h"
32 #include "mini-llvm-cpp.h"
33 #include "llvm-jit.h"
34 #include "aot-compiler.h"
35 #include "mini-llvm.h"
37 #ifndef DISABLE_JIT
39 #ifdef __MINGW32__
41 #include <stddef.h>
42 extern void *memset(void *, int, size_t);
43 void bzero (void *to, size_t count) { memset (to, 0, count); }
45 #endif
47 #if LLVM_API_VERSION < 4
48 #error "The version of the mono llvm repository is too old."
49 #endif
51 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
54 * Information associated by mono with LLVM modules.
56 typedef struct {
57 LLVMModuleRef lmodule;
58 LLVMValueRef throw_icall, rethrow, match_exc, throw_corlib_exception, resume_eh;
59 GHashTable *llvm_types;
60 LLVMValueRef got_var;
61 const char *got_symbol;
62 const char *get_method_symbol;
63 const char *get_unbox_tramp_symbol;
64 GHashTable *plt_entries;
65 GHashTable *plt_entries_ji;
66 GHashTable *method_to_lmethod;
67 GHashTable *direct_callables;
68 char **bb_names;
69 int bb_names_len;
70 GPtrArray *used;
71 LLVMTypeRef ptr_type;
72 GPtrArray *subprogram_mds;
73 MonoEERef *mono_ee;
74 LLVMExecutionEngineRef ee;
75 gboolean external_symbols;
76 gboolean emit_dwarf;
77 int max_got_offset;
78 LLVMValueRef personality;
80 /* For AOT */
81 MonoAssembly *assembly;
82 char *global_prefix;
83 MonoAotFileInfo aot_info;
84 const char *jit_got_symbol;
85 const char *eh_frame_symbol;
86 LLVMValueRef get_method, get_unbox_tramp;
87 LLVMValueRef init_method, init_method_gshared_mrgctx, init_method_gshared_this, init_method_gshared_vtable;
88 LLVMValueRef code_start, code_end;
89 LLVMValueRef inited_var;
90 int max_inited_idx, max_method_idx;
91 gboolean has_jitted_code;
92 gboolean static_link;
93 gboolean llvm_only;
94 GHashTable *idx_to_lmethod;
95 GHashTable *idx_to_unbox_tramp;
96 /* Maps a MonoMethod to LLVM instructions representing it */
97 GHashTable *method_to_callers;
98 LLVMContextRef context;
99 LLVMValueRef sentinel_exception;
100 void *di_builder, *cu;
101 GHashTable *objc_selector_to_var;
102 } MonoLLVMModule;
105 * Information associated by the backend with mono basic blocks.
107 typedef struct {
108 LLVMBasicBlockRef bblock, end_bblock;
109 LLVMValueRef finally_ind;
110 gboolean added, invoke_target;
112 * If this bblock is the start of a finally clause, this is a list of bblocks it
113 * needs to branch to in ENDFINALLY.
115 GSList *call_handler_return_bbs;
117 * If this bblock is the start of a finally clause, this is the bblock that
118 * CALL_HANDLER needs to branch to.
120 LLVMBasicBlockRef call_handler_target_bb;
121 /* The list of switch statements generated by ENDFINALLY instructions */
122 GSList *endfinally_switch_ins_list;
123 GSList *phi_nodes;
124 } BBInfo;
127 * Structure containing emit state
129 typedef struct {
130 MonoMemPool *mempool;
132 /* Maps method names to the corresponding LLVMValueRef */
133 GHashTable *emitted_method_decls;
135 MonoCompile *cfg;
136 LLVMValueRef lmethod;
137 MonoLLVMModule *module;
138 LLVMModuleRef lmodule;
139 BBInfo *bblocks;
140 int sindex, default_index, ex_index;
141 LLVMBuilderRef builder;
142 LLVMValueRef *values, *addresses;
143 MonoType **vreg_cli_types;
144 LLVMCallInfo *linfo;
145 MonoMethodSignature *sig;
146 GSList *builders;
147 GHashTable *region_to_handler;
148 GHashTable *clause_to_handler;
149 LLVMBuilderRef alloca_builder;
150 LLVMValueRef last_alloca;
151 LLVMValueRef rgctx_arg;
152 LLVMValueRef this_arg;
153 LLVMTypeRef *vreg_types;
154 gboolean *is_vphi;
155 LLVMTypeRef method_type;
156 LLVMBasicBlockRef init_bb, inited_bb;
157 gboolean *is_dead;
158 gboolean *unreachable;
159 gboolean llvm_only;
160 gboolean has_got_access;
161 gboolean is_linkonce;
162 int this_arg_pindex, rgctx_arg_pindex;
163 LLVMValueRef imt_rgctx_loc;
164 GHashTable *llvm_types;
165 LLVMValueRef dbg_md;
166 MonoDebugMethodInfo *minfo;
167 char temp_name [32];
168 /* For every clause, the clauses it is nested in */
169 GSList **nested_in;
170 LLVMValueRef ex_var;
171 GHashTable *exc_meta;
172 GHashTable *method_to_callers;
173 GPtrArray *phi_values;
174 GPtrArray *bblock_list;
175 char *method_name;
176 GHashTable *jit_callees;
177 LLVMValueRef long_bb_break_var;
178 } EmitContext;
180 typedef struct {
181 MonoBasicBlock *bb;
182 MonoInst *phi;
183 MonoBasicBlock *in_bb;
184 int sreg;
185 } PhiNode;
188 * Instruction metadata
189 * This is the same as ins_info, but LREG != IREG.
191 #ifdef MINI_OP
192 #undef MINI_OP
193 #endif
194 #ifdef MINI_OP3
195 #undef MINI_OP3
196 #endif
197 #define MINI_OP(a,b,dest,src1,src2) dest, src1, src2, ' ',
198 #define MINI_OP3(a,b,dest,src1,src2,src3) dest, src1, src2, src3,
199 #define NONE ' '
200 #define IREG 'i'
201 #define FREG 'f'
202 #define VREG 'v'
203 #define XREG 'x'
204 #define LREG 'l'
205 /* keep in sync with the enum in mini.h */
206 const char
207 llvm_ins_info[] = {
208 #include "mini-ops.h"
210 #undef MINI_OP
211 #undef MINI_OP3
213 #if SIZEOF_VOID_P == 4
214 #define GET_LONG_IMM(ins) (((guint64)(ins)->inst_ms_word << 32) | (guint64)(guint32)(ins)->inst_ls_word)
215 #else
216 #define GET_LONG_IMM(ins) ((ins)->inst_imm)
217 #endif
219 #define LLVM_INS_INFO(opcode) (&llvm_ins_info [((opcode) - OP_START - 1) * 4])
221 #if 0
222 #define TRACE_FAILURE(msg) do { printf ("%s\n", msg); } while (0)
223 #else
224 #define TRACE_FAILURE(msg)
225 #endif
227 #ifdef TARGET_X86
228 #define IS_TARGET_X86 1
229 #else
230 #define IS_TARGET_X86 0
231 #endif
233 #ifdef TARGET_AMD64
234 #define IS_TARGET_AMD64 1
235 #else
236 #define IS_TARGET_AMD64 0
237 #endif
239 #define ctx_ok(ctx) (!(ctx)->cfg->disable_llvm)
241 static LLVMIntPredicate cond_to_llvm_cond [] = {
242 LLVMIntEQ,
243 LLVMIntNE,
244 LLVMIntSLE,
245 LLVMIntSGE,
246 LLVMIntSLT,
247 LLVMIntSGT,
248 LLVMIntULE,
249 LLVMIntUGE,
250 LLVMIntULT,
251 LLVMIntUGT,
254 static LLVMRealPredicate fpcond_to_llvm_cond [] = {
255 LLVMRealOEQ,
256 LLVMRealUNE,
257 LLVMRealOLE,
258 LLVMRealOGE,
259 LLVMRealOLT,
260 LLVMRealOGT,
261 LLVMRealULE,
262 LLVMRealUGE,
263 LLVMRealULT,
264 LLVMRealUGT,
267 static MonoNativeTlsKey current_cfg_tls_id;
269 static MonoLLVMModule aot_module;
271 static GHashTable *intrins_id_to_name;
272 static GHashTable *intrins_name_to_id;
274 static void init_jit_module (MonoDomain *domain);
276 static void emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil_code);
277 static LLVMValueRef emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, const char *name);
278 static void emit_dbg_info (MonoLLVMModule *module, const char *filename, const char *cu_name);
279 static void emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *exc_type, LLVMValueRef cmp);
280 static LLVMValueRef get_intrinsic (EmitContext *ctx, const char *name);
281 static void decode_llvm_eh_info (EmitContext *ctx, gpointer eh_frame);
283 static inline void
284 set_failure (EmitContext *ctx, const char *message)
286 TRACE_FAILURE (reason);
287 ctx->cfg->exception_message = g_strdup (message);
288 ctx->cfg->disable_llvm = TRUE;
292 * IntPtrType:
294 * The LLVM type with width == sizeof (gpointer)
296 static LLVMTypeRef
297 IntPtrType (void)
299 return sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type ();
302 static LLVMTypeRef
303 ObjRefType (void)
305 return sizeof (gpointer) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
308 static LLVMTypeRef
309 ThisType (void)
311 return sizeof (gpointer) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
315 * get_vtype_size:
317 * Return the size of the LLVM representation of the vtype T.
319 static guint32
320 get_vtype_size (MonoType *t)
322 int size;
324 size = mono_class_value_size (mono_class_from_mono_type (t), NULL);
326 /* LLVMArgAsIArgs depends on this since it stores whole words */
327 while (size < 2 * sizeof (gpointer) && mono_is_power_of_two (size) == -1)
328 size ++;
330 return size;
334 * simd_class_to_llvm_type:
336 * Return the LLVM type corresponding to the Mono.SIMD class KLASS
338 static LLVMTypeRef
339 simd_class_to_llvm_type (EmitContext *ctx, MonoClass *klass)
341 if (!strcmp (klass->name, "Vector2d")) {
342 return LLVMVectorType (LLVMDoubleType (), 2);
343 } else if (!strcmp (klass->name, "Vector2l")) {
344 return LLVMVectorType (LLVMInt64Type (), 2);
345 } else if (!strcmp (klass->name, "Vector2ul")) {
346 return LLVMVectorType (LLVMInt64Type (), 2);
347 } else if (!strcmp (klass->name, "Vector4i")) {
348 return LLVMVectorType (LLVMInt32Type (), 4);
349 } else if (!strcmp (klass->name, "Vector4ui")) {
350 return LLVMVectorType (LLVMInt32Type (), 4);
351 } else if (!strcmp (klass->name, "Vector4f")) {
352 return LLVMVectorType (LLVMFloatType (), 4);
353 } else if (!strcmp (klass->name, "Vector8s")) {
354 return LLVMVectorType (LLVMInt16Type (), 8);
355 } else if (!strcmp (klass->name, "Vector8us")) {
356 return LLVMVectorType (LLVMInt16Type (), 8);
357 } else if (!strcmp (klass->name, "Vector16sb")) {
358 return LLVMVectorType (LLVMInt8Type (), 16);
359 } else if (!strcmp (klass->name, "Vector16b")) {
360 return LLVMVectorType (LLVMInt8Type (), 16);
361 } else if (!strcmp (klass->name, "Vector2")) {
362 /* System.Numerics */
363 return LLVMVectorType (LLVMFloatType (), 4);
364 } else if (!strcmp (klass->name, "Vector3")) {
365 return LLVMVectorType (LLVMFloatType (), 4);
366 } else if (!strcmp (klass->name, "Vector4")) {
367 return LLVMVectorType (LLVMFloatType (), 4);
368 } else if (!strcmp (klass->name, "Vector`1")) {
369 MonoType *etype = mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
370 switch (etype->type) {
371 case MONO_TYPE_I1:
372 case MONO_TYPE_U1:
373 return LLVMVectorType (LLVMInt8Type (), 16);
374 case MONO_TYPE_I2:
375 case MONO_TYPE_U2:
376 return LLVMVectorType (LLVMInt16Type (), 8);
377 case MONO_TYPE_I4:
378 case MONO_TYPE_U4:
379 return LLVMVectorType (LLVMInt32Type (), 4);
380 case MONO_TYPE_I8:
381 case MONO_TYPE_U8:
382 return LLVMVectorType (LLVMInt64Type (), 2);
383 case MONO_TYPE_R4:
384 return LLVMVectorType (LLVMFloatType (), 4);
385 case MONO_TYPE_R8:
386 return LLVMVectorType (LLVMDoubleType (), 2);
387 default:
388 g_assert_not_reached ();
389 return NULL;
391 } else {
392 printf ("%s\n", klass->name);
393 NOT_IMPLEMENTED;
394 return NULL;
398 /* Return the 128 bit SIMD type corresponding to the mono type TYPE */
399 static inline G_GNUC_UNUSED LLVMTypeRef
400 type_to_simd_type (int type)
402 switch (type) {
403 case MONO_TYPE_I1:
404 return LLVMVectorType (LLVMInt8Type (), 16);
405 case MONO_TYPE_I2:
406 return LLVMVectorType (LLVMInt16Type (), 8);
407 case MONO_TYPE_I4:
408 return LLVMVectorType (LLVMInt32Type (), 4);
409 case MONO_TYPE_I8:
410 return LLVMVectorType (LLVMInt64Type (), 2);
411 case MONO_TYPE_R8:
412 return LLVMVectorType (LLVMDoubleType (), 2);
413 case MONO_TYPE_R4:
414 return LLVMVectorType (LLVMFloatType (), 4);
415 default:
416 g_assert_not_reached ();
417 return NULL;
421 static LLVMTypeRef
422 create_llvm_type_for_type (MonoLLVMModule *module, MonoClass *klass)
424 int i, size, nfields, esize;
425 LLVMTypeRef *eltypes;
426 char *name;
427 MonoType *t;
428 LLVMTypeRef ltype;
430 t = &klass->byval_arg;
432 if (mini_type_is_hfa (t, &nfields, &esize)) {
434 * This is needed on arm64 where HFAs are returned in
435 * registers.
437 size = nfields;
438 eltypes = g_new (LLVMTypeRef, size);
439 for (i = 0; i < size; ++i)
440 eltypes [i] = esize == 4 ? LLVMFloatType () : LLVMDoubleType ();
441 } else {
442 size = get_vtype_size (t);
444 eltypes = g_new (LLVMTypeRef, size);
445 for (i = 0; i < size; ++i)
446 eltypes [i] = LLVMInt8Type ();
449 name = mono_type_full_name (&klass->byval_arg);
450 ltype = LLVMStructCreateNamed (module->context, name);
451 LLVMStructSetBody (ltype, eltypes, size, FALSE);
452 g_free (eltypes);
453 g_free (name);
455 return ltype;
459 * type_to_llvm_type:
461 * Return the LLVM type corresponding to T.
463 static LLVMTypeRef
464 type_to_llvm_type (EmitContext *ctx, MonoType *t)
466 t = mini_get_underlying_type (t);
468 switch (t->type) {
469 case MONO_TYPE_VOID:
470 return LLVMVoidType ();
471 case MONO_TYPE_I1:
472 return LLVMInt8Type ();
473 case MONO_TYPE_I2:
474 return LLVMInt16Type ();
475 case MONO_TYPE_I4:
476 return LLVMInt32Type ();
477 case MONO_TYPE_U1:
478 return LLVMInt8Type ();
479 case MONO_TYPE_U2:
480 return LLVMInt16Type ();
481 case MONO_TYPE_U4:
482 return LLVMInt32Type ();
483 case MONO_TYPE_BOOLEAN:
484 return LLVMInt8Type ();
485 case MONO_TYPE_I8:
486 case MONO_TYPE_U8:
487 return LLVMInt64Type ();
488 case MONO_TYPE_CHAR:
489 return LLVMInt16Type ();
490 case MONO_TYPE_R4:
491 return LLVMFloatType ();
492 case MONO_TYPE_R8:
493 return LLVMDoubleType ();
494 case MONO_TYPE_I:
495 case MONO_TYPE_U:
496 return IntPtrType ();
497 case MONO_TYPE_OBJECT:
498 case MONO_TYPE_CLASS:
499 case MONO_TYPE_ARRAY:
500 case MONO_TYPE_SZARRAY:
501 case MONO_TYPE_STRING:
502 case MONO_TYPE_PTR:
503 return ObjRefType ();
504 case MONO_TYPE_VAR:
505 case MONO_TYPE_MVAR:
506 /* Because of generic sharing */
507 return ObjRefType ();
508 case MONO_TYPE_GENERICINST:
509 if (!mono_type_generic_inst_is_valuetype (t))
510 return ObjRefType ();
511 /* Fall through */
512 case MONO_TYPE_VALUETYPE:
513 case MONO_TYPE_TYPEDBYREF: {
514 MonoClass *klass;
515 LLVMTypeRef ltype;
517 klass = mono_class_from_mono_type (t);
519 if (MONO_CLASS_IS_SIMD (ctx->cfg, klass))
520 return simd_class_to_llvm_type (ctx, klass);
522 if (klass->enumtype)
523 return type_to_llvm_type (ctx, mono_class_enum_basetype (klass));
525 ltype = (LLVMTypeRef)g_hash_table_lookup (ctx->module->llvm_types, klass);
526 if (!ltype) {
527 ltype = create_llvm_type_for_type (ctx->module, klass);
528 g_hash_table_insert (ctx->module->llvm_types, klass, ltype);
530 return ltype;
533 default:
534 printf ("X: %d\n", t->type);
535 ctx->cfg->exception_message = g_strdup_printf ("type %s", mono_type_full_name (t));
536 ctx->cfg->disable_llvm = TRUE;
537 return NULL;
542 * type_is_unsigned:
544 * Return whenever T is an unsigned int type.
546 static gboolean
547 type_is_unsigned (EmitContext *ctx, MonoType *t)
549 t = mini_get_underlying_type (t);
550 if (t->byref)
551 return FALSE;
552 switch (t->type) {
553 case MONO_TYPE_U1:
554 case MONO_TYPE_U2:
555 case MONO_TYPE_CHAR:
556 case MONO_TYPE_U4:
557 case MONO_TYPE_U8:
558 return TRUE;
559 default:
560 return FALSE;
565 * type_to_llvm_arg_type:
567 * Same as type_to_llvm_type, but treat i8/i16 as i32.
569 static LLVMTypeRef
570 type_to_llvm_arg_type (EmitContext *ctx, MonoType *t)
572 LLVMTypeRef ptype = type_to_llvm_type (ctx, t);
574 if (ctx->cfg->llvm_only)
575 return ptype;
578 * This works on all abis except arm64/ios which passes multiple
579 * arguments in one stack slot.
581 #ifndef TARGET_ARM64
582 if (ptype == LLVMInt8Type () || ptype == LLVMInt16Type ()) {
584 * LLVM generates code which only sets the lower bits, while JITted
585 * code expects all the bits to be set.
587 ptype = LLVMInt32Type ();
589 #endif
591 return ptype;
595 * llvm_type_to_stack_type:
597 * Return the LLVM type which needs to be used when a value of type TYPE is pushed
598 * on the IL stack.
600 static G_GNUC_UNUSED LLVMTypeRef
601 llvm_type_to_stack_type (MonoCompile *cfg, LLVMTypeRef type)
603 if (type == NULL)
604 return NULL;
605 if (type == LLVMInt8Type ())
606 return LLVMInt32Type ();
607 else if (type == LLVMInt16Type ())
608 return LLVMInt32Type ();
609 else if (!cfg->r4fp && type == LLVMFloatType ())
610 return LLVMDoubleType ();
611 else
612 return type;
616 * regtype_to_llvm_type:
618 * Return the LLVM type corresponding to the regtype C used in instruction
619 * descriptions.
621 static LLVMTypeRef
622 regtype_to_llvm_type (char c)
624 switch (c) {
625 case 'i':
626 return LLVMInt32Type ();
627 case 'l':
628 return LLVMInt64Type ();
629 case 'f':
630 return LLVMDoubleType ();
631 default:
632 return NULL;
637 * op_to_llvm_type:
639 * Return the LLVM type corresponding to the unary/binary opcode OPCODE.
641 static LLVMTypeRef
642 op_to_llvm_type (int opcode)
644 switch (opcode) {
645 case OP_ICONV_TO_I1:
646 case OP_LCONV_TO_I1:
647 return LLVMInt8Type ();
648 case OP_ICONV_TO_U1:
649 case OP_LCONV_TO_U1:
650 return LLVMInt8Type ();
651 case OP_ICONV_TO_I2:
652 case OP_LCONV_TO_I2:
653 return LLVMInt16Type ();
654 case OP_ICONV_TO_U2:
655 case OP_LCONV_TO_U2:
656 return LLVMInt16Type ();
657 case OP_ICONV_TO_I4:
658 case OP_LCONV_TO_I4:
659 return LLVMInt32Type ();
660 case OP_ICONV_TO_U4:
661 case OP_LCONV_TO_U4:
662 return LLVMInt32Type ();
663 case OP_ICONV_TO_I8:
664 return LLVMInt64Type ();
665 case OP_ICONV_TO_R4:
666 return LLVMFloatType ();
667 case OP_ICONV_TO_R8:
668 return LLVMDoubleType ();
669 case OP_ICONV_TO_U8:
670 return LLVMInt64Type ();
671 case OP_FCONV_TO_I4:
672 return LLVMInt32Type ();
673 case OP_FCONV_TO_I8:
674 return LLVMInt64Type ();
675 case OP_FCONV_TO_I1:
676 case OP_FCONV_TO_U1:
677 case OP_RCONV_TO_I1:
678 case OP_RCONV_TO_U1:
679 return LLVMInt8Type ();
680 case OP_FCONV_TO_I2:
681 case OP_FCONV_TO_U2:
682 case OP_RCONV_TO_I2:
683 case OP_RCONV_TO_U2:
684 return LLVMInt16Type ();
685 case OP_RCONV_TO_U4:
686 return LLVMInt32Type ();
687 case OP_FCONV_TO_I:
688 case OP_FCONV_TO_U:
689 return sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type ();
690 case OP_IADD_OVF:
691 case OP_IADD_OVF_UN:
692 case OP_ISUB_OVF:
693 case OP_ISUB_OVF_UN:
694 case OP_IMUL_OVF:
695 case OP_IMUL_OVF_UN:
696 return LLVMInt32Type ();
697 case OP_LADD_OVF:
698 case OP_LADD_OVF_UN:
699 case OP_LSUB_OVF:
700 case OP_LSUB_OVF_UN:
701 case OP_LMUL_OVF:
702 case OP_LMUL_OVF_UN:
703 return LLVMInt64Type ();
704 default:
705 printf ("%s\n", mono_inst_name (opcode));
706 g_assert_not_reached ();
707 return NULL;
711 #define CLAUSE_START(clause) ((clause)->try_offset)
712 #define CLAUSE_END(clause) (((clause))->try_offset + ((clause))->try_len)
715 * load_store_to_llvm_type:
717 * Return the size/sign/zero extension corresponding to the load/store opcode
718 * OPCODE.
720 static LLVMTypeRef
721 load_store_to_llvm_type (int opcode, int *size, gboolean *sext, gboolean *zext)
723 *sext = FALSE;
724 *zext = FALSE;
726 switch (opcode) {
727 case OP_LOADI1_MEMBASE:
728 case OP_STOREI1_MEMBASE_REG:
729 case OP_STOREI1_MEMBASE_IMM:
730 case OP_ATOMIC_LOAD_I1:
731 case OP_ATOMIC_STORE_I1:
732 *size = 1;
733 *sext = TRUE;
734 return LLVMInt8Type ();
735 case OP_LOADU1_MEMBASE:
736 case OP_LOADU1_MEM:
737 case OP_ATOMIC_LOAD_U1:
738 case OP_ATOMIC_STORE_U1:
739 *size = 1;
740 *zext = TRUE;
741 return LLVMInt8Type ();
742 case OP_LOADI2_MEMBASE:
743 case OP_STOREI2_MEMBASE_REG:
744 case OP_STOREI2_MEMBASE_IMM:
745 case OP_ATOMIC_LOAD_I2:
746 case OP_ATOMIC_STORE_I2:
747 *size = 2;
748 *sext = TRUE;
749 return LLVMInt16Type ();
750 case OP_LOADU2_MEMBASE:
751 case OP_LOADU2_MEM:
752 case OP_ATOMIC_LOAD_U2:
753 case OP_ATOMIC_STORE_U2:
754 *size = 2;
755 *zext = TRUE;
756 return LLVMInt16Type ();
757 case OP_LOADI4_MEMBASE:
758 case OP_LOADU4_MEMBASE:
759 case OP_LOADI4_MEM:
760 case OP_LOADU4_MEM:
761 case OP_STOREI4_MEMBASE_REG:
762 case OP_STOREI4_MEMBASE_IMM:
763 case OP_ATOMIC_LOAD_I4:
764 case OP_ATOMIC_STORE_I4:
765 case OP_ATOMIC_LOAD_U4:
766 case OP_ATOMIC_STORE_U4:
767 *size = 4;
768 return LLVMInt32Type ();
769 case OP_LOADI8_MEMBASE:
770 case OP_LOADI8_MEM:
771 case OP_STOREI8_MEMBASE_REG:
772 case OP_STOREI8_MEMBASE_IMM:
773 case OP_ATOMIC_LOAD_I8:
774 case OP_ATOMIC_STORE_I8:
775 case OP_ATOMIC_LOAD_U8:
776 case OP_ATOMIC_STORE_U8:
777 *size = 8;
778 return LLVMInt64Type ();
779 case OP_LOADR4_MEMBASE:
780 case OP_STORER4_MEMBASE_REG:
781 case OP_ATOMIC_LOAD_R4:
782 case OP_ATOMIC_STORE_R4:
783 *size = 4;
784 return LLVMFloatType ();
785 case OP_LOADR8_MEMBASE:
786 case OP_STORER8_MEMBASE_REG:
787 case OP_ATOMIC_LOAD_R8:
788 case OP_ATOMIC_STORE_R8:
789 *size = 8;
790 return LLVMDoubleType ();
791 case OP_LOAD_MEMBASE:
792 case OP_LOAD_MEM:
793 case OP_STORE_MEMBASE_REG:
794 case OP_STORE_MEMBASE_IMM:
795 *size = sizeof (gpointer);
796 return IntPtrType ();
797 default:
798 g_assert_not_reached ();
799 return NULL;
804 * ovf_op_to_intrins:
806 * Return the LLVM intrinsics corresponding to the overflow opcode OPCODE.
808 static const char*
809 ovf_op_to_intrins (int opcode)
811 switch (opcode) {
812 case OP_IADD_OVF:
813 return "llvm.sadd.with.overflow.i32";
814 case OP_IADD_OVF_UN:
815 return "llvm.uadd.with.overflow.i32";
816 case OP_ISUB_OVF:
817 return "llvm.ssub.with.overflow.i32";
818 case OP_ISUB_OVF_UN:
819 return "llvm.usub.with.overflow.i32";
820 case OP_IMUL_OVF:
821 return "llvm.smul.with.overflow.i32";
822 case OP_IMUL_OVF_UN:
823 return "llvm.umul.with.overflow.i32";
824 case OP_LADD_OVF:
825 return "llvm.sadd.with.overflow.i64";
826 case OP_LADD_OVF_UN:
827 return "llvm.uadd.with.overflow.i64";
828 case OP_LSUB_OVF:
829 return "llvm.ssub.with.overflow.i64";
830 case OP_LSUB_OVF_UN:
831 return "llvm.usub.with.overflow.i64";
832 case OP_LMUL_OVF:
833 return "llvm.smul.with.overflow.i64";
834 case OP_LMUL_OVF_UN:
835 return "llvm.umul.with.overflow.i64";
836 default:
837 g_assert_not_reached ();
838 return NULL;
842 static const char*
843 simd_op_to_intrins (int opcode)
845 switch (opcode) {
846 #if defined(TARGET_X86) || defined(TARGET_AMD64)
847 case OP_MINPD:
848 return "llvm.x86.sse2.min.pd";
849 case OP_MINPS:
850 return "llvm.x86.sse.min.ps";
851 case OP_MAXPD:
852 return "llvm.x86.sse2.max.pd";
853 case OP_MAXPS:
854 return "llvm.x86.sse.max.ps";
855 case OP_HADDPD:
856 return "llvm.x86.sse3.hadd.pd";
857 case OP_HADDPS:
858 return "llvm.x86.sse3.hadd.ps";
859 case OP_HSUBPD:
860 return "llvm.x86.sse3.hsub.pd";
861 case OP_HSUBPS:
862 return "llvm.x86.sse3.hsub.ps";
863 case OP_ADDSUBPS:
864 return "llvm.x86.sse3.addsub.ps";
865 case OP_ADDSUBPD:
866 return "llvm.x86.sse3.addsub.pd";
867 case OP_EXTRACT_MASK:
868 return "llvm.x86.sse2.pmovmskb.128";
869 case OP_PSHRW:
870 case OP_PSHRW_REG:
871 return "llvm.x86.sse2.psrli.w";
872 case OP_PSHRD:
873 case OP_PSHRD_REG:
874 return "llvm.x86.sse2.psrli.d";
875 case OP_PSHRQ:
876 case OP_PSHRQ_REG:
877 return "llvm.x86.sse2.psrli.q";
878 case OP_PSHLW:
879 case OP_PSHLW_REG:
880 return "llvm.x86.sse2.pslli.w";
881 case OP_PSHLD:
882 case OP_PSHLD_REG:
883 return "llvm.x86.sse2.pslli.d";
884 case OP_PSHLQ:
885 case OP_PSHLQ_REG:
886 return "llvm.x86.sse2.pslli.q";
887 case OP_PSARW:
888 case OP_PSARW_REG:
889 return "llvm.x86.sse2.psrai.w";
890 case OP_PSARD:
891 case OP_PSARD_REG:
892 return "llvm.x86.sse2.psrai.d";
893 case OP_PADDB_SAT:
894 return "llvm.x86.sse2.padds.b";
895 case OP_PADDW_SAT:
896 return "llvm.x86.sse2.padds.w";
897 case OP_PSUBB_SAT:
898 return "llvm.x86.sse2.psubs.b";
899 case OP_PSUBW_SAT:
900 return "llvm.x86.sse2.psubs.w";
901 case OP_PADDB_SAT_UN:
902 return "llvm.x86.sse2.paddus.b";
903 case OP_PADDW_SAT_UN:
904 return "llvm.x86.sse2.paddus.w";
905 case OP_PSUBB_SAT_UN:
906 return "llvm.x86.sse2.psubus.b";
907 case OP_PSUBW_SAT_UN:
908 return "llvm.x86.sse2.psubus.w";
909 case OP_PAVGB_UN:
910 return "llvm.x86.sse2.pavg.b";
911 case OP_PAVGW_UN:
912 return "llvm.x86.sse2.pavg.w";
913 case OP_SQRTPS:
914 return "llvm.x86.sse.sqrt.ps";
915 case OP_SQRTPD:
916 return "llvm.x86.sse2.sqrt.pd";
917 case OP_RSQRTPS:
918 return "llvm.x86.sse.rsqrt.ps";
919 case OP_RCPPS:
920 return "llvm.x86.sse.rcp.ps";
921 case OP_CVTDQ2PD:
922 return "llvm.x86.sse2.cvtdq2pd";
923 case OP_CVTDQ2PS:
924 return "llvm.x86.sse2.cvtdq2ps";
925 case OP_CVTPD2DQ:
926 return "llvm.x86.sse2.cvtpd2dq";
927 case OP_CVTPS2DQ:
928 return "llvm.x86.sse2.cvtps2dq";
929 case OP_CVTPD2PS:
930 return "llvm.x86.sse2.cvtpd2ps";
931 case OP_CVTPS2PD:
932 return "llvm.x86.sse2.cvtps2pd";
933 case OP_CVTTPD2DQ:
934 return "llvm.x86.sse2.cvttpd2dq";
935 case OP_CVTTPS2DQ:
936 return "llvm.x86.sse2.cvttps2dq";
937 case OP_PACKW:
938 return "llvm.x86.sse2.packsswb.128";
939 case OP_PACKD:
940 return "llvm.x86.sse2.packssdw.128";
941 case OP_PACKW_UN:
942 return "llvm.x86.sse2.packuswb.128";
943 case OP_PACKD_UN:
944 return "llvm.x86.sse41.packusdw";
945 case OP_PMULW_HIGH:
946 return "llvm.x86.sse2.pmulh.w";
947 case OP_PMULW_HIGH_UN:
948 return "llvm.x86.sse2.pmulhu.w";
949 case OP_DPPS:
950 return "llvm.x86.sse41.dpps";
951 #endif
952 default:
953 g_assert_not_reached ();
954 return NULL;
958 static LLVMTypeRef
959 simd_op_to_llvm_type (int opcode)
961 #if defined(TARGET_X86) || defined(TARGET_AMD64)
962 switch (opcode) {
963 case OP_EXTRACT_R8:
964 case OP_EXPAND_R8:
965 return type_to_simd_type (MONO_TYPE_R8);
966 case OP_EXTRACT_I8:
967 case OP_EXPAND_I8:
968 return type_to_simd_type (MONO_TYPE_I8);
969 case OP_EXTRACT_I4:
970 case OP_EXPAND_I4:
971 return type_to_simd_type (MONO_TYPE_I4);
972 case OP_EXTRACT_I2:
973 case OP_EXTRACT_U2:
974 case OP_EXTRACTX_U2:
975 case OP_EXPAND_I2:
976 return type_to_simd_type (MONO_TYPE_I2);
977 case OP_EXTRACT_I1:
978 case OP_EXTRACT_U1:
979 case OP_EXPAND_I1:
980 return type_to_simd_type (MONO_TYPE_I1);
981 case OP_EXPAND_R4:
982 return type_to_simd_type (MONO_TYPE_R4);
983 case OP_CVTDQ2PD:
984 case OP_CVTDQ2PS:
985 return type_to_simd_type (MONO_TYPE_I4);
986 case OP_CVTPD2DQ:
987 case OP_CVTPD2PS:
988 case OP_CVTTPD2DQ:
989 return type_to_simd_type (MONO_TYPE_R8);
990 case OP_CVTPS2DQ:
991 case OP_CVTPS2PD:
992 case OP_CVTTPS2DQ:
993 return type_to_simd_type (MONO_TYPE_R4);
994 case OP_EXTRACT_MASK:
995 return type_to_simd_type (MONO_TYPE_I1);
996 case OP_SQRTPS:
997 case OP_RSQRTPS:
998 case OP_RCPPS:
999 case OP_DUPPS_LOW:
1000 case OP_DUPPS_HIGH:
1001 return type_to_simd_type (MONO_TYPE_R4);
1002 case OP_SQRTPD:
1003 case OP_DUPPD:
1004 return type_to_simd_type (MONO_TYPE_R8);
1005 default:
1006 g_assert_not_reached ();
1007 return NULL;
1009 #else
1010 return NULL;
1011 #endif
1015 * get_bb:
1017 * Return the LLVM basic block corresponding to BB.
1019 static LLVMBasicBlockRef
1020 get_bb (EmitContext *ctx, MonoBasicBlock *bb)
1022 char bb_name_buf [128];
1023 char *bb_name;
1025 if (ctx->bblocks [bb->block_num].bblock == NULL) {
1026 if (bb->flags & BB_EXCEPTION_HANDLER) {
1027 int clause_index = (mono_get_block_region_notry (ctx->cfg, bb->region) >> 8) - 1;
1028 sprintf (bb_name_buf, "EH_CLAUSE%d_BB%d", clause_index, bb->block_num);
1029 bb_name = bb_name_buf;
1030 } else if (bb->block_num < 256) {
1031 if (!ctx->module->bb_names) {
1032 ctx->module->bb_names_len = 256;
1033 ctx->module->bb_names = g_new0 (char*, ctx->module->bb_names_len);
1035 if (!ctx->module->bb_names [bb->block_num]) {
1036 char *n;
1038 n = g_strdup_printf ("BB%d", bb->block_num);
1039 mono_memory_barrier ();
1040 ctx->module->bb_names [bb->block_num] = n;
1042 bb_name = ctx->module->bb_names [bb->block_num];
1043 } else {
1044 sprintf (bb_name_buf, "BB%d", bb->block_num);
1045 bb_name = bb_name_buf;
1048 ctx->bblocks [bb->block_num].bblock = LLVMAppendBasicBlock (ctx->lmethod, bb_name);
1049 ctx->bblocks [bb->block_num].end_bblock = ctx->bblocks [bb->block_num].bblock;
1052 return ctx->bblocks [bb->block_num].bblock;
1056 * get_end_bb:
1058 * Return the last LLVM bblock corresponding to BB.
1059 * This might not be equal to the bb returned by get_bb () since we need to generate
1060 * multiple LLVM bblocks for a mono bblock to handle throwing exceptions.
1062 static LLVMBasicBlockRef
1063 get_end_bb (EmitContext *ctx, MonoBasicBlock *bb)
1065 get_bb (ctx, bb);
1066 return ctx->bblocks [bb->block_num].end_bblock;
1069 static LLVMBasicBlockRef
1070 gen_bb (EmitContext *ctx, const char *prefix)
1072 char bb_name [128];
1074 sprintf (bb_name, "%s%d", prefix, ++ ctx->ex_index);
1075 return LLVMAppendBasicBlock (ctx->lmethod, bb_name);
1079 * resolve_patch:
1081 * Return the target of the patch identified by TYPE and TARGET.
1083 static gpointer
1084 resolve_patch (MonoCompile *cfg, MonoJumpInfoType type, gconstpointer target)
1086 MonoJumpInfo ji;
1087 MonoError error;
1088 gpointer res;
1090 memset (&ji, 0, sizeof (ji));
1091 ji.type = type;
1092 ji.data.target = target;
1094 res = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, &ji, FALSE, &error);
1095 mono_error_assert_ok (&error);
1097 return res;
1101 * convert_full:
1103 * Emit code to convert the LLVM value V to DTYPE.
1105 static LLVMValueRef
1106 convert_full (EmitContext *ctx, LLVMValueRef v, LLVMTypeRef dtype, gboolean is_unsigned)
1108 LLVMTypeRef stype = LLVMTypeOf (v);
1110 if (stype != dtype) {
1111 gboolean ext = FALSE;
1113 /* Extend */
1114 if (dtype == LLVMInt64Type () && (stype == LLVMInt32Type () || stype == LLVMInt16Type () || stype == LLVMInt8Type ()))
1115 ext = TRUE;
1116 else if (dtype == LLVMInt32Type () && (stype == LLVMInt16Type () || stype == LLVMInt8Type ()))
1117 ext = TRUE;
1118 else if (dtype == LLVMInt16Type () && (stype == LLVMInt8Type ()))
1119 ext = TRUE;
1121 if (ext)
1122 return is_unsigned ? LLVMBuildZExt (ctx->builder, v, dtype, "") : LLVMBuildSExt (ctx->builder, v, dtype, "");
1124 if (dtype == LLVMDoubleType () && stype == LLVMFloatType ())
1125 return LLVMBuildFPExt (ctx->builder, v, dtype, "");
1127 /* Trunc */
1128 if (stype == LLVMInt64Type () && (dtype == LLVMInt32Type () || dtype == LLVMInt16Type () || dtype == LLVMInt8Type ()))
1129 return LLVMBuildTrunc (ctx->builder, v, dtype, "");
1130 if (stype == LLVMInt32Type () && (dtype == LLVMInt16Type () || dtype == LLVMInt8Type ()))
1131 return LLVMBuildTrunc (ctx->builder, v, dtype, "");
1132 if (stype == LLVMInt16Type () && dtype == LLVMInt8Type ())
1133 return LLVMBuildTrunc (ctx->builder, v, dtype, "");
1134 if (stype == LLVMDoubleType () && dtype == LLVMFloatType ())
1135 return LLVMBuildFPTrunc (ctx->builder, v, dtype, "");
1137 if (LLVMGetTypeKind (stype) == LLVMPointerTypeKind && LLVMGetTypeKind (dtype) == LLVMPointerTypeKind)
1138 return LLVMBuildBitCast (ctx->builder, v, dtype, "");
1139 if (LLVMGetTypeKind (dtype) == LLVMPointerTypeKind)
1140 return LLVMBuildIntToPtr (ctx->builder, v, dtype, "");
1141 if (LLVMGetTypeKind (stype) == LLVMPointerTypeKind)
1142 return LLVMBuildPtrToInt (ctx->builder, v, dtype, "");
1144 if (mono_arch_is_soft_float ()) {
1145 if (stype == LLVMInt32Type () && dtype == LLVMFloatType ())
1146 return LLVMBuildBitCast (ctx->builder, v, dtype, "");
1147 if (stype == LLVMInt32Type () && dtype == LLVMDoubleType ())
1148 return LLVMBuildBitCast (ctx->builder, LLVMBuildZExt (ctx->builder, v, LLVMInt64Type (), ""), dtype, "");
1151 if (LLVMGetTypeKind (stype) == LLVMVectorTypeKind && LLVMGetTypeKind (dtype) == LLVMVectorTypeKind)
1152 return LLVMBuildBitCast (ctx->builder, v, dtype, "");
1154 LLVMDumpValue (v);
1155 LLVMDumpValue (LLVMConstNull (dtype));
1156 g_assert_not_reached ();
1157 return NULL;
1158 } else {
1159 return v;
1163 static LLVMValueRef
1164 convert (EmitContext *ctx, LLVMValueRef v, LLVMTypeRef dtype)
1166 return convert_full (ctx, v, dtype, FALSE);
1170 * emit_volatile_load:
1172 * If vreg is volatile, emit a load from its address.
1174 static LLVMValueRef
1175 emit_volatile_load (EmitContext *ctx, int vreg)
1177 MonoType *t;
1178 LLVMValueRef v;
1180 #ifdef TARGET_ARM64
1181 // FIXME: This hack is required because we pass the rgctx in a callee saved
1182 // register on arm64 (x15), and llvm might keep the value in that register
1183 // even through the register is marked as 'reserved' inside llvm.
1184 if (ctx->cfg->rgctx_var && ctx->cfg->rgctx_var->dreg == vreg)
1185 v = mono_llvm_build_load (ctx->builder, ctx->addresses [vreg], "", TRUE);
1186 else
1187 v = LLVMBuildLoad (ctx->builder, ctx->addresses [vreg], "");
1188 #else
1189 v = LLVMBuildLoad (ctx->builder, ctx->addresses [vreg], "");
1190 #endif
1191 t = ctx->vreg_cli_types [vreg];
1192 if (t && !t->byref) {
1194 * Might have to zero extend since llvm doesn't have
1195 * unsigned types.
1197 if (t->type == MONO_TYPE_U1 || t->type == MONO_TYPE_U2 || t->type == MONO_TYPE_CHAR || t->type == MONO_TYPE_BOOLEAN)
1198 v = LLVMBuildZExt (ctx->builder, v, LLVMInt32Type (), "");
1199 else if (t->type == MONO_TYPE_I1 || t->type == MONO_TYPE_I2)
1200 v = LLVMBuildSExt (ctx->builder, v, LLVMInt32Type (), "");
1201 else if (t->type == MONO_TYPE_U8)
1202 v = LLVMBuildZExt (ctx->builder, v, LLVMInt64Type (), "");
1205 return v;
1209 * emit_volatile_store:
1211 * If VREG is volatile, emit a store from its value to its address.
1213 static void
1214 emit_volatile_store (EmitContext *ctx, int vreg)
1216 MonoInst *var = get_vreg_to_inst (ctx->cfg, vreg);
1218 if (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) {
1219 g_assert (ctx->addresses [vreg]);
1220 LLVMBuildStore (ctx->builder, convert (ctx, ctx->values [vreg], type_to_llvm_type (ctx, var->inst_vtype)), ctx->addresses [vreg]);
1224 static LLVMTypeRef
1225 sig_to_llvm_sig_no_cinfo (EmitContext *ctx, MonoMethodSignature *sig)
1227 LLVMTypeRef ret_type;
1228 LLVMTypeRef *param_types = NULL;
1229 LLVMTypeRef res;
1230 int i, pindex;
1231 MonoType *rtype;
1233 rtype = mini_get_underlying_type (sig->ret);
1234 ret_type = type_to_llvm_type (ctx, rtype);
1235 if (!ctx_ok (ctx))
1236 return NULL;
1238 param_types = g_new0 (LLVMTypeRef, (sig->param_count * 8) + 3);
1239 pindex = 0;
1241 if (sig->hasthis)
1242 param_types [pindex ++] = ThisType ();
1243 for (i = 0; i < sig->param_count; ++i)
1244 param_types [pindex ++] = type_to_llvm_arg_type (ctx, sig->params [i]);
1246 if (!ctx_ok (ctx)) {
1247 g_free (param_types);
1248 return NULL;
1251 res = LLVMFunctionType (ret_type, param_types, pindex, FALSE);
1252 g_free (param_types);
1254 return res;
1258 * sig_to_llvm_sig_full:
1260 * Return the LLVM signature corresponding to the mono signature SIG using the
1261 * calling convention information in CINFO. Fill out the parameter mapping information in CINFO.
1263 static LLVMTypeRef
1264 sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *cinfo)
1266 LLVMTypeRef ret_type;
1267 LLVMTypeRef *param_types = NULL;
1268 LLVMTypeRef res;
1269 int i, j, pindex, vret_arg_pindex = 0;
1270 gboolean vretaddr = FALSE;
1271 MonoType *rtype;
1273 if (!cinfo)
1274 return sig_to_llvm_sig_no_cinfo (ctx, sig);
1276 rtype = mini_get_underlying_type (sig->ret);
1277 ret_type = type_to_llvm_type (ctx, rtype);
1278 if (!ctx_ok (ctx))
1279 return NULL;
1281 switch (cinfo->ret.storage) {
1282 case LLVMArgVtypeInReg:
1283 /* LLVM models this by returning an aggregate value */
1284 if (cinfo->ret.pair_storage [0] == LLVMArgInIReg && cinfo->ret.pair_storage [1] == LLVMArgNone) {
1285 LLVMTypeRef members [2];
1287 members [0] = IntPtrType ();
1288 ret_type = LLVMStructType (members, 1, FALSE);
1289 } else if (cinfo->ret.pair_storage [0] == LLVMArgNone && cinfo->ret.pair_storage [1] == LLVMArgNone) {
1290 /* Empty struct */
1291 ret_type = LLVMVoidType ();
1292 } else if (cinfo->ret.pair_storage [0] == LLVMArgInIReg && cinfo->ret.pair_storage [1] == LLVMArgInIReg) {
1293 LLVMTypeRef members [2];
1295 members [0] = IntPtrType ();
1296 members [1] = IntPtrType ();
1297 ret_type = LLVMStructType (members, 2, FALSE);
1298 } else {
1299 g_assert_not_reached ();
1301 break;
1302 case LLVMArgVtypeByVal:
1303 /* Vtype returned normally by val */
1304 break;
1305 case LLVMArgVtypeAsScalar: {
1306 int size = mono_class_value_size (mono_class_from_mono_type (rtype), NULL);
1307 /* LLVM models this by returning an int */
1308 if (size < SIZEOF_VOID_P) {
1309 g_assert (cinfo->ret.nslots == 1);
1310 ret_type = LLVMIntType (size * 8);
1311 } else {
1312 g_assert (cinfo->ret.nslots == 1 || cinfo->ret.nslots == 2);
1313 ret_type = LLVMIntType (cinfo->ret.nslots * sizeof (mgreg_t) * 8);
1315 break;
1317 case LLVMArgAsIArgs:
1318 ret_type = LLVMArrayType (IntPtrType (), cinfo->ret.nslots);
1319 break;
1320 case LLVMArgFpStruct: {
1321 /* Vtype returned as a fp struct */
1322 LLVMTypeRef members [16];
1324 /* Have to create our own structure since we don't map fp structures to LLVM fp structures yet */
1325 for (i = 0; i < cinfo->ret.nslots; ++i)
1326 members [i] = cinfo->ret.esize == 8 ? LLVMDoubleType () : LLVMFloatType ();
1327 ret_type = LLVMStructType (members, cinfo->ret.nslots, FALSE);
1328 break;
1330 case LLVMArgVtypeByRef:
1331 /* Vtype returned using a hidden argument */
1332 ret_type = LLVMVoidType ();
1333 break;
1334 case LLVMArgVtypeRetAddr:
1335 case LLVMArgGsharedvtFixed:
1336 case LLVMArgGsharedvtFixedVtype:
1337 case LLVMArgGsharedvtVariable:
1338 vretaddr = TRUE;
1339 ret_type = LLVMVoidType ();
1340 break;
1341 default:
1342 break;
1345 param_types = g_new0 (LLVMTypeRef, (sig->param_count * 8) + 3);
1346 pindex = 0;
1347 if (cinfo->ret.storage == LLVMArgVtypeByRef) {
1349 * Has to be the first argument because of the sret argument attribute
1350 * FIXME: This might conflict with passing 'this' as the first argument, but
1351 * this is only used on arm64 which has a dedicated struct return register.
1353 cinfo->vret_arg_pindex = pindex;
1354 param_types [pindex] = type_to_llvm_arg_type (ctx, sig->ret);
1355 if (!ctx_ok (ctx)) {
1356 g_free (param_types);
1357 return NULL;
1359 param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
1360 pindex ++;
1362 if (!ctx->llvm_only && cinfo->rgctx_arg) {
1363 cinfo->rgctx_arg_pindex = pindex;
1364 param_types [pindex] = ctx->module->ptr_type;
1365 pindex ++;
1367 if (cinfo->imt_arg) {
1368 cinfo->imt_arg_pindex = pindex;
1369 param_types [pindex] = ctx->module->ptr_type;
1370 pindex ++;
1372 if (vretaddr) {
1373 /* Compute the index in the LLVM signature where the vret arg needs to be passed */
1374 vret_arg_pindex = pindex;
1375 if (cinfo->vret_arg_index == 1) {
1376 /* Add the slots consumed by the first argument */
1377 LLVMArgInfo *ainfo = &cinfo->args [0];
1378 switch (ainfo->storage) {
1379 case LLVMArgVtypeInReg:
1380 for (j = 0; j < 2; ++j) {
1381 if (ainfo->pair_storage [j] == LLVMArgInIReg)
1382 vret_arg_pindex ++;
1384 break;
1385 default:
1386 vret_arg_pindex ++;
1390 cinfo->vret_arg_pindex = vret_arg_pindex;
1393 if (vretaddr && vret_arg_pindex == pindex)
1394 param_types [pindex ++] = IntPtrType ();
1395 if (sig->hasthis) {
1396 cinfo->this_arg_pindex = pindex;
1397 param_types [pindex ++] = ThisType ();
1398 cinfo->args [0].pindex = cinfo->this_arg_pindex;
1400 if (vretaddr && vret_arg_pindex == pindex)
1401 param_types [pindex ++] = IntPtrType ();
1402 for (i = 0; i < sig->param_count; ++i) {
1403 LLVMArgInfo *ainfo = &cinfo->args [i + sig->hasthis];
1405 if (vretaddr && vret_arg_pindex == pindex)
1406 param_types [pindex ++] = IntPtrType ();
1407 ainfo->pindex = pindex;
1409 switch (ainfo->storage) {
1410 case LLVMArgVtypeInReg:
1411 for (j = 0; j < 2; ++j) {
1412 switch (ainfo->pair_storage [j]) {
1413 case LLVMArgInIReg:
1414 param_types [pindex ++] = LLVMIntType (sizeof (gpointer) * 8);
1415 break;
1416 case LLVMArgNone:
1417 break;
1418 default:
1419 g_assert_not_reached ();
1422 break;
1423 case LLVMArgVtypeByVal:
1424 param_types [pindex] = type_to_llvm_arg_type (ctx, ainfo->type);
1425 if (!ctx_ok (ctx))
1426 break;
1427 param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
1428 pindex ++;
1429 break;
1430 case LLVMArgAsIArgs:
1431 param_types [pindex] = LLVMArrayType (IntPtrType (), ainfo->nslots);
1432 pindex ++;
1433 break;
1434 case LLVMArgVtypeByRef:
1435 param_types [pindex] = type_to_llvm_arg_type (ctx, ainfo->type);
1436 if (!ctx_ok (ctx))
1437 break;
1438 param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
1439 pindex ++;
1440 break;
1441 case LLVMArgAsFpArgs: {
1442 int j;
1444 /* Emit dummy fp arguments if needed so the rest is passed on the stack */
1445 for (j = 0; j < ainfo->ndummy_fpargs; ++j)
1446 param_types [pindex ++] = LLVMDoubleType ();
1447 for (j = 0; j < ainfo->nslots; ++j)
1448 param_types [pindex ++] = ainfo->esize == 8 ? LLVMDoubleType () : LLVMFloatType ();
1449 break;
1451 case LLVMArgVtypeAsScalar:
1452 g_assert_not_reached ();
1453 break;
1454 case LLVMArgGsharedvtFixed:
1455 case LLVMArgGsharedvtFixedVtype:
1456 param_types [pindex ++] = LLVMPointerType (type_to_llvm_arg_type (ctx, ainfo->type), 0);
1457 break;
1458 case LLVMArgGsharedvtVariable:
1459 param_types [pindex ++] = LLVMPointerType (IntPtrType (), 0);
1460 break;
1461 default:
1462 param_types [pindex ++] = type_to_llvm_arg_type (ctx, ainfo->type);
1463 break;
1466 if (!ctx_ok (ctx)) {
1467 g_free (param_types);
1468 return NULL;
1470 if (vretaddr && vret_arg_pindex == pindex)
1471 param_types [pindex ++] = IntPtrType ();
1472 if (ctx->llvm_only && cinfo->rgctx_arg) {
1473 /* Pass the rgctx as the last argument */
1474 cinfo->rgctx_arg_pindex = pindex;
1475 param_types [pindex] = ctx->module->ptr_type;
1476 pindex ++;
1479 res = LLVMFunctionType (ret_type, param_types, pindex, FALSE);
1480 g_free (param_types);
1482 return res;
1485 static LLVMTypeRef
1486 sig_to_llvm_sig (EmitContext *ctx, MonoMethodSignature *sig)
1488 return sig_to_llvm_sig_full (ctx, sig, NULL);
1492 * LLVMFunctionType1:
1494 * Create an LLVM function type from the arguments.
1496 static G_GNUC_UNUSED LLVMTypeRef
1497 LLVMFunctionType0 (LLVMTypeRef ReturnType,
1498 int IsVarArg)
1500 return LLVMFunctionType (ReturnType, NULL, 0, IsVarArg);
1504 * LLVMFunctionType1:
1506 * Create an LLVM function type from the arguments.
1508 static G_GNUC_UNUSED LLVMTypeRef
1509 LLVMFunctionType1 (LLVMTypeRef ReturnType,
1510 LLVMTypeRef ParamType1,
1511 int IsVarArg)
1513 LLVMTypeRef param_types [1];
1515 param_types [0] = ParamType1;
1517 return LLVMFunctionType (ReturnType, param_types, 1, IsVarArg);
1521 * LLVMFunctionType2:
1523 * Create an LLVM function type from the arguments.
1525 static G_GNUC_UNUSED LLVMTypeRef
1526 LLVMFunctionType2 (LLVMTypeRef ReturnType,
1527 LLVMTypeRef ParamType1,
1528 LLVMTypeRef ParamType2,
1529 int IsVarArg)
1531 LLVMTypeRef param_types [2];
1533 param_types [0] = ParamType1;
1534 param_types [1] = ParamType2;
1536 return LLVMFunctionType (ReturnType, param_types, 2, IsVarArg);
1540 * LLVMFunctionType3:
1542 * Create an LLVM function type from the arguments.
1544 static G_GNUC_UNUSED LLVMTypeRef
1545 LLVMFunctionType3 (LLVMTypeRef ReturnType,
1546 LLVMTypeRef ParamType1,
1547 LLVMTypeRef ParamType2,
1548 LLVMTypeRef ParamType3,
1549 int IsVarArg)
1551 LLVMTypeRef param_types [3];
1553 param_types [0] = ParamType1;
1554 param_types [1] = ParamType2;
1555 param_types [2] = ParamType3;
1557 return LLVMFunctionType (ReturnType, param_types, 3, IsVarArg);
1560 static G_GNUC_UNUSED LLVMTypeRef
1561 LLVMFunctionType5 (LLVMTypeRef ReturnType,
1562 LLVMTypeRef ParamType1,
1563 LLVMTypeRef ParamType2,
1564 LLVMTypeRef ParamType3,
1565 LLVMTypeRef ParamType4,
1566 LLVMTypeRef ParamType5,
1567 int IsVarArg)
1569 LLVMTypeRef param_types [5];
1571 param_types [0] = ParamType1;
1572 param_types [1] = ParamType2;
1573 param_types [2] = ParamType3;
1574 param_types [3] = ParamType4;
1575 param_types [4] = ParamType5;
1577 return LLVMFunctionType (ReturnType, param_types, 5, IsVarArg);
1581 * create_builder:
1583 * Create an LLVM builder and remember it so it can be freed later.
1585 static LLVMBuilderRef
1586 create_builder (EmitContext *ctx)
1588 LLVMBuilderRef builder = LLVMCreateBuilder ();
1590 ctx->builders = g_slist_prepend_mempool (ctx->cfg->mempool, ctx->builders, builder);
1592 return builder;
1595 static char*
1596 get_aotconst_name (MonoJumpInfoType type, gconstpointer data, int got_offset)
1598 char *name;
1600 switch (type) {
1601 case MONO_PATCH_INFO_INTERNAL_METHOD:
1602 name = g_strdup_printf ("jit_icall_%s", data);
1603 break;
1604 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1605 MonoJumpInfoRgctxEntry *entry = (MonoJumpInfoRgctxEntry*)data;
1606 name = g_strdup_printf ("RGCTX_SLOT_INDEX_%s", mono_rgctx_info_type_to_str (entry->info_type));
1607 break;
1609 default:
1610 name = g_strdup_printf ("%s_%d", mono_ji_type_to_string (type), got_offset);
1611 break;
1614 return name;
1617 static LLVMValueRef
1618 get_aotconst_typed (EmitContext *ctx, MonoJumpInfoType type, gconstpointer data, LLVMTypeRef llvm_type)
1620 MonoCompile *cfg;
1621 guint32 got_offset;
1622 LLVMValueRef indexes [2];
1623 LLVMValueRef got_entry_addr, load;
1624 LLVMBuilderRef builder = ctx->builder;
1625 char *name = NULL;
1627 cfg = ctx->cfg;
1629 MonoJumpInfo tmp_ji;
1630 tmp_ji.type = type;
1631 tmp_ji.data.target = data;
1633 MonoJumpInfo *ji = mono_aot_patch_info_dup (&tmp_ji);
1635 ji->next = cfg->patch_info;
1636 cfg->patch_info = ji;
1638 got_offset = mono_aot_get_got_offset (cfg->patch_info);
1639 ctx->module->max_got_offset = MAX (ctx->module->max_got_offset, got_offset);
1641 * If the got slot is shared, it means its initialized when the aot image is loaded, so we don't need to
1642 * explicitly initialize it.
1644 if (!mono_aot_is_shared_got_offset (got_offset)) {
1645 //mono_print_ji (ji);
1646 //printf ("\n");
1647 ctx->has_got_access = TRUE;
1650 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
1651 indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
1652 got_entry_addr = LLVMBuildGEP (builder, ctx->module->got_var, indexes, 2, "");
1654 name = get_aotconst_name (type, data, got_offset);
1655 if (llvm_type) {
1656 load = LLVMBuildLoad (builder, got_entry_addr, "");
1657 load = convert (ctx, load, llvm_type);
1658 LLVMSetValueName (load, name ? name : "");
1659 } else {
1660 load = LLVMBuildLoad (builder, got_entry_addr, name ? name : "");
1662 g_free (name);
1663 //set_invariant_load_flag (load);
1665 return load;
1668 static LLVMValueRef
1669 get_aotconst (EmitContext *ctx, MonoJumpInfoType type, gconstpointer data)
1671 return get_aotconst_typed (ctx, type, data, NULL);
1674 static LLVMValueRef
1675 get_callee (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gconstpointer data)
1677 LLVMValueRef callee;
1678 char *callee_name;
1679 if (ctx->llvm_only) {
1680 callee_name = mono_aot_get_direct_call_symbol (type, data);
1681 if (callee_name) {
1682 /* Directly callable */
1683 // FIXME: Locking
1684 callee = (LLVMValueRef)g_hash_table_lookup (ctx->module->direct_callables, callee_name);
1685 if (!callee) {
1686 callee = LLVMAddFunction (ctx->lmodule, callee_name, llvm_sig);
1688 LLVMSetVisibility (callee, LLVMHiddenVisibility);
1690 g_hash_table_insert (ctx->module->direct_callables, (char*)callee_name, callee);
1691 } else {
1692 /* LLVMTypeRef's are uniqued */
1693 if (LLVMGetElementType (LLVMTypeOf (callee)) != llvm_sig)
1694 return LLVMConstBitCast (callee, LLVMPointerType (llvm_sig, 0));
1696 g_free (callee_name);
1698 return callee;
1702 * Calls are made through the GOT.
1704 return get_aotconst_typed (ctx, type, data, LLVMPointerType (llvm_sig, 0));
1705 } else {
1706 MonoJumpInfo *ji = NULL;
1708 callee_name = mono_aot_get_plt_symbol (type, data);
1709 if (!callee_name)
1710 return NULL;
1712 if (ctx->cfg->compile_aot)
1713 /* Add a patch so referenced wrappers can be compiled in full aot mode */
1714 mono_add_patch_info (ctx->cfg, 0, type, data);
1716 // FIXME: Locking
1717 callee = (LLVMValueRef)g_hash_table_lookup (ctx->module->plt_entries, callee_name);
1718 if (!callee) {
1719 callee = LLVMAddFunction (ctx->lmodule, callee_name, llvm_sig);
1721 LLVMSetVisibility (callee, LLVMHiddenVisibility);
1723 g_hash_table_insert (ctx->module->plt_entries, (char*)callee_name, callee);
1726 if (ctx->cfg->compile_aot) {
1727 ji = g_new0 (MonoJumpInfo, 1);
1728 ji->type = type;
1729 ji->data.target = data;
1731 g_hash_table_insert (ctx->module->plt_entries_ji, ji, callee);
1734 return callee;
1738 static LLVMValueRef
1739 emit_jit_callee (EmitContext *ctx, const char *name, LLVMTypeRef llvm_sig, gpointer target)
1741 #if LLVM_API_VERSION > 100
1742 LLVMValueRef tramp_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (llvm_sig, 0), name);
1743 LLVMSetInitializer (tramp_var, LLVMConstIntToPtr (LLVMConstInt (LLVMInt64Type (), (guint64)(size_t)target, FALSE), LLVMPointerType (llvm_sig, 0)));
1744 LLVMSetLinkage (tramp_var, LLVMExternalLinkage);
1745 LLVMValueRef callee = LLVMBuildLoad (ctx->builder, tramp_var, "");
1746 return callee;
1747 #else
1748 LLVMValueRef callee = LLVMAddFunction (ctx->lmodule, "", llvm_sig);
1749 LLVMAddGlobalMapping (ctx->module->ee, callee, target);
1750 return callee;
1751 #endif
1754 static int
1755 get_handler_clause (MonoCompile *cfg, MonoBasicBlock *bb)
1757 MonoMethodHeader *header = cfg->header;
1758 MonoExceptionClause *clause;
1759 int i;
1761 /* Directly */
1762 if (bb->region != -1 && MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY))
1763 return (bb->region >> 8) - 1;
1765 /* Indirectly */
1766 for (i = 0; i < header->num_clauses; ++i) {
1767 clause = &header->clauses [i];
1769 if (MONO_OFFSET_IN_CLAUSE (clause, bb->real_offset) && clause->flags == MONO_EXCEPTION_CLAUSE_NONE)
1770 return i;
1773 return -1;
1776 static MonoExceptionClause *
1777 get_most_deep_clause (MonoCompile *cfg, EmitContext *ctx, MonoBasicBlock *bb)
1779 if (bb == cfg->bb_init)
1780 return NULL;
1781 // Since they're sorted by nesting we just need
1782 // the first one that the bb is a member of
1783 for (int i = 0; i < cfg->header->num_clauses; i++) {
1784 MonoExceptionClause *curr = &cfg->header->clauses [i];
1786 if (MONO_OFFSET_IN_CLAUSE (curr, bb->real_offset))
1787 return curr;
1790 return NULL;
1793 static void
1794 set_metadata_flag (LLVMValueRef v, const char *flag_name)
1796 LLVMValueRef md_arg;
1797 int md_kind;
1799 md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
1800 md_arg = LLVMMDString ("mono", 4);
1801 LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
1804 static void
1805 set_invariant_load_flag (LLVMValueRef v)
1807 LLVMValueRef md_arg;
1808 int md_kind;
1809 const char *flag_name;
1811 // FIXME: Cache this
1812 flag_name = "invariant.load";
1813 md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
1814 md_arg = LLVMMDString ("<index>", strlen ("<index>"));
1815 LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
1819 * emit_call:
1821 * Emit an LLVM call or invoke instruction depending on whenever the call is inside
1822 * a try region.
1824 static LLVMValueRef
1825 emit_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, LLVMValueRef callee, LLVMValueRef *args, int pindex)
1827 MonoCompile *cfg = ctx->cfg;
1828 LLVMValueRef lcall = NULL;
1829 LLVMBuilderRef builder = *builder_ref;
1830 MonoExceptionClause *clause;
1832 if (ctx->llvm_only) {
1833 clause = get_most_deep_clause (cfg, ctx, bb);
1835 if (clause) {
1836 g_assert (clause->flags == MONO_EXCEPTION_CLAUSE_NONE || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY);
1839 * Have to use an invoke instead of a call, branching to the
1840 * handler bblock of the clause containing this bblock.
1842 intptr_t key = CLAUSE_END(clause);
1844 LLVMBasicBlockRef lpad_bb = (LLVMBasicBlockRef)g_hash_table_lookup (ctx->exc_meta, (gconstpointer)key);
1846 // FIXME: Find the one that has the lowest end bound for the right start address
1847 // FIXME: Finally + nesting
1849 if (lpad_bb) {
1850 LLVMBasicBlockRef noex_bb = gen_bb (ctx, "CALL_NOEX_BB");
1852 /* Use an invoke */
1853 lcall = LLVMBuildInvoke (builder, callee, args, pindex, noex_bb, lpad_bb, "");
1855 builder = ctx->builder = create_builder (ctx);
1856 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
1858 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
1861 } else {
1862 int clause_index = get_handler_clause (cfg, bb);
1864 if (clause_index != -1) {
1865 MonoMethodHeader *header = cfg->header;
1866 MonoExceptionClause *ec = &header->clauses [clause_index];
1867 MonoBasicBlock *tblock;
1868 LLVMBasicBlockRef ex_bb, noex_bb;
1871 * Have to use an invoke instead of a call, branching to the
1872 * handler bblock of the clause containing this bblock.
1875 g_assert (ec->flags == MONO_EXCEPTION_CLAUSE_NONE || ec->flags == MONO_EXCEPTION_CLAUSE_FINALLY);
1877 tblock = cfg->cil_offset_to_bb [ec->handler_offset];
1878 g_assert (tblock);
1880 ctx->bblocks [tblock->block_num].invoke_target = TRUE;
1882 ex_bb = get_bb (ctx, tblock);
1884 noex_bb = gen_bb (ctx, "NOEX_BB");
1886 /* Use an invoke */
1887 lcall = LLVMBuildInvoke (builder, callee, args, pindex, noex_bb, ex_bb, "");
1889 builder = ctx->builder = create_builder (ctx);
1890 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
1892 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
1896 if (!lcall) {
1897 lcall = LLVMBuildCall (builder, callee, args, pindex, "");
1898 ctx->builder = builder;
1901 if (builder_ref)
1902 *builder_ref = ctx->builder;
1904 return lcall;
1907 static LLVMValueRef
1908 emit_load_general (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef addr, LLVMValueRef base, const char *name, gboolean is_faulting, BarrierKind barrier)
1910 const char *intrins_name;
1911 LLVMValueRef args [16], res;
1912 LLVMTypeRef addr_type;
1913 gboolean use_intrinsics = TRUE;
1915 #if LLVM_API_VERSION > 100
1916 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only) {
1917 /* The llvm.mono.load/store intrinsics are not supported by this llvm version, emit an explicit null check instead */
1918 LLVMValueRef cmp;
1920 cmp = LLVMBuildICmp (*builder_ref, LLVMIntEQ, base, LLVMConstNull (LLVMTypeOf (base)), "");
1921 emit_cond_system_exception (ctx, bb, "NullReferenceException", cmp);
1922 *builder_ref = ctx->builder;
1923 use_intrinsics = FALSE;
1925 #endif
1927 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only && use_intrinsics) {
1928 LLVMAtomicOrdering ordering;
1930 switch (barrier) {
1931 case LLVM_BARRIER_NONE:
1932 ordering = LLVMAtomicOrderingNotAtomic;
1933 break;
1934 case LLVM_BARRIER_ACQ:
1935 ordering = LLVMAtomicOrderingAcquire;
1936 break;
1937 case LLVM_BARRIER_SEQ:
1938 ordering = LLVMAtomicOrderingSequentiallyConsistent;
1939 break;
1940 default:
1941 g_assert_not_reached ();
1942 break;
1946 * We handle loads which can fault by calling a mono specific intrinsic
1947 * using an invoke, so they are handled properly inside try blocks.
1948 * We can't use this outside clauses, since LLVM optimizes intrinsics which
1949 * are marked with IntrReadArgMem.
1951 switch (size) {
1952 case 1:
1953 intrins_name = "llvm.mono.load.i8.p0i8";
1954 break;
1955 case 2:
1956 intrins_name = "llvm.mono.load.i16.p0i16";
1957 break;
1958 case 4:
1959 intrins_name = "llvm.mono.load.i32.p0i32";
1960 break;
1961 case 8:
1962 intrins_name = "llvm.mono.load.i64.p0i64";
1963 break;
1964 default:
1965 g_assert_not_reached ();
1968 addr_type = LLVMTypeOf (addr);
1969 if (addr_type == LLVMPointerType (LLVMDoubleType (), 0) || addr_type == LLVMPointerType (LLVMFloatType (), 0))
1970 addr = LLVMBuildBitCast (*builder_ref, addr, LLVMPointerType (LLVMIntType (size * 8), 0), "");
1972 args [0] = addr;
1973 args [1] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
1974 args [2] = LLVMConstInt (LLVMInt1Type (), TRUE, FALSE);
1975 args [3] = LLVMConstInt (LLVMInt32Type (), ordering, FALSE);
1976 res = emit_call (ctx, bb, builder_ref, get_intrinsic (ctx, intrins_name), args, 4);
1978 if (addr_type == LLVMPointerType (LLVMDoubleType (), 0))
1979 res = LLVMBuildBitCast (*builder_ref, res, LLVMDoubleType (), "");
1980 else if (addr_type == LLVMPointerType (LLVMFloatType (), 0))
1981 res = LLVMBuildBitCast (*builder_ref, res, LLVMFloatType (), "");
1983 return res;
1984 } else {
1985 LLVMValueRef res;
1988 * We emit volatile loads for loads which can fault, because otherwise
1989 * LLVM will generate invalid code when encountering a load from a
1990 * NULL address.
1992 if (barrier != LLVM_BARRIER_NONE)
1993 res = mono_llvm_build_atomic_load (*builder_ref, addr, name, is_faulting, size, barrier);
1994 else
1995 res = mono_llvm_build_load (*builder_ref, addr, name, is_faulting);
1997 /* Mark it with a custom metadata */
1999 if (is_faulting)
2000 set_metadata_flag (res, "mono.faulting.load");
2003 return res;
2007 static LLVMValueRef
2008 emit_load (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef addr, const char *name, gboolean is_faulting)
2010 return emit_load_general (ctx, bb, builder_ref, size, addr, addr, name, is_faulting, LLVM_BARRIER_NONE);
2013 static void
2014 emit_store_general (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef value, LLVMValueRef addr, LLVMValueRef base, gboolean is_faulting, BarrierKind barrier)
2016 const char *intrins_name;
2017 LLVMValueRef args [16];
2018 gboolean use_intrinsics = TRUE;
2020 #if LLVM_API_VERSION > 100
2021 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only) {
2022 /* The llvm.mono.load/store intrinsics are not supported by this llvm version, emit an explicit null check instead */
2023 LLVMValueRef cmp = LLVMBuildICmp (*builder_ref, LLVMIntEQ, base, LLVMConstNull (LLVMTypeOf (base)), "");
2024 emit_cond_system_exception (ctx, bb, "NullReferenceException", cmp);
2025 *builder_ref = ctx->builder;
2026 use_intrinsics = FALSE;
2028 #endif
2030 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only && use_intrinsics) {
2031 LLVMAtomicOrdering ordering;
2033 switch (barrier) {
2034 case LLVM_BARRIER_NONE:
2035 ordering = LLVMAtomicOrderingNotAtomic;
2036 break;
2037 case LLVM_BARRIER_REL:
2038 ordering = LLVMAtomicOrderingRelease;
2039 break;
2040 case LLVM_BARRIER_SEQ:
2041 ordering = LLVMAtomicOrderingSequentiallyConsistent;
2042 break;
2043 default:
2044 g_assert_not_reached ();
2045 break;
2048 switch (size) {
2049 case 1:
2050 intrins_name = "llvm.mono.store.i8.p0i8";
2051 break;
2052 case 2:
2053 intrins_name = "llvm.mono.store.i16.p0i16";
2054 break;
2055 case 4:
2056 intrins_name = "llvm.mono.store.i32.p0i32";
2057 break;
2058 case 8:
2059 intrins_name = "llvm.mono.store.i64.p0i64";
2060 break;
2061 default:
2062 g_assert_not_reached ();
2065 if (LLVMTypeOf (value) == LLVMDoubleType () || LLVMTypeOf (value) == LLVMFloatType ()) {
2066 value = LLVMBuildBitCast (*builder_ref, value, LLVMIntType (size * 8), "");
2067 addr = LLVMBuildBitCast (*builder_ref, addr, LLVMPointerType (LLVMIntType (size * 8), 0), "");
2070 args [0] = value;
2071 args [1] = addr;
2072 args [2] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2073 args [3] = LLVMConstInt (LLVMInt1Type (), TRUE, FALSE);
2074 args [4] = LLVMConstInt (LLVMInt32Type (), ordering, FALSE);
2075 emit_call (ctx, bb, builder_ref, get_intrinsic (ctx, intrins_name), args, 5);
2076 } else {
2077 if (barrier != LLVM_BARRIER_NONE)
2078 mono_llvm_build_aligned_store (*builder_ref, value, addr, barrier, size);
2079 else
2080 mono_llvm_build_store (*builder_ref, value, addr, is_faulting, barrier);
2084 static void
2085 emit_store (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef value, LLVMValueRef addr, LLVMValueRef base, gboolean is_faulting)
2087 emit_store_general (ctx, bb, builder_ref, size, value, addr, base, is_faulting, LLVM_BARRIER_NONE);
2091 * emit_cond_system_exception:
2093 * Emit code to throw the exception EXC_TYPE if the condition CMP is false.
2094 * Might set the ctx exception.
2096 static void
2097 emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *exc_type, LLVMValueRef cmp)
2099 LLVMBasicBlockRef ex_bb, ex2_bb = NULL, noex_bb;
2100 LLVMBuilderRef builder;
2101 MonoClass *exc_class;
2102 LLVMValueRef args [2];
2103 LLVMValueRef callee;
2104 gboolean no_pc = FALSE;
2106 if (IS_TARGET_AMD64)
2107 /* Some platforms don't require the pc argument */
2108 no_pc = TRUE;
2110 ex_bb = gen_bb (ctx, "EX_BB");
2111 if (ctx->llvm_only)
2112 ex2_bb = gen_bb (ctx, "EX2_BB");
2113 noex_bb = gen_bb (ctx, "NOEX_BB");
2115 LLVMBuildCondBr (ctx->builder, cmp, ex_bb, noex_bb);
2117 exc_class = mono_class_load_from_name (mono_get_corlib (), "System", exc_type);
2119 /* Emit exception throwing code */
2120 ctx->builder = builder = create_builder (ctx);
2121 LLVMPositionBuilderAtEnd (builder, ex_bb);
2123 if (ctx->cfg->llvm_only) {
2124 static LLVMTypeRef sig;
2126 if (!sig)
2127 sig = LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE);
2128 callee = get_callee (ctx, sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_llvm_throw_corlib_exception");
2130 LLVMBuildBr (builder, ex2_bb);
2132 ctx->builder = builder = create_builder (ctx);
2133 LLVMPositionBuilderAtEnd (ctx->builder, ex2_bb);
2135 args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE);
2136 emit_call (ctx, bb, &builder, callee, args, 1);
2137 LLVMBuildUnreachable (builder);
2139 ctx->builder = builder = create_builder (ctx);
2140 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
2142 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
2144 ctx->ex_index ++;
2145 return;
2148 callee = ctx->module->throw_corlib_exception;
2149 if (!callee) {
2150 LLVMTypeRef sig;
2151 const char *icall_name;
2153 if (no_pc)
2154 sig = LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE);
2155 else
2156 sig = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), LLVMPointerType (LLVMInt8Type (), 0), FALSE);
2157 icall_name = "llvm_throw_corlib_exception_abs_trampoline";
2159 if (ctx->cfg->compile_aot) {
2160 callee = get_callee (ctx, sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
2161 } else {
2163 * Differences between the LLVM/non-LLVM throw corlib exception trampoline:
2164 * - On x86, LLVM generated code doesn't push the arguments
2165 * - The trampoline takes the throw address as an arguments, not a pc offset.
2167 gpointer target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
2168 callee = emit_jit_callee (ctx, "llvm_throw_corlib_exception_trampoline", sig, target);
2170 #if LLVM_API_VERSION > 100
2172 * Make sure that ex_bb starts with the invoke, so the block address points to it, and not to the load
2173 * added by emit_jit_callee ().
2175 ex2_bb = gen_bb (ctx, "EX2_BB");
2176 LLVMBuildBr (builder, ex2_bb);
2177 ex_bb = ex2_bb;
2179 ctx->builder = builder = create_builder (ctx);
2180 LLVMPositionBuilderAtEnd (ctx->builder, ex2_bb);
2181 #else
2182 mono_memory_barrier ();
2183 ctx->module->throw_corlib_exception = callee;
2184 #endif
2188 args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE);
2191 * The LLVM mono branch contains changes so a block address can be passed as an
2192 * argument to a call.
2194 if (no_pc) {
2195 emit_call (ctx, bb, &builder, callee, args, 1);
2196 } else {
2197 args [1] = LLVMBlockAddress (ctx->lmethod, ex_bb);
2198 emit_call (ctx, bb, &builder, callee, args, 2);
2201 LLVMBuildUnreachable (builder);
2203 ctx->builder = builder = create_builder (ctx);
2204 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
2206 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
2208 ctx->ex_index ++;
2209 return;
2213 * emit_args_to_vtype:
2215 * Emit code to store the vtype in the arguments args to the address ADDRESS.
2217 static void
2218 emit_args_to_vtype (EmitContext *ctx, LLVMBuilderRef builder, MonoType *t, LLVMValueRef address, LLVMArgInfo *ainfo, LLVMValueRef *args)
2220 int j, size, nslots;
2222 size = mono_class_value_size (mono_class_from_mono_type (t), NULL);
2224 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (t))) {
2225 address = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (LLVMInt8Type (), 0), "");
2228 if (ainfo->storage == LLVMArgAsFpArgs)
2229 nslots = ainfo->nslots;
2230 else
2231 nslots = 2;
2233 for (j = 0; j < nslots; ++j) {
2234 LLVMValueRef index [2], addr, daddr;
2235 int part_size = size > sizeof (gpointer) ? sizeof (gpointer) : size;
2236 LLVMTypeRef part_type;
2238 while (part_size != 1 && part_size != 2 && part_size != 4 && part_size < 8)
2239 part_size ++;
2241 if (ainfo->pair_storage [j] == LLVMArgNone)
2242 continue;
2244 switch (ainfo->pair_storage [j]) {
2245 case LLVMArgInIReg: {
2246 part_type = LLVMIntType (part_size * 8);
2247 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (t))) {
2248 index [0] = LLVMConstInt (LLVMInt32Type (), j * sizeof (gpointer), FALSE);
2249 addr = LLVMBuildGEP (builder, address, index, 1, "");
2250 } else {
2251 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (IntPtrType (), 0), "");
2252 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2253 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2255 LLVMBuildStore (builder, convert (ctx, args [j], part_type), LLVMBuildBitCast (ctx->builder, addr, LLVMPointerType (part_type, 0), ""));
2256 break;
2258 case LLVMArgInFPReg: {
2259 LLVMTypeRef arg_type;
2261 if (ainfo->esize == 8)
2262 arg_type = LLVMDoubleType ();
2263 else
2264 arg_type = LLVMFloatType ();
2266 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2267 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (arg_type, 0), "");
2268 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2269 LLVMBuildStore (builder, args [j], addr);
2270 break;
2272 case LLVMArgNone:
2273 break;
2274 default:
2275 g_assert_not_reached ();
2278 size -= sizeof (gpointer);
2283 * emit_vtype_to_args:
2285 * Emit code to load a vtype at address ADDRESS into scalar arguments. Store the arguments
2286 * into ARGS, and the number of arguments into NARGS.
2288 static void
2289 emit_vtype_to_args (EmitContext *ctx, LLVMBuilderRef builder, MonoType *t, LLVMValueRef address, LLVMArgInfo *ainfo, LLVMValueRef *args, guint32 *nargs)
2291 int pindex = 0;
2292 int j, size, nslots;
2293 LLVMTypeRef arg_type;
2295 size = get_vtype_size (t);
2297 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (t)))
2298 address = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (LLVMInt8Type (), 0), "");
2300 if (ainfo->storage == LLVMArgAsFpArgs)
2301 nslots = ainfo->nslots;
2302 else
2303 nslots = 2;
2304 for (j = 0; j < nslots; ++j) {
2305 LLVMValueRef index [2], addr, daddr;
2306 int partsize = size > sizeof (gpointer) ? sizeof (gpointer) : size;
2308 if (ainfo->pair_storage [j] == LLVMArgNone)
2309 continue;
2311 switch (ainfo->pair_storage [j]) {
2312 case LLVMArgInIReg:
2313 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (t))) {
2314 index [0] = LLVMConstInt (LLVMInt32Type (), j * sizeof (gpointer), FALSE);
2315 addr = LLVMBuildGEP (builder, address, index, 1, "");
2316 } else {
2317 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (IntPtrType (), 0), "");
2318 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2319 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2321 args [pindex ++] = convert (ctx, LLVMBuildLoad (builder, LLVMBuildBitCast (ctx->builder, addr, LLVMPointerType (LLVMIntType (partsize * 8), 0), ""), ""), IntPtrType ());
2322 break;
2323 case LLVMArgInFPReg:
2324 if (ainfo->esize == 8)
2325 arg_type = LLVMDoubleType ();
2326 else
2327 arg_type = LLVMFloatType ();
2328 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (arg_type, 0), "");
2329 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2330 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2331 args [pindex ++] = LLVMBuildLoad (builder, addr, "");
2332 break;
2333 case LLVMArgNone:
2334 break;
2335 default:
2336 g_assert_not_reached ();
2338 size -= sizeof (gpointer);
2341 *nargs = pindex;
2344 static LLVMValueRef
2345 build_alloca_llvm_type_name (EmitContext *ctx, LLVMTypeRef t, int align, const char *name)
2348 * Have to place all alloca's at the end of the entry bb, since otherwise they would
2349 * get executed every time control reaches them.
2351 LLVMPositionBuilder (ctx->alloca_builder, get_bb (ctx, ctx->cfg->bb_entry), ctx->last_alloca);
2353 ctx->last_alloca = mono_llvm_build_alloca (ctx->alloca_builder, t, NULL, align, name);
2354 return ctx->last_alloca;
2357 static LLVMValueRef
2358 build_alloca_llvm_type (EmitContext *ctx, LLVMTypeRef t, int align)
2360 return build_alloca_llvm_type_name (ctx, t, align, "");
2363 static LLVMValueRef
2364 build_alloca (EmitContext *ctx, MonoType *t)
2366 MonoClass *k = mono_class_from_mono_type (t);
2367 int align;
2369 g_assert (!mini_is_gsharedvt_variable_type (t));
2371 if (MONO_CLASS_IS_SIMD (ctx->cfg, k))
2372 align = 16;
2373 else
2374 align = mono_class_min_align (k);
2376 /* Sometimes align is not a power of 2 */
2377 while (mono_is_power_of_two (align) == -1)
2378 align ++;
2380 return build_alloca_llvm_type (ctx, type_to_llvm_type (ctx, t), align);
2383 static LLVMValueRef
2384 emit_gsharedvt_ldaddr (EmitContext *ctx, int vreg)
2387 * gsharedvt local.
2388 * Compute the address of the local as gsharedvt_locals_var + gsharedvt_info_var->locals_offsets [idx].
2390 MonoCompile *cfg = ctx->cfg;
2391 LLVMBuilderRef builder = ctx->builder;
2392 LLVMValueRef offset, offset_var;
2393 LLVMValueRef info_var = ctx->values [cfg->gsharedvt_info_var->dreg];
2394 LLVMValueRef locals_var = ctx->values [cfg->gsharedvt_locals_var->dreg];
2395 LLVMValueRef ptr;
2396 char *name;
2398 g_assert (info_var);
2399 g_assert (locals_var);
2401 int idx = cfg->gsharedvt_vreg_to_idx [vreg] - 1;
2403 offset = LLVMConstInt (LLVMInt32Type (), MONO_STRUCT_OFFSET (MonoGSharedVtMethodRuntimeInfo, entries) + (idx * sizeof (gpointer)), FALSE);
2404 ptr = LLVMBuildAdd (builder, convert (ctx, info_var, IntPtrType ()), convert (ctx, offset, IntPtrType ()), "");
2406 name = g_strdup_printf ("gsharedvt_local_%d_offset", vreg);
2407 offset_var = LLVMBuildLoad (builder, convert (ctx, ptr, LLVMPointerType (LLVMInt32Type (), 0)), name);
2409 return LLVMBuildAdd (builder, convert (ctx, locals_var, IntPtrType ()), convert (ctx, offset_var, IntPtrType ()), "");
2413 * Put the global into the 'llvm.used' array to prevent it from being optimized away.
2415 static void
2416 mark_as_used (MonoLLVMModule *module, LLVMValueRef global)
2418 if (!module->used)
2419 module->used = g_ptr_array_sized_new (16);
2420 g_ptr_array_add (module->used, global);
2423 static void
2424 emit_llvm_used (MonoLLVMModule *module)
2426 LLVMModuleRef lmodule = module->lmodule;
2427 LLVMTypeRef used_type;
2428 LLVMValueRef used, *used_elem;
2429 int i;
2431 if (!module->used)
2432 return;
2434 used_type = LLVMArrayType (LLVMPointerType (LLVMInt8Type (), 0), module->used->len);
2435 used = LLVMAddGlobal (lmodule, used_type, "llvm.used");
2436 used_elem = g_new0 (LLVMValueRef, module->used->len);
2437 for (i = 0; i < module->used->len; ++i)
2438 used_elem [i] = LLVMConstBitCast ((LLVMValueRef)g_ptr_array_index (module->used, i), LLVMPointerType (LLVMInt8Type (), 0));
2439 LLVMSetInitializer (used, LLVMConstArray (LLVMPointerType (LLVMInt8Type (), 0), used_elem, module->used->len));
2440 LLVMSetLinkage (used, LLVMAppendingLinkage);
2441 LLVMSetSection (used, "llvm.metadata");
2445 * emit_get_method:
2447 * Emit a function mapping method indexes to their code
2449 static void
2450 emit_get_method (MonoLLVMModule *module)
2452 LLVMModuleRef lmodule = module->lmodule;
2453 LLVMValueRef func, switch_ins, m;
2454 LLVMBasicBlockRef entry_bb, fail_bb, bb, code_start_bb, code_end_bb;
2455 LLVMBasicBlockRef *bbs;
2456 LLVMTypeRef rtype;
2457 LLVMBuilderRef builder = LLVMCreateBuilder ();
2458 char *name;
2459 int i;
2462 * Emit a switch statement. Emitting a table of function addresses is smaller/faster,
2463 * but generating code seems safer.
2465 rtype = LLVMPointerType (LLVMInt8Type (), 0);
2466 func = LLVMAddFunction (lmodule, module->get_method_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
2467 LLVMSetLinkage (func, LLVMExternalLinkage);
2468 LLVMSetVisibility (func, LLVMHiddenVisibility);
2469 LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
2470 module->get_method = func;
2472 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2475 * Return llvm_code_start/llvm_code_end when called with -1/-2.
2476 * Hopefully, the toolchain doesn't reorder these functions. If it does,
2477 * then we will have to find another solution.
2480 name = g_strdup_printf ("BB_CODE_START");
2481 code_start_bb = LLVMAppendBasicBlock (func, name);
2482 g_free (name);
2483 LLVMPositionBuilderAtEnd (builder, code_start_bb);
2484 LLVMBuildRet (builder, LLVMBuildBitCast (builder, module->code_start, rtype, ""));
2486 name = g_strdup_printf ("BB_CODE_END");
2487 code_end_bb = LLVMAppendBasicBlock (func, name);
2488 g_free (name);
2489 LLVMPositionBuilderAtEnd (builder, code_end_bb);
2490 LLVMBuildRet (builder, LLVMBuildBitCast (builder, module->code_end, rtype, ""));
2492 bbs = g_new0 (LLVMBasicBlockRef, module->max_method_idx + 1);
2493 for (i = 0; i < module->max_method_idx + 1; ++i) {
2494 name = g_strdup_printf ("BB_%d", i);
2495 bb = LLVMAppendBasicBlock (func, name);
2496 g_free (name);
2497 bbs [i] = bb;
2499 LLVMPositionBuilderAtEnd (builder, bb);
2501 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_lmethod, GINT_TO_POINTER (i));
2502 if (m)
2503 LLVMBuildRet (builder, LLVMBuildBitCast (builder, m, rtype, ""));
2504 else
2505 LLVMBuildRet (builder, LLVMConstNull (rtype));
2508 fail_bb = LLVMAppendBasicBlock (func, "FAIL");
2509 LLVMPositionBuilderAtEnd (builder, fail_bb);
2510 LLVMBuildRet (builder, LLVMConstNull (rtype));
2512 LLVMPositionBuilderAtEnd (builder, entry_bb);
2514 switch_ins = LLVMBuildSwitch (builder, LLVMGetParam (func, 0), fail_bb, 0);
2515 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), -1, FALSE), code_start_bb);
2516 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), -2, FALSE), code_end_bb);
2517 for (i = 0; i < module->max_method_idx + 1; ++i) {
2518 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i, FALSE), bbs [i]);
2521 mark_as_used (module, func);
2523 LLVMDisposeBuilder (builder);
2527 * emit_get_unbox_tramp:
2529 * Emit a function mapping method indexes to their unbox trampoline
2531 static void
2532 emit_get_unbox_tramp (MonoLLVMModule *module)
2534 LLVMModuleRef lmodule = module->lmodule;
2535 LLVMValueRef func, switch_ins, m;
2536 LLVMBasicBlockRef entry_bb, fail_bb, bb;
2537 LLVMBasicBlockRef *bbs;
2538 LLVMTypeRef rtype;
2539 LLVMBuilderRef builder = LLVMCreateBuilder ();
2540 char *name;
2541 int i;
2543 /* Similar to emit_get_method () */
2545 rtype = LLVMPointerType (LLVMInt8Type (), 0);
2546 func = LLVMAddFunction (lmodule, module->get_unbox_tramp_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
2547 LLVMSetLinkage (func, LLVMExternalLinkage);
2548 LLVMSetVisibility (func, LLVMHiddenVisibility);
2549 LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
2550 module->get_unbox_tramp = func;
2552 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2554 bbs = g_new0 (LLVMBasicBlockRef, module->max_method_idx + 1);
2555 for (i = 0; i < module->max_method_idx + 1; ++i) {
2556 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_unbox_tramp, GINT_TO_POINTER (i));
2557 if (!m)
2558 continue;
2560 name = g_strdup_printf ("BB_%d", i);
2561 bb = LLVMAppendBasicBlock (func, name);
2562 g_free (name);
2563 bbs [i] = bb;
2565 LLVMPositionBuilderAtEnd (builder, bb);
2567 LLVMBuildRet (builder, LLVMBuildBitCast (builder, m, rtype, ""));
2570 fail_bb = LLVMAppendBasicBlock (func, "FAIL");
2571 LLVMPositionBuilderAtEnd (builder, fail_bb);
2572 LLVMBuildRet (builder, LLVMConstNull (rtype));
2574 LLVMPositionBuilderAtEnd (builder, entry_bb);
2576 switch_ins = LLVMBuildSwitch (builder, LLVMGetParam (func, 0), fail_bb, 0);
2577 for (i = 0; i < module->max_method_idx + 1; ++i) {
2578 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_unbox_tramp, GINT_TO_POINTER (i));
2579 if (!m)
2580 continue;
2582 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i, FALSE), bbs [i]);
2585 mark_as_used (module, func);
2586 LLVMDisposeBuilder (builder);
2589 /* Add a function to mark the beginning of LLVM code */
2590 static void
2591 emit_llvm_code_start (MonoLLVMModule *module)
2593 LLVMModuleRef lmodule = module->lmodule;
2594 LLVMValueRef func;
2595 LLVMBasicBlockRef entry_bb;
2596 LLVMBuilderRef builder;
2598 func = LLVMAddFunction (lmodule, "llvm_code_start", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
2599 LLVMSetLinkage (func, LLVMInternalLinkage);
2600 LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
2601 module->code_start = func;
2602 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2603 builder = LLVMCreateBuilder ();
2604 LLVMPositionBuilderAtEnd (builder, entry_bb);
2605 LLVMBuildRetVoid (builder);
2606 LLVMDisposeBuilder (builder);
2609 static LLVMValueRef
2610 emit_init_icall_wrapper (MonoLLVMModule *module, const char *name, const char *icall_name, int subtype)
2612 LLVMModuleRef lmodule = module->lmodule;
2613 LLVMValueRef func, indexes [2], got_entry_addr, args [16], callee;
2614 LLVMBasicBlockRef entry_bb;
2615 LLVMBuilderRef builder;
2616 LLVMTypeRef sig;
2617 MonoJumpInfo *ji;
2618 int got_offset;
2620 switch (subtype) {
2621 case 0:
2622 func = LLVMAddFunction (lmodule, name, LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE));
2623 sig = LLVMFunctionType2 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), FALSE);
2624 break;
2625 case 1:
2626 case 3:
2627 /* mrgctx/vtable */
2628 func = LLVMAddFunction (lmodule, name, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), IntPtrType (), FALSE));
2629 sig = LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), IntPtrType (), FALSE);
2630 break;
2631 case 2:
2632 func = LLVMAddFunction (lmodule, name, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), ObjRefType (), FALSE));
2633 sig = LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), ObjRefType (), FALSE);
2634 break;
2635 default:
2636 g_assert_not_reached ();
2638 LLVMSetLinkage (func, LLVMInternalLinkage);
2639 LLVMAddFunctionAttr (func, LLVMNoInlineAttribute);
2640 mono_llvm_set_preserveall_cc (func);
2641 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2642 builder = LLVMCreateBuilder ();
2643 LLVMPositionBuilderAtEnd (builder, entry_bb);
2645 /* get_aotconst */
2646 ji = g_new0 (MonoJumpInfo, 1);
2647 ji->type = MONO_PATCH_INFO_AOT_MODULE;
2648 ji = mono_aot_patch_info_dup (ji);
2649 got_offset = mono_aot_get_got_offset (ji);
2650 module->max_got_offset = MAX (module->max_got_offset, got_offset);
2651 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2652 indexes [1] = LLVMConstInt (LLVMInt32Type (), got_offset, FALSE);
2653 got_entry_addr = LLVMBuildGEP (builder, module->got_var, indexes, 2, "");
2654 args [0] = LLVMBuildPtrToInt (builder, LLVMBuildLoad (builder, got_entry_addr, ""), IntPtrType (), "");
2655 args [1] = LLVMGetParam (func, 0);
2656 if (subtype)
2657 args [2] = LLVMGetParam (func, 1);
2659 ji = g_new0 (MonoJumpInfo, 1);
2660 ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
2661 ji->data.name = icall_name;
2662 ji = mono_aot_patch_info_dup (ji);
2663 got_offset = mono_aot_get_got_offset (ji);
2664 module->max_got_offset = MAX (module->max_got_offset, got_offset);
2665 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2666 indexes [1] = LLVMConstInt (LLVMInt32Type (), got_offset, FALSE);
2667 got_entry_addr = LLVMBuildGEP (builder, module->got_var, indexes, 2, "");
2668 callee = LLVMBuildLoad (builder, got_entry_addr, "");
2669 callee = LLVMBuildBitCast (builder, callee, LLVMPointerType (sig, 0), "");
2670 LLVMBuildCall (builder, callee, args, LLVMCountParamTypes (sig), "");
2672 // Set the inited flag
2673 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2674 indexes [1] = LLVMGetParam (func, 0);
2675 LLVMBuildStore (builder, LLVMConstInt (LLVMInt8Type (), 1, FALSE), LLVMBuildGEP (builder, module->inited_var, indexes, 2, ""));
2677 LLVMBuildRetVoid (builder);
2679 LLVMVerifyFunction(func, LLVMAbortProcessAction);
2680 LLVMDisposeBuilder (builder);
2681 return func;
2685 * Emit wrappers around the C icalls used to initialize llvm methods, to
2686 * make the calling code smaller and to enable usage of the llvm
2687 * PreserveAll calling convention.
2689 static void
2690 emit_init_icall_wrappers (MonoLLVMModule *module)
2692 module->init_method = emit_init_icall_wrapper (module, "init_method", "mono_aot_init_llvm_method", 0);
2693 module->init_method_gshared_mrgctx = emit_init_icall_wrapper (module, "init_method_gshared_mrgctx", "mono_aot_init_gshared_method_mrgctx", 1);
2694 module->init_method_gshared_this = emit_init_icall_wrapper (module, "init_method_gshared_this", "mono_aot_init_gshared_method_this", 2);
2695 module->init_method_gshared_vtable = emit_init_icall_wrapper (module, "init_method_gshared_vtable", "mono_aot_init_gshared_method_vtable", 3);
2698 static void
2699 emit_llvm_code_end (MonoLLVMModule *module)
2701 LLVMModuleRef lmodule = module->lmodule;
2702 LLVMValueRef func;
2703 LLVMBasicBlockRef entry_bb;
2704 LLVMBuilderRef builder;
2706 func = LLVMAddFunction (lmodule, "llvm_code_end", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
2707 LLVMSetLinkage (func, LLVMInternalLinkage);
2708 LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
2709 module->code_end = func;
2710 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2711 builder = LLVMCreateBuilder ();
2712 LLVMPositionBuilderAtEnd (builder, entry_bb);
2713 LLVMBuildRetVoid (builder);
2714 LLVMDisposeBuilder (builder);
2717 static void
2718 emit_div_check (EmitContext *ctx, LLVMBuilderRef builder, MonoBasicBlock *bb, MonoInst *ins, LLVMValueRef lhs, LLVMValueRef rhs)
2720 gboolean need_div_check = ctx->cfg->backend->need_div_check;
2722 if (bb->region)
2723 /* LLVM doesn't know that these can throw an exception since they are not called through an intrinsic */
2724 need_div_check = TRUE;
2726 if (!need_div_check)
2727 return;
2729 switch (ins->opcode) {
2730 case OP_IDIV:
2731 case OP_LDIV:
2732 case OP_IREM:
2733 case OP_LREM:
2734 case OP_IDIV_UN:
2735 case OP_LDIV_UN:
2736 case OP_IREM_UN:
2737 case OP_LREM_UN:
2738 case OP_IDIV_IMM:
2739 case OP_LDIV_IMM:
2740 case OP_IREM_IMM:
2741 case OP_LREM_IMM:
2742 case OP_IDIV_UN_IMM:
2743 case OP_LDIV_UN_IMM:
2744 case OP_IREM_UN_IMM:
2745 case OP_LREM_UN_IMM: {
2746 LLVMValueRef cmp;
2747 gboolean is_signed = (ins->opcode == OP_IDIV || ins->opcode == OP_LDIV || ins->opcode == OP_IREM || ins->opcode == OP_LREM ||
2748 ins->opcode == OP_IDIV_IMM || ins->opcode == OP_LDIV_IMM || ins->opcode == OP_IREM_IMM || ins->opcode == OP_LREM_IMM);
2750 cmp = LLVMBuildICmp (builder, LLVMIntEQ, rhs, LLVMConstInt (LLVMTypeOf (rhs), 0, FALSE), "");
2751 emit_cond_system_exception (ctx, bb, "DivideByZeroException", cmp);
2752 if (!ctx_ok (ctx))
2753 break;
2754 builder = ctx->builder;
2756 /* b == -1 && a == 0x80000000 */
2757 if (is_signed) {
2758 LLVMValueRef c = (LLVMTypeOf (lhs) == LLVMInt32Type ()) ? LLVMConstInt (LLVMTypeOf (lhs), 0x80000000, FALSE) : LLVMConstInt (LLVMTypeOf (lhs), 0x8000000000000000LL, FALSE);
2759 LLVMValueRef cond1 = LLVMBuildICmp (builder, LLVMIntEQ, rhs, LLVMConstInt (LLVMTypeOf (rhs), -1, FALSE), "");
2760 LLVMValueRef cond2 = LLVMBuildICmp (builder, LLVMIntEQ, lhs, c, "");
2762 cmp = LLVMBuildICmp (builder, LLVMIntEQ, LLVMBuildAnd (builder, cond1, cond2, ""), LLVMConstInt (LLVMInt1Type (), 1, FALSE), "");
2763 emit_cond_system_exception (ctx, bb, "OverflowException", cmp);
2764 if (!ctx_ok (ctx))
2765 break;
2766 builder = ctx->builder;
2768 break;
2770 default:
2771 break;
2776 * emit_init_method:
2778 * Emit code to initialize the GOT slots used by the method.
2780 static void
2781 emit_init_method (EmitContext *ctx)
2783 LLVMValueRef indexes [16], args [16], callee;
2784 LLVMValueRef inited_var, cmp, call;
2785 LLVMBasicBlockRef inited_bb, notinited_bb;
2786 LLVMBuilderRef builder = ctx->builder;
2787 MonoCompile *cfg = ctx->cfg;
2789 ctx->module->max_inited_idx = MAX (ctx->module->max_inited_idx, cfg->method_index);
2791 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2792 indexes [1] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, FALSE);
2793 inited_var = LLVMBuildLoad (builder, LLVMBuildGEP (builder, ctx->module->inited_var, indexes, 2, ""), "is_inited");
2795 args [0] = inited_var;
2796 args [1] = LLVMConstInt (LLVMInt8Type (), 1, FALSE);
2797 inited_var = LLVMBuildCall (ctx->builder, get_intrinsic (ctx, "llvm.expect.i8"), args, 2, "");
2799 cmp = LLVMBuildICmp (builder, LLVMIntEQ, inited_var, LLVMConstInt (LLVMTypeOf (inited_var), 0, FALSE), "");
2801 inited_bb = ctx->inited_bb;
2802 notinited_bb = gen_bb (ctx, "NOTINITED_BB");
2804 LLVMBuildCondBr (ctx->builder, cmp, notinited_bb, inited_bb);
2806 builder = ctx->builder = create_builder (ctx);
2807 LLVMPositionBuilderAtEnd (ctx->builder, notinited_bb);
2809 // FIXME: Cache
2810 if (ctx->rgctx_arg && cfg->method->is_inflated && mono_method_get_context (cfg->method)->method_inst) {
2811 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
2812 args [1] = convert (ctx, ctx->rgctx_arg, IntPtrType ());
2813 callee = ctx->module->init_method_gshared_mrgctx;
2814 call = LLVMBuildCall (builder, callee, args, 2, "");
2815 } else if (ctx->rgctx_arg) {
2816 /* A vtable is passed as the rgctx argument */
2817 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
2818 args [1] = convert (ctx, ctx->rgctx_arg, IntPtrType ());
2819 callee = ctx->module->init_method_gshared_vtable;
2820 call = LLVMBuildCall (builder, callee, args, 2, "");
2821 } else if (cfg->gshared) {
2822 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
2823 args [1] = convert (ctx, ctx->this_arg, ObjRefType ());
2824 callee = ctx->module->init_method_gshared_this;
2825 call = LLVMBuildCall (builder, callee, args, 2, "");
2826 } else {
2827 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
2828 callee = ctx->module->init_method;
2829 call = LLVMBuildCall (builder, callee, args, 1, "");
2833 * This enables llvm to keep arguments in their original registers/
2834 * scratch registers, since the call will not clobber them.
2836 mono_llvm_set_call_preserveall_cc (call);
2838 LLVMBuildBr (builder, inited_bb);
2839 ctx->bblocks [cfg->bb_entry->block_num].end_bblock = inited_bb;
2841 builder = ctx->builder = create_builder (ctx);
2842 LLVMPositionBuilderAtEnd (ctx->builder, inited_bb);
2845 static void
2846 emit_unbox_tramp (EmitContext *ctx, const char *method_name, LLVMTypeRef method_type, LLVMValueRef method, int method_index)
2849 * Emit unbox trampoline using a tail call
2851 LLVMValueRef tramp, call, *args;
2852 LLVMBuilderRef builder;
2853 LLVMBasicBlockRef lbb;
2854 LLVMCallInfo *linfo;
2855 char *tramp_name;
2856 int i, nargs;
2858 tramp_name = g_strdup_printf ("ut_%s", method_name);
2859 tramp = LLVMAddFunction (ctx->module->lmodule, tramp_name, method_type);
2860 LLVMSetLinkage (tramp, LLVMInternalLinkage);
2861 LLVMAddFunctionAttr (tramp, LLVMOptimizeForSizeAttribute);
2862 //LLVMAddFunctionAttr (tramp, LLVMNoUnwindAttribute);
2863 linfo = ctx->linfo;
2864 // FIXME: Reduce code duplication with mono_llvm_compile_method () etc.
2865 if (!ctx->llvm_only && ctx->rgctx_arg_pindex != -1)
2866 LLVMAddAttribute (LLVMGetParam (tramp, ctx->rgctx_arg_pindex), LLVMInRegAttribute);
2867 if (ctx->cfg->vret_addr) {
2868 LLVMSetValueName (LLVMGetParam (tramp, linfo->vret_arg_pindex), "vret");
2869 if (linfo->ret.storage == LLVMArgVtypeByRef) {
2870 LLVMAddAttribute (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVMStructRetAttribute);
2871 LLVMAddAttribute (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVMNoAliasAttribute);
2875 lbb = LLVMAppendBasicBlock (tramp, "");
2876 builder = LLVMCreateBuilder ();
2877 LLVMPositionBuilderAtEnd (builder, lbb);
2879 nargs = LLVMCountParamTypes (method_type);
2880 args = g_new0 (LLVMValueRef, nargs);
2881 for (i = 0; i < nargs; ++i) {
2882 args [i] = LLVMGetParam (tramp, i);
2883 if (i == ctx->this_arg_pindex) {
2884 LLVMTypeRef arg_type = LLVMTypeOf (args [i]);
2886 args [i] = LLVMBuildPtrToInt (builder, args [i], IntPtrType (), "");
2887 args [i] = LLVMBuildAdd (builder, args [i], LLVMConstInt (IntPtrType (), sizeof (MonoObject), FALSE), "");
2888 args [i] = LLVMBuildIntToPtr (builder, args [i], arg_type, "");
2891 call = LLVMBuildCall (builder, method, args, nargs, "");
2892 if (!ctx->llvm_only && ctx->rgctx_arg_pindex != -1)
2893 LLVMAddInstrAttribute (call, 1 + ctx->rgctx_arg_pindex, LLVMInRegAttribute);
2894 if (linfo->ret.storage == LLVMArgVtypeByRef)
2895 LLVMAddInstrAttribute (call, 1 + linfo->vret_arg_pindex, LLVMStructRetAttribute);
2897 // FIXME: This causes assertions in clang
2898 //mono_llvm_set_must_tail (call);
2899 if (LLVMGetReturnType (method_type) == LLVMVoidType ())
2900 LLVMBuildRetVoid (builder);
2901 else
2902 LLVMBuildRet (builder, call);
2904 g_hash_table_insert (ctx->module->idx_to_unbox_tramp, GINT_TO_POINTER (method_index), tramp);
2905 LLVMDisposeBuilder (builder);
2909 * emit_entry_bb:
2911 * Emit code to load/convert arguments.
2913 static void
2914 emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
2916 int i, j, pindex;
2917 MonoCompile *cfg = ctx->cfg;
2918 MonoMethodSignature *sig = ctx->sig;
2919 LLVMCallInfo *linfo = ctx->linfo;
2920 MonoBasicBlock *bb;
2921 char **names;
2923 LLVMBuilderRef old_builder = ctx->builder;
2924 ctx->builder = builder;
2926 ctx->alloca_builder = create_builder (ctx);
2929 * Handle indirect/volatile variables by allocating memory for them
2930 * using 'alloca', and storing their address in a temporary.
2932 for (i = 0; i < cfg->num_varinfo; ++i) {
2933 MonoInst *var = cfg->varinfo [i];
2934 LLVMTypeRef vtype;
2936 if (var->opcode == OP_GSHAREDVT_LOCAL || var->opcode == OP_GSHAREDVT_ARG_REGOFFSET) {
2937 } else if (var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || (mini_type_is_vtype (var->inst_vtype) && !MONO_CLASS_IS_SIMD (ctx->cfg, var->klass))) {
2938 vtype = type_to_llvm_type (ctx, var->inst_vtype);
2939 if (!ctx_ok (ctx))
2940 return;
2941 /* Could be already created by an OP_VPHI */
2942 if (!ctx->addresses [var->dreg]) {
2943 ctx->addresses [var->dreg] = build_alloca (ctx, var->inst_vtype);
2944 //LLVMSetValueName (ctx->addresses [var->dreg], g_strdup_printf ("vreg_loc_%d", var->dreg));
2946 ctx->vreg_cli_types [var->dreg] = var->inst_vtype;
2950 names = g_new (char *, sig->param_count);
2951 mono_method_get_param_names (cfg->method, (const char **) names);
2953 for (i = 0; i < sig->param_count; ++i) {
2954 LLVMArgInfo *ainfo = &linfo->args [i + sig->hasthis];
2955 int reg = cfg->args [i + sig->hasthis]->dreg;
2956 char *name;
2958 pindex = ainfo->pindex;
2960 switch (ainfo->storage) {
2961 case LLVMArgVtypeInReg:
2962 case LLVMArgAsFpArgs: {
2963 LLVMValueRef args [8];
2964 int j;
2966 pindex += ainfo->ndummy_fpargs;
2968 /* The argument is received as a set of int/fp arguments, store them into the real argument */
2969 memset (args, 0, sizeof (args));
2970 if (ainfo->storage == LLVMArgVtypeInReg) {
2971 args [0] = LLVMGetParam (ctx->lmethod, pindex);
2972 if (ainfo->pair_storage [1] != LLVMArgNone)
2973 args [1] = LLVMGetParam (ctx->lmethod, pindex + 1);
2974 } else {
2975 g_assert (ainfo->nslots <= 8);
2976 for (j = 0; j < ainfo->nslots; ++j)
2977 args [j] = LLVMGetParam (ctx->lmethod, pindex + j);
2979 ctx->addresses [reg] = build_alloca (ctx, ainfo->type);
2981 emit_args_to_vtype (ctx, builder, ainfo->type, ctx->addresses [reg], ainfo, args);
2983 if (ainfo->storage == LLVMArgVtypeInReg && MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (ainfo->type))) {
2984 /* Treat these as normal values */
2985 ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "");
2987 break;
2989 case LLVMArgVtypeByVal: {
2990 ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindex);
2992 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (ainfo->type))) {
2993 /* Treat these as normal values */
2994 ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "");
2996 break;
2998 case LLVMArgVtypeByRef: {
2999 /* The argument is passed by ref */
3000 ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindex);
3001 break;
3003 case LLVMArgAsIArgs: {
3004 LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
3005 int size;
3007 /* The argument is received as an array of ints, store it into the real argument */
3008 ctx->addresses [reg] = build_alloca (ctx, ainfo->type);
3010 size = mono_class_value_size (mono_class_from_mono_type (ainfo->type), NULL);
3011 if (size < SIZEOF_VOID_P) {
3012 /* The upper bits of the registers might not be valid */
3013 LLVMValueRef val = LLVMBuildExtractValue (builder, arg, 0, "");
3014 LLVMValueRef dest = convert (ctx, ctx->addresses [reg], LLVMPointerType (LLVMIntType (size * 8), 0));
3015 LLVMBuildStore (ctx->builder, LLVMBuildTrunc (builder, val, LLVMIntType (size * 8), ""), dest);
3016 } else {
3017 LLVMBuildStore (ctx->builder, arg, convert (ctx, ctx->addresses [reg], LLVMPointerType (LLVMTypeOf (arg), 0)));
3019 break;
3021 case LLVMArgVtypeAsScalar:
3022 g_assert_not_reached ();
3023 break;
3024 case LLVMArgGsharedvtFixed: {
3025 /* These are non-gsharedvt arguments passed by ref, the rest of the IR treats them as scalars */
3026 LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
3028 if (names [i])
3029 name = g_strdup_printf ("arg_%s", names [i]);
3030 else
3031 name = g_strdup_printf ("arg_%d", i);
3033 ctx->values [reg] = LLVMBuildLoad (builder, convert (ctx, arg, LLVMPointerType (type_to_llvm_type (ctx, ainfo->type), 0)), name);
3034 break;
3036 case LLVMArgGsharedvtFixedVtype: {
3037 LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
3039 if (names [i])
3040 name = g_strdup_printf ("vtype_arg_%s", names [i]);
3041 else
3042 name = g_strdup_printf ("vtype_arg_%d", i);
3044 /* Non-gsharedvt vtype argument passed by ref, the rest of the IR treats it as a vtype */
3045 g_assert (ctx->addresses [reg]);
3046 LLVMSetValueName (ctx->addresses [reg], name);
3047 LLVMBuildStore (builder, LLVMBuildLoad (builder, convert (ctx, arg, LLVMPointerType (type_to_llvm_type (ctx, ainfo->type), 0)), ""), ctx->addresses [reg]);
3048 break;
3050 case LLVMArgGsharedvtVariable:
3051 /* The IR treats these as variables with addresses */
3052 ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindex);
3053 break;
3054 default:
3055 ctx->values [reg] = convert_full (ctx, ctx->values [reg], llvm_type_to_stack_type (cfg, type_to_llvm_type (ctx, ainfo->type)), type_is_unsigned (ctx, ainfo->type));
3056 break;
3059 g_free (names);
3061 if (cfg->vret_addr)
3062 emit_volatile_store (ctx, cfg->vret_addr->dreg);
3063 if (sig->hasthis)
3064 emit_volatile_store (ctx, cfg->args [0]->dreg);
3065 for (i = 0; i < sig->param_count; ++i)
3066 if (!mini_type_is_vtype (sig->params [i]))
3067 emit_volatile_store (ctx, cfg->args [i + sig->hasthis]->dreg);
3069 if (sig->hasthis && !cfg->rgctx_var && cfg->gshared) {
3070 LLVMValueRef this_alloc;
3073 * The exception handling code needs the location where the this argument was
3074 * stored for gshared methods. We create a separate alloca to hold it, and mark it
3075 * with the "mono.this" custom metadata to tell llvm that it needs to save its
3076 * location into the LSDA.
3078 this_alloc = mono_llvm_build_alloca (builder, ThisType (), LLVMConstInt (LLVMInt32Type (), 1, FALSE), 0, "");
3079 /* This volatile store will keep the alloca alive */
3080 mono_llvm_build_store (builder, ctx->values [cfg->args [0]->dreg], this_alloc, TRUE, LLVM_BARRIER_NONE);
3082 set_metadata_flag (this_alloc, "mono.this");
3085 if (cfg->rgctx_var) {
3086 LLVMValueRef rgctx_alloc, store;
3089 * We handle the rgctx arg similarly to the this pointer.
3091 g_assert (ctx->addresses [cfg->rgctx_var->dreg]);
3092 rgctx_alloc = ctx->addresses [cfg->rgctx_var->dreg];
3093 /* This volatile store will keep the alloca alive */
3094 store = mono_llvm_build_store (builder, convert (ctx, ctx->rgctx_arg, IntPtrType ()), rgctx_alloc, TRUE, LLVM_BARRIER_NONE);
3096 set_metadata_flag (rgctx_alloc, "mono.this");
3099 /* Initialize the method if needed */
3100 if (cfg->compile_aot && ctx->llvm_only) {
3101 /* Emit a location for the initialization code */
3102 ctx->init_bb = gen_bb (ctx, "INIT_BB");
3103 ctx->inited_bb = gen_bb (ctx, "INITED_BB");
3105 LLVMBuildBr (ctx->builder, ctx->init_bb);
3106 builder = ctx->builder = create_builder (ctx);
3107 LLVMPositionBuilderAtEnd (ctx->builder, ctx->inited_bb);
3108 ctx->bblocks [cfg->bb_entry->block_num].end_bblock = ctx->inited_bb;
3111 /* Compute nesting between clauses */
3112 ctx->nested_in = (GSList**)mono_mempool_alloc0 (cfg->mempool, sizeof (GSList*) * cfg->header->num_clauses);
3113 for (i = 0; i < cfg->header->num_clauses; ++i) {
3114 for (j = 0; j < cfg->header->num_clauses; ++j) {
3115 MonoExceptionClause *clause1 = &cfg->header->clauses [i];
3116 MonoExceptionClause *clause2 = &cfg->header->clauses [j];
3118 if (i != j && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset)
3119 ctx->nested_in [i] = g_slist_prepend_mempool (cfg->mempool, ctx->nested_in [i], GINT_TO_POINTER (j));
3124 * For finally clauses, create an indicator variable telling OP_ENDFINALLY whenever
3125 * it needs to continue normally, or return back to the exception handling system.
3127 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3128 int clause_index;
3129 char name [128];
3131 if (!(bb->region != -1 && (bb->flags & BB_EXCEPTION_HANDLER)))
3132 continue;
3134 clause_index = MONO_REGION_CLAUSE_INDEX (bb->region);
3135 g_hash_table_insert (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)), bb);
3136 g_hash_table_insert (ctx->clause_to_handler, GINT_TO_POINTER (clause_index), bb);
3138 if (bb->in_scount == 0) {
3139 LLVMValueRef val;
3141 sprintf (name, "finally_ind_bb%d", bb->block_num);
3142 val = LLVMBuildAlloca (builder, LLVMInt32Type (), name);
3143 LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), val);
3145 ctx->bblocks [bb->block_num].finally_ind = val;
3146 } else {
3147 /* Create a variable to hold the exception var */
3148 if (!ctx->ex_var)
3149 ctx->ex_var = LLVMBuildAlloca (builder, ObjRefType (), "exvar");
3153 * Create a new bblock which CALL_HANDLER/landing pads can branch to, because branching to the
3154 * LLVM bblock containing a landing pad causes problems for the
3155 * LLVM optimizer passes.
3157 sprintf (name, "BB%d_CALL_HANDLER_TARGET", bb->block_num);
3158 ctx->bblocks [bb->block_num].call_handler_target_bb = LLVMAppendBasicBlock (ctx->lmethod, name);
3160 ctx->builder = old_builder;
3163 static void
3164 process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, MonoInst *ins)
3166 MonoCompile *cfg = ctx->cfg;
3167 LLVMValueRef *values = ctx->values;
3168 LLVMValueRef *addresses = ctx->addresses;
3169 MonoCallInst *call = (MonoCallInst*)ins;
3170 MonoMethodSignature *sig = call->signature;
3171 LLVMValueRef callee = NULL, lcall;
3172 LLVMValueRef *args;
3173 LLVMCallInfo *cinfo;
3174 GSList *l;
3175 int i, len, nargs;
3176 gboolean vretaddr;
3177 LLVMTypeRef llvm_sig;
3178 gpointer target;
3179 gboolean is_virtual, calli, preserveall;
3180 LLVMBuilderRef builder = *builder_ref;
3182 if ((call->signature->call_convention != MONO_CALL_DEFAULT) && !((call->signature->call_convention == MONO_CALL_C) && ctx->llvm_only)) {
3183 set_failure (ctx, "non-default callconv");
3184 return;
3187 cinfo = call->cinfo;
3188 g_assert (cinfo);
3189 if (call->rgctx_arg_reg)
3190 cinfo->rgctx_arg = TRUE;
3191 if (call->imt_arg_reg)
3192 cinfo->imt_arg = TRUE;
3194 vretaddr = (cinfo->ret.storage == LLVMArgVtypeRetAddr || cinfo->ret.storage == LLVMArgVtypeByRef || cinfo->ret.storage == LLVMArgGsharedvtFixed || cinfo->ret.storage == LLVMArgGsharedvtVariable || cinfo->ret.storage == LLVMArgGsharedvtFixedVtype);
3196 llvm_sig = sig_to_llvm_sig_full (ctx, sig, cinfo);
3197 if (!ctx_ok (ctx))
3198 return;
3200 is_virtual = (ins->opcode == OP_VOIDCALL_MEMBASE || ins->opcode == OP_CALL_MEMBASE || ins->opcode == OP_VCALL_MEMBASE || ins->opcode == OP_LCALL_MEMBASE || ins->opcode == OP_FCALL_MEMBASE || ins->opcode == OP_RCALL_MEMBASE);
3201 calli = !call->fptr_is_patch && (ins->opcode == OP_VOIDCALL_REG || ins->opcode == OP_CALL_REG || ins->opcode == OP_VCALL_REG || ins->opcode == OP_LCALL_REG || ins->opcode == OP_FCALL_REG || ins->opcode == OP_RCALL_REG);
3202 /* Unused */
3203 preserveall = FALSE;
3205 /* FIXME: Avoid creating duplicate methods */
3207 if (ins->flags & MONO_INST_HAS_METHOD) {
3208 if (is_virtual) {
3209 callee = NULL;
3210 } else {
3211 if (cfg->compile_aot) {
3212 callee = get_callee (ctx, llvm_sig, MONO_PATCH_INFO_METHOD, call->method);
3213 if (!callee) {
3214 set_failure (ctx, "can't encode patch");
3215 return;
3217 if (cfg->llvm_only && call->method->klass->image->assembly == ctx->module->assembly) {
3219 * Collect instructions representing the callee into a hash so they can be replaced
3220 * by the llvm method for the callee if the callee turns out to be direct
3221 * callable. Currently this only requires it to not fail llvm compilation.
3223 GSList *l = (GSList*)g_hash_table_lookup (ctx->method_to_callers, call->method);
3224 l = g_slist_prepend (l, callee);
3225 g_hash_table_insert (ctx->method_to_callers, call->method, l);
3227 } else {
3228 MonoError error;
3229 static int tramp_index;
3230 char *name;
3232 name = g_strdup_printf ("tramp_%d", tramp_index);
3233 tramp_index ++;
3235 #if LLVM_API_VERSION > 100
3237 * Use our trampoline infrastructure for lazy compilation instead of llvm's.
3238 * Make all calls through a global. The address of the global will be saved in
3239 * MonoJitDomainInfo.llvm_jit_callees and updated when the method it refers to is
3240 * compiled.
3242 LLVMValueRef tramp_var = g_hash_table_lookup (ctx->jit_callees, call->method);
3243 if (!tramp_var) {
3244 target =
3245 mono_create_jit_trampoline (mono_domain_get (),
3246 call->method, &error);
3247 if (!is_ok (&error)) {
3248 set_failure (ctx, mono_error_get_message (&error));
3249 mono_error_cleanup (&error);
3250 return;
3253 tramp_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (llvm_sig, 0), name);
3254 LLVMSetInitializer (tramp_var, LLVMConstIntToPtr (LLVMConstInt (LLVMInt64Type (), (guint64)(size_t)target, FALSE), LLVMPointerType (llvm_sig, 0)));
3255 LLVMSetLinkage (tramp_var, LLVMExternalLinkage);
3256 g_hash_table_insert (ctx->jit_callees, call->method, tramp_var);
3258 callee = LLVMBuildLoad (builder, tramp_var, "");
3259 #else
3260 target =
3261 mono_create_jit_trampoline (mono_domain_get (),
3262 call->method, &error);
3263 if (!is_ok (&error)) {
3264 g_free (name);
3265 set_failure (ctx, mono_error_get_message (&error));
3266 mono_error_cleanup (&error);
3267 return;
3270 callee = LLVMAddFunction (ctx->lmodule, name, llvm_sig);
3271 g_free (name);
3273 LLVMAddGlobalMapping (ctx->module->ee, callee, target);
3274 #endif
3278 if (!cfg->llvm_only && call->method && strstr (call->method->klass->name, "AsyncVoidMethodBuilder")) {
3279 /* LLVM miscompiles async methods */
3280 set_failure (ctx, "#13734");
3281 return;
3283 } else if (calli) {
3284 } else {
3285 MonoJitICallInfo *info = mono_find_jit_icall_by_addr (call->fptr);
3287 if (info) {
3289 MonoJumpInfo ji;
3291 memset (&ji, 0, sizeof (ji));
3292 ji.type = MONO_PATCH_INFO_JIT_ICALL_ADDR;
3293 ji.data.target = info->name;
3295 target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, &ji, FALSE);
3297 if (cfg->compile_aot) {
3298 callee = get_callee (ctx, llvm_sig, MONO_PATCH_INFO_INTERNAL_METHOD, (char*)info->name);
3299 if (!callee) {
3300 set_failure (ctx, "can't encode patch");
3301 return;
3303 } else {
3304 target = (gpointer)mono_icall_get_wrapper (info);
3305 callee = emit_jit_callee (ctx, "", llvm_sig, target);
3307 } else {
3308 if (cfg->compile_aot) {
3309 callee = NULL;
3310 if (cfg->abs_patches) {
3311 MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
3312 if (abs_ji) {
3313 callee = get_callee (ctx, llvm_sig, abs_ji->type, abs_ji->data.target);
3314 if (!callee) {
3315 set_failure (ctx, "can't encode patch");
3316 return;
3320 if (!callee) {
3321 set_failure (ctx, "aot");
3322 return;
3324 } else {
3325 #if LLVM_API_VERSION > 100
3326 if (cfg->abs_patches) {
3327 MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
3328 if (abs_ji) {
3329 MonoError error;
3331 target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, abs_ji, FALSE, &error);
3332 mono_error_assert_ok (&error);
3333 callee = emit_jit_callee (ctx, "", llvm_sig, target);
3334 } else {
3335 g_assert_not_reached ();
3337 } else {
3338 g_assert_not_reached ();
3340 #else
3341 callee = LLVMAddFunction (ctx->lmodule, "", llvm_sig);
3342 target = NULL;
3343 if (cfg->abs_patches) {
3344 MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
3345 if (abs_ji) {
3346 MonoError error;
3349 * FIXME: Some trampolines might have
3350 * their own calling convention on some platforms.
3352 target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, abs_ji, FALSE, &error);
3353 mono_error_assert_ok (&error);
3354 LLVMAddGlobalMapping (ctx->module->ee, callee, target);
3357 if (!target)
3358 LLVMAddGlobalMapping (ctx->module->ee, callee, (gpointer)call->fptr);
3359 #endif
3364 if (is_virtual) {
3365 int size = sizeof (gpointer);
3366 LLVMValueRef index;
3368 g_assert (ins->inst_offset % size == 0);
3369 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
3371 callee = convert (ctx, LLVMBuildLoad (builder, LLVMBuildGEP (builder, convert (ctx, values [ins->inst_basereg], LLVMPointerType (LLVMPointerType (IntPtrType (), 0), 0)), &index, 1, ""), ""), LLVMPointerType (llvm_sig, 0));
3372 } else if (calli) {
3373 callee = convert (ctx, values [ins->sreg1], LLVMPointerType (llvm_sig, 0));
3374 } else {
3375 if (ins->flags & MONO_INST_HAS_METHOD) {
3380 * Collect and convert arguments
3382 nargs = (sig->param_count * 16) + sig->hasthis + vretaddr + call->rgctx_reg + call->imt_arg_reg;
3383 len = sizeof (LLVMValueRef) * nargs;
3384 args = (LLVMValueRef*)alloca (len);
3385 memset (args, 0, len);
3386 l = call->out_ireg_args;
3388 if (call->rgctx_arg_reg) {
3389 g_assert (values [call->rgctx_arg_reg]);
3390 g_assert (cinfo->rgctx_arg_pindex < nargs);
3392 * On ARM, the imt/rgctx argument is passed in a caller save register, but some of our trampolines etc. clobber it, leading to
3393 * problems is LLVM moves the arg assignment earlier. To work around this, save the argument into a stack slot and load
3394 * it using a volatile load.
3396 #ifdef TARGET_ARM
3397 if (!ctx->imt_rgctx_loc)
3398 ctx->imt_rgctx_loc = build_alloca_llvm_type (ctx, ctx->module->ptr_type, sizeof (gpointer));
3399 LLVMBuildStore (builder, convert (ctx, ctx->values [call->rgctx_arg_reg], ctx->module->ptr_type), ctx->imt_rgctx_loc);
3400 args [cinfo->rgctx_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE);
3401 #else
3402 args [cinfo->rgctx_arg_pindex] = convert (ctx, values [call->rgctx_arg_reg], ctx->module->ptr_type);
3403 #endif
3405 if (call->imt_arg_reg) {
3406 g_assert (!ctx->llvm_only);
3407 g_assert (values [call->imt_arg_reg]);
3408 g_assert (cinfo->imt_arg_pindex < nargs);
3409 #ifdef TARGET_ARM
3410 if (!ctx->imt_rgctx_loc)
3411 ctx->imt_rgctx_loc = build_alloca_llvm_type (ctx, ctx->module->ptr_type, sizeof (gpointer));
3412 LLVMBuildStore (builder, convert (ctx, ctx->values [call->imt_arg_reg], ctx->module->ptr_type), ctx->imt_rgctx_loc);
3413 args [cinfo->imt_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE);
3414 #else
3415 args [cinfo->imt_arg_pindex] = convert (ctx, values [call->imt_arg_reg], ctx->module->ptr_type);
3416 #endif
3418 switch (cinfo->ret.storage) {
3419 case LLVMArgGsharedvtVariable: {
3420 MonoInst *var = get_vreg_to_inst (cfg, call->inst.dreg);
3422 if (var && var->opcode == OP_GSHAREDVT_LOCAL) {
3423 args [cinfo->vret_arg_pindex] = convert (ctx, emit_gsharedvt_ldaddr (ctx, var->dreg), IntPtrType ());
3424 } else {
3425 g_assert (addresses [call->inst.dreg]);
3426 args [cinfo->vret_arg_pindex] = addresses [call->inst.dreg];
3428 break;
3430 default:
3431 if (vretaddr) {
3432 if (!addresses [call->inst.dreg])
3433 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3434 g_assert (cinfo->vret_arg_pindex < nargs);
3435 if (cinfo->ret.storage == LLVMArgVtypeByRef)
3436 args [cinfo->vret_arg_pindex] = addresses [call->inst.dreg];
3437 else
3438 args [cinfo->vret_arg_pindex] = LLVMBuildPtrToInt (builder, addresses [call->inst.dreg], IntPtrType (), "");
3440 break;
3444 * Sometimes the same method is called with two different signatures (i.e. with and without 'this'), so
3445 * use the real callee for argument type conversion.
3447 LLVMTypeRef callee_type = LLVMGetElementType (LLVMTypeOf (callee));
3448 LLVMTypeRef *param_types = (LLVMTypeRef*)g_alloca (sizeof (LLVMTypeRef) * LLVMCountParamTypes (callee_type));
3449 LLVMGetParamTypes (callee_type, param_types);
3451 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
3452 guint32 regpair;
3453 int reg, pindex;
3454 LLVMArgInfo *ainfo = &call->cinfo->args [i];
3456 pindex = ainfo->pindex;
3458 regpair = (guint32)(gssize)(l->data);
3459 reg = regpair & 0xffffff;
3460 args [pindex] = values [reg];
3461 switch (ainfo->storage) {
3462 case LLVMArgVtypeInReg:
3463 case LLVMArgAsFpArgs: {
3464 guint32 nargs;
3465 int j;
3467 for (j = 0; j < ainfo->ndummy_fpargs; ++j)
3468 args [pindex + j] = LLVMConstNull (LLVMDoubleType ());
3469 pindex += ainfo->ndummy_fpargs;
3471 g_assert (addresses [reg]);
3472 emit_vtype_to_args (ctx, builder, ainfo->type, addresses [reg], ainfo, args + pindex, &nargs);
3473 pindex += nargs;
3475 // FIXME: alignment
3476 // FIXME: Get rid of the VMOVE
3477 break;
3479 case LLVMArgVtypeByVal:
3480 g_assert (addresses [reg]);
3481 args [pindex] = addresses [reg];
3482 break;
3483 case LLVMArgVtypeByRef: {
3484 g_assert (addresses [reg]);
3485 args [pindex] = convert (ctx, addresses [reg], LLVMPointerType (type_to_llvm_arg_type (ctx, ainfo->type), 0));
3486 break;
3488 case LLVMArgAsIArgs:
3489 g_assert (addresses [reg]);
3490 args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo->nslots), 0)), "");
3491 break;
3492 case LLVMArgVtypeAsScalar:
3493 g_assert_not_reached ();
3494 break;
3495 case LLVMArgGsharedvtFixed:
3496 case LLVMArgGsharedvtFixedVtype:
3497 g_assert (addresses [reg]);
3498 args [pindex] = convert (ctx, addresses [reg], LLVMPointerType (type_to_llvm_arg_type (ctx, ainfo->type), 0));
3499 break;
3500 case LLVMArgGsharedvtVariable:
3501 g_assert (addresses [reg]);
3502 args [pindex] = convert (ctx, addresses [reg], LLVMPointerType (IntPtrType (), 0));
3503 break;
3504 default:
3505 g_assert (args [pindex]);
3506 if (i == 0 && sig->hasthis)
3507 args [pindex] = convert (ctx, args [pindex], param_types [pindex]);
3508 else
3509 args [pindex] = convert (ctx, args [pindex], type_to_llvm_arg_type (ctx, ainfo->type));
3510 break;
3512 g_assert (pindex <= nargs);
3514 l = l->next;
3517 // FIXME: Align call sites
3520 * Emit the call
3523 lcall = emit_call (ctx, bb, &builder, callee, args, LLVMCountParamTypes (llvm_sig));
3525 if (ins->opcode != OP_TAILCALL && LLVMGetInstructionOpcode (lcall) == LLVMCall)
3526 mono_llvm_set_call_notail (lcall);
3529 * Modify cconv and parameter attributes to pass rgctx/imt correctly.
3531 #if defined(MONO_ARCH_IMT_REG) && defined(MONO_ARCH_RGCTX_REG)
3532 g_assert (MONO_ARCH_IMT_REG == MONO_ARCH_RGCTX_REG);
3533 #endif
3534 /* The two can't be used together, so use only one LLVM calling conv to pass them */
3535 g_assert (!(call->rgctx_arg_reg && call->imt_arg_reg));
3536 if (!sig->pinvoke && !cfg->llvm_only)
3537 LLVMSetInstructionCallConv (lcall, LLVMMono1CallConv);
3538 if (preserveall)
3539 mono_llvm_set_call_preserveall_cc (lcall);
3541 if (cinfo->ret.storage == LLVMArgVtypeByRef)
3542 LLVMAddInstrAttribute (lcall, 1 + cinfo->vret_arg_pindex, LLVMStructRetAttribute);
3543 if (!ctx->llvm_only && call->rgctx_arg_reg)
3544 LLVMAddInstrAttribute (lcall, 1 + cinfo->rgctx_arg_pindex, LLVMInRegAttribute);
3545 if (call->imt_arg_reg)
3546 LLVMAddInstrAttribute (lcall, 1 + cinfo->imt_arg_pindex, LLVMInRegAttribute);
3548 /* Add byval attributes if needed */
3549 for (i = 0; i < sig->param_count; ++i) {
3550 LLVMArgInfo *ainfo = &call->cinfo->args [i + sig->hasthis];
3552 if (ainfo && ainfo->storage == LLVMArgVtypeByVal)
3553 LLVMAddInstrAttribute (lcall, 1 + ainfo->pindex, LLVMByValAttribute);
3557 * Convert the result
3559 switch (cinfo->ret.storage) {
3560 case LLVMArgVtypeInReg: {
3561 LLVMValueRef regs [2];
3563 if (LLVMTypeOf (lcall) == LLVMVoidType ())
3564 /* Empty struct */
3565 break;
3567 if (!addresses [ins->dreg])
3568 addresses [ins->dreg] = build_alloca (ctx, sig->ret);
3570 regs [0] = LLVMBuildExtractValue (builder, lcall, 0, "");
3571 if (cinfo->ret.pair_storage [1] != LLVMArgNone)
3572 regs [1] = LLVMBuildExtractValue (builder, lcall, 1, "");
3573 emit_args_to_vtype (ctx, builder, sig->ret, addresses [ins->dreg], &cinfo->ret, regs);
3574 break;
3576 case LLVMArgVtypeByVal:
3577 if (!addresses [call->inst.dreg])
3578 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3579 LLVMBuildStore (builder, lcall, addresses [call->inst.dreg]);
3580 break;
3581 case LLVMArgAsIArgs:
3582 case LLVMArgFpStruct:
3583 if (!addresses [call->inst.dreg])
3584 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3585 LLVMBuildStore (builder, lcall, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (LLVMTypeOf (lcall), 0), FALSE));
3586 break;
3587 case LLVMArgVtypeAsScalar:
3588 if (!addresses [call->inst.dreg])
3589 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3590 LLVMBuildStore (builder, lcall, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (LLVMTypeOf (lcall), 0), FALSE));
3591 break;
3592 case LLVMArgVtypeRetAddr:
3593 case LLVMArgVtypeByRef:
3594 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (sig->ret))) {
3595 /* Some opcodes like STOREX_MEMBASE access these by value */
3596 g_assert (addresses [call->inst.dreg]);
3597 values [ins->dreg] = LLVMBuildLoad (builder, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (type_to_llvm_type (ctx, sig->ret), 0), FALSE), "");
3599 break;
3600 case LLVMArgGsharedvtVariable:
3601 break;
3602 case LLVMArgGsharedvtFixed:
3603 case LLVMArgGsharedvtFixedVtype:
3604 values [ins->dreg] = LLVMBuildLoad (builder, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (type_to_llvm_type (ctx, sig->ret), 0), FALSE), "");
3605 break;
3606 default:
3607 if (sig->ret->type != MONO_TYPE_VOID)
3608 /* If the method returns an unsigned value, need to zext it */
3609 values [ins->dreg] = convert_full (ctx, lcall, llvm_type_to_stack_type (cfg, type_to_llvm_type (ctx, sig->ret)), type_is_unsigned (ctx, sig->ret));
3610 break;
3613 *builder_ref = ctx->builder;
3616 static void
3617 emit_llvmonly_throw (EmitContext *ctx, MonoBasicBlock *bb, gboolean rethrow, LLVMValueRef exc)
3619 const char *icall_name = rethrow ? "mono_llvm_rethrow_exception" : "mono_llvm_throw_exception";
3620 LLVMValueRef callee = rethrow ? ctx->module->rethrow : ctx->module->throw_icall;
3622 LLVMTypeRef exc_type = type_to_llvm_type (ctx, &mono_get_exception_class ()->byval_arg);
3624 if (!callee) {
3625 LLVMTypeRef fun_sig = LLVMFunctionType1 (LLVMVoidType (), exc_type, FALSE);
3627 if (ctx->cfg->compile_aot) {
3628 callee = get_callee (ctx, fun_sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, icall_name);
3629 } else {
3630 callee = LLVMAddFunction (ctx->lmodule, icall_name, fun_sig);
3631 LLVMAddGlobalMapping (ctx->module->ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
3632 mono_memory_barrier ();
3634 if (rethrow)
3635 ctx->module->rethrow = callee;
3636 else
3637 ctx->module->throw_icall = callee;
3641 LLVMValueRef args [2];
3643 args [0] = convert (ctx, exc, exc_type);
3644 emit_call (ctx, bb, &ctx->builder, callee, args, 1);
3646 LLVMBuildUnreachable (ctx->builder);
3648 ctx->builder = create_builder (ctx);
3651 static void
3652 emit_throw (EmitContext *ctx, MonoBasicBlock *bb, gboolean rethrow, LLVMValueRef exc)
3654 MonoMethodSignature *throw_sig;
3655 LLVMValueRef callee, arg;
3656 const char *icall_name;
3658 callee = rethrow ? ctx->module->rethrow : ctx->module->throw_icall;
3659 icall_name = rethrow ? "mono_arch_rethrow_exception" : "mono_arch_throw_exception";
3661 if (!callee) {
3662 throw_sig = mono_metadata_signature_alloc (mono_get_corlib (), 1);
3663 throw_sig->ret = &mono_get_void_class ()->byval_arg;
3664 throw_sig->params [0] = &mono_get_object_class ()->byval_arg;
3665 if (ctx->cfg->compile_aot) {
3666 callee = get_callee (ctx, sig_to_llvm_sig (ctx, throw_sig), MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3667 } else {
3668 gpointer target;
3669 #ifdef TARGET_X86
3671 * LLVM doesn't push the exception argument, so we need a different
3672 * trampoline.
3674 target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, rethrow ? "llvm_rethrow_exception_trampoline" : "llvm_throw_exception_trampoline");
3675 #else
3676 target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3677 #endif
3678 callee = emit_jit_callee (ctx, icall_name, sig_to_llvm_sig (ctx, throw_sig), target);
3681 mono_memory_barrier ();
3682 #if LLVM_API_VERSION < 100
3683 if (rethrow)
3684 ctx->module->rethrow = callee;
3685 else
3686 ctx->module->throw_icall = callee;
3687 #endif
3689 arg = convert (ctx, exc, type_to_llvm_type (ctx, &mono_get_object_class ()->byval_arg));
3690 emit_call (ctx, bb, &ctx->builder, callee, &arg, 1);
3693 static void
3694 emit_resume_eh (EmitContext *ctx, MonoBasicBlock *bb)
3696 const char *icall_name = "mono_llvm_resume_exception";
3697 LLVMValueRef callee = ctx->module->resume_eh;
3699 LLVMTypeRef fun_sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
3701 if (!callee) {
3702 if (ctx->cfg->compile_aot) {
3703 callee = get_callee (ctx, fun_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3704 } else {
3705 callee = LLVMAddFunction (ctx->lmodule, icall_name, fun_sig);
3706 LLVMAddGlobalMapping (ctx->module->ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
3707 mono_memory_barrier ();
3709 ctx->module->resume_eh = callee;
3713 emit_call (ctx, bb, &ctx->builder, callee, NULL, 0);
3715 LLVMBuildUnreachable (ctx->builder);
3717 ctx->builder = create_builder (ctx);
3720 static LLVMValueRef
3721 mono_llvm_emit_clear_exception_call (EmitContext *ctx, LLVMBuilderRef builder)
3723 const char *icall_name = "mono_llvm_clear_exception";
3725 LLVMTypeRef call_sig = LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE);
3726 LLVMValueRef callee = NULL;
3728 if (!callee) {
3729 if (ctx->cfg->compile_aot) {
3730 callee = get_callee (ctx, call_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3731 } else {
3732 // FIXME: This is broken.
3733 callee = LLVMAddFunction (ctx->lmodule, icall_name, call_sig);
3737 g_assert (builder && callee);
3739 return LLVMBuildCall (builder, callee, NULL, 0, "");
3742 static LLVMValueRef
3743 mono_llvm_emit_load_exception_call (EmitContext *ctx, LLVMBuilderRef builder)
3745 const char *icall_name = "mono_llvm_load_exception";
3747 LLVMTypeRef call_sig = LLVMFunctionType (ObjRefType (), NULL, 0, FALSE);
3748 LLVMValueRef callee = NULL;
3750 if (!callee) {
3751 if (ctx->cfg->compile_aot) {
3752 callee = get_callee (ctx, call_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3753 } else {
3754 // FIXME: This is broken.
3755 callee = LLVMAddFunction (ctx->lmodule, icall_name, call_sig);
3759 g_assert (builder && callee);
3761 return LLVMBuildCall (builder, callee, NULL, 0, icall_name);
3765 static LLVMValueRef
3766 mono_llvm_emit_match_exception_call (EmitContext *ctx, LLVMBuilderRef builder, gint32 region_start, gint32 region_end)
3768 const char *icall_name = "mono_llvm_match_exception";
3770 ctx->builder = builder;
3772 const int num_args = 5;
3773 LLVMValueRef args [num_args];
3774 args [0] = convert (ctx, get_aotconst (ctx, MONO_PATCH_INFO_AOT_JIT_INFO, GINT_TO_POINTER (ctx->cfg->method_index)), IntPtrType ());
3775 args [1] = LLVMConstInt (LLVMInt32Type (), region_start, 0);
3776 args [2] = LLVMConstInt (LLVMInt32Type (), region_end, 0);
3777 if (ctx->cfg->rgctx_var) {
3778 LLVMValueRef rgctx_alloc = ctx->addresses [ctx->cfg->rgctx_var->dreg];
3779 g_assert (rgctx_alloc);
3780 args [3] = LLVMBuildLoad (builder, convert (ctx, rgctx_alloc, LLVMPointerType (IntPtrType (), 0)), "");
3781 } else {
3782 args [3] = LLVMConstInt (IntPtrType (), 0, 0);
3784 if (ctx->this_arg)
3785 args [4] = convert (ctx, ctx->this_arg, IntPtrType ());
3786 else
3787 args [4] = LLVMConstInt (IntPtrType (), 0, 0);
3789 LLVMTypeRef match_sig = LLVMFunctionType5 (LLVMInt32Type (), IntPtrType (), LLVMInt32Type (), LLVMInt32Type (), IntPtrType (), IntPtrType (), FALSE);
3790 LLVMValueRef callee = ctx->module->match_exc;
3792 if (!callee) {
3793 if (ctx->cfg->compile_aot) {
3794 ctx->builder = builder;
3795 // get_callee expects ctx->builder to be the emitting builder
3796 callee = get_callee (ctx, match_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3797 } else {
3798 callee = ctx->module->match_exc = LLVMAddFunction (ctx->lmodule, icall_name, match_sig);
3799 LLVMAddGlobalMapping (ctx->module->ee, ctx->module->match_exc, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
3800 ctx->module->match_exc = callee;
3801 mono_memory_barrier ();
3805 g_assert (builder && callee);
3807 g_assert (ctx->ex_var);
3809 return LLVMBuildCall (builder, callee, args, num_args, icall_name);
3812 // FIXME: This won't work because the code-finding makes this
3813 // not a constant.
3814 /*#define MONO_PERSONALITY_DEBUG*/
3816 #ifdef MONO_PERSONALITY_DEBUG
3817 static const gboolean use_debug_personality = TRUE;
3818 static const char *default_personality_name = "mono_debug_personality";
3819 #else
3820 static const gboolean use_debug_personality = FALSE;
3821 static const char *default_personality_name = "__gxx_personality_v0";
3822 #endif
3824 static LLVMTypeRef
3825 default_cpp_lpad_exc_signature (void)
3827 static gboolean inited = FALSE;
3828 static LLVMTypeRef sig;
3830 if (!sig) {
3831 LLVMTypeRef signature [2];
3832 signature [0] = LLVMPointerType (LLVMInt8Type (), 0);
3833 signature [1] = LLVMInt32Type ();
3834 sig = LLVMStructType (signature, 2, FALSE);
3835 inited = TRUE;
3838 return sig;
3841 static LLVMValueRef
3842 get_mono_personality (EmitContext *ctx)
3844 LLVMValueRef personality = NULL;
3845 static gint32 mapping_inited = FALSE;
3846 LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
3848 if (!use_debug_personality) {
3849 if (ctx->cfg->compile_aot) {
3850 personality = get_intrinsic (ctx, default_personality_name);
3851 } else if (InterlockedCompareExchange (&mapping_inited, 1, 0) == 0) {
3852 personality = LLVMAddFunction (ctx->lmodule, default_personality_name, personality_type);
3853 LLVMAddGlobalMapping (ctx->module->ee, personality, personality);
3855 } else {
3856 if (ctx->cfg->compile_aot) {
3857 personality = get_callee (ctx, personality_type, MONO_PATCH_INFO_INTERNAL_METHOD, default_personality_name);
3858 } else {
3859 personality = LLVMAddFunction (ctx->lmodule, default_personality_name, personality_type);
3860 LLVMAddGlobalMapping (ctx->module->ee, personality, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, default_personality_name));
3861 mono_memory_barrier ();
3865 g_assert (personality);
3866 return personality;
3869 static LLVMBasicBlockRef
3870 emit_landing_pad (EmitContext *ctx, int group_index, int group_size)
3872 MonoCompile *cfg = ctx->cfg;
3873 LLVMBuilderRef old_builder = ctx->builder;
3874 MonoExceptionClause *group_start = cfg->header->clauses + group_index;
3876 LLVMBuilderRef lpadBuilder = create_builder (ctx);
3877 ctx->builder = lpadBuilder;
3879 MonoBasicBlock *handler_bb = cfg->cil_offset_to_bb [CLAUSE_START (group_start)];
3880 g_assert (handler_bb);
3882 // <resultval> = landingpad <somety> personality <type> <pers_fn> <clause>+
3883 LLVMValueRef personality = get_mono_personality (ctx);
3884 g_assert (personality);
3886 char *bb_name = g_strdup_printf ("LPAD%d_BB", group_index);
3887 LLVMBasicBlockRef lpad_bb = gen_bb (ctx, bb_name);
3888 g_free (bb_name);
3889 LLVMPositionBuilderAtEnd (lpadBuilder, lpad_bb);
3890 LLVMValueRef landing_pad = LLVMBuildLandingPad (lpadBuilder, default_cpp_lpad_exc_signature (), personality, 0, "");
3891 g_assert (landing_pad);
3893 LLVMValueRef cast = LLVMBuildBitCast (lpadBuilder, ctx->module->sentinel_exception, LLVMPointerType (LLVMInt8Type (), 0), "int8TypeInfo");
3894 LLVMAddClause (landing_pad, cast);
3896 LLVMBasicBlockRef resume_bb = gen_bb (ctx, "RESUME_BB");
3897 LLVMBuilderRef resume_builder = create_builder (ctx);
3898 ctx->builder = resume_builder;
3899 LLVMPositionBuilderAtEnd (resume_builder, resume_bb);
3901 emit_resume_eh (ctx, handler_bb);
3903 // Build match
3904 ctx->builder = lpadBuilder;
3905 LLVMPositionBuilderAtEnd (lpadBuilder, lpad_bb);
3907 gboolean finally_only = TRUE;
3909 MonoExceptionClause *group_cursor = group_start;
3911 for (int i = 0; i < group_size; i ++) {
3912 if (!(group_cursor->flags & MONO_EXCEPTION_CLAUSE_FINALLY))
3913 finally_only = FALSE;
3915 group_cursor++;
3918 // FIXME:
3919 // Handle landing pad inlining
3921 if (!finally_only) {
3922 // So at each level of the exception stack we will match the exception again.
3923 // During that match, we need to compare against the handler types for the current
3924 // protected region. We send the try start and end so that we can only check against
3925 // handlers for this lexical protected region.
3926 LLVMValueRef match = mono_llvm_emit_match_exception_call (ctx, lpadBuilder, group_start->try_offset, group_start->try_offset + group_start->try_len);
3928 // if returns -1, resume
3929 LLVMValueRef switch_ins = LLVMBuildSwitch (lpadBuilder, match, resume_bb, group_size);
3931 // else move to that target bb
3932 for (int i = 0; i < group_size; i++) {
3933 MonoExceptionClause *clause = group_start + i;
3934 int clause_index = clause - cfg->header->clauses;
3935 MonoBasicBlock *handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (clause_index));
3936 g_assert (handler_bb);
3937 g_assert (ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
3938 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE), ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
3940 } else {
3941 int clause_index = group_start - cfg->header->clauses;
3942 MonoBasicBlock *finally_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (clause_index));
3943 g_assert (finally_bb);
3945 LLVMBuildBr (ctx->builder, ctx->bblocks [finally_bb->block_num].call_handler_target_bb);
3948 ctx->builder = old_builder;
3950 return lpad_bb;
3954 static void
3955 emit_llvmonly_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBasicBlockRef cbb)
3957 int clause_index = MONO_REGION_CLAUSE_INDEX (bb->region);
3958 MonoExceptionClause *clause = &ctx->cfg->header->clauses [clause_index];
3960 // Make exception available to catch blocks
3961 if (!(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
3962 LLVMValueRef mono_exc = mono_llvm_emit_load_exception_call (ctx, ctx->builder);
3964 g_assert (ctx->ex_var);
3965 LLVMBuildStore (ctx->builder, LLVMBuildBitCast (ctx->builder, mono_exc, ObjRefType (), ""), ctx->ex_var);
3967 if (bb->in_scount == 1) {
3968 MonoInst *exvar = bb->in_stack [0];
3969 g_assert (!ctx->values [exvar->dreg]);
3970 g_assert (ctx->ex_var);
3971 ctx->values [exvar->dreg] = LLVMBuildLoad (ctx->builder, ctx->ex_var, "save_exception");
3972 emit_volatile_store (ctx, exvar->dreg);
3975 mono_llvm_emit_clear_exception_call (ctx, ctx->builder);
3978 LLVMBuilderRef handler_builder = create_builder (ctx);
3979 LLVMBasicBlockRef target_bb = ctx->bblocks [bb->block_num].call_handler_target_bb;
3980 LLVMPositionBuilderAtEnd (handler_builder, target_bb);
3982 // Make the handler code end with a jump to cbb
3983 LLVMBuildBr (handler_builder, cbb);
3986 static void
3987 emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder)
3989 MonoCompile *cfg = ctx->cfg;
3990 LLVMValueRef *values = ctx->values;
3991 LLVMModuleRef lmodule = ctx->lmodule;
3992 BBInfo *bblocks = ctx->bblocks;
3993 LLVMTypeRef i8ptr;
3994 LLVMValueRef personality;
3995 LLVMValueRef landing_pad;
3996 LLVMBasicBlockRef target_bb;
3997 MonoInst *exvar;
3998 static int ti_generator;
3999 char ti_name [128];
4000 LLVMValueRef type_info;
4001 int clause_index;
4002 GSList *l;
4004 // <resultval> = landingpad <somety> personality <type> <pers_fn> <clause>+
4006 if (cfg->compile_aot) {
4007 /* Use a dummy personality function */
4008 personality = LLVMGetNamedFunction (lmodule, "mono_personality");
4009 g_assert (personality);
4010 } else {
4011 #if LLVM_API_VERSION > 100
4012 personality = ctx->module->personality;
4013 if (!personality) {
4014 LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
4015 personality = LLVMAddFunction (ctx->lmodule, "mono_personality", personality_type);
4016 LLVMAddFunctionAttr (personality, LLVMNoUnwindAttribute);
4017 LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlock (personality, "ENTRY");
4018 LLVMBuilderRef builder2 = LLVMCreateBuilder ();
4019 LLVMPositionBuilderAtEnd (builder2, entry_bb);
4020 LLVMBuildRet (builder2, LLVMConstInt (LLVMInt32Type (), 0, FALSE));
4021 ctx->module->personality = personality;
4022 LLVMDisposeBuilder (builder2);
4024 #else
4025 static gint32 mapping_inited;
4027 personality = LLVMGetNamedFunction (lmodule, "mono_personality");
4029 if (InterlockedCompareExchange (&mapping_inited, 1, 0) == 0)
4030 LLVMAddGlobalMapping (ctx->module->ee, personality, (gpointer)mono_personality);
4031 #endif
4034 i8ptr = LLVMPointerType (LLVMInt8Type (), 0);
4036 clause_index = (mono_get_block_region_notry (cfg, bb->region) >> 8) - 1;
4039 * Create the type info
4041 sprintf (ti_name, "type_info_%d", ti_generator);
4042 ti_generator ++;
4044 if (cfg->compile_aot) {
4045 /* decode_eh_frame () in aot-runtime.c will decode this */
4046 type_info = LLVMAddGlobal (lmodule, LLVMInt32Type (), ti_name);
4047 LLVMSetInitializer (type_info, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE));
4050 * These symbols are not really used, the clause_index is embedded into the EH tables generated by DwarfMonoException in LLVM.
4052 LLVMSetLinkage (type_info, LLVMInternalLinkage);
4053 } else {
4054 #if LLVM_API_VERSION > 100
4055 type_info = LLVMAddGlobal (lmodule, LLVMInt32Type (), ti_name);
4056 LLVMSetInitializer (type_info, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE));
4057 #else
4058 gint32 *ti;
4061 * After the cfg mempool is freed, the type info will point to stale memory,
4062 * but this is not a problem, since we decode it once in exception_cb during
4063 * compilation.
4065 ti = (gint32*)mono_mempool_alloc (cfg->mempool, sizeof (gint32));
4066 *(gint32*)ti = clause_index;
4068 type_info = LLVMAddGlobal (lmodule, i8ptr, ti_name);
4070 LLVMAddGlobalMapping (ctx->module->ee, type_info, ti);
4071 #endif
4075 LLVMTypeRef members [2], ret_type;
4077 members [0] = i8ptr;
4078 members [1] = LLVMInt32Type ();
4079 ret_type = LLVMStructType (members, 2, FALSE);
4081 landing_pad = LLVMBuildLandingPad (builder, ret_type, personality, 1, "");
4082 LLVMAddClause (landing_pad, type_info);
4084 /* Store the exception into the exvar */
4085 if (ctx->ex_var)
4086 LLVMBuildStore (builder, convert (ctx, LLVMBuildExtractValue (builder, landing_pad, 0, "ex_obj"), ObjRefType ()), ctx->ex_var);
4090 * LLVM throw sites are associated with a one landing pad, and LLVM generated
4091 * code expects control to be transferred to this landing pad even in the
4092 * presence of nested clauses. The landing pad needs to branch to the landing
4093 * pads belonging to nested clauses based on the selector value returned by
4094 * the landing pad instruction, which is passed to the landing pad in a
4095 * register by the EH code.
4097 target_bb = bblocks [bb->block_num].call_handler_target_bb;
4098 g_assert (target_bb);
4101 * Branch to the correct landing pad
4103 LLVMValueRef ex_selector = LLVMBuildExtractValue (builder, landing_pad, 1, "ex_selector");
4104 LLVMValueRef switch_ins = LLVMBuildSwitch (builder, ex_selector, target_bb, 0);
4106 for (l = ctx->nested_in [clause_index]; l; l = l->next) {
4107 int nesting_clause_index = GPOINTER_TO_INT (l->data);
4108 MonoBasicBlock *handler_bb;
4110 handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (nesting_clause_index));
4111 g_assert (handler_bb);
4113 g_assert (ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
4114 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), nesting_clause_index, FALSE), ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
4117 /* Start a new bblock which CALL_HANDLER can branch to */
4118 target_bb = bblocks [bb->block_num].call_handler_target_bb;
4119 if (target_bb) {
4120 ctx->builder = builder = create_builder (ctx);
4121 LLVMPositionBuilderAtEnd (ctx->builder, target_bb);
4123 ctx->bblocks [bb->block_num].end_bblock = target_bb;
4125 /* Store the exception into the IL level exvar */
4126 if (bb->in_scount == 1) {
4127 g_assert (bb->in_scount == 1);
4128 exvar = bb->in_stack [0];
4130 // FIXME: This is shared with filter clauses ?
4131 g_assert (!values [exvar->dreg]);
4133 g_assert (ctx->ex_var);
4134 values [exvar->dreg] = LLVMBuildLoad (builder, ctx->ex_var, "");
4135 emit_volatile_store (ctx, exvar->dreg);
4140 static void
4141 process_bb (EmitContext *ctx, MonoBasicBlock *bb)
4143 MonoCompile *cfg = ctx->cfg;
4144 MonoMethodSignature *sig = ctx->sig;
4145 LLVMValueRef method = ctx->lmethod;
4146 LLVMValueRef *values = ctx->values;
4147 LLVMValueRef *addresses = ctx->addresses;
4148 LLVMCallInfo *linfo = ctx->linfo;
4149 BBInfo *bblocks = ctx->bblocks;
4150 MonoInst *ins;
4151 LLVMBasicBlockRef cbb;
4152 LLVMBuilderRef builder, starting_builder;
4153 gboolean has_terminator;
4154 LLVMValueRef v;
4155 LLVMValueRef lhs, rhs;
4156 int nins = 0;
4158 cbb = get_end_bb (ctx, bb);
4160 builder = create_builder (ctx);
4161 ctx->builder = builder;
4162 LLVMPositionBuilderAtEnd (builder, cbb);
4164 if (!ctx_ok (ctx))
4165 return;
4167 if (bb->flags & BB_EXCEPTION_HANDLER) {
4168 if (!ctx->llvm_only && !bblocks [bb->block_num].invoke_target) {
4169 set_failure (ctx, "handler without invokes");
4170 return;
4173 if (ctx->llvm_only)
4174 emit_llvmonly_handler_start (ctx, bb, cbb);
4175 else
4176 emit_handler_start (ctx, bb, builder);
4177 if (!ctx_ok (ctx))
4178 return;
4179 builder = ctx->builder;
4182 has_terminator = FALSE;
4183 starting_builder = builder;
4184 for (ins = bb->code; ins; ins = ins->next) {
4185 const char *spec = LLVM_INS_INFO (ins->opcode);
4186 char *dname = NULL;
4187 char dname_buf [128];
4189 emit_dbg_loc (ctx, builder, ins->cil_code);
4191 nins ++;
4192 if (nins > 1000) {
4194 * Some steps in llc are non-linear in the size of basic blocks, see #5714.
4195 * Start a new bblock.
4196 * Prevent the bblocks to be merged by doing a volatile load + cond branch
4197 * from localloc-ed memory.
4199 if (!cfg->llvm_only)
4200 ;//set_failure (ctx, "basic block too long");
4202 if (!ctx->long_bb_break_var) {
4203 ctx->long_bb_break_var = build_alloca_llvm_type_name (ctx, LLVMInt32Type (), 0, "long_bb_break");
4204 mono_llvm_build_store (ctx->alloca_builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), ctx->long_bb_break_var, TRUE, LLVM_BARRIER_NONE);
4207 cbb = gen_bb (ctx, "CONT_LONG_BB");
4208 LLVMBasicBlockRef dummy_bb = gen_bb (ctx, "CONT_LONG_BB_DUMMY");
4210 LLVMValueRef load = mono_llvm_build_load (builder, ctx->long_bb_break_var, "", TRUE);
4212 * The long_bb_break_var is initialized to 0 in the prolog, so this branch will always go to 'cbb'
4213 * but llvm doesn't know that, so the branch is not going to be eliminated.
4215 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntEQ, load, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
4217 LLVMBuildCondBr (builder, cmp, cbb, dummy_bb);
4219 /* Emit a dummy false bblock which does nothing but contains a volatile store so it cannot be eliminated */
4220 ctx->builder = builder = create_builder (ctx);
4221 LLVMPositionBuilderAtEnd (builder, dummy_bb);
4222 mono_llvm_build_store (builder, LLVMConstInt (LLVMInt32Type (), 1, FALSE), ctx->long_bb_break_var, TRUE, LLVM_BARRIER_NONE);
4223 LLVMBuildBr (builder, cbb);
4225 ctx->builder = builder = create_builder (ctx);
4226 LLVMPositionBuilderAtEnd (builder, cbb);
4227 ctx->bblocks [bb->block_num].end_bblock = cbb;
4228 nins = 0;
4231 if (has_terminator)
4232 /* There could be instructions after a terminator, skip them */
4233 break;
4235 if (spec [MONO_INST_DEST] != ' ' && !MONO_IS_STORE_MEMBASE (ins)) {
4236 sprintf (dname_buf, "t%d", ins->dreg);
4237 dname = dname_buf;
4240 if (spec [MONO_INST_SRC1] != ' ' && spec [MONO_INST_SRC1] != 'v') {
4241 MonoInst *var = get_vreg_to_inst (cfg, ins->sreg1);
4243 if (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) && var->opcode != OP_GSHAREDVT_ARG_REGOFFSET) {
4244 lhs = emit_volatile_load (ctx, ins->sreg1);
4245 } else {
4246 /* It is ok for SETRET to have an uninitialized argument */
4247 if (!values [ins->sreg1] && ins->opcode != OP_SETRET) {
4248 set_failure (ctx, "sreg1");
4249 return;
4251 lhs = values [ins->sreg1];
4253 } else {
4254 lhs = NULL;
4257 if (spec [MONO_INST_SRC2] != ' ' && spec [MONO_INST_SRC2] != ' ') {
4258 MonoInst *var = get_vreg_to_inst (cfg, ins->sreg2);
4259 if (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) {
4260 rhs = emit_volatile_load (ctx, ins->sreg2);
4261 } else {
4262 if (!values [ins->sreg2]) {
4263 set_failure (ctx, "sreg2");
4264 return;
4266 rhs = values [ins->sreg2];
4268 } else {
4269 rhs = NULL;
4272 //mono_print_ins (ins);
4273 switch (ins->opcode) {
4274 case OP_NOP:
4275 case OP_NOT_NULL:
4276 case OP_LIVERANGE_START:
4277 case OP_LIVERANGE_END:
4278 break;
4279 case OP_ICONST:
4280 values [ins->dreg] = LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE);
4281 break;
4282 case OP_I8CONST:
4283 #if SIZEOF_VOID_P == 4
4284 values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins), FALSE);
4285 #else
4286 values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), (gint64)ins->inst_c0, FALSE);
4287 #endif
4288 break;
4289 case OP_R8CONST:
4290 values [ins->dreg] = LLVMConstReal (LLVMDoubleType (), *(double*)ins->inst_p0);
4291 break;
4292 case OP_R4CONST:
4293 if (cfg->r4fp)
4294 values [ins->dreg] = LLVMConstReal (LLVMFloatType (), *(float*)ins->inst_p0);
4295 else
4296 values [ins->dreg] = LLVMConstFPExt (LLVMConstReal (LLVMFloatType (), *(float*)ins->inst_p0), LLVMDoubleType ());
4297 break;
4298 case OP_DUMMY_ICONST:
4299 values [ins->dreg] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
4300 break;
4301 case OP_DUMMY_I8CONST:
4302 values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
4303 break;
4304 case OP_DUMMY_R8CONST:
4305 values [ins->dreg] = LLVMConstReal (LLVMDoubleType (), 0.0f);
4306 break;
4307 case OP_BR: {
4308 LLVMBasicBlockRef target_bb = get_bb (ctx, ins->inst_target_bb);
4309 LLVMBuildBr (builder, target_bb);
4310 has_terminator = TRUE;
4311 break;
4313 case OP_SWITCH: {
4314 int i;
4315 LLVMValueRef v;
4316 char bb_name [128];
4317 LLVMBasicBlockRef new_bb;
4318 LLVMBuilderRef new_builder;
4320 // The default branch is already handled
4321 // FIXME: Handle it here
4323 /* Start new bblock */
4324 sprintf (bb_name, "SWITCH_DEFAULT_BB%d", ctx->default_index ++);
4325 new_bb = LLVMAppendBasicBlock (ctx->lmethod, bb_name);
4327 lhs = convert (ctx, lhs, LLVMInt32Type ());
4328 v = LLVMBuildSwitch (builder, lhs, new_bb, GPOINTER_TO_UINT (ins->klass));
4329 for (i = 0; i < GPOINTER_TO_UINT (ins->klass); ++i) {
4330 MonoBasicBlock *target_bb = ins->inst_many_bb [i];
4332 LLVMAddCase (v, LLVMConstInt (LLVMInt32Type (), i, FALSE), get_bb (ctx, target_bb));
4335 new_builder = create_builder (ctx);
4336 LLVMPositionBuilderAtEnd (new_builder, new_bb);
4337 LLVMBuildUnreachable (new_builder);
4339 has_terminator = TRUE;
4340 g_assert (!ins->next);
4342 break;
4345 case OP_SETRET:
4346 switch (linfo->ret.storage) {
4347 case LLVMArgVtypeInReg: {
4348 LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
4349 LLVMValueRef val, addr, retval;
4350 int i;
4352 retval = LLVMGetUndef (ret_type);
4354 if (!addresses [ins->sreg1]) {
4356 * The return type is an LLVM vector type, have to convert between it and the
4357 * real return type which is a struct type.
4359 g_assert (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (sig->ret)));
4360 /* Convert to 2xi64 first */
4361 val = LLVMBuildBitCast (builder, values [ins->sreg1], LLVMVectorType (IntPtrType (), 2), "");
4363 for (i = 0; i < 2; ++i) {
4364 if (linfo->ret.pair_storage [i] == LLVMArgInIReg) {
4365 retval = LLVMBuildInsertValue (builder, retval, LLVMBuildExtractElement (builder, val, LLVMConstInt (LLVMInt32Type (), i, FALSE), ""), i, "");
4366 } else {
4367 g_assert (linfo->ret.pair_storage [i] == LLVMArgNone);
4370 } else {
4371 addr = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), "");
4372 for (i = 0; i < 2; ++i) {
4373 if (linfo->ret.pair_storage [i] == LLVMArgInIReg) {
4374 LLVMValueRef indexes [2], part_addr;
4376 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
4377 indexes [1] = LLVMConstInt (LLVMInt32Type (), i, FALSE);
4378 part_addr = LLVMBuildGEP (builder, addr, indexes, 2, "");
4380 retval = LLVMBuildInsertValue (builder, retval, LLVMBuildLoad (builder, part_addr, ""), i, "");
4381 } else {
4382 g_assert (linfo->ret.pair_storage [i] == LLVMArgNone);
4386 LLVMBuildRet (builder, retval);
4387 break;
4389 case LLVMArgVtypeAsScalar: {
4390 LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
4391 LLVMValueRef retval;
4393 g_assert (addresses [ins->sreg1]);
4395 retval = LLVMBuildLoad (builder, LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), ""), "");
4396 LLVMBuildRet (builder, retval);
4397 break;
4399 case LLVMArgVtypeByVal: {
4400 LLVMValueRef retval;
4402 g_assert (addresses [ins->sreg1]);
4403 retval = LLVMBuildLoad (builder, addresses [ins->sreg1], "");
4404 LLVMBuildRet (builder, retval);
4405 break;
4407 case LLVMArgVtypeByRef: {
4408 LLVMBuildRetVoid (builder);
4409 break;
4411 case LLVMArgGsharedvtFixed: {
4412 LLVMTypeRef ret_type = type_to_llvm_type (ctx, sig->ret);
4413 /* The return value is in lhs, need to store to the vret argument */
4414 /* sreg1 might not be set */
4415 if (lhs) {
4416 g_assert (cfg->vret_addr);
4417 g_assert (values [cfg->vret_addr->dreg]);
4418 LLVMBuildStore (builder, convert (ctx, lhs, ret_type), convert (ctx, values [cfg->vret_addr->dreg], LLVMPointerType (ret_type, 0)));
4420 LLVMBuildRetVoid (builder);
4421 break;
4423 case LLVMArgGsharedvtFixedVtype: {
4424 /* Already set */
4425 LLVMBuildRetVoid (builder);
4426 break;
4428 case LLVMArgGsharedvtVariable: {
4429 /* Already set */
4430 LLVMBuildRetVoid (builder);
4431 break;
4433 case LLVMArgVtypeRetAddr: {
4434 LLVMBuildRetVoid (builder);
4435 break;
4437 case LLVMArgAsIArgs:
4438 case LLVMArgFpStruct: {
4439 LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
4440 LLVMValueRef retval;
4442 g_assert (addresses [ins->sreg1]);
4443 retval = LLVMBuildLoad (builder, convert (ctx, addresses [ins->sreg1], LLVMPointerType (ret_type, 0)), "");
4444 LLVMBuildRet (builder, retval);
4445 break;
4447 case LLVMArgNone:
4448 case LLVMArgNormal: {
4449 if (!lhs || ctx->is_dead [ins->sreg1]) {
4451 * The method did not set its return value, probably because it
4452 * ends with a throw.
4454 if (cfg->vret_addr)
4455 LLVMBuildRetVoid (builder);
4456 else
4457 LLVMBuildRet (builder, LLVMConstNull (type_to_llvm_type (ctx, sig->ret)));
4458 } else {
4459 LLVMBuildRet (builder, convert (ctx, lhs, type_to_llvm_type (ctx, sig->ret)));
4461 has_terminator = TRUE;
4462 break;
4464 default:
4465 g_assert_not_reached ();
4466 break;
4468 break;
4469 case OP_ICOMPARE:
4470 case OP_FCOMPARE:
4471 case OP_RCOMPARE:
4472 case OP_LCOMPARE:
4473 case OP_COMPARE:
4474 case OP_ICOMPARE_IMM:
4475 case OP_LCOMPARE_IMM:
4476 case OP_COMPARE_IMM: {
4477 CompRelation rel;
4478 LLVMValueRef cmp, args [16];
4479 gboolean likely = (ins->flags & MONO_INST_LIKELY) != 0;
4481 if (ins->next->opcode == OP_NOP)
4482 break;
4484 if (ins->next->opcode == OP_BR)
4485 /* The comparison result is not needed */
4486 continue;
4488 rel = mono_opcode_to_cond (ins->next->opcode);
4490 if (ins->opcode == OP_ICOMPARE_IMM) {
4491 lhs = convert (ctx, lhs, LLVMInt32Type ());
4492 rhs = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
4494 if (ins->opcode == OP_LCOMPARE_IMM) {
4495 lhs = convert (ctx, lhs, LLVMInt64Type ());
4496 rhs = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins), FALSE);
4498 if (ins->opcode == OP_LCOMPARE) {
4499 lhs = convert (ctx, lhs, LLVMInt64Type ());
4500 rhs = convert (ctx, rhs, LLVMInt64Type ());
4502 if (ins->opcode == OP_ICOMPARE) {
4503 lhs = convert (ctx, lhs, LLVMInt32Type ());
4504 rhs = convert (ctx, rhs, LLVMInt32Type ());
4507 if (lhs && rhs) {
4508 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind)
4509 rhs = convert (ctx, rhs, LLVMTypeOf (lhs));
4510 else if (LLVMGetTypeKind (LLVMTypeOf (rhs)) == LLVMPointerTypeKind)
4511 lhs = convert (ctx, lhs, LLVMTypeOf (rhs));
4514 /* We use COMPARE+SETcc/Bcc, llvm uses SETcc+br cond */
4515 if (ins->opcode == OP_FCOMPARE) {
4516 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMDoubleType ()), convert (ctx, rhs, LLVMDoubleType ()), "");
4517 } else if (ins->opcode == OP_RCOMPARE) {
4518 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMFloatType ()), convert (ctx, rhs, LLVMFloatType ()), "");
4519 } else if (ins->opcode == OP_COMPARE_IMM) {
4520 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind && ins->inst_imm == 0)
4521 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, LLVMConstNull (LLVMTypeOf (lhs)), "");
4522 else
4523 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), "");
4524 } else if (ins->opcode == OP_LCOMPARE_IMM) {
4525 if (SIZEOF_REGISTER == 4 && COMPILE_LLVM (cfg)) {
4526 /* The immediate is encoded in two fields */
4527 guint64 l = ((guint64)(guint32)ins->inst_offset << 32) | ((guint32)ins->inst_imm);
4528 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, LLVMInt64Type ()), LLVMConstInt (LLVMInt64Type (), l, FALSE), "");
4529 } else {
4530 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, LLVMInt64Type ()), LLVMConstInt (LLVMInt64Type (), ins->inst_imm, FALSE), "");
4533 else if (ins->opcode == OP_COMPARE) {
4534 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind && LLVMTypeOf (lhs) == LLVMTypeOf (rhs))
4535 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, rhs, "");
4536 else
4537 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, IntPtrType ()), convert (ctx, rhs, IntPtrType ()), "");
4538 } else
4539 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, rhs, "");
4541 if (likely) {
4542 args [0] = cmp;
4543 args [1] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
4544 cmp = LLVMBuildCall (ctx->builder, get_intrinsic (ctx, "llvm.expect.i1"), args, 2, "");
4547 if (MONO_IS_COND_BRANCH_OP (ins->next)) {
4548 if (ins->next->inst_true_bb == ins->next->inst_false_bb) {
4550 * If the target bb contains PHI instructions, LLVM requires
4551 * two PHI entries for this bblock, while we only generate one.
4552 * So convert this to an unconditional bblock. (bxc #171).
4554 LLVMBuildBr (builder, get_bb (ctx, ins->next->inst_true_bb));
4555 } else {
4556 LLVMBuildCondBr (builder, cmp, get_bb (ctx, ins->next->inst_true_bb), get_bb (ctx, ins->next->inst_false_bb));
4558 has_terminator = TRUE;
4559 } else if (MONO_IS_SETCC (ins->next)) {
4560 sprintf (dname_buf, "t%d", ins->next->dreg);
4561 dname = dname_buf;
4562 values [ins->next->dreg] = LLVMBuildZExt (builder, cmp, LLVMInt32Type (), dname);
4564 /* Add stores for volatile variables */
4565 emit_volatile_store (ctx, ins->next->dreg);
4566 } else if (MONO_IS_COND_EXC (ins->next)) {
4567 emit_cond_system_exception (ctx, bb, (const char*)ins->next->inst_p1, cmp);
4568 if (!ctx_ok (ctx))
4569 break;
4570 builder = ctx->builder;
4571 } else {
4572 set_failure (ctx, "next");
4573 break;
4576 ins = ins->next;
4577 break;
4579 case OP_FCEQ:
4580 case OP_FCNEQ:
4581 case OP_FCLT:
4582 case OP_FCLT_UN:
4583 case OP_FCGT:
4584 case OP_FCGT_UN:
4585 case OP_FCGE:
4586 case OP_FCLE: {
4587 CompRelation rel;
4588 LLVMValueRef cmp;
4590 rel = mono_opcode_to_cond (ins->opcode);
4592 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMDoubleType ()), convert (ctx, rhs, LLVMDoubleType ()), "");
4593 values [ins->dreg] = LLVMBuildZExt (builder, cmp, LLVMInt32Type (), dname);
4594 break;
4596 case OP_RCEQ:
4597 case OP_RCLT:
4598 case OP_RCLT_UN:
4599 case OP_RCGT:
4600 case OP_RCGT_UN: {
4601 CompRelation rel;
4602 LLVMValueRef cmp;
4604 rel = mono_opcode_to_cond (ins->opcode);
4606 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMFloatType ()), convert (ctx, rhs, LLVMFloatType ()), "");
4607 values [ins->dreg] = LLVMBuildZExt (builder, cmp, LLVMInt32Type (), dname);
4608 break;
4610 case OP_PHI:
4611 case OP_FPHI:
4612 case OP_VPHI:
4613 case OP_XPHI: {
4614 int i;
4615 gboolean empty = TRUE;
4617 /* Check that all input bblocks really branch to us */
4618 for (i = 0; i < bb->in_count; ++i) {
4619 if (bb->in_bb [i]->last_ins && bb->in_bb [i]->last_ins->opcode == OP_NOT_REACHED)
4620 ins->inst_phi_args [i + 1] = -1;
4621 else
4622 empty = FALSE;
4625 if (empty) {
4626 /* LLVM doesn't like phi instructions with zero operands */
4627 ctx->is_dead [ins->dreg] = TRUE;
4628 break;
4631 /* Created earlier, insert it now */
4632 LLVMInsertIntoBuilder (builder, values [ins->dreg]);
4634 for (i = 0; i < ins->inst_phi_args [0]; i++) {
4635 int sreg1 = ins->inst_phi_args [i + 1];
4636 int count, j;
4639 * Count the number of times the incoming bblock branches to us,
4640 * since llvm requires a separate entry for each.
4642 if (bb->in_bb [i]->last_ins && bb->in_bb [i]->last_ins->opcode == OP_SWITCH) {
4643 MonoInst *switch_ins = bb->in_bb [i]->last_ins;
4645 count = 0;
4646 for (j = 0; j < GPOINTER_TO_UINT (switch_ins->klass); ++j) {
4647 if (switch_ins->inst_many_bb [j] == bb)
4648 count ++;
4650 } else {
4651 count = 1;
4654 /* Remember for later */
4655 for (j = 0; j < count; ++j) {
4656 PhiNode *node = (PhiNode*)mono_mempool_alloc0 (ctx->mempool, sizeof (PhiNode));
4657 node->bb = bb;
4658 node->phi = ins;
4659 node->in_bb = bb->in_bb [i];
4660 node->sreg = sreg1;
4661 bblocks [bb->in_bb [i]->block_num].phi_nodes = g_slist_prepend_mempool (ctx->mempool, bblocks [bb->in_bb [i]->block_num].phi_nodes, node);
4664 break;
4666 case OP_MOVE:
4667 case OP_LMOVE:
4668 case OP_XMOVE:
4669 case OP_SETFRET:
4670 g_assert (lhs);
4671 values [ins->dreg] = lhs;
4672 break;
4673 case OP_FMOVE:
4674 case OP_RMOVE: {
4675 MonoInst *var = get_vreg_to_inst (cfg, ins->dreg);
4677 g_assert (lhs);
4678 values [ins->dreg] = lhs;
4680 if (var && var->klass->byval_arg.type == MONO_TYPE_R4) {
4682 * This is added by the spilling pass in case of the JIT,
4683 * but we have to do it ourselves.
4685 values [ins->dreg] = convert (ctx, values [ins->dreg], LLVMFloatType ());
4687 break;
4689 case OP_MOVE_F_TO_I4: {
4690 values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildFPTrunc (builder, lhs, LLVMFloatType (), ""), LLVMInt32Type (), "");
4691 break;
4693 case OP_MOVE_I4_TO_F: {
4694 values [ins->dreg] = LLVMBuildFPExt (builder, LLVMBuildBitCast (builder, lhs, LLVMFloatType (), ""), LLVMDoubleType (), "");
4695 break;
4697 case OP_MOVE_F_TO_I8: {
4698 values [ins->dreg] = LLVMBuildBitCast (builder, lhs, LLVMInt64Type (), "");
4699 break;
4701 case OP_MOVE_I8_TO_F: {
4702 values [ins->dreg] = LLVMBuildBitCast (builder, lhs, LLVMDoubleType (), "");
4703 break;
4705 case OP_IADD:
4706 case OP_ISUB:
4707 case OP_IAND:
4708 case OP_IMUL:
4709 case OP_IDIV:
4710 case OP_IDIV_UN:
4711 case OP_IREM:
4712 case OP_IREM_UN:
4713 case OP_IOR:
4714 case OP_IXOR:
4715 case OP_ISHL:
4716 case OP_ISHR:
4717 case OP_ISHR_UN:
4718 case OP_FADD:
4719 case OP_FSUB:
4720 case OP_FMUL:
4721 case OP_FDIV:
4722 case OP_LADD:
4723 case OP_LSUB:
4724 case OP_LMUL:
4725 case OP_LDIV:
4726 case OP_LDIV_UN:
4727 case OP_LREM:
4728 case OP_LREM_UN:
4729 case OP_LAND:
4730 case OP_LOR:
4731 case OP_LXOR:
4732 case OP_LSHL:
4733 case OP_LSHR:
4734 case OP_LSHR_UN:
4735 lhs = convert (ctx, lhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
4736 rhs = convert (ctx, rhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
4738 emit_div_check (ctx, builder, bb, ins, lhs, rhs);
4739 if (!ctx_ok (ctx))
4740 break;
4741 builder = ctx->builder;
4743 switch (ins->opcode) {
4744 case OP_IADD:
4745 case OP_LADD:
4746 values [ins->dreg] = LLVMBuildAdd (builder, lhs, rhs, dname);
4747 break;
4748 case OP_ISUB:
4749 case OP_LSUB:
4750 values [ins->dreg] = LLVMBuildSub (builder, lhs, rhs, dname);
4751 break;
4752 case OP_IMUL:
4753 case OP_LMUL:
4754 values [ins->dreg] = LLVMBuildMul (builder, lhs, rhs, dname);
4755 break;
4756 case OP_IREM:
4757 case OP_LREM:
4758 values [ins->dreg] = LLVMBuildSRem (builder, lhs, rhs, dname);
4759 break;
4760 case OP_IREM_UN:
4761 case OP_LREM_UN:
4762 values [ins->dreg] = LLVMBuildURem (builder, lhs, rhs, dname);
4763 break;
4764 case OP_IDIV:
4765 case OP_LDIV:
4766 values [ins->dreg] = LLVMBuildSDiv (builder, lhs, rhs, dname);
4767 break;
4768 case OP_IDIV_UN:
4769 case OP_LDIV_UN:
4770 values [ins->dreg] = LLVMBuildUDiv (builder, lhs, rhs, dname);
4771 break;
4772 case OP_FDIV:
4773 case OP_RDIV:
4774 values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, dname);
4775 break;
4776 case OP_IAND:
4777 case OP_LAND:
4778 values [ins->dreg] = LLVMBuildAnd (builder, lhs, rhs, dname);
4779 break;
4780 case OP_IOR:
4781 case OP_LOR:
4782 values [ins->dreg] = LLVMBuildOr (builder, lhs, rhs, dname);
4783 break;
4784 case OP_IXOR:
4785 case OP_LXOR:
4786 values [ins->dreg] = LLVMBuildXor (builder, lhs, rhs, dname);
4787 break;
4788 case OP_ISHL:
4789 case OP_LSHL:
4790 values [ins->dreg] = LLVMBuildShl (builder, lhs, rhs, dname);
4791 break;
4792 case OP_ISHR:
4793 case OP_LSHR:
4794 values [ins->dreg] = LLVMBuildAShr (builder, lhs, rhs, dname);
4795 break;
4796 case OP_ISHR_UN:
4797 case OP_LSHR_UN:
4798 values [ins->dreg] = LLVMBuildLShr (builder, lhs, rhs, dname);
4799 break;
4801 case OP_FADD:
4802 values [ins->dreg] = LLVMBuildFAdd (builder, lhs, rhs, dname);
4803 break;
4804 case OP_FSUB:
4805 values [ins->dreg] = LLVMBuildFSub (builder, lhs, rhs, dname);
4806 break;
4807 case OP_FMUL:
4808 values [ins->dreg] = LLVMBuildFMul (builder, lhs, rhs, dname);
4809 break;
4811 default:
4812 g_assert_not_reached ();
4814 break;
4815 case OP_RADD:
4816 case OP_RSUB:
4817 case OP_RMUL:
4818 case OP_RDIV: {
4819 lhs = convert (ctx, lhs, LLVMFloatType ());
4820 rhs = convert (ctx, rhs, LLVMFloatType ());
4821 switch (ins->opcode) {
4822 case OP_RADD:
4823 values [ins->dreg] = LLVMBuildFAdd (builder, lhs, rhs, dname);
4824 break;
4825 case OP_RSUB:
4826 values [ins->dreg] = LLVMBuildFSub (builder, lhs, rhs, dname);
4827 break;
4828 case OP_RMUL:
4829 values [ins->dreg] = LLVMBuildFMul (builder, lhs, rhs, dname);
4830 break;
4831 case OP_RDIV:
4832 values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, dname);
4833 break;
4834 default:
4835 g_assert_not_reached ();
4836 break;
4838 break;
4840 case OP_IADD_IMM:
4841 case OP_ISUB_IMM:
4842 case OP_IMUL_IMM:
4843 case OP_IREM_IMM:
4844 case OP_IREM_UN_IMM:
4845 case OP_IDIV_IMM:
4846 case OP_IDIV_UN_IMM:
4847 case OP_IAND_IMM:
4848 case OP_IOR_IMM:
4849 case OP_IXOR_IMM:
4850 case OP_ISHL_IMM:
4851 case OP_ISHR_IMM:
4852 case OP_ISHR_UN_IMM:
4853 case OP_LADD_IMM:
4854 case OP_LSUB_IMM:
4855 case OP_LMUL_IMM:
4856 case OP_LREM_IMM:
4857 case OP_LAND_IMM:
4858 case OP_LOR_IMM:
4859 case OP_LXOR_IMM:
4860 case OP_LSHL_IMM:
4861 case OP_LSHR_IMM:
4862 case OP_LSHR_UN_IMM:
4863 case OP_ADD_IMM:
4864 case OP_AND_IMM:
4865 case OP_MUL_IMM:
4866 case OP_SHL_IMM:
4867 case OP_SHR_IMM:
4868 case OP_SHR_UN_IMM: {
4869 LLVMValueRef imm;
4871 if (spec [MONO_INST_SRC1] == 'l') {
4872 imm = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins), FALSE);
4873 } else {
4874 imm = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
4877 emit_div_check (ctx, builder, bb, ins, lhs, imm);
4878 if (!ctx_ok (ctx))
4879 break;
4880 builder = ctx->builder;
4882 #if SIZEOF_VOID_P == 4
4883 if (ins->opcode == OP_LSHL_IMM || ins->opcode == OP_LSHR_IMM || ins->opcode == OP_LSHR_UN_IMM)
4884 imm = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
4885 #endif
4887 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind)
4888 lhs = convert (ctx, lhs, IntPtrType ());
4889 imm = convert (ctx, imm, LLVMTypeOf (lhs));
4890 switch (ins->opcode) {
4891 case OP_IADD_IMM:
4892 case OP_LADD_IMM:
4893 case OP_ADD_IMM:
4894 values [ins->dreg] = LLVMBuildAdd (builder, lhs, imm, dname);
4895 break;
4896 case OP_ISUB_IMM:
4897 case OP_LSUB_IMM:
4898 values [ins->dreg] = LLVMBuildSub (builder, lhs, imm, dname);
4899 break;
4900 case OP_IMUL_IMM:
4901 case OP_MUL_IMM:
4902 case OP_LMUL_IMM:
4903 values [ins->dreg] = LLVMBuildMul (builder, lhs, imm, dname);
4904 break;
4905 case OP_IDIV_IMM:
4906 case OP_LDIV_IMM:
4907 values [ins->dreg] = LLVMBuildSDiv (builder, lhs, imm, dname);
4908 break;
4909 case OP_IDIV_UN_IMM:
4910 case OP_LDIV_UN_IMM:
4911 values [ins->dreg] = LLVMBuildUDiv (builder, lhs, imm, dname);
4912 break;
4913 case OP_IREM_IMM:
4914 case OP_LREM_IMM:
4915 values [ins->dreg] = LLVMBuildSRem (builder, lhs, imm, dname);
4916 break;
4917 case OP_IREM_UN_IMM:
4918 values [ins->dreg] = LLVMBuildURem (builder, lhs, imm, dname);
4919 break;
4920 case OP_IAND_IMM:
4921 case OP_LAND_IMM:
4922 case OP_AND_IMM:
4923 values [ins->dreg] = LLVMBuildAnd (builder, lhs, imm, dname);
4924 break;
4925 case OP_IOR_IMM:
4926 case OP_LOR_IMM:
4927 values [ins->dreg] = LLVMBuildOr (builder, lhs, imm, dname);
4928 break;
4929 case OP_IXOR_IMM:
4930 case OP_LXOR_IMM:
4931 values [ins->dreg] = LLVMBuildXor (builder, lhs, imm, dname);
4932 break;
4933 case OP_ISHL_IMM:
4934 case OP_LSHL_IMM:
4935 case OP_SHL_IMM:
4936 values [ins->dreg] = LLVMBuildShl (builder, lhs, imm, dname);
4937 break;
4938 case OP_ISHR_IMM:
4939 case OP_LSHR_IMM:
4940 case OP_SHR_IMM:
4941 values [ins->dreg] = LLVMBuildAShr (builder, lhs, imm, dname);
4942 break;
4943 case OP_ISHR_UN_IMM:
4944 /* This is used to implement conv.u4, so the lhs could be an i8 */
4945 lhs = convert (ctx, lhs, LLVMInt32Type ());
4946 imm = convert (ctx, imm, LLVMInt32Type ());
4947 values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
4948 break;
4949 case OP_LSHR_UN_IMM:
4950 case OP_SHR_UN_IMM:
4951 values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
4952 break;
4953 default:
4954 g_assert_not_reached ();
4956 break;
4958 case OP_INEG:
4959 values [ins->dreg] = LLVMBuildSub (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), convert (ctx, lhs, LLVMInt32Type ()), dname);
4960 break;
4961 case OP_LNEG:
4962 values [ins->dreg] = LLVMBuildSub (builder, LLVMConstInt (LLVMInt64Type (), 0, FALSE), lhs, dname);
4963 break;
4964 case OP_FNEG:
4965 lhs = convert (ctx, lhs, LLVMDoubleType ());
4966 values [ins->dreg] = LLVMBuildFSub (builder, LLVMConstReal (LLVMDoubleType (), 0.0), lhs, dname);
4967 break;
4968 case OP_RNEG:
4969 lhs = convert (ctx, lhs, LLVMFloatType ());
4970 values [ins->dreg] = LLVMBuildFSub (builder, LLVMConstReal (LLVMFloatType (), 0.0), lhs, dname);
4971 break;
4972 case OP_INOT: {
4973 guint32 v = 0xffffffff;
4974 values [ins->dreg] = LLVMBuildXor (builder, LLVMConstInt (LLVMInt32Type (), v, FALSE), convert (ctx, lhs, LLVMInt32Type ()), dname);
4975 break;
4977 case OP_LNOT: {
4978 guint64 v = 0xffffffffffffffffLL;
4979 values [ins->dreg] = LLVMBuildXor (builder, LLVMConstInt (LLVMInt64Type (), v, FALSE), lhs, dname);
4980 break;
4982 #if defined(TARGET_X86) || defined(TARGET_AMD64)
4983 case OP_X86_LEA: {
4984 LLVMValueRef v1, v2;
4986 v1 = LLVMBuildMul (builder, convert (ctx, rhs, IntPtrType ()), LLVMConstInt (IntPtrType (), (1 << ins->backend.shift_amount), FALSE), "");
4987 v2 = LLVMBuildAdd (builder, convert (ctx, lhs, IntPtrType ()), v1, "");
4988 values [ins->dreg] = LLVMBuildAdd (builder, v2, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), dname);
4989 break;
4991 #endif
4993 case OP_ICONV_TO_I1:
4994 case OP_ICONV_TO_I2:
4995 case OP_ICONV_TO_I4:
4996 case OP_ICONV_TO_U1:
4997 case OP_ICONV_TO_U2:
4998 case OP_ICONV_TO_U4:
4999 case OP_LCONV_TO_I1:
5000 case OP_LCONV_TO_I2:
5001 case OP_LCONV_TO_U1:
5002 case OP_LCONV_TO_U2:
5003 case OP_LCONV_TO_U4: {
5004 gboolean sign;
5006 sign = (ins->opcode == OP_ICONV_TO_I1) || (ins->opcode == OP_ICONV_TO_I2) || (ins->opcode == OP_ICONV_TO_I4) || (ins->opcode == OP_LCONV_TO_I1) || (ins->opcode == OP_LCONV_TO_I2);
5008 /* Have to do two casts since our vregs have type int */
5009 v = LLVMBuildTrunc (builder, lhs, op_to_llvm_type (ins->opcode), "");
5010 if (sign)
5011 values [ins->dreg] = LLVMBuildSExt (builder, v, LLVMInt32Type (), dname);
5012 else
5013 values [ins->dreg] = LLVMBuildZExt (builder, v, LLVMInt32Type (), dname);
5014 break;
5016 case OP_ICONV_TO_I8:
5017 values [ins->dreg] = LLVMBuildSExt (builder, lhs, LLVMInt64Type (), dname);
5018 break;
5019 case OP_ICONV_TO_U8:
5020 values [ins->dreg] = LLVMBuildZExt (builder, lhs, LLVMInt64Type (), dname);
5021 break;
5022 case OP_FCONV_TO_I4:
5023 case OP_RCONV_TO_I4:
5024 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, LLVMInt32Type (), dname);
5025 break;
5026 case OP_FCONV_TO_I1:
5027 case OP_RCONV_TO_I1:
5028 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildFPToSI (builder, lhs, LLVMInt8Type (), dname), LLVMInt32Type (), "");
5029 break;
5030 case OP_FCONV_TO_U1:
5031 case OP_RCONV_TO_U1:
5032 values [ins->dreg] = LLVMBuildZExt (builder, LLVMBuildTrunc (builder, LLVMBuildFPToUI (builder, lhs, IntPtrType (), dname), LLVMInt8Type (), ""), LLVMInt32Type (), "");
5033 break;
5034 case OP_FCONV_TO_I2:
5035 case OP_RCONV_TO_I2:
5036 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildFPToSI (builder, lhs, LLVMInt16Type (), dname), LLVMInt32Type (), "");
5037 break;
5038 case OP_FCONV_TO_U2:
5039 case OP_RCONV_TO_U2:
5040 values [ins->dreg] = LLVMBuildZExt (builder, LLVMBuildFPToUI (builder, lhs, LLVMInt16Type (), dname), LLVMInt32Type (), "");
5041 break;
5042 case OP_RCONV_TO_U4:
5043 values [ins->dreg] = LLVMBuildFPToUI (builder, lhs, LLVMInt32Type (), dname);
5044 break;
5045 case OP_FCONV_TO_I8:
5046 case OP_RCONV_TO_I8:
5047 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, LLVMInt64Type (), dname);
5048 break;
5049 case OP_FCONV_TO_I:
5050 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, IntPtrType (), dname);
5051 break;
5052 case OP_ICONV_TO_R8:
5053 case OP_LCONV_TO_R8:
5054 values [ins->dreg] = LLVMBuildSIToFP (builder, lhs, LLVMDoubleType (), dname);
5055 break;
5056 case OP_ICONV_TO_R_UN:
5057 case OP_LCONV_TO_R_UN:
5058 values [ins->dreg] = LLVMBuildUIToFP (builder, lhs, LLVMDoubleType (), dname);
5059 break;
5060 #if SIZEOF_VOID_P == 4
5061 case OP_LCONV_TO_U:
5062 #endif
5063 case OP_LCONV_TO_I4:
5064 values [ins->dreg] = LLVMBuildTrunc (builder, lhs, LLVMInt32Type (), dname);
5065 break;
5066 case OP_ICONV_TO_R4:
5067 case OP_LCONV_TO_R4:
5068 v = LLVMBuildSIToFP (builder, lhs, LLVMFloatType (), "");
5069 if (cfg->r4fp)
5070 values [ins->dreg] = v;
5071 else
5072 values [ins->dreg] = LLVMBuildFPExt (builder, v, LLVMDoubleType (), dname);
5073 break;
5074 case OP_FCONV_TO_R4:
5075 v = LLVMBuildFPTrunc (builder, lhs, LLVMFloatType (), "");
5076 if (cfg->r4fp)
5077 values [ins->dreg] = v;
5078 else
5079 values [ins->dreg] = LLVMBuildFPExt (builder, v, LLVMDoubleType (), dname);
5080 break;
5081 case OP_RCONV_TO_R8:
5082 values [ins->dreg] = LLVMBuildFPExt (builder, lhs, LLVMDoubleType (), dname);
5083 break;
5084 case OP_RCONV_TO_R4:
5085 values [ins->dreg] = lhs;
5086 break;
5087 case OP_SEXT_I4:
5088 values [ins->dreg] = LLVMBuildSExt (builder, convert (ctx, lhs, LLVMInt32Type ()), LLVMInt64Type (), dname);
5089 break;
5090 case OP_ZEXT_I4:
5091 values [ins->dreg] = LLVMBuildZExt (builder, convert (ctx, lhs, LLVMInt32Type ()), LLVMInt64Type (), dname);
5092 break;
5093 case OP_TRUNC_I4:
5094 values [ins->dreg] = LLVMBuildTrunc (builder, lhs, LLVMInt32Type (), dname);
5095 break;
5096 case OP_LOCALLOC_IMM: {
5097 LLVMValueRef v;
5099 guint32 size = ins->inst_imm;
5100 size = (size + (MONO_ARCH_FRAME_ALIGNMENT - 1)) & ~ (MONO_ARCH_FRAME_ALIGNMENT - 1);
5102 v = mono_llvm_build_alloca (builder, LLVMInt8Type (), LLVMConstInt (LLVMInt32Type (), size, FALSE), MONO_ARCH_FRAME_ALIGNMENT, "");
5104 if (ins->flags & MONO_INST_INIT) {
5105 LLVMValueRef args [5];
5107 args [0] = v;
5108 args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
5109 args [2] = LLVMConstInt (LLVMInt32Type (), size, FALSE);
5110 args [3] = LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT, FALSE);
5111 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5112 LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memset.p0i8.i32"), args, 5, "");
5115 values [ins->dreg] = v;
5116 break;
5118 case OP_LOCALLOC: {
5119 LLVMValueRef v, size;
5121 size = LLVMBuildAnd (builder, LLVMBuildAdd (builder, convert (ctx, lhs, LLVMInt32Type ()), LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT - 1, FALSE), ""), LLVMConstInt (LLVMInt32Type (), ~ (MONO_ARCH_FRAME_ALIGNMENT - 1), FALSE), "");
5123 v = mono_llvm_build_alloca (builder, LLVMInt8Type (), size, MONO_ARCH_FRAME_ALIGNMENT, "");
5125 if (ins->flags & MONO_INST_INIT) {
5126 LLVMValueRef args [5];
5128 args [0] = v;
5129 args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
5130 args [2] = size;
5131 args [3] = LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT, FALSE);
5132 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5133 LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memset.p0i8.i32"), args, 5, "");
5135 values [ins->dreg] = v;
5136 break;
5139 case OP_LOADI1_MEMBASE:
5140 case OP_LOADU1_MEMBASE:
5141 case OP_LOADI2_MEMBASE:
5142 case OP_LOADU2_MEMBASE:
5143 case OP_LOADI4_MEMBASE:
5144 case OP_LOADU4_MEMBASE:
5145 case OP_LOADI8_MEMBASE:
5146 case OP_LOADR4_MEMBASE:
5147 case OP_LOADR8_MEMBASE:
5148 case OP_LOAD_MEMBASE:
5149 case OP_LOADI8_MEM:
5150 case OP_LOADU1_MEM:
5151 case OP_LOADU2_MEM:
5152 case OP_LOADI4_MEM:
5153 case OP_LOADU4_MEM:
5154 case OP_LOAD_MEM: {
5155 int size = 8;
5156 LLVMValueRef base, index, addr;
5157 LLVMTypeRef t;
5158 gboolean sext = FALSE, zext = FALSE;
5159 gboolean is_volatile = (ins->flags & MONO_INST_FAULT);
5161 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5163 if (sext || zext)
5164 dname = (char*)"";
5166 if ((ins->opcode == OP_LOADI8_MEM) || (ins->opcode == OP_LOAD_MEM) || (ins->opcode == OP_LOADI4_MEM) || (ins->opcode == OP_LOADU4_MEM) || (ins->opcode == OP_LOADU1_MEM) || (ins->opcode == OP_LOADU2_MEM)) {
5167 addr = LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE);
5168 base = addr;
5169 } else {
5170 /* _MEMBASE */
5171 base = lhs;
5173 if (ins->inst_offset == 0) {
5174 addr = base;
5175 } else if (ins->inst_offset % size != 0) {
5176 /* Unaligned load */
5177 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
5178 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
5179 } else {
5180 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5181 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5185 addr = convert (ctx, addr, LLVMPointerType (t, 0));
5187 values [ins->dreg] = emit_load_general (ctx, bb, &builder, size, addr, base, dname, is_volatile, LLVM_BARRIER_NONE);
5189 if (!is_volatile && (ins->flags & MONO_INST_INVARIANT_LOAD)) {
5191 * These will signal LLVM that these loads do not alias any stores, and
5192 * they can't fail, allowing them to be hoisted out of loops.
5194 set_invariant_load_flag (values [ins->dreg]);
5195 #if LLVM_API_VERSION < 100
5196 set_metadata_flag (values [ins->dreg], "mono.nofail.load");
5197 #endif
5200 if (sext)
5201 values [ins->dreg] = LLVMBuildSExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5202 else if (zext)
5203 values [ins->dreg] = LLVMBuildZExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5204 else if (!cfg->r4fp && ins->opcode == OP_LOADR4_MEMBASE)
5205 values [ins->dreg] = LLVMBuildFPExt (builder, values [ins->dreg], LLVMDoubleType (), dname);
5206 break;
5209 case OP_STOREI1_MEMBASE_REG:
5210 case OP_STOREI2_MEMBASE_REG:
5211 case OP_STOREI4_MEMBASE_REG:
5212 case OP_STOREI8_MEMBASE_REG:
5213 case OP_STORER4_MEMBASE_REG:
5214 case OP_STORER8_MEMBASE_REG:
5215 case OP_STORE_MEMBASE_REG: {
5216 int size = 8;
5217 LLVMValueRef index, addr, base;
5218 LLVMTypeRef t;
5219 gboolean sext = FALSE, zext = FALSE;
5220 gboolean is_volatile = (ins->flags & MONO_INST_FAULT);
5222 if (!values [ins->inst_destbasereg]) {
5223 set_failure (ctx, "inst_destbasereg");
5224 break;
5227 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5229 base = values [ins->inst_destbasereg];
5230 if (ins->inst_offset % size != 0) {
5231 /* Unaligned store */
5232 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
5233 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
5234 } else {
5235 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5236 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5238 emit_store (ctx, bb, &builder, size, convert (ctx, values [ins->sreg1], t), convert (ctx, addr, LLVMPointerType (t, 0)), base, is_volatile);
5239 break;
5242 case OP_STOREI1_MEMBASE_IMM:
5243 case OP_STOREI2_MEMBASE_IMM:
5244 case OP_STOREI4_MEMBASE_IMM:
5245 case OP_STOREI8_MEMBASE_IMM:
5246 case OP_STORE_MEMBASE_IMM: {
5247 int size = 8;
5248 LLVMValueRef index, addr, base;
5249 LLVMTypeRef t;
5250 gboolean sext = FALSE, zext = FALSE;
5251 gboolean is_volatile = (ins->flags & MONO_INST_FAULT);
5253 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5255 base = values [ins->inst_destbasereg];
5256 if (ins->inst_offset % size != 0) {
5257 /* Unaligned store */
5258 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
5259 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
5260 } else {
5261 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5262 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5264 emit_store (ctx, bb, &builder, size, convert (ctx, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), t), convert (ctx, addr, LLVMPointerType (t, 0)), base, is_volatile);
5265 break;
5268 case OP_CHECK_THIS:
5269 emit_load_general (ctx, bb, &builder, sizeof (gpointer), convert (ctx, lhs, LLVMPointerType (IntPtrType (), 0)), lhs, "", TRUE, LLVM_BARRIER_NONE);
5270 break;
5271 case OP_OUTARG_VTRETADDR:
5272 break;
5273 case OP_VOIDCALL:
5274 case OP_CALL:
5275 case OP_LCALL:
5276 case OP_FCALL:
5277 case OP_RCALL:
5278 case OP_VCALL:
5279 case OP_VOIDCALL_MEMBASE:
5280 case OP_CALL_MEMBASE:
5281 case OP_LCALL_MEMBASE:
5282 case OP_FCALL_MEMBASE:
5283 case OP_RCALL_MEMBASE:
5284 case OP_VCALL_MEMBASE:
5285 case OP_VOIDCALL_REG:
5286 case OP_CALL_REG:
5287 case OP_LCALL_REG:
5288 case OP_FCALL_REG:
5289 case OP_RCALL_REG:
5290 case OP_VCALL_REG: {
5291 process_call (ctx, bb, &builder, ins);
5292 break;
5294 case OP_AOTCONST: {
5295 guint32 got_offset;
5296 LLVMValueRef indexes [2];
5297 MonoJumpInfo *tmp_ji, *ji;
5298 LLVMValueRef got_entry_addr;
5299 char *name;
5302 * FIXME: Can't allocate from the cfg mempool since that is freed if
5303 * the LLVM compile fails.
5305 tmp_ji = g_new0 (MonoJumpInfo, 1);
5306 tmp_ji->type = (MonoJumpInfoType)ins->inst_c1;
5307 tmp_ji->data.target = ins->inst_p0;
5309 ji = mono_aot_patch_info_dup (tmp_ji);
5310 g_free (tmp_ji);
5312 if (ji->type == MONO_PATCH_INFO_ICALL_ADDR) {
5313 char *symbol = mono_aot_get_direct_call_symbol (MONO_PATCH_INFO_ICALL_ADDR_CALL, ji->data.target);
5314 if (symbol) {
5316 * Avoid emitting a got entry for these since the method is directly called, and it might not be
5317 * resolvable at runtime using dlsym ().
5319 g_free (symbol);
5320 values [ins->dreg] = LLVMConstInt (IntPtrType (), 0, FALSE);
5321 break;
5325 ji->next = cfg->patch_info;
5326 cfg->patch_info = ji;
5328 //mono_add_patch_info (cfg, 0, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
5329 got_offset = mono_aot_get_got_offset (cfg->patch_info);
5330 ctx->module->max_got_offset = MAX (ctx->module->max_got_offset, got_offset);
5331 if (!mono_aot_is_shared_got_offset (got_offset)) {
5332 //mono_print_ji (ji);
5333 //printf ("\n");
5334 ctx->has_got_access = TRUE;
5337 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5338 indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
5339 got_entry_addr = LLVMBuildGEP (builder, ctx->module->got_var, indexes, 2, "");
5341 name = get_aotconst_name (ji->type, ji->data.target, got_offset);
5342 values [ins->dreg] = LLVMBuildLoad (builder, got_entry_addr, name);
5343 g_free (name);
5344 /* Can't use this in llvmonly mode since the got slots are initialized by the methods themselves */
5345 if (!cfg->llvm_only)
5346 set_invariant_load_flag (values [ins->dreg]);
5347 break;
5349 case OP_NOT_REACHED:
5350 LLVMBuildUnreachable (builder);
5351 has_terminator = TRUE;
5352 g_assert (bb->block_num < cfg->max_block_num);
5353 ctx->unreachable [bb->block_num] = TRUE;
5354 /* Might have instructions after this */
5355 while (ins->next) {
5356 MonoInst *next = ins->next;
5358 * FIXME: If later code uses the regs defined by these instructions,
5359 * compilation will fail.
5361 MONO_DELETE_INS (bb, next);
5363 break;
5364 case OP_LDADDR: {
5365 MonoInst *var = ins->inst_i0;
5367 if (var->opcode == OP_VTARG_ADDR) {
5368 /* The variable contains the vtype address */
5369 values [ins->dreg] = values [var->dreg];
5370 } else if (var->opcode == OP_GSHAREDVT_LOCAL) {
5371 values [ins->dreg] = emit_gsharedvt_ldaddr (ctx, var->dreg);
5372 } else {
5373 values [ins->dreg] = addresses [var->dreg];
5375 break;
5377 case OP_SIN: {
5378 LLVMValueRef args [1];
5380 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5381 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.sin.f64"), args, 1, dname);
5382 break;
5384 case OP_COS: {
5385 LLVMValueRef args [1];
5387 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5388 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.cos.f64"), args, 1, dname);
5389 break;
5391 case OP_SQRT: {
5392 LLVMValueRef args [1];
5394 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5395 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.sqrt.f64"), args, 1, dname);
5396 break;
5398 case OP_ABS: {
5399 LLVMValueRef args [1];
5401 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5402 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "fabs"), args, 1, dname);
5403 break;
5406 case OP_IMIN:
5407 case OP_LMIN:
5408 case OP_IMAX:
5409 case OP_LMAX:
5410 case OP_IMIN_UN:
5411 case OP_LMIN_UN:
5412 case OP_IMAX_UN:
5413 case OP_LMAX_UN: {
5414 LLVMValueRef v;
5416 lhs = convert (ctx, lhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
5417 rhs = convert (ctx, rhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
5419 switch (ins->opcode) {
5420 case OP_IMIN:
5421 case OP_LMIN:
5422 v = LLVMBuildICmp (builder, LLVMIntSLE, lhs, rhs, "");
5423 break;
5424 case OP_IMAX:
5425 case OP_LMAX:
5426 v = LLVMBuildICmp (builder, LLVMIntSGE, lhs, rhs, "");
5427 break;
5428 case OP_IMIN_UN:
5429 case OP_LMIN_UN:
5430 v = LLVMBuildICmp (builder, LLVMIntULE, lhs, rhs, "");
5431 break;
5432 case OP_IMAX_UN:
5433 case OP_LMAX_UN:
5434 v = LLVMBuildICmp (builder, LLVMIntUGE, lhs, rhs, "");
5435 break;
5436 default:
5437 g_assert_not_reached ();
5438 break;
5440 values [ins->dreg] = LLVMBuildSelect (builder, v, lhs, rhs, dname);
5441 break;
5445 * See the ARM64 comment in mono/utils/atomic.h for an explanation of why this
5446 * hack is necessary (for now).
5448 #ifdef TARGET_ARM64
5449 #define ARM64_ATOMIC_FENCE_FIX mono_llvm_build_fence (builder, LLVM_BARRIER_SEQ)
5450 #else
5451 #define ARM64_ATOMIC_FENCE_FIX
5452 #endif
5454 case OP_ATOMIC_EXCHANGE_I4:
5455 case OP_ATOMIC_EXCHANGE_I8: {
5456 LLVMValueRef args [2];
5457 LLVMTypeRef t;
5459 if (ins->opcode == OP_ATOMIC_EXCHANGE_I4)
5460 t = LLVMInt32Type ();
5461 else
5462 t = LLVMInt64Type ();
5464 g_assert (ins->inst_offset == 0);
5466 args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
5467 args [1] = convert (ctx, rhs, t);
5469 ARM64_ATOMIC_FENCE_FIX;
5470 values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
5471 ARM64_ATOMIC_FENCE_FIX;
5472 break;
5474 case OP_ATOMIC_ADD_I4:
5475 case OP_ATOMIC_ADD_I8: {
5476 LLVMValueRef args [2];
5477 LLVMTypeRef t;
5479 if (ins->opcode == OP_ATOMIC_ADD_I4)
5480 t = LLVMInt32Type ();
5481 else
5482 t = LLVMInt64Type ();
5484 g_assert (ins->inst_offset == 0);
5486 args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
5487 args [1] = convert (ctx, rhs, t);
5488 ARM64_ATOMIC_FENCE_FIX;
5489 values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname);
5490 ARM64_ATOMIC_FENCE_FIX;
5491 break;
5493 case OP_ATOMIC_CAS_I4:
5494 case OP_ATOMIC_CAS_I8: {
5495 LLVMValueRef args [3], val;
5496 LLVMTypeRef t;
5498 if (ins->opcode == OP_ATOMIC_CAS_I4)
5499 t = LLVMInt32Type ();
5500 else
5501 t = LLVMInt64Type ();
5503 args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
5504 /* comparand */
5505 args [1] = convert (ctx, values [ins->sreg3], t);
5506 /* new value */
5507 args [2] = convert (ctx, values [ins->sreg2], t);
5508 ARM64_ATOMIC_FENCE_FIX;
5509 val = mono_llvm_build_cmpxchg (builder, args [0], args [1], args [2]);
5510 ARM64_ATOMIC_FENCE_FIX;
5511 /* cmpxchg returns a pair */
5512 values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, "");
5513 break;
5515 case OP_MEMORY_BARRIER: {
5516 mono_llvm_build_fence (builder, (BarrierKind) ins->backend.memory_barrier_kind);
5517 break;
5519 case OP_ATOMIC_LOAD_I1:
5520 case OP_ATOMIC_LOAD_I2:
5521 case OP_ATOMIC_LOAD_I4:
5522 case OP_ATOMIC_LOAD_I8:
5523 case OP_ATOMIC_LOAD_U1:
5524 case OP_ATOMIC_LOAD_U2:
5525 case OP_ATOMIC_LOAD_U4:
5526 case OP_ATOMIC_LOAD_U8:
5527 case OP_ATOMIC_LOAD_R4:
5528 case OP_ATOMIC_LOAD_R8: {
5529 #if LLVM_API_VERSION > 100
5530 int size;
5531 gboolean sext, zext;
5532 LLVMTypeRef t;
5533 gboolean is_volatile = (ins->flags & MONO_INST_FAULT);
5534 BarrierKind barrier = (BarrierKind) ins->backend.memory_barrier_kind;
5535 LLVMValueRef index, addr;
5537 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5539 if (sext || zext)
5540 dname = (char *)"";
5542 if (ins->inst_offset != 0) {
5543 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5544 addr = LLVMBuildGEP (builder, convert (ctx, lhs, LLVMPointerType (t, 0)), &index, 1, "");
5545 } else {
5546 addr = lhs;
5549 addr = convert (ctx, addr, LLVMPointerType (t, 0));
5551 ARM64_ATOMIC_FENCE_FIX;
5552 values [ins->dreg] = emit_load_general (ctx, bb, &builder, size, addr, lhs, dname, is_volatile, barrier);
5553 ARM64_ATOMIC_FENCE_FIX;
5555 if (sext)
5556 values [ins->dreg] = LLVMBuildSExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5557 else if (zext)
5558 values [ins->dreg] = LLVMBuildZExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5559 break;
5560 #else
5561 set_failure (ctx, "atomic mono.load intrinsic");
5562 break;
5563 #endif
5565 case OP_ATOMIC_STORE_I1:
5566 case OP_ATOMIC_STORE_I2:
5567 case OP_ATOMIC_STORE_I4:
5568 case OP_ATOMIC_STORE_I8:
5569 case OP_ATOMIC_STORE_U1:
5570 case OP_ATOMIC_STORE_U2:
5571 case OP_ATOMIC_STORE_U4:
5572 case OP_ATOMIC_STORE_U8:
5573 case OP_ATOMIC_STORE_R4:
5574 case OP_ATOMIC_STORE_R8: {
5575 int size;
5576 gboolean sext, zext;
5577 LLVMTypeRef t;
5578 gboolean is_volatile = (ins->flags & MONO_INST_FAULT);
5579 BarrierKind barrier = (BarrierKind) ins->backend.memory_barrier_kind;
5580 LLVMValueRef index, addr, value, base;
5582 #if LLVM_API_VERSION < 100
5583 if (!cfg->llvm_only) {
5584 set_failure (ctx, "atomic mono.store intrinsic");
5585 break;
5587 #endif
5589 if (!values [ins->inst_destbasereg]) {
5590 set_failure (ctx, "inst_destbasereg");
5591 break;
5594 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5596 base = values [ins->inst_destbasereg];
5597 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5598 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5599 value = convert (ctx, values [ins->sreg1], t);
5601 ARM64_ATOMIC_FENCE_FIX;
5602 emit_store_general (ctx, bb, &builder, size, value, addr, base, is_volatile, barrier);
5603 ARM64_ATOMIC_FENCE_FIX;
5604 break;
5606 case OP_RELAXED_NOP: {
5607 #if defined(TARGET_AMD64) || defined(TARGET_X86)
5608 emit_call (ctx, bb, &builder, get_intrinsic (ctx, "llvm.x86.sse2.pause"), NULL, 0);
5609 break;
5610 #else
5611 break;
5612 #endif
5614 case OP_TLS_GET: {
5615 #if (defined(TARGET_AMD64) || defined(TARGET_X86)) && defined(__linux__)
5616 #ifdef TARGET_AMD64
5617 // 257 == FS segment register
5618 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 257);
5619 #else
5620 // 256 == GS segment register
5621 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
5622 #endif
5623 // FIXME: XEN
5624 values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), ins->inst_offset, TRUE), ptrtype, ""), "");
5625 #elif defined(TARGET_AMD64) && defined(TARGET_OSX)
5626 /* See mono_amd64_emit_tls_get () */
5627 int offset = mono_amd64_get_tls_gs_offset () + (ins->inst_offset * 8);
5629 // 256 == GS segment register
5630 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
5631 values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), offset, TRUE), ptrtype, ""), "");
5632 #else
5633 set_failure (ctx, "opcode tls-get");
5634 break;
5635 #endif
5637 break;
5639 case OP_TLS_GET_REG: {
5640 #if defined(TARGET_AMD64) && defined(__linux__)
5641 // 257 == FS segment register
5642 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 257);
5643 values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, convert (ctx, lhs, LLVMInt64Type ()), ptrtype, ""), "");
5644 #elif defined(TARGET_AMD64) && defined(TARGET_OSX)
5645 /* See emit_tls_get_reg () */
5646 // 256 == GS segment register
5647 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
5648 values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, convert (ctx, lhs, LLVMInt32Type ()), ptrtype, ""), "");
5649 #else
5650 set_failure (ctx, "opcode tls-get");
5651 break;
5652 #endif
5653 break;
5656 case OP_TLS_SET_REG: {
5657 #if defined(TARGET_AMD64) && defined(TARGET_OSX)
5658 /* See emit_tls_get_reg () */
5659 // 256 == GS segment register
5660 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
5661 LLVMBuildStore (builder, convert (ctx, lhs, IntPtrType ()), LLVMBuildIntToPtr (builder, convert (ctx, rhs, LLVMInt32Type ()), ptrtype, ""));
5662 #else
5663 set_failure (ctx, "opcode tls-set-reg");
5664 break;
5665 #endif
5666 break;
5668 case OP_GC_SAFE_POINT: {
5669 LLVMValueRef val, cmp, callee;
5670 LLVMBasicBlockRef poll_bb, cont_bb;
5671 static LLVMTypeRef sig;
5672 const char *icall_name = "mono_threads_state_poll";
5674 if (!sig)
5675 sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
5678 * if (!*sreg1)
5679 * mono_threads_state_poll ();
5680 * FIXME: Use a preserveall wrapper
5682 val = mono_llvm_build_load (builder, convert (ctx, lhs, LLVMPointerType (IntPtrType (), 0)), "", TRUE);
5683 cmp = LLVMBuildICmp (builder, LLVMIntEQ, val, LLVMConstNull (LLVMTypeOf (val)), "");
5684 poll_bb = gen_bb (ctx, "POLL_BB");
5685 cont_bb = gen_bb (ctx, "CONT_BB");
5686 LLVMBuildCondBr (builder, cmp, cont_bb, poll_bb);
5688 ctx->builder = builder = create_builder (ctx);
5689 LLVMPositionBuilderAtEnd (builder, poll_bb);
5691 if (ctx->cfg->compile_aot) {
5692 callee = get_callee (ctx, sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
5693 } else {
5694 gpointer target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
5695 callee = emit_jit_callee (ctx, icall_name, sig, target);
5697 LLVMBuildCall (builder, callee, NULL, 0, "");
5698 LLVMBuildBr (builder, cont_bb);
5700 ctx->builder = builder = create_builder (ctx);
5701 LLVMPositionBuilderAtEnd (builder, cont_bb);
5702 ctx->bblocks [bb->block_num].end_bblock = cont_bb;
5703 break;
5707 * Overflow opcodes.
5709 case OP_IADD_OVF:
5710 case OP_IADD_OVF_UN:
5711 case OP_ISUB_OVF:
5712 case OP_ISUB_OVF_UN:
5713 case OP_IMUL_OVF:
5714 case OP_IMUL_OVF_UN:
5715 case OP_LADD_OVF:
5716 case OP_LADD_OVF_UN:
5717 case OP_LSUB_OVF:
5718 case OP_LSUB_OVF_UN:
5719 case OP_LMUL_OVF:
5720 case OP_LMUL_OVF_UN:
5722 LLVMValueRef args [2], val, ovf, func;
5724 args [0] = convert (ctx, lhs, op_to_llvm_type (ins->opcode));
5725 args [1] = convert (ctx, rhs, op_to_llvm_type (ins->opcode));
5726 func = get_intrinsic (ctx, ovf_op_to_intrins (ins->opcode));
5727 g_assert (func);
5728 val = LLVMBuildCall (builder, func, args, 2, "");
5729 values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, dname);
5730 ovf = LLVMBuildExtractValue (builder, val, 1, "");
5731 emit_cond_system_exception (ctx, bb, "OverflowException", ovf);
5732 if (!ctx_ok (ctx))
5733 break;
5734 builder = ctx->builder;
5735 break;
5739 * Valuetypes.
5740 * We currently model them using arrays. Promotion to local vregs is
5741 * disabled for them in mono_handle_global_vregs () in the LLVM case,
5742 * so we always have an entry in cfg->varinfo for them.
5743 * FIXME: Is this needed ?
5745 case OP_VZERO: {
5746 MonoClass *klass = ins->klass;
5747 LLVMValueRef args [5];
5749 if (!klass) {
5750 // FIXME:
5751 set_failure (ctx, "!klass");
5752 break;
5755 if (!addresses [ins->dreg])
5756 addresses [ins->dreg] = build_alloca (ctx, &klass->byval_arg);
5757 args [0] = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
5758 args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
5759 args [2] = LLVMConstInt (LLVMInt32Type (), mono_class_value_size (klass, NULL), FALSE);
5760 // FIXME: Alignment
5761 args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5762 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5763 LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memset.p0i8.i32"), args, 5, "");
5764 break;
5766 case OP_DUMMY_VZERO:
5767 break;
5769 case OP_STOREV_MEMBASE:
5770 case OP_LOADV_MEMBASE:
5771 case OP_VMOVE: {
5772 MonoClass *klass = ins->klass;
5773 LLVMValueRef src = NULL, dst, args [5];
5774 gboolean done = FALSE;
5776 if (!klass) {
5777 // FIXME:
5778 set_failure (ctx, "!klass");
5779 break;
5782 if (mini_is_gsharedvt_klass (klass)) {
5783 // FIXME:
5784 set_failure (ctx, "gsharedvt");
5785 break;
5788 switch (ins->opcode) {
5789 case OP_STOREV_MEMBASE:
5790 if (cfg->gen_write_barriers && klass->has_references && ins->inst_destbasereg != cfg->frame_reg &&
5791 LLVMGetInstructionOpcode (values [ins->inst_destbasereg]) != LLVMAlloca) {
5792 /* Decomposed earlier */
5793 g_assert_not_reached ();
5794 break;
5796 if (!addresses [ins->sreg1]) {
5797 /* SIMD */
5798 g_assert (values [ins->sreg1]);
5799 dst = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_destbasereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (type_to_llvm_type (ctx, &klass->byval_arg), 0));
5800 LLVMBuildStore (builder, values [ins->sreg1], dst);
5801 done = TRUE;
5802 } else {
5803 src = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (LLVMInt8Type (), 0), "");
5804 dst = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_destbasereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (LLVMInt8Type (), 0));
5806 break;
5807 case OP_LOADV_MEMBASE:
5808 if (!addresses [ins->dreg])
5809 addresses [ins->dreg] = build_alloca (ctx, &klass->byval_arg);
5810 src = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_basereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (LLVMInt8Type (), 0));
5811 dst = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
5812 break;
5813 case OP_VMOVE:
5814 if (!addresses [ins->sreg1])
5815 addresses [ins->sreg1] = build_alloca (ctx, &klass->byval_arg);
5816 if (!addresses [ins->dreg])
5817 addresses [ins->dreg] = build_alloca (ctx, &klass->byval_arg);
5818 src = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (LLVMInt8Type (), 0), "");
5819 dst = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
5820 break;
5821 default:
5822 g_assert_not_reached ();
5824 if (!ctx_ok (ctx))
5825 break;
5827 if (done)
5828 break;
5830 args [0] = dst;
5831 args [1] = src;
5832 args [2] = LLVMConstInt (LLVMInt32Type (), mono_class_value_size (klass, NULL), FALSE);
5833 args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5834 // FIXME: Alignment
5835 args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5836 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5837 LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memcpy.p0i8.p0i8.i32"), args, 5, "");
5838 break;
5840 case OP_LLVM_OUTARG_VT: {
5841 LLVMArgInfo *ainfo = (LLVMArgInfo*)ins->inst_p0;
5842 MonoType *t = mini_get_underlying_type (ins->inst_vtype);
5844 if (ainfo->storage == LLVMArgGsharedvtVariable) {
5845 MonoInst *var = get_vreg_to_inst (cfg, ins->sreg1);
5847 if (var && var->opcode == OP_GSHAREDVT_LOCAL) {
5848 addresses [ins->dreg] = convert (ctx, emit_gsharedvt_ldaddr (ctx, var->dreg), LLVMPointerType (IntPtrType (), 0));
5849 } else {
5850 g_assert (addresses [ins->sreg1]);
5851 addresses [ins->dreg] = addresses [ins->sreg1];
5853 } else if (ainfo->storage == LLVMArgGsharedvtFixed) {
5854 if (!addresses [ins->sreg1]) {
5855 addresses [ins->sreg1] = build_alloca (ctx, t);
5856 g_assert (values [ins->sreg1]);
5858 LLVMBuildStore (builder, convert (ctx, values [ins->sreg1], LLVMGetElementType (LLVMTypeOf (addresses [ins->sreg1]))), addresses [ins->sreg1]);
5859 addresses [ins->dreg] = addresses [ins->sreg1];
5860 } else {
5861 if (!addresses [ins->sreg1]) {
5862 addresses [ins->sreg1] = build_alloca (ctx, t);
5863 g_assert (values [ins->sreg1]);
5864 LLVMBuildStore (builder, convert (ctx, values [ins->sreg1], type_to_llvm_type (ctx, t)), addresses [ins->sreg1]);
5866 addresses [ins->dreg] = addresses [ins->sreg1];
5868 break;
5870 case OP_OBJC_GET_SELECTOR: {
5871 const char *name = (const char*)ins->inst_p0;
5872 LLVMValueRef var;
5874 if (!ctx->module->objc_selector_to_var)
5875 ctx->module->objc_selector_to_var = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
5876 var = g_hash_table_lookup (ctx->module->objc_selector_to_var, name);
5877 if (!var) {
5878 LLVMValueRef indexes [16];
5880 LLVMValueRef name_var = LLVMAddGlobal (ctx->lmodule, LLVMArrayType (LLVMInt8Type (), strlen (name) + 1), "@OBJC_METH_VAR_NAME_");
5881 LLVMSetInitializer (name_var, mono_llvm_create_constant_data_array ((const uint8_t*)name, strlen (name) + 1));
5882 LLVMSetLinkage (name_var, LLVMPrivateLinkage);
5883 LLVMSetSection (name_var, "__TEXT,__objc_methname,cstring_literals");
5884 mark_as_used (ctx->module, name_var);
5886 LLVMValueRef ref_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (LLVMInt8Type (), 0), "@OBJC_SELECTOR_REFERENCES_");
5888 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, 0);
5889 indexes [1] = LLVMConstInt (LLVMInt32Type (), 0, 0);
5890 LLVMSetInitializer (ref_var, LLVMConstGEP (name_var, indexes, 2));
5891 LLVMSetLinkage (ref_var, LLVMPrivateLinkage);
5892 LLVMSetExternallyInitialized (ref_var, TRUE);
5893 LLVMSetSection (ref_var, "__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
5894 LLVMSetAlignment (ref_var, sizeof (mgreg_t));
5895 mark_as_used (ctx->module, ref_var);
5897 g_hash_table_insert (ctx->module->objc_selector_to_var, g_strdup (name), ref_var);
5898 var = ref_var;
5901 values [ins->dreg] = LLVMBuildLoad (builder, var, "");
5902 break;
5906 * SIMD
5908 #if defined(TARGET_X86) || defined(TARGET_AMD64)
5909 case OP_XZERO: {
5910 values [ins->dreg] = LLVMConstNull (type_to_llvm_type (ctx, &ins->klass->byval_arg));
5911 break;
5913 case OP_LOADX_MEMBASE: {
5914 LLVMTypeRef t = type_to_llvm_type (ctx, &ins->klass->byval_arg);
5915 LLVMValueRef src;
5917 src = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_basereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (t, 0));
5918 values [ins->dreg] = mono_llvm_build_aligned_load (builder, src, "", FALSE, 1);
5919 break;
5921 case OP_STOREX_MEMBASE: {
5922 LLVMTypeRef t = LLVMTypeOf (values [ins->sreg1]);
5923 LLVMValueRef dest;
5925 dest = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_destbasereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (t, 0));
5926 mono_llvm_build_aligned_store (builder, values [ins->sreg1], dest, FALSE, 1);
5927 break;
5929 case OP_PADDB:
5930 case OP_PADDW:
5931 case OP_PADDD:
5932 case OP_PADDQ:
5933 values [ins->dreg] = LLVMBuildAdd (builder, lhs, rhs, "");
5934 break;
5935 case OP_ADDPD:
5936 case OP_ADDPS:
5937 values [ins->dreg] = LLVMBuildFAdd (builder, lhs, rhs, "");
5938 break;
5939 case OP_PSUBB:
5940 case OP_PSUBW:
5941 case OP_PSUBD:
5942 case OP_PSUBQ:
5943 values [ins->dreg] = LLVMBuildSub (builder, lhs, rhs, "");
5944 break;
5945 case OP_SUBPD:
5946 case OP_SUBPS:
5947 values [ins->dreg] = LLVMBuildFSub (builder, lhs, rhs, "");
5948 break;
5949 case OP_MULPD:
5950 case OP_MULPS:
5951 values [ins->dreg] = LLVMBuildFMul (builder, lhs, rhs, "");
5952 break;
5953 case OP_DIVPD:
5954 case OP_DIVPS:
5955 values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, "");
5956 break;
5957 case OP_PAND:
5958 values [ins->dreg] = LLVMBuildAnd (builder, lhs, rhs, "");
5959 break;
5960 case OP_POR:
5961 values [ins->dreg] = LLVMBuildOr (builder, lhs, rhs, "");
5962 break;
5963 case OP_PXOR:
5964 values [ins->dreg] = LLVMBuildXor (builder, lhs, rhs, "");
5965 break;
5966 case OP_PMULW:
5967 case OP_PMULD:
5968 values [ins->dreg] = LLVMBuildMul (builder, lhs, rhs, "");
5969 break;
5970 case OP_ANDPS:
5971 case OP_ANDNPS:
5972 case OP_ORPS:
5973 case OP_XORPS:
5974 case OP_ANDPD:
5975 case OP_ANDNPD:
5976 case OP_ORPD:
5977 case OP_XORPD: {
5978 LLVMTypeRef t, rt;
5979 LLVMValueRef v = NULL;
5981 switch (ins->opcode) {
5982 case OP_ANDPS:
5983 case OP_ANDNPS:
5984 case OP_ORPS:
5985 case OP_XORPS:
5986 t = LLVMVectorType (LLVMInt32Type (), 4);
5987 rt = LLVMVectorType (LLVMFloatType (), 4);
5988 break;
5989 case OP_ANDPD:
5990 case OP_ANDNPD:
5991 case OP_ORPD:
5992 case OP_XORPD:
5993 t = LLVMVectorType (LLVMInt64Type (), 2);
5994 rt = LLVMVectorType (LLVMDoubleType (), 2);
5995 break;
5996 default:
5997 t = LLVMInt32Type ();
5998 rt = LLVMInt32Type ();
5999 g_assert_not_reached ();
6002 lhs = LLVMBuildBitCast (builder, lhs, t, "");
6003 rhs = LLVMBuildBitCast (builder, rhs, t, "");
6004 switch (ins->opcode) {
6005 case OP_ANDPS:
6006 case OP_ANDPD:
6007 v = LLVMBuildAnd (builder, lhs, rhs, "");
6008 break;
6009 case OP_ORPS:
6010 case OP_ORPD:
6011 v = LLVMBuildOr (builder, lhs, rhs, "");
6012 break;
6013 case OP_XORPS:
6014 case OP_XORPD:
6015 v = LLVMBuildXor (builder, lhs, rhs, "");
6016 break;
6017 case OP_ANDNPS:
6018 case OP_ANDNPD:
6019 v = LLVMBuildAnd (builder, rhs, LLVMBuildNot (builder, lhs, ""), "");
6020 break;
6022 values [ins->dreg] = LLVMBuildBitCast (builder, v, rt, "");
6023 break;
6025 case OP_PMIND_UN:
6026 case OP_PMINW_UN:
6027 case OP_PMINB_UN: {
6028 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntULT, lhs, rhs, "");
6029 values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
6030 break;
6032 case OP_PMAXD_UN:
6033 case OP_PMAXW_UN:
6034 case OP_PMAXB_UN: {
6035 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntUGT, lhs, rhs, "");
6036 values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
6037 break;
6039 case OP_PMINW: {
6040 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntSLT, lhs, rhs, "");
6041 values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
6042 break;
6044 case OP_MINPD:
6045 case OP_MINPS:
6046 case OP_MAXPD:
6047 case OP_MAXPS:
6048 case OP_ADDSUBPD:
6049 case OP_ADDSUBPS:
6050 case OP_HADDPD:
6051 case OP_HADDPS:
6052 case OP_HSUBPD:
6053 case OP_HSUBPS:
6054 case OP_PADDB_SAT:
6055 case OP_PADDW_SAT:
6056 case OP_PSUBB_SAT:
6057 case OP_PSUBW_SAT:
6058 case OP_PADDB_SAT_UN:
6059 case OP_PADDW_SAT_UN:
6060 case OP_PSUBB_SAT_UN:
6061 case OP_PSUBW_SAT_UN:
6062 case OP_PAVGB_UN:
6063 case OP_PAVGW_UN:
6064 case OP_PACKW:
6065 case OP_PACKD:
6066 case OP_PACKW_UN:
6067 case OP_PACKD_UN:
6068 case OP_PMULW_HIGH:
6069 case OP_PMULW_HIGH_UN: {
6070 LLVMValueRef args [2];
6072 args [0] = lhs;
6073 args [1] = rhs;
6075 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6076 break;
6078 case OP_PCMPEQB:
6079 case OP_PCMPEQW:
6080 case OP_PCMPEQD:
6081 case OP_PCMPEQQ: {
6082 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildICmp (builder, LLVMIntEQ, lhs, rhs, ""), LLVMTypeOf (lhs), "");
6083 break;
6085 case OP_PCMPGTB: {
6086 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildICmp (builder, LLVMIntSGT, lhs, rhs, ""), LLVMTypeOf (lhs), "");
6087 break;
6089 case OP_EXTRACT_R8:
6090 case OP_EXTRACT_I8:
6091 case OP_EXTRACT_I4:
6092 case OP_EXTRACT_I2:
6093 case OP_EXTRACT_U2:
6094 case OP_EXTRACTX_U2:
6095 case OP_EXTRACT_I1:
6096 case OP_EXTRACT_U1: {
6097 LLVMTypeRef t;
6098 gboolean zext = FALSE;
6100 t = simd_op_to_llvm_type (ins->opcode);
6102 switch (ins->opcode) {
6103 case OP_EXTRACT_R8:
6104 case OP_EXTRACT_I8:
6105 case OP_EXTRACT_I4:
6106 case OP_EXTRACT_I2:
6107 case OP_EXTRACT_I1:
6108 break;
6109 case OP_EXTRACT_U2:
6110 case OP_EXTRACTX_U2:
6111 case OP_EXTRACT_U1:
6112 zext = TRUE;
6113 break;
6114 default:
6115 t = LLVMInt32Type ();
6116 g_assert_not_reached ();
6119 lhs = LLVMBuildBitCast (builder, lhs, t, "");
6120 values [ins->dreg] = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), "");
6121 if (zext)
6122 values [ins->dreg] = LLVMBuildZExt (builder, values [ins->dreg], LLVMInt32Type (), "");
6123 break;
6126 case OP_EXPAND_I1:
6127 case OP_EXPAND_I2:
6128 case OP_EXPAND_I4:
6129 case OP_EXPAND_I8:
6130 case OP_EXPAND_R4:
6131 case OP_EXPAND_R8: {
6132 LLVMTypeRef t = simd_op_to_llvm_type (ins->opcode);
6133 LLVMValueRef mask [16], v;
6134 int i;
6136 for (i = 0; i < 16; ++i)
6137 mask [i] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6139 v = convert (ctx, values [ins->sreg1], LLVMGetElementType (t));
6141 values [ins->dreg] = LLVMBuildInsertElement (builder, LLVMConstNull (t), v, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6142 values [ins->dreg] = LLVMBuildShuffleVector (builder, values [ins->dreg], LLVMGetUndef (t), LLVMConstVector (mask, LLVMGetVectorSize (t)), "");
6143 break;
6146 case OP_INSERT_I1:
6147 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt8Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6148 break;
6149 case OP_INSERT_I2:
6150 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt16Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6151 break;
6152 case OP_INSERT_I4:
6153 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt32Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6154 break;
6155 case OP_INSERT_I8:
6156 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt64Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6157 break;
6158 case OP_INSERT_R4:
6159 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMFloatType ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6160 break;
6161 case OP_INSERT_R8:
6162 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMDoubleType ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6163 break;
6165 #if 0
6166 // Requires a later llvm version
6167 case OP_CVTDQ2PD: {
6168 LLVMValueRef indexes [16];
6170 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6171 indexes [1] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
6172 LLVMValueRef mask = LLVMConstVector (indexes, 2);
6173 LLVMValueRef shuffle = LLVMBuildShuffleVector (builder, lhs, LLVMConstNull (LLVMTypeOf (lhs)), mask, "");
6174 values [ins->dreg] = LLVMBuildSIToFP (builder, shuffle, LLVMVectorType (LLVMDoubleType (), 2), dname);
6175 break;
6177 case OP_CVTPS2PD: {
6178 LLVMValueRef indexes [16];
6180 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6181 indexes [1] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
6182 LLVMValueRef mask = LLVMConstVector (indexes, 2);
6183 LLVMValueRef shuffle = LLVMBuildShuffleVector (builder, lhs, LLVMConstNull (LLVMTypeOf (lhs)), mask, "");
6184 values [ins->dreg] = LLVMBuildFPExt (builder, shuffle, LLVMVectorType (LLVMDoubleType (), 2), dname);
6185 break;
6187 case OP_CVTTPS2DQ:
6188 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, LLVMVectorType (LLVMInt32Type (), 4), dname);
6189 break;
6190 #endif
6192 case OP_CVTDQ2PD:
6193 case OP_CVTDQ2PS:
6194 case OP_CVTPD2DQ:
6195 case OP_CVTPS2DQ:
6196 case OP_CVTPD2PS:
6197 case OP_CVTPS2PD:
6198 case OP_CVTTPD2DQ:
6199 case OP_CVTTPS2DQ:
6200 case OP_EXTRACT_MASK:
6201 case OP_SQRTPS:
6202 case OP_SQRTPD:
6203 case OP_RSQRTPS:
6204 case OP_RCPPS: {
6205 LLVMValueRef v;
6207 v = convert (ctx, values [ins->sreg1], simd_op_to_llvm_type (ins->opcode));
6209 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), &v, 1, dname);
6210 break;
6212 case OP_COMPPS:
6213 case OP_COMPPD: {
6214 LLVMRealPredicate op;
6216 switch (ins->inst_c0) {
6217 case SIMD_COMP_EQ:
6218 op = LLVMRealOEQ;
6219 break;
6220 case SIMD_COMP_LT:
6221 op = LLVMRealOLT;
6222 break;
6223 case SIMD_COMP_LE:
6224 op = LLVMRealOLE;
6225 break;
6226 case SIMD_COMP_UNORD:
6227 op = LLVMRealUNO;
6228 break;
6229 case SIMD_COMP_NEQ:
6230 op = LLVMRealUNE;
6231 break;
6232 case SIMD_COMP_NLT:
6233 op = LLVMRealUGE;
6234 break;
6235 case SIMD_COMP_NLE:
6236 op = LLVMRealUGT;
6237 break;
6238 case SIMD_COMP_ORD:
6239 op = LLVMRealORD;
6240 break;
6241 default:
6242 g_assert_not_reached ();
6245 LLVMValueRef cmp = LLVMBuildFCmp (builder, op, lhs, rhs, "");
6246 if (ins->opcode == OP_COMPPD)
6247 values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildSExt (builder, cmp, LLVMVectorType (LLVMInt64Type (), 2), ""), LLVMTypeOf (lhs), "");
6248 else
6249 values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildSExt (builder, cmp, LLVMVectorType (LLVMInt32Type (), 4), ""), LLVMTypeOf (lhs), "");
6250 break;
6252 case OP_ICONV_TO_X:
6253 /* This is only used for implementing shifts by non-immediate */
6254 values [ins->dreg] = lhs;
6255 break;
6257 case OP_PSHRW:
6258 case OP_PSHRD:
6259 case OP_PSHRQ:
6260 case OP_PSARW:
6261 case OP_PSARD:
6262 case OP_PSHLW:
6263 case OP_PSHLD:
6264 case OP_PSHLQ: {
6265 LLVMValueRef args [3];
6267 args [0] = lhs;
6268 args [1] = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
6270 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6271 break;
6274 case OP_PSHRW_REG:
6275 case OP_PSHRD_REG:
6276 case OP_PSHRQ_REG:
6277 case OP_PSARW_REG:
6278 case OP_PSARD_REG:
6279 case OP_PSHLW_REG:
6280 case OP_PSHLD_REG:
6281 case OP_PSHLQ_REG: {
6282 LLVMValueRef args [3];
6284 args [0] = lhs;
6285 args [1] = values [ins->sreg2];
6287 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6288 break;
6291 case OP_SHUFPS:
6292 case OP_SHUFPD:
6293 case OP_PSHUFLED:
6294 case OP_PSHUFLEW_LOW:
6295 case OP_PSHUFLEW_HIGH: {
6296 int mask [16];
6297 LLVMValueRef v1 = NULL, v2 = NULL, mask_values [16];
6298 int i, mask_size = 0;
6299 int imask = ins->inst_c0;
6301 /* Convert the x86 shuffle mask to LLVM's */
6302 switch (ins->opcode) {
6303 case OP_SHUFPS:
6304 mask_size = 4;
6305 mask [0] = ((imask >> 0) & 3);
6306 mask [1] = ((imask >> 2) & 3);
6307 mask [2] = ((imask >> 4) & 3) + 4;
6308 mask [3] = ((imask >> 6) & 3) + 4;
6309 v1 = values [ins->sreg1];
6310 v2 = values [ins->sreg2];
6311 break;
6312 case OP_SHUFPD:
6313 mask_size = 2;
6314 mask [0] = ((imask >> 0) & 1);
6315 mask [1] = ((imask >> 1) & 1) + 2;
6316 v1 = values [ins->sreg1];
6317 v2 = values [ins->sreg2];
6318 break;
6319 case OP_PSHUFLEW_LOW:
6320 mask_size = 8;
6321 mask [0] = ((imask >> 0) & 3);
6322 mask [1] = ((imask >> 2) & 3);
6323 mask [2] = ((imask >> 4) & 3);
6324 mask [3] = ((imask >> 6) & 3);
6325 mask [4] = 4 + 0;
6326 mask [5] = 4 + 1;
6327 mask [6] = 4 + 2;
6328 mask [7] = 4 + 3;
6329 v1 = values [ins->sreg1];
6330 v2 = LLVMGetUndef (LLVMTypeOf (v1));
6331 break;
6332 case OP_PSHUFLEW_HIGH:
6333 mask_size = 8;
6334 mask [0] = 0;
6335 mask [1] = 1;
6336 mask [2] = 2;
6337 mask [3] = 3;
6338 mask [4] = 4 + ((imask >> 0) & 3);
6339 mask [5] = 4 + ((imask >> 2) & 3);
6340 mask [6] = 4 + ((imask >> 4) & 3);
6341 mask [7] = 4 + ((imask >> 6) & 3);
6342 v1 = values [ins->sreg1];
6343 v2 = LLVMGetUndef (LLVMTypeOf (v1));
6344 break;
6345 case OP_PSHUFLED:
6346 mask_size = 4;
6347 mask [0] = ((imask >> 0) & 3);
6348 mask [1] = ((imask >> 2) & 3);
6349 mask [2] = ((imask >> 4) & 3);
6350 mask [3] = ((imask >> 6) & 3);
6351 v1 = values [ins->sreg1];
6352 v2 = LLVMGetUndef (LLVMTypeOf (v1));
6353 break;
6354 default:
6355 g_assert_not_reached ();
6357 for (i = 0; i < mask_size; ++i)
6358 mask_values [i] = LLVMConstInt (LLVMInt32Type (), mask [i], FALSE);
6360 values [ins->dreg] =
6361 LLVMBuildShuffleVector (builder, v1, v2,
6362 LLVMConstVector (mask_values, mask_size), dname);
6363 break;
6366 case OP_UNPACK_LOWB:
6367 case OP_UNPACK_LOWW:
6368 case OP_UNPACK_LOWD:
6369 case OP_UNPACK_LOWQ:
6370 case OP_UNPACK_LOWPS:
6371 case OP_UNPACK_LOWPD:
6372 case OP_UNPACK_HIGHB:
6373 case OP_UNPACK_HIGHW:
6374 case OP_UNPACK_HIGHD:
6375 case OP_UNPACK_HIGHQ:
6376 case OP_UNPACK_HIGHPS:
6377 case OP_UNPACK_HIGHPD: {
6378 int mask [16];
6379 LLVMValueRef mask_values [16];
6380 int i, mask_size = 0;
6381 gboolean low = FALSE;
6383 switch (ins->opcode) {
6384 case OP_UNPACK_LOWB:
6385 mask_size = 16;
6386 low = TRUE;
6387 break;
6388 case OP_UNPACK_LOWW:
6389 mask_size = 8;
6390 low = TRUE;
6391 break;
6392 case OP_UNPACK_LOWD:
6393 case OP_UNPACK_LOWPS:
6394 mask_size = 4;
6395 low = TRUE;
6396 break;
6397 case OP_UNPACK_LOWQ:
6398 case OP_UNPACK_LOWPD:
6399 mask_size = 2;
6400 low = TRUE;
6401 break;
6402 case OP_UNPACK_HIGHB:
6403 mask_size = 16;
6404 break;
6405 case OP_UNPACK_HIGHW:
6406 mask_size = 8;
6407 break;
6408 case OP_UNPACK_HIGHD:
6409 case OP_UNPACK_HIGHPS:
6410 mask_size = 4;
6411 break;
6412 case OP_UNPACK_HIGHQ:
6413 case OP_UNPACK_HIGHPD:
6414 mask_size = 2;
6415 break;
6416 default:
6417 g_assert_not_reached ();
6420 if (low) {
6421 for (i = 0; i < (mask_size / 2); ++i) {
6422 mask [(i * 2)] = i;
6423 mask [(i * 2) + 1] = mask_size + i;
6425 } else {
6426 for (i = 0; i < (mask_size / 2); ++i) {
6427 mask [(i * 2)] = (mask_size / 2) + i;
6428 mask [(i * 2) + 1] = mask_size + (mask_size / 2) + i;
6432 for (i = 0; i < mask_size; ++i)
6433 mask_values [i] = LLVMConstInt (LLVMInt32Type (), mask [i], FALSE);
6435 values [ins->dreg] =
6436 LLVMBuildShuffleVector (builder, values [ins->sreg1], values [ins->sreg2],
6437 LLVMConstVector (mask_values, mask_size), dname);
6438 break;
6441 case OP_DUPPD: {
6442 LLVMTypeRef t = simd_op_to_llvm_type (ins->opcode);
6443 LLVMValueRef v, val;
6445 v = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6446 val = LLVMConstNull (t);
6447 val = LLVMBuildInsertElement (builder, val, v, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6448 val = LLVMBuildInsertElement (builder, val, v, LLVMConstInt (LLVMInt32Type (), 1, FALSE), dname);
6450 values [ins->dreg] = val;
6451 break;
6453 case OP_DUPPS_LOW:
6454 case OP_DUPPS_HIGH: {
6455 LLVMTypeRef t = simd_op_to_llvm_type (ins->opcode);
6456 LLVMValueRef v1, v2, val;
6459 if (ins->opcode == OP_DUPPS_LOW) {
6460 v1 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6461 v2 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 2, FALSE), "");
6462 } else {
6463 v1 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 1, FALSE), "");
6464 v2 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 3, FALSE), "");
6466 val = LLVMConstNull (t);
6467 val = LLVMBuildInsertElement (builder, val, v1, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6468 val = LLVMBuildInsertElement (builder, val, v1, LLVMConstInt (LLVMInt32Type (), 1, FALSE), "");
6469 val = LLVMBuildInsertElement (builder, val, v2, LLVMConstInt (LLVMInt32Type (), 2, FALSE), "");
6470 val = LLVMBuildInsertElement (builder, val, v2, LLVMConstInt (LLVMInt32Type (), 3, FALSE), "");
6472 values [ins->dreg] = val;
6473 break;
6476 case OP_DPPS: {
6477 LLVMValueRef args [3];
6479 args [0] = lhs;
6480 args [1] = rhs;
6481 /* 0xf1 == multiply all 4 elements, add them together, and store the result to the lowest element */
6482 args [2] = LLVMConstInt (LLVMInt32Type (), 0xf1, FALSE);
6484 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 3, dname);
6485 break;
6488 #endif /* SIMD */
6490 case OP_DUMMY_USE:
6491 break;
6494 * EXCEPTION HANDLING
6496 case OP_IMPLICIT_EXCEPTION:
6497 /* This marks a place where an implicit exception can happen */
6498 if (bb->region != -1)
6499 set_failure (ctx, "implicit-exception");
6500 break;
6501 case OP_THROW:
6502 case OP_RETHROW: {
6503 gboolean rethrow = (ins->opcode == OP_RETHROW);
6504 if (ctx->llvm_only) {
6505 emit_llvmonly_throw (ctx, bb, rethrow, lhs);
6506 has_terminator = TRUE;
6507 ctx->unreachable [bb->block_num] = TRUE;
6508 } else {
6509 emit_throw (ctx, bb, rethrow, lhs);
6510 builder = ctx->builder;
6512 break;
6514 case OP_CALL_HANDLER: {
6516 * We don't 'call' handlers, but instead simply branch to them.
6517 * The code generated by ENDFINALLY will branch back to us.
6519 LLVMBasicBlockRef noex_bb;
6520 GSList *bb_list;
6521 BBInfo *info = &bblocks [ins->inst_target_bb->block_num];
6523 bb_list = info->call_handler_return_bbs;
6526 * Set the indicator variable for the finally clause.
6528 lhs = info->finally_ind;
6529 g_assert (lhs);
6530 LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), g_slist_length (bb_list) + 1, FALSE), lhs);
6532 /* Branch to the finally clause */
6533 LLVMBuildBr (builder, info->call_handler_target_bb);
6535 noex_bb = gen_bb (ctx, "CALL_HANDLER_CONT_BB");
6536 info->call_handler_return_bbs = g_slist_append_mempool (cfg->mempool, info->call_handler_return_bbs, noex_bb);
6538 builder = ctx->builder = create_builder (ctx);
6539 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
6541 bblocks [bb->block_num].end_bblock = noex_bb;
6542 break;
6544 case OP_START_HANDLER: {
6545 break;
6547 case OP_ENDFINALLY: {
6548 LLVMBasicBlockRef resume_bb;
6549 MonoBasicBlock *handler_bb;
6550 LLVMValueRef val, switch_ins, callee;
6551 GSList *bb_list;
6552 BBInfo *info;
6554 handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)));
6555 g_assert (handler_bb);
6556 info = &bblocks [handler_bb->block_num];
6557 lhs = info->finally_ind;
6558 g_assert (lhs);
6560 bb_list = info->call_handler_return_bbs;
6562 resume_bb = gen_bb (ctx, "ENDFINALLY_RESUME_BB");
6564 /* Load the finally variable */
6565 val = LLVMBuildLoad (builder, lhs, "");
6567 /* Reset the variable */
6568 LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), lhs);
6570 /* Branch to either resume_bb, or to the bblocks in bb_list */
6571 switch_ins = LLVMBuildSwitch (builder, val, resume_bb, g_slist_length (bb_list));
6573 * The other targets are added at the end to handle OP_CALL_HANDLER
6574 * opcodes processed later.
6576 info->endfinally_switch_ins_list = g_slist_append_mempool (cfg->mempool, info->endfinally_switch_ins_list, switch_ins);
6578 builder = ctx->builder = create_builder (ctx);
6579 LLVMPositionBuilderAtEnd (ctx->builder, resume_bb);
6581 if (ctx->llvm_only) {
6582 emit_resume_eh (ctx, bb);
6583 } else {
6584 if (ctx->cfg->compile_aot) {
6585 callee = get_callee (ctx, LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE), MONO_PATCH_INFO_INTERNAL_METHOD, "llvm_resume_unwind_trampoline");
6586 } else {
6587 #if LLVM_API_VERSION > 100
6588 MonoJitICallInfo *info;
6590 info = mono_find_jit_icall_by_name ("llvm_resume_unwind_trampoline");
6591 g_assert (info);
6592 gpointer target = (void*)info->func;
6593 LLVMTypeRef icall_sig = LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE);
6594 callee = emit_jit_callee (ctx, "llvm_resume_unwind_trampoline", icall_sig, target);
6595 #else
6596 callee = LLVMGetNamedFunction (ctx->lmodule, "llvm_resume_unwind_trampoline");
6597 #endif
6599 LLVMBuildCall (builder, callee, NULL, 0, "");
6600 LLVMBuildUnreachable (builder);
6603 has_terminator = TRUE;
6604 break;
6606 case OP_IL_SEQ_POINT:
6607 break;
6608 default: {
6609 char reason [128];
6611 sprintf (reason, "opcode %s", mono_inst_name (ins->opcode));
6612 set_failure (ctx, reason);
6613 break;
6617 if (!ctx_ok (ctx))
6618 break;
6620 /* Convert the value to the type required by phi nodes */
6621 if (spec [MONO_INST_DEST] != ' ' && !MONO_IS_STORE_MEMBASE (ins) && ctx->vreg_types [ins->dreg]) {
6622 if (ctx->is_vphi [ins->dreg])
6623 /* vtypes */
6624 values [ins->dreg] = addresses [ins->dreg];
6625 else
6626 values [ins->dreg] = convert (ctx, values [ins->dreg], ctx->vreg_types [ins->dreg]);
6629 /* Add stores for volatile variables */
6630 if (spec [MONO_INST_DEST] != ' ' && spec [MONO_INST_DEST] != 'v' && !MONO_IS_STORE_MEMBASE (ins))
6631 emit_volatile_store (ctx, ins->dreg);
6634 if (!ctx_ok (ctx))
6635 return;
6637 if (!has_terminator && bb->next_bb && (bb == cfg->bb_entry || bb->in_count > 0)) {
6638 LLVMBuildBr (builder, get_bb (ctx, bb->next_bb));
6641 if (bb == cfg->bb_exit && sig->ret->type == MONO_TYPE_VOID) {
6642 emit_dbg_loc (ctx, builder, cfg->header->code + cfg->header->code_size - 1);
6643 LLVMBuildRetVoid (builder);
6646 if (bb == cfg->bb_entry)
6647 ctx->last_alloca = LLVMGetLastInstruction (get_bb (ctx, cfg->bb_entry));
6651 * mono_llvm_check_method_supported:
6653 * Do some quick checks to decide whenever cfg->method can be compiled by LLVM, to avoid
6654 * compiling a method twice.
6656 void
6657 mono_llvm_check_method_supported (MonoCompile *cfg)
6659 int i, j;
6661 if (cfg->llvm_only)
6662 return;
6664 if (cfg->method->save_lmf) {
6665 cfg->exception_message = g_strdup ("lmf");
6666 cfg->disable_llvm = TRUE;
6668 if (cfg->disable_llvm)
6669 return;
6672 * Nested clauses where one of the clauses is a finally clause is
6673 * not supported, because LLVM can't figure out the control flow,
6674 * probably because we resume exception handling by calling our
6675 * own function instead of using the 'resume' llvm instruction.
6677 for (i = 0; i < cfg->header->num_clauses; ++i) {
6678 for (j = 0; j < cfg->header->num_clauses; ++j) {
6679 MonoExceptionClause *clause1 = &cfg->header->clauses [i];
6680 MonoExceptionClause *clause2 = &cfg->header->clauses [j];
6682 // FIXME: Nested try clauses fail in some cases too, i.e. #37273
6683 if (i != j && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
6684 //(clause1->flags == MONO_EXCEPTION_CLAUSE_FINALLY || clause2->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
6685 cfg->exception_message = g_strdup ("nested clauses");
6686 cfg->disable_llvm = TRUE;
6687 break;
6691 if (cfg->disable_llvm)
6692 return;
6694 /* FIXME: */
6695 if (cfg->method->dynamic) {
6696 cfg->exception_message = g_strdup ("dynamic.");
6697 cfg->disable_llvm = TRUE;
6699 if (cfg->disable_llvm)
6700 return;
6703 static LLVMCallInfo*
6704 get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
6706 LLVMCallInfo *linfo;
6707 int i;
6709 if (cfg->gsharedvt && cfg->llvm_only && mini_is_gsharedvt_variable_signature (sig)) {
6710 int i, n, pindex;
6713 * Gsharedvt methods have the following calling convention:
6714 * - all arguments are passed by ref, even non generic ones
6715 * - the return value is returned by ref too, using a vret
6716 * argument passed after 'this'.
6718 n = sig->param_count + sig->hasthis;
6719 linfo = (LLVMCallInfo*)mono_mempool_alloc0 (cfg->mempool, sizeof (LLVMCallInfo) + (sizeof (LLVMArgInfo) * n));
6721 pindex = 0;
6722 if (sig->hasthis)
6723 linfo->args [pindex ++].storage = LLVMArgNormal;
6725 if (sig->ret->type != MONO_TYPE_VOID) {
6726 if (mini_is_gsharedvt_variable_type (sig->ret))
6727 linfo->ret.storage = LLVMArgGsharedvtVariable;
6728 else if (mini_type_is_vtype (sig->ret))
6729 linfo->ret.storage = LLVMArgGsharedvtFixedVtype;
6730 else
6731 linfo->ret.storage = LLVMArgGsharedvtFixed;
6732 linfo->vret_arg_index = pindex;
6733 } else {
6734 linfo->ret.storage = LLVMArgNone;
6737 for (i = 0; i < sig->param_count; ++i) {
6738 if (sig->params [i]->byref)
6739 linfo->args [pindex].storage = LLVMArgNormal;
6740 else if (mini_is_gsharedvt_variable_type (sig->params [i]))
6741 linfo->args [pindex].storage = LLVMArgGsharedvtVariable;
6742 else if (mini_type_is_vtype (sig->params [i]))
6743 linfo->args [pindex].storage = LLVMArgGsharedvtFixedVtype;
6744 else
6745 linfo->args [pindex].storage = LLVMArgGsharedvtFixed;
6746 linfo->args [pindex].type = sig->params [i];
6747 pindex ++;
6749 return linfo;
6753 linfo = mono_arch_get_llvm_call_info (cfg, sig);
6754 for (i = 0; i < sig->param_count; ++i)
6755 linfo->args [i + sig->hasthis].type = sig->params [i];
6757 return linfo;
6760 static void
6761 emit_method_inner (EmitContext *ctx);
6763 static void
6764 free_ctx (EmitContext *ctx)
6766 GSList *l;
6768 g_free (ctx->values);
6769 g_free (ctx->addresses);
6770 g_free (ctx->vreg_types);
6771 g_free (ctx->is_vphi);
6772 g_free (ctx->vreg_cli_types);
6773 g_free (ctx->is_dead);
6774 g_free (ctx->unreachable);
6775 g_ptr_array_free (ctx->phi_values, TRUE);
6776 g_free (ctx->bblocks);
6777 g_hash_table_destroy (ctx->region_to_handler);
6778 g_hash_table_destroy (ctx->clause_to_handler);
6779 g_hash_table_destroy (ctx->jit_callees);
6781 GHashTableIter iter;
6782 g_hash_table_iter_init (&iter, ctx->method_to_callers);
6783 while (g_hash_table_iter_next (&iter, NULL, (gpointer)&l))
6784 g_slist_free (l);
6786 g_hash_table_destroy (ctx->method_to_callers);
6788 g_free (ctx->method_name);
6789 g_ptr_array_free (ctx->bblock_list, TRUE);
6791 for (l = ctx->builders; l; l = l->next) {
6792 LLVMBuilderRef builder = (LLVMBuilderRef)l->data;
6793 LLVMDisposeBuilder (builder);
6796 g_free (ctx);
6800 * mono_llvm_emit_method:
6802 * Emit LLVM IL from the mono IL, and compile it to native code using LLVM.
6804 void
6805 mono_llvm_emit_method (MonoCompile *cfg)
6807 EmitContext *ctx;
6808 char *method_name;
6809 gboolean is_linkonce = FALSE;
6810 int i;
6812 /* The code below might acquire the loader lock, so use it for global locking */
6813 mono_loader_lock ();
6815 /* Used to communicate with the callbacks */
6816 mono_native_tls_set_value (current_cfg_tls_id, cfg);
6818 ctx = g_new0 (EmitContext, 1);
6819 ctx->cfg = cfg;
6820 ctx->mempool = cfg->mempool;
6823 * This maps vregs to the LLVM instruction defining them
6825 ctx->values = g_new0 (LLVMValueRef, cfg->next_vreg);
6827 * This maps vregs for volatile variables to the LLVM instruction defining their
6828 * address.
6830 ctx->addresses = g_new0 (LLVMValueRef, cfg->next_vreg);
6831 ctx->vreg_types = g_new0 (LLVMTypeRef, cfg->next_vreg);
6832 ctx->is_vphi = g_new0 (gboolean, cfg->next_vreg);
6833 ctx->vreg_cli_types = g_new0 (MonoType*, cfg->next_vreg);
6834 ctx->phi_values = g_ptr_array_sized_new (256);
6836 * This signals whenever the vreg was defined by a phi node with no input vars
6837 * (i.e. all its input bblocks end with NOT_REACHABLE).
6839 ctx->is_dead = g_new0 (gboolean, cfg->next_vreg);
6840 /* Whenever the bblock is unreachable */
6841 ctx->unreachable = g_new0 (gboolean, cfg->max_block_num);
6842 ctx->bblock_list = g_ptr_array_sized_new (256);
6844 ctx->region_to_handler = g_hash_table_new (NULL, NULL);
6845 ctx->clause_to_handler = g_hash_table_new (NULL, NULL);
6846 ctx->method_to_callers = g_hash_table_new (NULL, NULL);
6847 ctx->jit_callees = g_hash_table_new (NULL, NULL);
6848 if (cfg->compile_aot) {
6849 ctx->module = &aot_module;
6851 method_name = NULL;
6853 * Allow the linker to discard duplicate copies of wrappers, generic instances etc. by using the 'linkonce'
6854 * linkage for them. This requires the following:
6855 * - the method needs to have a unique mangled name
6856 * - llvmonly mode, since the code in aot-runtime.c would initialize got slots in the wrong aot image etc.
6858 is_linkonce = ctx->module->llvm_only && ctx->module->static_link && mono_aot_is_linkonce_method (cfg->method);
6859 if (is_linkonce) {
6860 method_name = mono_aot_get_mangled_method_name (cfg->method);
6861 if (!method_name)
6862 is_linkonce = FALSE;
6864 if (method_name)
6865 printf ("%s %s\n", mono_method_full_name (cfg->method, 1), method_name);
6866 else
6867 printf ("%s\n", mono_method_full_name (cfg->method, 1));
6870 if (!method_name)
6871 method_name = mono_aot_get_method_name (cfg);
6872 cfg->llvm_method_name = g_strdup (method_name);
6873 } else {
6874 init_jit_module (cfg->domain);
6875 ctx->module = (MonoLLVMModule*)domain_jit_info (cfg->domain)->llvm_module;
6876 method_name = mono_method_full_name (cfg->method, TRUE);
6878 ctx->method_name = method_name;
6879 ctx->is_linkonce = is_linkonce;
6881 #if LLVM_API_VERSION > 100
6882 if (cfg->compile_aot)
6883 ctx->lmodule = ctx->module->lmodule;
6884 else
6885 ctx->lmodule = LLVMModuleCreateWithName ("jit-module");
6886 #else
6887 ctx->lmodule = ctx->module->lmodule;
6888 #endif
6889 ctx->llvm_only = ctx->module->llvm_only;
6891 emit_method_inner (ctx);
6893 if (!ctx_ok (ctx)) {
6894 if (ctx->lmethod) {
6895 /* Need to add unused phi nodes as they can be referenced by other values */
6896 LLVMBasicBlockRef phi_bb = LLVMAppendBasicBlock (ctx->lmethod, "PHI_BB");
6897 LLVMBuilderRef builder;
6899 builder = create_builder (ctx);
6900 LLVMPositionBuilderAtEnd (builder, phi_bb);
6902 for (i = 0; i < ctx->phi_values->len; ++i) {
6903 LLVMValueRef v = (LLVMValueRef)g_ptr_array_index (ctx->phi_values, i);
6904 if (LLVMGetInstructionParent (v) == NULL)
6905 LLVMInsertIntoBuilder (builder, v);
6908 LLVMDeleteFunction (ctx->lmethod);
6912 free_ctx (ctx);
6914 mono_native_tls_set_value (current_cfg_tls_id, NULL);
6916 mono_loader_unlock ();
6919 static void
6920 emit_method_inner (EmitContext *ctx)
6922 MonoCompile *cfg = ctx->cfg;
6923 MonoMethodSignature *sig;
6924 MonoBasicBlock *bb;
6925 LLVMTypeRef method_type;
6926 LLVMValueRef method = NULL;
6927 LLVMValueRef *values = ctx->values;
6928 int i, max_block_num, bb_index;
6929 gboolean last = FALSE;
6930 LLVMCallInfo *linfo;
6931 LLVMModuleRef lmodule = ctx->lmodule;
6932 BBInfo *bblocks;
6933 GPtrArray *bblock_list = ctx->bblock_list;
6934 MonoMethodHeader *header;
6935 MonoExceptionClause *clause;
6936 char **names;
6938 if (cfg->gsharedvt && !cfg->llvm_only) {
6939 set_failure (ctx, "gsharedvt");
6940 return;
6943 #if 1
6945 static int count = 0;
6946 count ++;
6948 if (g_getenv ("LLVM_COUNT")) {
6949 if (count == atoi (g_getenv ("LLVM_COUNT"))) {
6950 printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
6951 fflush (stdout);
6952 last = TRUE;
6954 if (count > atoi (g_getenv ("LLVM_COUNT"))) {
6955 set_failure (ctx, "count");
6956 return;
6960 #endif
6962 sig = mono_method_signature (cfg->method);
6963 ctx->sig = sig;
6965 linfo = get_llvm_call_info (cfg, sig);
6966 ctx->linfo = linfo;
6967 if (!ctx_ok (ctx))
6968 return;
6970 if (cfg->rgctx_var)
6971 linfo->rgctx_arg = TRUE;
6972 ctx->method_type = method_type = sig_to_llvm_sig_full (ctx, sig, linfo);
6973 if (!ctx_ok (ctx))
6974 return;
6976 method = LLVMAddFunction (lmodule, ctx->method_name, method_type);
6977 ctx->lmethod = method;
6979 if (!cfg->llvm_only)
6980 LLVMSetFunctionCallConv (method, LLVMMono1CallConv);
6981 LLVMSetLinkage (method, LLVMPrivateLinkage);
6983 LLVMAddFunctionAttr (method, LLVMUWTable);
6985 if (cfg->compile_aot) {
6986 LLVMSetLinkage (method, LLVMInternalLinkage);
6987 if (ctx->module->external_symbols) {
6988 LLVMSetLinkage (method, LLVMExternalLinkage);
6989 LLVMSetVisibility (method, LLVMHiddenVisibility);
6991 if (ctx->is_linkonce) {
6992 LLVMSetLinkage (method, LLVMLinkOnceAnyLinkage);
6993 LLVMSetVisibility (method, LLVMDefaultVisibility);
6995 } else {
6996 #if LLVM_API_VERSION > 100
6997 LLVMSetLinkage (method, LLVMExternalLinkage);
6998 #else
6999 LLVMSetLinkage (method, LLVMPrivateLinkage);
7000 #endif
7003 if (cfg->method->save_lmf && !cfg->llvm_only) {
7004 set_failure (ctx, "lmf");
7005 return;
7008 if (sig->pinvoke && cfg->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && !cfg->llvm_only) {
7009 set_failure (ctx, "pinvoke signature");
7010 return;
7013 header = cfg->header;
7014 for (i = 0; i < header->num_clauses; ++i) {
7015 clause = &header->clauses [i];
7016 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_NONE) {
7017 set_failure (ctx, "non-finally/catch clause.");
7018 return;
7021 if (header->num_clauses || (cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING) || cfg->no_inline)
7022 /* We can't handle inlined methods with clauses */
7023 LLVMAddFunctionAttr (method, LLVMNoInlineAttribute);
7025 if (linfo->rgctx_arg) {
7026 ctx->rgctx_arg = LLVMGetParam (method, linfo->rgctx_arg_pindex);
7027 ctx->rgctx_arg_pindex = linfo->rgctx_arg_pindex;
7029 * We mark the rgctx parameter with the inreg attribute, which is mapped to
7030 * MONO_ARCH_RGCTX_REG in the Mono calling convention in llvm, i.e.
7031 * CC_X86_64_Mono in X86CallingConv.td.
7033 if (!ctx->llvm_only)
7034 LLVMAddAttribute (ctx->rgctx_arg, LLVMInRegAttribute);
7035 LLVMSetValueName (ctx->rgctx_arg, "rgctx");
7036 } else {
7037 ctx->rgctx_arg_pindex = -1;
7039 if (cfg->vret_addr) {
7040 values [cfg->vret_addr->dreg] = LLVMGetParam (method, linfo->vret_arg_pindex);
7041 LLVMSetValueName (values [cfg->vret_addr->dreg], "vret");
7042 if (linfo->ret.storage == LLVMArgVtypeByRef) {
7043 LLVMAddAttribute (LLVMGetParam (method, linfo->vret_arg_pindex), LLVMStructRetAttribute);
7044 LLVMAddAttribute (LLVMGetParam (method, linfo->vret_arg_pindex), LLVMNoAliasAttribute);
7048 if (sig->hasthis) {
7049 ctx->this_arg_pindex = linfo->this_arg_pindex;
7050 ctx->this_arg = LLVMGetParam (method, linfo->this_arg_pindex);
7051 values [cfg->args [0]->dreg] = ctx->this_arg;
7052 LLVMSetValueName (values [cfg->args [0]->dreg], "this");
7055 names = g_new (char *, sig->param_count);
7056 mono_method_get_param_names (cfg->method, (const char **) names);
7058 /* Set parameter names/attributes */
7059 for (i = 0; i < sig->param_count; ++i) {
7060 LLVMArgInfo *ainfo = &linfo->args [i + sig->hasthis];
7061 char *name;
7062 int pindex = ainfo->pindex + ainfo->ndummy_fpargs;
7063 int j;
7065 for (j = 0; j < ainfo->ndummy_fpargs; ++j) {
7066 name = g_strdup_printf ("dummy_%d_%d", i, j);
7067 LLVMSetValueName (LLVMGetParam (method, ainfo->pindex + j), name);
7068 g_free (name);
7071 if (ainfo->storage == LLVMArgVtypeInReg && ainfo->pair_storage [0] == LLVMArgNone && ainfo->pair_storage [1] == LLVMArgNone)
7072 continue;
7074 values [cfg->args [i + sig->hasthis]->dreg] = LLVMGetParam (method, pindex);
7075 if (ainfo->storage == LLVMArgGsharedvtFixed || ainfo->storage == LLVMArgGsharedvtFixedVtype) {
7076 if (names [i] && names [i][0] != '\0')
7077 name = g_strdup_printf ("p_arg_%s", names [i]);
7078 else
7079 name = g_strdup_printf ("p_arg_%d", i);
7080 } else {
7081 if (names [i] && names [i][0] != '\0')
7082 name = g_strdup_printf ("arg_%s", names [i]);
7083 else
7084 name = g_strdup_printf ("arg_%d", i);
7086 LLVMSetValueName (values [cfg->args [i + sig->hasthis]->dreg], name);
7087 g_free (name);
7088 if (ainfo->storage == LLVMArgVtypeByVal)
7089 LLVMAddAttribute (LLVMGetParam (method, pindex), LLVMByValAttribute);
7091 if (ainfo->storage == LLVMArgVtypeByRef) {
7092 /* For OP_LDADDR */
7093 cfg->args [i + sig->hasthis]->opcode = OP_VTARG_ADDR;
7096 g_free (names);
7098 if (ctx->module->emit_dwarf && cfg->compile_aot && mono_debug_enabled ()) {
7099 ctx->minfo = mono_debug_lookup_method (cfg->method);
7100 ctx->dbg_md = emit_dbg_subprogram (ctx, cfg, method, ctx->method_name);
7103 max_block_num = 0;
7104 for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
7105 max_block_num = MAX (max_block_num, bb->block_num);
7106 ctx->bblocks = bblocks = g_new0 (BBInfo, max_block_num + 1);
7108 /* Add branches between non-consecutive bblocks */
7109 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7110 if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins) &&
7111 bb->next_bb != bb->last_ins->inst_false_bb) {
7113 MonoInst *inst = (MonoInst*)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
7114 inst->opcode = OP_BR;
7115 inst->inst_target_bb = bb->last_ins->inst_false_bb;
7116 mono_bblock_add_inst (bb, inst);
7121 * The INDIRECT flag added by OP_LDADDR inhibits optimizations, even if the LDADDR
7122 * was later optimized away, so clear these flags, and add them back for the still
7123 * present OP_LDADDR instructions.
7125 for (i = 0; i < cfg->next_vreg; ++i) {
7126 MonoInst *ins;
7128 ins = get_vreg_to_inst (cfg, i);
7129 if (ins && ins != cfg->rgctx_var)
7130 ins->flags &= ~MONO_INST_INDIRECT;
7134 * Make a first pass over the code to precreate PHI nodes/set INDIRECT flags.
7136 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7137 MonoInst *ins;
7138 LLVMBuilderRef builder;
7139 char *dname;
7140 char dname_buf[128];
7142 builder = create_builder (ctx);
7144 for (ins = bb->code; ins; ins = ins->next) {
7145 switch (ins->opcode) {
7146 case OP_PHI:
7147 case OP_FPHI:
7148 case OP_VPHI:
7149 case OP_XPHI: {
7150 LLVMTypeRef phi_type = llvm_type_to_stack_type (cfg, type_to_llvm_type (ctx, &ins->klass->byval_arg));
7152 if (!ctx_ok (ctx))
7153 return;
7155 if (ins->opcode == OP_VPHI) {
7156 /* Treat valuetype PHI nodes as operating on the address itself */
7157 g_assert (ins->klass);
7158 phi_type = LLVMPointerType (type_to_llvm_type (ctx, &ins->klass->byval_arg), 0);
7162 * Have to precreate these, as they can be referenced by
7163 * earlier instructions.
7165 sprintf (dname_buf, "t%d", ins->dreg);
7166 dname = dname_buf;
7167 values [ins->dreg] = LLVMBuildPhi (builder, phi_type, dname);
7169 if (ins->opcode == OP_VPHI)
7170 ctx->addresses [ins->dreg] = values [ins->dreg];
7172 g_ptr_array_add (ctx->phi_values, values [ins->dreg]);
7175 * Set the expected type of the incoming arguments since these have
7176 * to have the same type.
7178 for (i = 0; i < ins->inst_phi_args [0]; i++) {
7179 int sreg1 = ins->inst_phi_args [i + 1];
7181 if (sreg1 != -1) {
7182 if (ins->opcode == OP_VPHI)
7183 ctx->is_vphi [sreg1] = TRUE;
7184 ctx->vreg_types [sreg1] = phi_type;
7187 break;
7189 case OP_LDADDR:
7190 ((MonoInst*)ins->inst_p0)->flags |= MONO_INST_INDIRECT;
7191 break;
7192 default:
7193 break;
7199 * Create an ordering for bblocks, use the depth first order first, then
7200 * put the exception handling bblocks last.
7202 for (bb_index = 0; bb_index < cfg->num_bblocks; ++bb_index) {
7203 bb = cfg->bblocks [bb_index];
7204 if (!(bb->region != -1 && !MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY))) {
7205 g_ptr_array_add (bblock_list, bb);
7206 bblocks [bb->block_num].added = TRUE;
7210 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7211 if (!bblocks [bb->block_num].added)
7212 g_ptr_array_add (bblock_list, bb);
7216 * Second pass: generate code.
7218 // Emit entry point
7219 LLVMBuilderRef entry_builder = create_builder (ctx);
7220 LLVMBasicBlockRef entry_bb = get_bb (ctx, cfg->bb_entry);
7221 LLVMPositionBuilderAtEnd (entry_builder, entry_bb);
7222 emit_entry_bb (ctx, entry_builder);
7224 // Make landing pads first
7225 ctx->exc_meta = g_hash_table_new_full (NULL, NULL, NULL, NULL);
7227 if (ctx->llvm_only) {
7228 size_t group_index = 0;
7229 while (group_index < cfg->header->num_clauses) {
7230 int count = 0;
7231 size_t cursor = group_index;
7232 while (cursor < cfg->header->num_clauses &&
7233 CLAUSE_START (&cfg->header->clauses [cursor]) == CLAUSE_START (&cfg->header->clauses [group_index]) &&
7234 CLAUSE_END (&cfg->header->clauses [cursor]) == CLAUSE_END (&cfg->header->clauses [group_index])) {
7235 count++;
7236 cursor++;
7239 LLVMBasicBlockRef lpad_bb = emit_landing_pad (ctx, group_index, count);
7240 intptr_t key = CLAUSE_END (&cfg->header->clauses [group_index]);
7241 g_hash_table_insert (ctx->exc_meta, (gpointer)key, lpad_bb);
7243 group_index = cursor;
7247 for (bb_index = 0; bb_index < bblock_list->len; ++bb_index) {
7248 bb = (MonoBasicBlock*)g_ptr_array_index (bblock_list, bb_index);
7250 // Prune unreachable mono BBs.
7251 if (!(bb == cfg->bb_entry || bb->in_count > 0))
7252 continue;
7254 process_bb (ctx, bb);
7255 if (!ctx_ok (ctx))
7256 return;
7258 g_hash_table_destroy (ctx->exc_meta);
7260 mono_memory_barrier ();
7262 /* Add incoming phi values */
7263 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7264 GSList *l, *ins_list;
7266 ins_list = bblocks [bb->block_num].phi_nodes;
7268 for (l = ins_list; l; l = l->next) {
7269 PhiNode *node = (PhiNode*)l->data;
7270 MonoInst *phi = node->phi;
7271 int sreg1 = node->sreg;
7272 LLVMBasicBlockRef in_bb;
7274 if (sreg1 == -1)
7275 continue;
7277 in_bb = get_end_bb (ctx, node->in_bb);
7279 if (ctx->unreachable [node->in_bb->block_num])
7280 continue;
7282 if (!values [sreg1]) {
7283 /* Can happen with values in EH clauses */
7284 set_failure (ctx, "incoming phi sreg1");
7285 return;
7288 if (phi->opcode == OP_VPHI) {
7289 g_assert (LLVMTypeOf (ctx->addresses [sreg1]) == LLVMTypeOf (values [phi->dreg]));
7290 LLVMAddIncoming (values [phi->dreg], &ctx->addresses [sreg1], &in_bb, 1);
7291 } else {
7292 if (LLVMTypeOf (values [sreg1]) != LLVMTypeOf (values [phi->dreg])) {
7293 set_failure (ctx, "incoming phi arg type mismatch");
7294 return;
7296 g_assert (LLVMTypeOf (values [sreg1]) == LLVMTypeOf (values [phi->dreg]));
7297 LLVMAddIncoming (values [phi->dreg], &values [sreg1], &in_bb, 1);
7302 /* Nullify empty phi instructions */
7303 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7304 GSList *l, *ins_list;
7306 ins_list = bblocks [bb->block_num].phi_nodes;
7308 for (l = ins_list; l; l = l->next) {
7309 PhiNode *node = (PhiNode*)l->data;
7310 MonoInst *phi = node->phi;
7311 LLVMValueRef phi_ins = values [phi->dreg];
7313 if (!phi_ins)
7314 /* Already removed */
7315 continue;
7317 if (LLVMCountIncoming (phi_ins) == 0) {
7318 mono_llvm_replace_uses_of (phi_ins, LLVMConstNull (LLVMTypeOf (phi_ins)));
7319 LLVMInstructionEraseFromParent (phi_ins);
7320 values [phi->dreg] = NULL;
7325 /* Create the SWITCH statements for ENDFINALLY instructions */
7326 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7327 BBInfo *info = &bblocks [bb->block_num];
7328 GSList *l;
7329 for (l = info->endfinally_switch_ins_list; l; l = l->next) {
7330 LLVMValueRef switch_ins = (LLVMValueRef)l->data;
7331 GSList *bb_list = info->call_handler_return_bbs;
7333 GSList *bb_list_iter;
7334 i = 0;
7335 for (bb_list_iter = bb_list; bb_list_iter; bb_list_iter = g_slist_next (bb_list_iter)) {
7336 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i + 1, FALSE), (LLVMBasicBlockRef)bb_list_iter->data);
7337 i ++;
7342 /* Initialize the method if needed */
7343 if (cfg->compile_aot && ctx->llvm_only) {
7344 // FIXME: Add more shared got entries
7345 ctx->builder = create_builder (ctx);
7346 LLVMPositionBuilderAtEnd (ctx->builder, ctx->init_bb);
7348 ctx->module->max_method_idx = MAX (ctx->module->max_method_idx, cfg->method_index);
7350 // FIXME: beforefieldinit
7352 * NATIVE_TO_MANAGED methods might be called on a thread not attached to the runtime, so they are initialized when loaded
7353 * in load_method ().
7355 if ((ctx->has_got_access || mono_class_get_cctor (cfg->method->klass)) && !(cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED)) {
7357 * linkonce methods shouldn't have initialization,
7358 * because they might belong to assemblies which
7359 * haven't been loaded yet.
7361 g_assert (!ctx->is_linkonce);
7362 emit_init_method (ctx);
7363 } else {
7364 LLVMBuildBr (ctx->builder, ctx->inited_bb);
7368 if (cfg->llvm_only) {
7369 GHashTableIter iter;
7370 MonoMethod *method;
7371 GSList *callers, *l, *l2;
7374 * Add the contents of ctx->method_to_callers to module->method_to_callers.
7375 * We can't do this earlier, as it contains llvm instructions which can be
7376 * freed if compilation fails.
7377 * FIXME: Get rid of this when all methods can be llvm compiled.
7379 g_hash_table_iter_init (&iter, ctx->method_to_callers);
7380 while (g_hash_table_iter_next (&iter, (void**)&method, (void**)&callers)) {
7381 for (l = callers; l; l = l->next) {
7382 l2 = (GSList*)g_hash_table_lookup (ctx->module->method_to_callers, method);
7383 l2 = g_slist_prepend (l2, l->data);
7384 g_hash_table_insert (ctx->module->method_to_callers, method, l2);
7389 if (cfg->verbose_level > 1)
7390 mono_llvm_dump_value (method);
7392 if (cfg->compile_aot && !cfg->llvm_only)
7393 mark_as_used (ctx->module, method);
7395 if (!cfg->llvm_only) {
7396 LLVMValueRef md_args [16];
7397 LLVMValueRef md_node;
7398 int method_index;
7400 if (cfg->compile_aot)
7401 method_index = mono_aot_get_method_index (cfg->orig_method);
7402 else
7403 method_index = 1;
7404 md_args [0] = LLVMMDString (ctx->method_name, strlen (ctx->method_name));
7405 md_args [1] = LLVMConstInt (LLVMInt32Type (), method_index, FALSE);
7406 md_node = LLVMMDNode (md_args, 2);
7407 LLVMAddNamedMetadataOperand (lmodule, "mono.function_indexes", md_node);
7408 //LLVMSetMetadata (method, md_kind, LLVMMDNode (&md_arg, 1));
7411 if (cfg->compile_aot) {
7412 /* Don't generate native code, keep the LLVM IR */
7413 if (cfg->verbose_level)
7414 printf ("%s emitted as %s\n", mono_method_full_name (cfg->method, TRUE), ctx->method_name);
7416 #if LLVM_API_VERSION < 100
7417 /* VerifyFunction can't handle some of the debug info created by DIBuilder in llvm 3.9 */
7418 int err = LLVMVerifyFunction(ctx->lmethod, LLVMPrintMessageAction);
7419 g_assert (err == 0);
7420 #endif
7421 } else {
7422 //LLVMVerifyFunction(method, 0);
7423 #if LLVM_API_VERSION > 100
7424 MonoDomain *domain = mono_domain_get ();
7425 MonoJitDomainInfo *domain_info;
7426 int nvars = g_hash_table_size (ctx->jit_callees);
7427 LLVMValueRef *callee_vars = g_new0 (LLVMValueRef, nvars);
7428 gpointer *callee_addrs = g_new0 (gpointer, nvars);
7429 GHashTableIter iter;
7430 LLVMValueRef var;
7431 MonoMethod *callee;
7432 gpointer eh_frame;
7435 * Compute the addresses of the LLVM globals pointing to the
7436 * methods called by the current method. Pass it to the trampoline
7437 * code so it can update them after their corresponding method was
7438 * compiled.
7440 g_hash_table_iter_init (&iter, ctx->jit_callees);
7441 i = 0;
7442 while (g_hash_table_iter_next (&iter, NULL, (void**)&var))
7443 callee_vars [i ++] = var;
7445 cfg->native_code = mono_llvm_compile_method (ctx->module->mono_ee, ctx->lmethod, nvars, callee_vars, callee_addrs, &eh_frame);
7447 decode_llvm_eh_info (ctx, eh_frame);
7449 mono_domain_lock (domain);
7450 domain_info = domain_jit_info (domain);
7451 if (!domain_info->llvm_jit_callees)
7452 domain_info->llvm_jit_callees = g_hash_table_new (NULL, NULL);
7453 g_hash_table_iter_init (&iter, ctx->jit_callees);
7454 i = 0;
7455 while (g_hash_table_iter_next (&iter, (void**)&callee, (void**)&var)) {
7456 GSList *addrs = g_hash_table_lookup (domain_info->llvm_jit_callees, callee);
7457 addrs = g_slist_prepend (addrs, callee_addrs [i]);
7458 g_hash_table_insert (domain_info->llvm_jit_callees, callee, addrs);
7459 i ++;
7461 mono_domain_unlock (domain);
7462 #else
7463 mono_llvm_optimize_method (ctx->module->mono_ee, ctx->lmethod);
7465 if (cfg->verbose_level > 1)
7466 mono_llvm_dump_value (ctx->lmethod);
7468 cfg->native_code = (unsigned char*)LLVMGetPointerToGlobal (ctx->module->ee, ctx->lmethod);
7470 /* Set by emit_cb */
7471 g_assert (cfg->code_len);
7472 #endif
7475 if (ctx->module->method_to_lmethod)
7476 g_hash_table_insert (ctx->module->method_to_lmethod, cfg->method, ctx->lmethod);
7477 if (ctx->module->idx_to_lmethod)
7478 g_hash_table_insert (ctx->module->idx_to_lmethod, GINT_TO_POINTER (cfg->method_index), ctx->lmethod);
7480 if (ctx->llvm_only && cfg->orig_method->klass->valuetype && !(cfg->orig_method->flags & METHOD_ATTRIBUTE_STATIC))
7481 emit_unbox_tramp (ctx, ctx->method_name, ctx->method_type, ctx->lmethod, cfg->method_index);
7485 * mono_llvm_create_vars:
7487 * Same as mono_arch_create_vars () for LLVM.
7489 void
7490 mono_llvm_create_vars (MonoCompile *cfg)
7492 MonoMethodSignature *sig;
7494 sig = mono_method_signature (cfg->method);
7495 if (cfg->gsharedvt && cfg->llvm_only) {
7496 if (mini_is_gsharedvt_variable_signature (sig) && sig->ret->type != MONO_TYPE_VOID) {
7497 cfg->vret_addr = mono_compile_create_var (cfg, &mono_get_intptr_class ()->byval_arg, OP_ARG);
7498 if (G_UNLIKELY (cfg->verbose_level > 1)) {
7499 printf ("vret_addr = ");
7500 mono_print_ins (cfg->vret_addr);
7503 } else {
7504 mono_arch_create_vars (cfg);
7509 * mono_llvm_emit_call:
7511 * Same as mono_arch_emit_call () for LLVM.
7513 void
7514 mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call)
7516 MonoInst *in;
7517 MonoMethodSignature *sig;
7518 int i, n, stack_size;
7519 LLVMArgInfo *ainfo;
7521 stack_size = 0;
7523 sig = call->signature;
7524 n = sig->param_count + sig->hasthis;
7526 call->cinfo = get_llvm_call_info (cfg, sig);
7528 if (cfg->disable_llvm)
7529 return;
7531 if (sig->call_convention == MONO_CALL_VARARG) {
7532 cfg->exception_message = g_strdup ("varargs");
7533 cfg->disable_llvm = TRUE;
7536 for (i = 0; i < n; ++i) {
7537 MonoInst *ins;
7539 ainfo = call->cinfo->args + i;
7541 in = call->args [i];
7543 /* Simply remember the arguments */
7544 switch (ainfo->storage) {
7545 case LLVMArgNormal: {
7546 MonoType *t = (sig->hasthis && i == 0) ? &mono_get_intptr_class ()->byval_arg : ainfo->type;
7547 int opcode;
7549 opcode = mono_type_to_regmove (cfg, t);
7550 if (opcode == OP_FMOVE) {
7551 MONO_INST_NEW (cfg, ins, OP_FMOVE);
7552 ins->dreg = mono_alloc_freg (cfg);
7553 } else if (opcode == OP_LMOVE) {
7554 MONO_INST_NEW (cfg, ins, OP_LMOVE);
7555 ins->dreg = mono_alloc_lreg (cfg);
7556 } else if (opcode == OP_RMOVE) {
7557 MONO_INST_NEW (cfg, ins, OP_RMOVE);
7558 ins->dreg = mono_alloc_freg (cfg);
7559 } else {
7560 MONO_INST_NEW (cfg, ins, OP_MOVE);
7561 ins->dreg = mono_alloc_ireg (cfg);
7563 ins->sreg1 = in->dreg;
7564 break;
7566 case LLVMArgVtypeByVal:
7567 case LLVMArgVtypeByRef:
7568 case LLVMArgVtypeInReg:
7569 case LLVMArgVtypeAsScalar:
7570 case LLVMArgAsIArgs:
7571 case LLVMArgAsFpArgs:
7572 case LLVMArgGsharedvtVariable:
7573 case LLVMArgGsharedvtFixed:
7574 case LLVMArgGsharedvtFixedVtype:
7575 MONO_INST_NEW (cfg, ins, OP_LLVM_OUTARG_VT);
7576 ins->dreg = mono_alloc_ireg (cfg);
7577 ins->sreg1 = in->dreg;
7578 ins->inst_p0 = mono_mempool_alloc0 (cfg->mempool, sizeof (LLVMArgInfo));
7579 memcpy (ins->inst_p0, ainfo, sizeof (LLVMArgInfo));
7580 ins->inst_vtype = ainfo->type;
7581 ins->klass = mono_class_from_mono_type (ainfo->type);
7582 break;
7583 default:
7584 cfg->exception_message = g_strdup ("ainfo->storage");
7585 cfg->disable_llvm = TRUE;
7586 return;
7589 if (!cfg->disable_llvm) {
7590 MONO_ADD_INS (cfg->cbb, ins);
7591 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, 0, FALSE);
7596 static unsigned char*
7597 alloc_cb (LLVMValueRef function, int size)
7599 MonoCompile *cfg;
7601 cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
7603 if (cfg) {
7604 // FIXME: dynamic
7605 return (unsigned char*)mono_domain_code_reserve (cfg->domain, size);
7606 } else {
7607 return (unsigned char*)mono_domain_code_reserve (mono_domain_get (), size);
7611 static void
7612 emitted_cb (LLVMValueRef function, void *start, void *end)
7614 MonoCompile *cfg;
7616 cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
7617 g_assert (cfg);
7618 cfg->code_len = (guint8*)end - (guint8*)start;
7621 static void
7622 exception_cb (void *data)
7624 MonoCompile *cfg;
7625 MonoJitExceptionInfo *ei;
7626 guint32 ei_len, i, j, nested_len, nindex;
7627 gpointer *type_info;
7628 int this_reg, this_offset;
7630 cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
7631 g_assert (cfg);
7634 * data points to a DWARF FDE structure, convert it to our unwind format and
7635 * save it.
7636 * An alternative would be to save it directly, and modify our unwinder to work
7637 * with it.
7639 cfg->encoded_unwind_ops = mono_unwind_decode_fde ((guint8*)data, &cfg->encoded_unwind_ops_len, NULL, &ei, &ei_len, &type_info, &this_reg, &this_offset);
7640 if (cfg->verbose_level > 1)
7641 mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
7643 /* Count nested clauses */
7644 nested_len = 0;
7645 for (i = 0; i < ei_len; ++i) {
7646 gint32 cindex1 = *(gint32*)type_info [i];
7647 MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];
7649 for (j = 0; j < cfg->header->num_clauses; ++j) {
7650 int cindex2 = j;
7651 MonoExceptionClause *clause2 = &cfg->header->clauses [cindex2];
7653 if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
7654 nested_len ++;
7659 cfg->llvm_ex_info = (MonoJitExceptionInfo*)mono_mempool_alloc0 (cfg->mempool, (ei_len + nested_len) * sizeof (MonoJitExceptionInfo));
7660 cfg->llvm_ex_info_len = ei_len + nested_len;
7661 memcpy (cfg->llvm_ex_info, ei, ei_len * sizeof (MonoJitExceptionInfo));
7662 /* Fill the rest of the information from the type info */
7663 for (i = 0; i < ei_len; ++i) {
7664 gint32 clause_index = *(gint32*)type_info [i];
7665 MonoExceptionClause *clause = &cfg->header->clauses [clause_index];
7667 cfg->llvm_ex_info [i].flags = clause->flags;
7668 cfg->llvm_ex_info [i].data.catch_class = clause->data.catch_class;
7669 cfg->llvm_ex_info [i].clause_index = clause_index;
7673 * For nested clauses, the LLVM produced exception info associates the try interval with
7674 * the innermost handler, while mono expects it to be associated with all nesting clauses.
7675 * So add new clauses which use the IL info (catch class etc.) from the nesting clause,
7676 * and everything else from the nested clause.
7678 nindex = ei_len;
7679 for (i = 0; i < ei_len; ++i) {
7680 gint32 cindex1 = *(gint32*)type_info [i];
7681 MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];
7683 for (j = 0; j < cfg->header->num_clauses; ++j) {
7684 int cindex2 = j;
7685 MonoExceptionClause *clause2 = &cfg->header->clauses [cindex2];
7686 MonoJitExceptionInfo *nesting_ei, *nested_ei;
7688 if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
7689 /* clause1 is the nested clause */
7690 nested_ei = &cfg->llvm_ex_info [i];
7691 nesting_ei = &cfg->llvm_ex_info [nindex];
7692 nindex ++;
7694 memcpy (nesting_ei, nested_ei, sizeof (MonoJitExceptionInfo));
7696 nesting_ei->flags = clause2->flags;
7697 nesting_ei->data.catch_class = clause2->data.catch_class;
7698 nesting_ei->clause_index = cindex2;
7702 g_assert (nindex == ei_len + nested_len);
7703 cfg->llvm_this_reg = this_reg;
7704 cfg->llvm_this_offset = this_offset;
7706 /* type_info [i] is cfg mempool allocated, no need to free it */
7708 g_free (ei);
7709 g_free (type_info);
7712 #if LLVM_API_VERSION > 100
7714 * decode_llvm_eh_info:
7716 * Decode the EH table emitted by llvm in jit mode, and store
7717 * the result into cfg.
7719 static void
7720 decode_llvm_eh_info (EmitContext *ctx, gpointer eh_frame)
7722 MonoCompile *cfg = ctx->cfg;
7723 guint8 *cie, *fde;
7724 int fde_len;
7725 MonoLLVMFDEInfo info;
7726 MonoJitExceptionInfo *ei;
7727 guint8 *p = eh_frame;
7728 int version, fde_count, fde_offset;
7729 guint32 ei_len, i, nested_len;
7730 gpointer *type_info;
7731 gint32 *table;
7734 * Decode the one element EH table emitted by the MonoException class
7735 * in llvm.
7738 /* Similar to decode_llvm_mono_eh_frame () in aot-runtime.c */
7740 version = *p;
7741 g_assert (version == 3);
7742 p ++;
7743 p ++;
7744 p = (guint8 *)ALIGN_PTR_TO (p, 4);
7746 fde_count = *(guint32*)p;
7747 p += 4;
7748 table = (gint32*)p;
7750 g_assert (fde_count <= 2);
7752 /* The first entry is the real method */
7753 g_assert (table [0] == 1);
7754 fde_offset = table [1];
7755 table += fde_count * 2;
7756 /* Extra entry */
7757 cfg->code_len = table [0];
7758 fde_len = table [1] - fde_offset;
7759 table += 2;
7761 fde = (guint8*)eh_frame + fde_offset;
7762 cie = (guint8*)table;
7764 mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info);
7766 cfg->encoded_unwind_ops = info.unw_info;
7767 cfg->encoded_unwind_ops_len = info.unw_info_len;
7768 if (cfg->verbose_level > 1)
7769 mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
7770 if (info.this_reg != -1) {
7771 cfg->llvm_this_reg = info.this_reg;
7772 cfg->llvm_this_offset = info.this_offset;
7775 ei = info.ex_info;
7776 ei_len = info.ex_info_len;
7777 type_info = info.type_info;
7779 // Nested clauses are currently disabled
7780 nested_len = 0;
7782 cfg->llvm_ex_info = (MonoJitExceptionInfo*)mono_mempool_alloc0 (cfg->mempool, (ei_len + nested_len) * sizeof (MonoJitExceptionInfo));
7783 cfg->llvm_ex_info_len = ei_len + nested_len;
7784 memcpy (cfg->llvm_ex_info, ei, ei_len * sizeof (MonoJitExceptionInfo));
7785 /* Fill the rest of the information from the type info */
7786 for (i = 0; i < ei_len; ++i) {
7787 gint32 clause_index = *(gint32*)type_info [i];
7788 MonoExceptionClause *clause = &cfg->header->clauses [clause_index];
7790 cfg->llvm_ex_info [i].flags = clause->flags;
7791 cfg->llvm_ex_info [i].data.catch_class = clause->data.catch_class;
7792 cfg->llvm_ex_info [i].clause_index = clause_index;
7795 #endif
7797 static char*
7798 dlsym_cb (const char *name, void **symbol)
7800 MonoDl *current;
7801 char *err;
7803 err = NULL;
7804 if (!strcmp (name, "__bzero")) {
7805 *symbol = (void*)bzero;
7806 } else {
7807 current = mono_dl_open (NULL, 0, NULL);
7808 g_assert (current);
7810 err = mono_dl_symbol (current, name, symbol);
7812 mono_dl_close (current);
7814 #ifdef MONO_ARCH_HAVE_CREATE_LLVM_NATIVE_THUNK
7815 *symbol = (char*)mono_arch_create_llvm_native_thunk (mono_domain_get (), (guint8*)(*symbol));
7816 #endif
7817 return err;
7820 static inline void
7821 AddFunc (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeRef *param_types, int nparams)
7823 LLVMAddFunction (module, name, LLVMFunctionType (ret_type, param_types, nparams, FALSE));
7826 static inline void
7827 AddFunc2 (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeRef param_type1, LLVMTypeRef param_type2)
7829 LLVMTypeRef param_types [4];
7831 param_types [0] = param_type1;
7832 param_types [1] = param_type2;
7834 AddFunc (module, name, ret_type, param_types, 2);
7837 typedef enum {
7838 INTRINS_MEMSET,
7839 INTRINS_MEMCPY,
7840 INTRINS_SADD_OVF_I32,
7841 INTRINS_UADD_OVF_I32,
7842 INTRINS_SSUB_OVF_I32,
7843 INTRINS_USUB_OVF_I32,
7844 INTRINS_SMUL_OVF_I32,
7845 INTRINS_UMUL_OVF_I32,
7846 INTRINS_SADD_OVF_I64,
7847 INTRINS_UADD_OVF_I64,
7848 INTRINS_SSUB_OVF_I64,
7849 INTRINS_USUB_OVF_I64,
7850 INTRINS_SMUL_OVF_I64,
7851 INTRINS_UMUL_OVF_I64,
7852 INTRINS_SIN,
7853 INTRINS_COS,
7854 INTRINS_SQRT,
7855 INTRINS_FABS,
7856 INTRINS_EXPECT_I8,
7857 INTRINS_EXPECT_I1,
7858 #if defined(TARGET_AMD64) || defined(TARGET_X86)
7859 INTRINS_SSE_PMOVMSKB,
7860 INTRINS_SSE_PSRLI_W,
7861 INTRINS_SSE_PSRAI_W,
7862 INTRINS_SSE_PSLLI_W,
7863 INTRINS_SSE_PSRLI_D,
7864 INTRINS_SSE_PSRAI_D,
7865 INTRINS_SSE_PSLLI_D,
7866 INTRINS_SSE_PSRLI_Q,
7867 INTRINS_SSE_PSLLI_Q,
7868 INTRINS_SSE_SQRT_PD,
7869 INTRINS_SSE_SQRT_PS,
7870 INTRINS_SSE_RSQRT_PS,
7871 INTRINS_SSE_RCP_PS,
7872 INTRINS_SSE_CVTTPD2DQ,
7873 INTRINS_SSE_CVTTPS2DQ,
7874 INTRINS_SSE_CVTDQ2PD,
7875 INTRINS_SSE_CVTDQ2PS,
7876 INTRINS_SSE_CVTPD2DQ,
7877 INTRINS_SSE_CVTPS2DQ,
7878 INTRINS_SSE_CVTPD2PS,
7879 INTRINS_SSE_CVTPS2PD,
7880 INTRINS_SSE_CMPPD,
7881 INTRINS_SSE_CMPPS,
7882 INTRINS_SSE_PACKSSWB,
7883 INTRINS_SSE_PACKUSWB,
7884 INTRINS_SSE_PACKSSDW,
7885 INTRINS_SSE_PACKUSDW,
7886 INTRINS_SSE_MINPS,
7887 INTRINS_SSE_MAXPS,
7888 INTRINS_SSE_HADDPS,
7889 INTRINS_SSE_HSUBPS,
7890 INTRINS_SSE_ADDSUBPS,
7891 INTRINS_SSE_MINPD,
7892 INTRINS_SSE_MAXPD,
7893 INTRINS_SSE_HADDPD,
7894 INTRINS_SSE_HSUBPD,
7895 INTRINS_SSE_ADDSUBPD,
7896 INTRINS_SSE_PADDSW,
7897 INTRINS_SSE_PSUBSW,
7898 INTRINS_SSE_PADDUSW,
7899 INTRINS_SSE_PSUBUSW,
7900 INTRINS_SSE_PAVGW,
7901 INTRINS_SSE_PMULHW,
7902 INTRINS_SSE_PMULHU,
7903 INTRINS_SE_PADDSB,
7904 INTRINS_SSE_PSUBSB,
7905 INTRINS_SSE_PADDUSB,
7906 INTRINS_SSE_PSUBUSB,
7907 INTRINS_SSE_PAVGB,
7908 INTRINS_SSE_PAUSE,
7909 INTRINS_SSE_DPPS,
7910 #endif
7911 INTRINS_NUM
7912 } IntrinsicId;
7914 typedef struct {
7915 IntrinsicId id;
7916 const char *name;
7917 } IntrinsicDesc;
7919 static IntrinsicDesc intrinsics[] = {
7920 {INTRINS_MEMSET, "llvm.memset.p0i8.i32"},
7921 {INTRINS_MEMCPY, "llvm.memcpy.p0i8.p0i8.i32"},
7922 {INTRINS_SADD_OVF_I32, "llvm.sadd.with.overflow.i32"},
7923 {INTRINS_UADD_OVF_I32, "llvm.uadd.with.overflow.i32"},
7924 {INTRINS_SSUB_OVF_I32, "llvm.ssub.with.overflow.i32"},
7925 {INTRINS_USUB_OVF_I32, "llvm.usub.with.overflow.i32"},
7926 {INTRINS_SMUL_OVF_I32, "llvm.smul.with.overflow.i32"},
7927 {INTRINS_UMUL_OVF_I32, "llvm.umul.with.overflow.i32"},
7928 {INTRINS_SADD_OVF_I64, "llvm.sadd.with.overflow.i64"},
7929 {INTRINS_UADD_OVF_I64, "llvm.uadd.with.overflow.i64"},
7930 {INTRINS_SSUB_OVF_I64, "llvm.ssub.with.overflow.i64"},
7931 {INTRINS_USUB_OVF_I64, "llvm.usub.with.overflow.i64"},
7932 {INTRINS_SMUL_OVF_I64, "llvm.smul.with.overflow.i64"},
7933 {INTRINS_UMUL_OVF_I64, "llvm.umul.with.overflow.i64"},
7934 {INTRINS_SIN, "llvm.sin.f64"},
7935 {INTRINS_COS, "llvm.cos.f64"},
7936 {INTRINS_SQRT, "llvm.sqrt.f64"},
7937 /* This isn't an intrinsic, instead llvm seems to special case it by name */
7938 {INTRINS_FABS, "fabs"},
7939 {INTRINS_EXPECT_I8, "llvm.expect.i8"},
7940 {INTRINS_EXPECT_I1, "llvm.expect.i1"},
7941 #if defined(TARGET_AMD64) || defined(TARGET_X86)
7942 {INTRINS_SSE_PMOVMSKB, "llvm.x86.sse2.pmovmskb.128"},
7943 {INTRINS_SSE_PSRLI_W, "llvm.x86.sse2.psrli.w"},
7944 {INTRINS_SSE_PSRAI_W, "llvm.x86.sse2.psrai.w"},
7945 {INTRINS_SSE_PSLLI_W, "llvm.x86.sse2.pslli.w"},
7946 {INTRINS_SSE_PSRLI_D, "llvm.x86.sse2.psrli.d"},
7947 {INTRINS_SSE_PSRAI_D, "llvm.x86.sse2.psrai.d"},
7948 {INTRINS_SSE_PSLLI_D, "llvm.x86.sse2.pslli.d"},
7949 {INTRINS_SSE_PSRLI_Q, "llvm.x86.sse2.psrli.q"},
7950 {INTRINS_SSE_PSLLI_Q, "llvm.x86.sse2.pslli.q"},
7951 {INTRINS_SSE_SQRT_PD, "llvm.x86.sse2.sqrt.pd"},
7952 {INTRINS_SSE_SQRT_PS, "llvm.x86.sse.sqrt.ps"},
7953 {INTRINS_SSE_RSQRT_PS, "llvm.x86.sse.rsqrt.ps"},
7954 {INTRINS_SSE_RCP_PS, "llvm.x86.sse.rcp.ps"},
7955 {INTRINS_SSE_CVTTPD2DQ, "llvm.x86.sse2.cvttpd2dq"},
7956 {INTRINS_SSE_CVTTPS2DQ, "llvm.x86.sse2.cvttps2dq"},
7957 {INTRINS_SSE_CVTDQ2PD, "llvm.x86.sse2.cvtdq2pd"},
7958 {INTRINS_SSE_CVTDQ2PS, "llvm.x86.sse2.cvtdq2ps"},
7959 {INTRINS_SSE_CVTPD2DQ, "llvm.x86.sse2.cvtpd2dq"},
7960 {INTRINS_SSE_CVTPS2DQ, "llvm.x86.sse2.cvtps2dq"},
7961 {INTRINS_SSE_CVTPD2PS, "llvm.x86.sse2.cvtpd2ps"},
7962 {INTRINS_SSE_CVTPS2PD, "llvm.x86.sse2.cvtps2pd"},
7963 {INTRINS_SSE_CMPPD, "llvm.x86.sse2.cmp.pd"},
7964 {INTRINS_SSE_CMPPS, "llvm.x86.sse.cmp.ps"},
7965 {INTRINS_SSE_PACKSSWB, "llvm.x86.sse2.packsswb.128"},
7966 {INTRINS_SSE_PACKUSWB, "llvm.x86.sse2.packuswb.128"},
7967 {INTRINS_SSE_PACKSSDW, "llvm.x86.sse2.packssdw.128"},
7968 {INTRINS_SSE_PACKUSDW, "llvm.x86.sse41.packusdw"},
7969 {INTRINS_SSE_MINPS, "llvm.x86.sse.min.ps"},
7970 {INTRINS_SSE_MAXPS, "llvm.x86.sse.max.ps"},
7971 {INTRINS_SSE_HADDPS, "llvm.x86.sse3.hadd.ps"},
7972 {INTRINS_SSE_HSUBPS, "llvm.x86.sse3.hsub.ps"},
7973 {INTRINS_SSE_ADDSUBPS, "llvm.x86.sse3.addsub.ps"},
7974 {INTRINS_SSE_MINPD, "llvm.x86.sse2.min.pd"},
7975 {INTRINS_SSE_MAXPD, "llvm.x86.sse2.max.pd"},
7976 {INTRINS_SSE_HADDPD, "llvm.x86.sse3.hadd.pd"},
7977 {INTRINS_SSE_HSUBPD, "llvm.x86.sse3.hsub.pd"},
7978 {INTRINS_SSE_ADDSUBPD, "llvm.x86.sse3.addsub.pd"},
7979 {INTRINS_SSE_PADDSW, "llvm.x86.sse2.padds.w"},
7980 {INTRINS_SSE_PSUBSW, "llvm.x86.sse2.psubs.w"},
7981 {INTRINS_SSE_PADDUSW, "llvm.x86.sse2.paddus.w"},
7982 {INTRINS_SSE_PSUBUSW, "llvm.x86.sse2.psubus.w"},
7983 {INTRINS_SSE_PAVGW, "llvm.x86.sse2.pavg.w"},
7984 {INTRINS_SSE_PMULHW, "llvm.x86.sse2.pmulh.w"},
7985 {INTRINS_SSE_PMULHU, "llvm.x86.sse2.pmulhu.w"},
7986 {INTRINS_SE_PADDSB, "llvm.x86.sse2.padds.b"},
7987 {INTRINS_SSE_PSUBSB, "llvm.x86.sse2.psubs.b"},
7988 {INTRINS_SSE_PADDUSB, "llvm.x86.sse2.paddus.b"},
7989 {INTRINS_SSE_PSUBUSB, "llvm.x86.sse2.psubus.b"},
7990 {INTRINS_SSE_PAVGB, "llvm.x86.sse2.pavg.b"},
7991 {INTRINS_SSE_PAUSE, "llvm.x86.sse2.pause"},
7992 {INTRINS_SSE_DPPS, "llvm.x86.sse41.dpps"}
7993 #endif
7996 static void
7997 add_sse_binary (LLVMModuleRef module, const char *name, int type)
7999 LLVMTypeRef ret_type = type_to_simd_type (type);
8000 AddFunc2 (module, name, ret_type, ret_type, ret_type);
8003 static void
8004 add_intrinsic (LLVMModuleRef module, int id)
8006 const char *name;
8007 #if defined(TARGET_AMD64) || defined(TARGET_X86)
8008 LLVMTypeRef ret_type, arg_types [16];
8009 #endif
8011 name = g_hash_table_lookup (intrins_id_to_name, GINT_TO_POINTER (id));
8012 g_assert (name);
8014 switch (id) {
8015 case INTRINS_MEMSET: {
8016 LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMInt8Type (), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
8018 AddFunc (module, name, LLVMVoidType (), params, 5);
8019 break;
8021 case INTRINS_MEMCPY: {
8022 LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMPointerType (LLVMInt8Type (), 0), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
8024 AddFunc (module, name, LLVMVoidType (), params, 5);
8025 break;
8027 case INTRINS_SADD_OVF_I32:
8028 case INTRINS_UADD_OVF_I32:
8029 case INTRINS_SSUB_OVF_I32:
8030 case INTRINS_USUB_OVF_I32:
8031 case INTRINS_SMUL_OVF_I32:
8032 case INTRINS_UMUL_OVF_I32: {
8033 LLVMTypeRef ovf_res_i32 [] = { LLVMInt32Type (), LLVMInt1Type () };
8034 LLVMTypeRef params [] = { LLVMInt32Type (), LLVMInt32Type () };
8035 LLVMTypeRef ret_type = LLVMStructType (ovf_res_i32, 2, FALSE);
8037 AddFunc (module, name, ret_type, params, 2);
8038 break;
8040 case INTRINS_SADD_OVF_I64:
8041 case INTRINS_UADD_OVF_I64:
8042 case INTRINS_SSUB_OVF_I64:
8043 case INTRINS_USUB_OVF_I64:
8044 case INTRINS_SMUL_OVF_I64:
8045 case INTRINS_UMUL_OVF_I64: {
8046 LLVMTypeRef ovf_res_i64 [] = { LLVMInt64Type (), LLVMInt1Type () };
8047 LLVMTypeRef params [] = { LLVMInt64Type (), LLVMInt64Type () };
8048 LLVMTypeRef ret_type = LLVMStructType (ovf_res_i64, 2, FALSE);
8050 AddFunc (module, name, ret_type, params, 2);
8051 break;
8053 case INTRINS_SIN:
8054 case INTRINS_COS:
8055 case INTRINS_SQRT:
8056 case INTRINS_FABS: {
8057 LLVMTypeRef params [] = { LLVMDoubleType () };
8059 AddFunc (module, name, LLVMDoubleType (), params, 1);
8060 break;
8062 case INTRINS_EXPECT_I8:
8063 AddFunc2 (module, name, LLVMInt8Type (), LLVMInt8Type (), LLVMInt8Type ());
8064 break;
8065 case INTRINS_EXPECT_I1:
8066 AddFunc2 (module, name, LLVMInt1Type (), LLVMInt1Type (), LLVMInt1Type ());
8067 break;
8068 #if defined(TARGET_AMD64) || defined(TARGET_X86)
8069 case INTRINS_SSE_PMOVMSKB:
8070 /* pmovmskb */
8071 ret_type = LLVMInt32Type ();
8072 arg_types [0] = type_to_simd_type (MONO_TYPE_I1);
8073 AddFunc (module, name, ret_type, arg_types, 1);
8074 break;
8075 case INTRINS_SSE_PSRLI_W:
8076 case INTRINS_SSE_PSRAI_W:
8077 case INTRINS_SSE_PSLLI_W:
8078 /* shifts */
8079 ret_type = type_to_simd_type (MONO_TYPE_I2);
8080 arg_types [0] = ret_type;
8081 arg_types [1] = LLVMInt32Type ();
8082 AddFunc (module, name, ret_type, arg_types, 2);
8083 break;
8084 case INTRINS_SSE_PSRLI_D:
8085 case INTRINS_SSE_PSRAI_D:
8086 case INTRINS_SSE_PSLLI_D:
8087 ret_type = type_to_simd_type (MONO_TYPE_I4);
8088 arg_types [0] = ret_type;
8089 arg_types [1] = LLVMInt32Type ();
8090 AddFunc (module, name, ret_type, arg_types, 2);
8091 break;
8092 case INTRINS_SSE_PSRLI_Q:
8093 case INTRINS_SSE_PSLLI_Q:
8094 ret_type = type_to_simd_type (MONO_TYPE_I8);
8095 arg_types [0] = ret_type;
8096 arg_types [1] = LLVMInt32Type ();
8097 AddFunc (module, name, ret_type, arg_types, 2);
8098 break;
8099 case INTRINS_SSE_SQRT_PD:
8100 /* Unary ops */
8101 ret_type = type_to_simd_type (MONO_TYPE_R8);
8102 arg_types [0] = ret_type;
8103 AddFunc (module, name, ret_type, arg_types, 1);
8104 break;
8105 case INTRINS_SSE_SQRT_PS:
8106 ret_type = type_to_simd_type (MONO_TYPE_R4);
8107 arg_types [0] = ret_type;
8108 AddFunc (module, name, ret_type, arg_types, 1);
8109 break;
8110 case INTRINS_SSE_RSQRT_PS:
8111 ret_type = type_to_simd_type (MONO_TYPE_R4);
8112 arg_types [0] = ret_type;
8113 AddFunc (module, name, ret_type, arg_types, 1);
8114 break;
8115 case INTRINS_SSE_RCP_PS:
8116 ret_type = type_to_simd_type (MONO_TYPE_R4);
8117 arg_types [0] = ret_type;
8118 AddFunc (module, name, ret_type, arg_types, 1);
8119 break;
8120 case INTRINS_SSE_CVTTPD2DQ:
8121 ret_type = type_to_simd_type (MONO_TYPE_I4);
8122 arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
8123 AddFunc (module, name, ret_type, arg_types, 1);
8124 break;
8125 case INTRINS_SSE_CVTTPS2DQ:
8126 ret_type = type_to_simd_type (MONO_TYPE_I4);
8127 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8128 AddFunc (module, name, ret_type, arg_types, 1);
8129 break;
8130 case INTRINS_SSE_CVTDQ2PD:
8131 /* Conversion ops */
8132 ret_type = type_to_simd_type (MONO_TYPE_R8);
8133 arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
8134 AddFunc (module, name, ret_type, arg_types, 1);
8135 break;
8136 case INTRINS_SSE_CVTDQ2PS:
8137 ret_type = type_to_simd_type (MONO_TYPE_R4);
8138 arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
8139 AddFunc (module, name, ret_type, arg_types, 1);
8140 break;
8141 case INTRINS_SSE_CVTPD2DQ:
8142 ret_type = type_to_simd_type (MONO_TYPE_I4);
8143 arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
8144 AddFunc (module, name, ret_type, arg_types, 1);
8145 break;
8146 case INTRINS_SSE_CVTPS2DQ:
8147 ret_type = type_to_simd_type (MONO_TYPE_I4);
8148 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8149 AddFunc (module, name, ret_type, arg_types, 1);
8150 break;
8151 case INTRINS_SSE_CVTPD2PS:
8152 ret_type = type_to_simd_type (MONO_TYPE_R4);
8153 arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
8154 AddFunc (module, name, ret_type, arg_types, 1);
8155 break;
8156 case INTRINS_SSE_CVTPS2PD:
8157 ret_type = type_to_simd_type (MONO_TYPE_R8);
8158 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8159 AddFunc (module, name, ret_type, arg_types, 1);
8160 break;
8161 case INTRINS_SSE_CMPPD:
8162 /* cmp pd/ps */
8163 ret_type = type_to_simd_type (MONO_TYPE_R8);
8164 arg_types [0] = ret_type;
8165 arg_types [1] = ret_type;
8166 arg_types [2] = LLVMInt8Type ();
8167 AddFunc (module, name, ret_type, arg_types, 3);
8168 break;
8169 case INTRINS_SSE_CMPPS:
8170 ret_type = type_to_simd_type (MONO_TYPE_R4);
8171 arg_types [0] = ret_type;
8172 arg_types [1] = ret_type;
8173 arg_types [2] = LLVMInt8Type ();
8174 AddFunc (module, name, ret_type, arg_types, 3);
8175 break;
8176 case INTRINS_SSE_PACKSSWB:
8177 case INTRINS_SSE_PACKUSWB:
8178 case INTRINS_SSE_PACKSSDW:
8179 /* pack */
8180 ret_type = type_to_simd_type (MONO_TYPE_I1);
8181 arg_types [0] = type_to_simd_type (MONO_TYPE_I2);
8182 arg_types [1] = type_to_simd_type (MONO_TYPE_I2);
8183 AddFunc (module, name, ret_type, arg_types, 2);
8184 break;
8185 case INTRINS_SSE_PACKUSDW:
8186 ret_type = type_to_simd_type (MONO_TYPE_I2);
8187 arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
8188 arg_types [1] = type_to_simd_type (MONO_TYPE_I4);
8189 AddFunc (module, name, ret_type, arg_types, 2);
8190 break;
8191 /* SSE Binary ops */
8192 case INTRINS_SSE_PADDSW:
8193 case INTRINS_SSE_PSUBSW:
8194 case INTRINS_SSE_PADDUSW:
8195 case INTRINS_SSE_PSUBUSW:
8196 case INTRINS_SSE_PAVGW:
8197 case INTRINS_SSE_PMULHW:
8198 case INTRINS_SSE_PMULHU:
8199 add_sse_binary (module, name, MONO_TYPE_I2);
8200 break;
8201 case INTRINS_SSE_MINPS:
8202 case INTRINS_SSE_MAXPS:
8203 case INTRINS_SSE_HADDPS:
8204 case INTRINS_SSE_HSUBPS:
8205 case INTRINS_SSE_ADDSUBPS:
8206 add_sse_binary (module, name, MONO_TYPE_R4);
8207 break;
8208 case INTRINS_SSE_MINPD:
8209 case INTRINS_SSE_MAXPD:
8210 case INTRINS_SSE_HADDPD:
8211 case INTRINS_SSE_HSUBPD:
8212 case INTRINS_SSE_ADDSUBPD:
8213 add_sse_binary (module, name, MONO_TYPE_R8);
8214 break;
8215 case INTRINS_SE_PADDSB:
8216 case INTRINS_SSE_PSUBSB:
8217 case INTRINS_SSE_PADDUSB:
8218 case INTRINS_SSE_PSUBUSB:
8219 case INTRINS_SSE_PAVGB:
8220 add_sse_binary (module, name, MONO_TYPE_I1);
8221 break;
8222 case INTRINS_SSE_PAUSE:
8223 AddFunc (module, "llvm.x86.sse2.pause", LLVMVoidType (), NULL, 0);
8224 break;
8225 case INTRINS_SSE_DPPS:
8226 ret_type = type_to_simd_type (MONO_TYPE_R4);
8227 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8228 arg_types [1] = type_to_simd_type (MONO_TYPE_R4);
8229 arg_types [2] = LLVMInt32Type ();
8230 AddFunc (module, name, ret_type, arg_types, 3);
8231 break;
8232 #endif
8233 default:
8234 g_assert_not_reached ();
8235 break;
8239 static LLVMValueRef
8240 get_intrinsic (EmitContext *ctx, const char *name)
8242 #if LLVM_API_VERSION > 100
8243 LLVMValueRef res;
8246 * Every method is emitted into its own module so
8247 * we can add intrinsics on demand.
8249 res = LLVMGetNamedFunction (ctx->lmodule, name);
8250 if (!res) {
8251 int id = -1;
8253 /* No locking needed */
8254 id = GPOINTER_TO_INT (g_hash_table_lookup (intrins_name_to_id, name));
8255 id --;
8256 if (id == -1)
8257 printf ("%s\n", name);
8258 g_assert (id != -1);
8259 add_intrinsic (ctx->lmodule, id);
8260 res = LLVMGetNamedFunction (ctx->lmodule, name);
8261 g_assert (res);
8264 return res;
8265 #else
8266 LLVMValueRef res;
8268 res = LLVMGetNamedFunction (ctx->lmodule, name);
8269 g_assert (res);
8270 return res;
8271 #endif
8274 static void
8275 add_intrinsics (LLVMModuleRef module)
8277 int i;
8279 /* Emit declarations of instrinsics */
8281 * It would be nicer to emit only the intrinsics actually used, but LLVM's Module
8282 * type doesn't seem to do any locking.
8284 for (i = 0; i < INTRINS_NUM; ++i)
8285 add_intrinsic (module, i);
8287 /* EH intrinsics */
8289 AddFunc (module, "mono_personality", LLVMVoidType (), NULL, 0);
8291 AddFunc (module, "llvm_resume_unwind_trampoline", LLVMVoidType (), NULL, 0);
8294 /* Load/Store intrinsics */
8296 LLVMTypeRef arg_types [5];
8297 int i;
8298 char name [128];
8300 for (i = 1; i <= 8; i *= 2) {
8301 arg_types [0] = LLVMPointerType (LLVMIntType (i * 8), 0);
8302 arg_types [1] = LLVMInt32Type ();
8303 arg_types [2] = LLVMInt1Type ();
8304 arg_types [3] = LLVMInt32Type ();
8305 sprintf (name, "llvm.mono.load.i%d.p0i%d", i * 8, i * 8);
8306 AddFunc (module, name, LLVMIntType (i * 8), arg_types, 4);
8308 arg_types [0] = LLVMIntType (i * 8);
8309 arg_types [1] = LLVMPointerType (LLVMIntType (i * 8), 0);
8310 arg_types [2] = LLVMInt32Type ();
8311 arg_types [3] = LLVMInt1Type ();
8312 arg_types [4] = LLVMInt32Type ();
8313 sprintf (name, "llvm.mono.store.i%d.p0i%d", i * 8, i * 8);
8314 AddFunc (module, name, LLVMVoidType (), arg_types, 5);
8319 static void
8320 add_types (MonoLLVMModule *module)
8322 module->ptr_type = LLVMPointerType (sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type (), 0);
8325 void
8326 mono_llvm_init (void)
8328 GHashTable *h;
8329 int i;
8331 mono_native_tls_alloc (&current_cfg_tls_id, NULL);
8333 h = g_hash_table_new (NULL, NULL);
8334 for (i = 0; i < INTRINS_NUM; ++i)
8335 g_hash_table_insert (h, GINT_TO_POINTER (intrinsics [i].id), (gpointer)intrinsics [i].name);
8336 intrins_id_to_name = h;
8338 h = g_hash_table_new (g_str_hash, g_str_equal);
8339 for (i = 0; i < INTRINS_NUM; ++i)
8340 g_hash_table_insert (h, (gpointer)intrinsics [i].name, GINT_TO_POINTER (intrinsics [i].id + 1));
8341 intrins_name_to_id = h;
8344 static void
8345 init_jit_module (MonoDomain *domain)
8347 MonoJitDomainInfo *dinfo;
8348 MonoLLVMModule *module;
8349 char *name;
8351 dinfo = domain_jit_info (domain);
8352 if (dinfo->llvm_module)
8353 return;
8355 mono_loader_lock ();
8357 if (dinfo->llvm_module) {
8358 mono_loader_unlock ();
8359 return;
8362 module = g_new0 (MonoLLVMModule, 1);
8364 name = g_strdup_printf ("mono-%s", domain->friendly_name);
8365 module->lmodule = LLVMModuleCreateWithName (name);
8366 module->context = LLVMGetGlobalContext ();
8368 module->mono_ee = (MonoEERef*)mono_llvm_create_ee (LLVMCreateModuleProviderForExistingModule (module->lmodule), alloc_cb, emitted_cb, exception_cb, dlsym_cb, &module->ee);
8370 add_intrinsics (module->lmodule);
8371 add_types (module);
8373 module->llvm_types = g_hash_table_new (NULL, NULL);
8375 #if LLVM_API_VERSION < 100
8376 MonoJitICallInfo *info;
8378 info = mono_find_jit_icall_by_name ("llvm_resume_unwind_trampoline");
8379 g_assert (info);
8380 LLVMAddGlobalMapping (module->ee, LLVMGetNamedFunction (module->lmodule, "llvm_resume_unwind_trampoline"), (void*)info->func);
8381 #endif
8383 mono_memory_barrier ();
8385 dinfo->llvm_module = module;
8387 mono_loader_unlock ();
8390 void
8391 mono_llvm_cleanup (void)
8393 MonoLLVMModule *module = &aot_module;
8395 if (module->lmodule)
8396 LLVMDisposeModule (module->lmodule);
8398 if (module->context)
8399 LLVMContextDispose (module->context);
8402 void
8403 mono_llvm_free_domain_info (MonoDomain *domain)
8405 MonoJitDomainInfo *info = domain_jit_info (domain);
8406 MonoLLVMModule *module = (MonoLLVMModule*)info->llvm_module;
8407 int i;
8409 if (!module)
8410 return;
8412 if (module->llvm_types)
8413 g_hash_table_destroy (module->llvm_types);
8415 mono_llvm_dispose_ee (module->mono_ee);
8417 if (module->bb_names) {
8418 for (i = 0; i < module->bb_names_len; ++i)
8419 g_free (module->bb_names [i]);
8420 g_free (module->bb_names);
8422 //LLVMDisposeModule (module->module);
8424 g_free (module);
8426 info->llvm_module = NULL;
8429 void
8430 mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only)
8432 MonoLLVMModule *module = &aot_module;
8434 /* Delete previous module */
8435 if (module->plt_entries)
8436 g_hash_table_destroy (module->plt_entries);
8437 if (module->lmodule)
8438 LLVMDisposeModule (module->lmodule);
8440 memset (module, 0, sizeof (aot_module));
8442 module->lmodule = LLVMModuleCreateWithName ("aot");
8443 module->assembly = assembly;
8444 module->global_prefix = g_strdup (global_prefix);
8445 module->got_symbol = g_strdup_printf ("%s_llvm_got", global_prefix);
8446 module->eh_frame_symbol = g_strdup_printf ("%s_eh_frame", global_prefix);
8447 module->get_method_symbol = g_strdup_printf ("%s_get_method", global_prefix);
8448 module->get_unbox_tramp_symbol = g_strdup_printf ("%s_get_unbox_tramp", global_prefix);
8449 module->external_symbols = TRUE;
8450 module->emit_dwarf = emit_dwarf;
8451 module->static_link = static_link;
8452 module->llvm_only = llvm_only;
8453 /* The first few entries are reserved */
8454 module->max_got_offset = 16;
8455 module->context = LLVMGetGlobalContext ();
8457 if (llvm_only)
8458 /* clang ignores our debug info because it has an invalid version */
8459 module->emit_dwarf = FALSE;
8461 add_intrinsics (module->lmodule);
8462 add_types (module);
8464 #if LLVM_API_VERSION > 100
8465 if (module->emit_dwarf) {
8466 char *dir, *build_info, *s, *cu_name;
8468 module->di_builder = mono_llvm_create_di_builder (module->lmodule);
8470 // FIXME:
8471 dir = g_strdup (".");
8472 build_info = mono_get_runtime_build_info ();
8473 s = g_strdup_printf ("Mono AOT Compiler %s (LLVM)", build_info);
8474 cu_name = g_path_get_basename (assembly->image->name);
8475 module->cu = mono_llvm_di_create_compile_unit (module->di_builder, cu_name, dir, s);
8476 g_free (dir);
8477 g_free (build_info);
8478 g_free (s);
8480 #endif
8482 /* Add GOT */
8484 * We couldn't compute the type of the LLVM global representing the got because
8485 * its size is only known after all the methods have been emitted. So create
8486 * a dummy variable, and replace all uses it with the real got variable when
8487 * its size is known in mono_llvm_emit_aot_module ().
8490 LLVMTypeRef got_type = LLVMArrayType (module->ptr_type, 0);
8492 module->got_var = LLVMAddGlobal (module->lmodule, got_type, "mono_dummy_got");
8493 LLVMSetInitializer (module->got_var, LLVMConstNull (got_type));
8496 /* Add initialization array */
8497 if (llvm_only) {
8498 LLVMTypeRef inited_type = LLVMArrayType (LLVMInt8Type (), 0);
8500 module->inited_var = LLVMAddGlobal (aot_module.lmodule, inited_type, "mono_inited_tmp");
8501 LLVMSetInitializer (module->inited_var, LLVMConstNull (inited_type));
8504 if (llvm_only)
8505 emit_init_icall_wrappers (module);
8507 emit_llvm_code_start (module);
8509 /* Add a dummy personality function */
8510 if (!use_debug_personality) {
8511 LLVMValueRef personality = LLVMAddFunction (module->lmodule, default_personality_name, LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE));
8512 LLVMSetLinkage (personality, LLVMExternalLinkage);
8513 mark_as_used (module, personality);
8516 /* Add a reference to the c++ exception we throw/catch */
8518 LLVMTypeRef exc = LLVMPointerType (LLVMInt8Type (), 0);
8519 module->sentinel_exception = LLVMAddGlobal (module->lmodule, exc, "_ZTIPi");
8520 LLVMSetLinkage (module->sentinel_exception, LLVMExternalLinkage);
8521 mono_llvm_set_is_constant (module->sentinel_exception);
8524 module->llvm_types = g_hash_table_new (NULL, NULL);
8525 module->plt_entries = g_hash_table_new (g_str_hash, g_str_equal);
8526 module->plt_entries_ji = g_hash_table_new (NULL, NULL);
8527 module->direct_callables = g_hash_table_new (g_str_hash, g_str_equal);
8528 module->method_to_lmethod = g_hash_table_new (NULL, NULL);
8529 module->idx_to_lmethod = g_hash_table_new (NULL, NULL);
8530 module->idx_to_unbox_tramp = g_hash_table_new (NULL, NULL);
8531 module->method_to_callers = g_hash_table_new (NULL, NULL);
8534 static LLVMValueRef
8535 llvm_array_from_uints (LLVMTypeRef el_type, guint32 *values, int nvalues)
8537 int i;
8538 LLVMValueRef res, *vals;
8540 vals = g_new0 (LLVMValueRef, nvalues);
8541 for (i = 0; i < nvalues; ++i)
8542 vals [i] = LLVMConstInt (LLVMInt32Type (), values [i], FALSE);
8543 res = LLVMConstArray (LLVMInt32Type (), vals, nvalues);
8544 g_free (vals);
8545 return res;
8548 static LLVMValueRef
8549 llvm_array_from_bytes (guint8 *values, int nvalues)
8551 int i;
8552 LLVMValueRef res, *vals;
8554 vals = g_new0 (LLVMValueRef, nvalues);
8555 for (i = 0; i < nvalues; ++i)
8556 vals [i] = LLVMConstInt (LLVMInt8Type (), values [i], FALSE);
8557 res = LLVMConstArray (LLVMInt8Type (), vals, nvalues);
8558 g_free (vals);
8559 return res;
8562 * mono_llvm_emit_aot_file_info:
8564 * Emit the MonoAotFileInfo structure.
8565 * Same as emit_aot_file_info () in aot-compiler.c.
8567 void
8568 mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code)
8570 MonoLLVMModule *module = &aot_module;
8572 /* Save these for later */
8573 memcpy (&module->aot_info, info, sizeof (MonoAotFileInfo));
8574 module->has_jitted_code = has_jitted_code;
8578 * mono_llvm_emit_aot_data:
8580 * Emit the binary data DATA pointed to by symbol SYMBOL.
8582 void
8583 mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
8585 MonoLLVMModule *module = &aot_module;
8586 LLVMTypeRef type;
8587 LLVMValueRef d;
8589 type = LLVMArrayType (LLVMInt8Type (), data_len);
8590 d = LLVMAddGlobal (module->lmodule, type, symbol);
8591 LLVMSetVisibility (d, LLVMHiddenVisibility);
8592 LLVMSetLinkage (d, LLVMInternalLinkage);
8593 LLVMSetInitializer (d, mono_llvm_create_constant_data_array (data, data_len));
8594 mono_llvm_set_is_constant (d);
8597 /* Add a reference to a global defined in JITted code */
8598 static LLVMValueRef
8599 AddJitGlobal (MonoLLVMModule *module, LLVMTypeRef type, const char *name)
8601 char *s;
8602 LLVMValueRef v;
8604 s = g_strdup_printf ("%s%s", module->global_prefix, name);
8605 v = LLVMAddGlobal (module->lmodule, LLVMInt8Type (), s);
8606 g_free (s);
8607 return v;
8610 static void
8611 emit_aot_file_info (MonoLLVMModule *module)
8613 LLVMTypeRef file_info_type;
8614 LLVMTypeRef *eltypes, eltype;
8615 LLVMValueRef info_var;
8616 LLVMValueRef *fields;
8617 int i, nfields, tindex;
8618 MonoAotFileInfo *info;
8619 LLVMModuleRef lmodule = module->lmodule;
8621 info = &module->aot_info;
8623 /* Create an LLVM type to represent MonoAotFileInfo */
8624 nfields = 2 + MONO_AOT_FILE_INFO_NUM_SYMBOLS + 16 + 5;
8625 eltypes = g_new (LLVMTypeRef, nfields);
8626 tindex = 0;
8627 eltypes [tindex ++] = LLVMInt32Type ();
8628 eltypes [tindex ++] = LLVMInt32Type ();
8629 /* Symbols */
8630 for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i)
8631 eltypes [tindex ++] = LLVMPointerType (LLVMInt8Type (), 0);
8632 /* Scalars */
8633 for (i = 0; i < 15; ++i)
8634 eltypes [tindex ++] = LLVMInt32Type ();
8635 /* Arrays */
8636 eltypes [tindex ++] = LLVMArrayType (LLVMInt32Type (), MONO_AOT_TABLE_NUM);
8637 for (i = 0; i < 4; ++i)
8638 eltypes [tindex ++] = LLVMArrayType (LLVMInt32Type (), MONO_AOT_TRAMP_NUM);
8639 eltypes [tindex ++] = LLVMArrayType (LLVMInt8Type (), 16);
8640 g_assert (tindex == nfields);
8641 file_info_type = LLVMStructCreateNamed (module->context, "MonoAotFileInfo");
8642 LLVMStructSetBody (file_info_type, eltypes, nfields, FALSE);
8644 info_var = LLVMAddGlobal (lmodule, file_info_type, "mono_aot_file_info");
8645 if (module->static_link) {
8646 LLVMSetVisibility (info_var, LLVMHiddenVisibility);
8647 LLVMSetLinkage (info_var, LLVMInternalLinkage);
8649 fields = g_new (LLVMValueRef, nfields);
8650 tindex = 0;
8651 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->version, FALSE);
8652 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->dummy, FALSE);
8654 /* Symbols */
8656 * We use LLVMGetNamedGlobal () for symbol which are defined in LLVM code, and LLVMAddGlobal ()
8657 * for symbols defined in the .s file emitted by the aot compiler.
8659 eltype = eltypes [tindex];
8660 if (module->llvm_only)
8661 fields [tindex ++] = LLVMConstNull (eltype);
8662 else
8663 fields [tindex ++] = AddJitGlobal (module, eltype, "jit_got");
8664 fields [tindex ++] = module->got_var;
8665 /* llc defines this directly */
8666 if (!module->llvm_only) {
8667 fields [tindex ++] = LLVMAddGlobal (lmodule, eltype, module->eh_frame_symbol);
8668 fields [tindex ++] = LLVMConstNull (eltype);
8669 fields [tindex ++] = LLVMConstNull (eltype);
8670 } else {
8671 fields [tindex ++] = LLVMConstNull (eltype);
8672 fields [tindex ++] = module->get_method;
8673 fields [tindex ++] = module->get_unbox_tramp;
8675 if (module->has_jitted_code) {
8676 fields [tindex ++] = AddJitGlobal (module, eltype, "jit_code_start");
8677 fields [tindex ++] = AddJitGlobal (module, eltype, "jit_code_end");
8678 } else {
8679 fields [tindex ++] = LLVMConstNull (eltype);
8680 fields [tindex ++] = LLVMConstNull (eltype);
8682 if (!module->llvm_only)
8683 fields [tindex ++] = AddJitGlobal (module, eltype, "method_addresses");
8684 else
8685 fields [tindex ++] = LLVMConstNull (eltype);
8686 if (info->flags & MONO_AOT_FILE_FLAG_SEPARATE_DATA) {
8687 for (i = 0; i < MONO_AOT_TABLE_NUM; ++i)
8688 fields [tindex ++] = LLVMConstNull (eltype);
8689 } else {
8690 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "blob");
8691 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "class_name_table");
8692 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "class_info_offsets");
8693 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "method_info_offsets");
8694 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "ex_info_offsets");
8695 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "extra_method_info_offsets");
8696 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "extra_method_table");
8697 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "got_info_offsets");
8698 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "llvm_got_info_offsets");
8699 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "image_table");
8701 /* Not needed (mem_end) */
8702 fields [tindex ++] = LLVMConstNull (eltype);
8703 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "assembly_guid");
8704 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "runtime_version");
8705 if (info->trampoline_size [0]) {
8706 fields [tindex ++] = AddJitGlobal (module, eltype, "specific_trampolines");
8707 fields [tindex ++] = AddJitGlobal (module, eltype, "static_rgctx_trampolines");
8708 fields [tindex ++] = AddJitGlobal (module, eltype, "imt_trampolines");
8709 fields [tindex ++] = AddJitGlobal (module, eltype, "gsharedvt_arg_trampolines");
8710 } else {
8711 fields [tindex ++] = LLVMConstNull (eltype);
8712 fields [tindex ++] = LLVMConstNull (eltype);
8713 fields [tindex ++] = LLVMConstNull (eltype);
8714 fields [tindex ++] = LLVMConstNull (eltype);
8716 if (module->static_link && !module->llvm_only)
8717 fields [tindex ++] = AddJitGlobal (module, eltype, "globals");
8718 else
8719 fields [tindex ++] = LLVMConstNull (eltype);
8720 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "assembly_name");
8721 if (!module->llvm_only) {
8722 fields [tindex ++] = AddJitGlobal (module, eltype, "plt");
8723 fields [tindex ++] = AddJitGlobal (module, eltype, "plt_end");
8724 fields [tindex ++] = AddJitGlobal (module, eltype, "unwind_info");
8725 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_trampolines");
8726 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_trampolines_end");
8727 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_trampoline_addresses");
8728 } else {
8729 fields [tindex ++] = LLVMConstNull (eltype);
8730 fields [tindex ++] = LLVMConstNull (eltype);
8731 fields [tindex ++] = LLVMConstNull (eltype);
8732 fields [tindex ++] = LLVMConstNull (eltype);
8733 fields [tindex ++] = LLVMConstNull (eltype);
8734 fields [tindex ++] = LLVMConstNull (eltype);
8737 for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i)
8738 fields [2 + i] = LLVMConstBitCast (fields [2 + i], eltype);
8740 /* Scalars */
8741 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->plt_got_offset_base, FALSE);
8742 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->got_size, FALSE);
8743 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->plt_size, FALSE);
8744 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nmethods, FALSE);
8745 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->flags, FALSE);
8746 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->opts, FALSE);
8747 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->simd_opts, FALSE);
8748 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->gc_name_index, FALSE);
8749 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->num_rgctx_fetch_trampolines, FALSE);
8750 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->double_align, FALSE);
8751 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->long_align, FALSE);
8752 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->generic_tramp_num, FALSE);
8753 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->tramp_page_size, FALSE);
8754 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nshared_got_entries, FALSE);
8755 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->datafile_size, FALSE);
8756 /* Arrays */
8757 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->table_offsets, MONO_AOT_TABLE_NUM);
8758 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->num_trampolines, MONO_AOT_TRAMP_NUM);
8759 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->trampoline_got_offset_base, MONO_AOT_TRAMP_NUM);
8760 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->trampoline_size, MONO_AOT_TRAMP_NUM);
8761 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->tramp_page_code_offsets, MONO_AOT_TRAMP_NUM);
8763 fields [tindex ++] = llvm_array_from_bytes (info->aotid, 16);
8764 g_assert (tindex == nfields);
8766 LLVMSetInitializer (info_var, LLVMConstNamedStruct (file_info_type, fields, nfields));
8768 if (module->static_link) {
8769 char *s, *p;
8770 LLVMValueRef var;
8772 s = g_strdup_printf ("mono_aot_module_%s_info", module->assembly->aname.name);
8773 /* Get rid of characters which cannot occur in symbols */
8774 p = s;
8775 for (p = s; *p; ++p) {
8776 if (!(isalnum (*p) || *p == '_'))
8777 *p = '_';
8779 var = LLVMAddGlobal (module->lmodule, LLVMPointerType (LLVMInt8Type (), 0), s);
8780 g_free (s);
8781 LLVMSetInitializer (var, LLVMConstBitCast (LLVMGetNamedGlobal (module->lmodule, "mono_aot_file_info"), LLVMPointerType (LLVMInt8Type (), 0)));
8782 LLVMSetLinkage (var, LLVMExternalLinkage);
8787 * Emit the aot module into the LLVM bitcode file FILENAME.
8789 void
8790 mono_llvm_emit_aot_module (const char *filename, const char *cu_name)
8792 LLVMTypeRef got_type, inited_type;
8793 LLVMValueRef real_got, real_inited;
8794 MonoLLVMModule *module = &aot_module;
8796 emit_llvm_code_end (module);
8799 * Create the real got variable and replace all uses of the dummy variable with
8800 * the real one.
8802 got_type = LLVMArrayType (module->ptr_type, module->max_got_offset + 1);
8803 real_got = LLVMAddGlobal (module->lmodule, got_type, module->got_symbol);
8804 LLVMSetInitializer (real_got, LLVMConstNull (got_type));
8805 if (module->external_symbols) {
8806 LLVMSetLinkage (real_got, LLVMExternalLinkage);
8807 LLVMSetVisibility (real_got, LLVMHiddenVisibility);
8808 } else {
8809 LLVMSetLinkage (real_got, LLVMInternalLinkage);
8811 mono_llvm_replace_uses_of (module->got_var, real_got);
8813 mark_as_used (&aot_module, real_got);
8815 /* Delete the dummy got so it doesn't become a global */
8816 LLVMDeleteGlobal (module->got_var);
8817 module->got_var = real_got;
8820 * Same for the init_var
8822 if (module->llvm_only) {
8823 inited_type = LLVMArrayType (LLVMInt8Type (), module->max_inited_idx + 1);
8824 real_inited = LLVMAddGlobal (module->lmodule, inited_type, "mono_inited");
8825 LLVMSetInitializer (real_inited, LLVMConstNull (inited_type));
8826 LLVMSetLinkage (real_inited, LLVMInternalLinkage);
8827 mono_llvm_replace_uses_of (module->inited_var, real_inited);
8828 LLVMDeleteGlobal (module->inited_var);
8831 if (module->llvm_only) {
8832 emit_get_method (&aot_module);
8833 emit_get_unbox_tramp (&aot_module);
8836 emit_llvm_used (&aot_module);
8837 emit_dbg_info (&aot_module, filename, cu_name);
8838 emit_aot_file_info (&aot_module);
8841 * Replace GOT entries for directly callable methods with the methods themselves.
8842 * It would be easier to implement this by predefining all methods before compiling
8843 * their bodies, but that couldn't handle the case when a method fails to compile
8844 * with llvm.
8846 if (module->llvm_only) {
8847 GHashTableIter iter;
8848 MonoMethod *method;
8849 GSList *callers, *l;
8851 g_hash_table_iter_init (&iter, module->method_to_callers);
8852 while (g_hash_table_iter_next (&iter, (void**)&method, (void**)&callers)) {
8853 LLVMValueRef lmethod;
8855 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
8856 continue;
8858 lmethod = (LLVMValueRef)g_hash_table_lookup (module->method_to_lmethod, method);
8859 if (lmethod) {
8860 for (l = callers; l; l = l->next) {
8861 LLVMValueRef caller = (LLVMValueRef)l->data;
8863 mono_llvm_replace_uses_of (caller, lmethod);
8869 /* Replace PLT entries for directly callable methods with the methods themselves */
8871 GHashTableIter iter;
8872 MonoJumpInfo *ji;
8873 LLVMValueRef callee;
8875 g_hash_table_iter_init (&iter, module->plt_entries_ji);
8876 while (g_hash_table_iter_next (&iter, (void**)&ji, (void**)&callee)) {
8877 if (mono_aot_is_direct_callable (ji)) {
8878 LLVMValueRef lmethod;
8880 lmethod = (LLVMValueRef)g_hash_table_lookup (module->method_to_lmethod, ji->data.method);
8881 /* The types might not match because the caller might pass an rgctx */
8882 if (lmethod && LLVMTypeOf (callee) == LLVMTypeOf (lmethod)) {
8883 mono_llvm_replace_uses_of (callee, lmethod);
8884 mono_aot_mark_unused_llvm_plt_entry (ji);
8890 #if 1
8892 char *verifier_err;
8894 if (LLVMVerifyModule (module->lmodule, LLVMReturnStatusAction, &verifier_err)) {
8895 printf ("%s\n", verifier_err);
8896 g_assert_not_reached ();
8899 #endif
8901 LLVMWriteBitcodeToFile (module->lmodule, filename);
8905 static LLVMValueRef
8906 md_string (const char *s)
8908 return LLVMMDString (s, strlen (s));
8911 /* Debugging support */
8913 static void
8914 emit_dbg_info (MonoLLVMModule *module, const char *filename, const char *cu_name)
8916 LLVMModuleRef lmodule = module->lmodule;
8917 LLVMValueRef args [16], ver;
8920 * This can only be enabled when LLVM code is emitted into a separate object
8921 * file, since the AOT compiler also emits dwarf info,
8922 * and the abbrev indexes will not be correct since llvm has added its own
8923 * abbrevs.
8925 if (!module->emit_dwarf)
8926 return;
8928 #if LLVM_API_VERSION > 100
8929 mono_llvm_di_builder_finalize (module->di_builder);
8930 #else
8931 LLVMValueRef cu_args [16], cu;
8932 int n_cuargs;
8933 char *build_info, *s, *dir;
8936 * Emit dwarf info in the form of LLVM metadata. There is some
8937 * out-of-date documentation at:
8938 * http://llvm.org/docs/SourceLevelDebugging.html
8939 * but most of this was gathered from the llvm and
8940 * clang sources.
8943 n_cuargs = 0;
8944 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), DW_TAG_compile_unit, FALSE);
8945 /* CU name/compilation dir */
8946 dir = g_path_get_dirname (filename);
8947 args [0] = LLVMMDString (cu_name, strlen (cu_name));
8948 args [1] = LLVMMDString (dir, strlen (dir));
8949 cu_args [n_cuargs ++] = LLVMMDNode (args, 2);
8950 g_free (dir);
8951 /* Language */
8952 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), DW_LANG_C99, FALSE);
8953 /* Producer */
8954 build_info = mono_get_runtime_build_info ();
8955 s = g_strdup_printf ("Mono AOT Compiler %s (LLVM)", build_info);
8956 cu_args [n_cuargs ++] = LLVMMDString (s, strlen (s));
8957 g_free (build_info);
8958 /* Optimized */
8959 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
8960 /* Flags */
8961 cu_args [n_cuargs ++] = LLVMMDString ("", strlen (""));
8962 /* Runtime version */
8963 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
8964 /* Enums */
8965 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
8966 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
8967 /* Subprograms */
8968 if (module->subprogram_mds) {
8969 LLVMValueRef *mds;
8970 int i;
8972 mds = g_new0 (LLVMValueRef, module->subprogram_mds->len);
8973 for (i = 0; i < module->subprogram_mds->len; ++i)
8974 mds [i] = (LLVMValueRef)g_ptr_array_index (module->subprogram_mds, i);
8975 cu_args [n_cuargs ++] = LLVMMDNode (mds, module->subprogram_mds->len);
8976 } else {
8977 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
8979 /* GVs */
8980 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
8981 /* Imported modules */
8982 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
8983 /* SplitName */
8984 cu_args [n_cuargs ++] = LLVMMDString ("", strlen (""));
8985 /* DebugEmissionKind = FullDebug */
8986 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
8987 cu = LLVMMDNode (cu_args, n_cuargs);
8988 LLVMAddNamedMetadataOperand (lmodule, "llvm.dbg.cu", cu);
8989 #endif
8991 #if LLVM_API_VERSION > 100
8992 args [0] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
8993 args [1] = LLVMMDString ("Dwarf Version", strlen ("Dwarf Version"));
8994 args [2] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
8995 ver = LLVMMDNode (args, 3);
8996 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
8998 args [0] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
8999 args [1] = LLVMMDString ("Debug Info Version", strlen ("Debug Info Version"));
9000 args [2] = LLVMConstInt (LLVMInt64Type (), 3, FALSE);
9001 ver = LLVMMDNode (args, 3);
9002 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
9003 #else
9004 args [0] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9005 args [1] = LLVMMDString ("Dwarf Version", strlen ("Dwarf Version"));
9006 args [2] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
9007 ver = LLVMMDNode (args, 3);
9008 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
9010 args [0] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9011 args [1] = LLVMMDString ("Debug Info Version", strlen ("Debug Info Version"));
9012 args [2] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9013 ver = LLVMMDNode (args, 3);
9014 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
9015 #endif
9018 static LLVMValueRef
9019 emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, const char *name)
9021 MonoLLVMModule *module = ctx->module;
9022 MonoDebugMethodInfo *minfo = ctx->minfo;
9023 char *source_file, *dir, *filename;
9024 LLVMValueRef md, args [16], ctx_args [16], md_args [64], type_args [16], ctx_md, type_md;
9025 MonoSymSeqPoint *sym_seq_points;
9026 int n_seq_points;
9028 if (!minfo)
9029 return NULL;
9031 mono_debug_symfile_get_seq_points (minfo, &source_file, NULL, NULL, &sym_seq_points, &n_seq_points);
9032 if (!source_file)
9033 source_file = g_strdup ("<unknown>");
9034 dir = g_path_get_dirname (source_file);
9035 filename = g_path_get_basename (source_file);
9037 #if LLVM_API_VERSION > 100
9038 return mono_llvm_di_create_function (module->di_builder, module->cu, method, cfg->method->name, name, dir, filename, n_seq_points ? sym_seq_points [0].line : 1);
9039 #endif
9041 ctx_args [0] = LLVMConstInt (LLVMInt32Type (), 0x29, FALSE);
9042 args [0] = md_string (filename);
9043 args [1] = md_string (dir);
9044 ctx_args [1] = LLVMMDNode (args, 2);
9045 ctx_md = LLVMMDNode (ctx_args, 2);
9047 type_args [0] = LLVMConstInt (LLVMInt32Type (), DW_TAG_subroutine_type, FALSE);
9048 type_args [1] = NULL;
9049 type_args [2] = NULL;
9050 type_args [3] = LLVMMDString ("", 0);
9051 type_args [4] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9052 type_args [5] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
9053 type_args [6] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
9054 type_args [7] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
9055 type_args [8] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9056 type_args [9] = NULL;
9057 type_args [10] = NULL;
9058 type_args [11] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9059 type_args [12] = NULL;
9060 type_args [13] = NULL;
9061 type_args [14] = NULL;
9062 type_md = LLVMMDNode (type_args, 14);
9064 /* http://llvm.org/docs/SourceLevelDebugging.html#subprogram-descriptors */
9065 md_args [0] = LLVMConstInt (LLVMInt32Type (), DW_TAG_subprogram, FALSE);
9066 /* Source directory + file pair */
9067 args [0] = md_string (filename);
9068 args [1] = md_string (dir);
9069 md_args [1] = LLVMMDNode (args ,2);
9070 md_args [2] = ctx_md;
9071 md_args [3] = md_string (cfg->method->name);
9072 md_args [4] = md_string (name);
9073 md_args [5] = md_string (name);
9074 /* Line number */
9075 if (n_seq_points)
9076 md_args [6] = LLVMConstInt (LLVMInt32Type (), sym_seq_points [0].line, FALSE);
9077 else
9078 md_args [6] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9079 /* Type */
9080 md_args [7] = type_md;
9081 /* static */
9082 md_args [8] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
9083 /* not extern */
9084 md_args [9] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
9085 /* Virtuality */
9086 md_args [10] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9087 /* Index into a virtual function */
9088 md_args [11] = NULL;
9089 md_args [12] = NULL;
9090 /* Flags */
9091 md_args [13] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
9092 /* isOptimized */
9093 md_args [14] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
9094 /* Pointer to LLVM function */
9095 md_args [15] = method;
9096 /* Function template parameter */
9097 md_args [16] = NULL;
9098 /* Function declaration descriptor */
9099 md_args [17] = NULL;
9100 /* List of function variables */
9101 md_args [18] = LLVMMDNode (args, 0);
9102 /* Line number */
9103 md_args [19] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9104 md = LLVMMDNode (md_args, 20);
9106 if (!module->subprogram_mds)
9107 module->subprogram_mds = g_ptr_array_new ();
9108 g_ptr_array_add (module->subprogram_mds, md);
9110 g_free (dir);
9111 g_free (filename);
9112 g_free (source_file);
9113 g_free (sym_seq_points);
9115 return md;
9118 static void
9119 emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil_code)
9121 MonoCompile *cfg = ctx->cfg;
9123 if (ctx->minfo && cil_code && cil_code >= cfg->header->code && cil_code < cfg->header->code + cfg->header->code_size) {
9124 MonoDebugSourceLocation *loc;
9125 LLVMValueRef loc_md;
9127 loc = mono_debug_symfile_lookup_location (ctx->minfo, cil_code - cfg->header->code);
9129 if (loc) {
9130 #if LLVM_API_VERSION > 100
9131 loc_md = mono_llvm_di_create_location (ctx->module->di_builder, ctx->dbg_md, loc->row, loc->column);
9132 mono_llvm_di_set_location (builder, loc_md);
9133 #else
9134 LLVMValueRef md_args [16];
9135 int nmd_args;
9137 nmd_args = 0;
9138 md_args [nmd_args ++] = LLVMConstInt (LLVMInt32Type (), loc->row, FALSE);
9139 md_args [nmd_args ++] = LLVMConstInt (LLVMInt32Type (), loc->column, FALSE);
9140 md_args [nmd_args ++] = ctx->dbg_md;
9141 md_args [nmd_args ++] = NULL;
9142 loc_md = LLVMMDNode (md_args, nmd_args);
9143 LLVMSetCurrentDebugLocation (builder, loc_md);
9144 #endif
9145 mono_debug_symfile_free_location (loc);
9150 void
9151 default_mono_llvm_unhandled_exception (void)
9153 MonoJitTlsData *jit_tls = mono_get_jit_tls ();
9154 MonoObject *target = mono_gchandle_get_target (jit_tls->thrown_exc);
9156 mono_unhandled_exception (target);
9157 mono_invoke_unhandled_exception_hook (target);
9158 g_assert_not_reached ();
9162 DESIGN:
9163 - Emit LLVM IR from the mono IR using the LLVM C API.
9164 - The original arch specific code remains, so we can fall back to it if we run
9165 into something we can't handle.
9169 A partial list of issues:
9170 - Handling of opcodes which can throw exceptions.
9172 In the mono JIT, these are implemented using code like this:
9173 method:
9174 <compare>
9175 throw_pos:
9176 b<cond> ex_label
9177 <rest of code>
9178 ex_label:
9179 push throw_pos - method
9180 call <exception trampoline>
9182 The problematic part is push throw_pos - method, which cannot be represented
9183 in the LLVM IR, since it does not support label values.
9184 -> this can be implemented in AOT mode using inline asm + labels, but cannot
9185 be implemented in JIT mode ?
9186 -> a possible but slower implementation would use the normal exception
9187 throwing code but it would need to control the placement of the throw code
9188 (it needs to be exactly after the compare+branch).
9189 -> perhaps add a PC offset intrinsics ?
9191 - efficient implementation of .ovf opcodes.
9193 These are currently implemented as:
9194 <ins which sets the condition codes>
9195 b<cond> ex_label
9197 Some overflow opcodes are now supported by LLVM SVN.
9199 - exception handling, unwinding.
9200 - SSA is disabled for methods with exception handlers
9201 - How to obtain unwind info for LLVM compiled methods ?
9202 -> this is now solved by converting the unwind info generated by LLVM
9203 into our format.
9204 - LLVM uses the c++ exception handling framework, while we use our home grown
9205 code, and couldn't use the c++ one:
9206 - its not supported under VC++, other exotic platforms.
9207 - it might be impossible to support filter clauses with it.
9209 - trampolines.
9211 The trampolines need a predictable call sequence, since they need to disasm
9212 the calling code to obtain register numbers / offsets.
9214 LLVM currently generates this code in non-JIT mode:
9215 mov -0x98(%rax),%eax
9216 callq *%rax
9217 Here, the vtable pointer is lost.
9218 -> solution: use one vtable trampoline per class.
9220 - passing/receiving the IMT pointer/RGCTX.
9221 -> solution: pass them as normal arguments ?
9223 - argument passing.
9225 LLVM does not allow the specification of argument registers etc. This means
9226 that all calls are made according to the platform ABI.
9228 - passing/receiving vtypes.
9230 Vtypes passed/received in registers are handled by the front end by using
9231 a signature with scalar arguments, and loading the parts of the vtype into those
9232 arguments.
9234 Vtypes passed on the stack are handled using the 'byval' attribute.
9236 - ldaddr.
9238 Supported though alloca, we need to emit the load/store code.
9240 - types.
9242 The mono JIT uses pointer sized iregs/double fregs, while LLVM uses precisely
9243 typed registers, so we have to keep track of the precise LLVM type of each vreg.
9244 This is made easier because the IR is already in SSA form.
9245 An additional problem is that our IR is not consistent with types, i.e. i32/ia64
9246 types are frequently used incorrectly.
9250 AOT SUPPORT:
9251 Emit LLVM bytecode into a .bc file, compile it using llc into a .s file, then link
9252 it with the file containing the methods emitted by the JIT and the AOT data
9253 structures.
9256 /* FIXME: Normalize some aspects of the mono IR to allow easier translation, like:
9257 * - each bblock should end with a branch
9258 * - setting the return value, making cfg->ret non-volatile
9259 * - avoid some transformations in the JIT which make it harder for us to generate
9260 * code.
9261 * - use pointer types to help optimizations.
9264 #else /* DISABLE_JIT */
9266 void
9267 mono_llvm_cleanup (void)
9271 void
9272 mono_llvm_free_domain_info (MonoDomain *domain)
9276 void
9277 mono_llvm_init (void)
9281 void
9282 default_mono_llvm_unhandled_exception (void)
9286 #endif /* DISABLE_JIT */