[llvm] Delete some dead code.
[mono-project.git] / mono / mini / mini-llvm.c
blobce9cedebbb4c033b50f835db1ddf7880a1e00484
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 "mini.h"
10 #include <mono/metadata/debug-helpers.h>
11 #include <mono/metadata/debug-mono-symfile.h>
12 #include <mono/metadata/mempool-internals.h>
13 #include <mono/metadata/environment.h>
14 #include <mono/metadata/object-internals.h>
15 #include <mono/metadata/abi-details.h>
16 #include <mono/utils/mono-tls.h>
17 #include <mono/utils/mono-dl.h>
18 #include <mono/utils/mono-time.h>
19 #include <mono/utils/freebsd-dwarf.h>
21 #ifndef __STDC_LIMIT_MACROS
22 #define __STDC_LIMIT_MACROS
23 #endif
24 #ifndef __STDC_CONSTANT_MACROS
25 #define __STDC_CONSTANT_MACROS
26 #endif
28 #include "llvm-c/BitWriter.h"
29 #include "llvm-c/Analysis.h"
31 #include "mini-llvm-cpp.h"
32 #include "llvm-jit.h"
33 #include "aot-compiler.h"
34 #include "mini-llvm.h"
36 #ifdef __MINGW32__
38 #include <stddef.h>
39 extern void *memset(void *, int, size_t);
40 void bzero (void *to, size_t count) { memset (to, 0, count); }
42 #endif
44 #if LLVM_API_VERSION < 4
45 #error "The version of the mono llvm repository is too old."
46 #endif
48 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
51 * Information associated by mono with LLVM modules.
53 typedef struct {
54 LLVMModuleRef lmodule;
55 LLVMValueRef throw_icall, rethrow, match_exc, throw_corlib_exception, resume_eh;
56 GHashTable *llvm_types;
57 LLVMValueRef got_var;
58 const char *got_symbol;
59 const char *get_method_symbol;
60 const char *get_unbox_tramp_symbol;
61 GHashTable *plt_entries;
62 GHashTable *plt_entries_ji;
63 GHashTable *method_to_lmethod;
64 GHashTable *direct_callables;
65 char **bb_names;
66 int bb_names_len;
67 GPtrArray *used;
68 LLVMTypeRef ptr_type;
69 GPtrArray *subprogram_mds;
70 MonoEERef *mono_ee;
71 LLVMExecutionEngineRef ee;
72 gboolean external_symbols;
73 gboolean emit_dwarf;
74 int max_got_offset;
75 LLVMValueRef personality;
77 /* For AOT */
78 MonoAssembly *assembly;
79 char *global_prefix;
80 MonoAotFileInfo aot_info;
81 const char *jit_got_symbol;
82 const char *eh_frame_symbol;
83 LLVMValueRef get_method, get_unbox_tramp;
84 LLVMValueRef init_method, init_method_gshared_mrgctx, init_method_gshared_this, init_method_gshared_vtable;
85 LLVMValueRef code_start, code_end;
86 LLVMValueRef inited_var;
87 int max_inited_idx, max_method_idx;
88 gboolean has_jitted_code;
89 gboolean static_link;
90 gboolean llvm_only;
91 GHashTable *idx_to_lmethod;
92 GHashTable *idx_to_unbox_tramp;
93 /* Maps a MonoMethod to LLVM instructions representing it */
94 GHashTable *method_to_callers;
95 LLVMContextRef context;
96 LLVMValueRef sentinel_exception;
97 void *di_builder, *cu;
98 GHashTable *objc_selector_to_var;
99 } MonoLLVMModule;
102 * Information associated by the backend with mono basic blocks.
104 typedef struct {
105 LLVMBasicBlockRef bblock, end_bblock;
106 LLVMValueRef finally_ind;
107 gboolean added, invoke_target;
109 * If this bblock is the start of a finally clause, this is a list of bblocks it
110 * needs to branch to in ENDFINALLY.
112 GSList *call_handler_return_bbs;
114 * If this bblock is the start of a finally clause, this is the bblock that
115 * CALL_HANDLER needs to branch to.
117 LLVMBasicBlockRef call_handler_target_bb;
118 /* The list of switch statements generated by ENDFINALLY instructions */
119 GSList *endfinally_switch_ins_list;
120 GSList *phi_nodes;
121 } BBInfo;
124 * Structure containing emit state
126 typedef struct {
127 MonoMemPool *mempool;
129 /* Maps method names to the corresponding LLVMValueRef */
130 GHashTable *emitted_method_decls;
132 MonoCompile *cfg;
133 LLVMValueRef lmethod;
134 MonoLLVMModule *module;
135 LLVMModuleRef lmodule;
136 BBInfo *bblocks;
137 int sindex, default_index, ex_index;
138 LLVMBuilderRef builder;
139 LLVMValueRef *values, *addresses;
140 MonoType **vreg_cli_types;
141 LLVMCallInfo *linfo;
142 MonoMethodSignature *sig;
143 GSList *builders;
144 GHashTable *region_to_handler;
145 GHashTable *clause_to_handler;
146 LLVMBuilderRef alloca_builder;
147 LLVMValueRef last_alloca;
148 LLVMValueRef rgctx_arg;
149 LLVMValueRef this_arg;
150 LLVMTypeRef *vreg_types;
151 LLVMTypeRef method_type;
152 LLVMBasicBlockRef init_bb, inited_bb;
153 gboolean *is_dead;
154 gboolean *unreachable;
155 gboolean llvm_only;
156 gboolean has_got_access;
157 gboolean is_linkonce;
158 int this_arg_pindex, rgctx_arg_pindex;
159 LLVMValueRef imt_rgctx_loc;
160 GHashTable *llvm_types;
161 LLVMValueRef dbg_md;
162 MonoDebugMethodInfo *minfo;
163 char temp_name [32];
164 /* For every clause, the clauses it is nested in */
165 GSList **nested_in;
166 LLVMValueRef ex_var;
167 GHashTable *exc_meta;
168 GHashTable *method_to_callers;
169 GPtrArray *phi_values;
170 GPtrArray *bblock_list;
171 char *method_name;
172 GHashTable *jit_callees;
173 } EmitContext;
175 typedef struct {
176 MonoBasicBlock *bb;
177 MonoInst *phi;
178 MonoBasicBlock *in_bb;
179 int sreg;
180 } PhiNode;
183 * Instruction metadata
184 * This is the same as ins_info, but LREG != IREG.
186 #ifdef MINI_OP
187 #undef MINI_OP
188 #endif
189 #ifdef MINI_OP3
190 #undef MINI_OP3
191 #endif
192 #define MINI_OP(a,b,dest,src1,src2) dest, src1, src2, ' ',
193 #define MINI_OP3(a,b,dest,src1,src2,src3) dest, src1, src2, src3,
194 #define NONE ' '
195 #define IREG 'i'
196 #define FREG 'f'
197 #define VREG 'v'
198 #define XREG 'x'
199 #define LREG 'l'
200 /* keep in sync with the enum in mini.h */
201 const char
202 llvm_ins_info[] = {
203 #include "mini-ops.h"
205 #undef MINI_OP
206 #undef MINI_OP3
208 #if SIZEOF_VOID_P == 4
209 #define GET_LONG_IMM(ins) (((guint64)(ins)->inst_ms_word << 32) | (guint64)(guint32)(ins)->inst_ls_word)
210 #else
211 #define GET_LONG_IMM(ins) ((ins)->inst_imm)
212 #endif
214 #define LLVM_INS_INFO(opcode) (&llvm_ins_info [((opcode) - OP_START - 1) * 4])
216 #if 0
217 #define TRACE_FAILURE(msg) do { printf ("%s\n", msg); } while (0)
218 #else
219 #define TRACE_FAILURE(msg)
220 #endif
222 #ifdef TARGET_X86
223 #define IS_TARGET_X86 1
224 #else
225 #define IS_TARGET_X86 0
226 #endif
228 #ifdef TARGET_AMD64
229 #define IS_TARGET_AMD64 1
230 #else
231 #define IS_TARGET_AMD64 0
232 #endif
234 #define ctx_ok(ctx) (!(ctx)->cfg->disable_llvm)
236 static LLVMIntPredicate cond_to_llvm_cond [] = {
237 LLVMIntEQ,
238 LLVMIntNE,
239 LLVMIntSLE,
240 LLVMIntSGE,
241 LLVMIntSLT,
242 LLVMIntSGT,
243 LLVMIntULE,
244 LLVMIntUGE,
245 LLVMIntULT,
246 LLVMIntUGT,
249 static LLVMRealPredicate fpcond_to_llvm_cond [] = {
250 LLVMRealOEQ,
251 LLVMRealUNE,
252 LLVMRealOLE,
253 LLVMRealOGE,
254 LLVMRealOLT,
255 LLVMRealOGT,
256 LLVMRealULE,
257 LLVMRealUGE,
258 LLVMRealULT,
259 LLVMRealUGT,
262 static MonoNativeTlsKey current_cfg_tls_id;
264 static MonoLLVMModule aot_module;
266 static GHashTable *intrins_id_to_name;
267 static GHashTable *intrins_name_to_id;
269 static void init_jit_module (MonoDomain *domain);
271 static void emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil_code);
272 static LLVMValueRef emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, const char *name);
273 static void emit_dbg_info (MonoLLVMModule *module, const char *filename, const char *cu_name);
274 static void emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *exc_type, LLVMValueRef cmp);
275 static LLVMValueRef get_intrinsic (EmitContext *ctx, const char *name);
276 static void decode_llvm_eh_info (EmitContext *ctx, gpointer eh_frame);
278 static inline void
279 set_failure (EmitContext *ctx, const char *message)
281 TRACE_FAILURE (reason);
282 ctx->cfg->exception_message = g_strdup (message);
283 ctx->cfg->disable_llvm = TRUE;
287 * IntPtrType:
289 * The LLVM type with width == sizeof (gpointer)
291 static LLVMTypeRef
292 IntPtrType (void)
294 return sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type ();
297 static LLVMTypeRef
298 ObjRefType (void)
300 return sizeof (gpointer) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
303 static LLVMTypeRef
304 ThisType (void)
306 return sizeof (gpointer) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
310 * get_vtype_size:
312 * Return the size of the LLVM representation of the vtype T.
314 static guint32
315 get_vtype_size (MonoType *t)
317 int size;
319 size = mono_class_value_size (mono_class_from_mono_type (t), NULL);
321 /* LLVMArgAsIArgs depends on this since it stores whole words */
322 while (size < 2 * sizeof (gpointer) && mono_is_power_of_two (size) == -1)
323 size ++;
325 return size;
329 * simd_class_to_llvm_type:
331 * Return the LLVM type corresponding to the Mono.SIMD class KLASS
333 static LLVMTypeRef
334 simd_class_to_llvm_type (EmitContext *ctx, MonoClass *klass)
336 if (!strcmp (klass->name, "Vector2d")) {
337 return LLVMVectorType (LLVMDoubleType (), 2);
338 } else if (!strcmp (klass->name, "Vector2l")) {
339 return LLVMVectorType (LLVMInt64Type (), 2);
340 } else if (!strcmp (klass->name, "Vector2ul")) {
341 return LLVMVectorType (LLVMInt64Type (), 2);
342 } else if (!strcmp (klass->name, "Vector4i")) {
343 return LLVMVectorType (LLVMInt32Type (), 4);
344 } else if (!strcmp (klass->name, "Vector4ui")) {
345 return LLVMVectorType (LLVMInt32Type (), 4);
346 } else if (!strcmp (klass->name, "Vector4f")) {
347 return LLVMVectorType (LLVMFloatType (), 4);
348 } else if (!strcmp (klass->name, "Vector8s")) {
349 return LLVMVectorType (LLVMInt16Type (), 8);
350 } else if (!strcmp (klass->name, "Vector8us")) {
351 return LLVMVectorType (LLVMInt16Type (), 8);
352 } else if (!strcmp (klass->name, "Vector16sb")) {
353 return LLVMVectorType (LLVMInt8Type (), 16);
354 } else if (!strcmp (klass->name, "Vector16b")) {
355 return LLVMVectorType (LLVMInt8Type (), 16);
356 } else {
357 printf ("%s\n", klass->name);
358 NOT_IMPLEMENTED;
359 return NULL;
363 /* Return the 128 bit SIMD type corresponding to the mono type TYPE */
364 static inline G_GNUC_UNUSED LLVMTypeRef
365 type_to_simd_type (int type)
367 switch (type) {
368 case MONO_TYPE_I1:
369 return LLVMVectorType (LLVMInt8Type (), 16);
370 case MONO_TYPE_I2:
371 return LLVMVectorType (LLVMInt16Type (), 8);
372 case MONO_TYPE_I4:
373 return LLVMVectorType (LLVMInt32Type (), 4);
374 case MONO_TYPE_I8:
375 return LLVMVectorType (LLVMInt64Type (), 2);
376 case MONO_TYPE_R8:
377 return LLVMVectorType (LLVMDoubleType (), 2);
378 case MONO_TYPE_R4:
379 return LLVMVectorType (LLVMFloatType (), 4);
380 default:
381 g_assert_not_reached ();
382 return NULL;
386 static LLVMTypeRef
387 create_llvm_type_for_type (MonoLLVMModule *module, MonoClass *klass)
389 int i, size, nfields, esize;
390 LLVMTypeRef *eltypes;
391 char *name;
392 MonoType *t;
393 LLVMTypeRef ltype;
395 t = &klass->byval_arg;
397 if (mini_type_is_hfa (t, &nfields, &esize)) {
399 * This is needed on arm64 where HFAs are returned in
400 * registers.
402 size = nfields;
403 eltypes = g_new (LLVMTypeRef, size);
404 for (i = 0; i < size; ++i)
405 eltypes [i] = esize == 4 ? LLVMFloatType () : LLVMDoubleType ();
406 } else {
407 size = get_vtype_size (t);
409 eltypes = g_new (LLVMTypeRef, size);
410 for (i = 0; i < size; ++i)
411 eltypes [i] = LLVMInt8Type ();
414 name = mono_type_full_name (&klass->byval_arg);
415 ltype = LLVMStructCreateNamed (module->context, name);
416 LLVMStructSetBody (ltype, eltypes, size, FALSE);
417 g_free (eltypes);
418 g_free (name);
420 return ltype;
424 * type_to_llvm_type:
426 * Return the LLVM type corresponding to T.
428 static LLVMTypeRef
429 type_to_llvm_type (EmitContext *ctx, MonoType *t)
431 t = mini_get_underlying_type (t);
433 switch (t->type) {
434 case MONO_TYPE_VOID:
435 return LLVMVoidType ();
436 case MONO_TYPE_I1:
437 return LLVMInt8Type ();
438 case MONO_TYPE_I2:
439 return LLVMInt16Type ();
440 case MONO_TYPE_I4:
441 return LLVMInt32Type ();
442 case MONO_TYPE_U1:
443 return LLVMInt8Type ();
444 case MONO_TYPE_U2:
445 return LLVMInt16Type ();
446 case MONO_TYPE_U4:
447 return LLVMInt32Type ();
448 case MONO_TYPE_BOOLEAN:
449 return LLVMInt8Type ();
450 case MONO_TYPE_I8:
451 case MONO_TYPE_U8:
452 return LLVMInt64Type ();
453 case MONO_TYPE_CHAR:
454 return LLVMInt16Type ();
455 case MONO_TYPE_R4:
456 return LLVMFloatType ();
457 case MONO_TYPE_R8:
458 return LLVMDoubleType ();
459 case MONO_TYPE_I:
460 case MONO_TYPE_U:
461 return IntPtrType ();
462 case MONO_TYPE_OBJECT:
463 case MONO_TYPE_CLASS:
464 case MONO_TYPE_ARRAY:
465 case MONO_TYPE_SZARRAY:
466 case MONO_TYPE_STRING:
467 case MONO_TYPE_PTR:
468 return ObjRefType ();
469 case MONO_TYPE_VAR:
470 case MONO_TYPE_MVAR:
471 /* Because of generic sharing */
472 return ObjRefType ();
473 case MONO_TYPE_GENERICINST:
474 if (!mono_type_generic_inst_is_valuetype (t))
475 return ObjRefType ();
476 /* Fall through */
477 case MONO_TYPE_VALUETYPE:
478 case MONO_TYPE_TYPEDBYREF: {
479 MonoClass *klass;
480 LLVMTypeRef ltype;
482 klass = mono_class_from_mono_type (t);
484 if (MONO_CLASS_IS_SIMD (ctx->cfg, klass))
485 return simd_class_to_llvm_type (ctx, klass);
487 if (klass->enumtype)
488 return type_to_llvm_type (ctx, mono_class_enum_basetype (klass));
490 ltype = (LLVMTypeRef)g_hash_table_lookup (ctx->module->llvm_types, klass);
491 if (!ltype) {
492 ltype = create_llvm_type_for_type (ctx->module, klass);
493 g_hash_table_insert (ctx->module->llvm_types, klass, ltype);
495 return ltype;
498 default:
499 printf ("X: %d\n", t->type);
500 ctx->cfg->exception_message = g_strdup_printf ("type %s", mono_type_full_name (t));
501 ctx->cfg->disable_llvm = TRUE;
502 return NULL;
507 * type_is_unsigned:
509 * Return whenever T is an unsigned int type.
511 static gboolean
512 type_is_unsigned (EmitContext *ctx, MonoType *t)
514 t = mini_get_underlying_type (t);
515 if (t->byref)
516 return FALSE;
517 switch (t->type) {
518 case MONO_TYPE_U1:
519 case MONO_TYPE_U2:
520 case MONO_TYPE_CHAR:
521 case MONO_TYPE_U4:
522 case MONO_TYPE_U8:
523 return TRUE;
524 default:
525 return FALSE;
530 * type_to_llvm_arg_type:
532 * Same as type_to_llvm_type, but treat i8/i16 as i32.
534 static LLVMTypeRef
535 type_to_llvm_arg_type (EmitContext *ctx, MonoType *t)
537 LLVMTypeRef ptype = type_to_llvm_type (ctx, t);
539 if (ctx->cfg->llvm_only)
540 return ptype;
543 * This works on all abis except arm64/ios which passes multiple
544 * arguments in one stack slot.
546 #ifndef TARGET_ARM64
547 if (ptype == LLVMInt8Type () || ptype == LLVMInt16Type ()) {
549 * LLVM generates code which only sets the lower bits, while JITted
550 * code expects all the bits to be set.
552 ptype = LLVMInt32Type ();
554 #endif
556 return ptype;
560 * llvm_type_to_stack_type:
562 * Return the LLVM type which needs to be used when a value of type TYPE is pushed
563 * on the IL stack.
565 static G_GNUC_UNUSED LLVMTypeRef
566 llvm_type_to_stack_type (MonoCompile *cfg, LLVMTypeRef type)
568 if (type == NULL)
569 return NULL;
570 if (type == LLVMInt8Type ())
571 return LLVMInt32Type ();
572 else if (type == LLVMInt16Type ())
573 return LLVMInt32Type ();
574 else if (!cfg->r4fp && type == LLVMFloatType ())
575 return LLVMDoubleType ();
576 else
577 return type;
581 * regtype_to_llvm_type:
583 * Return the LLVM type corresponding to the regtype C used in instruction
584 * descriptions.
586 static LLVMTypeRef
587 regtype_to_llvm_type (char c)
589 switch (c) {
590 case 'i':
591 return LLVMInt32Type ();
592 case 'l':
593 return LLVMInt64Type ();
594 case 'f':
595 return LLVMDoubleType ();
596 default:
597 return NULL;
602 * op_to_llvm_type:
604 * Return the LLVM type corresponding to the unary/binary opcode OPCODE.
606 static LLVMTypeRef
607 op_to_llvm_type (int opcode)
609 switch (opcode) {
610 case OP_ICONV_TO_I1:
611 case OP_LCONV_TO_I1:
612 return LLVMInt8Type ();
613 case OP_ICONV_TO_U1:
614 case OP_LCONV_TO_U1:
615 return LLVMInt8Type ();
616 case OP_ICONV_TO_I2:
617 case OP_LCONV_TO_I2:
618 return LLVMInt16Type ();
619 case OP_ICONV_TO_U2:
620 case OP_LCONV_TO_U2:
621 return LLVMInt16Type ();
622 case OP_ICONV_TO_I4:
623 case OP_LCONV_TO_I4:
624 return LLVMInt32Type ();
625 case OP_ICONV_TO_U4:
626 case OP_LCONV_TO_U4:
627 return LLVMInt32Type ();
628 case OP_ICONV_TO_I8:
629 return LLVMInt64Type ();
630 case OP_ICONV_TO_R4:
631 return LLVMFloatType ();
632 case OP_ICONV_TO_R8:
633 return LLVMDoubleType ();
634 case OP_ICONV_TO_U8:
635 return LLVMInt64Type ();
636 case OP_FCONV_TO_I4:
637 return LLVMInt32Type ();
638 case OP_FCONV_TO_I8:
639 return LLVMInt64Type ();
640 case OP_FCONV_TO_I1:
641 case OP_FCONV_TO_U1:
642 case OP_RCONV_TO_I1:
643 case OP_RCONV_TO_U1:
644 return LLVMInt8Type ();
645 case OP_FCONV_TO_I2:
646 case OP_FCONV_TO_U2:
647 case OP_RCONV_TO_I2:
648 case OP_RCONV_TO_U2:
649 return LLVMInt16Type ();
650 case OP_RCONV_TO_U4:
651 return LLVMInt32Type ();
652 case OP_FCONV_TO_I:
653 case OP_FCONV_TO_U:
654 return sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type ();
655 case OP_IADD_OVF:
656 case OP_IADD_OVF_UN:
657 case OP_ISUB_OVF:
658 case OP_ISUB_OVF_UN:
659 case OP_IMUL_OVF:
660 case OP_IMUL_OVF_UN:
661 return LLVMInt32Type ();
662 case OP_LADD_OVF:
663 case OP_LADD_OVF_UN:
664 case OP_LSUB_OVF:
665 case OP_LSUB_OVF_UN:
666 case OP_LMUL_OVF:
667 case OP_LMUL_OVF_UN:
668 return LLVMInt64Type ();
669 default:
670 printf ("%s\n", mono_inst_name (opcode));
671 g_assert_not_reached ();
672 return NULL;
676 #define CLAUSE_START(clause) ((clause)->try_offset)
677 #define CLAUSE_END(clause) (((clause))->try_offset + ((clause))->try_len)
680 * load_store_to_llvm_type:
682 * Return the size/sign/zero extension corresponding to the load/store opcode
683 * OPCODE.
685 static LLVMTypeRef
686 load_store_to_llvm_type (int opcode, int *size, gboolean *sext, gboolean *zext)
688 *sext = FALSE;
689 *zext = FALSE;
691 switch (opcode) {
692 case OP_LOADI1_MEMBASE:
693 case OP_STOREI1_MEMBASE_REG:
694 case OP_STOREI1_MEMBASE_IMM:
695 case OP_ATOMIC_LOAD_I1:
696 case OP_ATOMIC_STORE_I1:
697 *size = 1;
698 *sext = TRUE;
699 return LLVMInt8Type ();
700 case OP_LOADU1_MEMBASE:
701 case OP_LOADU1_MEM:
702 case OP_ATOMIC_LOAD_U1:
703 case OP_ATOMIC_STORE_U1:
704 *size = 1;
705 *zext = TRUE;
706 return LLVMInt8Type ();
707 case OP_LOADI2_MEMBASE:
708 case OP_STOREI2_MEMBASE_REG:
709 case OP_STOREI2_MEMBASE_IMM:
710 case OP_ATOMIC_LOAD_I2:
711 case OP_ATOMIC_STORE_I2:
712 *size = 2;
713 *sext = TRUE;
714 return LLVMInt16Type ();
715 case OP_LOADU2_MEMBASE:
716 case OP_LOADU2_MEM:
717 case OP_ATOMIC_LOAD_U2:
718 case OP_ATOMIC_STORE_U2:
719 *size = 2;
720 *zext = TRUE;
721 return LLVMInt16Type ();
722 case OP_LOADI4_MEMBASE:
723 case OP_LOADU4_MEMBASE:
724 case OP_LOADI4_MEM:
725 case OP_LOADU4_MEM:
726 case OP_STOREI4_MEMBASE_REG:
727 case OP_STOREI4_MEMBASE_IMM:
728 case OP_ATOMIC_LOAD_I4:
729 case OP_ATOMIC_STORE_I4:
730 case OP_ATOMIC_LOAD_U4:
731 case OP_ATOMIC_STORE_U4:
732 *size = 4;
733 return LLVMInt32Type ();
734 case OP_LOADI8_MEMBASE:
735 case OP_LOADI8_MEM:
736 case OP_STOREI8_MEMBASE_REG:
737 case OP_STOREI8_MEMBASE_IMM:
738 case OP_ATOMIC_LOAD_I8:
739 case OP_ATOMIC_STORE_I8:
740 case OP_ATOMIC_LOAD_U8:
741 case OP_ATOMIC_STORE_U8:
742 *size = 8;
743 return LLVMInt64Type ();
744 case OP_LOADR4_MEMBASE:
745 case OP_STORER4_MEMBASE_REG:
746 case OP_ATOMIC_LOAD_R4:
747 case OP_ATOMIC_STORE_R4:
748 *size = 4;
749 return LLVMFloatType ();
750 case OP_LOADR8_MEMBASE:
751 case OP_STORER8_MEMBASE_REG:
752 case OP_ATOMIC_LOAD_R8:
753 case OP_ATOMIC_STORE_R8:
754 *size = 8;
755 return LLVMDoubleType ();
756 case OP_LOAD_MEMBASE:
757 case OP_LOAD_MEM:
758 case OP_STORE_MEMBASE_REG:
759 case OP_STORE_MEMBASE_IMM:
760 *size = sizeof (gpointer);
761 return IntPtrType ();
762 default:
763 g_assert_not_reached ();
764 return NULL;
769 * ovf_op_to_intrins:
771 * Return the LLVM intrinsics corresponding to the overflow opcode OPCODE.
773 static const char*
774 ovf_op_to_intrins (int opcode)
776 switch (opcode) {
777 case OP_IADD_OVF:
778 return "llvm.sadd.with.overflow.i32";
779 case OP_IADD_OVF_UN:
780 return "llvm.uadd.with.overflow.i32";
781 case OP_ISUB_OVF:
782 return "llvm.ssub.with.overflow.i32";
783 case OP_ISUB_OVF_UN:
784 return "llvm.usub.with.overflow.i32";
785 case OP_IMUL_OVF:
786 return "llvm.smul.with.overflow.i32";
787 case OP_IMUL_OVF_UN:
788 return "llvm.umul.with.overflow.i32";
789 case OP_LADD_OVF:
790 return "llvm.sadd.with.overflow.i64";
791 case OP_LADD_OVF_UN:
792 return "llvm.uadd.with.overflow.i64";
793 case OP_LSUB_OVF:
794 return "llvm.ssub.with.overflow.i64";
795 case OP_LSUB_OVF_UN:
796 return "llvm.usub.with.overflow.i64";
797 case OP_LMUL_OVF:
798 return "llvm.smul.with.overflow.i64";
799 case OP_LMUL_OVF_UN:
800 return "llvm.umul.with.overflow.i64";
801 default:
802 g_assert_not_reached ();
803 return NULL;
807 static const char*
808 simd_op_to_intrins (int opcode)
810 switch (opcode) {
811 #if defined(TARGET_X86) || defined(TARGET_AMD64)
812 case OP_MINPD:
813 return "llvm.x86.sse2.min.pd";
814 case OP_MINPS:
815 return "llvm.x86.sse.min.ps";
816 case OP_MAXPD:
817 return "llvm.x86.sse2.max.pd";
818 case OP_MAXPS:
819 return "llvm.x86.sse.max.ps";
820 case OP_HADDPD:
821 return "llvm.x86.sse3.hadd.pd";
822 case OP_HADDPS:
823 return "llvm.x86.sse3.hadd.ps";
824 case OP_HSUBPD:
825 return "llvm.x86.sse3.hsub.pd";
826 case OP_HSUBPS:
827 return "llvm.x86.sse3.hsub.ps";
828 case OP_ADDSUBPS:
829 return "llvm.x86.sse3.addsub.ps";
830 case OP_ADDSUBPD:
831 return "llvm.x86.sse3.addsub.pd";
832 case OP_EXTRACT_MASK:
833 return "llvm.x86.sse2.pmovmskb.128";
834 case OP_PSHRW:
835 case OP_PSHRW_REG:
836 return "llvm.x86.sse2.psrli.w";
837 case OP_PSHRD:
838 case OP_PSHRD_REG:
839 return "llvm.x86.sse2.psrli.d";
840 case OP_PSHRQ:
841 case OP_PSHRQ_REG:
842 return "llvm.x86.sse2.psrli.q";
843 case OP_PSHLW:
844 case OP_PSHLW_REG:
845 return "llvm.x86.sse2.pslli.w";
846 case OP_PSHLD:
847 case OP_PSHLD_REG:
848 return "llvm.x86.sse2.pslli.d";
849 case OP_PSHLQ:
850 case OP_PSHLQ_REG:
851 return "llvm.x86.sse2.pslli.q";
852 case OP_PSARW:
853 case OP_PSARW_REG:
854 return "llvm.x86.sse2.psrai.w";
855 case OP_PSARD:
856 case OP_PSARD_REG:
857 return "llvm.x86.sse2.psrai.d";
858 case OP_PADDB_SAT:
859 return "llvm.x86.sse2.padds.b";
860 case OP_PADDW_SAT:
861 return "llvm.x86.sse2.padds.w";
862 case OP_PSUBB_SAT:
863 return "llvm.x86.sse2.psubs.b";
864 case OP_PSUBW_SAT:
865 return "llvm.x86.sse2.psubs.w";
866 case OP_PADDB_SAT_UN:
867 return "llvm.x86.sse2.paddus.b";
868 case OP_PADDW_SAT_UN:
869 return "llvm.x86.sse2.paddus.w";
870 case OP_PSUBB_SAT_UN:
871 return "llvm.x86.sse2.psubus.b";
872 case OP_PSUBW_SAT_UN:
873 return "llvm.x86.sse2.psubus.w";
874 case OP_PAVGB_UN:
875 return "llvm.x86.sse2.pavg.b";
876 case OP_PAVGW_UN:
877 return "llvm.x86.sse2.pavg.w";
878 case OP_SQRTPS:
879 return "llvm.x86.sse.sqrt.ps";
880 case OP_SQRTPD:
881 return "llvm.x86.sse2.sqrt.pd";
882 case OP_RSQRTPS:
883 return "llvm.x86.sse.rsqrt.ps";
884 case OP_RCPPS:
885 return "llvm.x86.sse.rcp.ps";
886 case OP_CVTDQ2PD:
887 return "llvm.x86.sse2.cvtdq2pd";
888 case OP_CVTDQ2PS:
889 return "llvm.x86.sse2.cvtdq2ps";
890 case OP_CVTPD2DQ:
891 return "llvm.x86.sse2.cvtpd2dq";
892 case OP_CVTPS2DQ:
893 return "llvm.x86.sse2.cvtps2dq";
894 case OP_CVTPD2PS:
895 return "llvm.x86.sse2.cvtpd2ps";
896 case OP_CVTPS2PD:
897 return "llvm.x86.sse2.cvtps2pd";
898 case OP_CVTTPD2DQ:
899 return "llvm.x86.sse2.cvttpd2dq";
900 case OP_CVTTPS2DQ:
901 return "llvm.x86.sse2.cvttps2dq";
902 case OP_PACKW:
903 return "llvm.x86.sse2.packsswb.128";
904 case OP_PACKD:
905 return "llvm.x86.sse2.packssdw.128";
906 case OP_PACKW_UN:
907 return "llvm.x86.sse2.packuswb.128";
908 case OP_PACKD_UN:
909 return "llvm.x86.sse41.packusdw";
910 case OP_PMULW_HIGH:
911 return "llvm.x86.sse2.pmulh.w";
912 case OP_PMULW_HIGH_UN:
913 return "llvm.x86.sse2.pmulhu.w";
914 #endif
915 default:
916 g_assert_not_reached ();
917 return NULL;
921 static LLVMTypeRef
922 simd_op_to_llvm_type (int opcode)
924 #if defined(TARGET_X86) || defined(TARGET_AMD64)
925 switch (opcode) {
926 case OP_EXTRACT_R8:
927 case OP_EXPAND_R8:
928 return type_to_simd_type (MONO_TYPE_R8);
929 case OP_EXTRACT_I8:
930 case OP_EXPAND_I8:
931 return type_to_simd_type (MONO_TYPE_I8);
932 case OP_EXTRACT_I4:
933 case OP_EXPAND_I4:
934 return type_to_simd_type (MONO_TYPE_I4);
935 case OP_EXTRACT_I2:
936 case OP_EXTRACT_U2:
937 case OP_EXTRACTX_U2:
938 case OP_EXPAND_I2:
939 return type_to_simd_type (MONO_TYPE_I2);
940 case OP_EXTRACT_I1:
941 case OP_EXTRACT_U1:
942 case OP_EXPAND_I1:
943 return type_to_simd_type (MONO_TYPE_I1);
944 case OP_EXPAND_R4:
945 return type_to_simd_type (MONO_TYPE_R4);
946 case OP_CVTDQ2PD:
947 case OP_CVTDQ2PS:
948 return type_to_simd_type (MONO_TYPE_I4);
949 case OP_CVTPD2DQ:
950 case OP_CVTPD2PS:
951 case OP_CVTTPD2DQ:
952 return type_to_simd_type (MONO_TYPE_R8);
953 case OP_CVTPS2DQ:
954 case OP_CVTPS2PD:
955 case OP_CVTTPS2DQ:
956 return type_to_simd_type (MONO_TYPE_R4);
957 case OP_EXTRACT_MASK:
958 return type_to_simd_type (MONO_TYPE_I1);
959 case OP_SQRTPS:
960 case OP_RSQRTPS:
961 case OP_RCPPS:
962 case OP_DUPPS_LOW:
963 case OP_DUPPS_HIGH:
964 return type_to_simd_type (MONO_TYPE_R4);
965 case OP_SQRTPD:
966 case OP_DUPPD:
967 return type_to_simd_type (MONO_TYPE_R8);
968 default:
969 g_assert_not_reached ();
970 return NULL;
972 #else
973 return NULL;
974 #endif
978 * get_bb:
980 * Return the LLVM basic block corresponding to BB.
982 static LLVMBasicBlockRef
983 get_bb (EmitContext *ctx, MonoBasicBlock *bb)
985 char bb_name_buf [128];
986 char *bb_name;
988 if (ctx->bblocks [bb->block_num].bblock == NULL) {
989 if (bb->flags & BB_EXCEPTION_HANDLER) {
990 int clause_index = (mono_get_block_region_notry (ctx->cfg, bb->region) >> 8) - 1;
991 sprintf (bb_name_buf, "EH_CLAUSE%d_BB%d", clause_index, bb->block_num);
992 bb_name = bb_name_buf;
993 } else if (bb->block_num < 256) {
994 if (!ctx->module->bb_names) {
995 ctx->module->bb_names_len = 256;
996 ctx->module->bb_names = g_new0 (char*, ctx->module->bb_names_len);
998 if (!ctx->module->bb_names [bb->block_num]) {
999 char *n;
1001 n = g_strdup_printf ("BB%d", bb->block_num);
1002 mono_memory_barrier ();
1003 ctx->module->bb_names [bb->block_num] = n;
1005 bb_name = ctx->module->bb_names [bb->block_num];
1006 } else {
1007 sprintf (bb_name_buf, "BB%d", bb->block_num);
1008 bb_name = bb_name_buf;
1011 ctx->bblocks [bb->block_num].bblock = LLVMAppendBasicBlock (ctx->lmethod, bb_name);
1012 ctx->bblocks [bb->block_num].end_bblock = ctx->bblocks [bb->block_num].bblock;
1015 return ctx->bblocks [bb->block_num].bblock;
1019 * get_end_bb:
1021 * Return the last LLVM bblock corresponding to BB.
1022 * This might not be equal to the bb returned by get_bb () since we need to generate
1023 * multiple LLVM bblocks for a mono bblock to handle throwing exceptions.
1025 static LLVMBasicBlockRef
1026 get_end_bb (EmitContext *ctx, MonoBasicBlock *bb)
1028 get_bb (ctx, bb);
1029 return ctx->bblocks [bb->block_num].end_bblock;
1032 static LLVMBasicBlockRef
1033 gen_bb (EmitContext *ctx, const char *prefix)
1035 char bb_name [128];
1037 sprintf (bb_name, "%s%d", prefix, ++ ctx->ex_index);
1038 return LLVMAppendBasicBlock (ctx->lmethod, bb_name);
1042 * resolve_patch:
1044 * Return the target of the patch identified by TYPE and TARGET.
1046 static gpointer
1047 resolve_patch (MonoCompile *cfg, MonoJumpInfoType type, gconstpointer target)
1049 MonoJumpInfo ji;
1050 MonoError error;
1051 gpointer res;
1053 memset (&ji, 0, sizeof (ji));
1054 ji.type = type;
1055 ji.data.target = target;
1057 res = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, &ji, FALSE, &error);
1058 mono_error_assert_ok (&error);
1060 return res;
1064 * convert_full:
1066 * Emit code to convert the LLVM value V to DTYPE.
1068 static LLVMValueRef
1069 convert_full (EmitContext *ctx, LLVMValueRef v, LLVMTypeRef dtype, gboolean is_unsigned)
1071 LLVMTypeRef stype = LLVMTypeOf (v);
1073 if (stype != dtype) {
1074 gboolean ext = FALSE;
1076 /* Extend */
1077 if (dtype == LLVMInt64Type () && (stype == LLVMInt32Type () || stype == LLVMInt16Type () || stype == LLVMInt8Type ()))
1078 ext = TRUE;
1079 else if (dtype == LLVMInt32Type () && (stype == LLVMInt16Type () || stype == LLVMInt8Type ()))
1080 ext = TRUE;
1081 else if (dtype == LLVMInt16Type () && (stype == LLVMInt8Type ()))
1082 ext = TRUE;
1084 if (ext)
1085 return is_unsigned ? LLVMBuildZExt (ctx->builder, v, dtype, "") : LLVMBuildSExt (ctx->builder, v, dtype, "");
1087 if (dtype == LLVMDoubleType () && stype == LLVMFloatType ())
1088 return LLVMBuildFPExt (ctx->builder, v, dtype, "");
1090 /* Trunc */
1091 if (stype == LLVMInt64Type () && (dtype == LLVMInt32Type () || dtype == LLVMInt16Type () || dtype == LLVMInt8Type ()))
1092 return LLVMBuildTrunc (ctx->builder, v, dtype, "");
1093 if (stype == LLVMInt32Type () && (dtype == LLVMInt16Type () || dtype == LLVMInt8Type ()))
1094 return LLVMBuildTrunc (ctx->builder, v, dtype, "");
1095 if (stype == LLVMInt16Type () && dtype == LLVMInt8Type ())
1096 return LLVMBuildTrunc (ctx->builder, v, dtype, "");
1097 if (stype == LLVMDoubleType () && dtype == LLVMFloatType ())
1098 return LLVMBuildFPTrunc (ctx->builder, v, dtype, "");
1100 if (LLVMGetTypeKind (stype) == LLVMPointerTypeKind && LLVMGetTypeKind (dtype) == LLVMPointerTypeKind)
1101 return LLVMBuildBitCast (ctx->builder, v, dtype, "");
1102 if (LLVMGetTypeKind (dtype) == LLVMPointerTypeKind)
1103 return LLVMBuildIntToPtr (ctx->builder, v, dtype, "");
1104 if (LLVMGetTypeKind (stype) == LLVMPointerTypeKind)
1105 return LLVMBuildPtrToInt (ctx->builder, v, dtype, "");
1107 if (mono_arch_is_soft_float ()) {
1108 if (stype == LLVMInt32Type () && dtype == LLVMFloatType ())
1109 return LLVMBuildBitCast (ctx->builder, v, dtype, "");
1110 if (stype == LLVMInt32Type () && dtype == LLVMDoubleType ())
1111 return LLVMBuildBitCast (ctx->builder, LLVMBuildZExt (ctx->builder, v, LLVMInt64Type (), ""), dtype, "");
1114 if (LLVMGetTypeKind (stype) == LLVMVectorTypeKind && LLVMGetTypeKind (dtype) == LLVMVectorTypeKind)
1115 return LLVMBuildBitCast (ctx->builder, v, dtype, "");
1117 LLVMDumpValue (v);
1118 LLVMDumpValue (LLVMConstNull (dtype));
1119 g_assert_not_reached ();
1120 return NULL;
1121 } else {
1122 return v;
1126 static LLVMValueRef
1127 convert (EmitContext *ctx, LLVMValueRef v, LLVMTypeRef dtype)
1129 return convert_full (ctx, v, dtype, FALSE);
1133 * emit_volatile_load:
1135 * If vreg is volatile, emit a load from its address.
1137 static LLVMValueRef
1138 emit_volatile_load (EmitContext *ctx, int vreg)
1140 MonoType *t;
1142 LLVMValueRef v = LLVMBuildLoad (ctx->builder, ctx->addresses [vreg], "");
1143 t = ctx->vreg_cli_types [vreg];
1144 if (t && !t->byref) {
1146 * Might have to zero extend since llvm doesn't have
1147 * unsigned types.
1149 if (t->type == MONO_TYPE_U1 || t->type == MONO_TYPE_U2 || t->type == MONO_TYPE_CHAR || t->type == MONO_TYPE_BOOLEAN)
1150 v = LLVMBuildZExt (ctx->builder, v, LLVMInt32Type (), "");
1151 else if (t->type == MONO_TYPE_I1 || t->type == MONO_TYPE_I2)
1152 v = LLVMBuildSExt (ctx->builder, v, LLVMInt32Type (), "");
1153 else if (t->type == MONO_TYPE_U8)
1154 v = LLVMBuildZExt (ctx->builder, v, LLVMInt64Type (), "");
1157 return v;
1161 * emit_volatile_store:
1163 * If VREG is volatile, emit a store from its value to its address.
1165 static void
1166 emit_volatile_store (EmitContext *ctx, int vreg)
1168 MonoInst *var = get_vreg_to_inst (ctx->cfg, vreg);
1170 if (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) {
1171 g_assert (ctx->addresses [vreg]);
1172 LLVMBuildStore (ctx->builder, convert (ctx, ctx->values [vreg], type_to_llvm_type (ctx, var->inst_vtype)), ctx->addresses [vreg]);
1176 static LLVMTypeRef
1177 sig_to_llvm_sig_no_cinfo (EmitContext *ctx, MonoMethodSignature *sig)
1179 LLVMTypeRef ret_type;
1180 LLVMTypeRef *param_types = NULL;
1181 LLVMTypeRef res;
1182 int i, pindex;
1183 MonoType *rtype;
1185 rtype = mini_get_underlying_type (sig->ret);
1186 ret_type = type_to_llvm_type (ctx, rtype);
1187 if (!ctx_ok (ctx))
1188 return NULL;
1190 param_types = g_new0 (LLVMTypeRef, (sig->param_count * 8) + 3);
1191 pindex = 0;
1193 if (sig->hasthis)
1194 param_types [pindex ++] = ThisType ();
1195 for (i = 0; i < sig->param_count; ++i)
1196 param_types [pindex ++] = type_to_llvm_arg_type (ctx, sig->params [i]);
1198 if (!ctx_ok (ctx)) {
1199 g_free (param_types);
1200 return NULL;
1203 res = LLVMFunctionType (ret_type, param_types, pindex, FALSE);
1204 g_free (param_types);
1206 return res;
1210 * sig_to_llvm_sig_full:
1212 * Return the LLVM signature corresponding to the mono signature SIG using the
1213 * calling convention information in CINFO. Fill out the parameter mapping information in CINFO.
1215 static LLVMTypeRef
1216 sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *cinfo)
1218 LLVMTypeRef ret_type;
1219 LLVMTypeRef *param_types = NULL;
1220 LLVMTypeRef res;
1221 int i, j, pindex, vret_arg_pindex = 0;
1222 gboolean vretaddr = FALSE;
1223 MonoType *rtype;
1225 if (!cinfo)
1226 return sig_to_llvm_sig_no_cinfo (ctx, sig);
1228 rtype = mini_get_underlying_type (sig->ret);
1229 ret_type = type_to_llvm_type (ctx, rtype);
1230 if (!ctx_ok (ctx))
1231 return NULL;
1233 switch (cinfo->ret.storage) {
1234 case LLVMArgVtypeInReg:
1235 /* LLVM models this by returning an aggregate value */
1236 if (cinfo->ret.pair_storage [0] == LLVMArgInIReg && cinfo->ret.pair_storage [1] == LLVMArgNone) {
1237 LLVMTypeRef members [2];
1239 members [0] = IntPtrType ();
1240 ret_type = LLVMStructType (members, 1, FALSE);
1241 } else if (cinfo->ret.pair_storage [0] == LLVMArgNone && cinfo->ret.pair_storage [1] == LLVMArgNone) {
1242 /* Empty struct */
1243 ret_type = LLVMVoidType ();
1244 } else if (cinfo->ret.pair_storage [0] == LLVMArgInIReg && cinfo->ret.pair_storage [1] == LLVMArgInIReg) {
1245 LLVMTypeRef members [2];
1247 members [0] = IntPtrType ();
1248 members [1] = IntPtrType ();
1249 ret_type = LLVMStructType (members, 2, FALSE);
1250 } else {
1251 g_assert_not_reached ();
1253 break;
1254 case LLVMArgVtypeByVal:
1255 /* Vtype returned normally by val */
1256 break;
1257 case LLVMArgVtypeAsScalar: {
1258 int size = mono_class_value_size (mono_class_from_mono_type (rtype), NULL);
1259 /* LLVM models this by returning an int */
1260 if (size < SIZEOF_VOID_P) {
1261 g_assert (cinfo->ret.nslots == 1);
1262 ret_type = LLVMIntType (size * 8);
1263 } else {
1264 g_assert (cinfo->ret.nslots == 1 || cinfo->ret.nslots == 2);
1265 ret_type = LLVMIntType (cinfo->ret.nslots * sizeof (mgreg_t) * 8);
1267 break;
1269 case LLVMArgAsIArgs:
1270 ret_type = LLVMArrayType (IntPtrType (), cinfo->ret.nslots);
1271 break;
1272 case LLVMArgFpStruct: {
1273 /* Vtype returned as a fp struct */
1274 LLVMTypeRef members [16];
1276 /* Have to create our own structure since we don't map fp structures to LLVM fp structures yet */
1277 for (i = 0; i < cinfo->ret.nslots; ++i)
1278 members [i] = cinfo->ret.esize == 8 ? LLVMDoubleType () : LLVMFloatType ();
1279 ret_type = LLVMStructType (members, cinfo->ret.nslots, FALSE);
1280 break;
1282 case LLVMArgVtypeByRef:
1283 /* Vtype returned using a hidden argument */
1284 ret_type = LLVMVoidType ();
1285 break;
1286 case LLVMArgVtypeRetAddr:
1287 case LLVMArgGsharedvtFixed:
1288 case LLVMArgGsharedvtFixedVtype:
1289 case LLVMArgGsharedvtVariable:
1290 vretaddr = TRUE;
1291 ret_type = LLVMVoidType ();
1292 break;
1293 default:
1294 break;
1297 param_types = g_new0 (LLVMTypeRef, (sig->param_count * 8) + 3);
1298 pindex = 0;
1299 if (cinfo->ret.storage == LLVMArgVtypeByRef) {
1301 * Has to be the first argument because of the sret argument attribute
1302 * FIXME: This might conflict with passing 'this' as the first argument, but
1303 * this is only used on arm64 which has a dedicated struct return register.
1305 cinfo->vret_arg_pindex = pindex;
1306 param_types [pindex] = type_to_llvm_arg_type (ctx, sig->ret);
1307 if (!ctx_ok (ctx)) {
1308 g_free (param_types);
1309 return NULL;
1311 param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
1312 pindex ++;
1314 if (!ctx->llvm_only && cinfo->rgctx_arg) {
1315 cinfo->rgctx_arg_pindex = pindex;
1316 param_types [pindex] = ctx->module->ptr_type;
1317 pindex ++;
1319 if (cinfo->imt_arg) {
1320 cinfo->imt_arg_pindex = pindex;
1321 param_types [pindex] = ctx->module->ptr_type;
1322 pindex ++;
1324 if (vretaddr) {
1325 /* Compute the index in the LLVM signature where the vret arg needs to be passed */
1326 vret_arg_pindex = pindex;
1327 if (cinfo->vret_arg_index == 1) {
1328 /* Add the slots consumed by the first argument */
1329 LLVMArgInfo *ainfo = &cinfo->args [0];
1330 switch (ainfo->storage) {
1331 case LLVMArgVtypeInReg:
1332 for (j = 0; j < 2; ++j) {
1333 if (ainfo->pair_storage [j] == LLVMArgInIReg)
1334 vret_arg_pindex ++;
1336 break;
1337 default:
1338 vret_arg_pindex ++;
1342 cinfo->vret_arg_pindex = vret_arg_pindex;
1345 if (vretaddr && vret_arg_pindex == pindex)
1346 param_types [pindex ++] = IntPtrType ();
1347 if (sig->hasthis) {
1348 cinfo->this_arg_pindex = pindex;
1349 param_types [pindex ++] = ThisType ();
1350 cinfo->args [0].pindex = cinfo->this_arg_pindex;
1352 if (vretaddr && vret_arg_pindex == pindex)
1353 param_types [pindex ++] = IntPtrType ();
1354 for (i = 0; i < sig->param_count; ++i) {
1355 LLVMArgInfo *ainfo = &cinfo->args [i + sig->hasthis];
1357 if (vretaddr && vret_arg_pindex == pindex)
1358 param_types [pindex ++] = IntPtrType ();
1359 ainfo->pindex = pindex;
1361 switch (ainfo->storage) {
1362 case LLVMArgVtypeInReg:
1363 for (j = 0; j < 2; ++j) {
1364 switch (ainfo->pair_storage [j]) {
1365 case LLVMArgInIReg:
1366 param_types [pindex ++] = LLVMIntType (sizeof (gpointer) * 8);
1367 break;
1368 case LLVMArgNone:
1369 break;
1370 default:
1371 g_assert_not_reached ();
1374 break;
1375 case LLVMArgVtypeByVal:
1376 param_types [pindex] = type_to_llvm_arg_type (ctx, ainfo->type);
1377 if (!ctx_ok (ctx))
1378 break;
1379 param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
1380 pindex ++;
1381 break;
1382 case LLVMArgAsIArgs:
1383 param_types [pindex] = LLVMArrayType (IntPtrType (), ainfo->nslots);
1384 pindex ++;
1385 break;
1386 case LLVMArgVtypeByRef:
1387 param_types [pindex] = type_to_llvm_arg_type (ctx, ainfo->type);
1388 if (!ctx_ok (ctx))
1389 break;
1390 param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
1391 pindex ++;
1392 break;
1393 case LLVMArgAsFpArgs: {
1394 int j;
1396 /* Emit dummy fp arguments if needed so the rest is passed on the stack */
1397 for (j = 0; j < ainfo->ndummy_fpargs; ++j)
1398 param_types [pindex ++] = LLVMDoubleType ();
1399 for (j = 0; j < ainfo->nslots; ++j)
1400 param_types [pindex ++] = ainfo->esize == 8 ? LLVMDoubleType () : LLVMFloatType ();
1401 break;
1403 case LLVMArgVtypeAsScalar:
1404 g_assert_not_reached ();
1405 break;
1406 case LLVMArgGsharedvtFixed:
1407 case LLVMArgGsharedvtFixedVtype:
1408 param_types [pindex ++] = LLVMPointerType (type_to_llvm_arg_type (ctx, ainfo->type), 0);
1409 break;
1410 case LLVMArgGsharedvtVariable:
1411 param_types [pindex ++] = LLVMPointerType (IntPtrType (), 0);
1412 break;
1413 default:
1414 param_types [pindex ++] = type_to_llvm_arg_type (ctx, ainfo->type);
1415 break;
1418 if (!ctx_ok (ctx)) {
1419 g_free (param_types);
1420 return NULL;
1422 if (vretaddr && vret_arg_pindex == pindex)
1423 param_types [pindex ++] = IntPtrType ();
1424 if (ctx->llvm_only && cinfo->rgctx_arg) {
1425 /* Pass the rgctx as the last argument */
1426 cinfo->rgctx_arg_pindex = pindex;
1427 param_types [pindex] = ctx->module->ptr_type;
1428 pindex ++;
1431 res = LLVMFunctionType (ret_type, param_types, pindex, FALSE);
1432 g_free (param_types);
1434 return res;
1437 static LLVMTypeRef
1438 sig_to_llvm_sig (EmitContext *ctx, MonoMethodSignature *sig)
1440 return sig_to_llvm_sig_full (ctx, sig, NULL);
1444 * LLVMFunctionType1:
1446 * Create an LLVM function type from the arguments.
1448 static G_GNUC_UNUSED LLVMTypeRef
1449 LLVMFunctionType0 (LLVMTypeRef ReturnType,
1450 int IsVarArg)
1452 return LLVMFunctionType (ReturnType, NULL, 0, IsVarArg);
1456 * LLVMFunctionType1:
1458 * Create an LLVM function type from the arguments.
1460 static G_GNUC_UNUSED LLVMTypeRef
1461 LLVMFunctionType1 (LLVMTypeRef ReturnType,
1462 LLVMTypeRef ParamType1,
1463 int IsVarArg)
1465 LLVMTypeRef param_types [1];
1467 param_types [0] = ParamType1;
1469 return LLVMFunctionType (ReturnType, param_types, 1, IsVarArg);
1473 * LLVMFunctionType2:
1475 * Create an LLVM function type from the arguments.
1477 static G_GNUC_UNUSED LLVMTypeRef
1478 LLVMFunctionType2 (LLVMTypeRef ReturnType,
1479 LLVMTypeRef ParamType1,
1480 LLVMTypeRef ParamType2,
1481 int IsVarArg)
1483 LLVMTypeRef param_types [2];
1485 param_types [0] = ParamType1;
1486 param_types [1] = ParamType2;
1488 return LLVMFunctionType (ReturnType, param_types, 2, IsVarArg);
1492 * LLVMFunctionType3:
1494 * Create an LLVM function type from the arguments.
1496 static G_GNUC_UNUSED LLVMTypeRef
1497 LLVMFunctionType3 (LLVMTypeRef ReturnType,
1498 LLVMTypeRef ParamType1,
1499 LLVMTypeRef ParamType2,
1500 LLVMTypeRef ParamType3,
1501 int IsVarArg)
1503 LLVMTypeRef param_types [3];
1505 param_types [0] = ParamType1;
1506 param_types [1] = ParamType2;
1507 param_types [2] = ParamType3;
1509 return LLVMFunctionType (ReturnType, param_types, 3, IsVarArg);
1512 static G_GNUC_UNUSED LLVMTypeRef
1513 LLVMFunctionType5 (LLVMTypeRef ReturnType,
1514 LLVMTypeRef ParamType1,
1515 LLVMTypeRef ParamType2,
1516 LLVMTypeRef ParamType3,
1517 LLVMTypeRef ParamType4,
1518 LLVMTypeRef ParamType5,
1519 int IsVarArg)
1521 LLVMTypeRef param_types [5];
1523 param_types [0] = ParamType1;
1524 param_types [1] = ParamType2;
1525 param_types [2] = ParamType3;
1526 param_types [3] = ParamType4;
1527 param_types [4] = ParamType5;
1529 return LLVMFunctionType (ReturnType, param_types, 5, IsVarArg);
1533 * create_builder:
1535 * Create an LLVM builder and remember it so it can be freed later.
1537 static LLVMBuilderRef
1538 create_builder (EmitContext *ctx)
1540 LLVMBuilderRef builder = LLVMCreateBuilder ();
1542 ctx->builders = g_slist_prepend_mempool (ctx->cfg->mempool, ctx->builders, builder);
1544 return builder;
1547 static char*
1548 get_aotconst_name (MonoJumpInfoType type, gconstpointer data, int got_offset)
1550 char *name;
1552 switch (type) {
1553 case MONO_PATCH_INFO_INTERNAL_METHOD:
1554 name = g_strdup_printf ("jit_icall_%s", data);
1555 break;
1556 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1557 MonoJumpInfoRgctxEntry *entry = (MonoJumpInfoRgctxEntry*)data;
1558 name = g_strdup_printf ("RGCTX_SLOT_INDEX_%s", mono_rgctx_info_type_to_str (entry->info_type));
1559 break;
1561 default:
1562 name = g_strdup_printf ("%s_%d", mono_ji_type_to_string (type), got_offset);
1563 break;
1566 return name;
1569 static LLVMValueRef
1570 get_aotconst_typed (EmitContext *ctx, MonoJumpInfoType type, gconstpointer data, LLVMTypeRef llvm_type)
1572 MonoCompile *cfg;
1573 guint32 got_offset;
1574 LLVMValueRef indexes [2];
1575 LLVMValueRef got_entry_addr, load;
1576 LLVMBuilderRef builder = ctx->builder;
1577 char *name = NULL;
1579 cfg = ctx->cfg;
1581 MonoJumpInfo tmp_ji;
1582 tmp_ji.type = type;
1583 tmp_ji.data.target = data;
1585 MonoJumpInfo *ji = mono_aot_patch_info_dup (&tmp_ji);
1587 ji->next = cfg->patch_info;
1588 cfg->patch_info = ji;
1590 got_offset = mono_aot_get_got_offset (cfg->patch_info);
1591 ctx->module->max_got_offset = MAX (ctx->module->max_got_offset, got_offset);
1593 * If the got slot is shared, it means its initialized when the aot image is loaded, so we don't need to
1594 * explicitly initialize it.
1596 if (!mono_aot_is_shared_got_offset (got_offset)) {
1597 //mono_print_ji (ji);
1598 //printf ("\n");
1599 ctx->has_got_access = TRUE;
1602 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
1603 indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
1604 got_entry_addr = LLVMBuildGEP (builder, ctx->module->got_var, indexes, 2, "");
1606 name = get_aotconst_name (type, data, got_offset);
1607 if (llvm_type) {
1608 load = LLVMBuildLoad (builder, got_entry_addr, "");
1609 load = convert (ctx, load, llvm_type);
1610 LLVMSetValueName (load, name ? name : "");
1611 } else {
1612 load = LLVMBuildLoad (builder, got_entry_addr, name ? name : "");
1614 g_free (name);
1615 //set_invariant_load_flag (load);
1617 return load;
1620 static LLVMValueRef
1621 get_aotconst (EmitContext *ctx, MonoJumpInfoType type, gconstpointer data)
1623 return get_aotconst_typed (ctx, type, data, NULL);
1626 static LLVMValueRef
1627 get_callee (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gconstpointer data)
1629 LLVMValueRef callee;
1630 char *callee_name;
1631 if (ctx->llvm_only) {
1632 callee_name = mono_aot_get_direct_call_symbol (type, data);
1633 if (callee_name) {
1634 /* Directly callable */
1635 // FIXME: Locking
1636 callee = (LLVMValueRef)g_hash_table_lookup (ctx->module->direct_callables, callee_name);
1637 if (!callee) {
1638 callee = LLVMAddFunction (ctx->lmodule, callee_name, llvm_sig);
1640 LLVMSetVisibility (callee, LLVMHiddenVisibility);
1642 g_hash_table_insert (ctx->module->direct_callables, (char*)callee_name, callee);
1643 } else {
1644 /* LLVMTypeRef's are uniqued */
1645 if (LLVMGetElementType (LLVMTypeOf (callee)) != llvm_sig)
1646 return LLVMConstBitCast (callee, LLVMPointerType (llvm_sig, 0));
1648 g_free (callee_name);
1650 return callee;
1654 * Calls are made through the GOT.
1656 return get_aotconst_typed (ctx, type, data, LLVMPointerType (llvm_sig, 0));
1657 } else {
1658 MonoJumpInfo *ji = NULL;
1660 callee_name = mono_aot_get_plt_symbol (type, data);
1661 if (!callee_name)
1662 return NULL;
1664 if (ctx->cfg->compile_aot)
1665 /* Add a patch so referenced wrappers can be compiled in full aot mode */
1666 mono_add_patch_info (ctx->cfg, 0, type, data);
1668 // FIXME: Locking
1669 callee = (LLVMValueRef)g_hash_table_lookup (ctx->module->plt_entries, callee_name);
1670 if (!callee) {
1671 callee = LLVMAddFunction (ctx->lmodule, callee_name, llvm_sig);
1673 LLVMSetVisibility (callee, LLVMHiddenVisibility);
1675 g_hash_table_insert (ctx->module->plt_entries, (char*)callee_name, callee);
1678 if (ctx->cfg->compile_aot) {
1679 ji = g_new0 (MonoJumpInfo, 1);
1680 ji->type = type;
1681 ji->data.target = data;
1683 g_hash_table_insert (ctx->module->plt_entries_ji, ji, callee);
1686 return callee;
1690 static LLVMValueRef
1691 emit_jit_callee (EmitContext *ctx, const char *name, LLVMTypeRef llvm_sig, gpointer target)
1693 #if LLVM_API_VERSION > 100
1694 LLVMValueRef tramp_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (llvm_sig, 0), name);
1695 LLVMSetInitializer (tramp_var, LLVMConstIntToPtr (LLVMConstInt (LLVMInt64Type (), (guint64)(size_t)target, FALSE), LLVMPointerType (llvm_sig, 0)));
1696 LLVMSetLinkage (tramp_var, LLVMExternalLinkage);
1697 LLVMValueRef callee = LLVMBuildLoad (ctx->builder, tramp_var, "");
1698 return callee;
1699 #else
1700 LLVMValueRef callee = LLVMAddFunction (ctx->lmodule, "", llvm_sig);
1701 LLVMAddGlobalMapping (ctx->module->ee, callee, target);
1702 return callee;
1703 #endif
1706 static int
1707 get_handler_clause (MonoCompile *cfg, MonoBasicBlock *bb)
1709 MonoMethodHeader *header = cfg->header;
1710 MonoExceptionClause *clause;
1711 int i;
1713 /* Directly */
1714 if (bb->region != -1 && MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY))
1715 return (bb->region >> 8) - 1;
1717 /* Indirectly */
1718 for (i = 0; i < header->num_clauses; ++i) {
1719 clause = &header->clauses [i];
1721 if (MONO_OFFSET_IN_CLAUSE (clause, bb->real_offset) && clause->flags == MONO_EXCEPTION_CLAUSE_NONE)
1722 return i;
1725 return -1;
1728 static MonoExceptionClause *
1729 get_most_deep_clause (MonoCompile *cfg, EmitContext *ctx, MonoBasicBlock *bb)
1731 // Since they're sorted by nesting we just need
1732 // the first one that the bb is a member of
1733 for (int i = 0; i < cfg->header->num_clauses; i++) {
1734 MonoExceptionClause *curr = &cfg->header->clauses [i];
1736 if (MONO_OFFSET_IN_CLAUSE (curr, bb->real_offset))
1737 return curr;
1740 return NULL;
1743 static void
1744 set_metadata_flag (LLVMValueRef v, const char *flag_name)
1746 LLVMValueRef md_arg;
1747 int md_kind;
1749 md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
1750 md_arg = LLVMMDString ("mono", 4);
1751 LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
1754 static void
1755 set_invariant_load_flag (LLVMValueRef v)
1757 LLVMValueRef md_arg;
1758 int md_kind;
1759 const char *flag_name;
1761 // FIXME: Cache this
1762 flag_name = "invariant.load";
1763 md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
1764 md_arg = LLVMMDString ("<index>", strlen ("<index>"));
1765 LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
1769 * emit_call:
1771 * Emit an LLVM call or invoke instruction depending on whenever the call is inside
1772 * a try region.
1774 static LLVMValueRef
1775 emit_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, LLVMValueRef callee, LLVMValueRef *args, int pindex)
1777 MonoCompile *cfg = ctx->cfg;
1778 LLVMValueRef lcall = NULL;
1779 LLVMBuilderRef builder = *builder_ref;
1780 MonoExceptionClause *clause;
1782 if (ctx->llvm_only) {
1783 clause = get_most_deep_clause (cfg, ctx, bb);
1785 if (clause) {
1786 g_assert (clause->flags == MONO_EXCEPTION_CLAUSE_NONE || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY);
1789 * Have to use an invoke instead of a call, branching to the
1790 * handler bblock of the clause containing this bblock.
1792 intptr_t key = CLAUSE_END(clause);
1794 LLVMBasicBlockRef lpad_bb = (LLVMBasicBlockRef)g_hash_table_lookup (ctx->exc_meta, (gconstpointer)key);
1796 // FIXME: Find the one that has the lowest end bound for the right start address
1797 // FIXME: Finally + nesting
1799 if (lpad_bb) {
1800 LLVMBasicBlockRef noex_bb = gen_bb (ctx, "CALL_NOEX_BB");
1802 /* Use an invoke */
1803 lcall = LLVMBuildInvoke (builder, callee, args, pindex, noex_bb, lpad_bb, "");
1805 builder = ctx->builder = create_builder (ctx);
1806 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
1808 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
1811 } else {
1812 int clause_index = get_handler_clause (cfg, bb);
1814 if (clause_index != -1) {
1815 MonoMethodHeader *header = cfg->header;
1816 MonoExceptionClause *ec = &header->clauses [clause_index];
1817 MonoBasicBlock *tblock;
1818 LLVMBasicBlockRef ex_bb, noex_bb;
1821 * Have to use an invoke instead of a call, branching to the
1822 * handler bblock of the clause containing this bblock.
1825 g_assert (ec->flags == MONO_EXCEPTION_CLAUSE_NONE || ec->flags == MONO_EXCEPTION_CLAUSE_FINALLY);
1827 tblock = cfg->cil_offset_to_bb [ec->handler_offset];
1828 g_assert (tblock);
1830 ctx->bblocks [tblock->block_num].invoke_target = TRUE;
1832 ex_bb = get_bb (ctx, tblock);
1834 noex_bb = gen_bb (ctx, "NOEX_BB");
1836 /* Use an invoke */
1837 lcall = LLVMBuildInvoke (builder, callee, args, pindex, noex_bb, ex_bb, "");
1839 builder = ctx->builder = create_builder (ctx);
1840 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
1842 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
1846 if (!lcall) {
1847 lcall = LLVMBuildCall (builder, callee, args, pindex, "");
1848 ctx->builder = builder;
1851 if (builder_ref)
1852 *builder_ref = ctx->builder;
1854 return lcall;
1857 static LLVMValueRef
1858 emit_load_general (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef addr, LLVMValueRef base, const char *name, gboolean is_faulting, BarrierKind barrier)
1860 const char *intrins_name;
1861 LLVMValueRef args [16], res;
1862 LLVMTypeRef addr_type;
1863 gboolean use_intrinsics = TRUE;
1865 #if LLVM_API_VERSION > 100
1866 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only) {
1867 /* The llvm.mono.load/store intrinsics are not supported by this llvm version, emit an explicit null check instead */
1868 LLVMValueRef cmp;
1870 cmp = LLVMBuildICmp (*builder_ref, LLVMIntEQ, base, LLVMConstNull (LLVMTypeOf (base)), "");
1871 emit_cond_system_exception (ctx, bb, "NullReferenceException", cmp);
1872 *builder_ref = ctx->builder;
1873 use_intrinsics = FALSE;
1875 #endif
1877 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only && use_intrinsics) {
1878 LLVMAtomicOrdering ordering;
1880 switch (barrier) {
1881 case LLVM_BARRIER_NONE:
1882 ordering = LLVMAtomicOrderingNotAtomic;
1883 break;
1884 case LLVM_BARRIER_ACQ:
1885 ordering = LLVMAtomicOrderingAcquire;
1886 break;
1887 case LLVM_BARRIER_SEQ:
1888 ordering = LLVMAtomicOrderingSequentiallyConsistent;
1889 break;
1890 default:
1891 g_assert_not_reached ();
1892 break;
1896 * We handle loads which can fault by calling a mono specific intrinsic
1897 * using an invoke, so they are handled properly inside try blocks.
1898 * We can't use this outside clauses, since LLVM optimizes intrinsics which
1899 * are marked with IntrReadArgMem.
1901 switch (size) {
1902 case 1:
1903 intrins_name = "llvm.mono.load.i8.p0i8";
1904 break;
1905 case 2:
1906 intrins_name = "llvm.mono.load.i16.p0i16";
1907 break;
1908 case 4:
1909 intrins_name = "llvm.mono.load.i32.p0i32";
1910 break;
1911 case 8:
1912 intrins_name = "llvm.mono.load.i64.p0i64";
1913 break;
1914 default:
1915 g_assert_not_reached ();
1918 addr_type = LLVMTypeOf (addr);
1919 if (addr_type == LLVMPointerType (LLVMDoubleType (), 0) || addr_type == LLVMPointerType (LLVMFloatType (), 0))
1920 addr = LLVMBuildBitCast (*builder_ref, addr, LLVMPointerType (LLVMIntType (size * 8), 0), "");
1922 args [0] = addr;
1923 args [1] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
1924 args [2] = LLVMConstInt (LLVMInt1Type (), TRUE, FALSE);
1925 args [3] = LLVMConstInt (LLVMInt32Type (), ordering, FALSE);
1926 res = emit_call (ctx, bb, builder_ref, get_intrinsic (ctx, intrins_name), args, 4);
1928 if (addr_type == LLVMPointerType (LLVMDoubleType (), 0))
1929 res = LLVMBuildBitCast (*builder_ref, res, LLVMDoubleType (), "");
1930 else if (addr_type == LLVMPointerType (LLVMFloatType (), 0))
1931 res = LLVMBuildBitCast (*builder_ref, res, LLVMFloatType (), "");
1933 return res;
1934 } else {
1935 LLVMValueRef res;
1938 * We emit volatile loads for loads which can fault, because otherwise
1939 * LLVM will generate invalid code when encountering a load from a
1940 * NULL address.
1942 if (barrier != LLVM_BARRIER_NONE)
1943 res = mono_llvm_build_atomic_load (*builder_ref, addr, name, is_faulting, size, barrier);
1944 else
1945 res = mono_llvm_build_load (*builder_ref, addr, name, is_faulting);
1947 /* Mark it with a custom metadata */
1949 if (is_faulting)
1950 set_metadata_flag (res, "mono.faulting.load");
1953 return res;
1957 static LLVMValueRef
1958 emit_load (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef addr, const char *name, gboolean is_faulting)
1960 return emit_load_general (ctx, bb, builder_ref, size, addr, addr, name, is_faulting, LLVM_BARRIER_NONE);
1963 static void
1964 emit_store_general (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef value, LLVMValueRef addr, LLVMValueRef base, gboolean is_faulting, BarrierKind barrier)
1966 const char *intrins_name;
1967 LLVMValueRef args [16];
1968 gboolean use_intrinsics = TRUE;
1970 #if LLVM_API_VERSION > 100
1971 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only) {
1972 /* The llvm.mono.load/store intrinsics are not supported by this llvm version, emit an explicit null check instead */
1973 LLVMValueRef cmp = LLVMBuildICmp (*builder_ref, LLVMIntEQ, base, LLVMConstNull (LLVMTypeOf (base)), "");
1974 emit_cond_system_exception (ctx, bb, "NullReferenceException", cmp);
1975 *builder_ref = ctx->builder;
1976 use_intrinsics = FALSE;
1978 #endif
1980 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only && use_intrinsics) {
1981 LLVMAtomicOrdering ordering;
1983 switch (barrier) {
1984 case LLVM_BARRIER_NONE:
1985 ordering = LLVMAtomicOrderingNotAtomic;
1986 break;
1987 case LLVM_BARRIER_REL:
1988 ordering = LLVMAtomicOrderingRelease;
1989 break;
1990 case LLVM_BARRIER_SEQ:
1991 ordering = LLVMAtomicOrderingSequentiallyConsistent;
1992 break;
1993 default:
1994 g_assert_not_reached ();
1995 break;
1998 switch (size) {
1999 case 1:
2000 intrins_name = "llvm.mono.store.i8.p0i8";
2001 break;
2002 case 2:
2003 intrins_name = "llvm.mono.store.i16.p0i16";
2004 break;
2005 case 4:
2006 intrins_name = "llvm.mono.store.i32.p0i32";
2007 break;
2008 case 8:
2009 intrins_name = "llvm.mono.store.i64.p0i64";
2010 break;
2011 default:
2012 g_assert_not_reached ();
2015 if (LLVMTypeOf (value) == LLVMDoubleType () || LLVMTypeOf (value) == LLVMFloatType ()) {
2016 value = LLVMBuildBitCast (*builder_ref, value, LLVMIntType (size * 8), "");
2017 addr = LLVMBuildBitCast (*builder_ref, addr, LLVMPointerType (LLVMIntType (size * 8), 0), "");
2020 args [0] = value;
2021 args [1] = addr;
2022 args [2] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2023 args [3] = LLVMConstInt (LLVMInt1Type (), TRUE, FALSE);
2024 args [4] = LLVMConstInt (LLVMInt32Type (), ordering, FALSE);
2025 emit_call (ctx, bb, builder_ref, get_intrinsic (ctx, intrins_name), args, 5);
2026 } else {
2027 if (barrier != LLVM_BARRIER_NONE)
2028 mono_llvm_build_aligned_store (*builder_ref, value, addr, barrier, size);
2029 else
2030 mono_llvm_build_store (*builder_ref, value, addr, is_faulting, barrier);
2034 static void
2035 emit_store (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef value, LLVMValueRef addr, LLVMValueRef base, gboolean is_faulting)
2037 emit_store_general (ctx, bb, builder_ref, size, value, addr, base, is_faulting, LLVM_BARRIER_NONE);
2041 * emit_cond_system_exception:
2043 * Emit code to throw the exception EXC_TYPE if the condition CMP is false.
2044 * Might set the ctx exception.
2046 static void
2047 emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *exc_type, LLVMValueRef cmp)
2049 LLVMBasicBlockRef ex_bb, ex2_bb = NULL, noex_bb;
2050 LLVMBuilderRef builder;
2051 MonoClass *exc_class;
2052 LLVMValueRef args [2];
2053 LLVMValueRef callee;
2054 gboolean no_pc = FALSE;
2056 if (IS_TARGET_AMD64)
2057 /* Some platforms don't require the pc argument */
2058 no_pc = TRUE;
2060 ex_bb = gen_bb (ctx, "EX_BB");
2061 if (ctx->llvm_only)
2062 ex2_bb = gen_bb (ctx, "EX2_BB");
2063 noex_bb = gen_bb (ctx, "NOEX_BB");
2065 LLVMBuildCondBr (ctx->builder, cmp, ex_bb, noex_bb);
2067 exc_class = mono_class_load_from_name (mono_get_corlib (), "System", exc_type);
2069 /* Emit exception throwing code */
2070 ctx->builder = builder = create_builder (ctx);
2071 LLVMPositionBuilderAtEnd (builder, ex_bb);
2073 if (ctx->cfg->llvm_only) {
2074 static LLVMTypeRef sig;
2076 if (!sig)
2077 sig = LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE);
2078 callee = get_callee (ctx, sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_llvm_throw_corlib_exception");
2080 LLVMBuildBr (builder, ex2_bb);
2082 ctx->builder = builder = create_builder (ctx);
2083 LLVMPositionBuilderAtEnd (ctx->builder, ex2_bb);
2085 args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE);
2086 emit_call (ctx, bb, &builder, callee, args, 1);
2087 LLVMBuildUnreachable (builder);
2089 ctx->builder = builder = create_builder (ctx);
2090 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
2092 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
2094 ctx->ex_index ++;
2095 return;
2098 callee = ctx->module->throw_corlib_exception;
2099 if (!callee) {
2100 LLVMTypeRef sig;
2101 const char *icall_name;
2103 if (no_pc)
2104 sig = LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE);
2105 else
2106 sig = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), LLVMPointerType (LLVMInt8Type (), 0), FALSE);
2107 icall_name = "llvm_throw_corlib_exception_abs_trampoline";
2109 if (ctx->cfg->compile_aot) {
2110 callee = get_callee (ctx, sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
2111 } else {
2113 * Differences between the LLVM/non-LLVM throw corlib exception trampoline:
2114 * - On x86, LLVM generated code doesn't push the arguments
2115 * - The trampoline takes the throw address as an arguments, not a pc offset.
2117 gpointer target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
2118 callee = emit_jit_callee (ctx, "llvm_throw_corlib_exception_trampoline", sig, target);
2120 #if LLVM_API_VERSION > 100
2122 * Make sure that ex_bb starts with the invoke, so the block address points to it, and not to the load
2123 * added by emit_jit_callee ().
2125 ex2_bb = gen_bb (ctx, "EX2_BB");
2126 LLVMBuildBr (builder, ex2_bb);
2127 ex_bb = ex2_bb;
2129 ctx->builder = builder = create_builder (ctx);
2130 LLVMPositionBuilderAtEnd (ctx->builder, ex2_bb);
2131 #else
2132 mono_memory_barrier ();
2133 ctx->module->throw_corlib_exception = callee;
2134 #endif
2138 args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE);
2141 * The LLVM mono branch contains changes so a block address can be passed as an
2142 * argument to a call.
2144 if (no_pc) {
2145 emit_call (ctx, bb, &builder, callee, args, 1);
2146 } else {
2147 args [1] = LLVMBlockAddress (ctx->lmethod, ex_bb);
2148 emit_call (ctx, bb, &builder, callee, args, 2);
2151 LLVMBuildUnreachable (builder);
2153 ctx->builder = builder = create_builder (ctx);
2154 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
2156 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
2158 ctx->ex_index ++;
2159 return;
2163 * emit_args_to_vtype:
2165 * Emit code to store the vtype in the arguments args to the address ADDRESS.
2167 static void
2168 emit_args_to_vtype (EmitContext *ctx, LLVMBuilderRef builder, MonoType *t, LLVMValueRef address, LLVMArgInfo *ainfo, LLVMValueRef *args)
2170 int j, size, nslots;
2172 size = mono_class_value_size (mono_class_from_mono_type (t), NULL);
2174 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (t))) {
2175 address = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (LLVMInt8Type (), 0), "");
2178 if (ainfo->storage == LLVMArgAsFpArgs)
2179 nslots = ainfo->nslots;
2180 else
2181 nslots = 2;
2183 for (j = 0; j < nslots; ++j) {
2184 LLVMValueRef index [2], addr, daddr;
2185 int part_size = size > sizeof (gpointer) ? sizeof (gpointer) : size;
2186 LLVMTypeRef part_type;
2188 while (part_size != 1 && part_size != 2 && part_size != 4 && part_size < 8)
2189 part_size ++;
2191 if (ainfo->pair_storage [j] == LLVMArgNone)
2192 continue;
2194 switch (ainfo->pair_storage [j]) {
2195 case LLVMArgInIReg: {
2196 part_type = LLVMIntType (part_size * 8);
2197 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (t))) {
2198 index [0] = LLVMConstInt (LLVMInt32Type (), j * sizeof (gpointer), FALSE);
2199 addr = LLVMBuildGEP (builder, address, index, 1, "");
2200 } else {
2201 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (IntPtrType (), 0), "");
2202 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2203 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2205 LLVMBuildStore (builder, convert (ctx, args [j], part_type), LLVMBuildBitCast (ctx->builder, addr, LLVMPointerType (part_type, 0), ""));
2206 break;
2208 case LLVMArgInFPReg: {
2209 LLVMTypeRef arg_type;
2211 if (ainfo->esize == 8)
2212 arg_type = LLVMDoubleType ();
2213 else
2214 arg_type = LLVMFloatType ();
2216 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2217 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (arg_type, 0), "");
2218 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2219 LLVMBuildStore (builder, args [j], addr);
2220 break;
2222 case LLVMArgNone:
2223 break;
2224 default:
2225 g_assert_not_reached ();
2228 size -= sizeof (gpointer);
2233 * emit_vtype_to_args:
2235 * Emit code to load a vtype at address ADDRESS into scalar arguments. Store the arguments
2236 * into ARGS, and the number of arguments into NARGS.
2238 static void
2239 emit_vtype_to_args (EmitContext *ctx, LLVMBuilderRef builder, MonoType *t, LLVMValueRef address, LLVMArgInfo *ainfo, LLVMValueRef *args, guint32 *nargs)
2241 int pindex = 0;
2242 int j, size, nslots;
2243 LLVMTypeRef arg_type;
2245 size = get_vtype_size (t);
2247 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (t)))
2248 address = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (LLVMInt8Type (), 0), "");
2250 if (ainfo->storage == LLVMArgAsFpArgs)
2251 nslots = ainfo->nslots;
2252 else
2253 nslots = 2;
2254 for (j = 0; j < nslots; ++j) {
2255 LLVMValueRef index [2], addr, daddr;
2256 int partsize = size > sizeof (gpointer) ? sizeof (gpointer) : size;
2258 if (ainfo->pair_storage [j] == LLVMArgNone)
2259 continue;
2261 switch (ainfo->pair_storage [j]) {
2262 case LLVMArgInIReg:
2263 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (t))) {
2264 index [0] = LLVMConstInt (LLVMInt32Type (), j * sizeof (gpointer), FALSE);
2265 addr = LLVMBuildGEP (builder, address, index, 1, "");
2266 } else {
2267 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (IntPtrType (), 0), "");
2268 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2269 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2271 args [pindex ++] = convert (ctx, LLVMBuildLoad (builder, LLVMBuildBitCast (ctx->builder, addr, LLVMPointerType (LLVMIntType (partsize * 8), 0), ""), ""), IntPtrType ());
2272 break;
2273 case LLVMArgInFPReg:
2274 if (ainfo->esize == 8)
2275 arg_type = LLVMDoubleType ();
2276 else
2277 arg_type = LLVMFloatType ();
2278 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (arg_type, 0), "");
2279 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2280 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2281 args [pindex ++] = LLVMBuildLoad (builder, addr, "");
2282 break;
2283 case LLVMArgNone:
2284 break;
2285 default:
2286 g_assert_not_reached ();
2288 size -= sizeof (gpointer);
2291 *nargs = pindex;
2294 static LLVMValueRef
2295 build_alloca_llvm_type_name (EmitContext *ctx, LLVMTypeRef t, int align, const char *name)
2298 * Have to place all alloca's at the end of the entry bb, since otherwise they would
2299 * get executed every time control reaches them.
2301 LLVMPositionBuilder (ctx->alloca_builder, get_bb (ctx, ctx->cfg->bb_entry), ctx->last_alloca);
2303 ctx->last_alloca = mono_llvm_build_alloca (ctx->alloca_builder, t, NULL, align, name);
2304 return ctx->last_alloca;
2307 static LLVMValueRef
2308 build_alloca_llvm_type (EmitContext *ctx, LLVMTypeRef t, int align)
2310 return build_alloca_llvm_type_name (ctx, t, align, "");
2313 static LLVMValueRef
2314 build_alloca (EmitContext *ctx, MonoType *t)
2316 MonoClass *k = mono_class_from_mono_type (t);
2317 int align;
2319 g_assert (!mini_is_gsharedvt_variable_type (t));
2321 if (MONO_CLASS_IS_SIMD (ctx->cfg, k))
2322 align = 16;
2323 else
2324 align = mono_class_min_align (k);
2326 /* Sometimes align is not a power of 2 */
2327 while (mono_is_power_of_two (align) == -1)
2328 align ++;
2330 return build_alloca_llvm_type (ctx, type_to_llvm_type (ctx, t), align);
2333 static LLVMValueRef
2334 emit_gsharedvt_ldaddr (EmitContext *ctx, int vreg)
2337 * gsharedvt local.
2338 * Compute the address of the local as gsharedvt_locals_var + gsharedvt_info_var->locals_offsets [idx].
2340 MonoCompile *cfg = ctx->cfg;
2341 LLVMBuilderRef builder = ctx->builder;
2342 LLVMValueRef offset, offset_var;
2343 LLVMValueRef info_var = ctx->values [cfg->gsharedvt_info_var->dreg];
2344 LLVMValueRef locals_var = ctx->values [cfg->gsharedvt_locals_var->dreg];
2345 LLVMValueRef ptr;
2346 char *name;
2348 g_assert (info_var);
2349 g_assert (locals_var);
2351 int idx = cfg->gsharedvt_vreg_to_idx [vreg] - 1;
2353 offset = LLVMConstInt (LLVMInt32Type (), MONO_STRUCT_OFFSET (MonoGSharedVtMethodRuntimeInfo, entries) + (idx * sizeof (gpointer)), FALSE);
2354 ptr = LLVMBuildAdd (builder, convert (ctx, info_var, IntPtrType ()), convert (ctx, offset, IntPtrType ()), "");
2356 name = g_strdup_printf ("gsharedvt_local_%d_offset", vreg);
2357 offset_var = LLVMBuildLoad (builder, convert (ctx, ptr, LLVMPointerType (LLVMInt32Type (), 0)), name);
2359 return LLVMBuildAdd (builder, convert (ctx, locals_var, IntPtrType ()), convert (ctx, offset_var, IntPtrType ()), "");
2363 * Put the global into the 'llvm.used' array to prevent it from being optimized away.
2365 static void
2366 mark_as_used (MonoLLVMModule *module, LLVMValueRef global)
2368 if (!module->used)
2369 module->used = g_ptr_array_sized_new (16);
2370 g_ptr_array_add (module->used, global);
2373 static void
2374 emit_llvm_used (MonoLLVMModule *module)
2376 LLVMModuleRef lmodule = module->lmodule;
2377 LLVMTypeRef used_type;
2378 LLVMValueRef used, *used_elem;
2379 int i;
2381 if (!module->used)
2382 return;
2384 used_type = LLVMArrayType (LLVMPointerType (LLVMInt8Type (), 0), module->used->len);
2385 used = LLVMAddGlobal (lmodule, used_type, "llvm.used");
2386 used_elem = g_new0 (LLVMValueRef, module->used->len);
2387 for (i = 0; i < module->used->len; ++i)
2388 used_elem [i] = LLVMConstBitCast ((LLVMValueRef)g_ptr_array_index (module->used, i), LLVMPointerType (LLVMInt8Type (), 0));
2389 LLVMSetInitializer (used, LLVMConstArray (LLVMPointerType (LLVMInt8Type (), 0), used_elem, module->used->len));
2390 LLVMSetLinkage (used, LLVMAppendingLinkage);
2391 LLVMSetSection (used, "llvm.metadata");
2395 * emit_get_method:
2397 * Emit a function mapping method indexes to their code
2399 static void
2400 emit_get_method (MonoLLVMModule *module)
2402 LLVMModuleRef lmodule = module->lmodule;
2403 LLVMValueRef func, switch_ins, m;
2404 LLVMBasicBlockRef entry_bb, fail_bb, bb, code_start_bb, code_end_bb;
2405 LLVMBasicBlockRef *bbs;
2406 LLVMTypeRef rtype;
2407 LLVMBuilderRef builder = LLVMCreateBuilder ();
2408 char *name;
2409 int i;
2412 * Emit a switch statement. Emitting a table of function addresses is smaller/faster,
2413 * but generating code seems safer.
2415 rtype = LLVMPointerType (LLVMInt8Type (), 0);
2416 func = LLVMAddFunction (lmodule, module->get_method_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
2417 LLVMSetLinkage (func, LLVMExternalLinkage);
2418 LLVMSetVisibility (func, LLVMHiddenVisibility);
2419 LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
2420 module->get_method = func;
2422 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2425 * Return llvm_code_start/llvm_code_end when called with -1/-2.
2426 * Hopefully, the toolchain doesn't reorder these functions. If it does,
2427 * then we will have to find another solution.
2430 name = g_strdup_printf ("BB_CODE_START");
2431 code_start_bb = LLVMAppendBasicBlock (func, name);
2432 g_free (name);
2433 LLVMPositionBuilderAtEnd (builder, code_start_bb);
2434 LLVMBuildRet (builder, LLVMBuildBitCast (builder, module->code_start, rtype, ""));
2436 name = g_strdup_printf ("BB_CODE_END");
2437 code_end_bb = LLVMAppendBasicBlock (func, name);
2438 g_free (name);
2439 LLVMPositionBuilderAtEnd (builder, code_end_bb);
2440 LLVMBuildRet (builder, LLVMBuildBitCast (builder, module->code_end, rtype, ""));
2442 bbs = g_new0 (LLVMBasicBlockRef, module->max_method_idx + 1);
2443 for (i = 0; i < module->max_method_idx + 1; ++i) {
2444 name = g_strdup_printf ("BB_%d", i);
2445 bb = LLVMAppendBasicBlock (func, name);
2446 g_free (name);
2447 bbs [i] = bb;
2449 LLVMPositionBuilderAtEnd (builder, bb);
2451 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_lmethod, GINT_TO_POINTER (i));
2452 if (m)
2453 LLVMBuildRet (builder, LLVMBuildBitCast (builder, m, rtype, ""));
2454 else
2455 LLVMBuildRet (builder, LLVMConstNull (rtype));
2458 fail_bb = LLVMAppendBasicBlock (func, "FAIL");
2459 LLVMPositionBuilderAtEnd (builder, fail_bb);
2460 LLVMBuildRet (builder, LLVMConstNull (rtype));
2462 LLVMPositionBuilderAtEnd (builder, entry_bb);
2464 switch_ins = LLVMBuildSwitch (builder, LLVMGetParam (func, 0), fail_bb, 0);
2465 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), -1, FALSE), code_start_bb);
2466 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), -2, FALSE), code_end_bb);
2467 for (i = 0; i < module->max_method_idx + 1; ++i) {
2468 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i, FALSE), bbs [i]);
2471 mark_as_used (module, func);
2473 LLVMDisposeBuilder (builder);
2477 * emit_get_unbox_tramp:
2479 * Emit a function mapping method indexes to their unbox trampoline
2481 static void
2482 emit_get_unbox_tramp (MonoLLVMModule *module)
2484 LLVMModuleRef lmodule = module->lmodule;
2485 LLVMValueRef func, switch_ins, m;
2486 LLVMBasicBlockRef entry_bb, fail_bb, bb;
2487 LLVMBasicBlockRef *bbs;
2488 LLVMTypeRef rtype;
2489 LLVMBuilderRef builder = LLVMCreateBuilder ();
2490 char *name;
2491 int i;
2493 /* Similar to emit_get_method () */
2495 rtype = LLVMPointerType (LLVMInt8Type (), 0);
2496 func = LLVMAddFunction (lmodule, module->get_unbox_tramp_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
2497 LLVMSetLinkage (func, LLVMExternalLinkage);
2498 LLVMSetVisibility (func, LLVMHiddenVisibility);
2499 LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
2500 module->get_unbox_tramp = func;
2502 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2504 bbs = g_new0 (LLVMBasicBlockRef, module->max_method_idx + 1);
2505 for (i = 0; i < module->max_method_idx + 1; ++i) {
2506 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_unbox_tramp, GINT_TO_POINTER (i));
2507 if (!m)
2508 continue;
2510 name = g_strdup_printf ("BB_%d", i);
2511 bb = LLVMAppendBasicBlock (func, name);
2512 g_free (name);
2513 bbs [i] = bb;
2515 LLVMPositionBuilderAtEnd (builder, bb);
2517 LLVMBuildRet (builder, LLVMBuildBitCast (builder, m, rtype, ""));
2520 fail_bb = LLVMAppendBasicBlock (func, "FAIL");
2521 LLVMPositionBuilderAtEnd (builder, fail_bb);
2522 LLVMBuildRet (builder, LLVMConstNull (rtype));
2524 LLVMPositionBuilderAtEnd (builder, entry_bb);
2526 switch_ins = LLVMBuildSwitch (builder, LLVMGetParam (func, 0), fail_bb, 0);
2527 for (i = 0; i < module->max_method_idx + 1; ++i) {
2528 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_unbox_tramp, GINT_TO_POINTER (i));
2529 if (!m)
2530 continue;
2532 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i, FALSE), bbs [i]);
2535 mark_as_used (module, func);
2536 LLVMDisposeBuilder (builder);
2539 /* Add a function to mark the beginning of LLVM code */
2540 static void
2541 emit_llvm_code_start (MonoLLVMModule *module)
2543 LLVMModuleRef lmodule = module->lmodule;
2544 LLVMValueRef func;
2545 LLVMBasicBlockRef entry_bb;
2546 LLVMBuilderRef builder;
2548 func = LLVMAddFunction (lmodule, "llvm_code_start", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
2549 LLVMSetLinkage (func, LLVMInternalLinkage);
2550 LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
2551 module->code_start = func;
2552 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2553 builder = LLVMCreateBuilder ();
2554 LLVMPositionBuilderAtEnd (builder, entry_bb);
2555 LLVMBuildRetVoid (builder);
2556 LLVMDisposeBuilder (builder);
2559 static LLVMValueRef
2560 emit_init_icall_wrapper (MonoLLVMModule *module, const char *name, const char *icall_name, int subtype)
2562 LLVMModuleRef lmodule = module->lmodule;
2563 LLVMValueRef func, indexes [2], got_entry_addr, args [16], callee;
2564 LLVMBasicBlockRef entry_bb;
2565 LLVMBuilderRef builder;
2566 LLVMTypeRef sig;
2567 MonoJumpInfo *ji;
2568 int got_offset;
2570 switch (subtype) {
2571 case 0:
2572 func = LLVMAddFunction (lmodule, name, LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE));
2573 sig = LLVMFunctionType2 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), FALSE);
2574 break;
2575 case 1:
2576 case 3:
2577 /* mrgctx/vtable */
2578 func = LLVMAddFunction (lmodule, name, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), IntPtrType (), FALSE));
2579 sig = LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), IntPtrType (), FALSE);
2580 break;
2581 case 2:
2582 func = LLVMAddFunction (lmodule, name, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), ObjRefType (), FALSE));
2583 sig = LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), ObjRefType (), FALSE);
2584 break;
2585 default:
2586 g_assert_not_reached ();
2588 LLVMSetLinkage (func, LLVMInternalLinkage);
2589 LLVMAddFunctionAttr (func, LLVMNoInlineAttribute);
2590 mono_llvm_set_preserveall_cc (func);
2591 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2592 builder = LLVMCreateBuilder ();
2593 LLVMPositionBuilderAtEnd (builder, entry_bb);
2595 /* get_aotconst */
2596 ji = g_new0 (MonoJumpInfo, 1);
2597 ji->type = MONO_PATCH_INFO_AOT_MODULE;
2598 ji = mono_aot_patch_info_dup (ji);
2599 got_offset = mono_aot_get_got_offset (ji);
2600 module->max_got_offset = MAX (module->max_got_offset, got_offset);
2601 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2602 indexes [1] = LLVMConstInt (LLVMInt32Type (), got_offset, FALSE);
2603 got_entry_addr = LLVMBuildGEP (builder, module->got_var, indexes, 2, "");
2604 args [0] = LLVMBuildPtrToInt (builder, LLVMBuildLoad (builder, got_entry_addr, ""), IntPtrType (), "");
2605 args [1] = LLVMGetParam (func, 0);
2606 if (subtype)
2607 args [2] = LLVMGetParam (func, 1);
2609 ji = g_new0 (MonoJumpInfo, 1);
2610 ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
2611 ji->data.name = icall_name;
2612 ji = mono_aot_patch_info_dup (ji);
2613 got_offset = mono_aot_get_got_offset (ji);
2614 module->max_got_offset = MAX (module->max_got_offset, got_offset);
2615 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2616 indexes [1] = LLVMConstInt (LLVMInt32Type (), got_offset, FALSE);
2617 got_entry_addr = LLVMBuildGEP (builder, module->got_var, indexes, 2, "");
2618 callee = LLVMBuildLoad (builder, got_entry_addr, "");
2619 callee = LLVMBuildBitCast (builder, callee, LLVMPointerType (sig, 0), "");
2620 LLVMBuildCall (builder, callee, args, LLVMCountParamTypes (sig), "");
2622 // Set the inited flag
2623 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2624 indexes [1] = LLVMGetParam (func, 0);
2625 LLVMBuildStore (builder, LLVMConstInt (LLVMInt8Type (), 1, FALSE), LLVMBuildGEP (builder, module->inited_var, indexes, 2, ""));
2627 LLVMBuildRetVoid (builder);
2629 LLVMVerifyFunction(func, LLVMAbortProcessAction);
2630 LLVMDisposeBuilder (builder);
2631 return func;
2635 * Emit wrappers around the C icalls used to initialize llvm methods, to
2636 * make the calling code smaller and to enable usage of the llvm
2637 * PreserveAll calling convention.
2639 static void
2640 emit_init_icall_wrappers (MonoLLVMModule *module)
2642 module->init_method = emit_init_icall_wrapper (module, "init_method", "mono_aot_init_llvm_method", 0);
2643 module->init_method_gshared_mrgctx = emit_init_icall_wrapper (module, "init_method_gshared_mrgctx", "mono_aot_init_gshared_method_mrgctx", 1);
2644 module->init_method_gshared_this = emit_init_icall_wrapper (module, "init_method_gshared_this", "mono_aot_init_gshared_method_this", 2);
2645 module->init_method_gshared_vtable = emit_init_icall_wrapper (module, "init_method_gshared_vtable", "mono_aot_init_gshared_method_vtable", 3);
2648 static void
2649 emit_llvm_code_end (MonoLLVMModule *module)
2651 LLVMModuleRef lmodule = module->lmodule;
2652 LLVMValueRef func;
2653 LLVMBasicBlockRef entry_bb;
2654 LLVMBuilderRef builder;
2656 func = LLVMAddFunction (lmodule, "llvm_code_end", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
2657 LLVMSetLinkage (func, LLVMInternalLinkage);
2658 LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
2659 module->code_end = func;
2660 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2661 builder = LLVMCreateBuilder ();
2662 LLVMPositionBuilderAtEnd (builder, entry_bb);
2663 LLVMBuildRetVoid (builder);
2664 LLVMDisposeBuilder (builder);
2667 static void
2668 emit_div_check (EmitContext *ctx, LLVMBuilderRef builder, MonoBasicBlock *bb, MonoInst *ins, LLVMValueRef lhs, LLVMValueRef rhs)
2670 gboolean need_div_check = ctx->cfg->backend->need_div_check;
2672 if (bb->region)
2673 /* LLVM doesn't know that these can throw an exception since they are not called through an intrinsic */
2674 need_div_check = TRUE;
2676 if (!need_div_check)
2677 return;
2679 switch (ins->opcode) {
2680 case OP_IDIV:
2681 case OP_LDIV:
2682 case OP_IREM:
2683 case OP_LREM:
2684 case OP_IDIV_UN:
2685 case OP_LDIV_UN:
2686 case OP_IREM_UN:
2687 case OP_LREM_UN:
2688 case OP_IDIV_IMM:
2689 case OP_LDIV_IMM:
2690 case OP_IREM_IMM:
2691 case OP_LREM_IMM:
2692 case OP_IDIV_UN_IMM:
2693 case OP_LDIV_UN_IMM:
2694 case OP_IREM_UN_IMM:
2695 case OP_LREM_UN_IMM: {
2696 LLVMValueRef cmp;
2697 gboolean is_signed = (ins->opcode == OP_IDIV || ins->opcode == OP_LDIV || ins->opcode == OP_IREM || ins->opcode == OP_LREM ||
2698 ins->opcode == OP_IDIV_IMM || ins->opcode == OP_LDIV_IMM || ins->opcode == OP_IREM_IMM || ins->opcode == OP_LREM_IMM);
2700 cmp = LLVMBuildICmp (builder, LLVMIntEQ, rhs, LLVMConstInt (LLVMTypeOf (rhs), 0, FALSE), "");
2701 emit_cond_system_exception (ctx, bb, "DivideByZeroException", cmp);
2702 if (!ctx_ok (ctx))
2703 break;
2704 builder = ctx->builder;
2706 /* b == -1 && a == 0x80000000 */
2707 if (is_signed) {
2708 LLVMValueRef c = (LLVMTypeOf (lhs) == LLVMInt32Type ()) ? LLVMConstInt (LLVMTypeOf (lhs), 0x80000000, FALSE) : LLVMConstInt (LLVMTypeOf (lhs), 0x8000000000000000LL, FALSE);
2709 LLVMValueRef cond1 = LLVMBuildICmp (builder, LLVMIntEQ, rhs, LLVMConstInt (LLVMTypeOf (rhs), -1, FALSE), "");
2710 LLVMValueRef cond2 = LLVMBuildICmp (builder, LLVMIntEQ, lhs, c, "");
2712 cmp = LLVMBuildICmp (builder, LLVMIntEQ, LLVMBuildAnd (builder, cond1, cond2, ""), LLVMConstInt (LLVMInt1Type (), 1, FALSE), "");
2713 emit_cond_system_exception (ctx, bb, "OverflowException", cmp);
2714 if (!ctx_ok (ctx))
2715 break;
2716 builder = ctx->builder;
2718 break;
2720 default:
2721 break;
2726 * emit_init_method:
2728 * Emit code to initialize the GOT slots used by the method.
2730 static void
2731 emit_init_method (EmitContext *ctx)
2733 LLVMValueRef indexes [16], args [16], callee;
2734 LLVMValueRef inited_var, cmp, call;
2735 LLVMBasicBlockRef inited_bb, notinited_bb;
2736 LLVMBuilderRef builder = ctx->builder;
2737 MonoCompile *cfg = ctx->cfg;
2739 ctx->module->max_inited_idx = MAX (ctx->module->max_inited_idx, cfg->method_index);
2741 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2742 indexes [1] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, FALSE);
2743 inited_var = LLVMBuildLoad (builder, LLVMBuildGEP (builder, ctx->module->inited_var, indexes, 2, ""), "is_inited");
2745 args [0] = inited_var;
2746 args [1] = LLVMConstInt (LLVMInt8Type (), 1, FALSE);
2747 inited_var = LLVMBuildCall (ctx->builder, get_intrinsic (ctx, "llvm.expect.i8"), args, 2, "");
2749 cmp = LLVMBuildICmp (builder, LLVMIntEQ, inited_var, LLVMConstInt (LLVMTypeOf (inited_var), 0, FALSE), "");
2751 inited_bb = ctx->inited_bb;
2752 notinited_bb = gen_bb (ctx, "NOTINITED_BB");
2754 LLVMBuildCondBr (ctx->builder, cmp, notinited_bb, inited_bb);
2756 builder = ctx->builder = create_builder (ctx);
2757 LLVMPositionBuilderAtEnd (ctx->builder, notinited_bb);
2759 // FIXME: Cache
2760 if (ctx->rgctx_arg && cfg->method->is_inflated && mono_method_get_context (cfg->method)->method_inst) {
2761 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
2762 args [1] = convert (ctx, ctx->rgctx_arg, IntPtrType ());
2763 callee = ctx->module->init_method_gshared_mrgctx;
2764 call = LLVMBuildCall (builder, callee, args, 2, "");
2765 } else if (ctx->rgctx_arg) {
2766 /* A vtable is passed as the rgctx argument */
2767 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
2768 args [1] = convert (ctx, ctx->rgctx_arg, IntPtrType ());
2769 callee = ctx->module->init_method_gshared_vtable;
2770 call = LLVMBuildCall (builder, callee, args, 2, "");
2771 } else if (cfg->gshared) {
2772 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
2773 args [1] = convert (ctx, ctx->this_arg, ObjRefType ());
2774 callee = ctx->module->init_method_gshared_this;
2775 call = LLVMBuildCall (builder, callee, args, 2, "");
2776 } else {
2777 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
2778 callee = ctx->module->init_method;
2779 call = LLVMBuildCall (builder, callee, args, 1, "");
2783 * This enables llvm to keep arguments in their original registers/
2784 * scratch registers, since the call will not clobber them.
2786 mono_llvm_set_call_preserveall_cc (call);
2788 LLVMBuildBr (builder, inited_bb);
2789 ctx->bblocks [cfg->bb_entry->block_num].end_bblock = inited_bb;
2791 builder = ctx->builder = create_builder (ctx);
2792 LLVMPositionBuilderAtEnd (ctx->builder, inited_bb);
2795 static void
2796 emit_unbox_tramp (EmitContext *ctx, const char *method_name, LLVMTypeRef method_type, LLVMValueRef method, int method_index)
2799 * Emit unbox trampoline using a tail call
2801 LLVMValueRef tramp, call, *args;
2802 LLVMBuilderRef builder;
2803 LLVMBasicBlockRef lbb;
2804 LLVMCallInfo *linfo;
2805 char *tramp_name;
2806 int i, nargs;
2808 tramp_name = g_strdup_printf ("ut_%s", method_name);
2809 tramp = LLVMAddFunction (ctx->module->lmodule, tramp_name, method_type);
2810 LLVMSetLinkage (tramp, LLVMInternalLinkage);
2811 LLVMAddFunctionAttr (tramp, LLVMOptimizeForSizeAttribute);
2812 //LLVMAddFunctionAttr (tramp, LLVMNoUnwindAttribute);
2813 linfo = ctx->linfo;
2814 // FIXME: Reduce code duplication with mono_llvm_compile_method () etc.
2815 if (!ctx->llvm_only && ctx->rgctx_arg_pindex != -1)
2816 LLVMAddAttribute (LLVMGetParam (tramp, ctx->rgctx_arg_pindex), LLVMInRegAttribute);
2817 if (ctx->cfg->vret_addr) {
2818 LLVMSetValueName (LLVMGetParam (tramp, linfo->vret_arg_pindex), "vret");
2819 if (linfo->ret.storage == LLVMArgVtypeByRef) {
2820 LLVMAddAttribute (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVMStructRetAttribute);
2821 LLVMAddAttribute (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVMNoAliasAttribute);
2825 lbb = LLVMAppendBasicBlock (tramp, "");
2826 builder = LLVMCreateBuilder ();
2827 LLVMPositionBuilderAtEnd (builder, lbb);
2829 nargs = LLVMCountParamTypes (method_type);
2830 args = g_new0 (LLVMValueRef, nargs);
2831 for (i = 0; i < nargs; ++i) {
2832 args [i] = LLVMGetParam (tramp, i);
2833 if (i == ctx->this_arg_pindex) {
2834 LLVMTypeRef arg_type = LLVMTypeOf (args [i]);
2836 args [i] = LLVMBuildPtrToInt (builder, args [i], IntPtrType (), "");
2837 args [i] = LLVMBuildAdd (builder, args [i], LLVMConstInt (IntPtrType (), sizeof (MonoObject), FALSE), "");
2838 args [i] = LLVMBuildIntToPtr (builder, args [i], arg_type, "");
2841 call = LLVMBuildCall (builder, method, args, nargs, "");
2842 if (!ctx->llvm_only && ctx->rgctx_arg_pindex != -1)
2843 LLVMAddInstrAttribute (call, 1 + ctx->rgctx_arg_pindex, LLVMInRegAttribute);
2844 if (linfo->ret.storage == LLVMArgVtypeByRef)
2845 LLVMAddInstrAttribute (call, 1 + linfo->vret_arg_pindex, LLVMStructRetAttribute);
2847 // FIXME: This causes assertions in clang
2848 //mono_llvm_set_must_tail (call);
2849 if (LLVMGetReturnType (method_type) == LLVMVoidType ())
2850 LLVMBuildRetVoid (builder);
2851 else
2852 LLVMBuildRet (builder, call);
2854 g_hash_table_insert (ctx->module->idx_to_unbox_tramp, GINT_TO_POINTER (method_index), tramp);
2855 LLVMDisposeBuilder (builder);
2859 * emit_entry_bb:
2861 * Emit code to load/convert arguments.
2863 static void
2864 emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
2866 int i, j, pindex;
2867 MonoCompile *cfg = ctx->cfg;
2868 MonoMethodSignature *sig = ctx->sig;
2869 LLVMCallInfo *linfo = ctx->linfo;
2870 MonoBasicBlock *bb;
2871 char **names;
2873 LLVMBuilderRef old_builder = ctx->builder;
2874 ctx->builder = builder;
2876 ctx->alloca_builder = create_builder (ctx);
2879 * Handle indirect/volatile variables by allocating memory for them
2880 * using 'alloca', and storing their address in a temporary.
2882 for (i = 0; i < cfg->num_varinfo; ++i) {
2883 MonoInst *var = cfg->varinfo [i];
2884 LLVMTypeRef vtype;
2886 if (var->opcode == OP_GSHAREDVT_LOCAL || var->opcode == OP_GSHAREDVT_ARG_REGOFFSET) {
2887 } 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))) {
2888 vtype = type_to_llvm_type (ctx, var->inst_vtype);
2889 if (!ctx_ok (ctx))
2890 return;
2891 /* Could be already created by an OP_VPHI */
2892 if (!ctx->addresses [var->dreg]) {
2893 ctx->addresses [var->dreg] = build_alloca (ctx, var->inst_vtype);
2894 //LLVMSetValueName (ctx->addresses [var->dreg], g_strdup_printf ("vreg_loc_%d", var->dreg));
2896 ctx->vreg_cli_types [var->dreg] = var->inst_vtype;
2900 names = g_new (char *, sig->param_count);
2901 mono_method_get_param_names (cfg->method, (const char **) names);
2903 for (i = 0; i < sig->param_count; ++i) {
2904 LLVMArgInfo *ainfo = &linfo->args [i + sig->hasthis];
2905 int reg = cfg->args [i + sig->hasthis]->dreg;
2906 char *name;
2908 pindex = ainfo->pindex;
2910 switch (ainfo->storage) {
2911 case LLVMArgVtypeInReg:
2912 case LLVMArgAsFpArgs: {
2913 LLVMValueRef args [8];
2914 int j;
2916 pindex += ainfo->ndummy_fpargs;
2918 /* The argument is received as a set of int/fp arguments, store them into the real argument */
2919 memset (args, 0, sizeof (args));
2920 if (ainfo->storage == LLVMArgVtypeInReg) {
2921 args [0] = LLVMGetParam (ctx->lmethod, pindex);
2922 if (ainfo->pair_storage [1] != LLVMArgNone)
2923 args [1] = LLVMGetParam (ctx->lmethod, pindex + 1);
2924 } else {
2925 g_assert (ainfo->nslots <= 8);
2926 for (j = 0; j < ainfo->nslots; ++j)
2927 args [j] = LLVMGetParam (ctx->lmethod, pindex + j);
2929 ctx->addresses [reg] = build_alloca (ctx, ainfo->type);
2931 emit_args_to_vtype (ctx, builder, ainfo->type, ctx->addresses [reg], ainfo, args);
2933 if (ainfo->storage == LLVMArgVtypeInReg && MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (ainfo->type))) {
2934 /* Treat these as normal values */
2935 ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "");
2937 break;
2939 case LLVMArgVtypeByVal: {
2940 ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindex);
2942 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (ainfo->type))) {
2943 /* Treat these as normal values */
2944 ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "");
2946 break;
2948 case LLVMArgVtypeByRef: {
2949 /* The argument is passed by ref */
2950 ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindex);
2951 break;
2953 case LLVMArgAsIArgs: {
2954 LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
2955 int size;
2957 /* The argument is received as an array of ints, store it into the real argument */
2958 ctx->addresses [reg] = build_alloca (ctx, ainfo->type);
2960 size = mono_class_value_size (mono_class_from_mono_type (ainfo->type), NULL);
2961 if (size < SIZEOF_VOID_P) {
2962 /* The upper bits of the registers might not be valid */
2963 LLVMValueRef val = LLVMBuildExtractValue (builder, arg, 0, "");
2964 LLVMValueRef dest = convert (ctx, ctx->addresses [reg], LLVMPointerType (LLVMIntType (size * 8), 0));
2965 LLVMBuildStore (ctx->builder, LLVMBuildTrunc (builder, val, LLVMIntType (size * 8), ""), dest);
2966 } else {
2967 LLVMBuildStore (ctx->builder, arg, convert (ctx, ctx->addresses [reg], LLVMPointerType (LLVMTypeOf (arg), 0)));
2969 break;
2971 case LLVMArgVtypeAsScalar:
2972 g_assert_not_reached ();
2973 break;
2974 case LLVMArgGsharedvtFixed: {
2975 /* These are non-gsharedvt arguments passed by ref, the rest of the IR treats them as scalars */
2976 LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
2978 if (names [i])
2979 name = g_strdup_printf ("arg_%s", names [i]);
2980 else
2981 name = g_strdup_printf ("arg_%d", i);
2983 ctx->values [reg] = LLVMBuildLoad (builder, convert (ctx, arg, LLVMPointerType (type_to_llvm_type (ctx, ainfo->type), 0)), name);
2984 break;
2986 case LLVMArgGsharedvtFixedVtype: {
2987 LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
2989 if (names [i])
2990 name = g_strdup_printf ("vtype_arg_%s", names [i]);
2991 else
2992 name = g_strdup_printf ("vtype_arg_%d", i);
2994 /* Non-gsharedvt vtype argument passed by ref, the rest of the IR treats it as a vtype */
2995 g_assert (ctx->addresses [reg]);
2996 LLVMSetValueName (ctx->addresses [reg], name);
2997 LLVMBuildStore (builder, LLVMBuildLoad (builder, convert (ctx, arg, LLVMPointerType (type_to_llvm_type (ctx, ainfo->type), 0)), ""), ctx->addresses [reg]);
2998 break;
3000 case LLVMArgGsharedvtVariable:
3001 /* The IR treats these as variables with addresses */
3002 ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindex);
3003 break;
3004 default:
3005 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));
3006 break;
3009 g_free (names);
3011 if (cfg->vret_addr)
3012 emit_volatile_store (ctx, cfg->vret_addr->dreg);
3013 if (sig->hasthis)
3014 emit_volatile_store (ctx, cfg->args [0]->dreg);
3015 for (i = 0; i < sig->param_count; ++i)
3016 if (!mini_type_is_vtype (sig->params [i]))
3017 emit_volatile_store (ctx, cfg->args [i + sig->hasthis]->dreg);
3019 if (sig->hasthis && !cfg->rgctx_var && cfg->gshared) {
3020 LLVMValueRef this_alloc;
3023 * The exception handling code needs the location where the this argument was
3024 * stored for gshared methods. We create a separate alloca to hold it, and mark it
3025 * with the "mono.this" custom metadata to tell llvm that it needs to save its
3026 * location into the LSDA.
3028 this_alloc = mono_llvm_build_alloca (builder, ThisType (), LLVMConstInt (LLVMInt32Type (), 1, FALSE), 0, "");
3029 /* This volatile store will keep the alloca alive */
3030 mono_llvm_build_store (builder, ctx->values [cfg->args [0]->dreg], this_alloc, TRUE, LLVM_BARRIER_NONE);
3032 set_metadata_flag (this_alloc, "mono.this");
3035 if (cfg->rgctx_var) {
3036 LLVMValueRef rgctx_alloc, store;
3039 * We handle the rgctx arg similarly to the this pointer.
3041 g_assert (ctx->addresses [cfg->rgctx_var->dreg]);
3042 rgctx_alloc = ctx->addresses [cfg->rgctx_var->dreg];
3043 /* This volatile store will keep the alloca alive */
3044 store = mono_llvm_build_store (builder, convert (ctx, ctx->rgctx_arg, IntPtrType ()), rgctx_alloc, TRUE, LLVM_BARRIER_NONE);
3046 set_metadata_flag (rgctx_alloc, "mono.this");
3049 /* Initialize the method if needed */
3050 if (cfg->compile_aot && ctx->llvm_only) {
3051 /* Emit a location for the initialization code */
3052 ctx->init_bb = gen_bb (ctx, "INIT_BB");
3053 ctx->inited_bb = gen_bb (ctx, "INITED_BB");
3055 LLVMBuildBr (ctx->builder, ctx->init_bb);
3056 builder = ctx->builder = create_builder (ctx);
3057 LLVMPositionBuilderAtEnd (ctx->builder, ctx->inited_bb);
3058 ctx->bblocks [cfg->bb_entry->block_num].end_bblock = ctx->inited_bb;
3061 /* Compute nesting between clauses */
3062 ctx->nested_in = (GSList**)mono_mempool_alloc0 (cfg->mempool, sizeof (GSList*) * cfg->header->num_clauses);
3063 for (i = 0; i < cfg->header->num_clauses; ++i) {
3064 for (j = 0; j < cfg->header->num_clauses; ++j) {
3065 MonoExceptionClause *clause1 = &cfg->header->clauses [i];
3066 MonoExceptionClause *clause2 = &cfg->header->clauses [j];
3068 if (i != j && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset)
3069 ctx->nested_in [i] = g_slist_prepend_mempool (cfg->mempool, ctx->nested_in [i], GINT_TO_POINTER (j));
3074 * For finally clauses, create an indicator variable telling OP_ENDFINALLY whenever
3075 * it needs to continue normally, or return back to the exception handling system.
3077 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3078 int clause_index;
3079 char name [128];
3081 if (!(bb->region != -1 && (bb->flags & BB_EXCEPTION_HANDLER)))
3082 continue;
3084 clause_index = MONO_REGION_CLAUSE_INDEX (bb->region);
3085 g_hash_table_insert (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)), bb);
3086 g_hash_table_insert (ctx->clause_to_handler, GINT_TO_POINTER (clause_index), bb);
3088 if (bb->in_scount == 0) {
3089 LLVMValueRef val;
3091 sprintf (name, "finally_ind_bb%d", bb->block_num);
3092 val = LLVMBuildAlloca (builder, LLVMInt32Type (), name);
3093 LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), val);
3095 ctx->bblocks [bb->block_num].finally_ind = val;
3096 } else {
3097 /* Create a variable to hold the exception var */
3098 if (!ctx->ex_var)
3099 ctx->ex_var = LLVMBuildAlloca (builder, ObjRefType (), "exvar");
3103 * Create a new bblock which CALL_HANDLER/landing pads can branch to, because branching to the
3104 * LLVM bblock containing a landing pad causes problems for the
3105 * LLVM optimizer passes.
3107 sprintf (name, "BB%d_CALL_HANDLER_TARGET", bb->block_num);
3108 ctx->bblocks [bb->block_num].call_handler_target_bb = LLVMAppendBasicBlock (ctx->lmethod, name);
3110 ctx->builder = old_builder;
3113 static void
3114 process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, MonoInst *ins)
3116 MonoCompile *cfg = ctx->cfg;
3117 LLVMValueRef *values = ctx->values;
3118 LLVMValueRef *addresses = ctx->addresses;
3119 MonoCallInst *call = (MonoCallInst*)ins;
3120 MonoMethodSignature *sig = call->signature;
3121 LLVMValueRef callee = NULL, lcall;
3122 LLVMValueRef *args;
3123 LLVMCallInfo *cinfo;
3124 GSList *l;
3125 int i, len, nargs;
3126 gboolean vretaddr;
3127 LLVMTypeRef llvm_sig;
3128 gpointer target;
3129 gboolean is_virtual, calli, preserveall;
3130 LLVMBuilderRef builder = *builder_ref;
3132 if ((call->signature->call_convention != MONO_CALL_DEFAULT) && !((call->signature->call_convention == MONO_CALL_C) && ctx->llvm_only)) {
3133 set_failure (ctx, "non-default callconv");
3134 return;
3137 cinfo = call->cinfo;
3138 g_assert (cinfo);
3139 if (call->rgctx_arg_reg)
3140 cinfo->rgctx_arg = TRUE;
3141 if (call->imt_arg_reg)
3142 cinfo->imt_arg = TRUE;
3144 vretaddr = (cinfo->ret.storage == LLVMArgVtypeRetAddr || cinfo->ret.storage == LLVMArgVtypeByRef || cinfo->ret.storage == LLVMArgGsharedvtFixed || cinfo->ret.storage == LLVMArgGsharedvtVariable || cinfo->ret.storage == LLVMArgGsharedvtFixedVtype);
3146 llvm_sig = sig_to_llvm_sig_full (ctx, sig, cinfo);
3147 if (!ctx_ok (ctx))
3148 return;
3150 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);
3151 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);
3152 /* Unused */
3153 preserveall = FALSE;
3155 /* FIXME: Avoid creating duplicate methods */
3157 if (ins->flags & MONO_INST_HAS_METHOD) {
3158 if (is_virtual) {
3159 callee = NULL;
3160 } else {
3161 if (cfg->compile_aot) {
3162 callee = get_callee (ctx, llvm_sig, MONO_PATCH_INFO_METHOD, call->method);
3163 if (!callee) {
3164 set_failure (ctx, "can't encode patch");
3165 return;
3167 if (cfg->llvm_only && call->method->klass->image->assembly == ctx->module->assembly) {
3169 * Collect instructions representing the callee into a hash so they can be replaced
3170 * by the llvm method for the callee if the callee turns out to be direct
3171 * callable. Currently this only requires it to not fail llvm compilation.
3173 GSList *l = (GSList*)g_hash_table_lookup (ctx->method_to_callers, call->method);
3174 l = g_slist_prepend (l, callee);
3175 g_hash_table_insert (ctx->method_to_callers, call->method, l);
3177 } else {
3178 MonoError error;
3179 static int tramp_index;
3180 char *name;
3182 name = g_strdup_printf ("tramp_%d", tramp_index);
3183 tramp_index ++;
3185 #if LLVM_API_VERSION > 100
3187 * Use our trampoline infrastructure for lazy compilation instead of llvm's.
3188 * Make all calls through a global. The address of the global will be saved in
3189 * MonoJitDomainInfo.llvm_jit_callees and updated when the method it refers to is
3190 * compiled.
3192 LLVMValueRef tramp_var = g_hash_table_lookup (ctx->jit_callees, call->method);
3193 if (!tramp_var) {
3194 target =
3195 mono_create_jit_trampoline (mono_domain_get (),
3196 call->method, &error);
3197 if (!is_ok (&error)) {
3198 set_failure (ctx, mono_error_get_message (&error));
3199 mono_error_cleanup (&error);
3200 return;
3203 tramp_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (llvm_sig, 0), name);
3204 LLVMSetInitializer (tramp_var, LLVMConstIntToPtr (LLVMConstInt (LLVMInt64Type (), (guint64)(size_t)target, FALSE), LLVMPointerType (llvm_sig, 0)));
3205 LLVMSetLinkage (tramp_var, LLVMExternalLinkage);
3206 g_hash_table_insert (ctx->jit_callees, call->method, tramp_var);
3208 callee = LLVMBuildLoad (builder, tramp_var, "");
3209 #else
3210 target =
3211 mono_create_jit_trampoline (mono_domain_get (),
3212 call->method, &error);
3213 if (!is_ok (&error)) {
3214 g_free (name);
3215 set_failure (ctx, mono_error_get_message (&error));
3216 mono_error_cleanup (&error);
3217 return;
3220 callee = LLVMAddFunction (ctx->lmodule, name, llvm_sig);
3221 g_free (name);
3223 LLVMAddGlobalMapping (ctx->module->ee, callee, target);
3224 #endif
3228 if (!cfg->llvm_only && call->method && strstr (call->method->klass->name, "AsyncVoidMethodBuilder")) {
3229 /* LLVM miscompiles async methods */
3230 set_failure (ctx, "#13734");
3231 return;
3233 } else if (calli) {
3234 } else {
3235 MonoJitICallInfo *info = mono_find_jit_icall_by_addr (call->fptr);
3237 if (info) {
3239 MonoJumpInfo ji;
3241 memset (&ji, 0, sizeof (ji));
3242 ji.type = MONO_PATCH_INFO_JIT_ICALL_ADDR;
3243 ji.data.target = info->name;
3245 target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, &ji, FALSE);
3247 if (cfg->compile_aot) {
3248 callee = get_callee (ctx, llvm_sig, MONO_PATCH_INFO_INTERNAL_METHOD, (char*)info->name);
3249 if (!callee) {
3250 set_failure (ctx, "can't encode patch");
3251 return;
3253 } else {
3254 target = (gpointer)mono_icall_get_wrapper (info);
3255 callee = emit_jit_callee (ctx, "", llvm_sig, target);
3257 } else {
3258 if (cfg->compile_aot) {
3259 callee = NULL;
3260 if (cfg->abs_patches) {
3261 MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
3262 if (abs_ji) {
3263 callee = get_callee (ctx, llvm_sig, abs_ji->type, abs_ji->data.target);
3264 if (!callee) {
3265 set_failure (ctx, "can't encode patch");
3266 return;
3270 if (!callee) {
3271 set_failure (ctx, "aot");
3272 return;
3274 } else {
3275 #if LLVM_API_VERSION > 100
3276 if (cfg->abs_patches) {
3277 MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
3278 if (abs_ji) {
3279 MonoError error;
3281 target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, abs_ji, FALSE, &error);
3282 mono_error_assert_ok (&error);
3283 callee = emit_jit_callee (ctx, "", llvm_sig, target);
3284 } else {
3285 g_assert_not_reached ();
3287 } else {
3288 g_assert_not_reached ();
3290 #else
3291 callee = LLVMAddFunction (ctx->lmodule, "", llvm_sig);
3292 target = NULL;
3293 if (cfg->abs_patches) {
3294 MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
3295 if (abs_ji) {
3296 MonoError error;
3299 * FIXME: Some trampolines might have
3300 * their own calling convention on some platforms.
3302 target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, abs_ji, FALSE, &error);
3303 mono_error_assert_ok (&error);
3304 LLVMAddGlobalMapping (ctx->module->ee, callee, target);
3307 if (!target)
3308 LLVMAddGlobalMapping (ctx->module->ee, callee, (gpointer)call->fptr);
3309 #endif
3314 if (is_virtual) {
3315 int size = sizeof (gpointer);
3316 LLVMValueRef index;
3318 g_assert (ins->inst_offset % size == 0);
3319 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
3321 callee = convert (ctx, LLVMBuildLoad (builder, LLVMBuildGEP (builder, convert (ctx, values [ins->inst_basereg], LLVMPointerType (LLVMPointerType (IntPtrType (), 0), 0)), &index, 1, ""), ""), LLVMPointerType (llvm_sig, 0));
3322 } else if (calli) {
3323 callee = convert (ctx, values [ins->sreg1], LLVMPointerType (llvm_sig, 0));
3324 } else {
3325 if (ins->flags & MONO_INST_HAS_METHOD) {
3330 * Collect and convert arguments
3332 nargs = (sig->param_count * 16) + sig->hasthis + vretaddr + call->rgctx_reg + call->imt_arg_reg;
3333 len = sizeof (LLVMValueRef) * nargs;
3334 args = (LLVMValueRef*)alloca (len);
3335 memset (args, 0, len);
3336 l = call->out_ireg_args;
3338 if (call->rgctx_arg_reg) {
3339 g_assert (values [call->rgctx_arg_reg]);
3340 g_assert (cinfo->rgctx_arg_pindex < nargs);
3342 * On ARM, the imt/rgctx argument is passed in a caller save register, but some of our trampolines etc. clobber it, leading to
3343 * problems is LLVM moves the arg assignment earlier. To work around this, save the argument into a stack slot and load
3344 * it using a volatile load.
3346 #ifdef TARGET_ARM
3347 if (!ctx->imt_rgctx_loc)
3348 ctx->imt_rgctx_loc = build_alloca_llvm_type (ctx, ctx->module->ptr_type, sizeof (gpointer));
3349 LLVMBuildStore (builder, convert (ctx, ctx->values [call->rgctx_arg_reg], ctx->module->ptr_type), ctx->imt_rgctx_loc);
3350 args [cinfo->rgctx_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE);
3351 #else
3352 args [cinfo->rgctx_arg_pindex] = convert (ctx, values [call->rgctx_arg_reg], ctx->module->ptr_type);
3353 #endif
3355 if (call->imt_arg_reg) {
3356 g_assert (!ctx->llvm_only);
3357 g_assert (values [call->imt_arg_reg]);
3358 g_assert (cinfo->imt_arg_pindex < nargs);
3359 #ifdef TARGET_ARM
3360 if (!ctx->imt_rgctx_loc)
3361 ctx->imt_rgctx_loc = build_alloca_llvm_type (ctx, ctx->module->ptr_type, sizeof (gpointer));
3362 LLVMBuildStore (builder, convert (ctx, ctx->values [call->imt_arg_reg], ctx->module->ptr_type), ctx->imt_rgctx_loc);
3363 args [cinfo->imt_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE);
3364 #else
3365 args [cinfo->imt_arg_pindex] = convert (ctx, values [call->imt_arg_reg], ctx->module->ptr_type);
3366 #endif
3368 switch (cinfo->ret.storage) {
3369 case LLVMArgGsharedvtVariable: {
3370 MonoInst *var = get_vreg_to_inst (cfg, call->inst.dreg);
3372 if (var && var->opcode == OP_GSHAREDVT_LOCAL) {
3373 args [cinfo->vret_arg_pindex] = convert (ctx, emit_gsharedvt_ldaddr (ctx, var->dreg), IntPtrType ());
3374 } else {
3375 g_assert (addresses [call->inst.dreg]);
3376 args [cinfo->vret_arg_pindex] = addresses [call->inst.dreg];
3378 break;
3380 default:
3381 if (vretaddr) {
3382 if (!addresses [call->inst.dreg])
3383 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3384 g_assert (cinfo->vret_arg_pindex < nargs);
3385 if (cinfo->ret.storage == LLVMArgVtypeByRef)
3386 args [cinfo->vret_arg_pindex] = addresses [call->inst.dreg];
3387 else
3388 args [cinfo->vret_arg_pindex] = LLVMBuildPtrToInt (builder, addresses [call->inst.dreg], IntPtrType (), "");
3390 break;
3394 * Sometimes the same method is called with two different signatures (i.e. with and without 'this'), so
3395 * use the real callee for argument type conversion.
3397 LLVMTypeRef callee_type = LLVMGetElementType (LLVMTypeOf (callee));
3398 LLVMTypeRef *param_types = (LLVMTypeRef*)g_alloca (sizeof (LLVMTypeRef) * LLVMCountParamTypes (callee_type));
3399 LLVMGetParamTypes (callee_type, param_types);
3401 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
3402 guint32 regpair;
3403 int reg, pindex;
3404 LLVMArgInfo *ainfo = &call->cinfo->args [i];
3406 pindex = ainfo->pindex;
3408 regpair = (guint32)(gssize)(l->data);
3409 reg = regpair & 0xffffff;
3410 args [pindex] = values [reg];
3411 switch (ainfo->storage) {
3412 case LLVMArgVtypeInReg:
3413 case LLVMArgAsFpArgs: {
3414 guint32 nargs;
3415 int j;
3417 for (j = 0; j < ainfo->ndummy_fpargs; ++j)
3418 args [pindex + j] = LLVMConstNull (LLVMDoubleType ());
3419 pindex += ainfo->ndummy_fpargs;
3421 g_assert (addresses [reg]);
3422 emit_vtype_to_args (ctx, builder, ainfo->type, addresses [reg], ainfo, args + pindex, &nargs);
3423 pindex += nargs;
3425 // FIXME: alignment
3426 // FIXME: Get rid of the VMOVE
3427 break;
3429 case LLVMArgVtypeByVal:
3430 g_assert (addresses [reg]);
3431 args [pindex] = addresses [reg];
3432 break;
3433 case LLVMArgVtypeByRef: {
3434 g_assert (addresses [reg]);
3435 args [pindex] = convert (ctx, addresses [reg], LLVMPointerType (type_to_llvm_arg_type (ctx, ainfo->type), 0));
3436 break;
3438 case LLVMArgAsIArgs:
3439 g_assert (addresses [reg]);
3440 args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo->nslots), 0)), "");
3441 break;
3442 case LLVMArgVtypeAsScalar:
3443 g_assert_not_reached ();
3444 break;
3445 case LLVMArgGsharedvtFixed:
3446 case LLVMArgGsharedvtFixedVtype:
3447 g_assert (addresses [reg]);
3448 args [pindex] = convert (ctx, addresses [reg], LLVMPointerType (type_to_llvm_arg_type (ctx, ainfo->type), 0));
3449 break;
3450 case LLVMArgGsharedvtVariable:
3451 g_assert (addresses [reg]);
3452 args [pindex] = convert (ctx, addresses [reg], LLVMPointerType (IntPtrType (), 0));
3453 break;
3454 default:
3455 g_assert (args [pindex]);
3456 if (i == 0 && sig->hasthis)
3457 args [pindex] = convert (ctx, args [pindex], param_types [pindex]);
3458 else
3459 args [pindex] = convert (ctx, args [pindex], type_to_llvm_arg_type (ctx, ainfo->type));
3460 break;
3462 g_assert (pindex <= nargs);
3464 l = l->next;
3467 // FIXME: Align call sites
3470 * Emit the call
3473 lcall = emit_call (ctx, bb, &builder, callee, args, LLVMCountParamTypes (llvm_sig));
3476 * Modify cconv and parameter attributes to pass rgctx/imt correctly.
3478 #if defined(MONO_ARCH_IMT_REG) && defined(MONO_ARCH_RGCTX_REG)
3479 g_assert (MONO_ARCH_IMT_REG == MONO_ARCH_RGCTX_REG);
3480 #endif
3481 /* The two can't be used together, so use only one LLVM calling conv to pass them */
3482 g_assert (!(call->rgctx_arg_reg && call->imt_arg_reg));
3483 if (!sig->pinvoke && !cfg->llvm_only)
3484 LLVMSetInstructionCallConv (lcall, LLVMMono1CallConv);
3485 if (preserveall)
3486 mono_llvm_set_call_preserveall_cc (lcall);
3488 if (cinfo->ret.storage == LLVMArgVtypeByRef)
3489 LLVMAddInstrAttribute (lcall, 1 + cinfo->vret_arg_pindex, LLVMStructRetAttribute);
3490 if (!ctx->llvm_only && call->rgctx_arg_reg)
3491 LLVMAddInstrAttribute (lcall, 1 + cinfo->rgctx_arg_pindex, LLVMInRegAttribute);
3492 if (call->imt_arg_reg)
3493 LLVMAddInstrAttribute (lcall, 1 + cinfo->imt_arg_pindex, LLVMInRegAttribute);
3495 /* Add byval attributes if needed */
3496 for (i = 0; i < sig->param_count; ++i) {
3497 LLVMArgInfo *ainfo = &call->cinfo->args [i + sig->hasthis];
3499 if (ainfo && ainfo->storage == LLVMArgVtypeByVal)
3500 LLVMAddInstrAttribute (lcall, 1 + ainfo->pindex, LLVMByValAttribute);
3504 * Convert the result
3506 switch (cinfo->ret.storage) {
3507 case LLVMArgVtypeInReg: {
3508 LLVMValueRef regs [2];
3510 if (LLVMTypeOf (lcall) == LLVMVoidType ())
3511 /* Empty struct */
3512 break;
3514 if (!addresses [ins->dreg])
3515 addresses [ins->dreg] = build_alloca (ctx, sig->ret);
3517 regs [0] = LLVMBuildExtractValue (builder, lcall, 0, "");
3518 if (cinfo->ret.pair_storage [1] != LLVMArgNone)
3519 regs [1] = LLVMBuildExtractValue (builder, lcall, 1, "");
3520 emit_args_to_vtype (ctx, builder, sig->ret, addresses [ins->dreg], &cinfo->ret, regs);
3521 break;
3523 case LLVMArgVtypeByVal:
3524 if (!addresses [call->inst.dreg])
3525 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3526 LLVMBuildStore (builder, lcall, addresses [call->inst.dreg]);
3527 break;
3528 case LLVMArgAsIArgs:
3529 case LLVMArgFpStruct:
3530 if (!addresses [call->inst.dreg])
3531 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3532 LLVMBuildStore (builder, lcall, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (LLVMTypeOf (lcall), 0), FALSE));
3533 break;
3534 case LLVMArgVtypeAsScalar:
3535 if (!addresses [call->inst.dreg])
3536 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3537 LLVMBuildStore (builder, lcall, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (LLVMTypeOf (lcall), 0), FALSE));
3538 break;
3539 case LLVMArgVtypeRetAddr:
3540 case LLVMArgVtypeByRef:
3541 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (sig->ret))) {
3542 /* Some opcodes like STOREX_MEMBASE access these by value */
3543 g_assert (addresses [call->inst.dreg]);
3544 values [ins->dreg] = LLVMBuildLoad (builder, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (type_to_llvm_type (ctx, sig->ret), 0), FALSE), "");
3546 break;
3547 case LLVMArgGsharedvtVariable:
3548 break;
3549 case LLVMArgGsharedvtFixed:
3550 case LLVMArgGsharedvtFixedVtype:
3551 values [ins->dreg] = LLVMBuildLoad (builder, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (type_to_llvm_type (ctx, sig->ret), 0), FALSE), "");
3552 break;
3553 default:
3554 if (sig->ret->type != MONO_TYPE_VOID)
3555 /* If the method returns an unsigned value, need to zext it */
3556 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));
3557 break;
3560 *builder_ref = ctx->builder;
3563 static void
3564 emit_llvmonly_throw (EmitContext *ctx, MonoBasicBlock *bb, gboolean rethrow, LLVMValueRef exc)
3566 const char *icall_name = rethrow ? "mono_llvm_rethrow_exception" : "mono_llvm_throw_exception";
3567 LLVMValueRef callee = rethrow ? ctx->module->rethrow : ctx->module->throw_icall;
3569 LLVMTypeRef exc_type = type_to_llvm_type (ctx, &mono_get_exception_class ()->byval_arg);
3571 if (!callee) {
3572 LLVMTypeRef fun_sig = LLVMFunctionType1 (LLVMVoidType (), exc_type, FALSE);
3574 if (ctx->cfg->compile_aot) {
3575 callee = get_callee (ctx, fun_sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, icall_name);
3576 } else {
3577 callee = LLVMAddFunction (ctx->lmodule, icall_name, fun_sig);
3578 LLVMAddGlobalMapping (ctx->module->ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
3579 mono_memory_barrier ();
3581 if (rethrow)
3582 ctx->module->rethrow = callee;
3583 else
3584 ctx->module->throw_icall = callee;
3588 LLVMValueRef args [2];
3590 args [0] = convert (ctx, exc, exc_type);
3591 emit_call (ctx, bb, &ctx->builder, callee, args, 1);
3593 LLVMBuildUnreachable (ctx->builder);
3595 ctx->builder = create_builder (ctx);
3598 static void
3599 emit_throw (EmitContext *ctx, MonoBasicBlock *bb, gboolean rethrow, LLVMValueRef exc)
3601 MonoMethodSignature *throw_sig;
3602 LLVMValueRef callee, arg;
3603 const char *icall_name;
3605 callee = rethrow ? ctx->module->rethrow : ctx->module->throw_icall;
3606 icall_name = rethrow ? "mono_arch_rethrow_exception" : "mono_arch_throw_exception";
3608 if (!callee) {
3609 throw_sig = mono_metadata_signature_alloc (mono_get_corlib (), 1);
3610 throw_sig->ret = &mono_get_void_class ()->byval_arg;
3611 throw_sig->params [0] = &mono_get_object_class ()->byval_arg;
3612 if (ctx->cfg->compile_aot) {
3613 callee = get_callee (ctx, sig_to_llvm_sig (ctx, throw_sig), MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3614 } else {
3615 gpointer target;
3616 #ifdef TARGET_X86
3618 * LLVM doesn't push the exception argument, so we need a different
3619 * trampoline.
3621 target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, rethrow ? "llvm_rethrow_exception_trampoline" : "llvm_throw_exception_trampoline");
3622 #else
3623 target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3624 #endif
3625 callee = emit_jit_callee (ctx, icall_name, sig_to_llvm_sig (ctx, throw_sig), target);
3628 mono_memory_barrier ();
3629 #if LLVM_API_VERSION < 100
3630 if (rethrow)
3631 ctx->module->rethrow = callee;
3632 else
3633 ctx->module->throw_icall = callee;
3634 #endif
3636 arg = convert (ctx, exc, type_to_llvm_type (ctx, &mono_get_object_class ()->byval_arg));
3637 emit_call (ctx, bb, &ctx->builder, callee, &arg, 1);
3640 static void
3641 emit_resume_eh (EmitContext *ctx, MonoBasicBlock *bb)
3643 const char *icall_name = "mono_llvm_resume_exception";
3644 LLVMValueRef callee = ctx->module->resume_eh;
3646 LLVMTypeRef fun_sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
3648 if (!callee) {
3649 if (ctx->cfg->compile_aot) {
3650 callee = get_callee (ctx, fun_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3651 } else {
3652 callee = LLVMAddFunction (ctx->lmodule, icall_name, fun_sig);
3653 LLVMAddGlobalMapping (ctx->module->ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
3654 mono_memory_barrier ();
3656 ctx->module->resume_eh = callee;
3660 emit_call (ctx, bb, &ctx->builder, callee, NULL, 0);
3662 LLVMBuildUnreachable (ctx->builder);
3664 ctx->builder = create_builder (ctx);
3667 static LLVMValueRef
3668 mono_llvm_emit_clear_exception_call (EmitContext *ctx, LLVMBuilderRef builder)
3670 const char *icall_name = "mono_llvm_clear_exception";
3672 LLVMTypeRef call_sig = LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE);
3673 LLVMValueRef callee = NULL;
3675 if (!callee) {
3676 if (ctx->cfg->compile_aot) {
3677 callee = get_callee (ctx, call_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3678 } else {
3679 // FIXME: This is broken.
3680 callee = LLVMAddFunction (ctx->lmodule, icall_name, call_sig);
3684 g_assert (builder && callee);
3686 return LLVMBuildCall (builder, callee, NULL, 0, "");
3689 static LLVMValueRef
3690 mono_llvm_emit_load_exception_call (EmitContext *ctx, LLVMBuilderRef builder)
3692 const char *icall_name = "mono_llvm_load_exception";
3694 LLVMTypeRef call_sig = LLVMFunctionType (ObjRefType (), NULL, 0, FALSE);
3695 LLVMValueRef callee = NULL;
3697 if (!callee) {
3698 if (ctx->cfg->compile_aot) {
3699 callee = get_callee (ctx, call_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3700 } else {
3701 // FIXME: This is broken.
3702 callee = LLVMAddFunction (ctx->lmodule, icall_name, call_sig);
3706 g_assert (builder && callee);
3708 return LLVMBuildCall (builder, callee, NULL, 0, icall_name);
3712 static LLVMValueRef
3713 mono_llvm_emit_match_exception_call (EmitContext *ctx, LLVMBuilderRef builder, gint32 region_start, gint32 region_end)
3715 const char *icall_name = "mono_llvm_match_exception";
3717 ctx->builder = builder;
3719 const int num_args = 5;
3720 LLVMValueRef args [num_args];
3721 args [0] = convert (ctx, get_aotconst (ctx, MONO_PATCH_INFO_AOT_JIT_INFO, GINT_TO_POINTER (ctx->cfg->method_index)), IntPtrType ());
3722 args [1] = LLVMConstInt (LLVMInt32Type (), region_start, 0);
3723 args [2] = LLVMConstInt (LLVMInt32Type (), region_end, 0);
3724 if (ctx->cfg->rgctx_var) {
3725 LLVMValueRef rgctx_alloc = ctx->addresses [ctx->cfg->rgctx_var->dreg];
3726 g_assert (rgctx_alloc);
3727 args [3] = LLVMBuildLoad (builder, convert (ctx, rgctx_alloc, LLVMPointerType (IntPtrType (), 0)), "");
3728 } else {
3729 args [3] = LLVMConstInt (IntPtrType (), 0, 0);
3731 if (ctx->this_arg)
3732 args [4] = convert (ctx, ctx->this_arg, IntPtrType ());
3733 else
3734 args [4] = LLVMConstInt (IntPtrType (), 0, 0);
3736 LLVMTypeRef match_sig = LLVMFunctionType5 (LLVMInt32Type (), IntPtrType (), LLVMInt32Type (), LLVMInt32Type (), IntPtrType (), IntPtrType (), FALSE);
3737 LLVMValueRef callee = ctx->module->match_exc;
3739 if (!callee) {
3740 if (ctx->cfg->compile_aot) {
3741 ctx->builder = builder;
3742 // get_callee expects ctx->builder to be the emitting builder
3743 callee = get_callee (ctx, match_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3744 } else {
3745 callee = ctx->module->match_exc = LLVMAddFunction (ctx->lmodule, icall_name, match_sig);
3746 LLVMAddGlobalMapping (ctx->module->ee, ctx->module->match_exc, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
3747 ctx->module->match_exc = callee;
3748 mono_memory_barrier ();
3752 g_assert (builder && callee);
3754 g_assert (ctx->ex_var);
3756 return LLVMBuildCall (builder, callee, args, num_args, icall_name);
3759 // FIXME: This won't work because the code-finding makes this
3760 // not a constant.
3761 /*#define MONO_PERSONALITY_DEBUG*/
3763 #ifdef MONO_PERSONALITY_DEBUG
3764 static const gboolean use_debug_personality = TRUE;
3765 static const char *default_personality_name = "mono_debug_personality";
3766 #else
3767 static const gboolean use_debug_personality = FALSE;
3768 static const char *default_personality_name = "__gxx_personality_v0";
3769 #endif
3771 static LLVMTypeRef
3772 default_cpp_lpad_exc_signature (void)
3774 static gboolean inited = FALSE;
3775 static LLVMTypeRef sig;
3777 if (!sig) {
3778 LLVMTypeRef signature [2];
3779 signature [0] = LLVMPointerType (LLVMInt8Type (), 0);
3780 signature [1] = LLVMInt32Type ();
3781 sig = LLVMStructType (signature, 2, FALSE);
3782 inited = TRUE;
3785 return sig;
3788 static LLVMValueRef
3789 get_mono_personality (EmitContext *ctx)
3791 LLVMValueRef personality = NULL;
3792 static gint32 mapping_inited = FALSE;
3793 LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
3795 if (!use_debug_personality) {
3796 if (ctx->cfg->compile_aot) {
3797 personality = get_intrinsic (ctx, default_personality_name);
3798 } else if (InterlockedCompareExchange (&mapping_inited, 1, 0) == 0) {
3799 personality = LLVMAddFunction (ctx->lmodule, default_personality_name, personality_type);
3800 LLVMAddGlobalMapping (ctx->module->ee, personality, personality);
3802 } else {
3803 if (ctx->cfg->compile_aot) {
3804 personality = get_callee (ctx, personality_type, MONO_PATCH_INFO_INTERNAL_METHOD, default_personality_name);
3805 } else {
3806 personality = LLVMAddFunction (ctx->lmodule, default_personality_name, personality_type);
3807 LLVMAddGlobalMapping (ctx->module->ee, personality, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, default_personality_name));
3808 mono_memory_barrier ();
3812 g_assert (personality);
3813 return personality;
3816 static LLVMBasicBlockRef
3817 emit_landing_pad (EmitContext *ctx, int group_index, int group_size)
3819 MonoCompile *cfg = ctx->cfg;
3820 LLVMBuilderRef old_builder = ctx->builder;
3821 MonoExceptionClause *group_start = cfg->header->clauses + group_index;
3823 LLVMBuilderRef lpadBuilder = create_builder (ctx);
3824 ctx->builder = lpadBuilder;
3826 MonoBasicBlock *handler_bb = cfg->cil_offset_to_bb [CLAUSE_START (group_start)];
3827 g_assert (handler_bb);
3829 // <resultval> = landingpad <somety> personality <type> <pers_fn> <clause>+
3830 LLVMValueRef personality = get_mono_personality (ctx);
3831 g_assert (personality);
3833 char *bb_name = g_strdup_printf ("LPAD%d_BB", group_index);
3834 LLVMBasicBlockRef lpad_bb = gen_bb (ctx, bb_name);
3835 g_free (bb_name);
3836 LLVMPositionBuilderAtEnd (lpadBuilder, lpad_bb);
3837 LLVMValueRef landing_pad = LLVMBuildLandingPad (lpadBuilder, default_cpp_lpad_exc_signature (), personality, 0, "");
3838 g_assert (landing_pad);
3840 LLVMValueRef cast = LLVMBuildBitCast (lpadBuilder, ctx->module->sentinel_exception, LLVMPointerType (LLVMInt8Type (), 0), "int8TypeInfo");
3841 LLVMAddClause (landing_pad, cast);
3843 LLVMBasicBlockRef resume_bb = gen_bb (ctx, "RESUME_BB");
3844 LLVMBuilderRef resume_builder = create_builder (ctx);
3845 ctx->builder = resume_builder;
3846 LLVMPositionBuilderAtEnd (resume_builder, resume_bb);
3848 emit_resume_eh (ctx, handler_bb);
3850 // Build match
3851 ctx->builder = lpadBuilder;
3852 LLVMPositionBuilderAtEnd (lpadBuilder, lpad_bb);
3854 gboolean finally_only = TRUE;
3856 MonoExceptionClause *group_cursor = group_start;
3858 for (int i = 0; i < group_size; i ++) {
3859 if (!(group_cursor->flags & MONO_EXCEPTION_CLAUSE_FINALLY))
3860 finally_only = FALSE;
3862 group_cursor++;
3865 // FIXME:
3866 // Handle landing pad inlining
3868 if (!finally_only) {
3869 // So at each level of the exception stack we will match the exception again.
3870 // During that match, we need to compare against the handler types for the current
3871 // protected region. We send the try start and end so that we can only check against
3872 // handlers for this lexical protected region.
3873 LLVMValueRef match = mono_llvm_emit_match_exception_call (ctx, lpadBuilder, group_start->try_offset, group_start->try_offset + group_start->try_len);
3875 // if returns -1, resume
3876 LLVMValueRef switch_ins = LLVMBuildSwitch (lpadBuilder, match, resume_bb, group_size);
3878 // else move to that target bb
3879 for (int i=0; i < group_size; i++) {
3880 MonoExceptionClause *clause = group_start + i;
3881 int clause_index = clause - cfg->header->clauses;
3882 MonoBasicBlock *handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (clause_index));
3883 g_assert (handler_bb);
3884 g_assert (ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
3885 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE), ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
3887 } else {
3888 int clause_index = group_start - cfg->header->clauses;
3889 MonoBasicBlock *finally_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (clause_index));
3890 g_assert (finally_bb);
3892 LLVMBuildBr (ctx->builder, ctx->bblocks [finally_bb->block_num].call_handler_target_bb);
3895 ctx->builder = old_builder;
3897 return lpad_bb;
3901 static void
3902 emit_llvmonly_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBasicBlockRef cbb)
3904 int clause_index = MONO_REGION_CLAUSE_INDEX (bb->region);
3905 MonoExceptionClause *clause = &ctx->cfg->header->clauses [clause_index];
3907 // Make exception available to catch blocks
3908 if (!(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
3909 LLVMValueRef mono_exc = mono_llvm_emit_load_exception_call (ctx, ctx->builder);
3911 g_assert (ctx->ex_var);
3912 LLVMBuildStore (ctx->builder, LLVMBuildBitCast (ctx->builder, mono_exc, ObjRefType (), ""), ctx->ex_var);
3914 if (bb->in_scount == 1) {
3915 MonoInst *exvar = bb->in_stack [0];
3916 g_assert (!ctx->values [exvar->dreg]);
3917 g_assert (ctx->ex_var);
3918 ctx->values [exvar->dreg] = LLVMBuildLoad (ctx->builder, ctx->ex_var, "save_exception");
3919 emit_volatile_store (ctx, exvar->dreg);
3922 mono_llvm_emit_clear_exception_call (ctx, ctx->builder);
3925 LLVMBuilderRef handler_builder = create_builder (ctx);
3926 LLVMBasicBlockRef target_bb = ctx->bblocks [bb->block_num].call_handler_target_bb;
3927 LLVMPositionBuilderAtEnd (handler_builder, target_bb);
3929 // Make the handler code end with a jump to cbb
3930 LLVMBuildBr (handler_builder, cbb);
3933 static void
3934 emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder)
3936 MonoCompile *cfg = ctx->cfg;
3937 LLVMValueRef *values = ctx->values;
3938 LLVMModuleRef lmodule = ctx->lmodule;
3939 BBInfo *bblocks = ctx->bblocks;
3940 LLVMTypeRef i8ptr;
3941 LLVMValueRef personality;
3942 LLVMValueRef landing_pad;
3943 LLVMBasicBlockRef target_bb;
3944 MonoInst *exvar;
3945 static int ti_generator;
3946 char ti_name [128];
3947 LLVMValueRef type_info;
3948 int clause_index;
3949 GSList *l;
3951 // <resultval> = landingpad <somety> personality <type> <pers_fn> <clause>+
3953 if (cfg->compile_aot) {
3954 /* Use a dummy personality function */
3955 personality = LLVMGetNamedFunction (lmodule, "mono_personality");
3956 g_assert (personality);
3957 } else {
3958 #if LLVM_API_VERSION > 100
3959 personality = ctx->module->personality;
3960 if (!personality) {
3961 LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
3962 personality = LLVMAddFunction (ctx->lmodule, "mono_personality", personality_type);
3963 LLVMAddFunctionAttr (personality, LLVMNoUnwindAttribute);
3964 LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlock (personality, "ENTRY");
3965 LLVMBuilderRef builder2 = LLVMCreateBuilder ();
3966 LLVMPositionBuilderAtEnd (builder2, entry_bb);
3967 LLVMBuildRet (builder2, LLVMConstInt (LLVMInt32Type (), 0, FALSE));
3968 ctx->module->personality = personality;
3969 LLVMDisposeBuilder (builder2);
3971 #else
3972 static gint32 mapping_inited;
3974 personality = LLVMGetNamedFunction (lmodule, "mono_personality");
3976 if (InterlockedCompareExchange (&mapping_inited, 1, 0) == 0)
3977 LLVMAddGlobalMapping (ctx->module->ee, personality, (gpointer)mono_personality);
3978 #endif
3981 i8ptr = LLVMPointerType (LLVMInt8Type (), 0);
3983 clause_index = (mono_get_block_region_notry (cfg, bb->region) >> 8) - 1;
3986 * Create the type info
3988 sprintf (ti_name, "type_info_%d", ti_generator);
3989 ti_generator ++;
3991 if (cfg->compile_aot) {
3992 /* decode_eh_frame () in aot-runtime.c will decode this */
3993 type_info = LLVMAddGlobal (lmodule, LLVMInt32Type (), ti_name);
3994 LLVMSetInitializer (type_info, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE));
3997 * These symbols are not really used, the clause_index is embedded into the EH tables generated by DwarfMonoException in LLVM.
3999 LLVMSetLinkage (type_info, LLVMInternalLinkage);
4000 } else {
4001 #if LLVM_API_VERSION > 100
4002 type_info = LLVMAddGlobal (lmodule, LLVMInt32Type (), ti_name);
4003 LLVMSetInitializer (type_info, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE));
4004 #else
4005 gint32 *ti;
4008 * After the cfg mempool is freed, the type info will point to stale memory,
4009 * but this is not a problem, since we decode it once in exception_cb during
4010 * compilation.
4012 ti = (gint32*)mono_mempool_alloc (cfg->mempool, sizeof (gint32));
4013 *(gint32*)ti = clause_index;
4015 type_info = LLVMAddGlobal (lmodule, i8ptr, ti_name);
4017 LLVMAddGlobalMapping (ctx->module->ee, type_info, ti);
4018 #endif
4022 LLVMTypeRef members [2], ret_type;
4024 members [0] = i8ptr;
4025 members [1] = LLVMInt32Type ();
4026 ret_type = LLVMStructType (members, 2, FALSE);
4028 landing_pad = LLVMBuildLandingPad (builder, ret_type, personality, 1, "");
4029 LLVMAddClause (landing_pad, type_info);
4031 /* Store the exception into the exvar */
4032 if (ctx->ex_var)
4033 LLVMBuildStore (builder, convert (ctx, LLVMBuildExtractValue (builder, landing_pad, 0, "ex_obj"), ObjRefType ()), ctx->ex_var);
4037 * LLVM throw sites are associated with a one landing pad, and LLVM generated
4038 * code expects control to be transferred to this landing pad even in the
4039 * presence of nested clauses. The landing pad needs to branch to the landing
4040 * pads belonging to nested clauses based on the selector value returned by
4041 * the landing pad instruction, which is passed to the landing pad in a
4042 * register by the EH code.
4044 target_bb = bblocks [bb->block_num].call_handler_target_bb;
4045 g_assert (target_bb);
4048 * Branch to the correct landing pad
4050 LLVMValueRef ex_selector = LLVMBuildExtractValue (builder, landing_pad, 1, "ex_selector");
4051 LLVMValueRef switch_ins = LLVMBuildSwitch (builder, ex_selector, target_bb, 0);
4053 for (l = ctx->nested_in [clause_index]; l; l = l->next) {
4054 int nesting_clause_index = GPOINTER_TO_INT (l->data);
4055 MonoBasicBlock *handler_bb;
4057 handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (nesting_clause_index));
4058 g_assert (handler_bb);
4060 g_assert (ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
4061 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), nesting_clause_index, FALSE), ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
4064 /* Start a new bblock which CALL_HANDLER can branch to */
4065 target_bb = bblocks [bb->block_num].call_handler_target_bb;
4066 if (target_bb) {
4067 ctx->builder = builder = create_builder (ctx);
4068 LLVMPositionBuilderAtEnd (ctx->builder, target_bb);
4070 ctx->bblocks [bb->block_num].end_bblock = target_bb;
4072 /* Store the exception into the IL level exvar */
4073 if (bb->in_scount == 1) {
4074 g_assert (bb->in_scount == 1);
4075 exvar = bb->in_stack [0];
4077 // FIXME: This is shared with filter clauses ?
4078 g_assert (!values [exvar->dreg]);
4080 g_assert (ctx->ex_var);
4081 values [exvar->dreg] = LLVMBuildLoad (builder, ctx->ex_var, "");
4082 emit_volatile_store (ctx, exvar->dreg);
4087 static void
4088 process_bb (EmitContext *ctx, MonoBasicBlock *bb)
4090 MonoCompile *cfg = ctx->cfg;
4091 MonoMethodSignature *sig = ctx->sig;
4092 LLVMValueRef method = ctx->lmethod;
4093 LLVMValueRef *values = ctx->values;
4094 LLVMValueRef *addresses = ctx->addresses;
4095 LLVMCallInfo *linfo = ctx->linfo;
4096 BBInfo *bblocks = ctx->bblocks;
4097 MonoInst *ins;
4098 LLVMBasicBlockRef cbb;
4099 LLVMBuilderRef builder, starting_builder;
4100 gboolean has_terminator;
4101 LLVMValueRef v;
4102 LLVMValueRef lhs, rhs;
4103 int nins = 0;
4105 cbb = get_end_bb (ctx, bb);
4107 builder = create_builder (ctx);
4108 ctx->builder = builder;
4109 LLVMPositionBuilderAtEnd (builder, cbb);
4111 if (!ctx_ok (ctx))
4112 return;
4114 if (bb->flags & BB_EXCEPTION_HANDLER) {
4115 if (!ctx->llvm_only && !bblocks [bb->block_num].invoke_target) {
4116 set_failure (ctx, "handler without invokes");
4117 return;
4120 if (ctx->llvm_only)
4121 emit_llvmonly_handler_start (ctx, bb, cbb);
4122 else
4123 emit_handler_start (ctx, bb, builder);
4124 if (!ctx_ok (ctx))
4125 return;
4126 builder = ctx->builder;
4129 has_terminator = FALSE;
4130 starting_builder = builder;
4131 for (ins = bb->code; ins; ins = ins->next) {
4132 const char *spec = LLVM_INS_INFO (ins->opcode);
4133 char *dname = NULL;
4134 char dname_buf [128];
4136 emit_dbg_loc (ctx, builder, ins->cil_code);
4138 nins ++;
4139 if (nins > 1000) {
4141 * Some steps in llc are non-linear in the size of basic blocks, see #5714.
4142 * Start a new bblock. If the llvm optimization passes merge these, we
4143 * can work around that by doing a volatile load + cond branch from
4144 * localloc-ed memory.
4146 //set_failure (ctx, "basic block too long");
4147 cbb = gen_bb (ctx, "CONT_LONG_BB");
4148 LLVMBuildBr (ctx->builder, cbb);
4149 ctx->builder = builder = create_builder (ctx);
4150 LLVMPositionBuilderAtEnd (builder, cbb);
4151 ctx->bblocks [bb->block_num].end_bblock = cbb;
4152 nins = 0;
4155 if (has_terminator)
4156 /* There could be instructions after a terminator, skip them */
4157 break;
4159 if (spec [MONO_INST_DEST] != ' ' && !MONO_IS_STORE_MEMBASE (ins)) {
4160 sprintf (dname_buf, "t%d", ins->dreg);
4161 dname = dname_buf;
4164 if (spec [MONO_INST_SRC1] != ' ' && spec [MONO_INST_SRC1] != 'v') {
4165 MonoInst *var = get_vreg_to_inst (cfg, ins->sreg1);
4167 if (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) && var->opcode != OP_GSHAREDVT_ARG_REGOFFSET) {
4168 lhs = emit_volatile_load (ctx, ins->sreg1);
4169 } else {
4170 /* It is ok for SETRET to have an uninitialized argument */
4171 if (!values [ins->sreg1] && ins->opcode != OP_SETRET) {
4172 set_failure (ctx, "sreg1");
4173 return;
4175 lhs = values [ins->sreg1];
4177 } else {
4178 lhs = NULL;
4181 if (spec [MONO_INST_SRC2] != ' ' && spec [MONO_INST_SRC2] != ' ') {
4182 MonoInst *var = get_vreg_to_inst (cfg, ins->sreg2);
4183 if (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) {
4184 rhs = emit_volatile_load (ctx, ins->sreg2);
4185 } else {
4186 if (!values [ins->sreg2]) {
4187 set_failure (ctx, "sreg2");
4188 return;
4190 rhs = values [ins->sreg2];
4192 } else {
4193 rhs = NULL;
4196 //mono_print_ins (ins);
4197 switch (ins->opcode) {
4198 case OP_NOP:
4199 case OP_NOT_NULL:
4200 case OP_LIVERANGE_START:
4201 case OP_LIVERANGE_END:
4202 break;
4203 case OP_ICONST:
4204 values [ins->dreg] = LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE);
4205 break;
4206 case OP_I8CONST:
4207 #if SIZEOF_VOID_P == 4
4208 values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins), FALSE);
4209 #else
4210 values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), (gint64)ins->inst_c0, FALSE);
4211 #endif
4212 break;
4213 case OP_R8CONST:
4214 values [ins->dreg] = LLVMConstReal (LLVMDoubleType (), *(double*)ins->inst_p0);
4215 break;
4216 case OP_R4CONST:
4217 if (cfg->r4fp)
4218 values [ins->dreg] = LLVMConstReal (LLVMFloatType (), *(float*)ins->inst_p0);
4219 else
4220 values [ins->dreg] = LLVMConstFPExt (LLVMConstReal (LLVMFloatType (), *(float*)ins->inst_p0), LLVMDoubleType ());
4221 break;
4222 case OP_DUMMY_ICONST:
4223 values [ins->dreg] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
4224 break;
4225 case OP_DUMMY_I8CONST:
4226 values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
4227 break;
4228 case OP_DUMMY_R8CONST:
4229 values [ins->dreg] = LLVMConstReal (LLVMDoubleType (), 0.0f);
4230 break;
4231 case OP_BR: {
4232 LLVMBasicBlockRef target_bb = get_bb (ctx, ins->inst_target_bb);
4233 LLVMBuildBr (builder, target_bb);
4234 has_terminator = TRUE;
4235 break;
4237 case OP_SWITCH: {
4238 int i;
4239 LLVMValueRef v;
4240 char bb_name [128];
4241 LLVMBasicBlockRef new_bb;
4242 LLVMBuilderRef new_builder;
4244 // The default branch is already handled
4245 // FIXME: Handle it here
4247 /* Start new bblock */
4248 sprintf (bb_name, "SWITCH_DEFAULT_BB%d", ctx->default_index ++);
4249 new_bb = LLVMAppendBasicBlock (ctx->lmethod, bb_name);
4251 lhs = convert (ctx, lhs, LLVMInt32Type ());
4252 v = LLVMBuildSwitch (builder, lhs, new_bb, GPOINTER_TO_UINT (ins->klass));
4253 for (i = 0; i < GPOINTER_TO_UINT (ins->klass); ++i) {
4254 MonoBasicBlock *target_bb = ins->inst_many_bb [i];
4256 LLVMAddCase (v, LLVMConstInt (LLVMInt32Type (), i, FALSE), get_bb (ctx, target_bb));
4259 new_builder = create_builder (ctx);
4260 LLVMPositionBuilderAtEnd (new_builder, new_bb);
4261 LLVMBuildUnreachable (new_builder);
4263 has_terminator = TRUE;
4264 g_assert (!ins->next);
4266 break;
4269 case OP_SETRET:
4270 switch (linfo->ret.storage) {
4271 case LLVMArgVtypeInReg: {
4272 LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
4273 LLVMValueRef val, addr, retval;
4274 int i;
4276 retval = LLVMGetUndef (ret_type);
4278 if (!addresses [ins->sreg1]) {
4280 * The return type is an LLVM vector type, have to convert between it and the
4281 * real return type which is a struct type.
4283 g_assert (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type (sig->ret)));
4284 /* Convert to 2xi64 first */
4285 val = LLVMBuildBitCast (builder, values [ins->sreg1], LLVMVectorType (IntPtrType (), 2), "");
4287 for (i = 0; i < 2; ++i) {
4288 if (linfo->ret.pair_storage [i] == LLVMArgInIReg) {
4289 retval = LLVMBuildInsertValue (builder, retval, LLVMBuildExtractElement (builder, val, LLVMConstInt (LLVMInt32Type (), i, FALSE), ""), i, "");
4290 } else {
4291 g_assert (linfo->ret.pair_storage [i] == LLVMArgNone);
4294 } else {
4295 addr = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), "");
4296 for (i = 0; i < 2; ++i) {
4297 if (linfo->ret.pair_storage [i] == LLVMArgInIReg) {
4298 LLVMValueRef indexes [2], part_addr;
4300 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
4301 indexes [1] = LLVMConstInt (LLVMInt32Type (), i, FALSE);
4302 part_addr = LLVMBuildGEP (builder, addr, indexes, 2, "");
4304 retval = LLVMBuildInsertValue (builder, retval, LLVMBuildLoad (builder, part_addr, ""), i, "");
4305 } else {
4306 g_assert (linfo->ret.pair_storage [i] == LLVMArgNone);
4310 LLVMBuildRet (builder, retval);
4311 break;
4313 case LLVMArgVtypeAsScalar: {
4314 LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
4315 LLVMValueRef retval;
4317 g_assert (addresses [ins->sreg1]);
4319 retval = LLVMBuildLoad (builder, LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), ""), "");
4320 LLVMBuildRet (builder, retval);
4321 break;
4323 case LLVMArgVtypeByVal: {
4324 LLVMValueRef retval;
4326 g_assert (addresses [ins->sreg1]);
4327 retval = LLVMBuildLoad (builder, addresses [ins->sreg1], "");
4328 LLVMBuildRet (builder, retval);
4329 break;
4331 case LLVMArgVtypeByRef: {
4332 LLVMBuildRetVoid (builder);
4333 break;
4335 case LLVMArgGsharedvtFixed: {
4336 LLVMTypeRef ret_type = type_to_llvm_type (ctx, sig->ret);
4337 /* The return value is in lhs, need to store to the vret argument */
4338 /* sreg1 might not be set */
4339 if (lhs) {
4340 g_assert (cfg->vret_addr);
4341 g_assert (values [cfg->vret_addr->dreg]);
4342 LLVMBuildStore (builder, convert (ctx, lhs, ret_type), convert (ctx, values [cfg->vret_addr->dreg], LLVMPointerType (ret_type, 0)));
4344 LLVMBuildRetVoid (builder);
4345 break;
4347 case LLVMArgGsharedvtFixedVtype: {
4348 /* Already set */
4349 LLVMBuildRetVoid (builder);
4350 break;
4352 case LLVMArgGsharedvtVariable: {
4353 /* Already set */
4354 LLVMBuildRetVoid (builder);
4355 break;
4357 case LLVMArgVtypeRetAddr: {
4358 LLVMBuildRetVoid (builder);
4359 break;
4361 case LLVMArgAsIArgs:
4362 case LLVMArgFpStruct: {
4363 LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
4364 LLVMValueRef retval;
4366 g_assert (addresses [ins->sreg1]);
4367 retval = LLVMBuildLoad (builder, convert (ctx, addresses [ins->sreg1], LLVMPointerType (ret_type, 0)), "");
4368 LLVMBuildRet (builder, retval);
4369 break;
4371 case LLVMArgNone:
4372 case LLVMArgNormal: {
4373 if (!lhs || ctx->is_dead [ins->sreg1]) {
4375 * The method did not set its return value, probably because it
4376 * ends with a throw.
4378 if (cfg->vret_addr)
4379 LLVMBuildRetVoid (builder);
4380 else
4381 LLVMBuildRet (builder, LLVMConstNull (type_to_llvm_type (ctx, sig->ret)));
4382 } else {
4383 LLVMBuildRet (builder, convert (ctx, lhs, type_to_llvm_type (ctx, sig->ret)));
4385 has_terminator = TRUE;
4386 break;
4388 default:
4389 g_assert_not_reached ();
4390 break;
4392 break;
4393 case OP_ICOMPARE:
4394 case OP_FCOMPARE:
4395 case OP_RCOMPARE:
4396 case OP_LCOMPARE:
4397 case OP_COMPARE:
4398 case OP_ICOMPARE_IMM:
4399 case OP_LCOMPARE_IMM:
4400 case OP_COMPARE_IMM: {
4401 CompRelation rel;
4402 LLVMValueRef cmp, args [16];
4403 gboolean likely = (ins->flags & MONO_INST_LIKELY) != 0;
4405 if (ins->next->opcode == OP_NOP)
4406 break;
4408 if (ins->next->opcode == OP_BR)
4409 /* The comparison result is not needed */
4410 continue;
4412 rel = mono_opcode_to_cond (ins->next->opcode);
4414 if (ins->opcode == OP_ICOMPARE_IMM) {
4415 lhs = convert (ctx, lhs, LLVMInt32Type ());
4416 rhs = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
4418 if (ins->opcode == OP_LCOMPARE_IMM) {
4419 lhs = convert (ctx, lhs, LLVMInt64Type ());
4420 rhs = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins), FALSE);
4422 if (ins->opcode == OP_LCOMPARE) {
4423 lhs = convert (ctx, lhs, LLVMInt64Type ());
4424 rhs = convert (ctx, rhs, LLVMInt64Type ());
4426 if (ins->opcode == OP_ICOMPARE) {
4427 lhs = convert (ctx, lhs, LLVMInt32Type ());
4428 rhs = convert (ctx, rhs, LLVMInt32Type ());
4431 if (lhs && rhs) {
4432 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind)
4433 rhs = convert (ctx, rhs, LLVMTypeOf (lhs));
4434 else if (LLVMGetTypeKind (LLVMTypeOf (rhs)) == LLVMPointerTypeKind)
4435 lhs = convert (ctx, lhs, LLVMTypeOf (rhs));
4438 /* We use COMPARE+SETcc/Bcc, llvm uses SETcc+br cond */
4439 if (ins->opcode == OP_FCOMPARE) {
4440 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMDoubleType ()), convert (ctx, rhs, LLVMDoubleType ()), "");
4441 } else if (ins->opcode == OP_RCOMPARE) {
4442 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMFloatType ()), convert (ctx, rhs, LLVMFloatType ()), "");
4443 } else if (ins->opcode == OP_COMPARE_IMM) {
4444 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind && ins->inst_imm == 0)
4445 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, LLVMConstNull (LLVMTypeOf (lhs)), "");
4446 else
4447 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), "");
4448 } else if (ins->opcode == OP_LCOMPARE_IMM) {
4449 if (SIZEOF_REGISTER == 4 && COMPILE_LLVM (cfg)) {
4450 /* The immediate is encoded in two fields */
4451 guint64 l = ((guint64)(guint32)ins->inst_offset << 32) | ((guint32)ins->inst_imm);
4452 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, LLVMInt64Type ()), LLVMConstInt (LLVMInt64Type (), l, FALSE), "");
4453 } else {
4454 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, LLVMInt64Type ()), LLVMConstInt (LLVMInt64Type (), ins->inst_imm, FALSE), "");
4457 else if (ins->opcode == OP_COMPARE) {
4458 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind && LLVMTypeOf (lhs) == LLVMTypeOf (rhs))
4459 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, rhs, "");
4460 else
4461 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, IntPtrType ()), convert (ctx, rhs, IntPtrType ()), "");
4462 } else
4463 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, rhs, "");
4465 if (likely) {
4466 args [0] = cmp;
4467 args [1] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
4468 cmp = LLVMBuildCall (ctx->builder, get_intrinsic (ctx, "llvm.expect.i1"), args, 2, "");
4471 if (MONO_IS_COND_BRANCH_OP (ins->next)) {
4472 if (ins->next->inst_true_bb == ins->next->inst_false_bb) {
4474 * If the target bb contains PHI instructions, LLVM requires
4475 * two PHI entries for this bblock, while we only generate one.
4476 * So convert this to an unconditional bblock. (bxc #171).
4478 LLVMBuildBr (builder, get_bb (ctx, ins->next->inst_true_bb));
4479 } else {
4480 LLVMBuildCondBr (builder, cmp, get_bb (ctx, ins->next->inst_true_bb), get_bb (ctx, ins->next->inst_false_bb));
4482 has_terminator = TRUE;
4483 } else if (MONO_IS_SETCC (ins->next)) {
4484 sprintf (dname_buf, "t%d", ins->next->dreg);
4485 dname = dname_buf;
4486 values [ins->next->dreg] = LLVMBuildZExt (builder, cmp, LLVMInt32Type (), dname);
4488 /* Add stores for volatile variables */
4489 emit_volatile_store (ctx, ins->next->dreg);
4490 } else if (MONO_IS_COND_EXC (ins->next)) {
4491 emit_cond_system_exception (ctx, bb, (const char*)ins->next->inst_p1, cmp);
4492 if (!ctx_ok (ctx))
4493 break;
4494 builder = ctx->builder;
4495 } else {
4496 set_failure (ctx, "next");
4497 break;
4500 ins = ins->next;
4501 break;
4503 case OP_FCEQ:
4504 case OP_FCNEQ:
4505 case OP_FCLT:
4506 case OP_FCLT_UN:
4507 case OP_FCGT:
4508 case OP_FCGT_UN:
4509 case OP_FCGE:
4510 case OP_FCLE: {
4511 CompRelation rel;
4512 LLVMValueRef cmp;
4514 rel = mono_opcode_to_cond (ins->opcode);
4516 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMDoubleType ()), convert (ctx, rhs, LLVMDoubleType ()), "");
4517 values [ins->dreg] = LLVMBuildZExt (builder, cmp, LLVMInt32Type (), dname);
4518 break;
4520 case OP_RCEQ:
4521 case OP_RCLT:
4522 case OP_RCLT_UN:
4523 case OP_RCGT:
4524 case OP_RCGT_UN: {
4525 CompRelation rel;
4526 LLVMValueRef cmp;
4528 rel = mono_opcode_to_cond (ins->opcode);
4530 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMFloatType ()), convert (ctx, rhs, LLVMFloatType ()), "");
4531 values [ins->dreg] = LLVMBuildZExt (builder, cmp, LLVMInt32Type (), dname);
4532 break;
4534 case OP_PHI:
4535 case OP_FPHI:
4536 case OP_VPHI:
4537 case OP_XPHI: {
4538 int i;
4539 gboolean empty = TRUE;
4541 /* Check that all input bblocks really branch to us */
4542 for (i = 0; i < bb->in_count; ++i) {
4543 if (bb->in_bb [i]->last_ins && bb->in_bb [i]->last_ins->opcode == OP_NOT_REACHED)
4544 ins->inst_phi_args [i + 1] = -1;
4545 else
4546 empty = FALSE;
4549 if (empty) {
4550 /* LLVM doesn't like phi instructions with zero operands */
4551 ctx->is_dead [ins->dreg] = TRUE;
4552 break;
4555 /* Created earlier, insert it now */
4556 LLVMInsertIntoBuilder (builder, values [ins->dreg]);
4558 for (i = 0; i < ins->inst_phi_args [0]; i++) {
4559 int sreg1 = ins->inst_phi_args [i + 1];
4560 int count, j;
4563 * Count the number of times the incoming bblock branches to us,
4564 * since llvm requires a separate entry for each.
4566 if (bb->in_bb [i]->last_ins && bb->in_bb [i]->last_ins->opcode == OP_SWITCH) {
4567 MonoInst *switch_ins = bb->in_bb [i]->last_ins;
4569 count = 0;
4570 for (j = 0; j < GPOINTER_TO_UINT (switch_ins->klass); ++j) {
4571 if (switch_ins->inst_many_bb [j] == bb)
4572 count ++;
4574 } else {
4575 count = 1;
4578 /* Remember for later */
4579 for (j = 0; j < count; ++j) {
4580 PhiNode *node = (PhiNode*)mono_mempool_alloc0 (ctx->mempool, sizeof (PhiNode));
4581 node->bb = bb;
4582 node->phi = ins;
4583 node->in_bb = bb->in_bb [i];
4584 node->sreg = sreg1;
4585 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);
4588 break;
4590 case OP_MOVE:
4591 case OP_LMOVE:
4592 case OP_XMOVE:
4593 case OP_SETFRET:
4594 g_assert (lhs);
4595 values [ins->dreg] = lhs;
4596 break;
4597 case OP_FMOVE:
4598 case OP_RMOVE: {
4599 MonoInst *var = get_vreg_to_inst (cfg, ins->dreg);
4601 g_assert (lhs);
4602 values [ins->dreg] = lhs;
4604 if (var && var->klass->byval_arg.type == MONO_TYPE_R4) {
4606 * This is added by the spilling pass in case of the JIT,
4607 * but we have to do it ourselves.
4609 values [ins->dreg] = convert (ctx, values [ins->dreg], LLVMFloatType ());
4611 break;
4613 case OP_MOVE_F_TO_I4: {
4614 values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildFPTrunc (builder, lhs, LLVMFloatType (), ""), LLVMInt32Type (), "");
4615 break;
4617 case OP_MOVE_I4_TO_F: {
4618 values [ins->dreg] = LLVMBuildFPExt (builder, LLVMBuildBitCast (builder, lhs, LLVMFloatType (), ""), LLVMDoubleType (), "");
4619 break;
4621 case OP_MOVE_F_TO_I8: {
4622 values [ins->dreg] = LLVMBuildBitCast (builder, lhs, LLVMInt64Type (), "");
4623 break;
4625 case OP_MOVE_I8_TO_F: {
4626 values [ins->dreg] = LLVMBuildBitCast (builder, lhs, LLVMDoubleType (), "");
4627 break;
4629 case OP_IADD:
4630 case OP_ISUB:
4631 case OP_IAND:
4632 case OP_IMUL:
4633 case OP_IDIV:
4634 case OP_IDIV_UN:
4635 case OP_IREM:
4636 case OP_IREM_UN:
4637 case OP_IOR:
4638 case OP_IXOR:
4639 case OP_ISHL:
4640 case OP_ISHR:
4641 case OP_ISHR_UN:
4642 case OP_FADD:
4643 case OP_FSUB:
4644 case OP_FMUL:
4645 case OP_FDIV:
4646 case OP_LADD:
4647 case OP_LSUB:
4648 case OP_LMUL:
4649 case OP_LDIV:
4650 case OP_LDIV_UN:
4651 case OP_LREM:
4652 case OP_LREM_UN:
4653 case OP_LAND:
4654 case OP_LOR:
4655 case OP_LXOR:
4656 case OP_LSHL:
4657 case OP_LSHR:
4658 case OP_LSHR_UN:
4659 lhs = convert (ctx, lhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
4660 rhs = convert (ctx, rhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
4662 emit_div_check (ctx, builder, bb, ins, lhs, rhs);
4663 if (!ctx_ok (ctx))
4664 break;
4665 builder = ctx->builder;
4667 switch (ins->opcode) {
4668 case OP_IADD:
4669 case OP_LADD:
4670 values [ins->dreg] = LLVMBuildAdd (builder, lhs, rhs, dname);
4671 break;
4672 case OP_ISUB:
4673 case OP_LSUB:
4674 values [ins->dreg] = LLVMBuildSub (builder, lhs, rhs, dname);
4675 break;
4676 case OP_IMUL:
4677 case OP_LMUL:
4678 values [ins->dreg] = LLVMBuildMul (builder, lhs, rhs, dname);
4679 break;
4680 case OP_IREM:
4681 case OP_LREM:
4682 values [ins->dreg] = LLVMBuildSRem (builder, lhs, rhs, dname);
4683 break;
4684 case OP_IREM_UN:
4685 case OP_LREM_UN:
4686 values [ins->dreg] = LLVMBuildURem (builder, lhs, rhs, dname);
4687 break;
4688 case OP_IDIV:
4689 case OP_LDIV:
4690 values [ins->dreg] = LLVMBuildSDiv (builder, lhs, rhs, dname);
4691 break;
4692 case OP_IDIV_UN:
4693 case OP_LDIV_UN:
4694 values [ins->dreg] = LLVMBuildUDiv (builder, lhs, rhs, dname);
4695 break;
4696 case OP_FDIV:
4697 case OP_RDIV:
4698 values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, dname);
4699 break;
4700 case OP_IAND:
4701 case OP_LAND:
4702 values [ins->dreg] = LLVMBuildAnd (builder, lhs, rhs, dname);
4703 break;
4704 case OP_IOR:
4705 case OP_LOR:
4706 values [ins->dreg] = LLVMBuildOr (builder, lhs, rhs, dname);
4707 break;
4708 case OP_IXOR:
4709 case OP_LXOR:
4710 values [ins->dreg] = LLVMBuildXor (builder, lhs, rhs, dname);
4711 break;
4712 case OP_ISHL:
4713 case OP_LSHL:
4714 values [ins->dreg] = LLVMBuildShl (builder, lhs, rhs, dname);
4715 break;
4716 case OP_ISHR:
4717 case OP_LSHR:
4718 values [ins->dreg] = LLVMBuildAShr (builder, lhs, rhs, dname);
4719 break;
4720 case OP_ISHR_UN:
4721 case OP_LSHR_UN:
4722 values [ins->dreg] = LLVMBuildLShr (builder, lhs, rhs, dname);
4723 break;
4725 case OP_FADD:
4726 values [ins->dreg] = LLVMBuildFAdd (builder, lhs, rhs, dname);
4727 break;
4728 case OP_FSUB:
4729 values [ins->dreg] = LLVMBuildFSub (builder, lhs, rhs, dname);
4730 break;
4731 case OP_FMUL:
4732 values [ins->dreg] = LLVMBuildFMul (builder, lhs, rhs, dname);
4733 break;
4735 default:
4736 g_assert_not_reached ();
4738 break;
4739 case OP_RADD:
4740 case OP_RSUB:
4741 case OP_RMUL:
4742 case OP_RDIV: {
4743 lhs = convert (ctx, lhs, LLVMFloatType ());
4744 rhs = convert (ctx, rhs, LLVMFloatType ());
4745 switch (ins->opcode) {
4746 case OP_RADD:
4747 values [ins->dreg] = LLVMBuildFAdd (builder, lhs, rhs, dname);
4748 break;
4749 case OP_RSUB:
4750 values [ins->dreg] = LLVMBuildFSub (builder, lhs, rhs, dname);
4751 break;
4752 case OP_RMUL:
4753 values [ins->dreg] = LLVMBuildFMul (builder, lhs, rhs, dname);
4754 break;
4755 case OP_RDIV:
4756 values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, dname);
4757 break;
4758 default:
4759 g_assert_not_reached ();
4760 break;
4762 break;
4764 case OP_IADD_IMM:
4765 case OP_ISUB_IMM:
4766 case OP_IMUL_IMM:
4767 case OP_IREM_IMM:
4768 case OP_IREM_UN_IMM:
4769 case OP_IDIV_IMM:
4770 case OP_IDIV_UN_IMM:
4771 case OP_IAND_IMM:
4772 case OP_IOR_IMM:
4773 case OP_IXOR_IMM:
4774 case OP_ISHL_IMM:
4775 case OP_ISHR_IMM:
4776 case OP_ISHR_UN_IMM:
4777 case OP_LADD_IMM:
4778 case OP_LSUB_IMM:
4779 case OP_LMUL_IMM:
4780 case OP_LREM_IMM:
4781 case OP_LAND_IMM:
4782 case OP_LOR_IMM:
4783 case OP_LXOR_IMM:
4784 case OP_LSHL_IMM:
4785 case OP_LSHR_IMM:
4786 case OP_LSHR_UN_IMM:
4787 case OP_ADD_IMM:
4788 case OP_AND_IMM:
4789 case OP_MUL_IMM:
4790 case OP_SHL_IMM:
4791 case OP_SHR_IMM:
4792 case OP_SHR_UN_IMM: {
4793 LLVMValueRef imm;
4795 if (spec [MONO_INST_SRC1] == 'l') {
4796 imm = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins), FALSE);
4797 } else {
4798 imm = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
4801 emit_div_check (ctx, builder, bb, ins, lhs, imm);
4802 if (!ctx_ok (ctx))
4803 break;
4804 builder = ctx->builder;
4806 #if SIZEOF_VOID_P == 4
4807 if (ins->opcode == OP_LSHL_IMM || ins->opcode == OP_LSHR_IMM || ins->opcode == OP_LSHR_UN_IMM)
4808 imm = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
4809 #endif
4811 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind)
4812 lhs = convert (ctx, lhs, IntPtrType ());
4813 imm = convert (ctx, imm, LLVMTypeOf (lhs));
4814 switch (ins->opcode) {
4815 case OP_IADD_IMM:
4816 case OP_LADD_IMM:
4817 case OP_ADD_IMM:
4818 values [ins->dreg] = LLVMBuildAdd (builder, lhs, imm, dname);
4819 break;
4820 case OP_ISUB_IMM:
4821 case OP_LSUB_IMM:
4822 values [ins->dreg] = LLVMBuildSub (builder, lhs, imm, dname);
4823 break;
4824 case OP_IMUL_IMM:
4825 case OP_MUL_IMM:
4826 case OP_LMUL_IMM:
4827 values [ins->dreg] = LLVMBuildMul (builder, lhs, imm, dname);
4828 break;
4829 case OP_IDIV_IMM:
4830 case OP_LDIV_IMM:
4831 values [ins->dreg] = LLVMBuildSDiv (builder, lhs, imm, dname);
4832 break;
4833 case OP_IDIV_UN_IMM:
4834 case OP_LDIV_UN_IMM:
4835 values [ins->dreg] = LLVMBuildUDiv (builder, lhs, imm, dname);
4836 break;
4837 case OP_IREM_IMM:
4838 case OP_LREM_IMM:
4839 values [ins->dreg] = LLVMBuildSRem (builder, lhs, imm, dname);
4840 break;
4841 case OP_IREM_UN_IMM:
4842 values [ins->dreg] = LLVMBuildURem (builder, lhs, imm, dname);
4843 break;
4844 case OP_IAND_IMM:
4845 case OP_LAND_IMM:
4846 case OP_AND_IMM:
4847 values [ins->dreg] = LLVMBuildAnd (builder, lhs, imm, dname);
4848 break;
4849 case OP_IOR_IMM:
4850 case OP_LOR_IMM:
4851 values [ins->dreg] = LLVMBuildOr (builder, lhs, imm, dname);
4852 break;
4853 case OP_IXOR_IMM:
4854 case OP_LXOR_IMM:
4855 values [ins->dreg] = LLVMBuildXor (builder, lhs, imm, dname);
4856 break;
4857 case OP_ISHL_IMM:
4858 case OP_LSHL_IMM:
4859 case OP_SHL_IMM:
4860 values [ins->dreg] = LLVMBuildShl (builder, lhs, imm, dname);
4861 break;
4862 case OP_ISHR_IMM:
4863 case OP_LSHR_IMM:
4864 case OP_SHR_IMM:
4865 values [ins->dreg] = LLVMBuildAShr (builder, lhs, imm, dname);
4866 break;
4867 case OP_ISHR_UN_IMM:
4868 /* This is used to implement conv.u4, so the lhs could be an i8 */
4869 lhs = convert (ctx, lhs, LLVMInt32Type ());
4870 imm = convert (ctx, imm, LLVMInt32Type ());
4871 values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
4872 break;
4873 case OP_LSHR_UN_IMM:
4874 case OP_SHR_UN_IMM:
4875 values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
4876 break;
4877 default:
4878 g_assert_not_reached ();
4880 break;
4882 case OP_INEG:
4883 values [ins->dreg] = LLVMBuildSub (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), convert (ctx, lhs, LLVMInt32Type ()), dname);
4884 break;
4885 case OP_LNEG:
4886 values [ins->dreg] = LLVMBuildSub (builder, LLVMConstInt (LLVMInt64Type (), 0, FALSE), lhs, dname);
4887 break;
4888 case OP_FNEG:
4889 lhs = convert (ctx, lhs, LLVMDoubleType ());
4890 values [ins->dreg] = LLVMBuildFSub (builder, LLVMConstReal (LLVMDoubleType (), 0.0), lhs, dname);
4891 break;
4892 case OP_RNEG:
4893 lhs = convert (ctx, lhs, LLVMFloatType ());
4894 values [ins->dreg] = LLVMBuildFSub (builder, LLVMConstReal (LLVMFloatType (), 0.0), lhs, dname);
4895 break;
4896 case OP_INOT: {
4897 guint32 v = 0xffffffff;
4898 values [ins->dreg] = LLVMBuildXor (builder, LLVMConstInt (LLVMInt32Type (), v, FALSE), convert (ctx, lhs, LLVMInt32Type ()), dname);
4899 break;
4901 case OP_LNOT: {
4902 guint64 v = 0xffffffffffffffffLL;
4903 values [ins->dreg] = LLVMBuildXor (builder, LLVMConstInt (LLVMInt64Type (), v, FALSE), lhs, dname);
4904 break;
4906 #if defined(TARGET_X86) || defined(TARGET_AMD64)
4907 case OP_X86_LEA: {
4908 LLVMValueRef v1, v2;
4910 v1 = LLVMBuildMul (builder, convert (ctx, rhs, IntPtrType ()), LLVMConstInt (IntPtrType (), (1 << ins->backend.shift_amount), FALSE), "");
4911 v2 = LLVMBuildAdd (builder, convert (ctx, lhs, IntPtrType ()), v1, "");
4912 values [ins->dreg] = LLVMBuildAdd (builder, v2, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), dname);
4913 break;
4915 #endif
4917 case OP_ICONV_TO_I1:
4918 case OP_ICONV_TO_I2:
4919 case OP_ICONV_TO_I4:
4920 case OP_ICONV_TO_U1:
4921 case OP_ICONV_TO_U2:
4922 case OP_ICONV_TO_U4:
4923 case OP_LCONV_TO_I1:
4924 case OP_LCONV_TO_I2:
4925 case OP_LCONV_TO_U1:
4926 case OP_LCONV_TO_U2:
4927 case OP_LCONV_TO_U4: {
4928 gboolean sign;
4930 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);
4932 /* Have to do two casts since our vregs have type int */
4933 v = LLVMBuildTrunc (builder, lhs, op_to_llvm_type (ins->opcode), "");
4934 if (sign)
4935 values [ins->dreg] = LLVMBuildSExt (builder, v, LLVMInt32Type (), dname);
4936 else
4937 values [ins->dreg] = LLVMBuildZExt (builder, v, LLVMInt32Type (), dname);
4938 break;
4940 case OP_ICONV_TO_I8:
4941 values [ins->dreg] = LLVMBuildSExt (builder, lhs, LLVMInt64Type (), dname);
4942 break;
4943 case OP_ICONV_TO_U8:
4944 values [ins->dreg] = LLVMBuildZExt (builder, lhs, LLVMInt64Type (), dname);
4945 break;
4946 case OP_FCONV_TO_I4:
4947 case OP_RCONV_TO_I4:
4948 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, LLVMInt32Type (), dname);
4949 break;
4950 case OP_FCONV_TO_I1:
4951 case OP_RCONV_TO_I1:
4952 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildFPToSI (builder, lhs, LLVMInt8Type (), dname), LLVMInt32Type (), "");
4953 break;
4954 case OP_FCONV_TO_U1:
4955 case OP_RCONV_TO_U1:
4956 values [ins->dreg] = LLVMBuildZExt (builder, LLVMBuildTrunc (builder, LLVMBuildFPToUI (builder, lhs, IntPtrType (), dname), LLVMInt8Type (), ""), LLVMInt32Type (), "");
4957 break;
4958 case OP_FCONV_TO_I2:
4959 case OP_RCONV_TO_I2:
4960 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildFPToSI (builder, lhs, LLVMInt16Type (), dname), LLVMInt32Type (), "");
4961 break;
4962 case OP_FCONV_TO_U2:
4963 case OP_RCONV_TO_U2:
4964 values [ins->dreg] = LLVMBuildZExt (builder, LLVMBuildFPToUI (builder, lhs, LLVMInt16Type (), dname), LLVMInt32Type (), "");
4965 break;
4966 case OP_RCONV_TO_U4:
4967 values [ins->dreg] = LLVMBuildFPToUI (builder, lhs, LLVMInt32Type (), dname);
4968 break;
4969 case OP_FCONV_TO_I8:
4970 case OP_RCONV_TO_I8:
4971 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, LLVMInt64Type (), dname);
4972 break;
4973 case OP_FCONV_TO_I:
4974 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, IntPtrType (), dname);
4975 break;
4976 case OP_ICONV_TO_R8:
4977 case OP_LCONV_TO_R8:
4978 values [ins->dreg] = LLVMBuildSIToFP (builder, lhs, LLVMDoubleType (), dname);
4979 break;
4980 case OP_ICONV_TO_R_UN:
4981 case OP_LCONV_TO_R_UN:
4982 values [ins->dreg] = LLVMBuildUIToFP (builder, lhs, LLVMDoubleType (), dname);
4983 break;
4984 #if SIZEOF_VOID_P == 4
4985 case OP_LCONV_TO_U:
4986 #endif
4987 case OP_LCONV_TO_I4:
4988 values [ins->dreg] = LLVMBuildTrunc (builder, lhs, LLVMInt32Type (), dname);
4989 break;
4990 case OP_ICONV_TO_R4:
4991 case OP_LCONV_TO_R4:
4992 v = LLVMBuildSIToFP (builder, lhs, LLVMFloatType (), "");
4993 if (cfg->r4fp)
4994 values [ins->dreg] = v;
4995 else
4996 values [ins->dreg] = LLVMBuildFPExt (builder, v, LLVMDoubleType (), dname);
4997 break;
4998 case OP_FCONV_TO_R4:
4999 v = LLVMBuildFPTrunc (builder, lhs, LLVMFloatType (), "");
5000 if (cfg->r4fp)
5001 values [ins->dreg] = v;
5002 else
5003 values [ins->dreg] = LLVMBuildFPExt (builder, v, LLVMDoubleType (), dname);
5004 break;
5005 case OP_RCONV_TO_R8:
5006 values [ins->dreg] = LLVMBuildFPExt (builder, lhs, LLVMDoubleType (), dname);
5007 break;
5008 case OP_RCONV_TO_R4:
5009 values [ins->dreg] = lhs;
5010 break;
5011 case OP_SEXT_I4:
5012 values [ins->dreg] = LLVMBuildSExt (builder, convert (ctx, lhs, LLVMInt32Type ()), LLVMInt64Type (), dname);
5013 break;
5014 case OP_ZEXT_I4:
5015 values [ins->dreg] = LLVMBuildZExt (builder, convert (ctx, lhs, LLVMInt32Type ()), LLVMInt64Type (), dname);
5016 break;
5017 case OP_TRUNC_I4:
5018 values [ins->dreg] = LLVMBuildTrunc (builder, lhs, LLVMInt32Type (), dname);
5019 break;
5020 case OP_LOCALLOC_IMM: {
5021 LLVMValueRef v;
5023 guint32 size = ins->inst_imm;
5024 size = (size + (MONO_ARCH_FRAME_ALIGNMENT - 1)) & ~ (MONO_ARCH_FRAME_ALIGNMENT - 1);
5026 v = mono_llvm_build_alloca (builder, LLVMInt8Type (), LLVMConstInt (LLVMInt32Type (), size, FALSE), MONO_ARCH_FRAME_ALIGNMENT, "");
5028 if (ins->flags & MONO_INST_INIT) {
5029 LLVMValueRef args [5];
5031 args [0] = v;
5032 args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
5033 args [2] = LLVMConstInt (LLVMInt32Type (), size, FALSE);
5034 args [3] = LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT, FALSE);
5035 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5036 LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memset.p0i8.i32"), args, 5, "");
5039 values [ins->dreg] = v;
5040 break;
5042 case OP_LOCALLOC: {
5043 LLVMValueRef v, size;
5045 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), "");
5047 v = mono_llvm_build_alloca (builder, LLVMInt8Type (), size, MONO_ARCH_FRAME_ALIGNMENT, "");
5049 if (ins->flags & MONO_INST_INIT) {
5050 LLVMValueRef args [5];
5052 args [0] = v;
5053 args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
5054 args [2] = size;
5055 args [3] = LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT, FALSE);
5056 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5057 LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memset.p0i8.i32"), args, 5, "");
5059 values [ins->dreg] = v;
5060 break;
5063 case OP_LOADI1_MEMBASE:
5064 case OP_LOADU1_MEMBASE:
5065 case OP_LOADI2_MEMBASE:
5066 case OP_LOADU2_MEMBASE:
5067 case OP_LOADI4_MEMBASE:
5068 case OP_LOADU4_MEMBASE:
5069 case OP_LOADI8_MEMBASE:
5070 case OP_LOADR4_MEMBASE:
5071 case OP_LOADR8_MEMBASE:
5072 case OP_LOAD_MEMBASE:
5073 case OP_LOADI8_MEM:
5074 case OP_LOADU1_MEM:
5075 case OP_LOADU2_MEM:
5076 case OP_LOADI4_MEM:
5077 case OP_LOADU4_MEM:
5078 case OP_LOAD_MEM: {
5079 int size = 8;
5080 LLVMValueRef base, index, addr;
5081 LLVMTypeRef t;
5082 gboolean sext = FALSE, zext = FALSE;
5083 gboolean is_volatile = (ins->flags & MONO_INST_FAULT);
5085 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5087 if (sext || zext)
5088 dname = (char*)"";
5090 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)) {
5091 addr = LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE);
5092 base = addr;
5093 } else {
5094 /* _MEMBASE */
5095 base = lhs;
5097 if (ins->inst_offset == 0) {
5098 addr = base;
5099 } else if (ins->inst_offset % size != 0) {
5100 /* Unaligned load */
5101 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
5102 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
5103 } else {
5104 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5105 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5109 addr = convert (ctx, addr, LLVMPointerType (t, 0));
5111 values [ins->dreg] = emit_load_general (ctx, bb, &builder, size, addr, base, dname, is_volatile, LLVM_BARRIER_NONE);
5113 if (!is_volatile && (ins->flags & MONO_INST_INVARIANT_LOAD)) {
5115 * These will signal LLVM that these loads do not alias any stores, and
5116 * they can't fail, allowing them to be hoisted out of loops.
5118 set_invariant_load_flag (values [ins->dreg]);
5119 #if LLVM_API_VERSION < 100
5120 set_metadata_flag (values [ins->dreg], "mono.nofail.load");
5121 #endif
5124 if (sext)
5125 values [ins->dreg] = LLVMBuildSExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5126 else if (zext)
5127 values [ins->dreg] = LLVMBuildZExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5128 else if (!cfg->r4fp && ins->opcode == OP_LOADR4_MEMBASE)
5129 values [ins->dreg] = LLVMBuildFPExt (builder, values [ins->dreg], LLVMDoubleType (), dname);
5130 break;
5133 case OP_STOREI1_MEMBASE_REG:
5134 case OP_STOREI2_MEMBASE_REG:
5135 case OP_STOREI4_MEMBASE_REG:
5136 case OP_STOREI8_MEMBASE_REG:
5137 case OP_STORER4_MEMBASE_REG:
5138 case OP_STORER8_MEMBASE_REG:
5139 case OP_STORE_MEMBASE_REG: {
5140 int size = 8;
5141 LLVMValueRef index, addr, base;
5142 LLVMTypeRef t;
5143 gboolean sext = FALSE, zext = FALSE;
5144 gboolean is_volatile = (ins->flags & MONO_INST_FAULT);
5146 if (!values [ins->inst_destbasereg]) {
5147 set_failure (ctx, "inst_destbasereg");
5148 break;
5151 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5153 base = values [ins->inst_destbasereg];
5154 if (ins->inst_offset % size != 0) {
5155 /* Unaligned store */
5156 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
5157 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
5158 } else {
5159 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5160 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5162 emit_store (ctx, bb, &builder, size, convert (ctx, values [ins->sreg1], t), convert (ctx, addr, LLVMPointerType (t, 0)), base, is_volatile);
5163 break;
5166 case OP_STOREI1_MEMBASE_IMM:
5167 case OP_STOREI2_MEMBASE_IMM:
5168 case OP_STOREI4_MEMBASE_IMM:
5169 case OP_STOREI8_MEMBASE_IMM:
5170 case OP_STORE_MEMBASE_IMM: {
5171 int size = 8;
5172 LLVMValueRef index, addr, base;
5173 LLVMTypeRef t;
5174 gboolean sext = FALSE, zext = FALSE;
5175 gboolean is_volatile = (ins->flags & MONO_INST_FAULT);
5177 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5179 base = values [ins->inst_destbasereg];
5180 if (ins->inst_offset % size != 0) {
5181 /* Unaligned store */
5182 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
5183 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
5184 } else {
5185 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5186 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5188 emit_store (ctx, bb, &builder, size, convert (ctx, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), t), convert (ctx, addr, LLVMPointerType (t, 0)), base, is_volatile);
5189 break;
5192 case OP_CHECK_THIS:
5193 emit_load_general (ctx, bb, &builder, sizeof (gpointer), convert (ctx, lhs, LLVMPointerType (IntPtrType (), 0)), lhs, "", TRUE, LLVM_BARRIER_NONE);
5194 break;
5195 case OP_OUTARG_VTRETADDR:
5196 break;
5197 case OP_VOIDCALL:
5198 case OP_CALL:
5199 case OP_LCALL:
5200 case OP_FCALL:
5201 case OP_RCALL:
5202 case OP_VCALL:
5203 case OP_VOIDCALL_MEMBASE:
5204 case OP_CALL_MEMBASE:
5205 case OP_LCALL_MEMBASE:
5206 case OP_FCALL_MEMBASE:
5207 case OP_RCALL_MEMBASE:
5208 case OP_VCALL_MEMBASE:
5209 case OP_VOIDCALL_REG:
5210 case OP_CALL_REG:
5211 case OP_LCALL_REG:
5212 case OP_FCALL_REG:
5213 case OP_RCALL_REG:
5214 case OP_VCALL_REG: {
5215 process_call (ctx, bb, &builder, ins);
5216 break;
5218 case OP_AOTCONST: {
5219 guint32 got_offset;
5220 LLVMValueRef indexes [2];
5221 MonoJumpInfo *tmp_ji, *ji;
5222 LLVMValueRef got_entry_addr;
5223 char *name;
5226 * FIXME: Can't allocate from the cfg mempool since that is freed if
5227 * the LLVM compile fails.
5229 tmp_ji = g_new0 (MonoJumpInfo, 1);
5230 tmp_ji->type = (MonoJumpInfoType)ins->inst_c1;
5231 tmp_ji->data.target = ins->inst_p0;
5233 ji = mono_aot_patch_info_dup (tmp_ji);
5234 g_free (tmp_ji);
5236 if (ji->type == MONO_PATCH_INFO_ICALL_ADDR) {
5237 char *symbol = mono_aot_get_direct_call_symbol (MONO_PATCH_INFO_ICALL_ADDR_CALL, ji->data.target);
5238 if (symbol) {
5240 * Avoid emitting a got entry for these since the method is directly called, and it might not be
5241 * resolvable at runtime using dlsym ().
5243 g_free (symbol);
5244 values [ins->dreg] = LLVMConstInt (IntPtrType (), 0, FALSE);
5245 break;
5249 ji->next = cfg->patch_info;
5250 cfg->patch_info = ji;
5252 //mono_add_patch_info (cfg, 0, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
5253 got_offset = mono_aot_get_got_offset (cfg->patch_info);
5254 ctx->module->max_got_offset = MAX (ctx->module->max_got_offset, got_offset);
5255 if (!mono_aot_is_shared_got_offset (got_offset)) {
5256 //mono_print_ji (ji);
5257 //printf ("\n");
5258 ctx->has_got_access = TRUE;
5261 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5262 indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
5263 got_entry_addr = LLVMBuildGEP (builder, ctx->module->got_var, indexes, 2, "");
5265 name = get_aotconst_name (ji->type, ji->data.target, got_offset);
5266 values [ins->dreg] = LLVMBuildLoad (builder, got_entry_addr, name);
5267 g_free (name);
5268 /* Can't use this in llvmonly mode since the got slots are initialized by the methods themselves */
5269 if (!cfg->llvm_only)
5270 set_invariant_load_flag (values [ins->dreg]);
5271 break;
5273 case OP_NOT_REACHED:
5274 LLVMBuildUnreachable (builder);
5275 has_terminator = TRUE;
5276 g_assert (bb->block_num < cfg->max_block_num);
5277 ctx->unreachable [bb->block_num] = TRUE;
5278 /* Might have instructions after this */
5279 while (ins->next) {
5280 MonoInst *next = ins->next;
5282 * FIXME: If later code uses the regs defined by these instructions,
5283 * compilation will fail.
5285 MONO_DELETE_INS (bb, next);
5287 break;
5288 case OP_LDADDR: {
5289 MonoInst *var = ins->inst_i0;
5291 if (var->opcode == OP_VTARG_ADDR) {
5292 /* The variable contains the vtype address */
5293 values [ins->dreg] = values [var->dreg];
5294 } else if (var->opcode == OP_GSHAREDVT_LOCAL) {
5295 values [ins->dreg] = emit_gsharedvt_ldaddr (ctx, var->dreg);
5296 } else {
5297 values [ins->dreg] = addresses [var->dreg];
5299 break;
5301 case OP_SIN: {
5302 LLVMValueRef args [1];
5304 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5305 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.sin.f64"), args, 1, dname);
5306 break;
5308 case OP_COS: {
5309 LLVMValueRef args [1];
5311 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5312 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.cos.f64"), args, 1, dname);
5313 break;
5315 case OP_SQRT: {
5316 LLVMValueRef args [1];
5318 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5319 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.sqrt.f64"), args, 1, dname);
5320 break;
5322 case OP_ABS: {
5323 LLVMValueRef args [1];
5325 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5326 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "fabs"), args, 1, dname);
5327 break;
5330 case OP_IMIN:
5331 case OP_LMIN:
5332 case OP_IMAX:
5333 case OP_LMAX:
5334 case OP_IMIN_UN:
5335 case OP_LMIN_UN:
5336 case OP_IMAX_UN:
5337 case OP_LMAX_UN: {
5338 LLVMValueRef v;
5340 lhs = convert (ctx, lhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
5341 rhs = convert (ctx, rhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
5343 switch (ins->opcode) {
5344 case OP_IMIN:
5345 case OP_LMIN:
5346 v = LLVMBuildICmp (builder, LLVMIntSLE, lhs, rhs, "");
5347 break;
5348 case OP_IMAX:
5349 case OP_LMAX:
5350 v = LLVMBuildICmp (builder, LLVMIntSGE, lhs, rhs, "");
5351 break;
5352 case OP_IMIN_UN:
5353 case OP_LMIN_UN:
5354 v = LLVMBuildICmp (builder, LLVMIntULE, lhs, rhs, "");
5355 break;
5356 case OP_IMAX_UN:
5357 case OP_LMAX_UN:
5358 v = LLVMBuildICmp (builder, LLVMIntUGE, lhs, rhs, "");
5359 break;
5360 default:
5361 g_assert_not_reached ();
5362 break;
5364 values [ins->dreg] = LLVMBuildSelect (builder, v, lhs, rhs, dname);
5365 break;
5367 case OP_ATOMIC_EXCHANGE_I4:
5368 case OP_ATOMIC_EXCHANGE_I8: {
5369 LLVMValueRef args [2];
5370 LLVMTypeRef t;
5372 if (ins->opcode == OP_ATOMIC_EXCHANGE_I4)
5373 t = LLVMInt32Type ();
5374 else
5375 t = LLVMInt64Type ();
5377 g_assert (ins->inst_offset == 0);
5379 args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
5380 args [1] = convert (ctx, rhs, t);
5382 values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
5383 break;
5385 case OP_ATOMIC_ADD_I4:
5386 case OP_ATOMIC_ADD_I8: {
5387 LLVMValueRef args [2];
5388 LLVMTypeRef t;
5390 if (ins->opcode == OP_ATOMIC_ADD_I4)
5391 t = LLVMInt32Type ();
5392 else
5393 t = LLVMInt64Type ();
5395 g_assert (ins->inst_offset == 0);
5397 args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
5398 args [1] = convert (ctx, rhs, t);
5399 values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname);
5400 break;
5402 case OP_ATOMIC_CAS_I4:
5403 case OP_ATOMIC_CAS_I8: {
5404 LLVMValueRef args [3], val;
5405 LLVMTypeRef t;
5407 if (ins->opcode == OP_ATOMIC_CAS_I4)
5408 t = LLVMInt32Type ();
5409 else
5410 t = LLVMInt64Type ();
5412 args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
5413 /* comparand */
5414 args [1] = convert (ctx, values [ins->sreg3], t);
5415 /* new value */
5416 args [2] = convert (ctx, values [ins->sreg2], t);
5417 val = mono_llvm_build_cmpxchg (builder, args [0], args [1], args [2]);
5418 /* cmpxchg returns a pair */
5419 values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, "");
5420 break;
5422 case OP_MEMORY_BARRIER: {
5423 mono_llvm_build_fence (builder, (BarrierKind) ins->backend.memory_barrier_kind);
5424 break;
5426 case OP_ATOMIC_LOAD_I1:
5427 case OP_ATOMIC_LOAD_I2:
5428 case OP_ATOMIC_LOAD_I4:
5429 case OP_ATOMIC_LOAD_I8:
5430 case OP_ATOMIC_LOAD_U1:
5431 case OP_ATOMIC_LOAD_U2:
5432 case OP_ATOMIC_LOAD_U4:
5433 case OP_ATOMIC_LOAD_U8:
5434 case OP_ATOMIC_LOAD_R4:
5435 case OP_ATOMIC_LOAD_R8: {
5436 #if LLVM_API_VERSION > 100
5437 int size;
5438 gboolean sext, zext;
5439 LLVMTypeRef t;
5440 gboolean is_volatile = (ins->flags & MONO_INST_FAULT);
5441 BarrierKind barrier = (BarrierKind) ins->backend.memory_barrier_kind;
5442 LLVMValueRef index, addr;
5444 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5446 if (sext || zext)
5447 dname = (char *)"";
5449 if (ins->inst_offset != 0) {
5450 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5451 addr = LLVMBuildGEP (builder, convert (ctx, lhs, LLVMPointerType (t, 0)), &index, 1, "");
5452 } else {
5453 addr = lhs;
5456 addr = convert (ctx, addr, LLVMPointerType (t, 0));
5458 values [ins->dreg] = emit_load_general (ctx, bb, &builder, size, addr, lhs, dname, is_volatile, barrier);
5460 if (sext)
5461 values [ins->dreg] = LLVMBuildSExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5462 else if (zext)
5463 values [ins->dreg] = LLVMBuildZExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5464 break;
5465 #else
5466 set_failure (ctx, "atomic mono.load intrinsic");
5467 break;
5468 #endif
5470 case OP_ATOMIC_STORE_I1:
5471 case OP_ATOMIC_STORE_I2:
5472 case OP_ATOMIC_STORE_I4:
5473 case OP_ATOMIC_STORE_I8:
5474 case OP_ATOMIC_STORE_U1:
5475 case OP_ATOMIC_STORE_U2:
5476 case OP_ATOMIC_STORE_U4:
5477 case OP_ATOMIC_STORE_U8:
5478 case OP_ATOMIC_STORE_R4:
5479 case OP_ATOMIC_STORE_R8: {
5480 int size;
5481 gboolean sext, zext;
5482 LLVMTypeRef t;
5483 gboolean is_volatile = (ins->flags & MONO_INST_FAULT);
5484 BarrierKind barrier = (BarrierKind) ins->backend.memory_barrier_kind;
5485 LLVMValueRef index, addr, value, base;
5487 #if LLVM_API_VERSION < 100
5488 if (!cfg->llvm_only) {
5489 set_failure (ctx, "atomic mono.store intrinsic");
5490 break;
5492 #endif
5494 if (!values [ins->inst_destbasereg]) {
5495 set_failure (ctx, "inst_destbasereg");
5496 break;
5499 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5501 base = values [ins->inst_destbasereg];
5502 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5503 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5504 value = convert (ctx, values [ins->sreg1], t);
5506 emit_store_general (ctx, bb, &builder, size, value, addr, base, is_volatile, barrier);
5507 break;
5509 case OP_RELAXED_NOP: {
5510 #if defined(TARGET_AMD64) || defined(TARGET_X86)
5511 emit_call (ctx, bb, &builder, get_intrinsic (ctx, "llvm.x86.sse2.pause"), NULL, 0);
5512 break;
5513 #else
5514 break;
5515 #endif
5517 case OP_TLS_GET: {
5518 #if (defined(TARGET_AMD64) || defined(TARGET_X86)) && defined(__linux__)
5519 #ifdef TARGET_AMD64
5520 // 257 == FS segment register
5521 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 257);
5522 #else
5523 // 256 == GS segment register
5524 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
5525 #endif
5526 // FIXME: XEN
5527 values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), ins->inst_offset, TRUE), ptrtype, ""), "");
5528 #elif defined(TARGET_AMD64) && defined(TARGET_OSX)
5529 /* See mono_amd64_emit_tls_get () */
5530 int offset = mono_amd64_get_tls_gs_offset () + (ins->inst_offset * 8);
5532 // 256 == GS segment register
5533 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
5534 values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), offset, TRUE), ptrtype, ""), "");
5535 #else
5536 set_failure (ctx, "opcode tls-get");
5537 break;
5538 #endif
5540 break;
5542 case OP_TLS_GET_REG: {
5543 #if defined(TARGET_AMD64) && defined(__linux__)
5544 // 257 == FS segment register
5545 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 257);
5546 values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, convert (ctx, lhs, LLVMInt64Type ()), ptrtype, ""), "");
5547 #elif defined(TARGET_AMD64) && defined(TARGET_OSX)
5548 /* See emit_tls_get_reg () */
5549 // 256 == GS segment register
5550 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
5551 values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, convert (ctx, lhs, LLVMInt32Type ()), ptrtype, ""), "");
5552 #else
5553 set_failure (ctx, "opcode tls-get");
5554 break;
5555 #endif
5556 break;
5559 case OP_TLS_SET_REG: {
5560 #if defined(TARGET_AMD64) && defined(TARGET_OSX)
5561 /* See emit_tls_get_reg () */
5562 // 256 == GS segment register
5563 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
5564 LLVMBuildStore (builder, convert (ctx, lhs, IntPtrType ()), LLVMBuildIntToPtr (builder, convert (ctx, rhs, LLVMInt32Type ()), ptrtype, ""));
5565 #else
5566 set_failure (ctx, "opcode tls-set-reg");
5567 break;
5568 #endif
5569 break;
5571 case OP_GC_SAFE_POINT: {
5572 LLVMValueRef val, cmp, callee;
5573 LLVMBasicBlockRef poll_bb, cont_bb;
5574 static LLVMTypeRef sig;
5575 const char *icall_name = "mono_threads_state_poll";
5577 if (!sig)
5578 sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
5581 * if (!*sreg1)
5582 * mono_threads_state_poll ();
5583 * FIXME: Use a preserveall wrapper
5585 val = mono_llvm_build_load (builder, convert (ctx, lhs, LLVMPointerType (IntPtrType (), 0)), "", TRUE);
5586 cmp = LLVMBuildICmp (builder, LLVMIntEQ, val, LLVMConstNull (LLVMTypeOf (val)), "");
5587 poll_bb = gen_bb (ctx, "POLL_BB");
5588 cont_bb = gen_bb (ctx, "CONT_BB");
5589 LLVMBuildCondBr (builder, cmp, cont_bb, poll_bb);
5591 ctx->builder = builder = create_builder (ctx);
5592 LLVMPositionBuilderAtEnd (builder, poll_bb);
5594 if (ctx->cfg->compile_aot) {
5595 callee = get_callee (ctx, sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
5596 } else {
5597 gpointer target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
5598 callee = emit_jit_callee (ctx, icall_name, sig, target);
5600 LLVMBuildCall (builder, callee, NULL, 0, "");
5601 LLVMBuildBr (builder, cont_bb);
5603 ctx->builder = builder = create_builder (ctx);
5604 LLVMPositionBuilderAtEnd (builder, cont_bb);
5605 ctx->bblocks [bb->block_num].end_bblock = cont_bb;
5606 break;
5610 * Overflow opcodes.
5612 case OP_IADD_OVF:
5613 case OP_IADD_OVF_UN:
5614 case OP_ISUB_OVF:
5615 case OP_ISUB_OVF_UN:
5616 case OP_IMUL_OVF:
5617 case OP_IMUL_OVF_UN:
5618 case OP_LADD_OVF:
5619 case OP_LADD_OVF_UN:
5620 case OP_LSUB_OVF:
5621 case OP_LSUB_OVF_UN:
5622 case OP_LMUL_OVF:
5623 case OP_LMUL_OVF_UN:
5625 LLVMValueRef args [2], val, ovf, func;
5627 args [0] = convert (ctx, lhs, op_to_llvm_type (ins->opcode));
5628 args [1] = convert (ctx, rhs, op_to_llvm_type (ins->opcode));
5629 func = get_intrinsic (ctx, ovf_op_to_intrins (ins->opcode));
5630 g_assert (func);
5631 val = LLVMBuildCall (builder, func, args, 2, "");
5632 values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, dname);
5633 ovf = LLVMBuildExtractValue (builder, val, 1, "");
5634 emit_cond_system_exception (ctx, bb, "OverflowException", ovf);
5635 if (!ctx_ok (ctx))
5636 break;
5637 builder = ctx->builder;
5638 break;
5642 * Valuetypes.
5643 * We currently model them using arrays. Promotion to local vregs is
5644 * disabled for them in mono_handle_global_vregs () in the LLVM case,
5645 * so we always have an entry in cfg->varinfo for them.
5646 * FIXME: Is this needed ?
5648 case OP_VZERO: {
5649 MonoClass *klass = ins->klass;
5650 LLVMValueRef args [5];
5652 if (!klass) {
5653 // FIXME:
5654 set_failure (ctx, "!klass");
5655 break;
5658 if (!addresses [ins->dreg])
5659 addresses [ins->dreg] = build_alloca (ctx, &klass->byval_arg);
5660 args [0] = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
5661 args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
5662 args [2] = LLVMConstInt (LLVMInt32Type (), mono_class_value_size (klass, NULL), FALSE);
5663 // FIXME: Alignment
5664 args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5665 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5666 LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memset.p0i8.i32"), args, 5, "");
5667 break;
5669 case OP_DUMMY_VZERO:
5670 break;
5672 case OP_STOREV_MEMBASE:
5673 case OP_LOADV_MEMBASE:
5674 case OP_VMOVE: {
5675 MonoClass *klass = ins->klass;
5676 LLVMValueRef src = NULL, dst, args [5];
5677 gboolean done = FALSE;
5679 if (!klass) {
5680 // FIXME:
5681 set_failure (ctx, "!klass");
5682 break;
5685 if (mini_is_gsharedvt_klass (klass)) {
5686 // FIXME:
5687 set_failure (ctx, "gsharedvt");
5688 break;
5691 switch (ins->opcode) {
5692 case OP_STOREV_MEMBASE:
5693 if (cfg->gen_write_barriers && klass->has_references && ins->inst_destbasereg != cfg->frame_reg &&
5694 LLVMGetInstructionOpcode (values [ins->inst_destbasereg]) != LLVMAlloca) {
5695 /* Decomposed earlier */
5696 g_assert_not_reached ();
5697 break;
5699 if (!addresses [ins->sreg1]) {
5700 /* SIMD */
5701 g_assert (values [ins->sreg1]);
5702 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));
5703 LLVMBuildStore (builder, values [ins->sreg1], dst);
5704 done = TRUE;
5705 } else {
5706 src = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (LLVMInt8Type (), 0), "");
5707 dst = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_destbasereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (LLVMInt8Type (), 0));
5709 break;
5710 case OP_LOADV_MEMBASE:
5711 if (!addresses [ins->dreg])
5712 addresses [ins->dreg] = build_alloca (ctx, &klass->byval_arg);
5713 src = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_basereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (LLVMInt8Type (), 0));
5714 dst = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
5715 break;
5716 case OP_VMOVE:
5717 if (!addresses [ins->sreg1])
5718 addresses [ins->sreg1] = build_alloca (ctx, &klass->byval_arg);
5719 if (!addresses [ins->dreg])
5720 addresses [ins->dreg] = build_alloca (ctx, &klass->byval_arg);
5721 src = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (LLVMInt8Type (), 0), "");
5722 dst = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
5723 break;
5724 default:
5725 g_assert_not_reached ();
5727 if (!ctx_ok (ctx))
5728 break;
5730 if (done)
5731 break;
5733 args [0] = dst;
5734 args [1] = src;
5735 args [2] = LLVMConstInt (LLVMInt32Type (), mono_class_value_size (klass, NULL), FALSE);
5736 args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5737 // FIXME: Alignment
5738 args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5739 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5740 LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memcpy.p0i8.p0i8.i32"), args, 5, "");
5741 break;
5743 case OP_LLVM_OUTARG_VT: {
5744 LLVMArgInfo *ainfo = (LLVMArgInfo*)ins->inst_p0;
5745 MonoType *t = mini_get_underlying_type (ins->inst_vtype);
5747 if (ainfo->storage == LLVMArgGsharedvtVariable) {
5748 MonoInst *var = get_vreg_to_inst (cfg, ins->sreg1);
5750 if (var && var->opcode == OP_GSHAREDVT_LOCAL) {
5751 addresses [ins->dreg] = convert (ctx, emit_gsharedvt_ldaddr (ctx, var->dreg), LLVMPointerType (IntPtrType (), 0));
5752 } else {
5753 g_assert (addresses [ins->sreg1]);
5754 addresses [ins->dreg] = addresses [ins->sreg1];
5756 } else if (ainfo->storage == LLVMArgGsharedvtFixed) {
5757 if (!addresses [ins->sreg1]) {
5758 addresses [ins->sreg1] = build_alloca (ctx, t);
5759 g_assert (values [ins->sreg1]);
5761 LLVMBuildStore (builder, convert (ctx, values [ins->sreg1], LLVMGetElementType (LLVMTypeOf (addresses [ins->sreg1]))), addresses [ins->sreg1]);
5762 addresses [ins->dreg] = addresses [ins->sreg1];
5763 } else {
5764 if (!addresses [ins->sreg1]) {
5765 addresses [ins->sreg1] = build_alloca (ctx, t);
5766 g_assert (values [ins->sreg1]);
5767 LLVMBuildStore (builder, convert (ctx, values [ins->sreg1], type_to_llvm_type (ctx, t)), addresses [ins->sreg1]);
5769 addresses [ins->dreg] = addresses [ins->sreg1];
5771 break;
5773 case OP_OBJC_GET_SELECTOR: {
5774 const char *name = (const char*)ins->inst_p0;
5775 LLVMValueRef var;
5777 if (!ctx->module->objc_selector_to_var)
5778 ctx->module->objc_selector_to_var = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
5779 var = g_hash_table_lookup (ctx->module->objc_selector_to_var, name);
5780 if (!var) {
5781 LLVMValueRef indexes [16];
5783 LLVMValueRef name_var = LLVMAddGlobal (ctx->lmodule, LLVMArrayType (LLVMInt8Type (), strlen (name) + 1), "@OBJC_METH_VAR_NAME");
5784 LLVMSetInitializer (name_var, mono_llvm_create_constant_data_array ((const uint8_t*)name, strlen (name) + 1));
5785 LLVMSetLinkage (name_var, LLVMPrivateLinkage);
5786 LLVMSetSection (name_var, "__TEXT,__objc_methname,cstring_literals");
5788 LLVMValueRef ref_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (LLVMInt8Type (), 0), "@OBJC_SELECTOR_REFERENCES");
5790 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, 0);
5791 indexes [1] = LLVMConstInt (LLVMInt32Type (), 0, 0);
5792 LLVMSetInitializer (ref_var, LLVMConstGEP (name_var, indexes, 2));
5793 LLVMSetLinkage (ref_var, LLVMPrivateLinkage);
5794 LLVMSetExternallyInitialized (ref_var, TRUE);
5795 LLVMSetSection (ref_var, "__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
5796 LLVMSetAlignment (ref_var, sizeof (mgreg_t));
5798 g_hash_table_insert (ctx->module->objc_selector_to_var, g_strdup (name), ref_var);
5799 var = ref_var;
5802 values [ins->dreg] = LLVMBuildLoad (builder, var, "");
5803 break;
5807 * SIMD
5809 #if defined(TARGET_X86) || defined(TARGET_AMD64)
5810 case OP_XZERO: {
5811 values [ins->dreg] = LLVMConstNull (type_to_llvm_type (ctx, &ins->klass->byval_arg));
5812 break;
5814 case OP_LOADX_MEMBASE: {
5815 LLVMTypeRef t = type_to_llvm_type (ctx, &ins->klass->byval_arg);
5816 LLVMValueRef src;
5818 src = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_basereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (t, 0));
5819 values [ins->dreg] = mono_llvm_build_aligned_load (builder, src, "", FALSE, 1);
5820 break;
5822 case OP_STOREX_MEMBASE: {
5823 LLVMTypeRef t = LLVMTypeOf (values [ins->sreg1]);
5824 LLVMValueRef dest;
5826 dest = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_destbasereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (t, 0));
5827 mono_llvm_build_aligned_store (builder, values [ins->sreg1], dest, FALSE, 1);
5828 break;
5830 case OP_PADDB:
5831 case OP_PADDW:
5832 case OP_PADDD:
5833 case OP_PADDQ:
5834 values [ins->dreg] = LLVMBuildAdd (builder, lhs, rhs, "");
5835 break;
5836 case OP_ADDPD:
5837 case OP_ADDPS:
5838 values [ins->dreg] = LLVMBuildFAdd (builder, lhs, rhs, "");
5839 break;
5840 case OP_PSUBB:
5841 case OP_PSUBW:
5842 case OP_PSUBD:
5843 case OP_PSUBQ:
5844 values [ins->dreg] = LLVMBuildSub (builder, lhs, rhs, "");
5845 break;
5846 case OP_SUBPD:
5847 case OP_SUBPS:
5848 values [ins->dreg] = LLVMBuildFSub (builder, lhs, rhs, "");
5849 break;
5850 case OP_MULPD:
5851 case OP_MULPS:
5852 values [ins->dreg] = LLVMBuildFMul (builder, lhs, rhs, "");
5853 break;
5854 case OP_DIVPD:
5855 case OP_DIVPS:
5856 values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, "");
5857 break;
5858 case OP_PAND:
5859 values [ins->dreg] = LLVMBuildAnd (builder, lhs, rhs, "");
5860 break;
5861 case OP_POR:
5862 values [ins->dreg] = LLVMBuildOr (builder, lhs, rhs, "");
5863 break;
5864 case OP_PXOR:
5865 values [ins->dreg] = LLVMBuildXor (builder, lhs, rhs, "");
5866 break;
5867 case OP_PMULW:
5868 case OP_PMULD:
5869 values [ins->dreg] = LLVMBuildMul (builder, lhs, rhs, "");
5870 break;
5871 case OP_ANDPS:
5872 case OP_ANDNPS:
5873 case OP_ORPS:
5874 case OP_XORPS:
5875 case OP_ANDPD:
5876 case OP_ANDNPD:
5877 case OP_ORPD:
5878 case OP_XORPD: {
5879 LLVMTypeRef t, rt;
5880 LLVMValueRef v = NULL;
5882 switch (ins->opcode) {
5883 case OP_ANDPS:
5884 case OP_ANDNPS:
5885 case OP_ORPS:
5886 case OP_XORPS:
5887 t = LLVMVectorType (LLVMInt32Type (), 4);
5888 rt = LLVMVectorType (LLVMFloatType (), 4);
5889 break;
5890 case OP_ANDPD:
5891 case OP_ANDNPD:
5892 case OP_ORPD:
5893 case OP_XORPD:
5894 t = LLVMVectorType (LLVMInt64Type (), 2);
5895 rt = LLVMVectorType (LLVMDoubleType (), 2);
5896 break;
5897 default:
5898 t = LLVMInt32Type ();
5899 rt = LLVMInt32Type ();
5900 g_assert_not_reached ();
5903 lhs = LLVMBuildBitCast (builder, lhs, t, "");
5904 rhs = LLVMBuildBitCast (builder, rhs, t, "");
5905 switch (ins->opcode) {
5906 case OP_ANDPS:
5907 case OP_ANDPD:
5908 v = LLVMBuildAnd (builder, lhs, rhs, "");
5909 break;
5910 case OP_ORPS:
5911 case OP_ORPD:
5912 v = LLVMBuildOr (builder, lhs, rhs, "");
5913 break;
5914 case OP_XORPS:
5915 case OP_XORPD:
5916 v = LLVMBuildXor (builder, lhs, rhs, "");
5917 break;
5918 case OP_ANDNPS:
5919 case OP_ANDNPD:
5920 v = LLVMBuildAnd (builder, rhs, LLVMBuildNot (builder, lhs, ""), "");
5921 break;
5923 values [ins->dreg] = LLVMBuildBitCast (builder, v, rt, "");
5924 break;
5926 case OP_PMIND_UN:
5927 case OP_PMINW_UN:
5928 case OP_PMINB_UN: {
5929 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntULT, lhs, rhs, "");
5930 values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
5931 break;
5933 case OP_PMAXD_UN:
5934 case OP_PMAXW_UN:
5935 case OP_PMAXB_UN: {
5936 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntUGT, lhs, rhs, "");
5937 values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
5938 break;
5940 case OP_PMINW: {
5941 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntSLT, lhs, rhs, "");
5942 values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
5943 break;
5945 case OP_MINPD:
5946 case OP_MINPS:
5947 case OP_MAXPD:
5948 case OP_MAXPS:
5949 case OP_ADDSUBPD:
5950 case OP_ADDSUBPS:
5951 case OP_HADDPD:
5952 case OP_HADDPS:
5953 case OP_HSUBPD:
5954 case OP_HSUBPS:
5955 case OP_PADDB_SAT:
5956 case OP_PADDW_SAT:
5957 case OP_PSUBB_SAT:
5958 case OP_PSUBW_SAT:
5959 case OP_PADDB_SAT_UN:
5960 case OP_PADDW_SAT_UN:
5961 case OP_PSUBB_SAT_UN:
5962 case OP_PSUBW_SAT_UN:
5963 case OP_PAVGB_UN:
5964 case OP_PAVGW_UN:
5965 case OP_PACKW:
5966 case OP_PACKD:
5967 case OP_PACKW_UN:
5968 case OP_PACKD_UN:
5969 case OP_PMULW_HIGH:
5970 case OP_PMULW_HIGH_UN: {
5971 LLVMValueRef args [2];
5973 args [0] = lhs;
5974 args [1] = rhs;
5976 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
5977 break;
5979 case OP_PCMPEQB:
5980 case OP_PCMPEQW:
5981 case OP_PCMPEQD:
5982 case OP_PCMPEQQ: {
5983 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildICmp (builder, LLVMIntEQ, lhs, rhs, ""), LLVMTypeOf (lhs), "");
5984 break;
5986 case OP_PCMPGTB: {
5987 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildICmp (builder, LLVMIntSGT, lhs, rhs, ""), LLVMTypeOf (lhs), "");
5988 break;
5990 case OP_EXTRACT_R8:
5991 case OP_EXTRACT_I8:
5992 case OP_EXTRACT_I4:
5993 case OP_EXTRACT_I2:
5994 case OP_EXTRACT_U2:
5995 case OP_EXTRACTX_U2:
5996 case OP_EXTRACT_I1:
5997 case OP_EXTRACT_U1: {
5998 LLVMTypeRef t;
5999 gboolean zext = FALSE;
6001 t = simd_op_to_llvm_type (ins->opcode);
6003 switch (ins->opcode) {
6004 case OP_EXTRACT_R8:
6005 case OP_EXTRACT_I8:
6006 case OP_EXTRACT_I4:
6007 case OP_EXTRACT_I2:
6008 case OP_EXTRACT_I1:
6009 break;
6010 case OP_EXTRACT_U2:
6011 case OP_EXTRACTX_U2:
6012 case OP_EXTRACT_U1:
6013 zext = TRUE;
6014 break;
6015 default:
6016 t = LLVMInt32Type ();
6017 g_assert_not_reached ();
6020 lhs = LLVMBuildBitCast (builder, lhs, t, "");
6021 values [ins->dreg] = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), "");
6022 if (zext)
6023 values [ins->dreg] = LLVMBuildZExt (builder, values [ins->dreg], LLVMInt32Type (), "");
6024 break;
6027 case OP_EXPAND_I1:
6028 case OP_EXPAND_I2:
6029 case OP_EXPAND_I4:
6030 case OP_EXPAND_I8:
6031 case OP_EXPAND_R4:
6032 case OP_EXPAND_R8: {
6033 LLVMTypeRef t = simd_op_to_llvm_type (ins->opcode);
6034 LLVMValueRef mask [16], v;
6035 int i;
6037 for (i = 0; i < 16; ++i)
6038 mask [i] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6040 v = convert (ctx, values [ins->sreg1], LLVMGetElementType (t));
6042 values [ins->dreg] = LLVMBuildInsertElement (builder, LLVMConstNull (t), v, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6043 values [ins->dreg] = LLVMBuildShuffleVector (builder, values [ins->dreg], LLVMGetUndef (t), LLVMConstVector (mask, LLVMGetVectorSize (t)), "");
6044 break;
6047 case OP_INSERT_I1:
6048 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt8Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6049 break;
6050 case OP_INSERT_I2:
6051 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt16Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6052 break;
6053 case OP_INSERT_I4:
6054 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt32Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6055 break;
6056 case OP_INSERT_I8:
6057 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt64Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6058 break;
6059 case OP_INSERT_R4:
6060 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMFloatType ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6061 break;
6062 case OP_INSERT_R8:
6063 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMDoubleType ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6064 break;
6066 case OP_CVTDQ2PD:
6067 case OP_CVTDQ2PS:
6068 case OP_CVTPD2DQ:
6069 case OP_CVTPS2DQ:
6070 case OP_CVTPD2PS:
6071 case OP_CVTPS2PD:
6072 case OP_CVTTPD2DQ:
6073 case OP_CVTTPS2DQ:
6074 case OP_EXTRACT_MASK:
6075 case OP_SQRTPS:
6076 case OP_SQRTPD:
6077 case OP_RSQRTPS:
6078 case OP_RCPPS: {
6079 LLVMValueRef v;
6081 v = convert (ctx, values [ins->sreg1], simd_op_to_llvm_type (ins->opcode));
6083 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), &v, 1, dname);
6084 break;
6086 case OP_COMPPS:
6087 case OP_COMPPD: {
6088 LLVMRealPredicate op;
6090 switch (ins->inst_c0) {
6091 case SIMD_COMP_EQ:
6092 op = LLVMRealOEQ;
6093 break;
6094 case SIMD_COMP_LT:
6095 op = LLVMRealOLT;
6096 break;
6097 case SIMD_COMP_LE:
6098 op = LLVMRealOLE;
6099 break;
6100 case SIMD_COMP_UNORD:
6101 op = LLVMRealUNO;
6102 break;
6103 case SIMD_COMP_NEQ:
6104 op = LLVMRealUNE;
6105 break;
6106 case SIMD_COMP_NLT:
6107 op = LLVMRealUGE;
6108 break;
6109 case SIMD_COMP_NLE:
6110 op = LLVMRealUGT;
6111 break;
6112 case SIMD_COMP_ORD:
6113 op = LLVMRealORD;
6114 break;
6115 default:
6116 g_assert_not_reached ();
6119 LLVMValueRef cmp = LLVMBuildFCmp (builder, op, lhs, rhs, "");
6120 if (ins->opcode == OP_COMPPD)
6121 values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildSExt (builder, cmp, LLVMVectorType (LLVMInt64Type (), 2), ""), LLVMTypeOf (lhs), "");
6122 else
6123 values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildSExt (builder, cmp, LLVMVectorType (LLVMInt32Type (), 4), ""), LLVMTypeOf (lhs), "");
6124 break;
6126 case OP_ICONV_TO_X:
6127 /* This is only used for implementing shifts by non-immediate */
6128 values [ins->dreg] = lhs;
6129 break;
6131 case OP_PSHRW:
6132 case OP_PSHRD:
6133 case OP_PSHRQ:
6134 case OP_PSARW:
6135 case OP_PSARD:
6136 case OP_PSHLW:
6137 case OP_PSHLD:
6138 case OP_PSHLQ: {
6139 LLVMValueRef args [3];
6141 args [0] = lhs;
6142 args [1] = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
6144 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6145 break;
6148 case OP_PSHRW_REG:
6149 case OP_PSHRD_REG:
6150 case OP_PSHRQ_REG:
6151 case OP_PSARW_REG:
6152 case OP_PSARD_REG:
6153 case OP_PSHLW_REG:
6154 case OP_PSHLD_REG:
6155 case OP_PSHLQ_REG: {
6156 LLVMValueRef args [3];
6158 args [0] = lhs;
6159 args [1] = values [ins->sreg2];
6161 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6162 break;
6165 case OP_SHUFPS:
6166 case OP_SHUFPD:
6167 case OP_PSHUFLED:
6168 case OP_PSHUFLEW_LOW:
6169 case OP_PSHUFLEW_HIGH: {
6170 int mask [16];
6171 LLVMValueRef v1 = NULL, v2 = NULL, mask_values [16];
6172 int i, mask_size = 0;
6173 int imask = ins->inst_c0;
6175 /* Convert the x86 shuffle mask to LLVM's */
6176 switch (ins->opcode) {
6177 case OP_SHUFPS:
6178 mask_size = 4;
6179 mask [0] = ((imask >> 0) & 3);
6180 mask [1] = ((imask >> 2) & 3);
6181 mask [2] = ((imask >> 4) & 3) + 4;
6182 mask [3] = ((imask >> 6) & 3) + 4;
6183 v1 = values [ins->sreg1];
6184 v2 = values [ins->sreg2];
6185 break;
6186 case OP_SHUFPD:
6187 mask_size = 2;
6188 mask [0] = ((imask >> 0) & 1);
6189 mask [1] = ((imask >> 1) & 1) + 2;
6190 v1 = values [ins->sreg1];
6191 v2 = values [ins->sreg2];
6192 break;
6193 case OP_PSHUFLEW_LOW:
6194 mask_size = 8;
6195 mask [0] = ((imask >> 0) & 3);
6196 mask [1] = ((imask >> 2) & 3);
6197 mask [2] = ((imask >> 4) & 3);
6198 mask [3] = ((imask >> 6) & 3);
6199 mask [4] = 4 + 0;
6200 mask [5] = 4 + 1;
6201 mask [6] = 4 + 2;
6202 mask [7] = 4 + 3;
6203 v1 = values [ins->sreg1];
6204 v2 = LLVMGetUndef (LLVMTypeOf (v1));
6205 break;
6206 case OP_PSHUFLEW_HIGH:
6207 mask_size = 8;
6208 mask [0] = 0;
6209 mask [1] = 1;
6210 mask [2] = 2;
6211 mask [3] = 3;
6212 mask [4] = 4 + ((imask >> 0) & 3);
6213 mask [5] = 4 + ((imask >> 2) & 3);
6214 mask [6] = 4 + ((imask >> 4) & 3);
6215 mask [7] = 4 + ((imask >> 6) & 3);
6216 v1 = values [ins->sreg1];
6217 v2 = LLVMGetUndef (LLVMTypeOf (v1));
6218 break;
6219 case OP_PSHUFLED:
6220 mask_size = 4;
6221 mask [0] = ((imask >> 0) & 3);
6222 mask [1] = ((imask >> 2) & 3);
6223 mask [2] = ((imask >> 4) & 3);
6224 mask [3] = ((imask >> 6) & 3);
6225 v1 = values [ins->sreg1];
6226 v2 = LLVMGetUndef (LLVMTypeOf (v1));
6227 break;
6228 default:
6229 g_assert_not_reached ();
6231 for (i = 0; i < mask_size; ++i)
6232 mask_values [i] = LLVMConstInt (LLVMInt32Type (), mask [i], FALSE);
6234 values [ins->dreg] =
6235 LLVMBuildShuffleVector (builder, v1, v2,
6236 LLVMConstVector (mask_values, mask_size), dname);
6237 break;
6240 case OP_UNPACK_LOWB:
6241 case OP_UNPACK_LOWW:
6242 case OP_UNPACK_LOWD:
6243 case OP_UNPACK_LOWQ:
6244 case OP_UNPACK_LOWPS:
6245 case OP_UNPACK_LOWPD:
6246 case OP_UNPACK_HIGHB:
6247 case OP_UNPACK_HIGHW:
6248 case OP_UNPACK_HIGHD:
6249 case OP_UNPACK_HIGHQ:
6250 case OP_UNPACK_HIGHPS:
6251 case OP_UNPACK_HIGHPD: {
6252 int mask [16];
6253 LLVMValueRef mask_values [16];
6254 int i, mask_size = 0;
6255 gboolean low = FALSE;
6257 switch (ins->opcode) {
6258 case OP_UNPACK_LOWB:
6259 mask_size = 16;
6260 low = TRUE;
6261 break;
6262 case OP_UNPACK_LOWW:
6263 mask_size = 8;
6264 low = TRUE;
6265 break;
6266 case OP_UNPACK_LOWD:
6267 case OP_UNPACK_LOWPS:
6268 mask_size = 4;
6269 low = TRUE;
6270 break;
6271 case OP_UNPACK_LOWQ:
6272 case OP_UNPACK_LOWPD:
6273 mask_size = 2;
6274 low = TRUE;
6275 break;
6276 case OP_UNPACK_HIGHB:
6277 mask_size = 16;
6278 break;
6279 case OP_UNPACK_HIGHW:
6280 mask_size = 8;
6281 break;
6282 case OP_UNPACK_HIGHD:
6283 case OP_UNPACK_HIGHPS:
6284 mask_size = 4;
6285 break;
6286 case OP_UNPACK_HIGHQ:
6287 case OP_UNPACK_HIGHPD:
6288 mask_size = 2;
6289 break;
6290 default:
6291 g_assert_not_reached ();
6294 if (low) {
6295 for (i = 0; i < (mask_size / 2); ++i) {
6296 mask [(i * 2)] = i;
6297 mask [(i * 2) + 1] = mask_size + i;
6299 } else {
6300 for (i = 0; i < (mask_size / 2); ++i) {
6301 mask [(i * 2)] = (mask_size / 2) + i;
6302 mask [(i * 2) + 1] = mask_size + (mask_size / 2) + i;
6306 for (i = 0; i < mask_size; ++i)
6307 mask_values [i] = LLVMConstInt (LLVMInt32Type (), mask [i], FALSE);
6309 values [ins->dreg] =
6310 LLVMBuildShuffleVector (builder, values [ins->sreg1], values [ins->sreg2],
6311 LLVMConstVector (mask_values, mask_size), dname);
6312 break;
6315 case OP_DUPPD: {
6316 LLVMTypeRef t = simd_op_to_llvm_type (ins->opcode);
6317 LLVMValueRef v, val;
6319 v = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6320 val = LLVMConstNull (t);
6321 val = LLVMBuildInsertElement (builder, val, v, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6322 val = LLVMBuildInsertElement (builder, val, v, LLVMConstInt (LLVMInt32Type (), 1, FALSE), dname);
6324 values [ins->dreg] = val;
6325 break;
6327 case OP_DUPPS_LOW:
6328 case OP_DUPPS_HIGH: {
6329 LLVMTypeRef t = simd_op_to_llvm_type (ins->opcode);
6330 LLVMValueRef v1, v2, val;
6333 if (ins->opcode == OP_DUPPS_LOW) {
6334 v1 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6335 v2 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 2, FALSE), "");
6336 } else {
6337 v1 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 1, FALSE), "");
6338 v2 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 3, FALSE), "");
6340 val = LLVMConstNull (t);
6341 val = LLVMBuildInsertElement (builder, val, v1, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6342 val = LLVMBuildInsertElement (builder, val, v1, LLVMConstInt (LLVMInt32Type (), 1, FALSE), "");
6343 val = LLVMBuildInsertElement (builder, val, v2, LLVMConstInt (LLVMInt32Type (), 2, FALSE), "");
6344 val = LLVMBuildInsertElement (builder, val, v2, LLVMConstInt (LLVMInt32Type (), 3, FALSE), "");
6346 values [ins->dreg] = val;
6347 break;
6350 #endif /* SIMD */
6352 case OP_DUMMY_USE:
6353 break;
6356 * EXCEPTION HANDLING
6358 case OP_IMPLICIT_EXCEPTION:
6359 /* This marks a place where an implicit exception can happen */
6360 if (bb->region != -1)
6361 set_failure (ctx, "implicit-exception");
6362 break;
6363 case OP_THROW:
6364 case OP_RETHROW: {
6365 gboolean rethrow = (ins->opcode == OP_RETHROW);
6366 if (ctx->llvm_only) {
6367 emit_llvmonly_throw (ctx, bb, rethrow, lhs);
6368 has_terminator = TRUE;
6369 ctx->unreachable [bb->block_num] = TRUE;
6370 } else {
6371 emit_throw (ctx, bb, rethrow, lhs);
6372 builder = ctx->builder;
6374 break;
6376 case OP_CALL_HANDLER: {
6378 * We don't 'call' handlers, but instead simply branch to them.
6379 * The code generated by ENDFINALLY will branch back to us.
6381 LLVMBasicBlockRef noex_bb;
6382 GSList *bb_list;
6383 BBInfo *info = &bblocks [ins->inst_target_bb->block_num];
6385 bb_list = info->call_handler_return_bbs;
6388 * Set the indicator variable for the finally clause.
6390 lhs = info->finally_ind;
6391 g_assert (lhs);
6392 LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), g_slist_length (bb_list) + 1, FALSE), lhs);
6394 /* Branch to the finally clause */
6395 LLVMBuildBr (builder, info->call_handler_target_bb);
6397 noex_bb = gen_bb (ctx, "CALL_HANDLER_CONT_BB");
6398 info->call_handler_return_bbs = g_slist_append_mempool (cfg->mempool, info->call_handler_return_bbs, noex_bb);
6400 builder = ctx->builder = create_builder (ctx);
6401 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
6403 bblocks [bb->block_num].end_bblock = noex_bb;
6404 break;
6406 case OP_START_HANDLER: {
6407 break;
6409 case OP_ENDFINALLY: {
6410 LLVMBasicBlockRef resume_bb;
6411 MonoBasicBlock *handler_bb;
6412 LLVMValueRef val, switch_ins, callee;
6413 GSList *bb_list;
6414 BBInfo *info;
6416 handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)));
6417 g_assert (handler_bb);
6418 info = &bblocks [handler_bb->block_num];
6419 lhs = info->finally_ind;
6420 g_assert (lhs);
6422 bb_list = info->call_handler_return_bbs;
6424 resume_bb = gen_bb (ctx, "ENDFINALLY_RESUME_BB");
6426 /* Load the finally variable */
6427 val = LLVMBuildLoad (builder, lhs, "");
6429 /* Reset the variable */
6430 LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), lhs);
6432 /* Branch to either resume_bb, or to the bblocks in bb_list */
6433 switch_ins = LLVMBuildSwitch (builder, val, resume_bb, g_slist_length (bb_list));
6435 * The other targets are added at the end to handle OP_CALL_HANDLER
6436 * opcodes processed later.
6438 info->endfinally_switch_ins_list = g_slist_append_mempool (cfg->mempool, info->endfinally_switch_ins_list, switch_ins);
6440 builder = ctx->builder = create_builder (ctx);
6441 LLVMPositionBuilderAtEnd (ctx->builder, resume_bb);
6443 if (ctx->llvm_only) {
6444 emit_resume_eh (ctx, bb);
6445 } else {
6446 if (ctx->cfg->compile_aot) {
6447 callee = get_callee (ctx, LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE), MONO_PATCH_INFO_INTERNAL_METHOD, "llvm_resume_unwind_trampoline");
6448 } else {
6449 #if LLVM_API_VERSION > 100
6450 MonoJitICallInfo *info;
6452 info = mono_find_jit_icall_by_name ("llvm_resume_unwind_trampoline");
6453 g_assert (info);
6454 gpointer target = (void*)info->func;
6455 LLVMTypeRef icall_sig = LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE);
6456 callee = emit_jit_callee (ctx, "llvm_resume_unwind_trampoline", icall_sig, target);
6457 #else
6458 callee = LLVMGetNamedFunction (ctx->lmodule, "llvm_resume_unwind_trampoline");
6459 #endif
6461 LLVMBuildCall (builder, callee, NULL, 0, "");
6462 LLVMBuildUnreachable (builder);
6465 has_terminator = TRUE;
6466 break;
6468 case OP_IL_SEQ_POINT:
6469 break;
6470 default: {
6471 char reason [128];
6473 sprintf (reason, "opcode %s", mono_inst_name (ins->opcode));
6474 set_failure (ctx, reason);
6475 break;
6479 if (!ctx_ok (ctx))
6480 break;
6482 /* Convert the value to the type required by phi nodes */
6483 if (spec [MONO_INST_DEST] != ' ' && !MONO_IS_STORE_MEMBASE (ins) && ctx->vreg_types [ins->dreg]) {
6484 if (!values [ins->dreg])
6485 /* vtypes */
6486 values [ins->dreg] = addresses [ins->dreg];
6487 else
6488 values [ins->dreg] = convert (ctx, values [ins->dreg], ctx->vreg_types [ins->dreg]);
6491 /* Add stores for volatile variables */
6492 if (spec [MONO_INST_DEST] != ' ' && spec [MONO_INST_DEST] != 'v' && !MONO_IS_STORE_MEMBASE (ins))
6493 emit_volatile_store (ctx, ins->dreg);
6496 if (!ctx_ok (ctx))
6497 return;
6499 if (!has_terminator && bb->next_bb && (bb == cfg->bb_entry || bb->in_count > 0)) {
6500 LLVMBuildBr (builder, get_bb (ctx, bb->next_bb));
6503 if (bb == cfg->bb_exit && sig->ret->type == MONO_TYPE_VOID) {
6504 emit_dbg_loc (ctx, builder, cfg->header->code + cfg->header->code_size - 1);
6505 LLVMBuildRetVoid (builder);
6508 if (bb == cfg->bb_entry)
6509 ctx->last_alloca = LLVMGetLastInstruction (get_bb (ctx, cfg->bb_entry));
6513 * mono_llvm_check_method_supported:
6515 * Do some quick checks to decide whenever cfg->method can be compiled by LLVM, to avoid
6516 * compiling a method twice.
6518 void
6519 mono_llvm_check_method_supported (MonoCompile *cfg)
6521 int i, j;
6523 if (cfg->llvm_only)
6524 return;
6526 if (cfg->method->save_lmf) {
6527 cfg->exception_message = g_strdup ("lmf");
6528 cfg->disable_llvm = TRUE;
6530 if (cfg->disable_llvm)
6531 return;
6534 * Nested clauses where one of the clauses is a finally clause is
6535 * not supported, because LLVM can't figure out the control flow,
6536 * probably because we resume exception handling by calling our
6537 * own function instead of using the 'resume' llvm instruction.
6539 for (i = 0; i < cfg->header->num_clauses; ++i) {
6540 for (j = 0; j < cfg->header->num_clauses; ++j) {
6541 MonoExceptionClause *clause1 = &cfg->header->clauses [i];
6542 MonoExceptionClause *clause2 = &cfg->header->clauses [j];
6544 // FIXME: Nested try clauses fail in some cases too, i.e. #37273
6545 if (i != j && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
6546 //(clause1->flags == MONO_EXCEPTION_CLAUSE_FINALLY || clause2->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
6547 cfg->exception_message = g_strdup ("nested clauses");
6548 cfg->disable_llvm = TRUE;
6549 break;
6553 if (cfg->disable_llvm)
6554 return;
6556 /* FIXME: */
6557 if (cfg->method->dynamic) {
6558 cfg->exception_message = g_strdup ("dynamic.");
6559 cfg->disable_llvm = TRUE;
6561 if (cfg->disable_llvm)
6562 return;
6565 static LLVMCallInfo*
6566 get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
6568 LLVMCallInfo *linfo;
6569 int i;
6571 if (cfg->gsharedvt && cfg->llvm_only && mini_is_gsharedvt_variable_signature (sig)) {
6572 int i, n, pindex;
6575 * Gsharedvt methods have the following calling convention:
6576 * - all arguments are passed by ref, even non generic ones
6577 * - the return value is returned by ref too, using a vret
6578 * argument passed after 'this'.
6580 n = sig->param_count + sig->hasthis;
6581 linfo = (LLVMCallInfo*)mono_mempool_alloc0 (cfg->mempool, sizeof (LLVMCallInfo) + (sizeof (LLVMArgInfo) * n));
6583 pindex = 0;
6584 if (sig->hasthis)
6585 linfo->args [pindex ++].storage = LLVMArgNormal;
6587 if (sig->ret->type != MONO_TYPE_VOID) {
6588 if (mini_is_gsharedvt_variable_type (sig->ret))
6589 linfo->ret.storage = LLVMArgGsharedvtVariable;
6590 else if (mini_type_is_vtype (sig->ret))
6591 linfo->ret.storage = LLVMArgGsharedvtFixedVtype;
6592 else
6593 linfo->ret.storage = LLVMArgGsharedvtFixed;
6594 linfo->vret_arg_index = pindex;
6595 } else {
6596 linfo->ret.storage = LLVMArgNone;
6599 for (i = 0; i < sig->param_count; ++i) {
6600 if (sig->params [i]->byref)
6601 linfo->args [pindex].storage = LLVMArgNormal;
6602 else if (mini_is_gsharedvt_variable_type (sig->params [i]))
6603 linfo->args [pindex].storage = LLVMArgGsharedvtVariable;
6604 else if (mini_type_is_vtype (sig->params [i]))
6605 linfo->args [pindex].storage = LLVMArgGsharedvtFixedVtype;
6606 else
6607 linfo->args [pindex].storage = LLVMArgGsharedvtFixed;
6608 linfo->args [pindex].type = sig->params [i];
6609 pindex ++;
6611 return linfo;
6615 linfo = mono_arch_get_llvm_call_info (cfg, sig);
6616 for (i = 0; i < sig->param_count; ++i)
6617 linfo->args [i + sig->hasthis].type = sig->params [i];
6619 return linfo;
6622 static void
6623 emit_method_inner (EmitContext *ctx);
6625 static void
6626 free_ctx (EmitContext *ctx)
6628 GSList *l;
6630 g_free (ctx->values);
6631 g_free (ctx->addresses);
6632 g_free (ctx->vreg_types);
6633 g_free (ctx->vreg_cli_types);
6634 g_free (ctx->is_dead);
6635 g_free (ctx->unreachable);
6636 g_ptr_array_free (ctx->phi_values, TRUE);
6637 g_free (ctx->bblocks);
6638 g_hash_table_destroy (ctx->region_to_handler);
6639 g_hash_table_destroy (ctx->clause_to_handler);
6640 g_hash_table_destroy (ctx->jit_callees);
6642 GHashTableIter iter;
6643 g_hash_table_iter_init (&iter, ctx->method_to_callers);
6644 while (g_hash_table_iter_next (&iter, NULL, (gpointer)&l))
6645 g_slist_free (l);
6647 g_hash_table_destroy (ctx->method_to_callers);
6649 g_free (ctx->method_name);
6650 g_ptr_array_free (ctx->bblock_list, TRUE);
6652 for (l = ctx->builders; l; l = l->next) {
6653 LLVMBuilderRef builder = (LLVMBuilderRef)l->data;
6654 LLVMDisposeBuilder (builder);
6657 g_free (ctx);
6661 * mono_llvm_emit_method:
6663 * Emit LLVM IL from the mono IL, and compile it to native code using LLVM.
6665 void
6666 mono_llvm_emit_method (MonoCompile *cfg)
6668 EmitContext *ctx;
6669 char *method_name;
6670 gboolean is_linkonce = FALSE;
6671 int i;
6673 /* The code below might acquire the loader lock, so use it for global locking */
6674 mono_loader_lock ();
6676 /* Used to communicate with the callbacks */
6677 mono_native_tls_set_value (current_cfg_tls_id, cfg);
6679 ctx = g_new0 (EmitContext, 1);
6680 ctx->cfg = cfg;
6681 ctx->mempool = cfg->mempool;
6684 * This maps vregs to the LLVM instruction defining them
6686 ctx->values = g_new0 (LLVMValueRef, cfg->next_vreg);
6688 * This maps vregs for volatile variables to the LLVM instruction defining their
6689 * address.
6691 ctx->addresses = g_new0 (LLVMValueRef, cfg->next_vreg);
6692 ctx->vreg_types = g_new0 (LLVMTypeRef, cfg->next_vreg);
6693 ctx->vreg_cli_types = g_new0 (MonoType*, cfg->next_vreg);
6694 ctx->phi_values = g_ptr_array_sized_new (256);
6696 * This signals whenever the vreg was defined by a phi node with no input vars
6697 * (i.e. all its input bblocks end with NOT_REACHABLE).
6699 ctx->is_dead = g_new0 (gboolean, cfg->next_vreg);
6700 /* Whenever the bblock is unreachable */
6701 ctx->unreachable = g_new0 (gboolean, cfg->max_block_num);
6702 ctx->bblock_list = g_ptr_array_sized_new (256);
6704 ctx->region_to_handler = g_hash_table_new (NULL, NULL);
6705 ctx->clause_to_handler = g_hash_table_new (NULL, NULL);
6706 ctx->method_to_callers = g_hash_table_new (NULL, NULL);
6707 ctx->jit_callees = g_hash_table_new (NULL, NULL);
6708 if (cfg->compile_aot) {
6709 ctx->module = &aot_module;
6711 method_name = NULL;
6713 * Allow the linker to discard duplicate copies of wrappers, generic instances etc. by using the 'linkonce'
6714 * linkage for them. This requires the following:
6715 * - the method needs to have a unique mangled name
6716 * - llvmonly mode, since the code in aot-runtime.c would initialize got slots in the wrong aot image etc.
6718 is_linkonce = ctx->module->llvm_only && ctx->module->static_link && mono_aot_is_linkonce_method (cfg->method);
6719 if (is_linkonce) {
6720 method_name = mono_aot_get_mangled_method_name (cfg->method);
6721 if (!method_name)
6722 is_linkonce = FALSE;
6724 if (method_name)
6725 printf ("%s %s\n", mono_method_full_name (cfg->method, 1), method_name);
6726 else
6727 printf ("%s\n", mono_method_full_name (cfg->method, 1));
6730 if (!method_name)
6731 method_name = mono_aot_get_method_name (cfg);
6732 cfg->llvm_method_name = g_strdup (method_name);
6733 } else {
6734 init_jit_module (cfg->domain);
6735 ctx->module = (MonoLLVMModule*)domain_jit_info (cfg->domain)->llvm_module;
6736 method_name = mono_method_full_name (cfg->method, TRUE);
6738 ctx->method_name = method_name;
6739 ctx->is_linkonce = is_linkonce;
6741 #if LLVM_API_VERSION > 100
6742 if (cfg->compile_aot)
6743 ctx->lmodule = ctx->module->lmodule;
6744 else
6745 ctx->lmodule = LLVMModuleCreateWithName ("jit-module");
6746 #else
6747 ctx->lmodule = ctx->module->lmodule;
6748 #endif
6749 ctx->llvm_only = ctx->module->llvm_only;
6751 emit_method_inner (ctx);
6753 if (!ctx_ok (ctx)) {
6754 if (ctx->lmethod) {
6755 /* Need to add unused phi nodes as they can be referenced by other values */
6756 LLVMBasicBlockRef phi_bb = LLVMAppendBasicBlock (ctx->lmethod, "PHI_BB");
6757 LLVMBuilderRef builder;
6759 builder = create_builder (ctx);
6760 LLVMPositionBuilderAtEnd (builder, phi_bb);
6762 for (i = 0; i < ctx->phi_values->len; ++i) {
6763 LLVMValueRef v = (LLVMValueRef)g_ptr_array_index (ctx->phi_values, i);
6764 if (LLVMGetInstructionParent (v) == NULL)
6765 LLVMInsertIntoBuilder (builder, v);
6768 LLVMDeleteFunction (ctx->lmethod);
6772 free_ctx (ctx);
6774 mono_native_tls_set_value (current_cfg_tls_id, NULL);
6776 mono_loader_unlock ();
6779 static void
6780 emit_method_inner (EmitContext *ctx)
6782 MonoCompile *cfg = ctx->cfg;
6783 MonoMethodSignature *sig;
6784 MonoBasicBlock *bb;
6785 LLVMTypeRef method_type;
6786 LLVMValueRef method = NULL;
6787 LLVMValueRef *values = ctx->values;
6788 int i, max_block_num, bb_index;
6789 gboolean last = FALSE;
6790 LLVMCallInfo *linfo;
6791 LLVMModuleRef lmodule = ctx->lmodule;
6792 BBInfo *bblocks;
6793 GPtrArray *bblock_list = ctx->bblock_list;
6794 MonoMethodHeader *header;
6795 MonoExceptionClause *clause;
6796 char **names;
6798 if (cfg->gsharedvt && !cfg->llvm_only) {
6799 set_failure (ctx, "gsharedvt");
6800 return;
6803 #if 1
6805 static int count = 0;
6806 count ++;
6808 if (g_getenv ("LLVM_COUNT")) {
6809 if (count == atoi (g_getenv ("LLVM_COUNT"))) {
6810 printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
6811 fflush (stdout);
6812 last = TRUE;
6814 if (count > atoi (g_getenv ("LLVM_COUNT"))) {
6815 set_failure (ctx, "count");
6816 return;
6820 #endif
6822 sig = mono_method_signature (cfg->method);
6823 ctx->sig = sig;
6825 linfo = get_llvm_call_info (cfg, sig);
6826 ctx->linfo = linfo;
6827 if (!ctx_ok (ctx))
6828 return;
6830 if (cfg->rgctx_var)
6831 linfo->rgctx_arg = TRUE;
6832 ctx->method_type = method_type = sig_to_llvm_sig_full (ctx, sig, linfo);
6833 if (!ctx_ok (ctx))
6834 return;
6836 method = LLVMAddFunction (lmodule, ctx->method_name, method_type);
6837 ctx->lmethod = method;
6839 if (!cfg->llvm_only)
6840 LLVMSetFunctionCallConv (method, LLVMMono1CallConv);
6841 LLVMSetLinkage (method, LLVMPrivateLinkage);
6843 LLVMAddFunctionAttr (method, LLVMUWTable);
6845 if (cfg->compile_aot) {
6846 LLVMSetLinkage (method, LLVMInternalLinkage);
6847 if (ctx->module->external_symbols) {
6848 LLVMSetLinkage (method, LLVMExternalLinkage);
6849 LLVMSetVisibility (method, LLVMHiddenVisibility);
6851 if (ctx->is_linkonce) {
6852 LLVMSetLinkage (method, LLVMLinkOnceAnyLinkage);
6853 LLVMSetVisibility (method, LLVMDefaultVisibility);
6855 } else {
6856 #if LLVM_API_VERSION > 100
6857 LLVMSetLinkage (method, LLVMExternalLinkage);
6858 #else
6859 LLVMSetLinkage (method, LLVMPrivateLinkage);
6860 #endif
6863 if (cfg->method->save_lmf && !cfg->llvm_only) {
6864 set_failure (ctx, "lmf");
6865 return;
6868 if (sig->pinvoke && cfg->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && !cfg->llvm_only) {
6869 set_failure (ctx, "pinvoke signature");
6870 return;
6873 header = cfg->header;
6874 for (i = 0; i < header->num_clauses; ++i) {
6875 clause = &header->clauses [i];
6876 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_NONE) {
6877 set_failure (ctx, "non-finally/catch clause.");
6878 return;
6881 if (header->num_clauses || (cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING) || cfg->no_inline)
6882 /* We can't handle inlined methods with clauses */
6883 LLVMAddFunctionAttr (method, LLVMNoInlineAttribute);
6885 if (linfo->rgctx_arg) {
6886 ctx->rgctx_arg = LLVMGetParam (method, linfo->rgctx_arg_pindex);
6887 ctx->rgctx_arg_pindex = linfo->rgctx_arg_pindex;
6889 * We mark the rgctx parameter with the inreg attribute, which is mapped to
6890 * MONO_ARCH_RGCTX_REG in the Mono calling convention in llvm, i.e.
6891 * CC_X86_64_Mono in X86CallingConv.td.
6893 if (!ctx->llvm_only)
6894 LLVMAddAttribute (ctx->rgctx_arg, LLVMInRegAttribute);
6895 LLVMSetValueName (ctx->rgctx_arg, "rgctx");
6896 } else {
6897 ctx->rgctx_arg_pindex = -1;
6899 if (cfg->vret_addr) {
6900 values [cfg->vret_addr->dreg] = LLVMGetParam (method, linfo->vret_arg_pindex);
6901 LLVMSetValueName (values [cfg->vret_addr->dreg], "vret");
6902 if (linfo->ret.storage == LLVMArgVtypeByRef) {
6903 LLVMAddAttribute (LLVMGetParam (method, linfo->vret_arg_pindex), LLVMStructRetAttribute);
6904 LLVMAddAttribute (LLVMGetParam (method, linfo->vret_arg_pindex), LLVMNoAliasAttribute);
6908 if (sig->hasthis) {
6909 ctx->this_arg_pindex = linfo->this_arg_pindex;
6910 ctx->this_arg = LLVMGetParam (method, linfo->this_arg_pindex);
6911 values [cfg->args [0]->dreg] = ctx->this_arg;
6912 LLVMSetValueName (values [cfg->args [0]->dreg], "this");
6915 names = g_new (char *, sig->param_count);
6916 mono_method_get_param_names (cfg->method, (const char **) names);
6918 /* Set parameter names/attributes */
6919 for (i = 0; i < sig->param_count; ++i) {
6920 LLVMArgInfo *ainfo = &linfo->args [i + sig->hasthis];
6921 char *name;
6922 int pindex = ainfo->pindex + ainfo->ndummy_fpargs;
6923 int j;
6925 for (j = 0; j < ainfo->ndummy_fpargs; ++j) {
6926 name = g_strdup_printf ("dummy_%d_%d", i, j);
6927 LLVMSetValueName (LLVMGetParam (method, ainfo->pindex + j), name);
6928 g_free (name);
6931 if (ainfo->storage == LLVMArgVtypeInReg && ainfo->pair_storage [0] == LLVMArgNone && ainfo->pair_storage [1] == LLVMArgNone)
6932 continue;
6934 values [cfg->args [i + sig->hasthis]->dreg] = LLVMGetParam (method, pindex);
6935 if (ainfo->storage == LLVMArgGsharedvtFixed || ainfo->storage == LLVMArgGsharedvtFixedVtype) {
6936 if (names [i] && names [i][0] != '\0')
6937 name = g_strdup_printf ("p_arg_%s", names [i]);
6938 else
6939 name = g_strdup_printf ("p_arg_%d", i);
6940 } else {
6941 if (names [i] && names [i][0] != '\0')
6942 name = g_strdup_printf ("arg_%s", names [i]);
6943 else
6944 name = g_strdup_printf ("arg_%d", i);
6946 LLVMSetValueName (values [cfg->args [i + sig->hasthis]->dreg], name);
6947 g_free (name);
6948 if (ainfo->storage == LLVMArgVtypeByVal)
6949 LLVMAddAttribute (LLVMGetParam (method, pindex), LLVMByValAttribute);
6951 if (ainfo->storage == LLVMArgVtypeByRef) {
6952 /* For OP_LDADDR */
6953 cfg->args [i + sig->hasthis]->opcode = OP_VTARG_ADDR;
6956 g_free (names);
6958 if (ctx->module->emit_dwarf && cfg->compile_aot && mono_debug_enabled ()) {
6959 ctx->minfo = mono_debug_lookup_method (cfg->method);
6960 ctx->dbg_md = emit_dbg_subprogram (ctx, cfg, method, ctx->method_name);
6963 max_block_num = 0;
6964 for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
6965 max_block_num = MAX (max_block_num, bb->block_num);
6966 ctx->bblocks = bblocks = g_new0 (BBInfo, max_block_num + 1);
6968 /* Add branches between non-consecutive bblocks */
6969 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
6970 if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins) &&
6971 bb->next_bb != bb->last_ins->inst_false_bb) {
6973 MonoInst *inst = (MonoInst*)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
6974 inst->opcode = OP_BR;
6975 inst->inst_target_bb = bb->last_ins->inst_false_bb;
6976 mono_bblock_add_inst (bb, inst);
6981 * The INDIRECT flag added by OP_LDADDR inhibits optimizations, even if the LDADDR
6982 * was later optimized away, so clear these flags, and add them back for the still
6983 * present OP_LDADDR instructions.
6985 for (i = 0; i < cfg->next_vreg; ++i) {
6986 MonoInst *ins;
6988 ins = get_vreg_to_inst (cfg, i);
6989 if (ins && ins != cfg->rgctx_var)
6990 ins->flags &= ~MONO_INST_INDIRECT;
6994 * Make a first pass over the code to precreate PHI nodes/set INDIRECT flags.
6996 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
6997 MonoInst *ins;
6998 LLVMBuilderRef builder;
6999 char *dname;
7000 char dname_buf[128];
7002 builder = create_builder (ctx);
7004 for (ins = bb->code; ins; ins = ins->next) {
7005 switch (ins->opcode) {
7006 case OP_PHI:
7007 case OP_FPHI:
7008 case OP_VPHI:
7009 case OP_XPHI: {
7010 LLVMTypeRef phi_type = llvm_type_to_stack_type (cfg, type_to_llvm_type (ctx, &ins->klass->byval_arg));
7012 if (!ctx_ok (ctx))
7013 return;
7015 if (ins->opcode == OP_VPHI) {
7016 /* Treat valuetype PHI nodes as operating on the address itself */
7017 g_assert (ins->klass);
7018 phi_type = LLVMPointerType (type_to_llvm_type (ctx, &ins->klass->byval_arg), 0);
7022 * Have to precreate these, as they can be referenced by
7023 * earlier instructions.
7025 sprintf (dname_buf, "t%d", ins->dreg);
7026 dname = dname_buf;
7027 values [ins->dreg] = LLVMBuildPhi (builder, phi_type, dname);
7029 if (ins->opcode == OP_VPHI)
7030 ctx->addresses [ins->dreg] = values [ins->dreg];
7032 g_ptr_array_add (ctx->phi_values, values [ins->dreg]);
7035 * Set the expected type of the incoming arguments since these have
7036 * to have the same type.
7038 for (i = 0; i < ins->inst_phi_args [0]; i++) {
7039 int sreg1 = ins->inst_phi_args [i + 1];
7041 if (sreg1 != -1)
7042 ctx->vreg_types [sreg1] = phi_type;
7044 break;
7046 case OP_LDADDR:
7047 ((MonoInst*)ins->inst_p0)->flags |= MONO_INST_INDIRECT;
7048 break;
7049 default:
7050 break;
7056 * Create an ordering for bblocks, use the depth first order first, then
7057 * put the exception handling bblocks last.
7059 for (bb_index = 0; bb_index < cfg->num_bblocks; ++bb_index) {
7060 bb = cfg->bblocks [bb_index];
7061 if (!(bb->region != -1 && !MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY))) {
7062 g_ptr_array_add (bblock_list, bb);
7063 bblocks [bb->block_num].added = TRUE;
7067 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7068 if (!bblocks [bb->block_num].added)
7069 g_ptr_array_add (bblock_list, bb);
7073 * Second pass: generate code.
7075 // Emit entry point
7076 LLVMBuilderRef entry_builder = create_builder (ctx);
7077 LLVMBasicBlockRef entry_bb = get_bb (ctx, cfg->bb_entry);
7078 LLVMPositionBuilderAtEnd (entry_builder, entry_bb);
7079 emit_entry_bb (ctx, entry_builder);
7081 // Make landing pads first
7082 ctx->exc_meta = g_hash_table_new_full (NULL, NULL, NULL, NULL);
7084 if (ctx->llvm_only) {
7085 size_t group_index = 0;
7086 while (group_index < cfg->header->num_clauses) {
7087 int count = 0;
7088 size_t cursor = group_index;
7089 while (cursor < cfg->header->num_clauses &&
7090 CLAUSE_START (&cfg->header->clauses [cursor]) == CLAUSE_START (&cfg->header->clauses [group_index]) &&
7091 CLAUSE_END (&cfg->header->clauses [cursor]) == CLAUSE_END (&cfg->header->clauses [group_index])) {
7092 count++;
7093 cursor++;
7096 LLVMBasicBlockRef lpad_bb = emit_landing_pad (ctx, group_index, count);
7097 intptr_t key = CLAUSE_END (&cfg->header->clauses [group_index]);
7098 g_hash_table_insert (ctx->exc_meta, (gpointer)key, lpad_bb);
7100 group_index = cursor;
7104 for (bb_index = 0; bb_index < bblock_list->len; ++bb_index) {
7105 bb = (MonoBasicBlock*)g_ptr_array_index (bblock_list, bb_index);
7107 // Prune unreachable mono BBs.
7108 if (!(bb == cfg->bb_entry || bb->in_count > 0))
7109 continue;
7111 process_bb (ctx, bb);
7112 if (!ctx_ok (ctx))
7113 return;
7115 g_hash_table_destroy (ctx->exc_meta);
7117 mono_memory_barrier ();
7119 /* Add incoming phi values */
7120 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7121 GSList *l, *ins_list;
7123 ins_list = bblocks [bb->block_num].phi_nodes;
7125 for (l = ins_list; l; l = l->next) {
7126 PhiNode *node = (PhiNode*)l->data;
7127 MonoInst *phi = node->phi;
7128 int sreg1 = node->sreg;
7129 LLVMBasicBlockRef in_bb;
7131 if (sreg1 == -1)
7132 continue;
7134 in_bb = get_end_bb (ctx, node->in_bb);
7136 if (ctx->unreachable [node->in_bb->block_num])
7137 continue;
7139 if (!values [sreg1]) {
7140 /* Can happen with values in EH clauses */
7141 set_failure (ctx, "incoming phi sreg1");
7142 return;
7145 if (phi->opcode == OP_VPHI) {
7146 g_assert (LLVMTypeOf (ctx->addresses [sreg1]) == LLVMTypeOf (values [phi->dreg]));
7147 LLVMAddIncoming (values [phi->dreg], &ctx->addresses [sreg1], &in_bb, 1);
7148 } else {
7149 if (LLVMTypeOf (values [sreg1]) != LLVMTypeOf (values [phi->dreg])) {
7150 set_failure (ctx, "incoming phi arg type mismatch");
7151 return;
7153 g_assert (LLVMTypeOf (values [sreg1]) == LLVMTypeOf (values [phi->dreg]));
7154 LLVMAddIncoming (values [phi->dreg], &values [sreg1], &in_bb, 1);
7159 /* Nullify empty phi instructions */
7160 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7161 GSList *l, *ins_list;
7163 ins_list = bblocks [bb->block_num].phi_nodes;
7165 for (l = ins_list; l; l = l->next) {
7166 PhiNode *node = (PhiNode*)l->data;
7167 MonoInst *phi = node->phi;
7168 LLVMValueRef phi_ins = values [phi->dreg];
7170 if (!phi_ins)
7171 /* Already removed */
7172 continue;
7174 if (LLVMCountIncoming (phi_ins) == 0) {
7175 mono_llvm_replace_uses_of (phi_ins, LLVMConstNull (LLVMTypeOf (phi_ins)));
7176 LLVMInstructionEraseFromParent (phi_ins);
7177 values [phi->dreg] = NULL;
7182 /* Create the SWITCH statements for ENDFINALLY instructions */
7183 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7184 BBInfo *info = &bblocks [bb->block_num];
7185 GSList *l;
7186 for (l = info->endfinally_switch_ins_list; l; l = l->next) {
7187 LLVMValueRef switch_ins = (LLVMValueRef)l->data;
7188 GSList *bb_list = info->call_handler_return_bbs;
7190 for (i = 0; i < g_slist_length (bb_list); ++i)
7191 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i + 1, FALSE), (LLVMBasicBlockRef)(g_slist_nth (bb_list, i)->data));
7195 /* Initialize the method if needed */
7196 if (cfg->compile_aot && ctx->llvm_only) {
7197 // FIXME: Add more shared got entries
7198 ctx->builder = create_builder (ctx);
7199 LLVMPositionBuilderAtEnd (ctx->builder, ctx->init_bb);
7201 ctx->module->max_method_idx = MAX (ctx->module->max_method_idx, cfg->method_index);
7203 // FIXME: beforefieldinit
7204 if (ctx->has_got_access || mono_class_get_cctor (cfg->method->klass)) {
7206 * linkonce methods shouldn't have initialization,
7207 * because they might belong to assemblies which
7208 * haven't been loaded yet.
7210 g_assert (!ctx->is_linkonce);
7211 emit_init_method (ctx);
7212 } else {
7213 LLVMBuildBr (ctx->builder, ctx->inited_bb);
7217 if (cfg->llvm_only) {
7218 GHashTableIter iter;
7219 MonoMethod *method;
7220 GSList *callers, *l, *l2;
7223 * Add the contents of ctx->method_to_callers to module->method_to_callers.
7224 * We can't do this earlier, as it contains llvm instructions which can be
7225 * freed if compilation fails.
7226 * FIXME: Get rid of this when all methods can be llvm compiled.
7228 g_hash_table_iter_init (&iter, ctx->method_to_callers);
7229 while (g_hash_table_iter_next (&iter, (void**)&method, (void**)&callers)) {
7230 for (l = callers; l; l = l->next) {
7231 l2 = (GSList*)g_hash_table_lookup (ctx->module->method_to_callers, method);
7232 l2 = g_slist_prepend (l2, l->data);
7233 g_hash_table_insert (ctx->module->method_to_callers, method, l2);
7238 if (cfg->verbose_level > 1)
7239 mono_llvm_dump_value (method);
7241 if (cfg->compile_aot && !cfg->llvm_only)
7242 mark_as_used (ctx->module, method);
7244 if (!cfg->llvm_only) {
7245 LLVMValueRef md_args [16];
7246 LLVMValueRef md_node;
7247 int method_index;
7249 if (cfg->compile_aot)
7250 method_index = mono_aot_get_method_index (cfg->orig_method);
7251 else
7252 method_index = 1;
7253 md_args [0] = LLVMMDString (ctx->method_name, strlen (ctx->method_name));
7254 md_args [1] = LLVMConstInt (LLVMInt32Type (), method_index, FALSE);
7255 md_node = LLVMMDNode (md_args, 2);
7256 LLVMAddNamedMetadataOperand (lmodule, "mono.function_indexes", md_node);
7257 //LLVMSetMetadata (method, md_kind, LLVMMDNode (&md_arg, 1));
7260 if (cfg->compile_aot) {
7261 /* Don't generate native code, keep the LLVM IR */
7262 if (cfg->verbose_level)
7263 printf ("%s emitted as %s\n", mono_method_full_name (cfg->method, TRUE), ctx->method_name);
7265 #if LLVM_API_VERSION < 100
7266 /* VerifyFunction can't handle some of the debug info created by DIBuilder in llvm 3.9 */
7267 int err = LLVMVerifyFunction(ctx->lmethod, LLVMPrintMessageAction);
7268 g_assert (err == 0);
7269 #endif
7270 } else {
7271 //LLVMVerifyFunction(method, 0);
7272 #if LLVM_API_VERSION > 100
7273 MonoDomain *domain = mono_domain_get ();
7274 MonoJitDomainInfo *domain_info;
7275 int nvars = g_hash_table_size (ctx->jit_callees);
7276 LLVMValueRef *callee_vars = g_new0 (LLVMValueRef, nvars);
7277 gpointer *callee_addrs = g_new0 (gpointer, nvars);
7278 GHashTableIter iter;
7279 LLVMValueRef var;
7280 MonoMethod *callee;
7281 gpointer eh_frame;
7284 * Compute the addresses of the LLVM globals pointing to the
7285 * methods called by the current method. Pass it to the trampoline
7286 * code so it can update them after their corresponding method was
7287 * compiled.
7289 g_hash_table_iter_init (&iter, ctx->jit_callees);
7290 i = 0;
7291 while (g_hash_table_iter_next (&iter, NULL, (void**)&var))
7292 callee_vars [i ++] = var;
7294 cfg->native_code = mono_llvm_compile_method (ctx->module->mono_ee, ctx->lmethod, nvars, callee_vars, callee_addrs, &eh_frame);
7296 decode_llvm_eh_info (ctx, eh_frame);
7298 mono_domain_lock (domain);
7299 domain_info = domain_jit_info (domain);
7300 if (!domain_info->llvm_jit_callees)
7301 domain_info->llvm_jit_callees = g_hash_table_new (NULL, NULL);
7302 g_hash_table_iter_init (&iter, ctx->jit_callees);
7303 i = 0;
7304 while (g_hash_table_iter_next (&iter, (void**)&callee, (void**)&var)) {
7305 GSList *addrs = g_hash_table_lookup (domain_info->llvm_jit_callees, callee);
7306 addrs = g_slist_prepend (addrs, callee_addrs [i]);
7307 g_hash_table_insert (domain_info->llvm_jit_callees, callee, addrs);
7308 i ++;
7310 mono_domain_unlock (domain);
7311 #else
7312 mono_llvm_optimize_method (ctx->module->mono_ee, ctx->lmethod);
7314 if (cfg->verbose_level > 1)
7315 mono_llvm_dump_value (ctx->lmethod);
7317 cfg->native_code = (unsigned char*)LLVMGetPointerToGlobal (ctx->module->ee, ctx->lmethod);
7319 /* Set by emit_cb */
7320 g_assert (cfg->code_len);
7321 #endif
7324 if (ctx->module->method_to_lmethod)
7325 g_hash_table_insert (ctx->module->method_to_lmethod, cfg->method, ctx->lmethod);
7326 if (ctx->module->idx_to_lmethod)
7327 g_hash_table_insert (ctx->module->idx_to_lmethod, GINT_TO_POINTER (cfg->method_index), ctx->lmethod);
7329 if (ctx->llvm_only && cfg->orig_method->klass->valuetype && !(cfg->orig_method->flags & METHOD_ATTRIBUTE_STATIC))
7330 emit_unbox_tramp (ctx, ctx->method_name, ctx->method_type, ctx->lmethod, cfg->method_index);
7334 * mono_llvm_create_vars:
7336 * Same as mono_arch_create_vars () for LLVM.
7338 void
7339 mono_llvm_create_vars (MonoCompile *cfg)
7341 MonoMethodSignature *sig;
7343 sig = mono_method_signature (cfg->method);
7344 if (cfg->gsharedvt && cfg->llvm_only) {
7345 if (mini_is_gsharedvt_variable_signature (sig) && sig->ret->type != MONO_TYPE_VOID) {
7346 cfg->vret_addr = mono_compile_create_var (cfg, &mono_get_intptr_class ()->byval_arg, OP_ARG);
7347 if (G_UNLIKELY (cfg->verbose_level > 1)) {
7348 printf ("vret_addr = ");
7349 mono_print_ins (cfg->vret_addr);
7352 } else {
7353 mono_arch_create_vars (cfg);
7358 * mono_llvm_emit_call:
7360 * Same as mono_arch_emit_call () for LLVM.
7362 void
7363 mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call)
7365 MonoInst *in;
7366 MonoMethodSignature *sig;
7367 int i, n, stack_size;
7368 LLVMArgInfo *ainfo;
7370 stack_size = 0;
7372 sig = call->signature;
7373 n = sig->param_count + sig->hasthis;
7375 call->cinfo = get_llvm_call_info (cfg, sig);
7377 if (cfg->disable_llvm)
7378 return;
7380 if (sig->call_convention == MONO_CALL_VARARG) {
7381 cfg->exception_message = g_strdup ("varargs");
7382 cfg->disable_llvm = TRUE;
7385 for (i = 0; i < n; ++i) {
7386 MonoInst *ins;
7388 ainfo = call->cinfo->args + i;
7390 in = call->args [i];
7392 /* Simply remember the arguments */
7393 switch (ainfo->storage) {
7394 case LLVMArgNormal: {
7395 MonoType *t = (sig->hasthis && i == 0) ? &mono_get_intptr_class ()->byval_arg : ainfo->type;
7396 int opcode;
7398 opcode = mono_type_to_regmove (cfg, t);
7399 if (opcode == OP_FMOVE) {
7400 MONO_INST_NEW (cfg, ins, OP_FMOVE);
7401 ins->dreg = mono_alloc_freg (cfg);
7402 } else if (opcode == OP_LMOVE) {
7403 MONO_INST_NEW (cfg, ins, OP_LMOVE);
7404 ins->dreg = mono_alloc_lreg (cfg);
7405 } else if (opcode == OP_RMOVE) {
7406 MONO_INST_NEW (cfg, ins, OP_RMOVE);
7407 ins->dreg = mono_alloc_freg (cfg);
7408 } else {
7409 MONO_INST_NEW (cfg, ins, OP_MOVE);
7410 ins->dreg = mono_alloc_ireg (cfg);
7412 ins->sreg1 = in->dreg;
7413 break;
7415 case LLVMArgVtypeByVal:
7416 case LLVMArgVtypeByRef:
7417 case LLVMArgVtypeInReg:
7418 case LLVMArgVtypeAsScalar:
7419 case LLVMArgAsIArgs:
7420 case LLVMArgAsFpArgs:
7421 case LLVMArgGsharedvtVariable:
7422 case LLVMArgGsharedvtFixed:
7423 case LLVMArgGsharedvtFixedVtype:
7424 MONO_INST_NEW (cfg, ins, OP_LLVM_OUTARG_VT);
7425 ins->dreg = mono_alloc_ireg (cfg);
7426 ins->sreg1 = in->dreg;
7427 ins->inst_p0 = mono_mempool_alloc0 (cfg->mempool, sizeof (LLVMArgInfo));
7428 memcpy (ins->inst_p0, ainfo, sizeof (LLVMArgInfo));
7429 ins->inst_vtype = ainfo->type;
7430 ins->klass = mono_class_from_mono_type (ainfo->type);
7431 break;
7432 default:
7433 cfg->exception_message = g_strdup ("ainfo->storage");
7434 cfg->disable_llvm = TRUE;
7435 return;
7438 if (!cfg->disable_llvm) {
7439 MONO_ADD_INS (cfg->cbb, ins);
7440 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, 0, FALSE);
7445 static unsigned char*
7446 alloc_cb (LLVMValueRef function, int size)
7448 MonoCompile *cfg;
7450 cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
7452 if (cfg) {
7453 // FIXME: dynamic
7454 return (unsigned char*)mono_domain_code_reserve (cfg->domain, size);
7455 } else {
7456 return (unsigned char*)mono_domain_code_reserve (mono_domain_get (), size);
7460 static void
7461 emitted_cb (LLVMValueRef function, void *start, void *end)
7463 MonoCompile *cfg;
7465 cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
7466 g_assert (cfg);
7467 cfg->code_len = (guint8*)end - (guint8*)start;
7470 static void
7471 exception_cb (void *data)
7473 MonoCompile *cfg;
7474 MonoJitExceptionInfo *ei;
7475 guint32 ei_len, i, j, nested_len, nindex;
7476 gpointer *type_info;
7477 int this_reg, this_offset;
7479 cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
7480 g_assert (cfg);
7483 * data points to a DWARF FDE structure, convert it to our unwind format and
7484 * save it.
7485 * An alternative would be to save it directly, and modify our unwinder to work
7486 * with it.
7488 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);
7489 if (cfg->verbose_level > 1)
7490 mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
7492 /* Count nested clauses */
7493 nested_len = 0;
7494 for (i = 0; i < ei_len; ++i) {
7495 gint32 cindex1 = *(gint32*)type_info [i];
7496 MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];
7498 for (j = 0; j < cfg->header->num_clauses; ++j) {
7499 int cindex2 = j;
7500 MonoExceptionClause *clause2 = &cfg->header->clauses [cindex2];
7502 if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
7503 nested_len ++;
7508 cfg->llvm_ex_info = (MonoJitExceptionInfo*)mono_mempool_alloc0 (cfg->mempool, (ei_len + nested_len) * sizeof (MonoJitExceptionInfo));
7509 cfg->llvm_ex_info_len = ei_len + nested_len;
7510 memcpy (cfg->llvm_ex_info, ei, ei_len * sizeof (MonoJitExceptionInfo));
7511 /* Fill the rest of the information from the type info */
7512 for (i = 0; i < ei_len; ++i) {
7513 gint32 clause_index = *(gint32*)type_info [i];
7514 MonoExceptionClause *clause = &cfg->header->clauses [clause_index];
7516 cfg->llvm_ex_info [i].flags = clause->flags;
7517 cfg->llvm_ex_info [i].data.catch_class = clause->data.catch_class;
7518 cfg->llvm_ex_info [i].clause_index = clause_index;
7522 * For nested clauses, the LLVM produced exception info associates the try interval with
7523 * the innermost handler, while mono expects it to be associated with all nesting clauses.
7524 * So add new clauses which use the IL info (catch class etc.) from the nesting clause,
7525 * and everything else from the nested clause.
7527 nindex = ei_len;
7528 for (i = 0; i < ei_len; ++i) {
7529 gint32 cindex1 = *(gint32*)type_info [i];
7530 MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];
7532 for (j = 0; j < cfg->header->num_clauses; ++j) {
7533 int cindex2 = j;
7534 MonoExceptionClause *clause2 = &cfg->header->clauses [cindex2];
7535 MonoJitExceptionInfo *nesting_ei, *nested_ei;
7537 if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
7538 /* clause1 is the nested clause */
7539 nested_ei = &cfg->llvm_ex_info [i];
7540 nesting_ei = &cfg->llvm_ex_info [nindex];
7541 nindex ++;
7543 memcpy (nesting_ei, nested_ei, sizeof (MonoJitExceptionInfo));
7545 nesting_ei->flags = clause2->flags;
7546 nesting_ei->data.catch_class = clause2->data.catch_class;
7547 nesting_ei->clause_index = cindex2;
7551 g_assert (nindex == ei_len + nested_len);
7552 cfg->llvm_this_reg = this_reg;
7553 cfg->llvm_this_offset = this_offset;
7555 /* type_info [i] is cfg mempool allocated, no need to free it */
7557 g_free (ei);
7558 g_free (type_info);
7561 #if LLVM_API_VERSION > 100
7563 * decode_llvm_eh_info:
7565 * Decode the EH table emitted by llvm in jit mode, and store
7566 * the result into cfg.
7568 static void
7569 decode_llvm_eh_info (EmitContext *ctx, gpointer eh_frame)
7571 MonoCompile *cfg = ctx->cfg;
7572 guint8 *cie, *fde;
7573 int fde_len;
7574 MonoLLVMFDEInfo info;
7575 MonoJitExceptionInfo *ei;
7576 guint8 *p = eh_frame;
7577 int version, fde_count, fde_offset;
7578 guint32 ei_len, i, nested_len;
7579 gpointer *type_info;
7580 gint32 *table;
7583 * Decode the one element EH table emitted by the MonoException class
7584 * in llvm.
7587 /* Similar to decode_llvm_mono_eh_frame () in aot-runtime.c */
7589 version = *p;
7590 g_assert (version == 3);
7591 p ++;
7592 p ++;
7593 p = (guint8 *)ALIGN_PTR_TO (p, 4);
7595 fde_count = *(guint32*)p;
7596 p += 4;
7597 table = (gint32*)p;
7599 g_assert (fde_count <= 2);
7601 /* The first entry is the real method */
7602 g_assert (table [0] == 1);
7603 fde_offset = table [1];
7604 table += fde_count * 2;
7605 /* Extra entry */
7606 cfg->code_len = table [0];
7607 fde_len = table [1] - fde_offset;
7608 table += 2;
7610 fde = (guint8*)eh_frame + fde_offset;
7611 cie = (guint8*)table;
7613 mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info);
7615 cfg->encoded_unwind_ops = info.unw_info;
7616 cfg->encoded_unwind_ops_len = info.unw_info_len;
7617 if (cfg->verbose_level > 1)
7618 mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
7619 if (info.this_reg != -1) {
7620 cfg->llvm_this_reg = info.this_reg;
7621 cfg->llvm_this_offset = info.this_offset;
7624 ei = info.ex_info;
7625 ei_len = info.ex_info_len;
7626 type_info = info.type_info;
7628 // Nested clauses are currently disabled
7629 nested_len = 0;
7631 cfg->llvm_ex_info = (MonoJitExceptionInfo*)mono_mempool_alloc0 (cfg->mempool, (ei_len + nested_len) * sizeof (MonoJitExceptionInfo));
7632 cfg->llvm_ex_info_len = ei_len + nested_len;
7633 memcpy (cfg->llvm_ex_info, ei, ei_len * sizeof (MonoJitExceptionInfo));
7634 /* Fill the rest of the information from the type info */
7635 for (i = 0; i < ei_len; ++i) {
7636 gint32 clause_index = *(gint32*)type_info [i];
7637 MonoExceptionClause *clause = &cfg->header->clauses [clause_index];
7639 cfg->llvm_ex_info [i].flags = clause->flags;
7640 cfg->llvm_ex_info [i].data.catch_class = clause->data.catch_class;
7641 cfg->llvm_ex_info [i].clause_index = clause_index;
7644 #endif
7646 static char*
7647 dlsym_cb (const char *name, void **symbol)
7649 MonoDl *current;
7650 char *err;
7652 err = NULL;
7653 if (!strcmp (name, "__bzero")) {
7654 *symbol = (void*)bzero;
7655 } else {
7656 current = mono_dl_open (NULL, 0, NULL);
7657 g_assert (current);
7659 err = mono_dl_symbol (current, name, symbol);
7661 mono_dl_close (current);
7663 #ifdef MONO_ARCH_HAVE_CREATE_LLVM_NATIVE_THUNK
7664 *symbol = (char*)mono_arch_create_llvm_native_thunk (mono_domain_get (), (guint8*)(*symbol));
7665 #endif
7666 return err;
7669 static inline void
7670 AddFunc (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeRef *param_types, int nparams)
7672 LLVMAddFunction (module, name, LLVMFunctionType (ret_type, param_types, nparams, FALSE));
7675 static inline void
7676 AddFunc2 (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeRef param_type1, LLVMTypeRef param_type2)
7678 LLVMTypeRef param_types [4];
7680 param_types [0] = param_type1;
7681 param_types [1] = param_type2;
7683 AddFunc (module, name, ret_type, param_types, 2);
7686 typedef enum {
7687 INTRINS_MEMSET,
7688 INTRINS_MEMCPY,
7689 INTRINS_SADD_OVF_I32,
7690 INTRINS_UADD_OVF_I32,
7691 INTRINS_SSUB_OVF_I32,
7692 INTRINS_USUB_OVF_I32,
7693 INTRINS_SMUL_OVF_I32,
7694 INTRINS_UMUL_OVF_I32,
7695 INTRINS_SADD_OVF_I64,
7696 INTRINS_UADD_OVF_I64,
7697 INTRINS_SSUB_OVF_I64,
7698 INTRINS_USUB_OVF_I64,
7699 INTRINS_SMUL_OVF_I64,
7700 INTRINS_UMUL_OVF_I64,
7701 INTRINS_SIN,
7702 INTRINS_COS,
7703 INTRINS_SQRT,
7704 INTRINS_FABS,
7705 INTRINS_EXPECT_I8,
7706 INTRINS_EXPECT_I1,
7707 #if defined(TARGET_AMD64) || defined(TARGET_X86)
7708 INTRINS_SSE_PMOVMSKB,
7709 INTRINS_SSE_PSRLI_W,
7710 INTRINS_SSE_PSRAI_W,
7711 INTRINS_SSE_PSLLI_W,
7712 INTRINS_SSE_PSRLI_D,
7713 INTRINS_SSE_PSRAI_D,
7714 INTRINS_SSE_PSLLI_D,
7715 INTRINS_SSE_PSRLI_Q,
7716 INTRINS_SSE_PSLLI_Q,
7717 INTRINS_SSE_SQRT_PD,
7718 INTRINS_SSE_SQRT_PS,
7719 INTRINS_SSE_RSQRT_PS,
7720 INTRINS_SSE_RCP_PS,
7721 INTRINS_SSE_CVTTPD2DQ,
7722 INTRINS_SSE_CVTTPS2DQ,
7723 INTRINS_SSE_CVTDQ2PD,
7724 INTRINS_SSE_CVTDQ2PS,
7725 INTRINS_SSE_CVTPD2DQ,
7726 INTRINS_SSE_CVTPS2DQ,
7727 INTRINS_SSE_CVTPD2PS,
7728 INTRINS_SSE_CVTPS2PD,
7729 INTRINS_SSE_CMPPD,
7730 INTRINS_SSE_CMPPS,
7731 INTRINS_SSE_PACKSSWB,
7732 INTRINS_SSE_PACKUSWB,
7733 INTRINS_SSE_PACKSSDW,
7734 INTRINS_SSE_PACKUSDW,
7735 INTRINS_SSE_MINPS,
7736 INTRINS_SSE_MAXPS,
7737 INTRINS_SSE_HADDPS,
7738 INTRINS_SSE_HSUBPS,
7739 INTRINS_SSE_ADDSUBPS,
7740 INTRINS_SSE_MINPD,
7741 INTRINS_SSE_MAXPD,
7742 INTRINS_SSE_HADDPD,
7743 INTRINS_SSE_HSUBPD,
7744 INTRINS_SSE_ADDSUBPD,
7745 INTRINS_SSE_PADDSW,
7746 INTRINS_SSE_PSUBSW,
7747 INTRINS_SSE_PADDUSW,
7748 INTRINS_SSE_PSUBUSW,
7749 INTRINS_SSE_PAVGW,
7750 INTRINS_SSE_PMULHW,
7751 INTRINS_SSE_PMULHU,
7752 INTRINS_SE_PADDSB,
7753 INTRINS_SSE_PSUBSB,
7754 INTRINS_SSE_PADDUSB,
7755 INTRINS_SSE_PSUBUSB,
7756 INTRINS_SSE_PAVGB,
7757 INTRINS_SSE_PAUSE,
7758 #endif
7759 INTRINS_NUM
7760 } IntrinsicId;
7762 typedef struct {
7763 IntrinsicId id;
7764 const char *name;
7765 } IntrinsicDesc;
7767 static IntrinsicDesc intrinsics[] = {
7768 {INTRINS_MEMSET, "llvm.memset.p0i8.i32"},
7769 {INTRINS_MEMCPY, "llvm.memcpy.p0i8.p0i8.i32"},
7770 {INTRINS_SADD_OVF_I32, "llvm.sadd.with.overflow.i32"},
7771 {INTRINS_UADD_OVF_I32, "llvm.uadd.with.overflow.i32"},
7772 {INTRINS_SSUB_OVF_I32, "llvm.ssub.with.overflow.i32"},
7773 {INTRINS_USUB_OVF_I32, "llvm.usub.with.overflow.i32"},
7774 {INTRINS_SMUL_OVF_I32, "llvm.smul.with.overflow.i32"},
7775 {INTRINS_UMUL_OVF_I32, "llvm.umul.with.overflow.i32"},
7776 {INTRINS_SADD_OVF_I64, "llvm.sadd.with.overflow.i64"},
7777 {INTRINS_UADD_OVF_I64, "llvm.uadd.with.overflow.i64"},
7778 {INTRINS_SSUB_OVF_I64, "llvm.ssub.with.overflow.i64"},
7779 {INTRINS_USUB_OVF_I64, "llvm.usub.with.overflow.i64"},
7780 {INTRINS_SMUL_OVF_I64, "llvm.smul.with.overflow.i64"},
7781 {INTRINS_UMUL_OVF_I64, "llvm.umul.with.overflow.i64"},
7782 {INTRINS_SIN, "llvm.sin.f64"},
7783 {INTRINS_COS, "llvm.cos.f64"},
7784 {INTRINS_SQRT, "llvm.sqrt.f64"},
7785 /* This isn't an intrinsic, instead llvm seems to special case it by name */
7786 {INTRINS_FABS, "fabs"},
7787 {INTRINS_EXPECT_I8, "llvm.expect.i8"},
7788 {INTRINS_EXPECT_I1, "llvm.expect.i1"},
7789 #if defined(TARGET_AMD64) || defined(TARGET_X86)
7790 {INTRINS_SSE_PMOVMSKB, "llvm.x86.sse2.pmovmskb.128"},
7791 {INTRINS_SSE_PSRLI_W, "llvm.x86.sse2.psrli.w"},
7792 {INTRINS_SSE_PSRAI_W, "llvm.x86.sse2.psrai.w"},
7793 {INTRINS_SSE_PSLLI_W, "llvm.x86.sse2.pslli.w"},
7794 {INTRINS_SSE_PSRLI_D, "llvm.x86.sse2.psrli.d"},
7795 {INTRINS_SSE_PSRAI_D, "llvm.x86.sse2.psrai.d"},
7796 {INTRINS_SSE_PSLLI_D, "llvm.x86.sse2.pslli.d"},
7797 {INTRINS_SSE_PSRLI_Q, "llvm.x86.sse2.psrli.q"},
7798 {INTRINS_SSE_PSLLI_Q, "llvm.x86.sse2.pslli.q"},
7799 {INTRINS_SSE_SQRT_PD, "llvm.x86.sse2.sqrt.pd"},
7800 {INTRINS_SSE_SQRT_PS, "llvm.x86.sse.sqrt.ps"},
7801 {INTRINS_SSE_RSQRT_PS, "llvm.x86.sse.rsqrt.ps"},
7802 {INTRINS_SSE_RCP_PS, "llvm.x86.sse.rcp.ps"},
7803 {INTRINS_SSE_CVTTPD2DQ, "llvm.x86.sse2.cvttpd2dq"},
7804 {INTRINS_SSE_CVTTPS2DQ, "llvm.x86.sse2.cvttps2dq"},
7805 {INTRINS_SSE_CVTDQ2PD, "llvm.x86.sse2.cvtdq2pd"},
7806 {INTRINS_SSE_CVTDQ2PS, "llvm.x86.sse2.cvtdq2ps"},
7807 {INTRINS_SSE_CVTPD2DQ, "llvm.x86.sse2.cvtpd2dq"},
7808 {INTRINS_SSE_CVTPS2DQ, "llvm.x86.sse2.cvtps2dq"},
7809 {INTRINS_SSE_CVTPD2PS, "llvm.x86.sse2.cvtpd2ps"},
7810 {INTRINS_SSE_CVTPS2PD, "llvm.x86.sse2.cvtps2pd"},
7811 {INTRINS_SSE_CMPPD, "llvm.x86.sse2.cmp.pd"},
7812 {INTRINS_SSE_CMPPS, "llvm.x86.sse.cmp.ps"},
7813 {INTRINS_SSE_PACKSSWB, "llvm.x86.sse2.packsswb.128"},
7814 {INTRINS_SSE_PACKUSWB, "llvm.x86.sse2.packuswb.128"},
7815 {INTRINS_SSE_PACKSSDW, "llvm.x86.sse2.packssdw.128"},
7816 {INTRINS_SSE_PACKUSDW, "llvm.x86.sse41.packusdw"},
7817 {INTRINS_SSE_MINPS, "llvm.x86.sse.min.ps"},
7818 {INTRINS_SSE_MAXPS, "llvm.x86.sse.max.ps"},
7819 {INTRINS_SSE_HADDPS, "llvm.x86.sse3.hadd.ps"},
7820 {INTRINS_SSE_HSUBPS, "llvm.x86.sse3.hsub.ps"},
7821 {INTRINS_SSE_ADDSUBPS, "llvm.x86.sse3.addsub.ps"},
7822 {INTRINS_SSE_MINPD, "llvm.x86.sse2.min.pd"},
7823 {INTRINS_SSE_MAXPD, "llvm.x86.sse2.max.pd"},
7824 {INTRINS_SSE_HADDPD, "llvm.x86.sse3.hadd.pd"},
7825 {INTRINS_SSE_HSUBPD, "llvm.x86.sse3.hsub.pd"},
7826 {INTRINS_SSE_ADDSUBPD, "llvm.x86.sse3.addsub.pd"},
7827 {INTRINS_SSE_PADDSW, "llvm.x86.sse2.padds.w"},
7828 {INTRINS_SSE_PSUBSW, "llvm.x86.sse2.psubs.w"},
7829 {INTRINS_SSE_PADDUSW, "llvm.x86.sse2.paddus.w"},
7830 {INTRINS_SSE_PSUBUSW, "llvm.x86.sse2.psubus.w"},
7831 {INTRINS_SSE_PAVGW, "llvm.x86.sse2.pavg.w"},
7832 {INTRINS_SSE_PMULHW, "llvm.x86.sse2.pmulh.w"},
7833 {INTRINS_SSE_PMULHU, "llvm.x86.sse2.pmulhu.w"},
7834 {INTRINS_SE_PADDSB, "llvm.x86.sse2.padds.b"},
7835 {INTRINS_SSE_PSUBSB, "llvm.x86.sse2.psubs.b"},
7836 {INTRINS_SSE_PADDUSB, "llvm.x86.sse2.paddus.b"},
7837 {INTRINS_SSE_PSUBUSB, "llvm.x86.sse2.psubus.b"},
7838 {INTRINS_SSE_PAVGB, "llvm.x86.sse2.pavg.b"},
7839 {INTRINS_SSE_PAUSE, "llvm.x86.sse2.pause"}
7840 #endif
7843 static void
7844 add_sse_binary (LLVMModuleRef module, const char *name, int type)
7846 LLVMTypeRef ret_type = type_to_simd_type (type);
7847 AddFunc2 (module, name, ret_type, ret_type, ret_type);
7850 static void
7851 add_intrinsic (LLVMModuleRef module, int id)
7853 const char *name;
7854 #if defined(TARGET_AMD64) || defined(TARGET_X86)
7855 LLVMTypeRef ret_type, arg_types [16];
7856 #endif
7858 name = g_hash_table_lookup (intrins_id_to_name, GINT_TO_POINTER (id));
7859 g_assert (name);
7861 switch (id) {
7862 case INTRINS_MEMSET: {
7863 LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMInt8Type (), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
7865 AddFunc (module, name, LLVMVoidType (), params, 5);
7866 break;
7868 case INTRINS_MEMCPY: {
7869 LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMPointerType (LLVMInt8Type (), 0), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
7871 AddFunc (module, name, LLVMVoidType (), params, 5);
7872 break;
7874 case INTRINS_SADD_OVF_I32:
7875 case INTRINS_UADD_OVF_I32:
7876 case INTRINS_SSUB_OVF_I32:
7877 case INTRINS_USUB_OVF_I32:
7878 case INTRINS_SMUL_OVF_I32:
7879 case INTRINS_UMUL_OVF_I32: {
7880 LLVMTypeRef ovf_res_i32 [] = { LLVMInt32Type (), LLVMInt1Type () };
7881 LLVMTypeRef params [] = { LLVMInt32Type (), LLVMInt32Type () };
7882 LLVMTypeRef ret_type = LLVMStructType (ovf_res_i32, 2, FALSE);
7884 AddFunc (module, name, ret_type, params, 2);
7885 break;
7887 case INTRINS_SADD_OVF_I64:
7888 case INTRINS_UADD_OVF_I64:
7889 case INTRINS_SSUB_OVF_I64:
7890 case INTRINS_USUB_OVF_I64:
7891 case INTRINS_SMUL_OVF_I64:
7892 case INTRINS_UMUL_OVF_I64: {
7893 LLVMTypeRef ovf_res_i64 [] = { LLVMInt64Type (), LLVMInt1Type () };
7894 LLVMTypeRef params [] = { LLVMInt64Type (), LLVMInt64Type () };
7895 LLVMTypeRef ret_type = LLVMStructType (ovf_res_i64, 2, FALSE);
7897 AddFunc (module, name, ret_type, params, 2);
7898 break;
7900 case INTRINS_SIN:
7901 case INTRINS_COS:
7902 case INTRINS_SQRT:
7903 case INTRINS_FABS: {
7904 LLVMTypeRef params [] = { LLVMDoubleType () };
7906 AddFunc (module, name, LLVMDoubleType (), params, 1);
7907 break;
7909 case INTRINS_EXPECT_I8:
7910 AddFunc2 (module, name, LLVMInt8Type (), LLVMInt8Type (), LLVMInt8Type ());
7911 break;
7912 case INTRINS_EXPECT_I1:
7913 AddFunc2 (module, name, LLVMInt1Type (), LLVMInt1Type (), LLVMInt1Type ());
7914 break;
7915 #if defined(TARGET_AMD64) || defined(TARGET_X86)
7916 case INTRINS_SSE_PMOVMSKB:
7917 /* pmovmskb */
7918 ret_type = LLVMInt32Type ();
7919 arg_types [0] = type_to_simd_type (MONO_TYPE_I1);
7920 AddFunc (module, name, ret_type, arg_types, 1);
7921 break;
7922 case INTRINS_SSE_PSRLI_W:
7923 case INTRINS_SSE_PSRAI_W:
7924 case INTRINS_SSE_PSLLI_W:
7925 /* shifts */
7926 ret_type = type_to_simd_type (MONO_TYPE_I2);
7927 arg_types [0] = ret_type;
7928 arg_types [1] = LLVMInt32Type ();
7929 AddFunc (module, name, ret_type, arg_types, 2);
7930 break;
7931 case INTRINS_SSE_PSRLI_D:
7932 case INTRINS_SSE_PSRAI_D:
7933 case INTRINS_SSE_PSLLI_D:
7934 ret_type = type_to_simd_type (MONO_TYPE_I4);
7935 arg_types [0] = ret_type;
7936 arg_types [1] = LLVMInt32Type ();
7937 AddFunc (module, name, ret_type, arg_types, 2);
7938 break;
7939 case INTRINS_SSE_PSRLI_Q:
7940 case INTRINS_SSE_PSLLI_Q:
7941 ret_type = type_to_simd_type (MONO_TYPE_I8);
7942 arg_types [0] = ret_type;
7943 arg_types [1] = LLVMInt32Type ();
7944 AddFunc (module, name, ret_type, arg_types, 2);
7945 break;
7946 case INTRINS_SSE_SQRT_PD:
7947 /* Unary ops */
7948 ret_type = type_to_simd_type (MONO_TYPE_R8);
7949 arg_types [0] = ret_type;
7950 AddFunc (module, name, ret_type, arg_types, 1);
7951 break;
7952 case INTRINS_SSE_SQRT_PS:
7953 ret_type = type_to_simd_type (MONO_TYPE_R4);
7954 arg_types [0] = ret_type;
7955 AddFunc (module, name, ret_type, arg_types, 1);
7956 break;
7957 case INTRINS_SSE_RSQRT_PS:
7958 ret_type = type_to_simd_type (MONO_TYPE_R4);
7959 arg_types [0] = ret_type;
7960 AddFunc (module, name, ret_type, arg_types, 1);
7961 break;
7962 case INTRINS_SSE_RCP_PS:
7963 ret_type = type_to_simd_type (MONO_TYPE_R4);
7964 arg_types [0] = ret_type;
7965 AddFunc (module, name, ret_type, arg_types, 1);
7966 break;
7967 case INTRINS_SSE_CVTTPD2DQ:
7968 ret_type = type_to_simd_type (MONO_TYPE_I4);
7969 arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
7970 AddFunc (module, name, ret_type, arg_types, 1);
7971 break;
7972 case INTRINS_SSE_CVTTPS2DQ:
7973 ret_type = type_to_simd_type (MONO_TYPE_I4);
7974 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
7975 AddFunc (module, name, ret_type, arg_types, 1);
7976 break;
7977 case INTRINS_SSE_CVTDQ2PD:
7978 /* Conversion ops */
7979 ret_type = type_to_simd_type (MONO_TYPE_R8);
7980 arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
7981 AddFunc (module, name, ret_type, arg_types, 1);
7982 break;
7983 case INTRINS_SSE_CVTDQ2PS:
7984 ret_type = type_to_simd_type (MONO_TYPE_R4);
7985 arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
7986 AddFunc (module, name, ret_type, arg_types, 1);
7987 break;
7988 case INTRINS_SSE_CVTPD2DQ:
7989 ret_type = type_to_simd_type (MONO_TYPE_I4);
7990 arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
7991 AddFunc (module, name, ret_type, arg_types, 1);
7992 break;
7993 case INTRINS_SSE_CVTPS2DQ:
7994 ret_type = type_to_simd_type (MONO_TYPE_I4);
7995 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
7996 AddFunc (module, name, ret_type, arg_types, 1);
7997 break;
7998 case INTRINS_SSE_CVTPD2PS:
7999 ret_type = type_to_simd_type (MONO_TYPE_R4);
8000 arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
8001 AddFunc (module, name, ret_type, arg_types, 1);
8002 break;
8003 case INTRINS_SSE_CVTPS2PD:
8004 ret_type = type_to_simd_type (MONO_TYPE_R8);
8005 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8006 AddFunc (module, name, ret_type, arg_types, 1);
8007 break;
8008 case INTRINS_SSE_CMPPD:
8009 /* cmp pd/ps */
8010 ret_type = type_to_simd_type (MONO_TYPE_R8);
8011 arg_types [0] = ret_type;
8012 arg_types [1] = ret_type;
8013 arg_types [2] = LLVMInt8Type ();
8014 AddFunc (module, name, ret_type, arg_types, 3);
8015 break;
8016 case INTRINS_SSE_CMPPS:
8017 ret_type = type_to_simd_type (MONO_TYPE_R4);
8018 arg_types [0] = ret_type;
8019 arg_types [1] = ret_type;
8020 arg_types [2] = LLVMInt8Type ();
8021 AddFunc (module, name, ret_type, arg_types, 3);
8022 break;
8023 case INTRINS_SSE_PACKSSWB:
8024 case INTRINS_SSE_PACKUSWB:
8025 case INTRINS_SSE_PACKSSDW:
8026 /* pack */
8027 ret_type = type_to_simd_type (MONO_TYPE_I1);
8028 arg_types [0] = type_to_simd_type (MONO_TYPE_I2);
8029 arg_types [1] = type_to_simd_type (MONO_TYPE_I2);
8030 AddFunc (module, name, ret_type, arg_types, 2);
8031 break;
8032 case INTRINS_SSE_PACKUSDW:
8033 ret_type = type_to_simd_type (MONO_TYPE_I2);
8034 arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
8035 arg_types [1] = type_to_simd_type (MONO_TYPE_I4);
8036 AddFunc (module, name, ret_type, arg_types, 2);
8037 break;
8038 /* SSE Binary ops */
8039 case INTRINS_SSE_PADDSW:
8040 case INTRINS_SSE_PSUBSW:
8041 case INTRINS_SSE_PADDUSW:
8042 case INTRINS_SSE_PSUBUSW:
8043 case INTRINS_SSE_PAVGW:
8044 case INTRINS_SSE_PMULHW:
8045 case INTRINS_SSE_PMULHU:
8046 add_sse_binary (module, name, MONO_TYPE_I2);
8047 break;
8048 case INTRINS_SSE_MINPS:
8049 case INTRINS_SSE_MAXPS:
8050 case INTRINS_SSE_HADDPS:
8051 case INTRINS_SSE_HSUBPS:
8052 case INTRINS_SSE_ADDSUBPS:
8053 add_sse_binary (module, name, MONO_TYPE_R4);
8054 break;
8055 case INTRINS_SSE_MINPD:
8056 case INTRINS_SSE_MAXPD:
8057 case INTRINS_SSE_HADDPD:
8058 case INTRINS_SSE_HSUBPD:
8059 case INTRINS_SSE_ADDSUBPD:
8060 add_sse_binary (module, name, MONO_TYPE_R8);
8061 break;
8062 case INTRINS_SE_PADDSB:
8063 case INTRINS_SSE_PSUBSB:
8064 case INTRINS_SSE_PADDUSB:
8065 case INTRINS_SSE_PSUBUSB:
8066 case INTRINS_SSE_PAVGB:
8067 add_sse_binary (module, name, MONO_TYPE_I1);
8068 break;
8069 case INTRINS_SSE_PAUSE:
8070 AddFunc (module, "llvm.x86.sse2.pause", LLVMVoidType (), NULL, 0);
8071 break;
8072 #endif
8073 default:
8074 g_assert_not_reached ();
8075 break;
8079 static LLVMValueRef
8080 get_intrinsic (EmitContext *ctx, const char *name)
8082 #if LLVM_API_VERSION > 100
8083 LLVMValueRef res;
8086 * Every method is emitted into its own module so
8087 * we can add intrinsics on demand.
8089 res = LLVMGetNamedFunction (ctx->lmodule, name);
8090 if (!res) {
8091 int id = -1;
8093 /* No locking needed */
8094 id = GPOINTER_TO_INT (g_hash_table_lookup (intrins_name_to_id, name));
8095 id --;
8096 if (id == -1)
8097 printf ("%s\n", name);
8098 g_assert (id != -1);
8099 add_intrinsic (ctx->lmodule, id);
8100 res = LLVMGetNamedFunction (ctx->lmodule, name);
8101 g_assert (res);
8104 return res;
8105 #else
8106 LLVMValueRef res;
8108 res = LLVMGetNamedFunction (ctx->lmodule, name);
8109 g_assert (res);
8110 return res;
8111 #endif
8114 static void
8115 add_intrinsics (LLVMModuleRef module)
8117 int i;
8119 /* Emit declarations of instrinsics */
8121 * It would be nicer to emit only the intrinsics actually used, but LLVM's Module
8122 * type doesn't seem to do any locking.
8124 for (i = 0; i < INTRINS_NUM; ++i)
8125 add_intrinsic (module, i);
8127 /* EH intrinsics */
8129 AddFunc (module, "mono_personality", LLVMVoidType (), NULL, 0);
8131 AddFunc (module, "llvm_resume_unwind_trampoline", LLVMVoidType (), NULL, 0);
8134 /* Load/Store intrinsics */
8136 LLVMTypeRef arg_types [5];
8137 int i;
8138 char name [128];
8140 for (i = 1; i <= 8; i *= 2) {
8141 arg_types [0] = LLVMPointerType (LLVMIntType (i * 8), 0);
8142 arg_types [1] = LLVMInt32Type ();
8143 arg_types [2] = LLVMInt1Type ();
8144 arg_types [3] = LLVMInt32Type ();
8145 sprintf (name, "llvm.mono.load.i%d.p0i%d", i * 8, i * 8);
8146 AddFunc (module, name, LLVMIntType (i * 8), arg_types, 4);
8148 arg_types [0] = LLVMIntType (i * 8);
8149 arg_types [1] = LLVMPointerType (LLVMIntType (i * 8), 0);
8150 arg_types [2] = LLVMInt32Type ();
8151 arg_types [3] = LLVMInt1Type ();
8152 arg_types [4] = LLVMInt32Type ();
8153 sprintf (name, "llvm.mono.store.i%d.p0i%d", i * 8, i * 8);
8154 AddFunc (module, name, LLVMVoidType (), arg_types, 5);
8159 static void
8160 add_types (MonoLLVMModule *module)
8162 module->ptr_type = LLVMPointerType (sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type (), 0);
8165 void
8166 mono_llvm_init (void)
8168 GHashTable *h;
8169 int i;
8171 mono_native_tls_alloc (&current_cfg_tls_id, NULL);
8173 h = g_hash_table_new (NULL, NULL);
8174 for (i = 0; i < INTRINS_NUM; ++i)
8175 g_hash_table_insert (h, GINT_TO_POINTER (intrinsics [i].id), (gpointer)intrinsics [i].name);
8176 intrins_id_to_name = h;
8178 h = g_hash_table_new (g_str_hash, g_str_equal);
8179 for (i = 0; i < INTRINS_NUM; ++i)
8180 g_hash_table_insert (h, (gpointer)intrinsics [i].name, GINT_TO_POINTER (intrinsics [i].id + 1));
8181 intrins_name_to_id = h;
8184 static void
8185 init_jit_module (MonoDomain *domain)
8187 MonoJitDomainInfo *dinfo;
8188 MonoLLVMModule *module;
8189 char *name;
8191 dinfo = domain_jit_info (domain);
8192 if (dinfo->llvm_module)
8193 return;
8195 mono_loader_lock ();
8197 if (dinfo->llvm_module) {
8198 mono_loader_unlock ();
8199 return;
8202 module = g_new0 (MonoLLVMModule, 1);
8204 name = g_strdup_printf ("mono-%s", domain->friendly_name);
8205 module->lmodule = LLVMModuleCreateWithName (name);
8206 module->context = LLVMGetGlobalContext ();
8208 module->mono_ee = (MonoEERef*)mono_llvm_create_ee (LLVMCreateModuleProviderForExistingModule (module->lmodule), alloc_cb, emitted_cb, exception_cb, dlsym_cb, &module->ee);
8210 add_intrinsics (module->lmodule);
8211 add_types (module);
8213 module->llvm_types = g_hash_table_new (NULL, NULL);
8215 #if LLVM_API_VERSION < 100
8216 MonoJitICallInfo *info;
8218 info = mono_find_jit_icall_by_name ("llvm_resume_unwind_trampoline");
8219 g_assert (info);
8220 LLVMAddGlobalMapping (module->ee, LLVMGetNamedFunction (module->lmodule, "llvm_resume_unwind_trampoline"), (void*)info->func);
8221 #endif
8223 mono_memory_barrier ();
8225 dinfo->llvm_module = module;
8227 mono_loader_unlock ();
8230 void
8231 mono_llvm_cleanup (void)
8233 MonoLLVMModule *module = &aot_module;
8235 if (module->lmodule)
8236 LLVMDisposeModule (module->lmodule);
8238 if (module->context)
8239 LLVMContextDispose (module->context);
8242 void
8243 mono_llvm_free_domain_info (MonoDomain *domain)
8245 MonoJitDomainInfo *info = domain_jit_info (domain);
8246 MonoLLVMModule *module = (MonoLLVMModule*)info->llvm_module;
8247 int i;
8249 if (!module)
8250 return;
8252 if (module->llvm_types)
8253 g_hash_table_destroy (module->llvm_types);
8255 mono_llvm_dispose_ee (module->mono_ee);
8257 if (module->bb_names) {
8258 for (i = 0; i < module->bb_names_len; ++i)
8259 g_free (module->bb_names [i]);
8260 g_free (module->bb_names);
8262 //LLVMDisposeModule (module->module);
8264 g_free (module);
8266 info->llvm_module = NULL;
8269 void
8270 mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only)
8272 MonoLLVMModule *module = &aot_module;
8274 /* Delete previous module */
8275 if (module->plt_entries)
8276 g_hash_table_destroy (module->plt_entries);
8277 if (module->lmodule)
8278 LLVMDisposeModule (module->lmodule);
8280 memset (module, 0, sizeof (aot_module));
8282 module->lmodule = LLVMModuleCreateWithName ("aot");
8283 module->assembly = assembly;
8284 module->global_prefix = g_strdup (global_prefix);
8285 module->got_symbol = g_strdup_printf ("%s_llvm_got", global_prefix);
8286 module->eh_frame_symbol = g_strdup_printf ("%s_eh_frame", global_prefix);
8287 module->get_method_symbol = g_strdup_printf ("%s_get_method", global_prefix);
8288 module->get_unbox_tramp_symbol = g_strdup_printf ("%s_get_unbox_tramp", global_prefix);
8289 module->external_symbols = TRUE;
8290 module->emit_dwarf = emit_dwarf;
8291 module->static_link = static_link;
8292 module->llvm_only = llvm_only;
8293 /* The first few entries are reserved */
8294 module->max_got_offset = 16;
8295 module->context = LLVMContextCreate ();
8297 if (llvm_only)
8298 /* clang ignores our debug info because it has an invalid version */
8299 module->emit_dwarf = FALSE;
8301 #if LLVM_API_VERSION > 100
8302 module->emit_dwarf = FALSE;
8303 #endif
8305 add_intrinsics (module->lmodule);
8306 add_types (module);
8308 #if LLVM_API_VERSION > 100
8309 if (module->emit_dwarf) {
8310 char *dir, *build_info, *s, *cu_name;
8312 module->di_builder = mono_llvm_create_di_builder (module->lmodule);
8314 // FIXME:
8315 dir = g_strdup (".");
8316 build_info = mono_get_runtime_build_info ();
8317 s = g_strdup_printf ("Mono AOT Compiler %s (LLVM)", build_info);
8318 cu_name = g_path_get_basename (assembly->image->name);
8319 module->cu = mono_llvm_di_create_compile_unit (module->di_builder, cu_name, dir, s);
8320 g_free (dir);
8321 g_free (build_info);
8322 g_free (s);
8324 #endif
8326 /* Add GOT */
8328 * We couldn't compute the type of the LLVM global representing the got because
8329 * its size is only known after all the methods have been emitted. So create
8330 * a dummy variable, and replace all uses it with the real got variable when
8331 * its size is known in mono_llvm_emit_aot_module ().
8334 LLVMTypeRef got_type = LLVMArrayType (module->ptr_type, 0);
8336 module->got_var = LLVMAddGlobal (module->lmodule, got_type, "mono_dummy_got");
8337 LLVMSetInitializer (module->got_var, LLVMConstNull (got_type));
8340 /* Add initialization array */
8341 if (llvm_only) {
8342 LLVMTypeRef inited_type = LLVMArrayType (LLVMInt8Type (), 0);
8344 module->inited_var = LLVMAddGlobal (aot_module.lmodule, inited_type, "mono_inited_tmp");
8345 LLVMSetInitializer (module->inited_var, LLVMConstNull (inited_type));
8348 if (llvm_only)
8349 emit_init_icall_wrappers (module);
8351 emit_llvm_code_start (module);
8353 /* Add a dummy personality function */
8354 if (!use_debug_personality) {
8355 LLVMValueRef personality = LLVMAddFunction (module->lmodule, default_personality_name, LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE));
8356 LLVMSetLinkage (personality, LLVMExternalLinkage);
8357 mark_as_used (module, personality);
8360 /* Add a reference to the c++ exception we throw/catch */
8362 LLVMTypeRef exc = LLVMPointerType (LLVMInt8Type (), 0);
8363 module->sentinel_exception = LLVMAddGlobal (module->lmodule, exc, "_ZTIPi");
8364 LLVMSetLinkage (module->sentinel_exception, LLVMExternalLinkage);
8365 mono_llvm_set_is_constant (module->sentinel_exception);
8368 module->llvm_types = g_hash_table_new (NULL, NULL);
8369 module->plt_entries = g_hash_table_new (g_str_hash, g_str_equal);
8370 module->plt_entries_ji = g_hash_table_new (NULL, NULL);
8371 module->direct_callables = g_hash_table_new (g_str_hash, g_str_equal);
8372 module->method_to_lmethod = g_hash_table_new (NULL, NULL);
8373 module->idx_to_lmethod = g_hash_table_new (NULL, NULL);
8374 module->idx_to_unbox_tramp = g_hash_table_new (NULL, NULL);
8375 module->method_to_callers = g_hash_table_new (NULL, NULL);
8378 static LLVMValueRef
8379 llvm_array_from_uints (LLVMTypeRef el_type, guint32 *values, int nvalues)
8381 int i;
8382 LLVMValueRef res, *vals;
8384 vals = g_new0 (LLVMValueRef, nvalues);
8385 for (i = 0; i < nvalues; ++i)
8386 vals [i] = LLVMConstInt (LLVMInt32Type (), values [i], FALSE);
8387 res = LLVMConstArray (LLVMInt32Type (), vals, nvalues);
8388 g_free (vals);
8389 return res;
8392 static LLVMValueRef
8393 llvm_array_from_bytes (guint8 *values, int nvalues)
8395 int i;
8396 LLVMValueRef res, *vals;
8398 vals = g_new0 (LLVMValueRef, nvalues);
8399 for (i = 0; i < nvalues; ++i)
8400 vals [i] = LLVMConstInt (LLVMInt8Type (), values [i], FALSE);
8401 res = LLVMConstArray (LLVMInt8Type (), vals, nvalues);
8402 g_free (vals);
8403 return res;
8406 * mono_llvm_emit_aot_file_info:
8408 * Emit the MonoAotFileInfo structure.
8409 * Same as emit_aot_file_info () in aot-compiler.c.
8411 void
8412 mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code)
8414 MonoLLVMModule *module = &aot_module;
8416 /* Save these for later */
8417 memcpy (&module->aot_info, info, sizeof (MonoAotFileInfo));
8418 module->has_jitted_code = has_jitted_code;
8422 * mono_llvm_emit_aot_data:
8424 * Emit the binary data DATA pointed to by symbol SYMBOL.
8426 void
8427 mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
8429 MonoLLVMModule *module = &aot_module;
8430 LLVMTypeRef type;
8431 LLVMValueRef d;
8433 type = LLVMArrayType (LLVMInt8Type (), data_len);
8434 d = LLVMAddGlobal (module->lmodule, type, symbol);
8435 LLVMSetVisibility (d, LLVMHiddenVisibility);
8436 LLVMSetLinkage (d, LLVMInternalLinkage);
8437 LLVMSetInitializer (d, mono_llvm_create_constant_data_array (data, data_len));
8438 mono_llvm_set_is_constant (d);
8441 /* Add a reference to a global defined in JITted code */
8442 static LLVMValueRef
8443 AddJitGlobal (MonoLLVMModule *module, LLVMTypeRef type, const char *name)
8445 char *s;
8446 LLVMValueRef v;
8448 s = g_strdup_printf ("%s%s", module->global_prefix, name);
8449 v = LLVMAddGlobal (module->lmodule, LLVMInt8Type (), s);
8450 g_free (s);
8451 return v;
8454 static void
8455 emit_aot_file_info (MonoLLVMModule *module)
8457 LLVMTypeRef file_info_type;
8458 LLVMTypeRef *eltypes, eltype;
8459 LLVMValueRef info_var;
8460 LLVMValueRef *fields;
8461 int i, nfields, tindex;
8462 MonoAotFileInfo *info;
8463 LLVMModuleRef lmodule = module->lmodule;
8465 info = &module->aot_info;
8467 /* Create an LLVM type to represent MonoAotFileInfo */
8468 nfields = 2 + MONO_AOT_FILE_INFO_NUM_SYMBOLS + 16 + 5;
8469 eltypes = g_new (LLVMTypeRef, nfields);
8470 tindex = 0;
8471 eltypes [tindex ++] = LLVMInt32Type ();
8472 eltypes [tindex ++] = LLVMInt32Type ();
8473 /* Symbols */
8474 for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i)
8475 eltypes [tindex ++] = LLVMPointerType (LLVMInt8Type (), 0);
8476 /* Scalars */
8477 for (i = 0; i < 15; ++i)
8478 eltypes [tindex ++] = LLVMInt32Type ();
8479 /* Arrays */
8480 eltypes [tindex ++] = LLVMArrayType (LLVMInt32Type (), MONO_AOT_TABLE_NUM);
8481 for (i = 0; i < 4; ++i)
8482 eltypes [tindex ++] = LLVMArrayType (LLVMInt32Type (), MONO_AOT_TRAMP_NUM);
8483 eltypes [tindex ++] = LLVMArrayType (LLVMInt8Type (), 16);
8484 g_assert (tindex == nfields);
8485 file_info_type = LLVMStructCreateNamed (module->context, "MonoAotFileInfo");
8486 LLVMStructSetBody (file_info_type, eltypes, nfields, FALSE);
8488 info_var = LLVMAddGlobal (lmodule, file_info_type, "mono_aot_file_info");
8489 if (module->static_link) {
8490 LLVMSetVisibility (info_var, LLVMHiddenVisibility);
8491 LLVMSetLinkage (info_var, LLVMInternalLinkage);
8493 fields = g_new (LLVMValueRef, nfields);
8494 tindex = 0;
8495 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->version, FALSE);
8496 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->dummy, FALSE);
8498 /* Symbols */
8500 * We use LLVMGetNamedGlobal () for symbol which are defined in LLVM code, and LLVMAddGlobal ()
8501 * for symbols defined in the .s file emitted by the aot compiler.
8503 eltype = eltypes [tindex];
8504 if (module->llvm_only)
8505 fields [tindex ++] = LLVMConstNull (eltype);
8506 else
8507 fields [tindex ++] = AddJitGlobal (module, eltype, "jit_got");
8508 fields [tindex ++] = module->got_var;
8509 /* llc defines this directly */
8510 if (!module->llvm_only) {
8511 fields [tindex ++] = LLVMAddGlobal (lmodule, eltype, module->eh_frame_symbol);
8512 fields [tindex ++] = LLVMConstNull (eltype);
8513 fields [tindex ++] = LLVMConstNull (eltype);
8514 } else {
8515 fields [tindex ++] = LLVMConstNull (eltype);
8516 fields [tindex ++] = module->get_method;
8517 fields [tindex ++] = module->get_unbox_tramp;
8519 if (module->has_jitted_code) {
8520 fields [tindex ++] = AddJitGlobal (module, eltype, "jit_code_start");
8521 fields [tindex ++] = AddJitGlobal (module, eltype, "jit_code_end");
8522 } else {
8523 fields [tindex ++] = LLVMConstNull (eltype);
8524 fields [tindex ++] = LLVMConstNull (eltype);
8526 if (!module->llvm_only)
8527 fields [tindex ++] = AddJitGlobal (module, eltype, "method_addresses");
8528 else
8529 fields [tindex ++] = LLVMConstNull (eltype);
8530 if (info->flags & MONO_AOT_FILE_FLAG_SEPARATE_DATA) {
8531 for (i = 0; i < MONO_AOT_TABLE_NUM; ++i)
8532 fields [tindex ++] = LLVMConstNull (eltype);
8533 } else {
8534 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "blob");
8535 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "class_name_table");
8536 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "class_info_offsets");
8537 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "method_info_offsets");
8538 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "ex_info_offsets");
8539 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "extra_method_info_offsets");
8540 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "extra_method_table");
8541 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "got_info_offsets");
8542 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "llvm_got_info_offsets");
8543 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "image_table");
8545 /* Not needed (mem_end) */
8546 fields [tindex ++] = LLVMConstNull (eltype);
8547 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "assembly_guid");
8548 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "runtime_version");
8549 if (info->trampoline_size [0]) {
8550 fields [tindex ++] = AddJitGlobal (module, eltype, "specific_trampolines");
8551 fields [tindex ++] = AddJitGlobal (module, eltype, "static_rgctx_trampolines");
8552 fields [tindex ++] = AddJitGlobal (module, eltype, "imt_thunks");
8553 fields [tindex ++] = AddJitGlobal (module, eltype, "gsharedvt_arg_trampolines");
8554 } else {
8555 fields [tindex ++] = LLVMConstNull (eltype);
8556 fields [tindex ++] = LLVMConstNull (eltype);
8557 fields [tindex ++] = LLVMConstNull (eltype);
8558 fields [tindex ++] = LLVMConstNull (eltype);
8560 if (module->static_link && !module->llvm_only)
8561 fields [tindex ++] = AddJitGlobal (module, eltype, "globals");
8562 else
8563 fields [tindex ++] = LLVMConstNull (eltype);
8564 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "assembly_name");
8565 if (!module->llvm_only) {
8566 fields [tindex ++] = AddJitGlobal (module, eltype, "plt");
8567 fields [tindex ++] = AddJitGlobal (module, eltype, "plt_end");
8568 fields [tindex ++] = AddJitGlobal (module, eltype, "unwind_info");
8569 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_trampolines");
8570 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_trampolines_end");
8571 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_trampoline_addresses");
8572 } else {
8573 fields [tindex ++] = LLVMConstNull (eltype);
8574 fields [tindex ++] = LLVMConstNull (eltype);
8575 fields [tindex ++] = LLVMConstNull (eltype);
8576 fields [tindex ++] = LLVMConstNull (eltype);
8577 fields [tindex ++] = LLVMConstNull (eltype);
8578 fields [tindex ++] = LLVMConstNull (eltype);
8581 for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i)
8582 fields [2 + i] = LLVMConstBitCast (fields [2 + i], eltype);
8584 /* Scalars */
8585 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->plt_got_offset_base, FALSE);
8586 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->got_size, FALSE);
8587 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->plt_size, FALSE);
8588 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nmethods, FALSE);
8589 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->flags, FALSE);
8590 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->opts, FALSE);
8591 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->simd_opts, FALSE);
8592 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->gc_name_index, FALSE);
8593 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->num_rgctx_fetch_trampolines, FALSE);
8594 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->double_align, FALSE);
8595 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->long_align, FALSE);
8596 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->generic_tramp_num, FALSE);
8597 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->tramp_page_size, FALSE);
8598 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nshared_got_entries, FALSE);
8599 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->datafile_size, FALSE);
8600 /* Arrays */
8601 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->table_offsets, MONO_AOT_TABLE_NUM);
8602 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->num_trampolines, MONO_AOT_TRAMP_NUM);
8603 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->trampoline_got_offset_base, MONO_AOT_TRAMP_NUM);
8604 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->trampoline_size, MONO_AOT_TRAMP_NUM);
8605 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->tramp_page_code_offsets, MONO_AOT_TRAMP_NUM);
8607 fields [tindex ++] = llvm_array_from_bytes (info->aotid, 16);
8608 g_assert (tindex == nfields);
8610 LLVMSetInitializer (info_var, LLVMConstNamedStruct (file_info_type, fields, nfields));
8612 if (module->static_link) {
8613 char *s, *p;
8614 LLVMValueRef var;
8616 s = g_strdup_printf ("mono_aot_module_%s_info", module->assembly->aname.name);
8617 /* Get rid of characters which cannot occur in symbols */
8618 p = s;
8619 for (p = s; *p; ++p) {
8620 if (!(isalnum (*p) || *p == '_'))
8621 *p = '_';
8623 var = LLVMAddGlobal (module->lmodule, LLVMPointerType (LLVMInt8Type (), 0), s);
8624 g_free (s);
8625 LLVMSetInitializer (var, LLVMConstBitCast (LLVMGetNamedGlobal (module->lmodule, "mono_aot_file_info"), LLVMPointerType (LLVMInt8Type (), 0)));
8626 LLVMSetLinkage (var, LLVMExternalLinkage);
8631 * Emit the aot module into the LLVM bitcode file FILENAME.
8633 void
8634 mono_llvm_emit_aot_module (const char *filename, const char *cu_name)
8636 LLVMTypeRef got_type, inited_type;
8637 LLVMValueRef real_got, real_inited;
8638 MonoLLVMModule *module = &aot_module;
8640 emit_llvm_code_end (module);
8643 * Create the real got variable and replace all uses of the dummy variable with
8644 * the real one.
8646 got_type = LLVMArrayType (module->ptr_type, module->max_got_offset + 1);
8647 real_got = LLVMAddGlobal (module->lmodule, got_type, module->got_symbol);
8648 LLVMSetInitializer (real_got, LLVMConstNull (got_type));
8649 if (module->external_symbols) {
8650 LLVMSetLinkage (real_got, LLVMExternalLinkage);
8651 LLVMSetVisibility (real_got, LLVMHiddenVisibility);
8652 } else {
8653 LLVMSetLinkage (real_got, LLVMInternalLinkage);
8655 mono_llvm_replace_uses_of (module->got_var, real_got);
8657 mark_as_used (&aot_module, real_got);
8659 /* Delete the dummy got so it doesn't become a global */
8660 LLVMDeleteGlobal (module->got_var);
8661 module->got_var = real_got;
8664 * Same for the init_var
8666 if (module->llvm_only) {
8667 inited_type = LLVMArrayType (LLVMInt8Type (), module->max_inited_idx + 1);
8668 real_inited = LLVMAddGlobal (module->lmodule, inited_type, "mono_inited");
8669 LLVMSetInitializer (real_inited, LLVMConstNull (inited_type));
8670 LLVMSetLinkage (real_inited, LLVMInternalLinkage);
8671 mono_llvm_replace_uses_of (module->inited_var, real_inited);
8672 LLVMDeleteGlobal (module->inited_var);
8675 if (module->llvm_only) {
8676 emit_get_method (&aot_module);
8677 emit_get_unbox_tramp (&aot_module);
8680 emit_llvm_used (&aot_module);
8681 emit_dbg_info (&aot_module, filename, cu_name);
8682 emit_aot_file_info (&aot_module);
8685 * Replace GOT entries for directly callable methods with the methods themselves.
8686 * It would be easier to implement this by predefining all methods before compiling
8687 * their bodies, but that couldn't handle the case when a method fails to compile
8688 * with llvm.
8690 if (module->llvm_only) {
8691 GHashTableIter iter;
8692 MonoMethod *method;
8693 GSList *callers, *l;
8695 g_hash_table_iter_init (&iter, module->method_to_callers);
8696 while (g_hash_table_iter_next (&iter, (void**)&method, (void**)&callers)) {
8697 LLVMValueRef lmethod;
8699 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
8700 continue;
8702 lmethod = (LLVMValueRef)g_hash_table_lookup (module->method_to_lmethod, method);
8703 if (lmethod) {
8704 for (l = callers; l; l = l->next) {
8705 LLVMValueRef caller = (LLVMValueRef)l->data;
8707 mono_llvm_replace_uses_of (caller, lmethod);
8713 /* Replace PLT entries for directly callable methods with the methods themselves */
8715 GHashTableIter iter;
8716 MonoJumpInfo *ji;
8717 LLVMValueRef callee;
8719 g_hash_table_iter_init (&iter, module->plt_entries_ji);
8720 while (g_hash_table_iter_next (&iter, (void**)&ji, (void**)&callee)) {
8721 if (mono_aot_is_direct_callable (ji)) {
8722 LLVMValueRef lmethod;
8724 lmethod = (LLVMValueRef)g_hash_table_lookup (module->method_to_lmethod, ji->data.method);
8725 /* The types might not match because the caller might pass an rgctx */
8726 if (lmethod && LLVMTypeOf (callee) == LLVMTypeOf (lmethod)) {
8727 mono_llvm_replace_uses_of (callee, lmethod);
8728 mono_aot_mark_unused_llvm_plt_entry (ji);
8734 #if 1
8736 char *verifier_err;
8738 if (LLVMVerifyModule (module->lmodule, LLVMReturnStatusAction, &verifier_err)) {
8739 printf ("%s\n", verifier_err);
8740 g_assert_not_reached ();
8743 #endif
8745 LLVMWriteBitcodeToFile (module->lmodule, filename);
8749 static LLVMValueRef
8750 md_string (const char *s)
8752 return LLVMMDString (s, strlen (s));
8755 /* Debugging support */
8757 static void
8758 emit_dbg_info (MonoLLVMModule *module, const char *filename, const char *cu_name)
8760 LLVMModuleRef lmodule = module->lmodule;
8761 LLVMValueRef args [16], ver;
8764 * This can only be enabled when LLVM code is emitted into a separate object
8765 * file, since the AOT compiler also emits dwarf info,
8766 * and the abbrev indexes will not be correct since llvm has added its own
8767 * abbrevs.
8769 if (!module->emit_dwarf)
8770 return;
8772 #if LLVM_API_VERSION > 100
8773 mono_llvm_di_builder_finalize (module->di_builder);
8774 #else
8775 LLVMValueRef cu_args [16], cu;
8776 int n_cuargs;
8777 char *build_info, *s, *dir;
8780 * Emit dwarf info in the form of LLVM metadata. There is some
8781 * out-of-date documentation at:
8782 * http://llvm.org/docs/SourceLevelDebugging.html
8783 * but most of this was gathered from the llvm and
8784 * clang sources.
8787 n_cuargs = 0;
8788 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), DW_TAG_compile_unit, FALSE);
8789 /* CU name/compilation dir */
8790 dir = g_path_get_dirname (filename);
8791 args [0] = LLVMMDString (cu_name, strlen (cu_name));
8792 args [1] = LLVMMDString (dir, strlen (dir));
8793 cu_args [n_cuargs ++] = LLVMMDNode (args, 2);
8794 g_free (dir);
8795 /* Language */
8796 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), DW_LANG_C99, FALSE);
8797 /* Producer */
8798 build_info = mono_get_runtime_build_info ();
8799 s = g_strdup_printf ("Mono AOT Compiler %s (LLVM)", build_info);
8800 cu_args [n_cuargs ++] = LLVMMDString (s, strlen (s));
8801 g_free (build_info);
8802 /* Optimized */
8803 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
8804 /* Flags */
8805 cu_args [n_cuargs ++] = LLVMMDString ("", strlen (""));
8806 /* Runtime version */
8807 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
8808 /* Enums */
8809 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
8810 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
8811 /* Subprograms */
8812 if (module->subprogram_mds) {
8813 LLVMValueRef *mds;
8814 int i;
8816 mds = g_new0 (LLVMValueRef, module->subprogram_mds->len);
8817 for (i = 0; i < module->subprogram_mds->len; ++i)
8818 mds [i] = (LLVMValueRef)g_ptr_array_index (module->subprogram_mds, i);
8819 cu_args [n_cuargs ++] = LLVMMDNode (mds, module->subprogram_mds->len);
8820 } else {
8821 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
8823 /* GVs */
8824 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
8825 /* Imported modules */
8826 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
8827 /* SplitName */
8828 cu_args [n_cuargs ++] = LLVMMDString ("", strlen (""));
8829 /* DebugEmissionKind = FullDebug */
8830 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
8831 cu = LLVMMDNode (cu_args, n_cuargs);
8832 LLVMAddNamedMetadataOperand (lmodule, "llvm.dbg.cu", cu);
8833 #endif
8835 #if LLVM_API_VERSION > 100
8836 args [0] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
8837 args [1] = LLVMMDString ("Dwarf Version", strlen ("Dwarf Version"));
8838 args [2] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
8839 ver = LLVMMDNode (args, 3);
8840 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
8842 args [0] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
8843 args [1] = LLVMMDString ("Debug Info Version", strlen ("Debug Info Version"));
8844 args [2] = LLVMConstInt (LLVMInt64Type (), 3, FALSE);
8845 ver = LLVMMDNode (args, 3);
8846 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
8847 #else
8848 args [0] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
8849 args [1] = LLVMMDString ("Dwarf Version", strlen ("Dwarf Version"));
8850 args [2] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
8851 ver = LLVMMDNode (args, 3);
8852 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
8854 args [0] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
8855 args [1] = LLVMMDString ("Debug Info Version", strlen ("Debug Info Version"));
8856 args [2] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
8857 ver = LLVMMDNode (args, 3);
8858 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
8859 #endif
8862 static LLVMValueRef
8863 emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, const char *name)
8865 MonoLLVMModule *module = ctx->module;
8866 MonoDebugMethodInfo *minfo = ctx->minfo;
8867 char *source_file, *dir, *filename;
8868 LLVMValueRef md, args [16], ctx_args [16], md_args [64], type_args [16], ctx_md, type_md;
8869 MonoSymSeqPoint *sym_seq_points;
8870 int n_seq_points;
8872 if (!minfo)
8873 return NULL;
8875 mono_debug_symfile_get_seq_points (minfo, &source_file, NULL, NULL, &sym_seq_points, &n_seq_points);
8876 if (!source_file)
8877 source_file = g_strdup ("<unknown>");
8878 dir = g_path_get_dirname (source_file);
8879 filename = g_path_get_basename (source_file);
8881 #if LLVM_API_VERSION > 100
8882 return mono_llvm_di_create_function (module->di_builder, module->cu, cfg->method->name, name, dir, filename, n_seq_points ? sym_seq_points [0].line : 1);
8883 #endif
8885 ctx_args [0] = LLVMConstInt (LLVMInt32Type (), 0x29, FALSE);
8886 args [0] = md_string (filename);
8887 args [1] = md_string (dir);
8888 ctx_args [1] = LLVMMDNode (args, 2);
8889 ctx_md = LLVMMDNode (ctx_args, 2);
8891 type_args [0] = LLVMConstInt (LLVMInt32Type (), DW_TAG_subroutine_type, FALSE);
8892 type_args [1] = NULL;
8893 type_args [2] = NULL;
8894 type_args [3] = LLVMMDString ("", 0);
8895 type_args [4] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
8896 type_args [5] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
8897 type_args [6] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
8898 type_args [7] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
8899 type_args [8] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
8900 type_args [9] = NULL;
8901 type_args [10] = NULL;
8902 type_args [11] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
8903 type_args [12] = NULL;
8904 type_args [13] = NULL;
8905 type_args [14] = NULL;
8906 type_md = LLVMMDNode (type_args, 14);
8908 /* http://llvm.org/docs/SourceLevelDebugging.html#subprogram-descriptors */
8909 md_args [0] = LLVMConstInt (LLVMInt32Type (), DW_TAG_subprogram, FALSE);
8910 /* Source directory + file pair */
8911 args [0] = md_string (filename);
8912 args [1] = md_string (dir);
8913 md_args [1] = LLVMMDNode (args ,2);
8914 md_args [2] = ctx_md;
8915 md_args [3] = md_string (cfg->method->name);
8916 md_args [4] = md_string (name);
8917 md_args [5] = md_string (name);
8918 /* Line number */
8919 if (n_seq_points)
8920 md_args [6] = LLVMConstInt (LLVMInt32Type (), sym_seq_points [0].line, FALSE);
8921 else
8922 md_args [6] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
8923 /* Type */
8924 md_args [7] = type_md;
8925 /* static */
8926 md_args [8] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
8927 /* not extern */
8928 md_args [9] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
8929 /* Virtuality */
8930 md_args [10] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
8931 /* Index into a virtual function */
8932 md_args [11] = NULL;
8933 md_args [12] = NULL;
8934 /* Flags */
8935 md_args [13] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
8936 /* isOptimized */
8937 md_args [14] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
8938 /* Pointer to LLVM function */
8939 md_args [15] = method;
8940 /* Function template parameter */
8941 md_args [16] = NULL;
8942 /* Function declaration descriptor */
8943 md_args [17] = NULL;
8944 /* List of function variables */
8945 md_args [18] = LLVMMDNode (args, 0);
8946 /* Line number */
8947 md_args [19] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
8948 md = LLVMMDNode (md_args, 20);
8950 if (!module->subprogram_mds)
8951 module->subprogram_mds = g_ptr_array_new ();
8952 g_ptr_array_add (module->subprogram_mds, md);
8954 g_free (dir);
8955 g_free (filename);
8956 g_free (source_file);
8957 g_free (sym_seq_points);
8959 return md;
8962 static void
8963 emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil_code)
8965 MonoCompile *cfg = ctx->cfg;
8967 if (ctx->minfo && cil_code && cil_code >= cfg->header->code && cil_code < cfg->header->code + cfg->header->code_size) {
8968 MonoDebugSourceLocation *loc;
8969 LLVMValueRef loc_md;
8971 loc = mono_debug_symfile_lookup_location (ctx->minfo, cil_code - cfg->header->code);
8973 if (loc) {
8974 #if LLVM_API_VERSION > 100
8975 loc_md = mono_llvm_di_create_location (ctx->module->di_builder, ctx->dbg_md, loc->row, loc->column);
8976 mono_llvm_di_set_location (builder, loc_md);
8977 #else
8978 LLVMValueRef md_args [16];
8979 int nmd_args;
8981 nmd_args = 0;
8982 md_args [nmd_args ++] = LLVMConstInt (LLVMInt32Type (), loc->row, FALSE);
8983 md_args [nmd_args ++] = LLVMConstInt (LLVMInt32Type (), loc->column, FALSE);
8984 md_args [nmd_args ++] = ctx->dbg_md;
8985 md_args [nmd_args ++] = NULL;
8986 loc_md = LLVMMDNode (md_args, nmd_args);
8987 LLVMSetCurrentDebugLocation (builder, loc_md);
8988 #endif
8989 mono_debug_symfile_free_location (loc);
8994 void
8995 default_mono_llvm_unhandled_exception (void)
8997 MonoJitTlsData *jit_tls = mono_get_jit_tls ();
8998 MonoObject *target = mono_gchandle_get_target (jit_tls->thrown_exc);
9000 mono_unhandled_exception (target);
9001 exit (mono_environment_exitcode_get ());
9005 DESIGN:
9006 - Emit LLVM IR from the mono IR using the LLVM C API.
9007 - The original arch specific code remains, so we can fall back to it if we run
9008 into something we can't handle.
9012 A partial list of issues:
9013 - Handling of opcodes which can throw exceptions.
9015 In the mono JIT, these are implemented using code like this:
9016 method:
9017 <compare>
9018 throw_pos:
9019 b<cond> ex_label
9020 <rest of code>
9021 ex_label:
9022 push throw_pos - method
9023 call <exception trampoline>
9025 The problematic part is push throw_pos - method, which cannot be represented
9026 in the LLVM IR, since it does not support label values.
9027 -> this can be implemented in AOT mode using inline asm + labels, but cannot
9028 be implemented in JIT mode ?
9029 -> a possible but slower implementation would use the normal exception
9030 throwing code but it would need to control the placement of the throw code
9031 (it needs to be exactly after the compare+branch).
9032 -> perhaps add a PC offset intrinsics ?
9034 - efficient implementation of .ovf opcodes.
9036 These are currently implemented as:
9037 <ins which sets the condition codes>
9038 b<cond> ex_label
9040 Some overflow opcodes are now supported by LLVM SVN.
9042 - exception handling, unwinding.
9043 - SSA is disabled for methods with exception handlers
9044 - How to obtain unwind info for LLVM compiled methods ?
9045 -> this is now solved by converting the unwind info generated by LLVM
9046 into our format.
9047 - LLVM uses the c++ exception handling framework, while we use our home grown
9048 code, and couldn't use the c++ one:
9049 - its not supported under VC++, other exotic platforms.
9050 - it might be impossible to support filter clauses with it.
9052 - trampolines.
9054 The trampolines need a predictable call sequence, since they need to disasm
9055 the calling code to obtain register numbers / offsets.
9057 LLVM currently generates this code in non-JIT mode:
9058 mov -0x98(%rax),%eax
9059 callq *%rax
9060 Here, the vtable pointer is lost.
9061 -> solution: use one vtable trampoline per class.
9063 - passing/receiving the IMT pointer/RGCTX.
9064 -> solution: pass them as normal arguments ?
9066 - argument passing.
9068 LLVM does not allow the specification of argument registers etc. This means
9069 that all calls are made according to the platform ABI.
9071 - passing/receiving vtypes.
9073 Vtypes passed/received in registers are handled by the front end by using
9074 a signature with scalar arguments, and loading the parts of the vtype into those
9075 arguments.
9077 Vtypes passed on the stack are handled using the 'byval' attribute.
9079 - ldaddr.
9081 Supported though alloca, we need to emit the load/store code.
9083 - types.
9085 The mono JIT uses pointer sized iregs/double fregs, while LLVM uses precisely
9086 typed registers, so we have to keep track of the precise LLVM type of each vreg.
9087 This is made easier because the IR is already in SSA form.
9088 An additional problem is that our IR is not consistent with types, i.e. i32/ia64
9089 types are frequently used incorrectly.
9093 AOT SUPPORT:
9094 Emit LLVM bytecode into a .bc file, compile it using llc into a .s file, then link
9095 it with the file containing the methods emitted by the JIT and the AOT data
9096 structures.
9099 /* FIXME: Normalize some aspects of the mono IR to allow easier translation, like:
9100 * - each bblock should end with a branch
9101 * - setting the return value, making cfg->ret non-volatile
9102 * - avoid some transformations in the JIT which make it harder for us to generate
9103 * code.
9104 * - use pointer types to help optimizations.