[llvm] Fix passing vtypes received by value as arguments, they need to be copied...
[mono-project.git] / mono / mini / mini-llvm.c
blobb8af03d91d0aa0328d015fc52cbd6bdd23a2774e
1 /**
2 * \file
3 * llvm "Backend" for the mono JIT
5 * Copyright 2009-2011 Novell Inc (http://www.novell.com)
6 * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
7 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
8 */
10 #include "config.h"
12 #include <mono/metadata/debug-helpers.h>
13 #include <mono/metadata/debug-internals.h>
14 #include <mono/metadata/mempool-internals.h>
15 #include <mono/metadata/environment.h>
16 #include <mono/metadata/object-internals.h>
17 #include <mono/metadata/abi-details.h>
18 #include <mono/utils/mono-tls.h>
19 #include <mono/utils/mono-dl.h>
20 #include <mono/utils/mono-time.h>
21 #include <mono/utils/freebsd-dwarf.h>
23 #ifndef __STDC_LIMIT_MACROS
24 #define __STDC_LIMIT_MACROS
25 #endif
26 #ifndef __STDC_CONSTANT_MACROS
27 #define __STDC_CONSTANT_MACROS
28 #endif
30 #include "llvm-c/BitWriter.h"
31 #include "llvm-c/Analysis.h"
33 #include "mini-llvm-cpp.h"
34 #include "llvm-jit.h"
35 #include "aot-compiler.h"
36 #include "mini-llvm.h"
37 #include "mini-runtime.h"
38 #include <mono/utils/mono-math.h>
40 #ifndef DISABLE_JIT
42 #if defined(__MINGW32__) || defined(_MSC_VER)
44 #include <stddef.h>
45 extern void *memset(void *, int, size_t);
46 void bzero (void *to, size_t count) { memset (to, 0, count); }
48 #endif
50 #if LLVM_API_VERSION < 4
51 #error "The version of the mono llvm repository is too old."
52 #endif
55 * Information associated by mono with LLVM modules.
57 typedef struct {
58 LLVMModuleRef lmodule;
59 LLVMValueRef throw_icall, rethrow, match_exc, throw_corlib_exception, resume_eh;
60 GHashTable *llvm_types;
61 LLVMValueRef got_var;
62 const char *got_symbol;
63 const char *get_method_symbol;
64 const char *get_unbox_tramp_symbol;
65 GHashTable *plt_entries;
66 GHashTable *plt_entries_ji;
67 GHashTable *method_to_lmethod;
68 GHashTable *direct_callables;
69 char **bb_names;
70 int bb_names_len;
71 GPtrArray *used;
72 LLVMTypeRef ptr_type;
73 GPtrArray *subprogram_mds;
74 MonoEERef *mono_ee;
75 LLVMExecutionEngineRef ee;
76 gboolean external_symbols;
77 gboolean emit_dwarf;
78 int max_got_offset;
79 LLVMValueRef personality;
81 /* For AOT */
82 MonoAssembly *assembly;
83 char *global_prefix;
84 MonoAotFileInfo aot_info;
85 const char *jit_got_symbol;
86 const char *eh_frame_symbol;
87 LLVMValueRef get_method, get_unbox_tramp;
88 LLVMValueRef init_method, init_method_gshared_mrgctx, init_method_gshared_this, init_method_gshared_vtable;
89 LLVMValueRef code_start, code_end;
90 LLVMValueRef inited_var;
91 int max_inited_idx, max_method_idx;
92 gboolean has_jitted_code;
93 gboolean static_link;
94 gboolean llvm_only;
95 GHashTable *idx_to_lmethod;
96 GHashTable *idx_to_unbox_tramp;
97 /* Maps a MonoMethod to LLVM instructions representing it */
98 GHashTable *method_to_callers;
99 LLVMContextRef context;
100 LLVMValueRef sentinel_exception;
101 void *di_builder, *cu;
102 GHashTable *objc_selector_to_var;
103 } MonoLLVMModule;
106 * Information associated by the backend with mono basic blocks.
108 typedef struct {
109 LLVMBasicBlockRef bblock, end_bblock;
110 LLVMValueRef finally_ind;
111 gboolean added, invoke_target;
113 * If this bblock is the start of a finally clause, this is a list of bblocks it
114 * needs to branch to in ENDFINALLY.
116 GSList *call_handler_return_bbs;
118 * If this bblock is the start of a finally clause, this is the bblock that
119 * CALL_HANDLER needs to branch to.
121 LLVMBasicBlockRef call_handler_target_bb;
122 /* The list of switch statements generated by ENDFINALLY instructions */
123 GSList *endfinally_switch_ins_list;
124 GSList *phi_nodes;
125 } BBInfo;
128 * Structure containing emit state
130 typedef struct {
131 MonoMemPool *mempool;
133 /* Maps method names to the corresponding LLVMValueRef */
134 GHashTable *emitted_method_decls;
136 MonoCompile *cfg;
137 LLVMValueRef lmethod;
138 MonoLLVMModule *module;
139 LLVMModuleRef lmodule;
140 BBInfo *bblocks;
141 int sindex, default_index, ex_index;
142 LLVMBuilderRef builder;
143 LLVMValueRef *values, *addresses;
144 MonoType **vreg_cli_types;
145 LLVMCallInfo *linfo;
146 MonoMethodSignature *sig;
147 GSList *builders;
148 GHashTable *region_to_handler;
149 GHashTable *clause_to_handler;
150 LLVMBuilderRef alloca_builder;
151 LLVMValueRef last_alloca;
152 LLVMValueRef rgctx_arg;
153 LLVMValueRef this_arg;
154 LLVMTypeRef *vreg_types;
155 gboolean *is_vphi;
156 LLVMTypeRef method_type;
157 LLVMBasicBlockRef init_bb, inited_bb;
158 gboolean *is_dead;
159 gboolean *unreachable;
160 gboolean llvm_only;
161 gboolean has_got_access;
162 gboolean is_linkonce;
163 gboolean emit_dummy_arg;
164 int this_arg_pindex, rgctx_arg_pindex;
165 LLVMValueRef imt_rgctx_loc;
166 GHashTable *llvm_types;
167 LLVMValueRef dbg_md;
168 MonoDebugMethodInfo *minfo;
169 /* For every clause, the clauses it is nested in */
170 GSList **nested_in;
171 LLVMValueRef ex_var;
172 GHashTable *exc_meta;
173 GHashTable *method_to_callers;
174 GPtrArray *phi_values;
175 GPtrArray *bblock_list;
176 char *method_name;
177 GHashTable *jit_callees;
178 LLVMValueRef long_bb_break_var;
179 } EmitContext;
181 typedef struct {
182 MonoBasicBlock *bb;
183 MonoInst *phi;
184 MonoBasicBlock *in_bb;
185 int sreg;
186 } PhiNode;
189 * Instruction metadata
190 * This is the same as ins_info, but LREG != IREG.
192 #ifdef MINI_OP
193 #undef MINI_OP
194 #endif
195 #ifdef MINI_OP3
196 #undef MINI_OP3
197 #endif
198 #define MINI_OP(a,b,dest,src1,src2) dest, src1, src2, ' ',
199 #define MINI_OP3(a,b,dest,src1,src2,src3) dest, src1, src2, src3,
200 #define NONE ' '
201 #define IREG 'i'
202 #define FREG 'f'
203 #define VREG 'v'
204 #define XREG 'x'
205 #define LREG 'l'
206 /* keep in sync with the enum in mini.h */
207 const char
208 mini_llvm_ins_info[] = {
209 #include "mini-ops.h"
211 #undef MINI_OP
212 #undef MINI_OP3
214 #if TARGET_SIZEOF_VOID_P == 4
215 #define GET_LONG_IMM(ins) ((ins)->inst_l)
216 #else
217 #define GET_LONG_IMM(ins) ((ins)->inst_imm)
218 #endif
220 #define LLVM_INS_INFO(opcode) (&mini_llvm_ins_info [((opcode) - OP_START - 1) * 4])
222 #if 0
223 #define TRACE_FAILURE(msg) do { printf ("%s\n", msg); } while (0)
224 #else
225 #define TRACE_FAILURE(msg)
226 #endif
228 #ifdef TARGET_X86
229 #define IS_TARGET_X86 1
230 #else
231 #define IS_TARGET_X86 0
232 #endif
234 #ifdef TARGET_AMD64
235 #define IS_TARGET_AMD64 1
236 #else
237 #define IS_TARGET_AMD64 0
238 #endif
240 #define ctx_ok(ctx) (!(ctx)->cfg->disable_llvm)
242 static LLVMIntPredicate cond_to_llvm_cond [] = {
243 LLVMIntEQ,
244 LLVMIntNE,
245 LLVMIntSLE,
246 LLVMIntSGE,
247 LLVMIntSLT,
248 LLVMIntSGT,
249 LLVMIntULE,
250 LLVMIntUGE,
251 LLVMIntULT,
252 LLVMIntUGT,
255 static LLVMRealPredicate fpcond_to_llvm_cond [] = {
256 LLVMRealOEQ,
257 LLVMRealUNE,
258 LLVMRealOLE,
259 LLVMRealOGE,
260 LLVMRealOLT,
261 LLVMRealOGT,
262 LLVMRealULE,
263 LLVMRealUGE,
264 LLVMRealULT,
265 LLVMRealUGT,
268 static MonoNativeTlsKey current_cfg_tls_id;
270 static MonoLLVMModule aot_module;
272 static GHashTable *intrins_id_to_name;
273 static GHashTable *intrins_name_to_id;
275 static void init_jit_module (MonoDomain *domain);
277 static void emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil_code);
278 static void emit_default_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder);
279 static LLVMValueRef emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, const char *name);
280 static void emit_dbg_info (MonoLLVMModule *module, const char *filename, const char *cu_name);
281 static void emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *exc_type, LLVMValueRef cmp);
282 static LLVMValueRef get_intrinsic (EmitContext *ctx, const char *name);
283 static void decode_llvm_eh_info (EmitContext *ctx, gpointer eh_frame);
285 static inline void
286 set_failure (EmitContext *ctx, const char *message)
288 TRACE_FAILURE (reason);
289 ctx->cfg->exception_message = g_strdup (message);
290 ctx->cfg->disable_llvm = TRUE;
294 * IntPtrType:
296 * The LLVM type with width == sizeof (gpointer)
298 static LLVMTypeRef
299 IntPtrType (void)
301 return sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type ();
304 static LLVMTypeRef
305 ObjRefType (void)
307 return sizeof (gpointer) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
310 static LLVMTypeRef
311 ThisType (void)
313 return sizeof (gpointer) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
317 * get_vtype_size:
319 * Return the size of the LLVM representation of the vtype T.
321 static guint32
322 get_vtype_size (MonoType *t)
324 int size;
326 size = mono_class_value_size (mono_class_from_mono_type_internal (t), NULL);
328 /* LLVMArgAsIArgs depends on this since it stores whole words */
329 while (size < 2 * sizeof (gpointer) && mono_is_power_of_two (size) == -1)
330 size ++;
332 return size;
336 * simd_class_to_llvm_type:
338 * Return the LLVM type corresponding to the Mono.SIMD class KLASS
340 static LLVMTypeRef
341 simd_class_to_llvm_type (EmitContext *ctx, MonoClass *klass)
343 const char *klass_name = m_class_get_name (klass);
344 if (!strcmp (klass_name, "Vector2d")) {
345 return LLVMVectorType (LLVMDoubleType (), 2);
346 } else if (!strcmp (klass_name, "Vector2l")) {
347 return LLVMVectorType (LLVMInt64Type (), 2);
348 } else if (!strcmp (klass_name, "Vector2ul")) {
349 return LLVMVectorType (LLVMInt64Type (), 2);
350 } else if (!strcmp (klass_name, "Vector4i")) {
351 return LLVMVectorType (LLVMInt32Type (), 4);
352 } else if (!strcmp (klass_name, "Vector4ui")) {
353 return LLVMVectorType (LLVMInt32Type (), 4);
354 } else if (!strcmp (klass_name, "Vector4f")) {
355 return LLVMVectorType (LLVMFloatType (), 4);
356 } else if (!strcmp (klass_name, "Vector8s")) {
357 return LLVMVectorType (LLVMInt16Type (), 8);
358 } else if (!strcmp (klass_name, "Vector8us")) {
359 return LLVMVectorType (LLVMInt16Type (), 8);
360 } else if (!strcmp (klass_name, "Vector16sb")) {
361 return LLVMVectorType (LLVMInt8Type (), 16);
362 } else if (!strcmp (klass_name, "Vector16b")) {
363 return LLVMVectorType (LLVMInt8Type (), 16);
364 } else if (!strcmp (klass_name, "Vector2")) {
365 /* System.Numerics */
366 return LLVMVectorType (LLVMFloatType (), 4);
367 } else if (!strcmp (klass_name, "Vector3")) {
368 return LLVMVectorType (LLVMFloatType (), 4);
369 } else if (!strcmp (klass_name, "Vector4")) {
370 return LLVMVectorType (LLVMFloatType (), 4);
371 } else if (!strcmp (klass_name, "Vector`1")) {
372 MonoType *etype = mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
373 switch (etype->type) {
374 case MONO_TYPE_I1:
375 case MONO_TYPE_U1:
376 return LLVMVectorType (LLVMInt8Type (), 16);
377 case MONO_TYPE_I2:
378 case MONO_TYPE_U2:
379 return LLVMVectorType (LLVMInt16Type (), 8);
380 case MONO_TYPE_I4:
381 case MONO_TYPE_U4:
382 return LLVMVectorType (LLVMInt32Type (), 4);
383 case MONO_TYPE_I8:
384 case MONO_TYPE_U8:
385 return LLVMVectorType (LLVMInt64Type (), 2);
386 case MONO_TYPE_R4:
387 return LLVMVectorType (LLVMFloatType (), 4);
388 case MONO_TYPE_R8:
389 return LLVMVectorType (LLVMDoubleType (), 2);
390 default:
391 g_assert_not_reached ();
392 return NULL;
394 } else {
395 printf ("%s\n", klass_name);
396 NOT_IMPLEMENTED;
397 return NULL;
401 /* Return the 128 bit SIMD type corresponding to the mono type TYPE */
402 static inline G_GNUC_UNUSED LLVMTypeRef
403 type_to_simd_type (int type)
405 switch (type) {
406 case MONO_TYPE_I1:
407 return LLVMVectorType (LLVMInt8Type (), 16);
408 case MONO_TYPE_I2:
409 return LLVMVectorType (LLVMInt16Type (), 8);
410 case MONO_TYPE_I4:
411 return LLVMVectorType (LLVMInt32Type (), 4);
412 case MONO_TYPE_I8:
413 return LLVMVectorType (LLVMInt64Type (), 2);
414 case MONO_TYPE_R8:
415 return LLVMVectorType (LLVMDoubleType (), 2);
416 case MONO_TYPE_R4:
417 return LLVMVectorType (LLVMFloatType (), 4);
418 default:
419 g_assert_not_reached ();
420 return NULL;
424 static LLVMTypeRef
425 create_llvm_type_for_type (MonoLLVMModule *module, MonoClass *klass)
427 int i, size, nfields, esize;
428 LLVMTypeRef *eltypes;
429 char *name;
430 MonoType *t;
431 LLVMTypeRef ltype;
433 t = m_class_get_byval_arg (klass);
435 if (mini_type_is_hfa (t, &nfields, &esize)) {
437 * This is needed on arm64 where HFAs are returned in
438 * registers.
440 /* SIMD types have size 16 in mono_class_value_size () */
441 if (m_class_is_simd_type (klass))
442 nfields = 16/ esize;
443 size = nfields;
444 eltypes = g_new (LLVMTypeRef, size);
445 for (i = 0; i < size; ++i)
446 eltypes [i] = esize == 4 ? LLVMFloatType () : LLVMDoubleType ();
447 } else {
448 size = get_vtype_size (t);
450 eltypes = g_new (LLVMTypeRef, size);
451 for (i = 0; i < size; ++i)
452 eltypes [i] = LLVMInt8Type ();
455 name = mono_type_full_name (m_class_get_byval_arg (klass));
456 ltype = LLVMStructCreateNamed (module->context, name);
457 LLVMStructSetBody (ltype, eltypes, size, FALSE);
458 g_free (eltypes);
459 g_free (name);
461 return ltype;
465 * type_to_llvm_type:
467 * Return the LLVM type corresponding to T.
469 static LLVMTypeRef
470 type_to_llvm_type (EmitContext *ctx, MonoType *t)
472 if (t->byref)
473 return ThisType ();
475 t = mini_get_underlying_type (t);
477 switch (t->type) {
478 case MONO_TYPE_VOID:
479 return LLVMVoidType ();
480 case MONO_TYPE_I1:
481 return LLVMInt8Type ();
482 case MONO_TYPE_I2:
483 return LLVMInt16Type ();
484 case MONO_TYPE_I4:
485 return LLVMInt32Type ();
486 case MONO_TYPE_U1:
487 return LLVMInt8Type ();
488 case MONO_TYPE_U2:
489 return LLVMInt16Type ();
490 case MONO_TYPE_U4:
491 return LLVMInt32Type ();
492 case MONO_TYPE_I8:
493 case MONO_TYPE_U8:
494 return LLVMInt64Type ();
495 case MONO_TYPE_R4:
496 return LLVMFloatType ();
497 case MONO_TYPE_R8:
498 return LLVMDoubleType ();
499 case MONO_TYPE_I:
500 case MONO_TYPE_U:
501 return IntPtrType ();
502 case MONO_TYPE_OBJECT:
503 case MONO_TYPE_PTR:
504 return ObjRefType ();
505 case MONO_TYPE_VAR:
506 case MONO_TYPE_MVAR:
507 /* Because of generic sharing */
508 return ObjRefType ();
509 case MONO_TYPE_GENERICINST:
510 if (!mono_type_generic_inst_is_valuetype (t))
511 return ObjRefType ();
512 /* Fall through */
513 case MONO_TYPE_VALUETYPE:
514 case MONO_TYPE_TYPEDBYREF: {
515 MonoClass *klass;
516 LLVMTypeRef ltype;
518 klass = mono_class_from_mono_type_internal (t);
520 if (MONO_CLASS_IS_SIMD (ctx->cfg, klass))
521 return simd_class_to_llvm_type (ctx, klass);
523 if (m_class_is_enumtype (klass))
524 return type_to_llvm_type (ctx, mono_class_enum_basetype_internal (klass));
526 ltype = (LLVMTypeRef)g_hash_table_lookup (ctx->module->llvm_types, klass);
527 if (!ltype) {
528 ltype = create_llvm_type_for_type (ctx->module, klass);
529 g_hash_table_insert (ctx->module->llvm_types, klass, ltype);
531 return ltype;
534 default:
535 printf ("X: %d\n", t->type);
536 ctx->cfg->exception_message = g_strdup_printf ("type %s", mono_type_full_name (t));
537 ctx->cfg->disable_llvm = TRUE;
538 return NULL;
543 * type_is_unsigned:
545 * Return whenever T is an unsigned int type.
547 static gboolean
548 type_is_unsigned (EmitContext *ctx, MonoType *t)
550 t = mini_get_underlying_type (t);
551 if (t->byref)
552 return FALSE;
553 switch (t->type) {
554 case MONO_TYPE_U1:
555 case MONO_TYPE_U2:
556 case MONO_TYPE_CHAR:
557 case MONO_TYPE_U4:
558 case MONO_TYPE_U8:
559 return TRUE;
560 default:
561 return FALSE;
566 * type_to_llvm_arg_type:
568 * Same as type_to_llvm_type, but treat i8/i16 as i32.
570 static LLVMTypeRef
571 type_to_llvm_arg_type (EmitContext *ctx, MonoType *t)
573 LLVMTypeRef ptype = type_to_llvm_type (ctx, t);
575 if (ctx->cfg->llvm_only)
576 return ptype;
579 * This works on all abis except arm64/ios which passes multiple
580 * arguments in one stack slot.
582 #ifndef TARGET_ARM64
583 if (ptype == LLVMInt8Type () || ptype == LLVMInt16Type ()) {
585 * LLVM generates code which only sets the lower bits, while JITted
586 * code expects all the bits to be set.
588 ptype = LLVMInt32Type ();
590 #endif
592 return ptype;
596 * llvm_type_to_stack_type:
598 * Return the LLVM type which needs to be used when a value of type TYPE is pushed
599 * on the IL stack.
601 static G_GNUC_UNUSED LLVMTypeRef
602 llvm_type_to_stack_type (MonoCompile *cfg, LLVMTypeRef type)
604 if (type == NULL)
605 return NULL;
606 if (type == LLVMInt8Type ())
607 return LLVMInt32Type ();
608 else if (type == LLVMInt16Type ())
609 return LLVMInt32Type ();
610 else if (!cfg->r4fp && type == LLVMFloatType ())
611 return LLVMDoubleType ();
612 else
613 return type;
617 * regtype_to_llvm_type:
619 * Return the LLVM type corresponding to the regtype C used in instruction
620 * descriptions.
622 static LLVMTypeRef
623 regtype_to_llvm_type (char c)
625 switch (c) {
626 case 'i':
627 return LLVMInt32Type ();
628 case 'l':
629 return LLVMInt64Type ();
630 case 'f':
631 return LLVMDoubleType ();
632 default:
633 return NULL;
638 * op_to_llvm_type:
640 * Return the LLVM type corresponding to the unary/binary opcode OPCODE.
642 static LLVMTypeRef
643 op_to_llvm_type (int opcode)
645 switch (opcode) {
646 case OP_ICONV_TO_I1:
647 case OP_LCONV_TO_I1:
648 return LLVMInt8Type ();
649 case OP_ICONV_TO_U1:
650 case OP_LCONV_TO_U1:
651 return LLVMInt8Type ();
652 case OP_ICONV_TO_I2:
653 case OP_LCONV_TO_I2:
654 return LLVMInt16Type ();
655 case OP_ICONV_TO_U2:
656 case OP_LCONV_TO_U2:
657 return LLVMInt16Type ();
658 case OP_ICONV_TO_I4:
659 case OP_LCONV_TO_I4:
660 return LLVMInt32Type ();
661 case OP_ICONV_TO_U4:
662 case OP_LCONV_TO_U4:
663 return LLVMInt32Type ();
664 case OP_ICONV_TO_I8:
665 return LLVMInt64Type ();
666 case OP_ICONV_TO_R4:
667 return LLVMFloatType ();
668 case OP_ICONV_TO_R8:
669 return LLVMDoubleType ();
670 case OP_ICONV_TO_U8:
671 return LLVMInt64Type ();
672 case OP_FCONV_TO_I4:
673 return LLVMInt32Type ();
674 case OP_FCONV_TO_I8:
675 return LLVMInt64Type ();
676 case OP_FCONV_TO_I1:
677 case OP_FCONV_TO_U1:
678 case OP_RCONV_TO_I1:
679 case OP_RCONV_TO_U1:
680 return LLVMInt8Type ();
681 case OP_FCONV_TO_I2:
682 case OP_FCONV_TO_U2:
683 case OP_RCONV_TO_I2:
684 case OP_RCONV_TO_U2:
685 return LLVMInt16Type ();
686 case OP_RCONV_TO_U4:
687 return LLVMInt32Type ();
688 case OP_FCONV_TO_I:
689 case OP_FCONV_TO_U:
690 return sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type ();
691 case OP_IADD_OVF:
692 case OP_IADD_OVF_UN:
693 case OP_ISUB_OVF:
694 case OP_ISUB_OVF_UN:
695 case OP_IMUL_OVF:
696 case OP_IMUL_OVF_UN:
697 return LLVMInt32Type ();
698 case OP_LADD_OVF:
699 case OP_LADD_OVF_UN:
700 case OP_LSUB_OVF:
701 case OP_LSUB_OVF_UN:
702 case OP_LMUL_OVF:
703 case OP_LMUL_OVF_UN:
704 return LLVMInt64Type ();
705 default:
706 printf ("%s\n", mono_inst_name (opcode));
707 g_assert_not_reached ();
708 return NULL;
712 #define CLAUSE_START(clause) ((clause)->try_offset)
713 #define CLAUSE_END(clause) (((clause))->try_offset + ((clause))->try_len)
716 * load_store_to_llvm_type:
718 * Return the size/sign/zero extension corresponding to the load/store opcode
719 * OPCODE.
721 static LLVMTypeRef
722 load_store_to_llvm_type (int opcode, int *size, gboolean *sext, gboolean *zext)
724 *sext = FALSE;
725 *zext = FALSE;
727 switch (opcode) {
728 case OP_LOADI1_MEMBASE:
729 case OP_STOREI1_MEMBASE_REG:
730 case OP_STOREI1_MEMBASE_IMM:
731 case OP_ATOMIC_LOAD_I1:
732 case OP_ATOMIC_STORE_I1:
733 *size = 1;
734 *sext = TRUE;
735 return LLVMInt8Type ();
736 case OP_LOADU1_MEMBASE:
737 case OP_LOADU1_MEM:
738 case OP_ATOMIC_LOAD_U1:
739 case OP_ATOMIC_STORE_U1:
740 *size = 1;
741 *zext = TRUE;
742 return LLVMInt8Type ();
743 case OP_LOADI2_MEMBASE:
744 case OP_STOREI2_MEMBASE_REG:
745 case OP_STOREI2_MEMBASE_IMM:
746 case OP_ATOMIC_LOAD_I2:
747 case OP_ATOMIC_STORE_I2:
748 *size = 2;
749 *sext = TRUE;
750 return LLVMInt16Type ();
751 case OP_LOADU2_MEMBASE:
752 case OP_LOADU2_MEM:
753 case OP_ATOMIC_LOAD_U2:
754 case OP_ATOMIC_STORE_U2:
755 *size = 2;
756 *zext = TRUE;
757 return LLVMInt16Type ();
758 case OP_LOADI4_MEMBASE:
759 case OP_LOADU4_MEMBASE:
760 case OP_LOADI4_MEM:
761 case OP_LOADU4_MEM:
762 case OP_STOREI4_MEMBASE_REG:
763 case OP_STOREI4_MEMBASE_IMM:
764 case OP_ATOMIC_LOAD_I4:
765 case OP_ATOMIC_STORE_I4:
766 case OP_ATOMIC_LOAD_U4:
767 case OP_ATOMIC_STORE_U4:
768 *size = 4;
769 return LLVMInt32Type ();
770 case OP_LOADI8_MEMBASE:
771 case OP_LOADI8_MEM:
772 case OP_STOREI8_MEMBASE_REG:
773 case OP_STOREI8_MEMBASE_IMM:
774 case OP_ATOMIC_LOAD_I8:
775 case OP_ATOMIC_STORE_I8:
776 case OP_ATOMIC_LOAD_U8:
777 case OP_ATOMIC_STORE_U8:
778 *size = 8;
779 return LLVMInt64Type ();
780 case OP_LOADR4_MEMBASE:
781 case OP_STORER4_MEMBASE_REG:
782 case OP_ATOMIC_LOAD_R4:
783 case OP_ATOMIC_STORE_R4:
784 *size = 4;
785 return LLVMFloatType ();
786 case OP_LOADR8_MEMBASE:
787 case OP_STORER8_MEMBASE_REG:
788 case OP_ATOMIC_LOAD_R8:
789 case OP_ATOMIC_STORE_R8:
790 *size = 8;
791 return LLVMDoubleType ();
792 case OP_LOAD_MEMBASE:
793 case OP_LOAD_MEM:
794 case OP_STORE_MEMBASE_REG:
795 case OP_STORE_MEMBASE_IMM:
796 *size = sizeof (gpointer);
797 return IntPtrType ();
798 default:
799 g_assert_not_reached ();
800 return NULL;
805 * ovf_op_to_intrins:
807 * Return the LLVM intrinsics corresponding to the overflow opcode OPCODE.
809 static const char*
810 ovf_op_to_intrins (int opcode)
812 switch (opcode) {
813 case OP_IADD_OVF:
814 return "llvm.sadd.with.overflow.i32";
815 case OP_IADD_OVF_UN:
816 return "llvm.uadd.with.overflow.i32";
817 case OP_ISUB_OVF:
818 return "llvm.ssub.with.overflow.i32";
819 case OP_ISUB_OVF_UN:
820 return "llvm.usub.with.overflow.i32";
821 case OP_IMUL_OVF:
822 return "llvm.smul.with.overflow.i32";
823 case OP_IMUL_OVF_UN:
824 return "llvm.umul.with.overflow.i32";
825 case OP_LADD_OVF:
826 return "llvm.sadd.with.overflow.i64";
827 case OP_LADD_OVF_UN:
828 return "llvm.uadd.with.overflow.i64";
829 case OP_LSUB_OVF:
830 return "llvm.ssub.with.overflow.i64";
831 case OP_LSUB_OVF_UN:
832 return "llvm.usub.with.overflow.i64";
833 case OP_LMUL_OVF:
834 return "llvm.smul.with.overflow.i64";
835 case OP_LMUL_OVF_UN:
836 return "llvm.umul.with.overflow.i64";
837 default:
838 g_assert_not_reached ();
839 return NULL;
843 static const char*
844 simd_op_to_intrins (int opcode)
846 switch (opcode) {
847 #if defined(TARGET_X86) || defined(TARGET_AMD64)
848 case OP_MINPD:
849 return "llvm.x86.sse2.min.pd";
850 case OP_MINPS:
851 return "llvm.x86.sse.min.ps";
852 case OP_MAXPD:
853 return "llvm.x86.sse2.max.pd";
854 case OP_MAXPS:
855 return "llvm.x86.sse.max.ps";
856 case OP_HADDPD:
857 return "llvm.x86.sse3.hadd.pd";
858 case OP_HADDPS:
859 return "llvm.x86.sse3.hadd.ps";
860 case OP_HSUBPD:
861 return "llvm.x86.sse3.hsub.pd";
862 case OP_HSUBPS:
863 return "llvm.x86.sse3.hsub.ps";
864 case OP_ADDSUBPS:
865 return "llvm.x86.sse3.addsub.ps";
866 case OP_ADDSUBPD:
867 return "llvm.x86.sse3.addsub.pd";
868 case OP_EXTRACT_MASK:
869 return "llvm.x86.sse2.pmovmskb.128";
870 case OP_PSHRW:
871 case OP_PSHRW_REG:
872 return "llvm.x86.sse2.psrli.w";
873 case OP_PSHRD:
874 case OP_PSHRD_REG:
875 return "llvm.x86.sse2.psrli.d";
876 case OP_PSHRQ:
877 case OP_PSHRQ_REG:
878 return "llvm.x86.sse2.psrli.q";
879 case OP_PSHLW:
880 case OP_PSHLW_REG:
881 return "llvm.x86.sse2.pslli.w";
882 case OP_PSHLD:
883 case OP_PSHLD_REG:
884 return "llvm.x86.sse2.pslli.d";
885 case OP_PSHLQ:
886 case OP_PSHLQ_REG:
887 return "llvm.x86.sse2.pslli.q";
888 case OP_PSARW:
889 case OP_PSARW_REG:
890 return "llvm.x86.sse2.psrai.w";
891 case OP_PSARD:
892 case OP_PSARD_REG:
893 return "llvm.x86.sse2.psrai.d";
894 case OP_PADDB_SAT:
895 return "llvm.x86.sse2.padds.b";
896 case OP_PADDW_SAT:
897 return "llvm.x86.sse2.padds.w";
898 case OP_PSUBB_SAT:
899 return "llvm.x86.sse2.psubs.b";
900 case OP_PSUBW_SAT:
901 return "llvm.x86.sse2.psubs.w";
902 case OP_PADDB_SAT_UN:
903 return "llvm.x86.sse2.paddus.b";
904 case OP_PADDW_SAT_UN:
905 return "llvm.x86.sse2.paddus.w";
906 case OP_PSUBB_SAT_UN:
907 return "llvm.x86.sse2.psubus.b";
908 case OP_PSUBW_SAT_UN:
909 return "llvm.x86.sse2.psubus.w";
910 case OP_PAVGB_UN:
911 return "llvm.x86.sse2.pavg.b";
912 case OP_PAVGW_UN:
913 return "llvm.x86.sse2.pavg.w";
914 case OP_SQRTPS:
915 return "llvm.x86.sse.sqrt.ps";
916 case OP_SQRTPD:
917 return "llvm.x86.sse2.sqrt.pd";
918 case OP_RSQRTPS:
919 return "llvm.x86.sse.rsqrt.ps";
920 case OP_RCPPS:
921 return "llvm.x86.sse.rcp.ps";
922 case OP_CVTDQ2PD:
923 return "llvm.x86.sse2.cvtdq2pd";
924 case OP_CVTDQ2PS:
925 return "llvm.x86.sse2.cvtdq2ps";
926 case OP_CVTPD2DQ:
927 return "llvm.x86.sse2.cvtpd2dq";
928 case OP_CVTPS2DQ:
929 return "llvm.x86.sse2.cvtps2dq";
930 case OP_CVTPD2PS:
931 return "llvm.x86.sse2.cvtpd2ps";
932 case OP_CVTPS2PD:
933 return "llvm.x86.sse2.cvtps2pd";
934 case OP_CVTTPD2DQ:
935 return "llvm.x86.sse2.cvttpd2dq";
936 case OP_CVTTPS2DQ:
937 return "llvm.x86.sse2.cvttps2dq";
938 case OP_PACKW:
939 return "llvm.x86.sse2.packsswb.128";
940 case OP_PACKD:
941 return "llvm.x86.sse2.packssdw.128";
942 case OP_PACKW_UN:
943 return "llvm.x86.sse2.packuswb.128";
944 case OP_PACKD_UN:
945 return "llvm.x86.sse41.packusdw";
946 case OP_PMULW_HIGH:
947 return "llvm.x86.sse2.pmulh.w";
948 case OP_PMULW_HIGH_UN:
949 return "llvm.x86.sse2.pmulhu.w";
950 case OP_DPPS:
951 return "llvm.x86.sse41.dpps";
952 #endif
953 default:
954 g_assert_not_reached ();
955 return NULL;
959 static LLVMTypeRef
960 simd_op_to_llvm_type (int opcode)
962 #if defined(TARGET_X86) || defined(TARGET_AMD64)
963 switch (opcode) {
964 case OP_EXTRACT_R8:
965 case OP_EXPAND_R8:
966 return type_to_simd_type (MONO_TYPE_R8);
967 case OP_EXTRACT_I8:
968 case OP_EXPAND_I8:
969 return type_to_simd_type (MONO_TYPE_I8);
970 case OP_EXTRACT_I4:
971 case OP_EXPAND_I4:
972 return type_to_simd_type (MONO_TYPE_I4);
973 case OP_EXTRACT_I2:
974 case OP_EXTRACT_U2:
975 case OP_EXTRACTX_U2:
976 case OP_EXPAND_I2:
977 return type_to_simd_type (MONO_TYPE_I2);
978 case OP_EXTRACT_I1:
979 case OP_EXTRACT_U1:
980 case OP_EXPAND_I1:
981 return type_to_simd_type (MONO_TYPE_I1);
982 case OP_EXPAND_R4:
983 return type_to_simd_type (MONO_TYPE_R4);
984 case OP_CVTDQ2PD:
985 case OP_CVTDQ2PS:
986 return type_to_simd_type (MONO_TYPE_I4);
987 case OP_CVTPD2DQ:
988 case OP_CVTPD2PS:
989 case OP_CVTTPD2DQ:
990 return type_to_simd_type (MONO_TYPE_R8);
991 case OP_CVTPS2DQ:
992 case OP_CVTPS2PD:
993 case OP_CVTTPS2DQ:
994 return type_to_simd_type (MONO_TYPE_R4);
995 case OP_EXTRACT_MASK:
996 return type_to_simd_type (MONO_TYPE_I1);
997 case OP_SQRTPS:
998 case OP_RSQRTPS:
999 case OP_RCPPS:
1000 case OP_DUPPS_LOW:
1001 case OP_DUPPS_HIGH:
1002 return type_to_simd_type (MONO_TYPE_R4);
1003 case OP_SQRTPD:
1004 case OP_DUPPD:
1005 return type_to_simd_type (MONO_TYPE_R8);
1006 default:
1007 g_assert_not_reached ();
1008 return NULL;
1010 #else
1011 return NULL;
1012 #endif
1015 static void
1016 set_preserveall_cc (LLVMValueRef func)
1019 * xcode10 doesn't seem to support preserveall on watchos, it fails with:
1020 * fatal error: error in backend: Unsupported calling convention
1022 #ifndef TARGET_WATCHOS
1023 mono_llvm_set_preserveall_cc (func);
1024 #endif
1027 static void
1028 set_call_preserveall_cc (LLVMValueRef func)
1030 #ifndef TARGET_WATCHOS
1031 mono_llvm_set_call_preserveall_cc (func);
1032 #endif
1036 * get_bb:
1038 * Return the LLVM basic block corresponding to BB.
1040 static LLVMBasicBlockRef
1041 get_bb (EmitContext *ctx, MonoBasicBlock *bb)
1043 char bb_name_buf [128];
1044 char *bb_name;
1046 if (ctx->bblocks [bb->block_num].bblock == NULL) {
1047 if (bb->flags & BB_EXCEPTION_HANDLER) {
1048 int clause_index = (mono_get_block_region_notry (ctx->cfg, bb->region) >> 8) - 1;
1049 sprintf (bb_name_buf, "EH_CLAUSE%d_BB%d", clause_index, bb->block_num);
1050 bb_name = bb_name_buf;
1051 } else if (bb->block_num < 256) {
1052 if (!ctx->module->bb_names) {
1053 ctx->module->bb_names_len = 256;
1054 ctx->module->bb_names = g_new0 (char*, ctx->module->bb_names_len);
1056 if (!ctx->module->bb_names [bb->block_num]) {
1057 char *n;
1059 n = g_strdup_printf ("BB%d", bb->block_num);
1060 mono_memory_barrier ();
1061 ctx->module->bb_names [bb->block_num] = n;
1063 bb_name = ctx->module->bb_names [bb->block_num];
1064 } else {
1065 sprintf (bb_name_buf, "BB%d", bb->block_num);
1066 bb_name = bb_name_buf;
1069 ctx->bblocks [bb->block_num].bblock = LLVMAppendBasicBlock (ctx->lmethod, bb_name);
1070 ctx->bblocks [bb->block_num].end_bblock = ctx->bblocks [bb->block_num].bblock;
1073 return ctx->bblocks [bb->block_num].bblock;
1077 * get_end_bb:
1079 * Return the last LLVM bblock corresponding to BB.
1080 * This might not be equal to the bb returned by get_bb () since we need to generate
1081 * multiple LLVM bblocks for a mono bblock to handle throwing exceptions.
1083 static LLVMBasicBlockRef
1084 get_end_bb (EmitContext *ctx, MonoBasicBlock *bb)
1086 get_bb (ctx, bb);
1087 return ctx->bblocks [bb->block_num].end_bblock;
1090 static LLVMBasicBlockRef
1091 gen_bb (EmitContext *ctx, const char *prefix)
1093 char bb_name [128];
1095 sprintf (bb_name, "%s%d", prefix, ++ ctx->ex_index);
1096 return LLVMAppendBasicBlock (ctx->lmethod, bb_name);
1100 * resolve_patch:
1102 * Return the target of the patch identified by TYPE and TARGET.
1104 static gpointer
1105 resolve_patch (MonoCompile *cfg, MonoJumpInfoType type, gconstpointer target)
1107 MonoJumpInfo ji;
1108 ERROR_DECL (error);
1109 gpointer res;
1111 memset (&ji, 0, sizeof (ji));
1112 ji.type = type;
1113 ji.data.target = target;
1115 res = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, &ji, FALSE, error);
1116 mono_error_assert_ok (error);
1118 return res;
1122 * convert_full:
1124 * Emit code to convert the LLVM value V to DTYPE.
1126 static LLVMValueRef
1127 convert_full (EmitContext *ctx, LLVMValueRef v, LLVMTypeRef dtype, gboolean is_unsigned)
1129 LLVMTypeRef stype = LLVMTypeOf (v);
1131 if (stype != dtype) {
1132 gboolean ext = FALSE;
1134 /* Extend */
1135 if (dtype == LLVMInt64Type () && (stype == LLVMInt32Type () || stype == LLVMInt16Type () || stype == LLVMInt8Type ()))
1136 ext = TRUE;
1137 else if (dtype == LLVMInt32Type () && (stype == LLVMInt16Type () || stype == LLVMInt8Type ()))
1138 ext = TRUE;
1139 else if (dtype == LLVMInt16Type () && (stype == LLVMInt8Type ()))
1140 ext = TRUE;
1142 if (ext)
1143 return is_unsigned ? LLVMBuildZExt (ctx->builder, v, dtype, "") : LLVMBuildSExt (ctx->builder, v, dtype, "");
1145 if (dtype == LLVMDoubleType () && stype == LLVMFloatType ())
1146 return LLVMBuildFPExt (ctx->builder, v, dtype, "");
1148 /* Trunc */
1149 if (stype == LLVMInt64Type () && (dtype == LLVMInt32Type () || dtype == LLVMInt16Type () || dtype == LLVMInt8Type ()))
1150 return LLVMBuildTrunc (ctx->builder, v, dtype, "");
1151 if (stype == LLVMInt32Type () && (dtype == LLVMInt16Type () || dtype == LLVMInt8Type ()))
1152 return LLVMBuildTrunc (ctx->builder, v, dtype, "");
1153 if (stype == LLVMInt16Type () && dtype == LLVMInt8Type ())
1154 return LLVMBuildTrunc (ctx->builder, v, dtype, "");
1155 if (stype == LLVMDoubleType () && dtype == LLVMFloatType ())
1156 return LLVMBuildFPTrunc (ctx->builder, v, dtype, "");
1158 if (LLVMGetTypeKind (stype) == LLVMPointerTypeKind && LLVMGetTypeKind (dtype) == LLVMPointerTypeKind)
1159 return LLVMBuildBitCast (ctx->builder, v, dtype, "");
1160 if (LLVMGetTypeKind (dtype) == LLVMPointerTypeKind)
1161 return LLVMBuildIntToPtr (ctx->builder, v, dtype, "");
1162 if (LLVMGetTypeKind (stype) == LLVMPointerTypeKind)
1163 return LLVMBuildPtrToInt (ctx->builder, v, dtype, "");
1165 if (mono_arch_is_soft_float ()) {
1166 if (stype == LLVMInt32Type () && dtype == LLVMFloatType ())
1167 return LLVMBuildBitCast (ctx->builder, v, dtype, "");
1168 if (stype == LLVMInt32Type () && dtype == LLVMDoubleType ())
1169 return LLVMBuildBitCast (ctx->builder, LLVMBuildZExt (ctx->builder, v, LLVMInt64Type (), ""), dtype, "");
1172 if (LLVMGetTypeKind (stype) == LLVMVectorTypeKind && LLVMGetTypeKind (dtype) == LLVMVectorTypeKind)
1173 return LLVMBuildBitCast (ctx->builder, v, dtype, "");
1175 LLVMDumpValue (v);
1176 LLVMDumpValue (LLVMConstNull (dtype));
1177 g_assert_not_reached ();
1178 return NULL;
1179 } else {
1180 return v;
1184 static LLVMValueRef
1185 convert (EmitContext *ctx, LLVMValueRef v, LLVMTypeRef dtype)
1187 return convert_full (ctx, v, dtype, FALSE);
1191 * emit_volatile_load:
1193 * If vreg is volatile, emit a load from its address.
1195 static LLVMValueRef
1196 emit_volatile_load (EmitContext *ctx, int vreg)
1198 MonoType *t;
1199 LLVMValueRef v;
1201 // On arm64, we pass the rgctx in a callee saved
1202 // register on arm64 (x15), and llvm might keep the value in that register
1203 // even through the register is marked as 'reserved' inside llvm.
1205 v = mono_llvm_build_load (ctx->builder, ctx->addresses [vreg], "", TRUE);
1206 t = ctx->vreg_cli_types [vreg];
1207 if (t && !t->byref) {
1209 * Might have to zero extend since llvm doesn't have
1210 * unsigned types.
1212 if (t->type == MONO_TYPE_U1 || t->type == MONO_TYPE_U2 || t->type == MONO_TYPE_CHAR || t->type == MONO_TYPE_BOOLEAN)
1213 v = LLVMBuildZExt (ctx->builder, v, LLVMInt32Type (), "");
1214 else if (t->type == MONO_TYPE_I1 || t->type == MONO_TYPE_I2)
1215 v = LLVMBuildSExt (ctx->builder, v, LLVMInt32Type (), "");
1216 else if (t->type == MONO_TYPE_U8)
1217 v = LLVMBuildZExt (ctx->builder, v, LLVMInt64Type (), "");
1220 return v;
1224 * emit_volatile_store:
1226 * If VREG is volatile, emit a store from its value to its address.
1228 static void
1229 emit_volatile_store (EmitContext *ctx, int vreg)
1231 MonoInst *var = get_vreg_to_inst (ctx->cfg, vreg);
1233 if (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) {
1234 g_assert (ctx->addresses [vreg]);
1235 LLVMBuildStore (ctx->builder, convert (ctx, ctx->values [vreg], type_to_llvm_type (ctx, var->inst_vtype)), ctx->addresses [vreg]);
1239 static LLVMTypeRef
1240 sig_to_llvm_sig_no_cinfo (EmitContext *ctx, MonoMethodSignature *sig)
1242 LLVMTypeRef ret_type;
1243 LLVMTypeRef *param_types = NULL;
1244 LLVMTypeRef res;
1245 int i, pindex;
1246 MonoType *rtype;
1248 ret_type = type_to_llvm_type (ctx, sig->ret);
1249 if (!ctx_ok (ctx))
1250 return NULL;
1251 rtype = mini_get_underlying_type (sig->ret);
1253 param_types = g_new0 (LLVMTypeRef, (sig->param_count * 8) + 3);
1254 pindex = 0;
1256 if (sig->hasthis)
1257 param_types [pindex ++] = ThisType ();
1258 for (i = 0; i < sig->param_count; ++i)
1259 param_types [pindex ++] = type_to_llvm_arg_type (ctx, sig->params [i]);
1261 if (!ctx_ok (ctx)) {
1262 g_free (param_types);
1263 return NULL;
1266 res = LLVMFunctionType (ret_type, param_types, pindex, FALSE);
1267 g_free (param_types);
1269 return res;
1273 * sig_to_llvm_sig_full:
1275 * Return the LLVM signature corresponding to the mono signature SIG using the
1276 * calling convention information in CINFO. Fill out the parameter mapping information in CINFO.
1278 static LLVMTypeRef
1279 sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *cinfo)
1281 LLVMTypeRef ret_type;
1282 LLVMTypeRef *param_types = NULL;
1283 LLVMTypeRef res;
1284 int i, j, pindex, vret_arg_pindex = 0;
1285 gboolean vretaddr = FALSE;
1286 MonoType *rtype;
1288 if (!cinfo)
1289 return sig_to_llvm_sig_no_cinfo (ctx, sig);
1291 ret_type = type_to_llvm_type (ctx, sig->ret);
1292 if (!ctx_ok (ctx))
1293 return NULL;
1294 rtype = mini_get_underlying_type (sig->ret);
1296 switch (cinfo->ret.storage) {
1297 case LLVMArgVtypeInReg:
1298 /* LLVM models this by returning an aggregate value */
1299 if (cinfo->ret.pair_storage [0] == LLVMArgInIReg && cinfo->ret.pair_storage [1] == LLVMArgNone) {
1300 LLVMTypeRef members [2];
1302 members [0] = IntPtrType ();
1303 ret_type = LLVMStructType (members, 1, FALSE);
1304 } else if (cinfo->ret.pair_storage [0] == LLVMArgNone && cinfo->ret.pair_storage [1] == LLVMArgNone) {
1305 /* Empty struct */
1306 ret_type = LLVMVoidType ();
1307 } else if (cinfo->ret.pair_storage [0] == LLVMArgInIReg && cinfo->ret.pair_storage [1] == LLVMArgInIReg) {
1308 LLVMTypeRef members [2];
1310 members [0] = IntPtrType ();
1311 members [1] = IntPtrType ();
1312 ret_type = LLVMStructType (members, 2, FALSE);
1313 } else {
1314 g_assert_not_reached ();
1316 break;
1317 case LLVMArgVtypeByVal:
1318 /* Vtype returned normally by val */
1319 break;
1320 case LLVMArgVtypeAsScalar: {
1321 int size = mono_class_value_size (mono_class_from_mono_type_internal (rtype), NULL);
1322 /* LLVM models this by returning an int */
1323 if (size < TARGET_SIZEOF_VOID_P) {
1324 g_assert (cinfo->ret.nslots == 1);
1325 ret_type = LLVMIntType (size * 8);
1326 } else {
1327 g_assert (cinfo->ret.nslots == 1 || cinfo->ret.nslots == 2);
1328 ret_type = LLVMIntType (cinfo->ret.nslots * sizeof (mgreg_t) * 8);
1330 break;
1332 case LLVMArgAsIArgs:
1333 ret_type = LLVMArrayType (IntPtrType (), cinfo->ret.nslots);
1334 break;
1335 case LLVMArgFpStruct: {
1336 /* Vtype returned as a fp struct */
1337 LLVMTypeRef members [16];
1339 /* Have to create our own structure since we don't map fp structures to LLVM fp structures yet */
1340 for (i = 0; i < cinfo->ret.nslots; ++i)
1341 members [i] = cinfo->ret.esize == 8 ? LLVMDoubleType () : LLVMFloatType ();
1342 ret_type = LLVMStructType (members, cinfo->ret.nslots, FALSE);
1343 break;
1345 case LLVMArgVtypeByRef:
1346 /* Vtype returned using a hidden argument */
1347 ret_type = LLVMVoidType ();
1348 break;
1349 case LLVMArgVtypeRetAddr:
1350 case LLVMArgGsharedvtFixed:
1351 case LLVMArgGsharedvtFixedVtype:
1352 case LLVMArgGsharedvtVariable:
1353 vretaddr = TRUE;
1354 ret_type = LLVMVoidType ();
1355 break;
1356 default:
1357 break;
1360 param_types = g_new0 (LLVMTypeRef, (sig->param_count * 8) + 3);
1361 pindex = 0;
1362 if (cinfo->ret.storage == LLVMArgVtypeByRef) {
1364 * Has to be the first argument because of the sret argument attribute
1365 * FIXME: This might conflict with passing 'this' as the first argument, but
1366 * this is only used on arm64 which has a dedicated struct return register.
1368 cinfo->vret_arg_pindex = pindex;
1369 param_types [pindex] = type_to_llvm_arg_type (ctx, sig->ret);
1370 if (!ctx_ok (ctx)) {
1371 g_free (param_types);
1372 return NULL;
1374 param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
1375 pindex ++;
1377 if (!ctx->llvm_only && cinfo->rgctx_arg) {
1378 cinfo->rgctx_arg_pindex = pindex;
1379 param_types [pindex] = ctx->module->ptr_type;
1380 pindex ++;
1382 if (cinfo->imt_arg) {
1383 cinfo->imt_arg_pindex = pindex;
1384 param_types [pindex] = ctx->module->ptr_type;
1385 pindex ++;
1387 if (vretaddr) {
1388 /* Compute the index in the LLVM signature where the vret arg needs to be passed */
1389 vret_arg_pindex = pindex;
1390 if (cinfo->vret_arg_index == 1) {
1391 /* Add the slots consumed by the first argument */
1392 LLVMArgInfo *ainfo = &cinfo->args [0];
1393 switch (ainfo->storage) {
1394 case LLVMArgVtypeInReg:
1395 for (j = 0; j < 2; ++j) {
1396 if (ainfo->pair_storage [j] == LLVMArgInIReg)
1397 vret_arg_pindex ++;
1399 break;
1400 default:
1401 vret_arg_pindex ++;
1405 cinfo->vret_arg_pindex = vret_arg_pindex;
1408 if (vretaddr && vret_arg_pindex == pindex)
1409 param_types [pindex ++] = IntPtrType ();
1410 if (sig->hasthis) {
1411 cinfo->this_arg_pindex = pindex;
1412 param_types [pindex ++] = ThisType ();
1413 cinfo->args [0].pindex = cinfo->this_arg_pindex;
1415 if (vretaddr && vret_arg_pindex == pindex)
1416 param_types [pindex ++] = IntPtrType ();
1417 for (i = 0; i < sig->param_count; ++i) {
1418 LLVMArgInfo *ainfo = &cinfo->args [i + sig->hasthis];
1420 if (vretaddr && vret_arg_pindex == pindex)
1421 param_types [pindex ++] = IntPtrType ();
1422 ainfo->pindex = pindex;
1424 switch (ainfo->storage) {
1425 case LLVMArgVtypeInReg:
1426 for (j = 0; j < 2; ++j) {
1427 switch (ainfo->pair_storage [j]) {
1428 case LLVMArgInIReg:
1429 param_types [pindex ++] = LLVMIntType (sizeof (gpointer) * 8);
1430 break;
1431 case LLVMArgNone:
1432 break;
1433 default:
1434 g_assert_not_reached ();
1437 break;
1438 case LLVMArgVtypeByVal:
1439 param_types [pindex] = type_to_llvm_arg_type (ctx, ainfo->type);
1440 if (!ctx_ok (ctx))
1441 break;
1442 param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
1443 pindex ++;
1444 break;
1445 case LLVMArgAsIArgs:
1446 if (ainfo->esize == 8)
1447 param_types [pindex] = LLVMArrayType (LLVMInt64Type (), ainfo->nslots);
1448 else
1449 param_types [pindex] = LLVMArrayType (IntPtrType (), ainfo->nslots);
1450 pindex ++;
1451 break;
1452 case LLVMArgVtypeByRef:
1453 param_types [pindex] = type_to_llvm_arg_type (ctx, ainfo->type);
1454 if (!ctx_ok (ctx))
1455 break;
1456 param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
1457 pindex ++;
1458 break;
1459 case LLVMArgAsFpArgs: {
1460 int j;
1462 /* Emit dummy fp arguments if needed so the rest is passed on the stack */
1463 for (j = 0; j < ainfo->ndummy_fpargs; ++j)
1464 param_types [pindex ++] = LLVMDoubleType ();
1465 for (j = 0; j < ainfo->nslots; ++j)
1466 param_types [pindex ++] = ainfo->esize == 8 ? LLVMDoubleType () : LLVMFloatType ();
1467 break;
1469 case LLVMArgVtypeAsScalar:
1470 g_assert_not_reached ();
1471 break;
1472 case LLVMArgGsharedvtFixed:
1473 case LLVMArgGsharedvtFixedVtype:
1474 param_types [pindex ++] = LLVMPointerType (type_to_llvm_arg_type (ctx, ainfo->type), 0);
1475 break;
1476 case LLVMArgGsharedvtVariable:
1477 param_types [pindex ++] = LLVMPointerType (IntPtrType (), 0);
1478 break;
1479 default:
1480 param_types [pindex ++] = type_to_llvm_arg_type (ctx, ainfo->type);
1481 break;
1484 if (!ctx_ok (ctx)) {
1485 g_free (param_types);
1486 return NULL;
1488 if (vretaddr && vret_arg_pindex == pindex)
1489 param_types [pindex ++] = IntPtrType ();
1490 if (ctx->llvm_only && cinfo->rgctx_arg) {
1491 /* Pass the rgctx as the last argument */
1492 cinfo->rgctx_arg_pindex = pindex;
1493 param_types [pindex] = ctx->module->ptr_type;
1494 pindex ++;
1495 } else if (ctx->llvm_only && cinfo->dummy_arg) {
1496 /* Pass a dummy arg last */
1497 cinfo->dummy_arg_pindex = pindex;
1498 param_types [pindex] = ctx->module->ptr_type;
1499 pindex ++;
1502 res = LLVMFunctionType (ret_type, param_types, pindex, FALSE);
1503 g_free (param_types);
1505 return res;
1508 static LLVMTypeRef
1509 sig_to_llvm_sig (EmitContext *ctx, MonoMethodSignature *sig)
1511 return sig_to_llvm_sig_full (ctx, sig, NULL);
1515 * LLVMFunctionType1:
1517 * Create an LLVM function type from the arguments.
1519 static G_GNUC_UNUSED LLVMTypeRef
1520 LLVMFunctionType0 (LLVMTypeRef ReturnType,
1521 int IsVarArg)
1523 return LLVMFunctionType (ReturnType, NULL, 0, IsVarArg);
1527 * LLVMFunctionType1:
1529 * Create an LLVM function type from the arguments.
1531 static G_GNUC_UNUSED LLVMTypeRef
1532 LLVMFunctionType1 (LLVMTypeRef ReturnType,
1533 LLVMTypeRef ParamType1,
1534 int IsVarArg)
1536 LLVMTypeRef param_types [1];
1538 param_types [0] = ParamType1;
1540 return LLVMFunctionType (ReturnType, param_types, 1, IsVarArg);
1544 * LLVMFunctionType2:
1546 * Create an LLVM function type from the arguments.
1548 static G_GNUC_UNUSED LLVMTypeRef
1549 LLVMFunctionType2 (LLVMTypeRef ReturnType,
1550 LLVMTypeRef ParamType1,
1551 LLVMTypeRef ParamType2,
1552 int IsVarArg)
1554 LLVMTypeRef param_types [2];
1556 param_types [0] = ParamType1;
1557 param_types [1] = ParamType2;
1559 return LLVMFunctionType (ReturnType, param_types, 2, IsVarArg);
1563 * LLVMFunctionType3:
1565 * Create an LLVM function type from the arguments.
1567 static G_GNUC_UNUSED LLVMTypeRef
1568 LLVMFunctionType3 (LLVMTypeRef ReturnType,
1569 LLVMTypeRef ParamType1,
1570 LLVMTypeRef ParamType2,
1571 LLVMTypeRef ParamType3,
1572 int IsVarArg)
1574 LLVMTypeRef param_types [3];
1576 param_types [0] = ParamType1;
1577 param_types [1] = ParamType2;
1578 param_types [2] = ParamType3;
1580 return LLVMFunctionType (ReturnType, param_types, 3, IsVarArg);
1583 static G_GNUC_UNUSED LLVMTypeRef
1584 LLVMFunctionType5 (LLVMTypeRef ReturnType,
1585 LLVMTypeRef ParamType1,
1586 LLVMTypeRef ParamType2,
1587 LLVMTypeRef ParamType3,
1588 LLVMTypeRef ParamType4,
1589 LLVMTypeRef ParamType5,
1590 int IsVarArg)
1592 LLVMTypeRef param_types [5];
1594 param_types [0] = ParamType1;
1595 param_types [1] = ParamType2;
1596 param_types [2] = ParamType3;
1597 param_types [3] = ParamType4;
1598 param_types [4] = ParamType5;
1600 return LLVMFunctionType (ReturnType, param_types, 5, IsVarArg);
1604 * create_builder:
1606 * Create an LLVM builder and remember it so it can be freed later.
1608 static LLVMBuilderRef
1609 create_builder (EmitContext *ctx)
1611 LLVMBuilderRef builder = LLVMCreateBuilder ();
1613 ctx->builders = g_slist_prepend_mempool (ctx->cfg->mempool, ctx->builders, builder);
1615 emit_default_dbg_loc (ctx, builder);
1617 return builder;
1620 static char*
1621 get_aotconst_name (MonoJumpInfoType type, gconstpointer data, int got_offset)
1623 char *name;
1625 switch (type) {
1626 case MONO_PATCH_INFO_INTERNAL_METHOD:
1627 name = g_strdup_printf ("jit_icall_%s", data);
1628 break;
1629 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1630 MonoJumpInfoRgctxEntry *entry = (MonoJumpInfoRgctxEntry*)data;
1631 name = g_strdup_printf ("RGCTX_SLOT_INDEX_%s", mono_rgctx_info_type_to_str (entry->info_type));
1632 break;
1634 default:
1635 name = g_strdup_printf ("%s_%d", mono_ji_type_to_string (type), got_offset);
1636 break;
1639 return name;
1642 static LLVMValueRef
1643 get_aotconst_typed (EmitContext *ctx, MonoJumpInfoType type, gconstpointer data, LLVMTypeRef llvm_type)
1645 MonoCompile *cfg;
1646 guint32 got_offset;
1647 LLVMValueRef indexes [2];
1648 LLVMValueRef got_entry_addr, load;
1649 LLVMBuilderRef builder = ctx->builder;
1650 char *name = NULL;
1652 cfg = ctx->cfg;
1654 MonoJumpInfo tmp_ji;
1655 tmp_ji.type = type;
1656 tmp_ji.data.target = data;
1658 MonoJumpInfo *ji = mono_aot_patch_info_dup (&tmp_ji);
1660 ji->next = cfg->patch_info;
1661 cfg->patch_info = ji;
1663 got_offset = mono_aot_get_got_offset (cfg->patch_info);
1664 ctx->module->max_got_offset = MAX (ctx->module->max_got_offset, got_offset);
1666 * If the got slot is shared, it means its initialized when the aot image is loaded, so we don't need to
1667 * explicitly initialize it.
1669 if (!mono_aot_is_shared_got_offset (got_offset)) {
1670 //mono_print_ji (ji);
1671 //printf ("\n");
1672 ctx->has_got_access = TRUE;
1675 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
1676 indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
1677 got_entry_addr = LLVMBuildGEP (builder, ctx->module->got_var, indexes, 2, "");
1679 name = get_aotconst_name (type, data, got_offset);
1680 if (llvm_type) {
1681 load = LLVMBuildLoad (builder, got_entry_addr, "");
1682 load = convert (ctx, load, llvm_type);
1683 LLVMSetValueName (load, name ? name : "");
1684 } else {
1685 load = LLVMBuildLoad (builder, got_entry_addr, name ? name : "");
1687 g_free (name);
1688 //set_invariant_load_flag (load);
1690 return load;
1693 static LLVMValueRef
1694 get_aotconst (EmitContext *ctx, MonoJumpInfoType type, gconstpointer data)
1696 return get_aotconst_typed (ctx, type, data, NULL);
1699 static LLVMValueRef
1700 get_callee (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gconstpointer data)
1702 LLVMValueRef callee;
1703 char *callee_name;
1704 if (ctx->llvm_only) {
1705 callee_name = mono_aot_get_direct_call_symbol (type, data);
1706 if (callee_name) {
1707 /* Directly callable */
1708 // FIXME: Locking
1709 callee = (LLVMValueRef)g_hash_table_lookup (ctx->module->direct_callables, callee_name);
1710 if (!callee) {
1711 callee = LLVMAddFunction (ctx->lmodule, callee_name, llvm_sig);
1713 LLVMSetVisibility (callee, LLVMHiddenVisibility);
1715 g_hash_table_insert (ctx->module->direct_callables, (char*)callee_name, callee);
1716 } else {
1717 /* LLVMTypeRef's are uniqued */
1718 if (LLVMGetElementType (LLVMTypeOf (callee)) != llvm_sig)
1719 return LLVMConstBitCast (callee, LLVMPointerType (llvm_sig, 0));
1721 g_free (callee_name);
1723 return callee;
1727 * Calls are made through the GOT.
1729 return get_aotconst_typed (ctx, type, data, LLVMPointerType (llvm_sig, 0));
1730 } else {
1731 MonoJumpInfo *ji = NULL;
1733 callee_name = mono_aot_get_plt_symbol (type, data);
1734 if (!callee_name)
1735 return NULL;
1737 if (ctx->cfg->compile_aot)
1738 /* Add a patch so referenced wrappers can be compiled in full aot mode */
1739 mono_add_patch_info (ctx->cfg, 0, type, data);
1741 // FIXME: Locking
1742 callee = (LLVMValueRef)g_hash_table_lookup (ctx->module->plt_entries, callee_name);
1743 if (!callee) {
1744 callee = LLVMAddFunction (ctx->lmodule, callee_name, llvm_sig);
1746 LLVMSetVisibility (callee, LLVMHiddenVisibility);
1748 g_hash_table_insert (ctx->module->plt_entries, (char*)callee_name, callee);
1751 if (ctx->cfg->compile_aot) {
1752 ji = g_new0 (MonoJumpInfo, 1);
1753 ji->type = type;
1754 ji->data.target = data;
1756 g_hash_table_insert (ctx->module->plt_entries_ji, ji, callee);
1759 return callee;
1763 static LLVMValueRef
1764 emit_jit_callee (EmitContext *ctx, const char *name, LLVMTypeRef llvm_sig, gpointer target)
1766 #if LLVM_API_VERSION > 100
1767 LLVMValueRef tramp_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (llvm_sig, 0), name);
1768 LLVMSetInitializer (tramp_var, LLVMConstIntToPtr (LLVMConstInt (LLVMInt64Type (), (guint64)(size_t)target, FALSE), LLVMPointerType (llvm_sig, 0)));
1769 LLVMSetLinkage (tramp_var, LLVMExternalLinkage);
1770 LLVMValueRef callee = LLVMBuildLoad (ctx->builder, tramp_var, "");
1771 return callee;
1772 #else
1773 LLVMValueRef callee = LLVMAddFunction (ctx->lmodule, "", llvm_sig);
1774 LLVMAddGlobalMapping (ctx->module->ee, callee, target);
1775 return callee;
1776 #endif
1779 static int
1780 get_handler_clause (MonoCompile *cfg, MonoBasicBlock *bb)
1782 MonoMethodHeader *header = cfg->header;
1783 MonoExceptionClause *clause;
1784 int i;
1786 /* Directly */
1787 if (bb->region != -1 && MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY))
1788 return (bb->region >> 8) - 1;
1790 /* Indirectly */
1791 for (i = 0; i < header->num_clauses; ++i) {
1792 clause = &header->clauses [i];
1794 if (MONO_OFFSET_IN_CLAUSE (clause, bb->real_offset) && clause->flags == MONO_EXCEPTION_CLAUSE_NONE)
1795 return i;
1798 return -1;
1801 static MonoExceptionClause *
1802 get_most_deep_clause (MonoCompile *cfg, EmitContext *ctx, MonoBasicBlock *bb)
1804 if (bb == cfg->bb_init)
1805 return NULL;
1806 // Since they're sorted by nesting we just need
1807 // the first one that the bb is a member of
1808 for (int i = 0; i < cfg->header->num_clauses; i++) {
1809 MonoExceptionClause *curr = &cfg->header->clauses [i];
1811 if (MONO_OFFSET_IN_CLAUSE (curr, bb->real_offset))
1812 return curr;
1815 return NULL;
1818 static void
1819 set_metadata_flag (LLVMValueRef v, const char *flag_name)
1821 LLVMValueRef md_arg;
1822 int md_kind;
1824 md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
1825 md_arg = LLVMMDString ("mono", 4);
1826 LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
1829 static void
1830 set_invariant_load_flag (LLVMValueRef v)
1832 LLVMValueRef md_arg;
1833 int md_kind;
1834 const char *flag_name;
1836 // FIXME: Cache this
1837 flag_name = "invariant.load";
1838 md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
1839 md_arg = LLVMMDString ("<index>", strlen ("<index>"));
1840 LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
1844 * emit_call:
1846 * Emit an LLVM call or invoke instruction depending on whenever the call is inside
1847 * a try region.
1849 static LLVMValueRef
1850 emit_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, LLVMValueRef callee, LLVMValueRef *args, int pindex)
1852 MonoCompile *cfg = ctx->cfg;
1853 LLVMValueRef lcall = NULL;
1854 LLVMBuilderRef builder = *builder_ref;
1855 MonoExceptionClause *clause;
1857 if (ctx->llvm_only) {
1858 clause = get_most_deep_clause (cfg, ctx, bb);
1860 if (clause) {
1861 g_assert (clause->flags == MONO_EXCEPTION_CLAUSE_NONE || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY || clause->flags == MONO_EXCEPTION_CLAUSE_FAULT);
1864 * Have to use an invoke instead of a call, branching to the
1865 * handler bblock of the clause containing this bblock.
1867 intptr_t key = CLAUSE_END(clause);
1869 LLVMBasicBlockRef lpad_bb = (LLVMBasicBlockRef)g_hash_table_lookup (ctx->exc_meta, (gconstpointer)key);
1871 // FIXME: Find the one that has the lowest end bound for the right start address
1872 // FIXME: Finally + nesting
1874 if (lpad_bb) {
1875 LLVMBasicBlockRef noex_bb = gen_bb (ctx, "CALL_NOEX_BB");
1877 /* Use an invoke */
1878 lcall = LLVMBuildInvoke (builder, callee, args, pindex, noex_bb, lpad_bb, "");
1880 builder = ctx->builder = create_builder (ctx);
1881 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
1883 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
1886 } else {
1887 int clause_index = get_handler_clause (cfg, bb);
1889 if (clause_index != -1) {
1890 MonoMethodHeader *header = cfg->header;
1891 MonoExceptionClause *ec = &header->clauses [clause_index];
1892 MonoBasicBlock *tblock;
1893 LLVMBasicBlockRef ex_bb, noex_bb;
1896 * Have to use an invoke instead of a call, branching to the
1897 * handler bblock of the clause containing this bblock.
1900 g_assert (ec->flags == MONO_EXCEPTION_CLAUSE_NONE || ec->flags == MONO_EXCEPTION_CLAUSE_FINALLY || ec->flags == MONO_EXCEPTION_CLAUSE_FAULT);
1902 tblock = cfg->cil_offset_to_bb [ec->handler_offset];
1903 g_assert (tblock);
1905 ctx->bblocks [tblock->block_num].invoke_target = TRUE;
1907 ex_bb = get_bb (ctx, tblock);
1909 noex_bb = gen_bb (ctx, "NOEX_BB");
1911 /* Use an invoke */
1912 lcall = LLVMBuildInvoke (builder, callee, args, pindex, noex_bb, ex_bb, "");
1914 builder = ctx->builder = create_builder (ctx);
1915 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
1917 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
1921 if (!lcall) {
1922 lcall = LLVMBuildCall (builder, callee, args, pindex, "");
1923 ctx->builder = builder;
1926 if (builder_ref)
1927 *builder_ref = ctx->builder;
1929 return lcall;
1932 static LLVMValueRef
1933 emit_load_general (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef addr, LLVMValueRef base, const char *name, gboolean is_faulting, BarrierKind barrier)
1935 const char *intrins_name;
1936 LLVMValueRef args [16], res;
1937 LLVMTypeRef addr_type;
1938 gboolean use_intrinsics = TRUE;
1940 #if LLVM_API_VERSION > 100
1941 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only) {
1942 /* The llvm.mono.load/store intrinsics are not supported by this llvm version, emit an explicit null check instead */
1943 LLVMValueRef cmp;
1945 cmp = LLVMBuildICmp (*builder_ref, LLVMIntEQ, base, LLVMConstNull (LLVMTypeOf (base)), "");
1946 emit_cond_system_exception (ctx, bb, "NullReferenceException", cmp);
1947 *builder_ref = ctx->builder;
1948 use_intrinsics = FALSE;
1950 #endif
1952 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only && use_intrinsics) {
1953 LLVMAtomicOrdering ordering;
1955 switch (barrier) {
1956 case LLVM_BARRIER_NONE:
1957 ordering = LLVMAtomicOrderingNotAtomic;
1958 break;
1959 case LLVM_BARRIER_ACQ:
1960 ordering = LLVMAtomicOrderingAcquire;
1961 break;
1962 case LLVM_BARRIER_SEQ:
1963 ordering = LLVMAtomicOrderingSequentiallyConsistent;
1964 break;
1965 default:
1966 g_assert_not_reached ();
1967 break;
1971 * We handle loads which can fault by calling a mono specific intrinsic
1972 * using an invoke, so they are handled properly inside try blocks.
1973 * We can't use this outside clauses, since LLVM optimizes intrinsics which
1974 * are marked with IntrReadArgMem.
1976 switch (size) {
1977 case 1:
1978 intrins_name = "llvm.mono.load.i8.p0i8";
1979 break;
1980 case 2:
1981 intrins_name = "llvm.mono.load.i16.p0i16";
1982 break;
1983 case 4:
1984 intrins_name = "llvm.mono.load.i32.p0i32";
1985 break;
1986 case 8:
1987 intrins_name = "llvm.mono.load.i64.p0i64";
1988 break;
1989 default:
1990 g_assert_not_reached ();
1993 addr_type = LLVMTypeOf (addr);
1994 if (addr_type == LLVMPointerType (LLVMDoubleType (), 0) || addr_type == LLVMPointerType (LLVMFloatType (), 0))
1995 addr = LLVMBuildBitCast (*builder_ref, addr, LLVMPointerType (LLVMIntType (size * 8), 0), "");
1997 args [0] = addr;
1998 args [1] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
1999 args [2] = LLVMConstInt (LLVMInt1Type (), TRUE, FALSE);
2000 args [3] = LLVMConstInt (LLVMInt32Type (), ordering, FALSE);
2001 res = emit_call (ctx, bb, builder_ref, get_intrinsic (ctx, intrins_name), args, 4);
2003 if (addr_type == LLVMPointerType (LLVMDoubleType (), 0))
2004 res = LLVMBuildBitCast (*builder_ref, res, LLVMDoubleType (), "");
2005 else if (addr_type == LLVMPointerType (LLVMFloatType (), 0))
2006 res = LLVMBuildBitCast (*builder_ref, res, LLVMFloatType (), "");
2008 return res;
2009 } else {
2010 LLVMValueRef res;
2013 * We emit volatile loads for loads which can fault, because otherwise
2014 * LLVM will generate invalid code when encountering a load from a
2015 * NULL address.
2017 if (barrier != LLVM_BARRIER_NONE)
2018 res = mono_llvm_build_atomic_load (*builder_ref, addr, name, is_faulting, size, barrier);
2019 else
2020 res = mono_llvm_build_load (*builder_ref, addr, name, is_faulting);
2022 /* Mark it with a custom metadata */
2024 if (is_faulting)
2025 set_metadata_flag (res, "mono.faulting.load");
2028 return res;
2032 static LLVMValueRef
2033 emit_load (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef addr, const char *name, gboolean is_faulting)
2035 return emit_load_general (ctx, bb, builder_ref, size, addr, addr, name, is_faulting, LLVM_BARRIER_NONE);
2038 static void
2039 emit_store_general (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef value, LLVMValueRef addr, LLVMValueRef base, gboolean is_faulting, BarrierKind barrier)
2041 const char *intrins_name;
2042 LLVMValueRef args [16];
2043 gboolean use_intrinsics = TRUE;
2045 #if LLVM_API_VERSION > 100
2046 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only) {
2047 /* The llvm.mono.load/store intrinsics are not supported by this llvm version, emit an explicit null check instead */
2048 LLVMValueRef cmp = LLVMBuildICmp (*builder_ref, LLVMIntEQ, base, LLVMConstNull (LLVMTypeOf (base)), "");
2049 emit_cond_system_exception (ctx, bb, "NullReferenceException", cmp);
2050 *builder_ref = ctx->builder;
2051 use_intrinsics = FALSE;
2053 #endif
2055 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only && use_intrinsics) {
2056 LLVMAtomicOrdering ordering;
2058 switch (barrier) {
2059 case LLVM_BARRIER_NONE:
2060 ordering = LLVMAtomicOrderingNotAtomic;
2061 break;
2062 case LLVM_BARRIER_REL:
2063 ordering = LLVMAtomicOrderingRelease;
2064 break;
2065 case LLVM_BARRIER_SEQ:
2066 ordering = LLVMAtomicOrderingSequentiallyConsistent;
2067 break;
2068 default:
2069 g_assert_not_reached ();
2070 break;
2073 switch (size) {
2074 case 1:
2075 intrins_name = "llvm.mono.store.i8.p0i8";
2076 break;
2077 case 2:
2078 intrins_name = "llvm.mono.store.i16.p0i16";
2079 break;
2080 case 4:
2081 intrins_name = "llvm.mono.store.i32.p0i32";
2082 break;
2083 case 8:
2084 intrins_name = "llvm.mono.store.i64.p0i64";
2085 break;
2086 default:
2087 g_assert_not_reached ();
2090 if (LLVMTypeOf (value) == LLVMDoubleType () || LLVMTypeOf (value) == LLVMFloatType ()) {
2091 value = LLVMBuildBitCast (*builder_ref, value, LLVMIntType (size * 8), "");
2092 addr = LLVMBuildBitCast (*builder_ref, addr, LLVMPointerType (LLVMIntType (size * 8), 0), "");
2095 args [0] = value;
2096 args [1] = addr;
2097 args [2] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2098 args [3] = LLVMConstInt (LLVMInt1Type (), TRUE, FALSE);
2099 args [4] = LLVMConstInt (LLVMInt32Type (), ordering, FALSE);
2100 emit_call (ctx, bb, builder_ref, get_intrinsic (ctx, intrins_name), args, 5);
2101 } else {
2102 if (barrier != LLVM_BARRIER_NONE)
2103 mono_llvm_build_aligned_store (*builder_ref, value, addr, barrier, size);
2104 else
2105 mono_llvm_build_store (*builder_ref, value, addr, is_faulting, barrier);
2109 static void
2110 emit_store (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef value, LLVMValueRef addr, LLVMValueRef base, gboolean is_faulting)
2112 emit_store_general (ctx, bb, builder_ref, size, value, addr, base, is_faulting, LLVM_BARRIER_NONE);
2116 * emit_cond_system_exception:
2118 * Emit code to throw the exception EXC_TYPE if the condition CMP is false.
2119 * Might set the ctx exception.
2121 static void
2122 emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *exc_type, LLVMValueRef cmp)
2124 LLVMBasicBlockRef ex_bb, ex2_bb = NULL, noex_bb;
2125 LLVMBuilderRef builder;
2126 MonoClass *exc_class;
2127 LLVMValueRef args [2];
2128 LLVMValueRef callee;
2129 gboolean no_pc = FALSE;
2131 if (IS_TARGET_AMD64)
2132 /* Some platforms don't require the pc argument */
2133 no_pc = TRUE;
2135 ex_bb = gen_bb (ctx, "EX_BB");
2136 if (ctx->llvm_only)
2137 ex2_bb = gen_bb (ctx, "EX2_BB");
2138 noex_bb = gen_bb (ctx, "NOEX_BB");
2140 LLVMBuildCondBr (ctx->builder, cmp, ex_bb, noex_bb);
2142 exc_class = mono_class_load_from_name (mono_get_corlib (), "System", exc_type);
2144 /* Emit exception throwing code */
2145 ctx->builder = builder = create_builder (ctx);
2146 LLVMPositionBuilderAtEnd (builder, ex_bb);
2148 if (ctx->cfg->llvm_only) {
2149 static LLVMTypeRef sig;
2151 if (!sig)
2152 sig = LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE);
2153 callee = get_callee (ctx, sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_llvm_throw_corlib_exception");
2155 LLVMBuildBr (builder, ex2_bb);
2157 ctx->builder = builder = create_builder (ctx);
2158 LLVMPositionBuilderAtEnd (ctx->builder, ex2_bb);
2160 args [0] = LLVMConstInt (LLVMInt32Type (), m_class_get_type_token (exc_class) - MONO_TOKEN_TYPE_DEF, FALSE);
2161 emit_call (ctx, bb, &builder, callee, args, 1);
2162 LLVMBuildUnreachable (builder);
2164 ctx->builder = builder = create_builder (ctx);
2165 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
2167 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
2169 ctx->ex_index ++;
2170 return;
2173 callee = ctx->module->throw_corlib_exception;
2174 if (!callee) {
2175 LLVMTypeRef sig;
2176 const char *icall_name;
2178 if (no_pc)
2179 sig = LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE);
2180 else
2181 sig = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), LLVMPointerType (LLVMInt8Type (), 0), FALSE);
2182 icall_name = "llvm_throw_corlib_exception_abs_trampoline";
2184 if (ctx->cfg->compile_aot) {
2185 callee = get_callee (ctx, sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
2186 } else {
2188 * Differences between the LLVM/non-LLVM throw corlib exception trampoline:
2189 * - On x86, LLVM generated code doesn't push the arguments
2190 * - The trampoline takes the throw address as an arguments, not a pc offset.
2192 gpointer target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
2193 callee = emit_jit_callee (ctx, "llvm_throw_corlib_exception_trampoline", sig, target);
2195 #if LLVM_API_VERSION > 100
2197 * Make sure that ex_bb starts with the invoke, so the block address points to it, and not to the load
2198 * added by emit_jit_callee ().
2200 ex2_bb = gen_bb (ctx, "EX2_BB");
2201 LLVMBuildBr (builder, ex2_bb);
2202 ex_bb = ex2_bb;
2204 ctx->builder = builder = create_builder (ctx);
2205 LLVMPositionBuilderAtEnd (ctx->builder, ex2_bb);
2206 #else
2207 mono_memory_barrier ();
2208 ctx->module->throw_corlib_exception = callee;
2209 #endif
2213 args [0] = LLVMConstInt (LLVMInt32Type (), m_class_get_type_token (exc_class) - MONO_TOKEN_TYPE_DEF, FALSE);
2216 * The LLVM mono branch contains changes so a block address can be passed as an
2217 * argument to a call.
2219 if (no_pc) {
2220 emit_call (ctx, bb, &builder, callee, args, 1);
2221 } else {
2222 args [1] = LLVMBlockAddress (ctx->lmethod, ex_bb);
2223 emit_call (ctx, bb, &builder, callee, args, 2);
2226 LLVMBuildUnreachable (builder);
2228 ctx->builder = builder = create_builder (ctx);
2229 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
2231 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
2233 ctx->ex_index ++;
2234 return;
2238 * emit_args_to_vtype:
2240 * Emit code to store the vtype in the arguments args to the address ADDRESS.
2242 static void
2243 emit_args_to_vtype (EmitContext *ctx, LLVMBuilderRef builder, MonoType *t, LLVMValueRef address, LLVMArgInfo *ainfo, LLVMValueRef *args)
2245 int j, size, nslots;
2247 size = mono_class_value_size (mono_class_from_mono_type_internal (t), NULL);
2249 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (t))) {
2250 address = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (LLVMInt8Type (), 0), "");
2253 if (ainfo->storage == LLVMArgAsFpArgs)
2254 nslots = ainfo->nslots;
2255 else
2256 nslots = 2;
2258 for (j = 0; j < nslots; ++j) {
2259 LLVMValueRef index [2], addr, daddr;
2260 int part_size = size > sizeof (gpointer) ? sizeof (gpointer) : size;
2261 LLVMTypeRef part_type;
2263 while (part_size != 1 && part_size != 2 && part_size != 4 && part_size < 8)
2264 part_size ++;
2266 if (ainfo->pair_storage [j] == LLVMArgNone)
2267 continue;
2269 switch (ainfo->pair_storage [j]) {
2270 case LLVMArgInIReg: {
2271 part_type = LLVMIntType (part_size * 8);
2272 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (t))) {
2273 index [0] = LLVMConstInt (LLVMInt32Type (), j * sizeof (gpointer), FALSE);
2274 addr = LLVMBuildGEP (builder, address, index, 1, "");
2275 } else {
2276 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (IntPtrType (), 0), "");
2277 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2278 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2280 LLVMBuildStore (builder, convert (ctx, args [j], part_type), LLVMBuildBitCast (ctx->builder, addr, LLVMPointerType (part_type, 0), ""));
2281 break;
2283 case LLVMArgInFPReg: {
2284 LLVMTypeRef arg_type;
2286 if (ainfo->esize == 8)
2287 arg_type = LLVMDoubleType ();
2288 else
2289 arg_type = LLVMFloatType ();
2291 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2292 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (arg_type, 0), "");
2293 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2294 LLVMBuildStore (builder, args [j], addr);
2295 break;
2297 case LLVMArgNone:
2298 break;
2299 default:
2300 g_assert_not_reached ();
2303 size -= sizeof (gpointer);
2308 * emit_vtype_to_args:
2310 * Emit code to load a vtype at address ADDRESS into scalar arguments. Store the arguments
2311 * into ARGS, and the number of arguments into NARGS.
2313 static void
2314 emit_vtype_to_args (EmitContext *ctx, LLVMBuilderRef builder, MonoType *t, LLVMValueRef address, LLVMArgInfo *ainfo, LLVMValueRef *args, guint32 *nargs)
2316 int pindex = 0;
2317 int j, size, nslots;
2318 LLVMTypeRef arg_type;
2320 size = get_vtype_size (t);
2322 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (t)))
2323 address = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (LLVMInt8Type (), 0), "");
2325 if (ainfo->storage == LLVMArgAsFpArgs)
2326 nslots = ainfo->nslots;
2327 else
2328 nslots = 2;
2329 for (j = 0; j < nslots; ++j) {
2330 LLVMValueRef index [2], addr, daddr;
2331 int partsize = size > sizeof (gpointer) ? sizeof (gpointer) : size;
2333 if (ainfo->pair_storage [j] == LLVMArgNone)
2334 continue;
2336 switch (ainfo->pair_storage [j]) {
2337 case LLVMArgInIReg:
2338 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (t))) {
2339 index [0] = LLVMConstInt (LLVMInt32Type (), j * sizeof (gpointer), FALSE);
2340 addr = LLVMBuildGEP (builder, address, index, 1, "");
2341 } else {
2342 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (IntPtrType (), 0), "");
2343 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2344 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2346 args [pindex ++] = convert (ctx, LLVMBuildLoad (builder, LLVMBuildBitCast (ctx->builder, addr, LLVMPointerType (LLVMIntType (partsize * 8), 0), ""), ""), IntPtrType ());
2347 break;
2348 case LLVMArgInFPReg:
2349 if (ainfo->esize == 8)
2350 arg_type = LLVMDoubleType ();
2351 else
2352 arg_type = LLVMFloatType ();
2353 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (arg_type, 0), "");
2354 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2355 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2356 args [pindex ++] = LLVMBuildLoad (builder, addr, "");
2357 break;
2358 case LLVMArgNone:
2359 break;
2360 default:
2361 g_assert_not_reached ();
2363 size -= sizeof (gpointer);
2366 *nargs = pindex;
2369 static LLVMValueRef
2370 build_alloca_llvm_type_name (EmitContext *ctx, LLVMTypeRef t, int align, const char *name)
2373 * Have to place all alloca's at the end of the entry bb, since otherwise they would
2374 * get executed every time control reaches them.
2376 LLVMPositionBuilder (ctx->alloca_builder, get_bb (ctx, ctx->cfg->bb_entry), ctx->last_alloca);
2378 ctx->last_alloca = mono_llvm_build_alloca (ctx->alloca_builder, t, NULL, align, name);
2379 return ctx->last_alloca;
2382 static LLVMValueRef
2383 build_alloca_llvm_type (EmitContext *ctx, LLVMTypeRef t, int align)
2385 return build_alloca_llvm_type_name (ctx, t, align, "");
2388 static LLVMValueRef
2389 build_alloca (EmitContext *ctx, MonoType *t)
2391 MonoClass *k = mono_class_from_mono_type_internal (t);
2392 int align;
2394 g_assert (!mini_is_gsharedvt_variable_type (t));
2396 if (MONO_CLASS_IS_SIMD (ctx->cfg, k))
2397 align = 16;
2398 else
2399 align = mono_class_min_align (k);
2401 /* Sometimes align is not a power of 2 */
2402 while (mono_is_power_of_two (align) == -1)
2403 align ++;
2405 return build_alloca_llvm_type (ctx, type_to_llvm_type (ctx, t), align);
2408 static LLVMValueRef
2409 emit_gsharedvt_ldaddr (EmitContext *ctx, int vreg)
2412 * gsharedvt local.
2413 * Compute the address of the local as gsharedvt_locals_var + gsharedvt_info_var->locals_offsets [idx].
2415 MonoCompile *cfg = ctx->cfg;
2416 LLVMBuilderRef builder = ctx->builder;
2417 LLVMValueRef offset, offset_var;
2418 LLVMValueRef info_var = ctx->values [cfg->gsharedvt_info_var->dreg];
2419 LLVMValueRef locals_var = ctx->values [cfg->gsharedvt_locals_var->dreg];
2420 LLVMValueRef ptr;
2421 char *name;
2423 g_assert (info_var);
2424 g_assert (locals_var);
2426 int idx = cfg->gsharedvt_vreg_to_idx [vreg] - 1;
2428 offset = LLVMConstInt (LLVMInt32Type (), MONO_STRUCT_OFFSET (MonoGSharedVtMethodRuntimeInfo, entries) + (idx * sizeof (gpointer)), FALSE);
2429 ptr = LLVMBuildAdd (builder, convert (ctx, info_var, IntPtrType ()), convert (ctx, offset, IntPtrType ()), "");
2431 name = g_strdup_printf ("gsharedvt_local_%d_offset", vreg);
2432 offset_var = LLVMBuildLoad (builder, convert (ctx, ptr, LLVMPointerType (LLVMInt32Type (), 0)), name);
2434 return LLVMBuildAdd (builder, convert (ctx, locals_var, IntPtrType ()), convert (ctx, offset_var, IntPtrType ()), "");
2438 * Put the global into the 'llvm.used' array to prevent it from being optimized away.
2440 static void
2441 mark_as_used (MonoLLVMModule *module, LLVMValueRef global)
2443 if (!module->used)
2444 module->used = g_ptr_array_sized_new (16);
2445 g_ptr_array_add (module->used, global);
2448 static void
2449 emit_llvm_used (MonoLLVMModule *module)
2451 LLVMModuleRef lmodule = module->lmodule;
2452 LLVMTypeRef used_type;
2453 LLVMValueRef used, *used_elem;
2454 int i;
2456 if (!module->used)
2457 return;
2459 used_type = LLVMArrayType (LLVMPointerType (LLVMInt8Type (), 0), module->used->len);
2460 used = LLVMAddGlobal (lmodule, used_type, "llvm.used");
2461 used_elem = g_new0 (LLVMValueRef, module->used->len);
2462 for (i = 0; i < module->used->len; ++i)
2463 used_elem [i] = LLVMConstBitCast ((LLVMValueRef)g_ptr_array_index (module->used, i), LLVMPointerType (LLVMInt8Type (), 0));
2464 LLVMSetInitializer (used, LLVMConstArray (LLVMPointerType (LLVMInt8Type (), 0), used_elem, module->used->len));
2465 LLVMSetLinkage (used, LLVMAppendingLinkage);
2466 LLVMSetSection (used, "llvm.metadata");
2470 * emit_get_method:
2472 * Emit a function mapping method indexes to their code
2474 static void
2475 emit_get_method (MonoLLVMModule *module)
2477 LLVMModuleRef lmodule = module->lmodule;
2478 LLVMValueRef func, switch_ins, m;
2479 LLVMBasicBlockRef entry_bb, fail_bb, bb, code_start_bb, code_end_bb;
2480 LLVMBasicBlockRef *bbs;
2481 LLVMTypeRef rtype;
2482 LLVMBuilderRef builder = LLVMCreateBuilder ();
2483 char *name;
2484 int i;
2487 * Emit a switch statement. Emitting a table of function addresses is smaller/faster,
2488 * but generating code seems safer.
2490 rtype = LLVMPointerType (LLVMInt8Type (), 0);
2491 func = LLVMAddFunction (lmodule, module->get_method_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
2492 LLVMSetLinkage (func, LLVMExternalLinkage);
2493 LLVMSetVisibility (func, LLVMHiddenVisibility);
2494 mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
2495 module->get_method = func;
2497 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2500 * Return llvm_code_start/llvm_code_end when called with -1/-2.
2501 * Hopefully, the toolchain doesn't reorder these functions. If it does,
2502 * then we will have to find another solution.
2505 name = g_strdup_printf ("BB_CODE_START");
2506 code_start_bb = LLVMAppendBasicBlock (func, name);
2507 g_free (name);
2508 LLVMPositionBuilderAtEnd (builder, code_start_bb);
2509 LLVMBuildRet (builder, LLVMBuildBitCast (builder, module->code_start, rtype, ""));
2511 name = g_strdup_printf ("BB_CODE_END");
2512 code_end_bb = LLVMAppendBasicBlock (func, name);
2513 g_free (name);
2514 LLVMPositionBuilderAtEnd (builder, code_end_bb);
2515 LLVMBuildRet (builder, LLVMBuildBitCast (builder, module->code_end, rtype, ""));
2517 bbs = g_new0 (LLVMBasicBlockRef, module->max_method_idx + 1);
2518 for (i = 0; i < module->max_method_idx + 1; ++i) {
2519 name = g_strdup_printf ("BB_%d", i);
2520 bb = LLVMAppendBasicBlock (func, name);
2521 g_free (name);
2522 bbs [i] = bb;
2524 LLVMPositionBuilderAtEnd (builder, bb);
2526 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_lmethod, GINT_TO_POINTER (i));
2527 if (m)
2528 LLVMBuildRet (builder, LLVMBuildBitCast (builder, m, rtype, ""));
2529 else
2530 LLVMBuildRet (builder, LLVMConstNull (rtype));
2533 fail_bb = LLVMAppendBasicBlock (func, "FAIL");
2534 LLVMPositionBuilderAtEnd (builder, fail_bb);
2535 LLVMBuildRet (builder, LLVMConstNull (rtype));
2537 LLVMPositionBuilderAtEnd (builder, entry_bb);
2539 switch_ins = LLVMBuildSwitch (builder, LLVMGetParam (func, 0), fail_bb, 0);
2540 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), -1, FALSE), code_start_bb);
2541 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), -2, FALSE), code_end_bb);
2542 for (i = 0; i < module->max_method_idx + 1; ++i) {
2543 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i, FALSE), bbs [i]);
2546 mark_as_used (module, func);
2548 LLVMDisposeBuilder (builder);
2552 * emit_get_unbox_tramp:
2554 * Emit a function mapping method indexes to their unbox trampoline
2556 static void
2557 emit_get_unbox_tramp (MonoLLVMModule *module)
2559 LLVMModuleRef lmodule = module->lmodule;
2560 LLVMValueRef func, switch_ins, m;
2561 LLVMBasicBlockRef entry_bb, fail_bb, bb;
2562 LLVMBasicBlockRef *bbs;
2563 LLVMTypeRef rtype;
2564 LLVMBuilderRef builder = LLVMCreateBuilder ();
2565 char *name;
2566 int i;
2568 /* Similar to emit_get_method () */
2570 rtype = LLVMPointerType (LLVMInt8Type (), 0);
2571 func = LLVMAddFunction (lmodule, module->get_unbox_tramp_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
2572 LLVMSetLinkage (func, LLVMExternalLinkage);
2573 LLVMSetVisibility (func, LLVMHiddenVisibility);
2574 mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
2575 module->get_unbox_tramp = func;
2577 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2579 bbs = g_new0 (LLVMBasicBlockRef, module->max_method_idx + 1);
2580 for (i = 0; i < module->max_method_idx + 1; ++i) {
2581 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_unbox_tramp, GINT_TO_POINTER (i));
2582 if (!m)
2583 continue;
2585 name = g_strdup_printf ("BB_%d", i);
2586 bb = LLVMAppendBasicBlock (func, name);
2587 g_free (name);
2588 bbs [i] = bb;
2590 LLVMPositionBuilderAtEnd (builder, bb);
2592 LLVMBuildRet (builder, LLVMBuildBitCast (builder, m, rtype, ""));
2595 fail_bb = LLVMAppendBasicBlock (func, "FAIL");
2596 LLVMPositionBuilderAtEnd (builder, fail_bb);
2597 LLVMBuildRet (builder, LLVMConstNull (rtype));
2599 LLVMPositionBuilderAtEnd (builder, entry_bb);
2601 switch_ins = LLVMBuildSwitch (builder, LLVMGetParam (func, 0), fail_bb, 0);
2602 for (i = 0; i < module->max_method_idx + 1; ++i) {
2603 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_unbox_tramp, GINT_TO_POINTER (i));
2604 if (!m)
2605 continue;
2607 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i, FALSE), bbs [i]);
2610 mark_as_used (module, func);
2611 LLVMDisposeBuilder (builder);
2614 /* Add a function to mark the beginning of LLVM code */
2615 static void
2616 emit_llvm_code_start (MonoLLVMModule *module)
2618 LLVMModuleRef lmodule = module->lmodule;
2619 LLVMValueRef func;
2620 LLVMBasicBlockRef entry_bb;
2621 LLVMBuilderRef builder;
2623 func = LLVMAddFunction (lmodule, "llvm_code_start", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
2624 LLVMSetLinkage (func, LLVMInternalLinkage);
2625 mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
2626 module->code_start = func;
2627 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2628 builder = LLVMCreateBuilder ();
2629 LLVMPositionBuilderAtEnd (builder, entry_bb);
2630 LLVMBuildRetVoid (builder);
2631 LLVMDisposeBuilder (builder);
2634 static LLVMValueRef
2635 emit_init_icall_wrapper (MonoLLVMModule *module, const char *name, const char *icall_name, int subtype)
2637 LLVMModuleRef lmodule = module->lmodule;
2638 LLVMValueRef func, indexes [2], got_entry_addr, args [16], callee;
2639 LLVMBasicBlockRef entry_bb;
2640 LLVMBuilderRef builder;
2641 LLVMTypeRef sig;
2642 MonoJumpInfo *ji;
2643 int got_offset;
2645 switch (subtype) {
2646 case 0:
2647 func = LLVMAddFunction (lmodule, name, LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE));
2648 sig = LLVMFunctionType2 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), FALSE);
2649 break;
2650 case 1:
2651 case 3:
2652 /* mrgctx/vtable */
2653 func = LLVMAddFunction (lmodule, name, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), IntPtrType (), FALSE));
2654 sig = LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), IntPtrType (), FALSE);
2655 break;
2656 case 2:
2657 func = LLVMAddFunction (lmodule, name, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), ObjRefType (), FALSE));
2658 sig = LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), ObjRefType (), FALSE);
2659 break;
2660 default:
2661 g_assert_not_reached ();
2663 LLVMSetLinkage (func, LLVMInternalLinkage);
2664 mono_llvm_add_func_attr (func, LLVM_ATTR_NO_INLINE);
2665 set_preserveall_cc (func);
2666 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2667 builder = LLVMCreateBuilder ();
2668 LLVMPositionBuilderAtEnd (builder, entry_bb);
2670 /* get_aotconst */
2671 ji = g_new0 (MonoJumpInfo, 1);
2672 ji->type = MONO_PATCH_INFO_AOT_MODULE;
2673 ji = mono_aot_patch_info_dup (ji);
2674 got_offset = mono_aot_get_got_offset (ji);
2675 module->max_got_offset = MAX (module->max_got_offset, got_offset);
2676 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2677 indexes [1] = LLVMConstInt (LLVMInt32Type (), got_offset, FALSE);
2678 got_entry_addr = LLVMBuildGEP (builder, module->got_var, indexes, 2, "");
2679 args [0] = LLVMBuildPtrToInt (builder, LLVMBuildLoad (builder, got_entry_addr, ""), IntPtrType (), "");
2680 args [1] = LLVMGetParam (func, 0);
2681 if (subtype)
2682 args [2] = LLVMGetParam (func, 1);
2684 ji = g_new0 (MonoJumpInfo, 1);
2685 ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
2686 ji->data.name = icall_name;
2687 ji = mono_aot_patch_info_dup (ji);
2688 got_offset = mono_aot_get_got_offset (ji);
2689 module->max_got_offset = MAX (module->max_got_offset, got_offset);
2690 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2691 indexes [1] = LLVMConstInt (LLVMInt32Type (), got_offset, FALSE);
2692 got_entry_addr = LLVMBuildGEP (builder, module->got_var, indexes, 2, "");
2693 callee = LLVMBuildLoad (builder, got_entry_addr, "");
2694 callee = LLVMBuildBitCast (builder, callee, LLVMPointerType (sig, 0), "");
2695 LLVMBuildCall (builder, callee, args, LLVMCountParamTypes (sig), "");
2697 // Set the inited flag
2698 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2699 indexes [1] = LLVMGetParam (func, 0);
2700 LLVMBuildStore (builder, LLVMConstInt (LLVMInt8Type (), 1, FALSE), LLVMBuildGEP (builder, module->inited_var, indexes, 2, ""));
2702 LLVMBuildRetVoid (builder);
2704 LLVMVerifyFunction(func, LLVMAbortProcessAction);
2705 LLVMDisposeBuilder (builder);
2706 return func;
2710 * Emit wrappers around the C icalls used to initialize llvm methods, to
2711 * make the calling code smaller and to enable usage of the llvm
2712 * PreserveAll calling convention.
2714 static void
2715 emit_init_icall_wrappers (MonoLLVMModule *module)
2717 module->init_method = emit_init_icall_wrapper (module, "init_method", "mono_aot_init_llvm_method", 0);
2718 module->init_method_gshared_mrgctx = emit_init_icall_wrapper (module, "init_method_gshared_mrgctx", "mono_aot_init_gshared_method_mrgctx", 1);
2719 module->init_method_gshared_this = emit_init_icall_wrapper (module, "init_method_gshared_this", "mono_aot_init_gshared_method_this", 2);
2720 module->init_method_gshared_vtable = emit_init_icall_wrapper (module, "init_method_gshared_vtable", "mono_aot_init_gshared_method_vtable", 3);
2723 static void
2724 emit_llvm_code_end (MonoLLVMModule *module)
2726 LLVMModuleRef lmodule = module->lmodule;
2727 LLVMValueRef func;
2728 LLVMBasicBlockRef entry_bb;
2729 LLVMBuilderRef builder;
2731 func = LLVMAddFunction (lmodule, "llvm_code_end", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
2732 LLVMSetLinkage (func, LLVMInternalLinkage);
2733 mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
2734 module->code_end = func;
2735 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2736 builder = LLVMCreateBuilder ();
2737 LLVMPositionBuilderAtEnd (builder, entry_bb);
2738 LLVMBuildRetVoid (builder);
2739 LLVMDisposeBuilder (builder);
2742 static void
2743 emit_div_check (EmitContext *ctx, LLVMBuilderRef builder, MonoBasicBlock *bb, MonoInst *ins, LLVMValueRef lhs, LLVMValueRef rhs)
2745 gboolean need_div_check = ctx->cfg->backend->need_div_check;
2747 if (bb->region)
2748 /* LLVM doesn't know that these can throw an exception since they are not called through an intrinsic */
2749 need_div_check = TRUE;
2751 if (!need_div_check)
2752 return;
2754 switch (ins->opcode) {
2755 case OP_IDIV:
2756 case OP_LDIV:
2757 case OP_IREM:
2758 case OP_LREM:
2759 case OP_IDIV_UN:
2760 case OP_LDIV_UN:
2761 case OP_IREM_UN:
2762 case OP_LREM_UN:
2763 case OP_IDIV_IMM:
2764 case OP_LDIV_IMM:
2765 case OP_IREM_IMM:
2766 case OP_LREM_IMM:
2767 case OP_IDIV_UN_IMM:
2768 case OP_LDIV_UN_IMM:
2769 case OP_IREM_UN_IMM:
2770 case OP_LREM_UN_IMM: {
2771 LLVMValueRef cmp;
2772 gboolean is_signed = (ins->opcode == OP_IDIV || ins->opcode == OP_LDIV || ins->opcode == OP_IREM || ins->opcode == OP_LREM ||
2773 ins->opcode == OP_IDIV_IMM || ins->opcode == OP_LDIV_IMM || ins->opcode == OP_IREM_IMM || ins->opcode == OP_LREM_IMM);
2775 cmp = LLVMBuildICmp (builder, LLVMIntEQ, rhs, LLVMConstInt (LLVMTypeOf (rhs), 0, FALSE), "");
2776 emit_cond_system_exception (ctx, bb, "DivideByZeroException", cmp);
2777 if (!ctx_ok (ctx))
2778 break;
2779 builder = ctx->builder;
2781 /* b == -1 && a == 0x80000000 */
2782 if (is_signed) {
2783 LLVMValueRef c = (LLVMTypeOf (lhs) == LLVMInt32Type ()) ? LLVMConstInt (LLVMTypeOf (lhs), 0x80000000, FALSE) : LLVMConstInt (LLVMTypeOf (lhs), 0x8000000000000000LL, FALSE);
2784 LLVMValueRef cond1 = LLVMBuildICmp (builder, LLVMIntEQ, rhs, LLVMConstInt (LLVMTypeOf (rhs), -1, FALSE), "");
2785 LLVMValueRef cond2 = LLVMBuildICmp (builder, LLVMIntEQ, lhs, c, "");
2787 cmp = LLVMBuildICmp (builder, LLVMIntEQ, LLVMBuildAnd (builder, cond1, cond2, ""), LLVMConstInt (LLVMInt1Type (), 1, FALSE), "");
2788 emit_cond_system_exception (ctx, bb, "OverflowException", cmp);
2789 if (!ctx_ok (ctx))
2790 break;
2791 builder = ctx->builder;
2793 break;
2795 default:
2796 break;
2801 * emit_init_method:
2803 * Emit code to initialize the GOT slots used by the method.
2805 static void
2806 emit_init_method (EmitContext *ctx)
2808 LLVMValueRef indexes [16], args [16], callee;
2809 LLVMValueRef inited_var, cmp, call;
2810 LLVMBasicBlockRef inited_bb, notinited_bb;
2811 LLVMBuilderRef builder = ctx->builder;
2812 MonoCompile *cfg = ctx->cfg;
2814 ctx->module->max_inited_idx = MAX (ctx->module->max_inited_idx, cfg->method_index);
2816 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2817 indexes [1] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, FALSE);
2818 inited_var = LLVMBuildLoad (builder, LLVMBuildGEP (builder, ctx->module->inited_var, indexes, 2, ""), "is_inited");
2820 //WASM doesn't support the "llvm.expect.i8" intrinsic
2821 #ifndef TARGET_WASM
2822 args [0] = inited_var;
2823 args [1] = LLVMConstInt (LLVMInt8Type (), 1, FALSE);
2824 inited_var = LLVMBuildCall (ctx->builder, get_intrinsic (ctx, "llvm.expect.i8"), args, 2, "");
2825 #endif
2827 cmp = LLVMBuildICmp (builder, LLVMIntEQ, inited_var, LLVMConstInt (LLVMTypeOf (inited_var), 0, FALSE), "");
2829 inited_bb = ctx->inited_bb;
2830 notinited_bb = gen_bb (ctx, "NOTINITED_BB");
2832 LLVMBuildCondBr (ctx->builder, cmp, notinited_bb, inited_bb);
2834 builder = ctx->builder = create_builder (ctx);
2835 LLVMPositionBuilderAtEnd (ctx->builder, notinited_bb);
2837 // FIXME: Cache
2838 if (ctx->rgctx_arg && cfg->method->is_inflated && mono_method_get_context (cfg->method)->method_inst) {
2839 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
2840 args [1] = convert (ctx, ctx->rgctx_arg, IntPtrType ());
2841 callee = ctx->module->init_method_gshared_mrgctx;
2842 call = LLVMBuildCall (builder, callee, args, 2, "");
2843 } else if (ctx->rgctx_arg) {
2844 /* A vtable is passed as the rgctx argument */
2845 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
2846 args [1] = convert (ctx, ctx->rgctx_arg, IntPtrType ());
2847 callee = ctx->module->init_method_gshared_vtable;
2848 call = LLVMBuildCall (builder, callee, args, 2, "");
2849 } else if (cfg->gshared) {
2850 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
2851 args [1] = convert (ctx, ctx->this_arg, ObjRefType ());
2852 callee = ctx->module->init_method_gshared_this;
2853 call = LLVMBuildCall (builder, callee, args, 2, "");
2854 } else {
2855 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
2856 callee = ctx->module->init_method;
2857 call = LLVMBuildCall (builder, callee, args, 1, "");
2861 * This enables llvm to keep arguments in their original registers/
2862 * scratch registers, since the call will not clobber them.
2864 set_call_preserveall_cc (call);
2866 LLVMBuildBr (builder, inited_bb);
2867 ctx->bblocks [cfg->bb_entry->block_num].end_bblock = inited_bb;
2869 builder = ctx->builder = create_builder (ctx);
2870 LLVMPositionBuilderAtEnd (ctx->builder, inited_bb);
2873 static void
2874 emit_unbox_tramp (EmitContext *ctx, const char *method_name, LLVMTypeRef method_type, LLVMValueRef method, int method_index)
2877 * Emit unbox trampoline using a tailcall
2879 LLVMValueRef tramp, call, *args;
2880 LLVMBuilderRef builder;
2881 LLVMBasicBlockRef lbb;
2882 LLVMCallInfo *linfo;
2883 char *tramp_name;
2884 int i, nargs;
2886 tramp_name = g_strdup_printf ("ut_%s", method_name);
2887 tramp = LLVMAddFunction (ctx->module->lmodule, tramp_name, method_type);
2888 LLVMSetLinkage (tramp, LLVMInternalLinkage);
2889 mono_llvm_add_func_attr (tramp, LLVM_ATTR_OPTIMIZE_FOR_SIZE);
2890 //mono_llvm_add_func_attr (tramp, LLVM_ATTR_NO_UNWIND);
2891 linfo = ctx->linfo;
2892 // FIXME: Reduce code duplication with mono_llvm_compile_method () etc.
2893 if (!ctx->llvm_only && ctx->rgctx_arg_pindex != -1)
2894 mono_llvm_add_param_attr (LLVMGetParam (tramp, ctx->rgctx_arg_pindex), LLVM_ATTR_IN_REG);
2895 if (ctx->cfg->vret_addr) {
2896 LLVMSetValueName (LLVMGetParam (tramp, linfo->vret_arg_pindex), "vret");
2897 if (linfo->ret.storage == LLVMArgVtypeByRef) {
2898 mono_llvm_add_param_attr (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVM_ATTR_STRUCT_RET);
2899 mono_llvm_add_param_attr (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVM_ATTR_NO_ALIAS);
2903 lbb = LLVMAppendBasicBlock (tramp, "");
2904 builder = LLVMCreateBuilder ();
2905 LLVMPositionBuilderAtEnd (builder, lbb);
2907 nargs = LLVMCountParamTypes (method_type);
2908 args = g_new0 (LLVMValueRef, nargs);
2909 for (i = 0; i < nargs; ++i) {
2910 args [i] = LLVMGetParam (tramp, i);
2911 if (i == ctx->this_arg_pindex) {
2912 LLVMTypeRef arg_type = LLVMTypeOf (args [i]);
2914 args [i] = LLVMBuildPtrToInt (builder, args [i], IntPtrType (), "");
2915 args [i] = LLVMBuildAdd (builder, args [i], LLVMConstInt (IntPtrType (), MONO_ABI_SIZEOF (MonoObject), FALSE), "");
2916 args [i] = LLVMBuildIntToPtr (builder, args [i], arg_type, "");
2919 call = LLVMBuildCall (builder, method, args, nargs, "");
2920 if (!ctx->llvm_only && ctx->rgctx_arg_pindex != -1)
2921 mono_llvm_add_instr_attr (call, 1 + ctx->rgctx_arg_pindex, LLVM_ATTR_IN_REG);
2922 if (linfo->ret.storage == LLVMArgVtypeByRef)
2923 mono_llvm_add_instr_attr (call, 1 + linfo->vret_arg_pindex, LLVM_ATTR_STRUCT_RET);
2925 // FIXME: This causes assertions in clang
2926 //mono_llvm_set_must_tailcall (call);
2927 if (LLVMGetReturnType (method_type) == LLVMVoidType ())
2928 LLVMBuildRetVoid (builder);
2929 else
2930 LLVMBuildRet (builder, call);
2932 g_hash_table_insert (ctx->module->idx_to_unbox_tramp, GINT_TO_POINTER (method_index), tramp);
2933 LLVMDisposeBuilder (builder);
2937 * emit_entry_bb:
2939 * Emit code to load/convert arguments.
2941 static void
2942 emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
2944 int i, j, pindex;
2945 MonoCompile *cfg = ctx->cfg;
2946 MonoMethodSignature *sig = ctx->sig;
2947 LLVMCallInfo *linfo = ctx->linfo;
2948 MonoBasicBlock *bb;
2949 char **names;
2951 LLVMBuilderRef old_builder = ctx->builder;
2952 ctx->builder = builder;
2954 ctx->alloca_builder = create_builder (ctx);
2957 * Handle indirect/volatile variables by allocating memory for them
2958 * using 'alloca', and storing their address in a temporary.
2960 for (i = 0; i < cfg->num_varinfo; ++i) {
2961 MonoInst *var = cfg->varinfo [i];
2962 LLVMTypeRef vtype;
2964 if (var->opcode == OP_GSHAREDVT_LOCAL || var->opcode == OP_GSHAREDVT_ARG_REGOFFSET) {
2965 } 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))) {
2966 vtype = type_to_llvm_type (ctx, var->inst_vtype);
2967 if (!ctx_ok (ctx))
2968 return;
2969 /* Could be already created by an OP_VPHI */
2970 if (!ctx->addresses [var->dreg]) {
2971 ctx->addresses [var->dreg] = build_alloca (ctx, var->inst_vtype);
2972 //LLVMSetValueName (ctx->addresses [var->dreg], g_strdup_printf ("vreg_loc_%d", var->dreg));
2974 ctx->vreg_cli_types [var->dreg] = var->inst_vtype;
2978 names = g_new (char *, sig->param_count);
2979 mono_method_get_param_names (cfg->method, (const char **) names);
2981 for (i = 0; i < sig->param_count; ++i) {
2982 LLVMArgInfo *ainfo = &linfo->args [i + sig->hasthis];
2983 int reg = cfg->args [i + sig->hasthis]->dreg;
2984 char *name;
2986 pindex = ainfo->pindex;
2988 switch (ainfo->storage) {
2989 case LLVMArgVtypeInReg:
2990 case LLVMArgAsFpArgs: {
2991 LLVMValueRef args [8];
2992 int j;
2994 pindex += ainfo->ndummy_fpargs;
2996 /* The argument is received as a set of int/fp arguments, store them into the real argument */
2997 memset (args, 0, sizeof (args));
2998 if (ainfo->storage == LLVMArgVtypeInReg) {
2999 args [0] = LLVMGetParam (ctx->lmethod, pindex);
3000 if (ainfo->pair_storage [1] != LLVMArgNone)
3001 args [1] = LLVMGetParam (ctx->lmethod, pindex + 1);
3002 } else {
3003 g_assert (ainfo->nslots <= 8);
3004 for (j = 0; j < ainfo->nslots; ++j)
3005 args [j] = LLVMGetParam (ctx->lmethod, pindex + j);
3007 ctx->addresses [reg] = build_alloca (ctx, ainfo->type);
3009 emit_args_to_vtype (ctx, builder, ainfo->type, ctx->addresses [reg], ainfo, args);
3011 if (ainfo->storage == LLVMArgVtypeInReg && MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (ainfo->type))) {
3012 /* Treat these as normal values */
3013 ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "");
3015 break;
3017 case LLVMArgVtypeByVal: {
3018 ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindex);
3020 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (ainfo->type))) {
3021 /* Treat these as normal values */
3022 ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "");
3024 break;
3026 case LLVMArgVtypeByRef: {
3027 /* The argument is passed by ref */
3028 ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindex);
3029 break;
3031 case LLVMArgAsIArgs: {
3032 LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
3033 int size;
3035 /* The argument is received as an array of ints, store it into the real argument */
3036 ctx->addresses [reg] = build_alloca (ctx, ainfo->type);
3038 size = mono_class_value_size (mono_class_from_mono_type_internal (ainfo->type), NULL);
3039 if (size == 0) {
3040 } else if (size < TARGET_SIZEOF_VOID_P) {
3041 /* The upper bits of the registers might not be valid */
3042 LLVMValueRef val = LLVMBuildExtractValue (builder, arg, 0, "");
3043 LLVMValueRef dest = convert (ctx, ctx->addresses [reg], LLVMPointerType (LLVMIntType (size * 8), 0));
3044 LLVMBuildStore (ctx->builder, LLVMBuildTrunc (builder, val, LLVMIntType (size * 8), ""), dest);
3045 } else {
3046 LLVMBuildStore (ctx->builder, arg, convert (ctx, ctx->addresses [reg], LLVMPointerType (LLVMTypeOf (arg), 0)));
3048 break;
3050 case LLVMArgVtypeAsScalar:
3051 g_assert_not_reached ();
3052 break;
3053 case LLVMArgGsharedvtFixed: {
3054 /* These are non-gsharedvt arguments passed by ref, the rest of the IR treats them as scalars */
3055 LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
3057 if (names [i])
3058 name = g_strdup_printf ("arg_%s", names [i]);
3059 else
3060 name = g_strdup_printf ("arg_%d", i);
3062 ctx->values [reg] = LLVMBuildLoad (builder, convert (ctx, arg, LLVMPointerType (type_to_llvm_type (ctx, ainfo->type), 0)), name);
3063 break;
3065 case LLVMArgGsharedvtFixedVtype: {
3066 LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
3068 if (names [i])
3069 name = g_strdup_printf ("vtype_arg_%s", names [i]);
3070 else
3071 name = g_strdup_printf ("vtype_arg_%d", i);
3073 /* Non-gsharedvt vtype argument passed by ref, the rest of the IR treats it as a vtype */
3074 g_assert (ctx->addresses [reg]);
3075 LLVMSetValueName (ctx->addresses [reg], name);
3076 LLVMBuildStore (builder, LLVMBuildLoad (builder, convert (ctx, arg, LLVMPointerType (type_to_llvm_type (ctx, ainfo->type), 0)), ""), ctx->addresses [reg]);
3077 break;
3079 case LLVMArgGsharedvtVariable:
3080 /* The IR treats these as variables with addresses */
3081 ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindex);
3082 break;
3083 default:
3084 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));
3085 break;
3088 g_free (names);
3090 if (cfg->vret_addr)
3091 emit_volatile_store (ctx, cfg->vret_addr->dreg);
3092 if (sig->hasthis)
3093 emit_volatile_store (ctx, cfg->args [0]->dreg);
3094 for (i = 0; i < sig->param_count; ++i)
3095 if (!mini_type_is_vtype (sig->params [i]))
3096 emit_volatile_store (ctx, cfg->args [i + sig->hasthis]->dreg);
3098 if (sig->hasthis && !cfg->rgctx_var && cfg->gshared) {
3099 LLVMValueRef this_alloc;
3102 * The exception handling code needs the location where the this argument was
3103 * stored for gshared methods. We create a separate alloca to hold it, and mark it
3104 * with the "mono.this" custom metadata to tell llvm that it needs to save its
3105 * location into the LSDA.
3107 this_alloc = mono_llvm_build_alloca (builder, ThisType (), LLVMConstInt (LLVMInt32Type (), 1, FALSE), 0, "");
3108 /* This volatile store will keep the alloca alive */
3109 mono_llvm_build_store (builder, ctx->values [cfg->args [0]->dreg], this_alloc, TRUE, LLVM_BARRIER_NONE);
3111 set_metadata_flag (this_alloc, "mono.this");
3114 if (cfg->rgctx_var) {
3115 LLVMValueRef rgctx_alloc, store;
3118 * We handle the rgctx arg similarly to the this pointer.
3120 g_assert (ctx->addresses [cfg->rgctx_var->dreg]);
3121 rgctx_alloc = ctx->addresses [cfg->rgctx_var->dreg];
3122 /* This volatile store will keep the alloca alive */
3123 store = mono_llvm_build_store (builder, convert (ctx, ctx->rgctx_arg, IntPtrType ()), rgctx_alloc, TRUE, LLVM_BARRIER_NONE);
3125 set_metadata_flag (rgctx_alloc, "mono.this");
3128 /* Initialize the method if needed */
3129 if (cfg->compile_aot && ctx->llvm_only) {
3130 /* Emit a location for the initialization code */
3131 ctx->init_bb = gen_bb (ctx, "INIT_BB");
3132 ctx->inited_bb = gen_bb (ctx, "INITED_BB");
3134 LLVMBuildBr (ctx->builder, ctx->init_bb);
3135 builder = ctx->builder = create_builder (ctx);
3136 LLVMPositionBuilderAtEnd (ctx->builder, ctx->inited_bb);
3137 ctx->bblocks [cfg->bb_entry->block_num].end_bblock = ctx->inited_bb;
3140 /* Compute nesting between clauses */
3141 ctx->nested_in = (GSList**)mono_mempool_alloc0 (cfg->mempool, sizeof (GSList*) * cfg->header->num_clauses);
3142 for (i = 0; i < cfg->header->num_clauses; ++i) {
3143 for (j = 0; j < cfg->header->num_clauses; ++j) {
3144 MonoExceptionClause *clause1 = &cfg->header->clauses [i];
3145 MonoExceptionClause *clause2 = &cfg->header->clauses [j];
3147 if (i != j && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset)
3148 ctx->nested_in [i] = g_slist_prepend_mempool (cfg->mempool, ctx->nested_in [i], GINT_TO_POINTER (j));
3153 * For finally clauses, create an indicator variable telling OP_ENDFINALLY whenever
3154 * it needs to continue normally, or return back to the exception handling system.
3156 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3157 int clause_index;
3158 char name [128];
3160 if (!(bb->region != -1 && (bb->flags & BB_EXCEPTION_HANDLER)))
3161 continue;
3163 clause_index = MONO_REGION_CLAUSE_INDEX (bb->region);
3164 g_hash_table_insert (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)), bb);
3165 g_hash_table_insert (ctx->clause_to_handler, GINT_TO_POINTER (clause_index), bb);
3167 if (bb->in_scount == 0) {
3168 LLVMValueRef val;
3170 sprintf (name, "finally_ind_bb%d", bb->block_num);
3171 val = LLVMBuildAlloca (builder, LLVMInt32Type (), name);
3172 LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), val);
3174 ctx->bblocks [bb->block_num].finally_ind = val;
3175 } else {
3176 /* Create a variable to hold the exception var */
3177 if (!ctx->ex_var)
3178 ctx->ex_var = LLVMBuildAlloca (builder, ObjRefType (), "exvar");
3182 * Create a new bblock which CALL_HANDLER/landing pads can branch to, because branching to the
3183 * LLVM bblock containing a landing pad causes problems for the
3184 * LLVM optimizer passes.
3186 sprintf (name, "BB%d_CALL_HANDLER_TARGET", bb->block_num);
3187 ctx->bblocks [bb->block_num].call_handler_target_bb = LLVMAppendBasicBlock (ctx->lmethod, name);
3189 ctx->builder = old_builder;
3192 static gboolean
3193 needs_extra_arg (EmitContext *ctx, MonoMethod *method)
3195 WrapperInfo *info = NULL;
3198 * When targeting wasm, the caller and callee signature has to match exactly. This means
3199 * that every method which can be called indirectly need an extra arg since the caller
3200 * will call it through an ftnptr and will pass an extra arg.
3202 if (!ctx->cfg->llvm_only || !ctx->emit_dummy_arg)
3203 return FALSE;
3204 if (method->wrapper_type)
3205 info = mono_marshal_get_wrapper_info (method);
3207 switch (method->wrapper_type) {
3208 case MONO_WRAPPER_UNKNOWN:
3209 if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG || info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG)
3210 /* Already have an explicit extra arg */
3211 return FALSE;
3212 break;
3213 case MONO_WRAPPER_MANAGED_TO_NATIVE:
3214 if (strstr (method->name, "icall_wrapper"))
3215 /* These are JIT icall wrappers which are only called from JITted code directly */
3216 return FALSE;
3217 /* Normal icalls can be virtual methods which need an extra arg */
3218 break;
3219 case MONO_WRAPPER_RUNTIME_INVOKE:
3220 case MONO_WRAPPER_ALLOC:
3221 case MONO_WRAPPER_CASTCLASS:
3222 case MONO_WRAPPER_WRITE_BARRIER:
3223 return FALSE;
3224 case MONO_WRAPPER_STELEMREF:
3225 if (info->subtype != WRAPPER_SUBTYPE_VIRTUAL_STELEMREF)
3226 return FALSE;
3227 break;
3228 case MONO_WRAPPER_MANAGED_TO_MANAGED:
3229 if (info->subtype == WRAPPER_SUBTYPE_STRING_CTOR)
3230 return FALSE;
3231 break;
3232 default:
3233 break;
3235 if (method->string_ctor)
3236 return FALSE;
3238 /* These are called from gsharedvt code with an indirect call which doesn't pass an extra arg */
3239 if (method->klass == mono_get_string_class () && (strstr (method->name, "memcpy") || strstr (method->name, "bzero")))
3240 return FALSE;
3241 return TRUE;
3244 static void
3245 process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, MonoInst *ins)
3247 MonoCompile *cfg = ctx->cfg;
3248 LLVMValueRef *values = ctx->values;
3249 LLVMValueRef *addresses = ctx->addresses;
3250 MonoCallInst *call = (MonoCallInst*)ins;
3251 MonoMethodSignature *sig = call->signature;
3252 LLVMValueRef callee = NULL, lcall;
3253 LLVMValueRef *args;
3254 LLVMCallInfo *cinfo;
3255 GSList *l;
3256 int i, len, nargs;
3257 gboolean vretaddr;
3258 LLVMTypeRef llvm_sig;
3259 gpointer target;
3260 gboolean is_virtual, calli, preserveall;
3261 LLVMBuilderRef builder = *builder_ref;
3263 /* If both imt and rgctx arg are required, only pass the imt arg, the rgctx trampoline will pass the rgctx */
3264 if (call->imt_arg_reg)
3265 call->rgctx_arg_reg = 0;
3267 if ((call->signature->call_convention != MONO_CALL_DEFAULT) && !((call->signature->call_convention == MONO_CALL_C) && ctx->llvm_only)) {
3268 set_failure (ctx, "non-default callconv");
3269 return;
3272 cinfo = call->cinfo;
3273 g_assert (cinfo);
3274 if (call->rgctx_arg_reg)
3275 cinfo->rgctx_arg = TRUE;
3276 if (call->imt_arg_reg)
3277 cinfo->imt_arg = TRUE;
3278 if (call->method && needs_extra_arg (ctx, call->method))
3279 cinfo->dummy_arg = TRUE;
3281 vretaddr = (cinfo->ret.storage == LLVMArgVtypeRetAddr || cinfo->ret.storage == LLVMArgVtypeByRef || cinfo->ret.storage == LLVMArgGsharedvtFixed || cinfo->ret.storage == LLVMArgGsharedvtVariable || cinfo->ret.storage == LLVMArgGsharedvtFixedVtype);
3283 llvm_sig = sig_to_llvm_sig_full (ctx, sig, cinfo);
3284 if (!ctx_ok (ctx))
3285 return;
3287 int const opcode = ins->opcode;
3289 is_virtual = opcode == OP_VOIDCALL_MEMBASE || opcode == OP_CALL_MEMBASE
3290 || opcode == OP_VCALL_MEMBASE || opcode == OP_LCALL_MEMBASE
3291 || opcode == OP_FCALL_MEMBASE || opcode == OP_RCALL_MEMBASE
3292 || opcode == OP_TAILCALL_MEMBASE;
3293 calli = !call->fptr_is_patch && (opcode == OP_VOIDCALL_REG || opcode == OP_CALL_REG
3294 || opcode == OP_VCALL_REG || opcode == OP_LCALL_REG || opcode == OP_FCALL_REG
3295 || opcode == OP_RCALL_REG || opcode == OP_TAILCALL_REG);
3297 /* Unused */
3298 preserveall = FALSE;
3300 /* FIXME: Avoid creating duplicate methods */
3302 if (ins->flags & MONO_INST_HAS_METHOD) {
3303 if (is_virtual) {
3304 callee = NULL;
3305 } else {
3306 if (cfg->compile_aot) {
3307 callee = get_callee (ctx, llvm_sig, MONO_PATCH_INFO_METHOD, call->method);
3308 if (!callee) {
3309 set_failure (ctx, "can't encode patch");
3310 return;
3312 if (cfg->llvm_only && m_class_get_image (call->method->klass)->assembly == ctx->module->assembly) {
3314 * Collect instructions representing the callee into a hash so they can be replaced
3315 * by the llvm method for the callee if the callee turns out to be direct
3316 * callable. Currently this only requires it to not fail llvm compilation.
3318 GSList *l = (GSList*)g_hash_table_lookup (ctx->method_to_callers, call->method);
3319 l = g_slist_prepend (l, callee);
3320 g_hash_table_insert (ctx->method_to_callers, call->method, l);
3322 } else {
3323 ERROR_DECL (error);
3324 static int tramp_index;
3325 char *name;
3327 name = g_strdup_printf ("tramp_%d", tramp_index);
3328 tramp_index ++;
3330 #if LLVM_API_VERSION > 100
3332 * Use our trampoline infrastructure for lazy compilation instead of llvm's.
3333 * Make all calls through a global. The address of the global will be saved in
3334 * MonoJitDomainInfo.llvm_jit_callees and updated when the method it refers to is
3335 * compiled.
3337 LLVMValueRef tramp_var = (LLVMValueRef)g_hash_table_lookup (ctx->jit_callees, call->method);
3338 if (!tramp_var) {
3339 target =
3340 mono_create_jit_trampoline (mono_domain_get (),
3341 call->method, error);
3342 if (!is_ok (error)) {
3343 set_failure (ctx, mono_error_get_message (error));
3344 mono_error_cleanup (error);
3345 return;
3348 tramp_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (llvm_sig, 0), name);
3349 LLVMSetInitializer (tramp_var, LLVMConstIntToPtr (LLVMConstInt (LLVMInt64Type (), (guint64)(size_t)target, FALSE), LLVMPointerType (llvm_sig, 0)));
3350 LLVMSetLinkage (tramp_var, LLVMExternalLinkage);
3351 g_hash_table_insert (ctx->jit_callees, call->method, tramp_var);
3353 callee = LLVMBuildLoad (builder, tramp_var, "");
3354 #else
3355 target =
3356 mono_create_jit_trampoline (mono_domain_get (),
3357 call->method, error);
3358 if (!is_ok (error)) {
3359 g_free (name);
3360 set_failure (ctx, mono_error_get_message (error));
3361 mono_error_cleanup (error);
3362 return;
3365 callee = LLVMAddFunction (ctx->lmodule, name, llvm_sig);
3366 g_free (name);
3368 LLVMAddGlobalMapping (ctx->module->ee, callee, target);
3369 #endif
3373 if (!cfg->llvm_only && call->method && strstr (m_class_get_name (call->method->klass), "AsyncVoidMethodBuilder")) {
3374 /* LLVM miscompiles async methods */
3375 set_failure (ctx, "#13734");
3376 return;
3378 } else if (calli) {
3379 } else {
3380 MonoJitICallInfo *info = mono_find_jit_icall_by_addr (call->fptr);
3382 if (info) {
3384 MonoJumpInfo ji;
3386 memset (&ji, 0, sizeof (ji));
3387 ji.type = MONO_PATCH_INFO_JIT_ICALL_ADDR;
3388 ji.data.target = info->name;
3390 target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, &ji, FALSE);
3392 if (cfg->compile_aot) {
3393 callee = get_callee (ctx, llvm_sig, MONO_PATCH_INFO_INTERNAL_METHOD, (char*)info->name);
3394 if (!callee) {
3395 set_failure (ctx, "can't encode patch");
3396 return;
3398 } else {
3399 target = (gpointer)mono_icall_get_wrapper (info);
3400 callee = emit_jit_callee (ctx, "", llvm_sig, target);
3402 } else {
3403 if (cfg->compile_aot) {
3404 callee = NULL;
3405 if (cfg->abs_patches) {
3406 MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
3407 if (abs_ji) {
3408 callee = get_callee (ctx, llvm_sig, abs_ji->type, abs_ji->data.target);
3409 if (!callee) {
3410 set_failure (ctx, "can't encode patch");
3411 return;
3415 if (!callee) {
3416 set_failure (ctx, "aot");
3417 return;
3419 } else {
3420 #if LLVM_API_VERSION > 100
3421 if (cfg->abs_patches) {
3422 MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
3423 if (abs_ji) {
3424 ERROR_DECL (error);
3426 target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, abs_ji, FALSE, error);
3427 mono_error_assert_ok (error);
3428 callee = emit_jit_callee (ctx, "", llvm_sig, target);
3429 } else {
3430 g_assert_not_reached ();
3432 } else {
3433 g_assert_not_reached ();
3435 #else
3436 callee = LLVMAddFunction (ctx->lmodule, "", llvm_sig);
3437 target = NULL;
3438 if (cfg->abs_patches) {
3439 MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
3440 if (abs_ji) {
3441 ERROR_DECL (error);
3444 * FIXME: Some trampolines might have
3445 * their own calling convention on some platforms.
3447 target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, abs_ji, FALSE, error);
3448 mono_error_assert_ok (error);
3449 LLVMAddGlobalMapping (ctx->module->ee, callee, target);
3452 if (!target)
3453 LLVMAddGlobalMapping (ctx->module->ee, callee, (gpointer)call->fptr);
3454 #endif
3459 if (is_virtual) {
3460 int size = sizeof (gpointer);
3461 LLVMValueRef index;
3463 g_assert (ins->inst_offset % size == 0);
3464 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
3466 callee = convert (ctx, LLVMBuildLoad (builder, LLVMBuildGEP (builder, convert (ctx, values [ins->inst_basereg], LLVMPointerType (LLVMPointerType (IntPtrType (), 0), 0)), &index, 1, ""), ""), LLVMPointerType (llvm_sig, 0));
3467 } else if (calli) {
3468 callee = convert (ctx, values [ins->sreg1], LLVMPointerType (llvm_sig, 0));
3469 } else {
3470 if (ins->flags & MONO_INST_HAS_METHOD) {
3475 * Collect and convert arguments
3477 nargs = (sig->param_count * 16) + sig->hasthis + vretaddr + call->rgctx_reg + call->imt_arg_reg + 1;
3478 len = sizeof (LLVMValueRef) * nargs;
3479 args = g_newa (LLVMValueRef, nargs);
3480 memset (args, 0, len);
3481 l = call->out_ireg_args;
3483 if (call->rgctx_arg_reg) {
3484 g_assert (values [call->rgctx_arg_reg]);
3485 g_assert (cinfo->rgctx_arg_pindex < nargs);
3487 * On ARM, the imt/rgctx argument is passed in a caller save register, but some of our trampolines etc. clobber it, leading to
3488 * problems is LLVM moves the arg assignment earlier. To work around this, save the argument into a stack slot and load
3489 * it using a volatile load.
3491 #ifdef TARGET_ARM
3492 if (!ctx->imt_rgctx_loc)
3493 ctx->imt_rgctx_loc = build_alloca_llvm_type (ctx, ctx->module->ptr_type, sizeof (gpointer));
3494 LLVMBuildStore (builder, convert (ctx, ctx->values [call->rgctx_arg_reg], ctx->module->ptr_type), ctx->imt_rgctx_loc);
3495 args [cinfo->rgctx_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE);
3496 #else
3497 args [cinfo->rgctx_arg_pindex] = convert (ctx, values [call->rgctx_arg_reg], ctx->module->ptr_type);
3498 #endif
3500 if (call->imt_arg_reg) {
3501 g_assert (!ctx->llvm_only);
3502 g_assert (values [call->imt_arg_reg]);
3503 g_assert (cinfo->imt_arg_pindex < nargs);
3504 #ifdef TARGET_ARM
3505 if (!ctx->imt_rgctx_loc)
3506 ctx->imt_rgctx_loc = build_alloca_llvm_type (ctx, ctx->module->ptr_type, sizeof (gpointer));
3507 LLVMBuildStore (builder, convert (ctx, ctx->values [call->imt_arg_reg], ctx->module->ptr_type), ctx->imt_rgctx_loc);
3508 args [cinfo->imt_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE);
3509 #else
3510 args [cinfo->imt_arg_pindex] = convert (ctx, values [call->imt_arg_reg], ctx->module->ptr_type);
3511 #endif
3513 switch (cinfo->ret.storage) {
3514 case LLVMArgGsharedvtVariable: {
3515 MonoInst *var = get_vreg_to_inst (cfg, call->inst.dreg);
3517 if (var && var->opcode == OP_GSHAREDVT_LOCAL) {
3518 args [cinfo->vret_arg_pindex] = convert (ctx, emit_gsharedvt_ldaddr (ctx, var->dreg), IntPtrType ());
3519 } else {
3520 g_assert (addresses [call->inst.dreg]);
3521 args [cinfo->vret_arg_pindex] = convert (ctx, addresses [call->inst.dreg], IntPtrType ());
3523 break;
3525 default:
3526 if (vretaddr) {
3527 if (!addresses [call->inst.dreg])
3528 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3529 g_assert (cinfo->vret_arg_pindex < nargs);
3530 if (cinfo->ret.storage == LLVMArgVtypeByRef)
3531 args [cinfo->vret_arg_pindex] = addresses [call->inst.dreg];
3532 else
3533 args [cinfo->vret_arg_pindex] = LLVMBuildPtrToInt (builder, addresses [call->inst.dreg], IntPtrType (), "");
3535 break;
3539 * Sometimes the same method is called with two different signatures (i.e. with and without 'this'), so
3540 * use the real callee for argument type conversion.
3542 LLVMTypeRef callee_type = LLVMGetElementType (LLVMTypeOf (callee));
3543 LLVMTypeRef *param_types = (LLVMTypeRef*)g_alloca (sizeof (LLVMTypeRef) * LLVMCountParamTypes (callee_type));
3544 LLVMGetParamTypes (callee_type, param_types);
3546 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
3547 guint32 regpair;
3548 int reg, pindex;
3549 LLVMArgInfo *ainfo = &call->cinfo->args [i];
3551 pindex = ainfo->pindex;
3553 regpair = (guint32)(gssize)(l->data);
3554 reg = regpair & 0xffffff;
3555 args [pindex] = values [reg];
3556 switch (ainfo->storage) {
3557 case LLVMArgVtypeInReg:
3558 case LLVMArgAsFpArgs: {
3559 guint32 nargs;
3560 int j;
3562 for (j = 0; j < ainfo->ndummy_fpargs; ++j)
3563 args [pindex + j] = LLVMConstNull (LLVMDoubleType ());
3564 pindex += ainfo->ndummy_fpargs;
3566 g_assert (addresses [reg]);
3567 emit_vtype_to_args (ctx, builder, ainfo->type, addresses [reg], ainfo, args + pindex, &nargs);
3568 pindex += nargs;
3570 // FIXME: alignment
3571 // FIXME: Get rid of the VMOVE
3572 break;
3574 case LLVMArgVtypeByVal:
3575 g_assert (addresses [reg]);
3576 args [pindex] = addresses [reg];
3577 break;
3578 case LLVMArgVtypeByRef: {
3579 g_assert (addresses [reg]);
3580 args [pindex] = convert (ctx, addresses [reg], LLVMPointerType (type_to_llvm_arg_type (ctx, ainfo->type), 0));
3581 break;
3583 case LLVMArgAsIArgs:
3584 g_assert (addresses [reg]);
3585 if (ainfo->esize == 8)
3586 args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (LLVMInt64Type (), ainfo->nslots), 0)), "");
3587 else
3588 args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo->nslots), 0)), "");
3589 break;
3590 case LLVMArgVtypeAsScalar:
3591 g_assert_not_reached ();
3592 break;
3593 case LLVMArgGsharedvtFixed:
3594 case LLVMArgGsharedvtFixedVtype:
3595 g_assert (addresses [reg]);
3596 args [pindex] = convert (ctx, addresses [reg], LLVMPointerType (type_to_llvm_arg_type (ctx, ainfo->type), 0));
3597 break;
3598 case LLVMArgGsharedvtVariable:
3599 g_assert (addresses [reg]);
3600 args [pindex] = convert (ctx, addresses [reg], LLVMPointerType (IntPtrType (), 0));
3601 break;
3602 default:
3603 g_assert (args [pindex]);
3604 if (i == 0 && sig->hasthis)
3605 args [pindex] = convert (ctx, args [pindex], param_types [pindex]);
3606 else
3607 args [pindex] = convert (ctx, args [pindex], type_to_llvm_arg_type (ctx, ainfo->type));
3608 break;
3610 g_assert (pindex <= nargs);
3612 l = l->next;
3614 if (call->cinfo->dummy_arg)
3615 args [call->cinfo->dummy_arg_pindex] = LLVMConstNull (ctx->module->ptr_type);
3617 // FIXME: Align call sites
3620 * Emit the call
3622 lcall = emit_call (ctx, bb, &builder, callee, args, LLVMCountParamTypes (llvm_sig));
3624 if (ins->opcode != OP_TAILCALL && ins->opcode != OP_TAILCALL_MEMBASE && LLVMGetInstructionOpcode (lcall) == LLVMCall)
3625 mono_llvm_set_call_notailcall (lcall);
3628 * Modify cconv and parameter attributes to pass rgctx/imt correctly.
3630 #if defined(MONO_ARCH_IMT_REG) && defined(MONO_ARCH_RGCTX_REG)
3631 g_assert (MONO_ARCH_IMT_REG == MONO_ARCH_RGCTX_REG);
3632 #endif
3633 /* The two can't be used together, so use only one LLVM calling conv to pass them */
3634 g_assert (!(call->rgctx_arg_reg && call->imt_arg_reg));
3635 if (!sig->pinvoke && !cfg->llvm_only)
3636 LLVMSetInstructionCallConv (lcall, LLVMMono1CallConv);
3637 if (preserveall)
3638 set_call_preserveall_cc (lcall);
3640 if (cinfo->ret.storage == LLVMArgVtypeByRef)
3641 mono_llvm_add_instr_attr (lcall, 1 + cinfo->vret_arg_pindex, LLVM_ATTR_STRUCT_RET);
3642 if (!ctx->llvm_only && call->rgctx_arg_reg)
3643 mono_llvm_add_instr_attr (lcall, 1 + cinfo->rgctx_arg_pindex, LLVM_ATTR_IN_REG);
3644 if (call->imt_arg_reg)
3645 mono_llvm_add_instr_attr (lcall, 1 + cinfo->imt_arg_pindex, LLVM_ATTR_IN_REG);
3647 /* Add byval attributes if needed */
3648 for (i = 0; i < sig->param_count; ++i) {
3649 LLVMArgInfo *ainfo = &call->cinfo->args [i + sig->hasthis];
3651 if (ainfo && ainfo->storage == LLVMArgVtypeByVal)
3652 mono_llvm_add_instr_attr (lcall, 1 + ainfo->pindex, LLVM_ATTR_BY_VAL);
3656 * Convert the result
3658 switch (cinfo->ret.storage) {
3659 case LLVMArgVtypeInReg: {
3660 LLVMValueRef regs [2];
3662 if (LLVMTypeOf (lcall) == LLVMVoidType ())
3663 /* Empty struct */
3664 break;
3666 if (!addresses [ins->dreg])
3667 addresses [ins->dreg] = build_alloca (ctx, sig->ret);
3669 regs [0] = LLVMBuildExtractValue (builder, lcall, 0, "");
3670 if (cinfo->ret.pair_storage [1] != LLVMArgNone)
3671 regs [1] = LLVMBuildExtractValue (builder, lcall, 1, "");
3672 emit_args_to_vtype (ctx, builder, sig->ret, addresses [ins->dreg], &cinfo->ret, regs);
3673 break;
3675 case LLVMArgVtypeByVal:
3676 if (!addresses [call->inst.dreg])
3677 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3678 LLVMBuildStore (builder, lcall, addresses [call->inst.dreg]);
3679 break;
3680 case LLVMArgAsIArgs:
3681 case LLVMArgFpStruct:
3682 if (!addresses [call->inst.dreg])
3683 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3684 LLVMBuildStore (builder, lcall, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (LLVMTypeOf (lcall), 0), FALSE));
3685 break;
3686 case LLVMArgVtypeAsScalar:
3687 if (!addresses [call->inst.dreg])
3688 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3689 LLVMBuildStore (builder, lcall, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (LLVMTypeOf (lcall), 0), FALSE));
3690 break;
3691 case LLVMArgVtypeRetAddr:
3692 case LLVMArgVtypeByRef:
3693 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (sig->ret))) {
3694 /* Some opcodes like STOREX_MEMBASE access these by value */
3695 g_assert (addresses [call->inst.dreg]);
3696 values [ins->dreg] = LLVMBuildLoad (builder, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (type_to_llvm_type (ctx, sig->ret), 0), FALSE), "");
3698 break;
3699 case LLVMArgGsharedvtVariable:
3700 break;
3701 case LLVMArgGsharedvtFixed:
3702 case LLVMArgGsharedvtFixedVtype:
3703 values [ins->dreg] = LLVMBuildLoad (builder, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (type_to_llvm_type (ctx, sig->ret), 0), FALSE), "");
3704 break;
3705 default:
3706 if (sig->ret->type != MONO_TYPE_VOID)
3707 /* If the method returns an unsigned value, need to zext it */
3708 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));
3709 break;
3712 *builder_ref = ctx->builder;
3715 static void
3716 emit_llvmonly_throw (EmitContext *ctx, MonoBasicBlock *bb, gboolean rethrow, LLVMValueRef exc)
3718 const char *icall_name = rethrow ? "mono_llvm_rethrow_exception" : "mono_llvm_throw_exception";
3719 LLVMValueRef callee = rethrow ? ctx->module->rethrow : ctx->module->throw_icall;
3721 LLVMTypeRef exc_type = type_to_llvm_type (ctx, m_class_get_byval_arg (mono_get_exception_class ()));
3723 if (!callee) {
3724 LLVMTypeRef fun_sig = LLVMFunctionType1 (LLVMVoidType (), exc_type, FALSE);
3726 if (ctx->cfg->compile_aot) {
3727 callee = get_callee (ctx, fun_sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, icall_name);
3728 } else {
3729 callee = LLVMAddFunction (ctx->lmodule, icall_name, fun_sig);
3730 LLVMAddGlobalMapping (ctx->module->ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
3731 mono_memory_barrier ();
3733 if (rethrow)
3734 ctx->module->rethrow = callee;
3735 else
3736 ctx->module->throw_icall = callee;
3740 LLVMValueRef args [2];
3742 args [0] = convert (ctx, exc, exc_type);
3743 emit_call (ctx, bb, &ctx->builder, callee, args, 1);
3745 LLVMBuildUnreachable (ctx->builder);
3747 ctx->builder = create_builder (ctx);
3750 static void
3751 emit_throw (EmitContext *ctx, MonoBasicBlock *bb, gboolean rethrow, LLVMValueRef exc)
3753 MonoMethodSignature *throw_sig;
3754 LLVMValueRef callee, arg;
3755 const char *icall_name;
3757 callee = rethrow ? ctx->module->rethrow : ctx->module->throw_icall;
3758 icall_name = rethrow ? "mono_arch_rethrow_exception" : "mono_arch_throw_exception";
3760 if (!callee) {
3761 throw_sig = mono_metadata_signature_alloc (mono_get_corlib (), 1);
3762 throw_sig->ret = m_class_get_byval_arg (mono_get_void_class ());
3763 throw_sig->params [0] = m_class_get_byval_arg (mono_get_object_class ());
3764 if (ctx->cfg->compile_aot) {
3765 callee = get_callee (ctx, sig_to_llvm_sig (ctx, throw_sig), MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3766 } else {
3767 gpointer target;
3768 #ifdef TARGET_X86
3770 * LLVM doesn't push the exception argument, so we need a different
3771 * trampoline.
3773 target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, rethrow ? "llvm_rethrow_exception_trampoline" : "llvm_throw_exception_trampoline");
3774 #else
3775 target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3776 #endif
3777 callee = emit_jit_callee (ctx, icall_name, sig_to_llvm_sig (ctx, throw_sig), target);
3780 mono_memory_barrier ();
3781 #if LLVM_API_VERSION < 100
3782 if (rethrow)
3783 ctx->module->rethrow = callee;
3784 else
3785 ctx->module->throw_icall = callee;
3786 #endif
3788 arg = convert (ctx, exc, type_to_llvm_type (ctx, m_class_get_byval_arg (mono_get_object_class ())));
3789 emit_call (ctx, bb, &ctx->builder, callee, &arg, 1);
3792 static void
3793 emit_resume_eh (EmitContext *ctx, MonoBasicBlock *bb)
3795 const char *icall_name = "mono_llvm_resume_exception";
3796 LLVMValueRef callee = ctx->module->resume_eh;
3798 LLVMTypeRef fun_sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
3800 if (!callee) {
3801 if (ctx->cfg->compile_aot) {
3802 callee = get_callee (ctx, fun_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3803 } else {
3804 callee = LLVMAddFunction (ctx->lmodule, icall_name, fun_sig);
3805 LLVMAddGlobalMapping (ctx->module->ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
3806 mono_memory_barrier ();
3808 ctx->module->resume_eh = callee;
3812 emit_call (ctx, bb, &ctx->builder, callee, NULL, 0);
3814 LLVMBuildUnreachable (ctx->builder);
3816 ctx->builder = create_builder (ctx);
3819 static LLVMValueRef
3820 mono_llvm_emit_clear_exception_call (EmitContext *ctx, LLVMBuilderRef builder)
3822 const char *icall_name = "mono_llvm_clear_exception";
3824 LLVMTypeRef call_sig = LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE);
3825 LLVMValueRef callee = NULL;
3827 if (!callee) {
3828 if (ctx->cfg->compile_aot) {
3829 callee = get_callee (ctx, call_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3830 } else {
3831 // FIXME: This is broken.
3832 callee = LLVMAddFunction (ctx->lmodule, icall_name, call_sig);
3836 g_assert (builder && callee);
3838 return LLVMBuildCall (builder, callee, NULL, 0, "");
3841 static LLVMValueRef
3842 mono_llvm_emit_load_exception_call (EmitContext *ctx, LLVMBuilderRef builder)
3844 const char *icall_name = "mono_llvm_load_exception";
3846 LLVMTypeRef call_sig = LLVMFunctionType (ObjRefType (), NULL, 0, FALSE);
3847 LLVMValueRef callee = NULL;
3849 if (!callee) {
3850 if (ctx->cfg->compile_aot) {
3851 callee = get_callee (ctx, call_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3852 } else {
3853 // FIXME: This is broken.
3854 callee = LLVMAddFunction (ctx->lmodule, icall_name, call_sig);
3858 g_assert (builder && callee);
3860 return LLVMBuildCall (builder, callee, NULL, 0, icall_name);
3864 static LLVMValueRef
3865 mono_llvm_emit_match_exception_call (EmitContext *ctx, LLVMBuilderRef builder, gint32 region_start, gint32 region_end)
3867 const char *icall_name = "mono_llvm_match_exception";
3869 ctx->builder = builder;
3871 LLVMValueRef args[5];
3872 const int num_args = G_N_ELEMENTS (args);
3874 args [0] = convert (ctx, get_aotconst (ctx, MONO_PATCH_INFO_AOT_JIT_INFO, GINT_TO_POINTER (ctx->cfg->method_index)), IntPtrType ());
3875 args [1] = LLVMConstInt (LLVMInt32Type (), region_start, 0);
3876 args [2] = LLVMConstInt (LLVMInt32Type (), region_end, 0);
3877 if (ctx->cfg->rgctx_var) {
3878 LLVMValueRef rgctx_alloc = ctx->addresses [ctx->cfg->rgctx_var->dreg];
3879 g_assert (rgctx_alloc);
3880 args [3] = LLVMBuildLoad (builder, convert (ctx, rgctx_alloc, LLVMPointerType (IntPtrType (), 0)), "");
3881 } else {
3882 args [3] = LLVMConstInt (IntPtrType (), 0, 0);
3884 if (ctx->this_arg)
3885 args [4] = convert (ctx, ctx->this_arg, IntPtrType ());
3886 else
3887 args [4] = LLVMConstInt (IntPtrType (), 0, 0);
3889 LLVMTypeRef match_sig = LLVMFunctionType5 (LLVMInt32Type (), IntPtrType (), LLVMInt32Type (), LLVMInt32Type (), IntPtrType (), IntPtrType (), FALSE);
3890 LLVMValueRef callee = ctx->module->match_exc;
3892 if (!callee) {
3893 if (ctx->cfg->compile_aot) {
3894 ctx->builder = builder;
3895 // get_callee expects ctx->builder to be the emitting builder
3896 callee = get_callee (ctx, match_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
3897 } else {
3898 callee = ctx->module->match_exc = LLVMAddFunction (ctx->lmodule, icall_name, match_sig);
3899 LLVMAddGlobalMapping (ctx->module->ee, ctx->module->match_exc, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
3900 ctx->module->match_exc = callee;
3901 mono_memory_barrier ();
3905 g_assert (builder && callee);
3907 g_assert (ctx->ex_var);
3909 return LLVMBuildCall (builder, callee, args, num_args, icall_name);
3912 // FIXME: This won't work because the code-finding makes this
3913 // not a constant.
3914 /*#define MONO_PERSONALITY_DEBUG*/
3916 #ifdef MONO_PERSONALITY_DEBUG
3917 static const gboolean use_debug_personality = TRUE;
3918 static const char *default_personality_name = "mono_debug_personality";
3919 #else
3920 static const gboolean use_debug_personality = FALSE;
3921 static const char *default_personality_name = "__gxx_personality_v0";
3922 #endif
3924 static LLVMTypeRef
3925 default_cpp_lpad_exc_signature (void)
3927 static gboolean inited = FALSE;
3928 static LLVMTypeRef sig;
3930 if (!sig) {
3931 LLVMTypeRef signature [2];
3932 signature [0] = LLVMPointerType (LLVMInt8Type (), 0);
3933 signature [1] = LLVMInt32Type ();
3934 sig = LLVMStructType (signature, 2, FALSE);
3935 inited = TRUE;
3938 return sig;
3941 static LLVMValueRef
3942 get_mono_personality (EmitContext *ctx)
3944 LLVMValueRef personality = NULL;
3945 static gint32 mapping_inited = FALSE;
3946 LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
3948 if (!use_debug_personality) {
3949 if (ctx->cfg->compile_aot) {
3950 personality = get_intrinsic (ctx, default_personality_name);
3951 } else if (mono_atomic_cas_i32 (&mapping_inited, 1, 0) == 0) {
3952 personality = LLVMAddFunction (ctx->lmodule, default_personality_name, personality_type);
3953 LLVMAddGlobalMapping (ctx->module->ee, personality, personality);
3955 } else {
3956 if (ctx->cfg->compile_aot) {
3957 personality = get_callee (ctx, personality_type, MONO_PATCH_INFO_INTERNAL_METHOD, default_personality_name);
3958 } else {
3959 personality = LLVMAddFunction (ctx->lmodule, default_personality_name, personality_type);
3960 LLVMAddGlobalMapping (ctx->module->ee, personality, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, default_personality_name));
3961 mono_memory_barrier ();
3965 g_assert (personality);
3966 return personality;
3969 static LLVMBasicBlockRef
3970 emit_landing_pad (EmitContext *ctx, int group_index, int group_size)
3972 MonoCompile *cfg = ctx->cfg;
3973 LLVMBuilderRef old_builder = ctx->builder;
3974 MonoExceptionClause *group_start = cfg->header->clauses + group_index;
3976 LLVMBuilderRef lpadBuilder = create_builder (ctx);
3977 ctx->builder = lpadBuilder;
3979 MonoBasicBlock *handler_bb = cfg->cil_offset_to_bb [CLAUSE_START (group_start)];
3980 g_assert (handler_bb);
3982 // <resultval> = landingpad <somety> personality <type> <pers_fn> <clause>+
3983 LLVMValueRef personality = get_mono_personality (ctx);
3984 g_assert (personality);
3986 char *bb_name = g_strdup_printf ("LPAD%d_BB", group_index);
3987 LLVMBasicBlockRef lpad_bb = gen_bb (ctx, bb_name);
3988 g_free (bb_name);
3989 LLVMPositionBuilderAtEnd (lpadBuilder, lpad_bb);
3990 LLVMValueRef landing_pad = LLVMBuildLandingPad (lpadBuilder, default_cpp_lpad_exc_signature (), personality, 0, "");
3991 g_assert (landing_pad);
3993 LLVMValueRef cast = LLVMBuildBitCast (lpadBuilder, ctx->module->sentinel_exception, LLVMPointerType (LLVMInt8Type (), 0), "int8TypeInfo");
3994 LLVMAddClause (landing_pad, cast);
3996 LLVMBasicBlockRef resume_bb = gen_bb (ctx, "RESUME_BB");
3997 LLVMBuilderRef resume_builder = create_builder (ctx);
3998 ctx->builder = resume_builder;
3999 LLVMPositionBuilderAtEnd (resume_builder, resume_bb);
4001 emit_resume_eh (ctx, handler_bb);
4003 // Build match
4004 ctx->builder = lpadBuilder;
4005 LLVMPositionBuilderAtEnd (lpadBuilder, lpad_bb);
4007 gboolean finally_only = TRUE;
4009 MonoExceptionClause *group_cursor = group_start;
4011 for (int i = 0; i < group_size; i ++) {
4012 if (!(group_cursor->flags & MONO_EXCEPTION_CLAUSE_FINALLY || group_cursor->flags & MONO_EXCEPTION_CLAUSE_FAULT))
4013 finally_only = FALSE;
4015 group_cursor++;
4018 // FIXME:
4019 // Handle landing pad inlining
4021 if (!finally_only) {
4022 // So at each level of the exception stack we will match the exception again.
4023 // During that match, we need to compare against the handler types for the current
4024 // protected region. We send the try start and end so that we can only check against
4025 // handlers for this lexical protected region.
4026 LLVMValueRef match = mono_llvm_emit_match_exception_call (ctx, lpadBuilder, group_start->try_offset, group_start->try_offset + group_start->try_len);
4028 // if returns -1, resume
4029 LLVMValueRef switch_ins = LLVMBuildSwitch (lpadBuilder, match, resume_bb, group_size);
4031 // else move to that target bb
4032 for (int i = 0; i < group_size; i++) {
4033 MonoExceptionClause *clause = group_start + i;
4034 int clause_index = clause - cfg->header->clauses;
4035 MonoBasicBlock *handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (clause_index));
4036 g_assert (handler_bb);
4037 g_assert (ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
4038 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE), ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
4040 } else {
4041 int clause_index = group_start - cfg->header->clauses;
4042 MonoBasicBlock *finally_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (clause_index));
4043 g_assert (finally_bb);
4045 LLVMBuildBr (ctx->builder, ctx->bblocks [finally_bb->block_num].call_handler_target_bb);
4048 ctx->builder = old_builder;
4050 return lpad_bb;
4054 static void
4055 emit_llvmonly_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBasicBlockRef cbb)
4057 int clause_index = MONO_REGION_CLAUSE_INDEX (bb->region);
4058 MonoExceptionClause *clause = &ctx->cfg->header->clauses [clause_index];
4060 // Make exception available to catch blocks
4061 if (!(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY || clause->flags & MONO_EXCEPTION_CLAUSE_FAULT)) {
4062 LLVMValueRef mono_exc = mono_llvm_emit_load_exception_call (ctx, ctx->builder);
4064 g_assert (ctx->ex_var);
4065 LLVMBuildStore (ctx->builder, LLVMBuildBitCast (ctx->builder, mono_exc, ObjRefType (), ""), ctx->ex_var);
4067 if (bb->in_scount == 1) {
4068 MonoInst *exvar = bb->in_stack [0];
4069 g_assert (!ctx->values [exvar->dreg]);
4070 g_assert (ctx->ex_var);
4071 ctx->values [exvar->dreg] = LLVMBuildLoad (ctx->builder, ctx->ex_var, "save_exception");
4072 emit_volatile_store (ctx, exvar->dreg);
4075 mono_llvm_emit_clear_exception_call (ctx, ctx->builder);
4078 LLVMBuilderRef handler_builder = create_builder (ctx);
4079 LLVMBasicBlockRef target_bb = ctx->bblocks [bb->block_num].call_handler_target_bb;
4080 LLVMPositionBuilderAtEnd (handler_builder, target_bb);
4082 // Make the handler code end with a jump to cbb
4083 LLVMBuildBr (handler_builder, cbb);
4086 static void
4087 emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder)
4089 MonoCompile *cfg = ctx->cfg;
4090 LLVMValueRef *values = ctx->values;
4091 LLVMModuleRef lmodule = ctx->lmodule;
4092 BBInfo *bblocks = ctx->bblocks;
4093 LLVMTypeRef i8ptr;
4094 LLVMValueRef personality;
4095 LLVMValueRef landing_pad;
4096 LLVMBasicBlockRef target_bb;
4097 MonoInst *exvar;
4098 static int ti_generator;
4099 char ti_name [128];
4100 LLVMValueRef type_info;
4101 int clause_index;
4102 GSList *l;
4104 // <resultval> = landingpad <somety> personality <type> <pers_fn> <clause>+
4106 if (cfg->compile_aot) {
4107 /* Use a dummy personality function */
4108 personality = LLVMGetNamedFunction (lmodule, "mono_personality");
4109 g_assert (personality);
4110 } else {
4111 #if LLVM_API_VERSION > 100
4112 /* Can't cache this as each method is in its own llvm module */
4113 LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
4114 personality = LLVMAddFunction (ctx->lmodule, "mono_personality", personality_type);
4115 mono_llvm_add_func_attr (personality, LLVM_ATTR_NO_UNWIND);
4116 LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlock (personality, "ENTRY");
4117 LLVMBuilderRef builder2 = LLVMCreateBuilder ();
4118 LLVMPositionBuilderAtEnd (builder2, entry_bb);
4119 LLVMBuildRet (builder2, LLVMConstInt (LLVMInt32Type (), 0, FALSE));
4120 LLVMDisposeBuilder (builder2);
4121 #else
4122 static gint32 mapping_inited;
4124 personality = LLVMGetNamedFunction (lmodule, "mono_personality");
4126 if (mono_atomic_cas_i32 (&mapping_inited, 1, 0) == 0)
4127 LLVMAddGlobalMapping (ctx->module->ee, personality, (gpointer)mono_personality);
4128 #endif
4131 i8ptr = LLVMPointerType (LLVMInt8Type (), 0);
4133 clause_index = (mono_get_block_region_notry (cfg, bb->region) >> 8) - 1;
4136 * Create the type info
4138 sprintf (ti_name, "type_info_%d", ti_generator);
4139 ti_generator ++;
4141 if (cfg->compile_aot) {
4142 /* decode_eh_frame () in aot-runtime.c will decode this */
4143 type_info = LLVMAddGlobal (lmodule, LLVMInt32Type (), ti_name);
4144 LLVMSetInitializer (type_info, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE));
4147 * These symbols are not really used, the clause_index is embedded into the EH tables generated by DwarfMonoException in LLVM.
4149 LLVMSetLinkage (type_info, LLVMInternalLinkage);
4150 } else {
4151 #if LLVM_API_VERSION > 100
4152 type_info = LLVMAddGlobal (lmodule, LLVMInt32Type (), ti_name);
4153 LLVMSetInitializer (type_info, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE));
4154 #else
4155 gint32 *ti;
4158 * After the cfg mempool is freed, the type info will point to stale memory,
4159 * but this is not a problem, since we decode it once in exception_cb during
4160 * compilation.
4162 ti = (gint32*)mono_mempool_alloc (cfg->mempool, sizeof (gint32));
4163 *(gint32*)ti = clause_index;
4165 type_info = LLVMAddGlobal (lmodule, i8ptr, ti_name);
4167 LLVMAddGlobalMapping (ctx->module->ee, type_info, ti);
4168 #endif
4172 LLVMTypeRef members [2], ret_type;
4174 members [0] = i8ptr;
4175 members [1] = LLVMInt32Type ();
4176 ret_type = LLVMStructType (members, 2, FALSE);
4178 landing_pad = LLVMBuildLandingPad (builder, ret_type, personality, 1, "");
4179 LLVMAddClause (landing_pad, type_info);
4181 /* Store the exception into the exvar */
4182 if (ctx->ex_var)
4183 LLVMBuildStore (builder, convert (ctx, LLVMBuildExtractValue (builder, landing_pad, 0, "ex_obj"), ObjRefType ()), ctx->ex_var);
4187 * LLVM throw sites are associated with a one landing pad, and LLVM generated
4188 * code expects control to be transferred to this landing pad even in the
4189 * presence of nested clauses. The landing pad needs to branch to the landing
4190 * pads belonging to nested clauses based on the selector value returned by
4191 * the landing pad instruction, which is passed to the landing pad in a
4192 * register by the EH code.
4194 target_bb = bblocks [bb->block_num].call_handler_target_bb;
4195 g_assert (target_bb);
4198 * Branch to the correct landing pad
4200 LLVMValueRef ex_selector = LLVMBuildExtractValue (builder, landing_pad, 1, "ex_selector");
4201 LLVMValueRef switch_ins = LLVMBuildSwitch (builder, ex_selector, target_bb, 0);
4203 for (l = ctx->nested_in [clause_index]; l; l = l->next) {
4204 int nesting_clause_index = GPOINTER_TO_INT (l->data);
4205 MonoBasicBlock *handler_bb;
4207 handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (nesting_clause_index));
4208 g_assert (handler_bb);
4210 g_assert (ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
4211 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), nesting_clause_index, FALSE), ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
4214 /* Start a new bblock which CALL_HANDLER can branch to */
4215 ctx->builder = builder = create_builder (ctx);
4216 LLVMPositionBuilderAtEnd (ctx->builder, target_bb);
4218 ctx->bblocks [bb->block_num].end_bblock = target_bb;
4220 /* Store the exception into the IL level exvar */
4221 if (bb->in_scount == 1) {
4222 g_assert (bb->in_scount == 1);
4223 exvar = bb->in_stack [0];
4225 // FIXME: This is shared with filter clauses ?
4226 g_assert (!values [exvar->dreg]);
4228 g_assert (ctx->ex_var);
4229 values [exvar->dreg] = LLVMBuildLoad (builder, ctx->ex_var, "");
4230 emit_volatile_store (ctx, exvar->dreg);
4233 /* Make normal branches to the start of the clause branch to the new bblock */
4234 bblocks [bb->block_num].bblock = target_bb;
4237 //Wasm requires us to canonicalize NaNs.
4238 static LLVMValueRef
4239 get_double_const (MonoCompile *cfg, double val)
4241 #ifdef TARGET_WASM
4242 if (mono_isnan (val))
4243 *(gint64 *)&val = 0x7FF8000000000000ll;
4244 #endif
4245 return LLVMConstReal (LLVMDoubleType (), val);
4248 static LLVMValueRef
4249 get_float_const (MonoCompile *cfg, float val)
4251 #ifdef TARGET_WASM
4252 if (mono_isnan (val))
4253 *(int *)&val = 0x7FC00000;
4254 #endif
4255 if (cfg->r4fp)
4256 return LLVMConstReal (LLVMFloatType (), val);
4257 else
4258 return LLVMConstFPExt (LLVMConstReal (LLVMFloatType (), val), LLVMDoubleType ());
4261 static void
4262 process_bb (EmitContext *ctx, MonoBasicBlock *bb)
4264 MonoCompile *cfg = ctx->cfg;
4265 MonoMethodSignature *sig = ctx->sig;
4266 LLVMValueRef method = ctx->lmethod;
4267 LLVMValueRef *values = ctx->values;
4268 LLVMValueRef *addresses = ctx->addresses;
4269 LLVMCallInfo *linfo = ctx->linfo;
4270 BBInfo *bblocks = ctx->bblocks;
4271 MonoInst *ins;
4272 LLVMBasicBlockRef cbb;
4273 LLVMBuilderRef builder, starting_builder;
4274 gboolean has_terminator;
4275 LLVMValueRef v;
4276 LLVMValueRef lhs, rhs;
4277 int nins = 0;
4279 cbb = get_end_bb (ctx, bb);
4281 builder = create_builder (ctx);
4282 ctx->builder = builder;
4283 LLVMPositionBuilderAtEnd (builder, cbb);
4285 if (!ctx_ok (ctx))
4286 return;
4288 if (bb->flags & BB_EXCEPTION_HANDLER) {
4289 if (!ctx->llvm_only && !bblocks [bb->block_num].invoke_target) {
4290 set_failure (ctx, "handler without invokes");
4291 return;
4294 if (ctx->llvm_only)
4295 emit_llvmonly_handler_start (ctx, bb, cbb);
4296 else
4297 emit_handler_start (ctx, bb, builder);
4298 if (!ctx_ok (ctx))
4299 return;
4300 builder = ctx->builder;
4303 has_terminator = FALSE;
4304 starting_builder = builder;
4305 for (ins = bb->code; ins; ins = ins->next) {
4306 const char *spec = LLVM_INS_INFO (ins->opcode);
4307 char *dname = NULL;
4308 char dname_buf [128];
4310 emit_dbg_loc (ctx, builder, ins->cil_code);
4312 nins ++;
4313 if (nins > 1000) {
4315 * Some steps in llc are non-linear in the size of basic blocks, see #5714.
4316 * Start a new bblock.
4317 * Prevent the bblocks to be merged by doing a volatile load + cond branch
4318 * from localloc-ed memory.
4320 if (!cfg->llvm_only)
4321 ;//set_failure (ctx, "basic block too long");
4323 if (!ctx->long_bb_break_var) {
4324 ctx->long_bb_break_var = build_alloca_llvm_type_name (ctx, LLVMInt32Type (), 0, "long_bb_break");
4325 mono_llvm_build_store (ctx->alloca_builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), ctx->long_bb_break_var, TRUE, LLVM_BARRIER_NONE);
4328 cbb = gen_bb (ctx, "CONT_LONG_BB");
4329 LLVMBasicBlockRef dummy_bb = gen_bb (ctx, "CONT_LONG_BB_DUMMY");
4331 LLVMValueRef load = mono_llvm_build_load (builder, ctx->long_bb_break_var, "", TRUE);
4333 * The long_bb_break_var is initialized to 0 in the prolog, so this branch will always go to 'cbb'
4334 * but llvm doesn't know that, so the branch is not going to be eliminated.
4336 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntEQ, load, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
4338 LLVMBuildCondBr (builder, cmp, cbb, dummy_bb);
4340 /* Emit a dummy false bblock which does nothing but contains a volatile store so it cannot be eliminated */
4341 ctx->builder = builder = create_builder (ctx);
4342 LLVMPositionBuilderAtEnd (builder, dummy_bb);
4343 mono_llvm_build_store (builder, LLVMConstInt (LLVMInt32Type (), 1, FALSE), ctx->long_bb_break_var, TRUE, LLVM_BARRIER_NONE);
4344 LLVMBuildBr (builder, cbb);
4346 ctx->builder = builder = create_builder (ctx);
4347 LLVMPositionBuilderAtEnd (builder, cbb);
4348 ctx->bblocks [bb->block_num].end_bblock = cbb;
4349 nins = 0;
4351 emit_dbg_loc (ctx, builder, ins->cil_code);
4354 if (has_terminator)
4355 /* There could be instructions after a terminator, skip them */
4356 break;
4358 if (spec [MONO_INST_DEST] != ' ' && !MONO_IS_STORE_MEMBASE (ins)) {
4359 sprintf (dname_buf, "t%d", ins->dreg);
4360 dname = dname_buf;
4363 if (spec [MONO_INST_SRC1] != ' ' && spec [MONO_INST_SRC1] != 'v') {
4364 MonoInst *var = get_vreg_to_inst (cfg, ins->sreg1);
4366 if (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) && var->opcode != OP_GSHAREDVT_ARG_REGOFFSET) {
4367 lhs = emit_volatile_load (ctx, ins->sreg1);
4368 } else {
4369 /* It is ok for SETRET to have an uninitialized argument */
4370 if (!values [ins->sreg1] && ins->opcode != OP_SETRET) {
4371 set_failure (ctx, "sreg1");
4372 return;
4374 lhs = values [ins->sreg1];
4376 } else {
4377 lhs = NULL;
4380 if (spec [MONO_INST_SRC2] != ' ' && spec [MONO_INST_SRC2] != ' ') {
4381 MonoInst *var = get_vreg_to_inst (cfg, ins->sreg2);
4382 if (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) {
4383 rhs = emit_volatile_load (ctx, ins->sreg2);
4384 } else {
4385 if (!values [ins->sreg2]) {
4386 set_failure (ctx, "sreg2");
4387 return;
4389 rhs = values [ins->sreg2];
4391 } else {
4392 rhs = NULL;
4395 //mono_print_ins (ins);
4396 switch (ins->opcode) {
4397 case OP_NOP:
4398 case OP_NOT_NULL:
4399 case OP_LIVERANGE_START:
4400 case OP_LIVERANGE_END:
4401 break;
4402 case OP_ICONST:
4403 values [ins->dreg] = LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE);
4404 break;
4405 case OP_I8CONST:
4406 #if TARGET_SIZEOF_VOID_P == 4
4407 values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins), FALSE);
4408 #else
4409 values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), (gint64)ins->inst_c0, FALSE);
4410 #endif
4411 break;
4412 case OP_R8CONST:
4413 values [ins->dreg] = get_double_const (cfg, *(double*)ins->inst_p0);
4414 break;
4415 case OP_R4CONST:
4416 values [ins->dreg] = get_float_const (cfg, *(float*)ins->inst_p0);
4417 break;
4418 case OP_DUMMY_ICONST:
4419 values [ins->dreg] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
4420 break;
4421 case OP_DUMMY_I8CONST:
4422 values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
4423 break;
4424 case OP_DUMMY_R8CONST:
4425 values [ins->dreg] = LLVMConstReal (LLVMDoubleType (), 0.0f);
4426 break;
4427 case OP_BR: {
4428 LLVMBasicBlockRef target_bb = get_bb (ctx, ins->inst_target_bb);
4429 LLVMBuildBr (builder, target_bb);
4430 has_terminator = TRUE;
4431 break;
4433 case OP_SWITCH: {
4434 int i;
4435 LLVMValueRef v;
4436 char bb_name [128];
4437 LLVMBasicBlockRef new_bb;
4438 LLVMBuilderRef new_builder;
4440 // The default branch is already handled
4441 // FIXME: Handle it here
4443 /* Start new bblock */
4444 sprintf (bb_name, "SWITCH_DEFAULT_BB%d", ctx->default_index ++);
4445 new_bb = LLVMAppendBasicBlock (ctx->lmethod, bb_name);
4447 lhs = convert (ctx, lhs, LLVMInt32Type ());
4448 v = LLVMBuildSwitch (builder, lhs, new_bb, GPOINTER_TO_UINT (ins->klass));
4449 for (i = 0; i < GPOINTER_TO_UINT (ins->klass); ++i) {
4450 MonoBasicBlock *target_bb = ins->inst_many_bb [i];
4452 LLVMAddCase (v, LLVMConstInt (LLVMInt32Type (), i, FALSE), get_bb (ctx, target_bb));
4455 new_builder = create_builder (ctx);
4456 LLVMPositionBuilderAtEnd (new_builder, new_bb);
4457 LLVMBuildUnreachable (new_builder);
4459 has_terminator = TRUE;
4460 g_assert (!ins->next);
4462 break;
4465 case OP_SETRET:
4466 switch (linfo->ret.storage) {
4467 case LLVMArgVtypeInReg: {
4468 LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
4469 LLVMValueRef val, addr, retval;
4470 int i;
4472 retval = LLVMGetUndef (ret_type);
4474 if (!addresses [ins->sreg1]) {
4476 * The return type is an LLVM vector type, have to convert between it and the
4477 * real return type which is a struct type.
4479 g_assert (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (sig->ret)));
4480 /* Convert to 2xi64 first */
4481 val = LLVMBuildBitCast (builder, values [ins->sreg1], LLVMVectorType (IntPtrType (), 2), "");
4483 for (i = 0; i < 2; ++i) {
4484 if (linfo->ret.pair_storage [i] == LLVMArgInIReg) {
4485 retval = LLVMBuildInsertValue (builder, retval, LLVMBuildExtractElement (builder, val, LLVMConstInt (LLVMInt32Type (), i, FALSE), ""), i, "");
4486 } else {
4487 g_assert (linfo->ret.pair_storage [i] == LLVMArgNone);
4490 } else {
4491 addr = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), "");
4492 for (i = 0; i < 2; ++i) {
4493 if (linfo->ret.pair_storage [i] == LLVMArgInIReg) {
4494 LLVMValueRef indexes [2], part_addr;
4496 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
4497 indexes [1] = LLVMConstInt (LLVMInt32Type (), i, FALSE);
4498 part_addr = LLVMBuildGEP (builder, addr, indexes, 2, "");
4500 retval = LLVMBuildInsertValue (builder, retval, LLVMBuildLoad (builder, part_addr, ""), i, "");
4501 } else {
4502 g_assert (linfo->ret.pair_storage [i] == LLVMArgNone);
4506 LLVMBuildRet (builder, retval);
4507 break;
4509 case LLVMArgVtypeAsScalar: {
4510 LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
4511 LLVMValueRef retval;
4513 g_assert (addresses [ins->sreg1]);
4515 retval = LLVMBuildLoad (builder, LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), ""), "");
4516 LLVMBuildRet (builder, retval);
4517 break;
4519 case LLVMArgVtypeByVal: {
4520 LLVMValueRef retval;
4522 g_assert (addresses [ins->sreg1]);
4523 retval = LLVMBuildLoad (builder, addresses [ins->sreg1], "");
4524 LLVMBuildRet (builder, retval);
4525 break;
4527 case LLVMArgVtypeByRef: {
4528 LLVMBuildRetVoid (builder);
4529 break;
4531 case LLVMArgGsharedvtFixed: {
4532 LLVMTypeRef ret_type = type_to_llvm_type (ctx, sig->ret);
4533 /* The return value is in lhs, need to store to the vret argument */
4534 /* sreg1 might not be set */
4535 if (lhs) {
4536 g_assert (cfg->vret_addr);
4537 g_assert (values [cfg->vret_addr->dreg]);
4538 LLVMBuildStore (builder, convert (ctx, lhs, ret_type), convert (ctx, values [cfg->vret_addr->dreg], LLVMPointerType (ret_type, 0)));
4540 LLVMBuildRetVoid (builder);
4541 break;
4543 case LLVMArgGsharedvtFixedVtype: {
4544 /* Already set */
4545 LLVMBuildRetVoid (builder);
4546 break;
4548 case LLVMArgGsharedvtVariable: {
4549 /* Already set */
4550 LLVMBuildRetVoid (builder);
4551 break;
4553 case LLVMArgVtypeRetAddr: {
4554 LLVMBuildRetVoid (builder);
4555 break;
4557 case LLVMArgAsIArgs:
4558 case LLVMArgFpStruct: {
4559 LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
4560 LLVMValueRef retval;
4562 g_assert (addresses [ins->sreg1]);
4563 retval = LLVMBuildLoad (builder, convert (ctx, addresses [ins->sreg1], LLVMPointerType (ret_type, 0)), "");
4564 LLVMBuildRet (builder, retval);
4565 break;
4567 case LLVMArgNone:
4568 case LLVMArgNormal: {
4569 if (!lhs || ctx->is_dead [ins->sreg1]) {
4571 * The method did not set its return value, probably because it
4572 * ends with a throw.
4574 if (cfg->vret_addr)
4575 LLVMBuildRetVoid (builder);
4576 else
4577 LLVMBuildRet (builder, LLVMConstNull (type_to_llvm_type (ctx, sig->ret)));
4578 } else {
4579 LLVMBuildRet (builder, convert (ctx, lhs, type_to_llvm_type (ctx, sig->ret)));
4581 has_terminator = TRUE;
4582 break;
4584 default:
4585 g_assert_not_reached ();
4586 break;
4588 break;
4589 case OP_ICOMPARE:
4590 case OP_FCOMPARE:
4591 case OP_RCOMPARE:
4592 case OP_LCOMPARE:
4593 case OP_COMPARE:
4594 case OP_ICOMPARE_IMM:
4595 case OP_LCOMPARE_IMM:
4596 case OP_COMPARE_IMM: {
4597 CompRelation rel;
4598 LLVMValueRef cmp, args [16];
4599 gboolean likely = (ins->flags & MONO_INST_LIKELY) != 0;
4601 if (ins->next->opcode == OP_NOP)
4602 break;
4604 if (ins->next->opcode == OP_BR)
4605 /* The comparison result is not needed */
4606 continue;
4608 rel = mono_opcode_to_cond (ins->next->opcode);
4610 if (ins->opcode == OP_ICOMPARE_IMM) {
4611 lhs = convert (ctx, lhs, LLVMInt32Type ());
4612 rhs = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
4614 if (ins->opcode == OP_LCOMPARE_IMM) {
4615 lhs = convert (ctx, lhs, LLVMInt64Type ());
4616 rhs = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins), FALSE);
4618 if (ins->opcode == OP_LCOMPARE) {
4619 lhs = convert (ctx, lhs, LLVMInt64Type ());
4620 rhs = convert (ctx, rhs, LLVMInt64Type ());
4622 if (ins->opcode == OP_ICOMPARE) {
4623 lhs = convert (ctx, lhs, LLVMInt32Type ());
4624 rhs = convert (ctx, rhs, LLVMInt32Type ());
4627 if (lhs && rhs) {
4628 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind)
4629 rhs = convert (ctx, rhs, LLVMTypeOf (lhs));
4630 else if (LLVMGetTypeKind (LLVMTypeOf (rhs)) == LLVMPointerTypeKind)
4631 lhs = convert (ctx, lhs, LLVMTypeOf (rhs));
4634 /* We use COMPARE+SETcc/Bcc, llvm uses SETcc+br cond */
4635 if (ins->opcode == OP_FCOMPARE) {
4636 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMDoubleType ()), convert (ctx, rhs, LLVMDoubleType ()), "");
4637 } else if (ins->opcode == OP_RCOMPARE) {
4638 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMFloatType ()), convert (ctx, rhs, LLVMFloatType ()), "");
4639 } else if (ins->opcode == OP_COMPARE_IMM) {
4640 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind && ins->inst_imm == 0)
4641 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, LLVMConstNull (LLVMTypeOf (lhs)), "");
4642 else
4643 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), "");
4644 } else if (ins->opcode == OP_LCOMPARE_IMM) {
4645 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, rhs, "");
4647 else if (ins->opcode == OP_COMPARE) {
4648 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind && LLVMTypeOf (lhs) == LLVMTypeOf (rhs))
4649 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, rhs, "");
4650 else
4651 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, IntPtrType ()), convert (ctx, rhs, IntPtrType ()), "");
4652 } else
4653 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, rhs, "");
4655 if (likely) {
4656 args [0] = cmp;
4657 args [1] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
4658 cmp = LLVMBuildCall (ctx->builder, get_intrinsic (ctx, "llvm.expect.i1"), args, 2, "");
4661 if (MONO_IS_COND_BRANCH_OP (ins->next)) {
4662 if (ins->next->inst_true_bb == ins->next->inst_false_bb) {
4664 * If the target bb contains PHI instructions, LLVM requires
4665 * two PHI entries for this bblock, while we only generate one.
4666 * So convert this to an unconditional bblock. (bxc #171).
4668 LLVMBuildBr (builder, get_bb (ctx, ins->next->inst_true_bb));
4669 } else {
4670 LLVMBuildCondBr (builder, cmp, get_bb (ctx, ins->next->inst_true_bb), get_bb (ctx, ins->next->inst_false_bb));
4672 has_terminator = TRUE;
4673 } else if (MONO_IS_SETCC (ins->next)) {
4674 sprintf (dname_buf, "t%d", ins->next->dreg);
4675 dname = dname_buf;
4676 values [ins->next->dreg] = LLVMBuildZExt (builder, cmp, LLVMInt32Type (), dname);
4678 /* Add stores for volatile variables */
4679 emit_volatile_store (ctx, ins->next->dreg);
4680 } else if (MONO_IS_COND_EXC (ins->next)) {
4681 emit_cond_system_exception (ctx, bb, (const char*)ins->next->inst_p1, cmp);
4682 if (!ctx_ok (ctx))
4683 break;
4684 builder = ctx->builder;
4685 } else {
4686 set_failure (ctx, "next");
4687 break;
4690 ins = ins->next;
4691 break;
4693 case OP_FCEQ:
4694 case OP_FCNEQ:
4695 case OP_FCLT:
4696 case OP_FCLT_UN:
4697 case OP_FCGT:
4698 case OP_FCGT_UN:
4699 case OP_FCGE:
4700 case OP_FCLE: {
4701 CompRelation rel;
4702 LLVMValueRef cmp;
4704 rel = mono_opcode_to_cond (ins->opcode);
4706 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMDoubleType ()), convert (ctx, rhs, LLVMDoubleType ()), "");
4707 values [ins->dreg] = LLVMBuildZExt (builder, cmp, LLVMInt32Type (), dname);
4708 break;
4710 case OP_RCEQ:
4711 case OP_RCNEQ:
4712 case OP_RCLT:
4713 case OP_RCLT_UN:
4714 case OP_RCGT:
4715 case OP_RCGT_UN: {
4716 CompRelation rel;
4717 LLVMValueRef cmp;
4719 rel = mono_opcode_to_cond (ins->opcode);
4721 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMFloatType ()), convert (ctx, rhs, LLVMFloatType ()), "");
4722 values [ins->dreg] = LLVMBuildZExt (builder, cmp, LLVMInt32Type (), dname);
4723 break;
4725 case OP_PHI:
4726 case OP_FPHI:
4727 case OP_VPHI:
4728 case OP_XPHI: {
4729 int i;
4730 gboolean empty = TRUE;
4732 /* Check that all input bblocks really branch to us */
4733 for (i = 0; i < bb->in_count; ++i) {
4734 if (bb->in_bb [i]->last_ins && bb->in_bb [i]->last_ins->opcode == OP_NOT_REACHED)
4735 ins->inst_phi_args [i + 1] = -1;
4736 else
4737 empty = FALSE;
4740 if (empty) {
4741 /* LLVM doesn't like phi instructions with zero operands */
4742 ctx->is_dead [ins->dreg] = TRUE;
4743 break;
4746 /* Created earlier, insert it now */
4747 LLVMInsertIntoBuilder (builder, values [ins->dreg]);
4749 for (i = 0; i < ins->inst_phi_args [0]; i++) {
4750 int sreg1 = ins->inst_phi_args [i + 1];
4751 int count, j;
4754 * Count the number of times the incoming bblock branches to us,
4755 * since llvm requires a separate entry for each.
4757 if (bb->in_bb [i]->last_ins && bb->in_bb [i]->last_ins->opcode == OP_SWITCH) {
4758 MonoInst *switch_ins = bb->in_bb [i]->last_ins;
4760 count = 0;
4761 for (j = 0; j < GPOINTER_TO_UINT (switch_ins->klass); ++j) {
4762 if (switch_ins->inst_many_bb [j] == bb)
4763 count ++;
4765 } else {
4766 count = 1;
4769 /* Remember for later */
4770 for (j = 0; j < count; ++j) {
4771 PhiNode *node = (PhiNode*)mono_mempool_alloc0 (ctx->mempool, sizeof (PhiNode));
4772 node->bb = bb;
4773 node->phi = ins;
4774 node->in_bb = bb->in_bb [i];
4775 node->sreg = sreg1;
4776 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);
4779 break;
4781 case OP_MOVE:
4782 case OP_LMOVE:
4783 case OP_XMOVE:
4784 case OP_SETFRET:
4785 g_assert (lhs);
4786 values [ins->dreg] = lhs;
4787 break;
4788 case OP_FMOVE:
4789 case OP_RMOVE: {
4790 MonoInst *var = get_vreg_to_inst (cfg, ins->dreg);
4792 g_assert (lhs);
4793 values [ins->dreg] = lhs;
4795 if (var && m_class_get_byval_arg (var->klass)->type == MONO_TYPE_R4) {
4797 * This is added by the spilling pass in case of the JIT,
4798 * but we have to do it ourselves.
4800 values [ins->dreg] = convert (ctx, values [ins->dreg], LLVMFloatType ());
4802 break;
4804 case OP_MOVE_F_TO_I4: {
4805 values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildFPTrunc (builder, lhs, LLVMFloatType (), ""), LLVMInt32Type (), "");
4806 break;
4808 case OP_MOVE_I4_TO_F: {
4809 values [ins->dreg] = LLVMBuildFPExt (builder, LLVMBuildBitCast (builder, lhs, LLVMFloatType (), ""), LLVMDoubleType (), "");
4810 break;
4812 case OP_MOVE_F_TO_I8: {
4813 values [ins->dreg] = LLVMBuildBitCast (builder, lhs, LLVMInt64Type (), "");
4814 break;
4816 case OP_MOVE_I8_TO_F: {
4817 values [ins->dreg] = LLVMBuildBitCast (builder, lhs, LLVMDoubleType (), "");
4818 break;
4820 case OP_IADD:
4821 case OP_ISUB:
4822 case OP_IAND:
4823 case OP_IMUL:
4824 case OP_IDIV:
4825 case OP_IDIV_UN:
4826 case OP_IREM:
4827 case OP_IREM_UN:
4828 case OP_IOR:
4829 case OP_IXOR:
4830 case OP_ISHL:
4831 case OP_ISHR:
4832 case OP_ISHR_UN:
4833 case OP_FADD:
4834 case OP_FSUB:
4835 case OP_FMUL:
4836 case OP_FDIV:
4837 case OP_LADD:
4838 case OP_LSUB:
4839 case OP_LMUL:
4840 case OP_LDIV:
4841 case OP_LDIV_UN:
4842 case OP_LREM:
4843 case OP_LREM_UN:
4844 case OP_LAND:
4845 case OP_LOR:
4846 case OP_LXOR:
4847 case OP_LSHL:
4848 case OP_LSHR:
4849 case OP_LSHR_UN:
4850 lhs = convert (ctx, lhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
4851 rhs = convert (ctx, rhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
4853 emit_div_check (ctx, builder, bb, ins, lhs, rhs);
4854 if (!ctx_ok (ctx))
4855 break;
4856 builder = ctx->builder;
4858 switch (ins->opcode) {
4859 case OP_IADD:
4860 case OP_LADD:
4861 values [ins->dreg] = LLVMBuildAdd (builder, lhs, rhs, dname);
4862 break;
4863 case OP_ISUB:
4864 case OP_LSUB:
4865 values [ins->dreg] = LLVMBuildSub (builder, lhs, rhs, dname);
4866 break;
4867 case OP_IMUL:
4868 case OP_LMUL:
4869 values [ins->dreg] = LLVMBuildMul (builder, lhs, rhs, dname);
4870 break;
4871 case OP_IREM:
4872 case OP_LREM:
4873 values [ins->dreg] = LLVMBuildSRem (builder, lhs, rhs, dname);
4874 break;
4875 case OP_IREM_UN:
4876 case OP_LREM_UN:
4877 values [ins->dreg] = LLVMBuildURem (builder, lhs, rhs, dname);
4878 break;
4879 case OP_IDIV:
4880 case OP_LDIV:
4881 values [ins->dreg] = LLVMBuildSDiv (builder, lhs, rhs, dname);
4882 break;
4883 case OP_IDIV_UN:
4884 case OP_LDIV_UN:
4885 values [ins->dreg] = LLVMBuildUDiv (builder, lhs, rhs, dname);
4886 break;
4887 case OP_FDIV:
4888 case OP_RDIV:
4889 values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, dname);
4890 break;
4891 case OP_IAND:
4892 case OP_LAND:
4893 values [ins->dreg] = LLVMBuildAnd (builder, lhs, rhs, dname);
4894 break;
4895 case OP_IOR:
4896 case OP_LOR:
4897 values [ins->dreg] = LLVMBuildOr (builder, lhs, rhs, dname);
4898 break;
4899 case OP_IXOR:
4900 case OP_LXOR:
4901 values [ins->dreg] = LLVMBuildXor (builder, lhs, rhs, dname);
4902 break;
4903 case OP_ISHL:
4904 case OP_LSHL:
4905 values [ins->dreg] = LLVMBuildShl (builder, lhs, rhs, dname);
4906 break;
4907 case OP_ISHR:
4908 case OP_LSHR:
4909 values [ins->dreg] = LLVMBuildAShr (builder, lhs, rhs, dname);
4910 break;
4911 case OP_ISHR_UN:
4912 case OP_LSHR_UN:
4913 values [ins->dreg] = LLVMBuildLShr (builder, lhs, rhs, dname);
4914 break;
4916 case OP_FADD:
4917 values [ins->dreg] = LLVMBuildFAdd (builder, lhs, rhs, dname);
4918 break;
4919 case OP_FSUB:
4920 values [ins->dreg] = LLVMBuildFSub (builder, lhs, rhs, dname);
4921 break;
4922 case OP_FMUL:
4923 values [ins->dreg] = LLVMBuildFMul (builder, lhs, rhs, dname);
4924 break;
4926 default:
4927 g_assert_not_reached ();
4929 break;
4930 case OP_RADD:
4931 case OP_RSUB:
4932 case OP_RMUL:
4933 case OP_RDIV: {
4934 lhs = convert (ctx, lhs, LLVMFloatType ());
4935 rhs = convert (ctx, rhs, LLVMFloatType ());
4936 switch (ins->opcode) {
4937 case OP_RADD:
4938 values [ins->dreg] = LLVMBuildFAdd (builder, lhs, rhs, dname);
4939 break;
4940 case OP_RSUB:
4941 values [ins->dreg] = LLVMBuildFSub (builder, lhs, rhs, dname);
4942 break;
4943 case OP_RMUL:
4944 values [ins->dreg] = LLVMBuildFMul (builder, lhs, rhs, dname);
4945 break;
4946 case OP_RDIV:
4947 values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, dname);
4948 break;
4949 default:
4950 g_assert_not_reached ();
4951 break;
4953 break;
4955 case OP_IADD_IMM:
4956 case OP_ISUB_IMM:
4957 case OP_IMUL_IMM:
4958 case OP_IREM_IMM:
4959 case OP_IREM_UN_IMM:
4960 case OP_IDIV_IMM:
4961 case OP_IDIV_UN_IMM:
4962 case OP_IAND_IMM:
4963 case OP_IOR_IMM:
4964 case OP_IXOR_IMM:
4965 case OP_ISHL_IMM:
4966 case OP_ISHR_IMM:
4967 case OP_ISHR_UN_IMM:
4968 case OP_LADD_IMM:
4969 case OP_LSUB_IMM:
4970 case OP_LMUL_IMM:
4971 case OP_LREM_IMM:
4972 case OP_LAND_IMM:
4973 case OP_LOR_IMM:
4974 case OP_LXOR_IMM:
4975 case OP_LSHL_IMM:
4976 case OP_LSHR_IMM:
4977 case OP_LSHR_UN_IMM:
4978 case OP_ADD_IMM:
4979 case OP_AND_IMM:
4980 case OP_MUL_IMM:
4981 case OP_SHL_IMM:
4982 case OP_SHR_IMM:
4983 case OP_SHR_UN_IMM: {
4984 LLVMValueRef imm;
4986 if (spec [MONO_INST_SRC1] == 'l') {
4987 imm = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins), FALSE);
4988 } else {
4989 imm = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
4992 emit_div_check (ctx, builder, bb, ins, lhs, imm);
4993 if (!ctx_ok (ctx))
4994 break;
4995 builder = ctx->builder;
4997 #if TARGET_SIZEOF_VOID_P == 4
4998 if (ins->opcode == OP_LSHL_IMM || ins->opcode == OP_LSHR_IMM || ins->opcode == OP_LSHR_UN_IMM)
4999 imm = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
5000 #endif
5002 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind)
5003 lhs = convert (ctx, lhs, IntPtrType ());
5004 imm = convert (ctx, imm, LLVMTypeOf (lhs));
5005 switch (ins->opcode) {
5006 case OP_IADD_IMM:
5007 case OP_LADD_IMM:
5008 case OP_ADD_IMM:
5009 values [ins->dreg] = LLVMBuildAdd (builder, lhs, imm, dname);
5010 break;
5011 case OP_ISUB_IMM:
5012 case OP_LSUB_IMM:
5013 values [ins->dreg] = LLVMBuildSub (builder, lhs, imm, dname);
5014 break;
5015 case OP_IMUL_IMM:
5016 case OP_MUL_IMM:
5017 case OP_LMUL_IMM:
5018 values [ins->dreg] = LLVMBuildMul (builder, lhs, imm, dname);
5019 break;
5020 case OP_IDIV_IMM:
5021 case OP_LDIV_IMM:
5022 values [ins->dreg] = LLVMBuildSDiv (builder, lhs, imm, dname);
5023 break;
5024 case OP_IDIV_UN_IMM:
5025 case OP_LDIV_UN_IMM:
5026 values [ins->dreg] = LLVMBuildUDiv (builder, lhs, imm, dname);
5027 break;
5028 case OP_IREM_IMM:
5029 case OP_LREM_IMM:
5030 values [ins->dreg] = LLVMBuildSRem (builder, lhs, imm, dname);
5031 break;
5032 case OP_IREM_UN_IMM:
5033 values [ins->dreg] = LLVMBuildURem (builder, lhs, imm, dname);
5034 break;
5035 case OP_IAND_IMM:
5036 case OP_LAND_IMM:
5037 case OP_AND_IMM:
5038 values [ins->dreg] = LLVMBuildAnd (builder, lhs, imm, dname);
5039 break;
5040 case OP_IOR_IMM:
5041 case OP_LOR_IMM:
5042 values [ins->dreg] = LLVMBuildOr (builder, lhs, imm, dname);
5043 break;
5044 case OP_IXOR_IMM:
5045 case OP_LXOR_IMM:
5046 values [ins->dreg] = LLVMBuildXor (builder, lhs, imm, dname);
5047 break;
5048 case OP_ISHL_IMM:
5049 case OP_LSHL_IMM:
5050 values [ins->dreg] = LLVMBuildShl (builder, lhs, imm, dname);
5051 break;
5052 case OP_SHL_IMM:
5053 if (TARGET_SIZEOF_VOID_P == 8) {
5054 /* The IL is not regular */
5055 lhs = convert (ctx, lhs, LLVMInt64Type ());
5056 imm = convert (ctx, imm, LLVMInt64Type ());
5058 values [ins->dreg] = LLVMBuildShl (builder, lhs, imm, dname);
5059 break;
5060 case OP_ISHR_IMM:
5061 case OP_LSHR_IMM:
5062 case OP_SHR_IMM:
5063 values [ins->dreg] = LLVMBuildAShr (builder, lhs, imm, dname);
5064 break;
5065 case OP_ISHR_UN_IMM:
5066 /* This is used to implement conv.u4, so the lhs could be an i8 */
5067 lhs = convert (ctx, lhs, LLVMInt32Type ());
5068 imm = convert (ctx, imm, LLVMInt32Type ());
5069 values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
5070 break;
5071 case OP_LSHR_UN_IMM:
5072 case OP_SHR_UN_IMM:
5073 values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
5074 break;
5075 default:
5076 g_assert_not_reached ();
5078 break;
5080 case OP_INEG:
5081 values [ins->dreg] = LLVMBuildSub (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), convert (ctx, lhs, LLVMInt32Type ()), dname);
5082 break;
5083 case OP_LNEG:
5084 values [ins->dreg] = LLVMBuildSub (builder, LLVMConstInt (LLVMInt64Type (), 0, FALSE), lhs, dname);
5085 break;
5086 case OP_FNEG:
5087 lhs = convert (ctx, lhs, LLVMDoubleType ());
5088 values [ins->dreg] = LLVMBuildFSub (builder, LLVMConstReal (LLVMDoubleType (), 0.0), lhs, dname);
5089 break;
5090 case OP_RNEG:
5091 lhs = convert (ctx, lhs, LLVMFloatType ());
5092 values [ins->dreg] = LLVMBuildFSub (builder, LLVMConstReal (LLVMFloatType (), 0.0), lhs, dname);
5093 break;
5094 case OP_INOT: {
5095 guint32 v = 0xffffffff;
5096 values [ins->dreg] = LLVMBuildXor (builder, LLVMConstInt (LLVMInt32Type (), v, FALSE), convert (ctx, lhs, LLVMInt32Type ()), dname);
5097 break;
5099 case OP_LNOT: {
5100 guint64 v = 0xffffffffffffffffLL;
5101 values [ins->dreg] = LLVMBuildXor (builder, LLVMConstInt (LLVMInt64Type (), v, FALSE), lhs, dname);
5102 break;
5104 #if defined(TARGET_X86) || defined(TARGET_AMD64)
5105 case OP_X86_LEA: {
5106 LLVMValueRef v1, v2;
5108 rhs = LLVMBuildSExt (builder, convert (ctx, rhs, LLVMInt32Type ()), LLVMInt64Type (), "");
5110 v1 = LLVMBuildMul (builder, convert (ctx, rhs, IntPtrType ()), LLVMConstInt (IntPtrType (), (1 << ins->backend.shift_amount), FALSE), "");
5111 v2 = LLVMBuildAdd (builder, convert (ctx, lhs, IntPtrType ()), v1, "");
5112 values [ins->dreg] = LLVMBuildAdd (builder, v2, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), dname);
5113 break;
5115 #endif
5117 case OP_ICONV_TO_I1:
5118 case OP_ICONV_TO_I2:
5119 case OP_ICONV_TO_I4:
5120 case OP_ICONV_TO_U1:
5121 case OP_ICONV_TO_U2:
5122 case OP_ICONV_TO_U4:
5123 case OP_LCONV_TO_I1:
5124 case OP_LCONV_TO_I2:
5125 case OP_LCONV_TO_U1:
5126 case OP_LCONV_TO_U2:
5127 case OP_LCONV_TO_U4: {
5128 gboolean sign;
5130 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);
5132 /* Have to do two casts since our vregs have type int */
5133 v = LLVMBuildTrunc (builder, lhs, op_to_llvm_type (ins->opcode), "");
5134 if (sign)
5135 values [ins->dreg] = LLVMBuildSExt (builder, v, LLVMInt32Type (), dname);
5136 else
5137 values [ins->dreg] = LLVMBuildZExt (builder, v, LLVMInt32Type (), dname);
5138 break;
5140 case OP_ICONV_TO_I8:
5141 values [ins->dreg] = LLVMBuildSExt (builder, lhs, LLVMInt64Type (), dname);
5142 break;
5143 case OP_ICONV_TO_U8:
5144 values [ins->dreg] = LLVMBuildZExt (builder, lhs, LLVMInt64Type (), dname);
5145 break;
5146 case OP_FCONV_TO_I4:
5147 case OP_RCONV_TO_I4:
5148 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, LLVMInt32Type (), dname);
5149 break;
5150 case OP_FCONV_TO_I1:
5151 case OP_RCONV_TO_I1:
5152 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildFPToSI (builder, lhs, LLVMInt8Type (), dname), LLVMInt32Type (), "");
5153 break;
5154 case OP_FCONV_TO_U1:
5155 case OP_RCONV_TO_U1:
5156 values [ins->dreg] = LLVMBuildZExt (builder, LLVMBuildTrunc (builder, LLVMBuildFPToUI (builder, lhs, IntPtrType (), dname), LLVMInt8Type (), ""), LLVMInt32Type (), "");
5157 break;
5158 case OP_FCONV_TO_I2:
5159 case OP_RCONV_TO_I2:
5160 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildFPToSI (builder, lhs, LLVMInt16Type (), dname), LLVMInt32Type (), "");
5161 break;
5162 case OP_FCONV_TO_U2:
5163 case OP_RCONV_TO_U2:
5164 values [ins->dreg] = LLVMBuildZExt (builder, LLVMBuildFPToUI (builder, lhs, LLVMInt16Type (), dname), LLVMInt32Type (), "");
5165 break;
5166 case OP_RCONV_TO_U4:
5167 values [ins->dreg] = LLVMBuildFPToUI (builder, lhs, LLVMInt32Type (), dname);
5168 break;
5169 case OP_FCONV_TO_I8:
5170 case OP_RCONV_TO_I8:
5171 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, LLVMInt64Type (), dname);
5172 break;
5173 case OP_FCONV_TO_I:
5174 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, IntPtrType (), dname);
5175 break;
5176 case OP_ICONV_TO_R8:
5177 case OP_LCONV_TO_R8:
5178 values [ins->dreg] = LLVMBuildSIToFP (builder, lhs, LLVMDoubleType (), dname);
5179 break;
5180 case OP_ICONV_TO_R_UN:
5181 case OP_LCONV_TO_R_UN:
5182 values [ins->dreg] = LLVMBuildUIToFP (builder, lhs, LLVMDoubleType (), dname);
5183 break;
5184 #if TARGET_SIZEOF_VOID_P == 4
5185 case OP_LCONV_TO_U:
5186 #endif
5187 case OP_LCONV_TO_I4:
5188 values [ins->dreg] = LLVMBuildTrunc (builder, lhs, LLVMInt32Type (), dname);
5189 break;
5190 case OP_ICONV_TO_R4:
5191 case OP_LCONV_TO_R4:
5192 v = LLVMBuildSIToFP (builder, lhs, LLVMFloatType (), "");
5193 if (cfg->r4fp)
5194 values [ins->dreg] = v;
5195 else
5196 values [ins->dreg] = LLVMBuildFPExt (builder, v, LLVMDoubleType (), dname);
5197 break;
5198 case OP_FCONV_TO_R4:
5199 v = LLVMBuildFPTrunc (builder, lhs, LLVMFloatType (), "");
5200 if (cfg->r4fp)
5201 values [ins->dreg] = v;
5202 else
5203 values [ins->dreg] = LLVMBuildFPExt (builder, v, LLVMDoubleType (), dname);
5204 break;
5205 case OP_RCONV_TO_R8:
5206 values [ins->dreg] = LLVMBuildFPExt (builder, lhs, LLVMDoubleType (), dname);
5207 break;
5208 case OP_RCONV_TO_R4:
5209 values [ins->dreg] = lhs;
5210 break;
5211 case OP_SEXT_I4:
5212 values [ins->dreg] = LLVMBuildSExt (builder, convert (ctx, lhs, LLVMInt32Type ()), LLVMInt64Type (), dname);
5213 break;
5214 case OP_ZEXT_I4:
5215 values [ins->dreg] = LLVMBuildZExt (builder, convert (ctx, lhs, LLVMInt32Type ()), LLVMInt64Type (), dname);
5216 break;
5217 case OP_TRUNC_I4:
5218 values [ins->dreg] = LLVMBuildTrunc (builder, lhs, LLVMInt32Type (), dname);
5219 break;
5220 case OP_LOCALLOC_IMM: {
5221 LLVMValueRef v;
5223 guint32 size = ins->inst_imm;
5224 size = (size + (MONO_ARCH_FRAME_ALIGNMENT - 1)) & ~ (MONO_ARCH_FRAME_ALIGNMENT - 1);
5226 v = mono_llvm_build_alloca (builder, LLVMInt8Type (), LLVMConstInt (LLVMInt32Type (), size, FALSE), MONO_ARCH_FRAME_ALIGNMENT, "");
5228 if (ins->flags & MONO_INST_INIT) {
5229 LLVMValueRef args [5];
5231 args [0] = v;
5232 args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
5233 args [2] = LLVMConstInt (LLVMInt32Type (), size, FALSE);
5234 args [3] = LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT, FALSE);
5235 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5236 LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memset.p0i8.i32"), args, 5, "");
5239 values [ins->dreg] = v;
5240 break;
5242 case OP_LOCALLOC: {
5243 LLVMValueRef v, size;
5245 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), "");
5247 v = mono_llvm_build_alloca (builder, LLVMInt8Type (), size, MONO_ARCH_FRAME_ALIGNMENT, "");
5249 if (ins->flags & MONO_INST_INIT) {
5250 LLVMValueRef args [5];
5252 args [0] = v;
5253 args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
5254 args [2] = size;
5255 args [3] = LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT, FALSE);
5256 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5257 LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memset.p0i8.i32"), args, 5, "");
5259 values [ins->dreg] = v;
5260 break;
5263 case OP_LOADI1_MEMBASE:
5264 case OP_LOADU1_MEMBASE:
5265 case OP_LOADI2_MEMBASE:
5266 case OP_LOADU2_MEMBASE:
5267 case OP_LOADI4_MEMBASE:
5268 case OP_LOADU4_MEMBASE:
5269 case OP_LOADI8_MEMBASE:
5270 case OP_LOADR4_MEMBASE:
5271 case OP_LOADR8_MEMBASE:
5272 case OP_LOAD_MEMBASE:
5273 case OP_LOADI8_MEM:
5274 case OP_LOADU1_MEM:
5275 case OP_LOADU2_MEM:
5276 case OP_LOADI4_MEM:
5277 case OP_LOADU4_MEM:
5278 case OP_LOAD_MEM: {
5279 int size = 8;
5280 LLVMValueRef base, index, addr;
5281 LLVMTypeRef t;
5282 gboolean sext = FALSE, zext = FALSE;
5283 gboolean is_volatile = (ins->flags & (MONO_INST_FAULT | MONO_INST_VOLATILE)) != 0;
5285 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5287 if (sext || zext)
5288 dname = (char*)"";
5290 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)) {
5291 addr = LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE);
5292 base = addr;
5293 } else {
5294 /* _MEMBASE */
5295 base = lhs;
5297 if (ins->inst_offset == 0) {
5298 addr = base;
5299 } else if (ins->inst_offset % size != 0) {
5300 /* Unaligned load */
5301 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
5302 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
5303 } else {
5304 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5305 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5309 addr = convert (ctx, addr, LLVMPointerType (t, 0));
5311 values [ins->dreg] = emit_load_general (ctx, bb, &builder, size, addr, base, dname, is_volatile, LLVM_BARRIER_NONE);
5313 if (!is_volatile && (ins->flags & MONO_INST_INVARIANT_LOAD)) {
5315 * These will signal LLVM that these loads do not alias any stores, and
5316 * they can't fail, allowing them to be hoisted out of loops.
5318 set_invariant_load_flag (values [ins->dreg]);
5319 #if LLVM_API_VERSION < 100
5320 set_metadata_flag (values [ins->dreg], "mono.nofail.load");
5321 #endif
5324 if (sext)
5325 values [ins->dreg] = LLVMBuildSExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5326 else if (zext)
5327 values [ins->dreg] = LLVMBuildZExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5328 else if (!cfg->r4fp && ins->opcode == OP_LOADR4_MEMBASE)
5329 values [ins->dreg] = LLVMBuildFPExt (builder, values [ins->dreg], LLVMDoubleType (), dname);
5330 break;
5333 case OP_STOREI1_MEMBASE_REG:
5334 case OP_STOREI2_MEMBASE_REG:
5335 case OP_STOREI4_MEMBASE_REG:
5336 case OP_STOREI8_MEMBASE_REG:
5337 case OP_STORER4_MEMBASE_REG:
5338 case OP_STORER8_MEMBASE_REG:
5339 case OP_STORE_MEMBASE_REG: {
5340 int size = 8;
5341 LLVMValueRef index, addr, base;
5342 LLVMTypeRef t;
5343 gboolean sext = FALSE, zext = FALSE;
5344 gboolean is_volatile = (ins->flags & (MONO_INST_FAULT | MONO_INST_VOLATILE)) != 0;
5346 if (!values [ins->inst_destbasereg]) {
5347 set_failure (ctx, "inst_destbasereg");
5348 break;
5351 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5353 base = values [ins->inst_destbasereg];
5354 if (ins->inst_offset % size != 0) {
5355 /* Unaligned store */
5356 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
5357 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
5358 } else {
5359 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5360 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5362 emit_store (ctx, bb, &builder, size, convert (ctx, values [ins->sreg1], t), convert (ctx, addr, LLVMPointerType (t, 0)), base, is_volatile);
5363 break;
5366 case OP_STOREI1_MEMBASE_IMM:
5367 case OP_STOREI2_MEMBASE_IMM:
5368 case OP_STOREI4_MEMBASE_IMM:
5369 case OP_STOREI8_MEMBASE_IMM:
5370 case OP_STORE_MEMBASE_IMM: {
5371 int size = 8;
5372 LLVMValueRef index, addr, base;
5373 LLVMTypeRef t;
5374 gboolean sext = FALSE, zext = FALSE;
5375 gboolean is_volatile = (ins->flags & (MONO_INST_FAULT | MONO_INST_VOLATILE)) != 0;
5377 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5379 base = values [ins->inst_destbasereg];
5380 if (ins->inst_offset % size != 0) {
5381 /* Unaligned store */
5382 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
5383 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
5384 } else {
5385 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5386 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5388 emit_store (ctx, bb, &builder, size, convert (ctx, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), t), convert (ctx, addr, LLVMPointerType (t, 0)), base, is_volatile);
5389 break;
5392 case OP_CHECK_THIS:
5393 emit_load_general (ctx, bb, &builder, sizeof (gpointer), convert (ctx, lhs, LLVMPointerType (IntPtrType (), 0)), lhs, "", TRUE, LLVM_BARRIER_NONE);
5394 break;
5395 case OP_OUTARG_VTRETADDR:
5396 break;
5397 case OP_VOIDCALL:
5398 case OP_CALL:
5399 case OP_LCALL:
5400 case OP_FCALL:
5401 case OP_RCALL:
5402 case OP_VCALL:
5403 case OP_VOIDCALL_MEMBASE:
5404 case OP_CALL_MEMBASE:
5405 case OP_LCALL_MEMBASE:
5406 case OP_FCALL_MEMBASE:
5407 case OP_RCALL_MEMBASE:
5408 case OP_VCALL_MEMBASE:
5409 case OP_VOIDCALL_REG:
5410 case OP_CALL_REG:
5411 case OP_LCALL_REG:
5412 case OP_FCALL_REG:
5413 case OP_RCALL_REG:
5414 case OP_VCALL_REG: {
5415 process_call (ctx, bb, &builder, ins);
5416 break;
5418 case OP_AOTCONST: {
5419 guint32 got_offset;
5420 LLVMValueRef indexes [2];
5421 MonoJumpInfo *tmp_ji, *ji;
5422 LLVMValueRef got_entry_addr;
5423 char *name;
5426 * FIXME: Can't allocate from the cfg mempool since that is freed if
5427 * the LLVM compile fails.
5429 tmp_ji = g_new0 (MonoJumpInfo, 1);
5430 tmp_ji->type = (MonoJumpInfoType)ins->inst_c1;
5431 tmp_ji->data.target = ins->inst_p0;
5433 ji = mono_aot_patch_info_dup (tmp_ji);
5434 g_free (tmp_ji);
5436 if (ji->type == MONO_PATCH_INFO_ICALL_ADDR) {
5437 char *symbol = mono_aot_get_direct_call_symbol (MONO_PATCH_INFO_ICALL_ADDR_CALL, ji->data.target);
5438 if (symbol) {
5440 * Avoid emitting a got entry for these since the method is directly called, and it might not be
5441 * resolvable at runtime using dlsym ().
5443 g_free (symbol);
5444 values [ins->dreg] = LLVMConstInt (IntPtrType (), 0, FALSE);
5445 break;
5449 ji->next = cfg->patch_info;
5450 cfg->patch_info = ji;
5452 //mono_add_patch_info (cfg, 0, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
5453 got_offset = mono_aot_get_got_offset (cfg->patch_info);
5454 ctx->module->max_got_offset = MAX (ctx->module->max_got_offset, got_offset);
5455 if (!mono_aot_is_shared_got_offset (got_offset)) {
5456 //mono_print_ji (ji);
5457 //printf ("\n");
5458 ctx->has_got_access = TRUE;
5461 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5462 indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
5463 got_entry_addr = LLVMBuildGEP (builder, ctx->module->got_var, indexes, 2, "");
5465 name = get_aotconst_name (ji->type, ji->data.target, got_offset);
5466 values [ins->dreg] = LLVMBuildLoad (builder, got_entry_addr, name);
5467 g_free (name);
5468 /* Can't use this in llvmonly mode since the got slots are initialized by the methods themselves */
5469 if (!cfg->llvm_only)
5470 set_invariant_load_flag (values [ins->dreg]);
5471 break;
5473 case OP_NOT_REACHED:
5474 LLVMBuildUnreachable (builder);
5475 has_terminator = TRUE;
5476 g_assert (bb->block_num < cfg->max_block_num);
5477 ctx->unreachable [bb->block_num] = TRUE;
5478 /* Might have instructions after this */
5479 while (ins->next) {
5480 MonoInst *next = ins->next;
5482 * FIXME: If later code uses the regs defined by these instructions,
5483 * compilation will fail.
5485 MONO_DELETE_INS (bb, next);
5487 break;
5488 case OP_LDADDR: {
5489 MonoInst *var = ins->inst_i0;
5491 if (var->opcode == OP_VTARG_ADDR) {
5492 /* The variable contains the vtype address */
5493 values [ins->dreg] = values [var->dreg];
5494 } else if (var->opcode == OP_GSHAREDVT_LOCAL) {
5495 values [ins->dreg] = emit_gsharedvt_ldaddr (ctx, var->dreg);
5496 } else {
5497 values [ins->dreg] = addresses [var->dreg];
5499 break;
5501 case OP_SIN: {
5502 LLVMValueRef args [1];
5504 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5505 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.sin.f64"), args, 1, dname);
5506 break;
5508 case OP_SINF: {
5509 LLVMValueRef args [1];
5511 args [0] = convert (ctx, lhs, LLVMFloatType ());
5512 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.sin.f32"), args, 1, dname);
5513 break;
5515 case OP_COS: {
5516 LLVMValueRef args [1];
5518 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5519 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.cos.f64"), args, 1, dname);
5520 break;
5522 case OP_COSF: {
5523 LLVMValueRef args [1];
5525 args [0] = convert (ctx, lhs, LLVMFloatType ());
5526 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.cos.f32"), args, 1, dname);
5527 break;
5529 case OP_SQRT: {
5530 LLVMValueRef args [1];
5532 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5533 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.sqrt.f64"), args, 1, dname);
5534 break;
5536 case OP_SQRTF: {
5537 LLVMValueRef args [1];
5539 args [0] = convert (ctx, lhs, LLVMFloatType ());
5540 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.sqrt.f32"), args, 1, dname);
5541 break;
5543 case OP_ABS: {
5544 LLVMValueRef args [1];
5546 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5547 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "fabs"), args, 1, dname);
5548 break;
5550 case OP_ABSF: {
5551 LLVMValueRef args [1];
5553 #ifdef TARGET_AMD64
5554 args [0] = convert (ctx, lhs, LLVMFloatType ());
5555 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.fabs.f32"), args, 1, dname);
5556 #else
5557 /* llvm.fabs not supported on all platforms */
5558 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5559 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "fabs"), args, 1, dname);
5560 values [ins->dreg] = convert (ctx, values [ins->dreg], LLVMFloatType ());
5561 #endif
5562 break;
5564 case OP_RPOW: {
5565 LLVMValueRef args [2];
5567 args [0] = convert (ctx, lhs, LLVMFloatType ());
5568 args [1] = convert (ctx, rhs, LLVMFloatType ());
5569 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.pow.f32"), args, 2, dname);
5570 break;
5573 case OP_IMIN:
5574 case OP_LMIN:
5575 case OP_IMAX:
5576 case OP_LMAX:
5577 case OP_IMIN_UN:
5578 case OP_LMIN_UN:
5579 case OP_IMAX_UN:
5580 case OP_LMAX_UN:
5581 case OP_RMAX: {
5582 LLVMValueRef v;
5584 lhs = convert (ctx, lhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
5585 rhs = convert (ctx, rhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
5587 switch (ins->opcode) {
5588 case OP_IMIN:
5589 case OP_LMIN:
5590 v = LLVMBuildICmp (builder, LLVMIntSLE, lhs, rhs, "");
5591 break;
5592 case OP_IMAX:
5593 case OP_LMAX:
5594 v = LLVMBuildICmp (builder, LLVMIntSGE, lhs, rhs, "");
5595 break;
5596 case OP_IMIN_UN:
5597 case OP_LMIN_UN:
5598 v = LLVMBuildICmp (builder, LLVMIntULE, lhs, rhs, "");
5599 break;
5600 case OP_IMAX_UN:
5601 case OP_LMAX_UN:
5602 v = LLVMBuildICmp (builder, LLVMIntUGE, lhs, rhs, "");
5603 break;
5604 case OP_RMAX:
5605 v = LLVMBuildFCmp (builder, LLVMRealUGE, lhs, rhs, "");
5606 break;
5607 default:
5608 g_assert_not_reached ();
5609 break;
5611 values [ins->dreg] = LLVMBuildSelect (builder, v, lhs, rhs, dname);
5612 break;
5616 * See the ARM64 comment in mono/utils/atomic.h for an explanation of why this
5617 * hack is necessary (for now).
5619 #ifdef TARGET_ARM64
5620 #define ARM64_ATOMIC_FENCE_FIX mono_llvm_build_fence (builder, LLVM_BARRIER_SEQ)
5621 #else
5622 #define ARM64_ATOMIC_FENCE_FIX
5623 #endif
5625 case OP_ATOMIC_EXCHANGE_I4:
5626 case OP_ATOMIC_EXCHANGE_I8: {
5627 LLVMValueRef args [2];
5628 LLVMTypeRef t;
5630 if (ins->opcode == OP_ATOMIC_EXCHANGE_I4)
5631 t = LLVMInt32Type ();
5632 else
5633 t = LLVMInt64Type ();
5635 g_assert (ins->inst_offset == 0);
5637 args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
5638 args [1] = convert (ctx, rhs, t);
5640 ARM64_ATOMIC_FENCE_FIX;
5641 values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
5642 ARM64_ATOMIC_FENCE_FIX;
5643 break;
5645 case OP_ATOMIC_ADD_I4:
5646 case OP_ATOMIC_ADD_I8: {
5647 LLVMValueRef args [2];
5648 LLVMTypeRef t;
5650 if (ins->opcode == OP_ATOMIC_ADD_I4)
5651 t = LLVMInt32Type ();
5652 else
5653 t = LLVMInt64Type ();
5655 g_assert (ins->inst_offset == 0);
5657 args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
5658 args [1] = convert (ctx, rhs, t);
5659 ARM64_ATOMIC_FENCE_FIX;
5660 values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname);
5661 ARM64_ATOMIC_FENCE_FIX;
5662 break;
5664 case OP_ATOMIC_CAS_I4:
5665 case OP_ATOMIC_CAS_I8: {
5666 LLVMValueRef args [3], val;
5667 LLVMTypeRef t;
5669 if (ins->opcode == OP_ATOMIC_CAS_I4)
5670 t = LLVMInt32Type ();
5671 else
5672 t = LLVMInt64Type ();
5674 args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
5675 /* comparand */
5676 args [1] = convert (ctx, values [ins->sreg3], t);
5677 /* new value */
5678 args [2] = convert (ctx, values [ins->sreg2], t);
5679 ARM64_ATOMIC_FENCE_FIX;
5680 val = mono_llvm_build_cmpxchg (builder, args [0], args [1], args [2]);
5681 ARM64_ATOMIC_FENCE_FIX;
5682 /* cmpxchg returns a pair */
5683 values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, "");
5684 break;
5686 case OP_MEMORY_BARRIER: {
5687 mono_llvm_build_fence (builder, (BarrierKind) ins->backend.memory_barrier_kind);
5688 break;
5690 case OP_ATOMIC_LOAD_I1:
5691 case OP_ATOMIC_LOAD_I2:
5692 case OP_ATOMIC_LOAD_I4:
5693 case OP_ATOMIC_LOAD_I8:
5694 case OP_ATOMIC_LOAD_U1:
5695 case OP_ATOMIC_LOAD_U2:
5696 case OP_ATOMIC_LOAD_U4:
5697 case OP_ATOMIC_LOAD_U8:
5698 case OP_ATOMIC_LOAD_R4:
5699 case OP_ATOMIC_LOAD_R8: {
5700 #if LLVM_API_VERSION > 100
5701 int size;
5702 gboolean sext, zext;
5703 LLVMTypeRef t;
5704 gboolean is_volatile = (ins->flags & (MONO_INST_FAULT | MONO_INST_VOLATILE)) != 0;
5705 BarrierKind barrier = (BarrierKind) ins->backend.memory_barrier_kind;
5706 LLVMValueRef index, addr;
5708 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5710 if (sext || zext)
5711 dname = (char *)"";
5713 if (ins->inst_offset != 0) {
5714 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5715 addr = LLVMBuildGEP (builder, convert (ctx, lhs, LLVMPointerType (t, 0)), &index, 1, "");
5716 } else {
5717 addr = lhs;
5720 addr = convert (ctx, addr, LLVMPointerType (t, 0));
5722 ARM64_ATOMIC_FENCE_FIX;
5723 values [ins->dreg] = emit_load_general (ctx, bb, &builder, size, addr, lhs, dname, is_volatile, barrier);
5724 ARM64_ATOMIC_FENCE_FIX;
5726 if (sext)
5727 values [ins->dreg] = LLVMBuildSExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5728 else if (zext)
5729 values [ins->dreg] = LLVMBuildZExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5730 break;
5731 #else
5732 set_failure (ctx, "atomic mono.load intrinsic");
5733 break;
5734 #endif
5736 case OP_ATOMIC_STORE_I1:
5737 case OP_ATOMIC_STORE_I2:
5738 case OP_ATOMIC_STORE_I4:
5739 case OP_ATOMIC_STORE_I8:
5740 case OP_ATOMIC_STORE_U1:
5741 case OP_ATOMIC_STORE_U2:
5742 case OP_ATOMIC_STORE_U4:
5743 case OP_ATOMIC_STORE_U8:
5744 case OP_ATOMIC_STORE_R4:
5745 case OP_ATOMIC_STORE_R8: {
5746 int size;
5747 gboolean sext, zext;
5748 LLVMTypeRef t;
5749 gboolean is_volatile = (ins->flags & (MONO_INST_FAULT | MONO_INST_VOLATILE)) != 0;
5750 BarrierKind barrier = (BarrierKind) ins->backend.memory_barrier_kind;
5751 LLVMValueRef index, addr, value, base;
5753 #if LLVM_API_VERSION < 100
5754 if (!cfg->llvm_only) {
5755 set_failure (ctx, "atomic mono.store intrinsic");
5756 break;
5758 #endif
5760 if (!values [ins->inst_destbasereg]) {
5761 set_failure (ctx, "inst_destbasereg");
5762 break;
5765 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5767 base = values [ins->inst_destbasereg];
5768 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5769 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5770 value = convert (ctx, values [ins->sreg1], t);
5772 ARM64_ATOMIC_FENCE_FIX;
5773 emit_store_general (ctx, bb, &builder, size, value, addr, base, is_volatile, barrier);
5774 ARM64_ATOMIC_FENCE_FIX;
5775 break;
5777 case OP_RELAXED_NOP: {
5778 #if defined(TARGET_AMD64) || defined(TARGET_X86)
5779 emit_call (ctx, bb, &builder, get_intrinsic (ctx, "llvm.x86.sse2.pause"), NULL, 0);
5780 break;
5781 #else
5782 break;
5783 #endif
5785 case OP_TLS_GET: {
5786 #if (defined(TARGET_AMD64) || defined(TARGET_X86)) && defined(__linux__)
5787 #ifdef TARGET_AMD64
5788 // 257 == FS segment register
5789 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 257);
5790 #else
5791 // 256 == GS segment register
5792 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
5793 #endif
5794 // FIXME: XEN
5795 values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), ins->inst_offset, TRUE), ptrtype, ""), "");
5796 #elif defined(TARGET_AMD64) && defined(TARGET_OSX)
5797 /* See mono_amd64_emit_tls_get () */
5798 int offset = mono_amd64_get_tls_gs_offset () + (ins->inst_offset * 8);
5800 // 256 == GS segment register
5801 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
5802 values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), offset, TRUE), ptrtype, ""), "");
5803 #else
5804 set_failure (ctx, "opcode tls-get");
5805 break;
5806 #endif
5808 break;
5810 case OP_GC_SAFE_POINT: {
5811 LLVMValueRef val, cmp, callee;
5812 LLVMBasicBlockRef poll_bb, cont_bb;
5813 static LLVMTypeRef sig;
5814 const char *icall_name = "mono_threads_state_poll";
5816 if (!sig)
5817 sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
5820 * if (!*sreg1)
5821 * mono_threads_state_poll ();
5822 * FIXME: Use a preserveall wrapper
5824 val = mono_llvm_build_load (builder, convert (ctx, lhs, LLVMPointerType (IntPtrType (), 0)), "", TRUE);
5825 cmp = LLVMBuildICmp (builder, LLVMIntEQ, val, LLVMConstNull (LLVMTypeOf (val)), "");
5826 poll_bb = gen_bb (ctx, "POLL_BB");
5827 cont_bb = gen_bb (ctx, "CONT_BB");
5828 LLVMBuildCondBr (builder, cmp, cont_bb, poll_bb);
5830 ctx->builder = builder = create_builder (ctx);
5831 LLVMPositionBuilderAtEnd (builder, poll_bb);
5833 if (ctx->cfg->compile_aot) {
5834 callee = get_callee (ctx, sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
5835 } else {
5836 gpointer target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
5837 callee = emit_jit_callee (ctx, icall_name, sig, target);
5839 LLVMBuildCall (builder, callee, NULL, 0, "");
5840 LLVMBuildBr (builder, cont_bb);
5842 ctx->builder = builder = create_builder (ctx);
5843 LLVMPositionBuilderAtEnd (builder, cont_bb);
5844 ctx->bblocks [bb->block_num].end_bblock = cont_bb;
5845 break;
5849 * Overflow opcodes.
5851 case OP_IADD_OVF:
5852 case OP_IADD_OVF_UN:
5853 case OP_ISUB_OVF:
5854 case OP_ISUB_OVF_UN:
5855 case OP_IMUL_OVF:
5856 case OP_IMUL_OVF_UN:
5857 case OP_LADD_OVF:
5858 case OP_LADD_OVF_UN:
5859 case OP_LSUB_OVF:
5860 case OP_LSUB_OVF_UN:
5861 case OP_LMUL_OVF:
5862 case OP_LMUL_OVF_UN:
5864 LLVMValueRef args [2], val, ovf, func;
5866 args [0] = convert (ctx, lhs, op_to_llvm_type (ins->opcode));
5867 args [1] = convert (ctx, rhs, op_to_llvm_type (ins->opcode));
5868 func = get_intrinsic (ctx, ovf_op_to_intrins (ins->opcode));
5869 g_assert (func);
5870 val = LLVMBuildCall (builder, func, args, 2, "");
5871 values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, dname);
5872 ovf = LLVMBuildExtractValue (builder, val, 1, "");
5873 emit_cond_system_exception (ctx, bb, "OverflowException", ovf);
5874 if (!ctx_ok (ctx))
5875 break;
5876 builder = ctx->builder;
5877 break;
5881 * Valuetypes.
5882 * We currently model them using arrays. Promotion to local vregs is
5883 * disabled for them in mono_handle_global_vregs () in the LLVM case,
5884 * so we always have an entry in cfg->varinfo for them.
5885 * FIXME: Is this needed ?
5887 case OP_VZERO: {
5888 MonoClass *klass = ins->klass;
5889 LLVMValueRef args [5];
5891 if (!klass) {
5892 // FIXME:
5893 set_failure (ctx, "!klass");
5894 break;
5897 if (!addresses [ins->dreg])
5898 addresses [ins->dreg] = build_alloca (ctx, m_class_get_byval_arg (klass));
5899 args [0] = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
5900 args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
5901 args [2] = LLVMConstInt (LLVMInt32Type (), mono_class_value_size (klass, NULL), FALSE);
5902 // FIXME: Alignment
5903 args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5904 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5905 LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memset.p0i8.i32"), args, 5, "");
5906 break;
5908 case OP_DUMMY_VZERO:
5909 break;
5911 case OP_STOREV_MEMBASE:
5912 case OP_LOADV_MEMBASE:
5913 case OP_VMOVE: {
5914 MonoClass *klass = ins->klass;
5915 LLVMValueRef src = NULL, dst, args [5];
5916 gboolean done = FALSE;
5918 if (!klass) {
5919 // FIXME:
5920 set_failure (ctx, "!klass");
5921 break;
5924 if (mini_is_gsharedvt_klass (klass)) {
5925 // FIXME:
5926 set_failure (ctx, "gsharedvt");
5927 break;
5930 switch (ins->opcode) {
5931 case OP_STOREV_MEMBASE:
5932 if (cfg->gen_write_barriers && m_class_has_references (klass) && ins->inst_destbasereg != cfg->frame_reg &&
5933 LLVMGetInstructionOpcode (values [ins->inst_destbasereg]) != LLVMAlloca) {
5934 /* Decomposed earlier */
5935 g_assert_not_reached ();
5936 break;
5938 if (!addresses [ins->sreg1]) {
5939 /* SIMD */
5940 g_assert (values [ins->sreg1]);
5941 dst = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_destbasereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (type_to_llvm_type (ctx, m_class_get_byval_arg (klass)), 0));
5942 LLVMBuildStore (builder, values [ins->sreg1], dst);
5943 done = TRUE;
5944 } else {
5945 src = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (LLVMInt8Type (), 0), "");
5946 dst = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_destbasereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (LLVMInt8Type (), 0));
5948 break;
5949 case OP_LOADV_MEMBASE:
5950 if (!addresses [ins->dreg])
5951 addresses [ins->dreg] = build_alloca (ctx, m_class_get_byval_arg (klass));
5952 src = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_basereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (LLVMInt8Type (), 0));
5953 dst = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
5954 break;
5955 case OP_VMOVE:
5956 if (!addresses [ins->sreg1])
5957 addresses [ins->sreg1] = build_alloca (ctx, m_class_get_byval_arg (klass));
5958 if (!addresses [ins->dreg])
5959 addresses [ins->dreg] = build_alloca (ctx, m_class_get_byval_arg (klass));
5960 src = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (LLVMInt8Type (), 0), "");
5961 dst = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
5962 break;
5963 default:
5964 g_assert_not_reached ();
5966 if (!ctx_ok (ctx))
5967 break;
5969 if (done)
5970 break;
5972 args [0] = dst;
5973 args [1] = src;
5974 args [2] = LLVMConstInt (LLVMInt32Type (), mono_class_value_size (klass, NULL), FALSE);
5975 args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5976 // FIXME: Alignment
5977 args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5978 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5979 LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memcpy.p0i8.p0i8.i32"), args, 5, "");
5980 break;
5982 case OP_LLVM_OUTARG_VT: {
5983 LLVMArgInfo *ainfo = (LLVMArgInfo*)ins->inst_p0;
5984 MonoType *t = mini_get_underlying_type (ins->inst_vtype);
5986 if (ainfo->storage == LLVMArgGsharedvtVariable) {
5987 MonoInst *var = get_vreg_to_inst (cfg, ins->sreg1);
5989 if (var && var->opcode == OP_GSHAREDVT_LOCAL) {
5990 addresses [ins->dreg] = convert (ctx, emit_gsharedvt_ldaddr (ctx, var->dreg), LLVMPointerType (IntPtrType (), 0));
5991 } else {
5992 g_assert (addresses [ins->sreg1]);
5993 addresses [ins->dreg] = addresses [ins->sreg1];
5995 } else if (ainfo->storage == LLVMArgGsharedvtFixed) {
5996 if (!addresses [ins->sreg1]) {
5997 addresses [ins->sreg1] = build_alloca (ctx, t);
5998 g_assert (values [ins->sreg1]);
6000 LLVMBuildStore (builder, convert (ctx, values [ins->sreg1], LLVMGetElementType (LLVMTypeOf (addresses [ins->sreg1]))), addresses [ins->sreg1]);
6001 addresses [ins->dreg] = addresses [ins->sreg1];
6002 } else {
6003 if (!addresses [ins->sreg1]) {
6004 addresses [ins->sreg1] = build_alloca (ctx, t);
6005 g_assert (values [ins->sreg1]);
6006 LLVMBuildStore (builder, convert (ctx, values [ins->sreg1], type_to_llvm_type (ctx, t)), addresses [ins->sreg1]);
6007 addresses [ins->dreg] = addresses [ins->sreg1];
6008 } else if (values [ins->sreg1] == addresses [ins->sreg1]) {
6009 /* LLVMArgVtypeByRef, have to make a copy */
6010 addresses [ins->dreg] = build_alloca (ctx, t);
6011 LLVMValueRef v = LLVMBuildLoad (builder, addresses [ins->sreg1], "");
6012 LLVMBuildStore (builder, convert (ctx, v, type_to_llvm_type (ctx, t)), addresses [ins->dreg]);
6013 } else {
6014 addresses [ins->dreg] = addresses [ins->sreg1];
6017 break;
6019 case OP_OBJC_GET_SELECTOR: {
6020 const char *name = (const char*)ins->inst_p0;
6021 LLVMValueRef var;
6023 if (!ctx->module->objc_selector_to_var) {
6024 ctx->module->objc_selector_to_var = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
6026 LLVMValueRef info_var = LLVMAddGlobal (ctx->lmodule, LLVMArrayType (LLVMInt8Type (), 8), "@OBJC_IMAGE_INFO");
6027 int32_t objc_imageinfo [] = { 0, 16 };
6028 LLVMSetInitializer (info_var, mono_llvm_create_constant_data_array ((uint8_t *) &objc_imageinfo, 8));
6029 LLVMSetLinkage (info_var, LLVMPrivateLinkage);
6030 LLVMSetExternallyInitialized (info_var, TRUE);
6031 LLVMSetSection (info_var, "__DATA, __objc_imageinfo,regular,no_dead_strip");
6032 LLVMSetAlignment (info_var, sizeof (mgreg_t));
6033 mark_as_used (ctx->module, info_var);
6036 var = (LLVMValueRef)g_hash_table_lookup (ctx->module->objc_selector_to_var, name);
6037 if (!var) {
6038 LLVMValueRef indexes [16];
6040 LLVMValueRef name_var = LLVMAddGlobal (ctx->lmodule, LLVMArrayType (LLVMInt8Type (), strlen (name) + 1), "@OBJC_METH_VAR_NAME_");
6041 LLVMSetInitializer (name_var, mono_llvm_create_constant_data_array ((const uint8_t*)name, strlen (name) + 1));
6042 LLVMSetLinkage (name_var, LLVMPrivateLinkage);
6043 LLVMSetSection (name_var, "__TEXT,__objc_methname,cstring_literals");
6044 mark_as_used (ctx->module, name_var);
6046 LLVMValueRef ref_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (LLVMInt8Type (), 0), "@OBJC_SELECTOR_REFERENCES_");
6048 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, 0);
6049 indexes [1] = LLVMConstInt (LLVMInt32Type (), 0, 0);
6050 LLVMSetInitializer (ref_var, LLVMConstGEP (name_var, indexes, 2));
6051 LLVMSetLinkage (ref_var, LLVMPrivateLinkage);
6052 LLVMSetExternallyInitialized (ref_var, TRUE);
6053 LLVMSetSection (ref_var, "__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
6054 LLVMSetAlignment (ref_var, sizeof (mgreg_t));
6055 mark_as_used (ctx->module, ref_var);
6057 g_hash_table_insert (ctx->module->objc_selector_to_var, g_strdup (name), ref_var);
6058 var = ref_var;
6061 values [ins->dreg] = LLVMBuildLoad (builder, var, "");
6062 break;
6066 * SIMD
6068 #if defined(TARGET_X86) || defined(TARGET_AMD64)
6069 case OP_XZERO: {
6070 values [ins->dreg] = LLVMConstNull (type_to_llvm_type (ctx, m_class_get_byval_arg (ins->klass)));
6071 break;
6073 case OP_LOADX_MEMBASE: {
6074 LLVMTypeRef t = type_to_llvm_type (ctx, m_class_get_byval_arg (ins->klass));
6075 LLVMValueRef src;
6077 src = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_basereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (t, 0));
6078 values [ins->dreg] = mono_llvm_build_aligned_load (builder, src, "", FALSE, 1);
6079 break;
6081 case OP_STOREX_MEMBASE: {
6082 LLVMTypeRef t = LLVMTypeOf (values [ins->sreg1]);
6083 LLVMValueRef dest;
6085 dest = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_destbasereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (t, 0));
6086 mono_llvm_build_aligned_store (builder, values [ins->sreg1], dest, FALSE, 1);
6087 break;
6089 case OP_PADDB:
6090 case OP_PADDW:
6091 case OP_PADDD:
6092 case OP_PADDQ:
6093 values [ins->dreg] = LLVMBuildAdd (builder, lhs, rhs, "");
6094 break;
6095 case OP_ADDPD:
6096 case OP_ADDPS:
6097 values [ins->dreg] = LLVMBuildFAdd (builder, lhs, rhs, "");
6098 break;
6099 case OP_PSUBB:
6100 case OP_PSUBW:
6101 case OP_PSUBD:
6102 case OP_PSUBQ:
6103 values [ins->dreg] = LLVMBuildSub (builder, lhs, rhs, "");
6104 break;
6105 case OP_SUBPD:
6106 case OP_SUBPS:
6107 values [ins->dreg] = LLVMBuildFSub (builder, lhs, rhs, "");
6108 break;
6109 case OP_MULPD:
6110 case OP_MULPS:
6111 values [ins->dreg] = LLVMBuildFMul (builder, lhs, rhs, "");
6112 break;
6113 case OP_DIVPD:
6114 case OP_DIVPS:
6115 values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, "");
6116 break;
6117 case OP_PAND:
6118 values [ins->dreg] = LLVMBuildAnd (builder, lhs, rhs, "");
6119 break;
6120 case OP_POR:
6121 values [ins->dreg] = LLVMBuildOr (builder, lhs, rhs, "");
6122 break;
6123 case OP_PXOR:
6124 values [ins->dreg] = LLVMBuildXor (builder, lhs, rhs, "");
6125 break;
6126 case OP_PMULW:
6127 case OP_PMULD:
6128 values [ins->dreg] = LLVMBuildMul (builder, lhs, rhs, "");
6129 break;
6130 case OP_ANDPS:
6131 case OP_ANDNPS:
6132 case OP_ORPS:
6133 case OP_XORPS:
6134 case OP_ANDPD:
6135 case OP_ANDNPD:
6136 case OP_ORPD:
6137 case OP_XORPD: {
6138 LLVMTypeRef t, rt;
6139 LLVMValueRef v = NULL;
6141 switch (ins->opcode) {
6142 case OP_ANDPS:
6143 case OP_ANDNPS:
6144 case OP_ORPS:
6145 case OP_XORPS:
6146 t = LLVMVectorType (LLVMInt32Type (), 4);
6147 rt = LLVMVectorType (LLVMFloatType (), 4);
6148 break;
6149 case OP_ANDPD:
6150 case OP_ANDNPD:
6151 case OP_ORPD:
6152 case OP_XORPD:
6153 t = LLVMVectorType (LLVMInt64Type (), 2);
6154 rt = LLVMVectorType (LLVMDoubleType (), 2);
6155 break;
6156 default:
6157 t = LLVMInt32Type ();
6158 rt = LLVMInt32Type ();
6159 g_assert_not_reached ();
6162 lhs = LLVMBuildBitCast (builder, lhs, t, "");
6163 rhs = LLVMBuildBitCast (builder, rhs, t, "");
6164 switch (ins->opcode) {
6165 case OP_ANDPS:
6166 case OP_ANDPD:
6167 v = LLVMBuildAnd (builder, lhs, rhs, "");
6168 break;
6169 case OP_ORPS:
6170 case OP_ORPD:
6171 v = LLVMBuildOr (builder, lhs, rhs, "");
6172 break;
6173 case OP_XORPS:
6174 case OP_XORPD:
6175 v = LLVMBuildXor (builder, lhs, rhs, "");
6176 break;
6177 case OP_ANDNPS:
6178 case OP_ANDNPD:
6179 v = LLVMBuildAnd (builder, rhs, LLVMBuildNot (builder, lhs, ""), "");
6180 break;
6182 values [ins->dreg] = LLVMBuildBitCast (builder, v, rt, "");
6183 break;
6185 case OP_PMIND_UN:
6186 case OP_PMINW_UN:
6187 case OP_PMINB_UN: {
6188 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntULT, lhs, rhs, "");
6189 values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
6190 break;
6192 case OP_PMAXD_UN:
6193 case OP_PMAXW_UN:
6194 case OP_PMAXB_UN: {
6195 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntUGT, lhs, rhs, "");
6196 values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
6197 break;
6199 case OP_PMINW: {
6200 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntSLT, lhs, rhs, "");
6201 values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
6202 break;
6204 case OP_MINPD:
6205 case OP_MINPS:
6206 case OP_MAXPD:
6207 case OP_MAXPS:
6208 case OP_ADDSUBPD:
6209 case OP_ADDSUBPS:
6210 case OP_HADDPD:
6211 case OP_HADDPS:
6212 case OP_HSUBPD:
6213 case OP_HSUBPS:
6214 case OP_PADDB_SAT:
6215 case OP_PADDW_SAT:
6216 case OP_PSUBB_SAT:
6217 case OP_PSUBW_SAT:
6218 case OP_PADDB_SAT_UN:
6219 case OP_PADDW_SAT_UN:
6220 case OP_PSUBB_SAT_UN:
6221 case OP_PSUBW_SAT_UN:
6222 case OP_PACKW:
6223 case OP_PACKD:
6224 case OP_PACKW_UN:
6225 case OP_PACKD_UN:
6226 case OP_PMULW_HIGH:
6227 case OP_PMULW_HIGH_UN: {
6228 LLVMValueRef args [2];
6230 args [0] = lhs;
6231 args [1] = rhs;
6233 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6234 break;
6236 case OP_PAVGB_UN:
6237 case OP_PAVGW_UN: {
6238 LLVMValueRef ones_vec;
6239 LLVMValueRef ones [32];
6240 int vector_size = LLVMGetVectorSize (LLVMTypeOf (lhs));
6241 LLVMTypeRef ext_elem_type = vector_size == 16 ? LLVMInt16Type () : LLVMInt32Type ();
6243 for (int i = 0; i < 32; ++i)
6244 ones [i] = LLVMConstInt (ext_elem_type, 1, FALSE);
6245 ones_vec = LLVMConstVector (ones, vector_size);
6247 #if LLVM_API_VERSION >= 500
6248 LLVMValueRef val;
6249 LLVMTypeRef ext_type = LLVMVectorType (ext_elem_type, vector_size);
6251 /* Have to increase the vector element size to prevent overflows */
6252 /* res = trunc ((zext (lhs) + zext (rhs) + 1) >> 1) */
6253 val = LLVMBuildAdd (builder, LLVMBuildZExt (builder, lhs, ext_type, ""), LLVMBuildZExt (builder, rhs, ext_type, ""), "");
6254 val = LLVMBuildAdd (builder, val, ones_vec, "");
6255 val = LLVMBuildLShr (builder, val, ones_vec, "");
6256 values [ins->dreg] = LLVMBuildTrunc (builder, val, LLVMTypeOf (lhs), "");
6257 #else
6258 LLVMValueRef args [2];
6260 args [0] = lhs;
6261 args [1] = rhs;
6263 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6264 #endif
6265 break;
6267 case OP_PCMPEQB:
6268 case OP_PCMPEQW:
6269 case OP_PCMPEQD:
6270 case OP_PCMPEQQ: {
6271 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildICmp (builder, LLVMIntEQ, lhs, rhs, ""), LLVMTypeOf (lhs), "");
6272 break;
6274 case OP_PCMPGTB: {
6275 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildICmp (builder, LLVMIntSGT, lhs, rhs, ""), LLVMTypeOf (lhs), "");
6276 break;
6278 case OP_EXTRACT_R8:
6279 case OP_EXTRACT_I8:
6280 case OP_EXTRACT_I4:
6281 case OP_EXTRACT_I2:
6282 case OP_EXTRACT_U2:
6283 case OP_EXTRACTX_U2:
6284 case OP_EXTRACT_I1:
6285 case OP_EXTRACT_U1: {
6286 LLVMTypeRef t;
6287 gboolean zext = FALSE;
6289 t = simd_op_to_llvm_type (ins->opcode);
6291 switch (ins->opcode) {
6292 case OP_EXTRACT_R8:
6293 case OP_EXTRACT_I8:
6294 case OP_EXTRACT_I4:
6295 case OP_EXTRACT_I2:
6296 case OP_EXTRACT_I1:
6297 break;
6298 case OP_EXTRACT_U2:
6299 case OP_EXTRACTX_U2:
6300 case OP_EXTRACT_U1:
6301 zext = TRUE;
6302 break;
6303 default:
6304 t = LLVMInt32Type ();
6305 g_assert_not_reached ();
6308 lhs = LLVMBuildBitCast (builder, lhs, t, "");
6309 values [ins->dreg] = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), "");
6310 if (zext)
6311 values [ins->dreg] = LLVMBuildZExt (builder, values [ins->dreg], LLVMInt32Type (), "");
6312 break;
6315 case OP_EXPAND_I1:
6316 case OP_EXPAND_I2:
6317 case OP_EXPAND_I4:
6318 case OP_EXPAND_I8:
6319 case OP_EXPAND_R4:
6320 case OP_EXPAND_R8: {
6321 LLVMTypeRef t = simd_op_to_llvm_type (ins->opcode);
6322 LLVMValueRef mask [16], v;
6323 int i;
6325 for (i = 0; i < 16; ++i)
6326 mask [i] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6328 v = convert (ctx, values [ins->sreg1], LLVMGetElementType (t));
6330 values [ins->dreg] = LLVMBuildInsertElement (builder, LLVMConstNull (t), v, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6331 values [ins->dreg] = LLVMBuildShuffleVector (builder, values [ins->dreg], LLVMGetUndef (t), LLVMConstVector (mask, LLVMGetVectorSize (t)), "");
6332 break;
6335 case OP_INSERT_I1:
6336 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt8Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6337 break;
6338 case OP_INSERT_I2:
6339 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt16Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6340 break;
6341 case OP_INSERT_I4:
6342 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt32Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6343 break;
6344 case OP_INSERT_I8:
6345 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt64Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6346 break;
6347 case OP_INSERT_R4:
6348 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMFloatType ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6349 break;
6350 case OP_INSERT_R8:
6351 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMDoubleType ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6352 break;
6354 #if LLVM_API_VERSION > 100
6355 case OP_CVTDQ2PD: {
6356 LLVMValueRef indexes [16];
6358 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6359 indexes [1] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
6360 LLVMValueRef mask = LLVMConstVector (indexes, 2);
6361 LLVMValueRef shuffle = LLVMBuildShuffleVector (builder, lhs, LLVMConstNull (LLVMTypeOf (lhs)), mask, "");
6362 values [ins->dreg] = LLVMBuildSIToFP (builder, shuffle, LLVMVectorType (LLVMDoubleType (), 2), dname);
6363 break;
6365 case OP_CVTPS2PD: {
6366 LLVMValueRef indexes [16];
6368 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6369 indexes [1] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
6370 LLVMValueRef mask = LLVMConstVector (indexes, 2);
6371 LLVMValueRef shuffle = LLVMBuildShuffleVector (builder, lhs, LLVMConstNull (LLVMTypeOf (lhs)), mask, "");
6372 values [ins->dreg] = LLVMBuildFPExt (builder, shuffle, LLVMVectorType (LLVMDoubleType (), 2), dname);
6373 break;
6375 case OP_CVTTPS2DQ:
6376 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, LLVMVectorType (LLVMInt32Type (), 4), dname);
6377 break;
6378 #endif
6380 #if LLVM_API_VERSION <= 100
6381 case OP_CVTDQ2PD:
6382 case OP_CVTPS2PD:
6383 case OP_CVTTPS2DQ:
6384 #endif
6385 case OP_CVTDQ2PS:
6386 case OP_CVTPD2DQ:
6387 case OP_CVTPS2DQ:
6388 case OP_CVTPD2PS:
6389 case OP_CVTTPD2DQ:
6390 case OP_EXTRACT_MASK:
6391 case OP_SQRTPS:
6392 case OP_SQRTPD:
6393 case OP_RSQRTPS:
6394 case OP_RCPPS: {
6395 LLVMValueRef v;
6397 v = convert (ctx, values [ins->sreg1], simd_op_to_llvm_type (ins->opcode));
6399 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), &v, 1, dname);
6400 break;
6402 case OP_COMPPS:
6403 case OP_COMPPD: {
6404 LLVMRealPredicate op;
6406 switch (ins->inst_c0) {
6407 case SIMD_COMP_EQ:
6408 op = LLVMRealOEQ;
6409 break;
6410 case SIMD_COMP_LT:
6411 op = LLVMRealOLT;
6412 break;
6413 case SIMD_COMP_LE:
6414 op = LLVMRealOLE;
6415 break;
6416 case SIMD_COMP_UNORD:
6417 op = LLVMRealUNO;
6418 break;
6419 case SIMD_COMP_NEQ:
6420 op = LLVMRealUNE;
6421 break;
6422 case SIMD_COMP_NLT:
6423 op = LLVMRealUGE;
6424 break;
6425 case SIMD_COMP_NLE:
6426 op = LLVMRealUGT;
6427 break;
6428 case SIMD_COMP_ORD:
6429 op = LLVMRealORD;
6430 break;
6431 default:
6432 g_assert_not_reached ();
6435 LLVMValueRef cmp = LLVMBuildFCmp (builder, op, lhs, rhs, "");
6436 if (ins->opcode == OP_COMPPD)
6437 values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildSExt (builder, cmp, LLVMVectorType (LLVMInt64Type (), 2), ""), LLVMTypeOf (lhs), "");
6438 else
6439 values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildSExt (builder, cmp, LLVMVectorType (LLVMInt32Type (), 4), ""), LLVMTypeOf (lhs), "");
6440 break;
6442 case OP_ICONV_TO_X:
6443 /* This is only used for implementing shifts by non-immediate */
6444 values [ins->dreg] = lhs;
6445 break;
6447 case OP_PSHRW:
6448 case OP_PSHRD:
6449 case OP_PSHRQ:
6450 case OP_PSARW:
6451 case OP_PSARD:
6452 case OP_PSHLW:
6453 case OP_PSHLD:
6454 case OP_PSHLQ: {
6455 LLVMValueRef args [3];
6457 args [0] = lhs;
6458 args [1] = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
6460 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6461 break;
6464 case OP_PSHRW_REG:
6465 case OP_PSHRD_REG:
6466 case OP_PSHRQ_REG:
6467 case OP_PSARW_REG:
6468 case OP_PSARD_REG:
6469 case OP_PSHLW_REG:
6470 case OP_PSHLD_REG:
6471 case OP_PSHLQ_REG: {
6472 LLVMValueRef args [3];
6474 args [0] = lhs;
6475 args [1] = values [ins->sreg2];
6477 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6478 break;
6481 case OP_SHUFPS:
6482 case OP_SHUFPD:
6483 case OP_PSHUFLED:
6484 case OP_PSHUFLEW_LOW:
6485 case OP_PSHUFLEW_HIGH: {
6486 int mask [16];
6487 LLVMValueRef v1 = NULL, v2 = NULL, mask_values [16];
6488 int i, mask_size = 0;
6489 int imask = ins->inst_c0;
6491 /* Convert the x86 shuffle mask to LLVM's */
6492 switch (ins->opcode) {
6493 case OP_SHUFPS:
6494 mask_size = 4;
6495 mask [0] = ((imask >> 0) & 3);
6496 mask [1] = ((imask >> 2) & 3);
6497 mask [2] = ((imask >> 4) & 3) + 4;
6498 mask [3] = ((imask >> 6) & 3) + 4;
6499 v1 = values [ins->sreg1];
6500 v2 = values [ins->sreg2];
6501 break;
6502 case OP_SHUFPD:
6503 mask_size = 2;
6504 mask [0] = ((imask >> 0) & 1);
6505 mask [1] = ((imask >> 1) & 1) + 2;
6506 v1 = values [ins->sreg1];
6507 v2 = values [ins->sreg2];
6508 break;
6509 case OP_PSHUFLEW_LOW:
6510 mask_size = 8;
6511 mask [0] = ((imask >> 0) & 3);
6512 mask [1] = ((imask >> 2) & 3);
6513 mask [2] = ((imask >> 4) & 3);
6514 mask [3] = ((imask >> 6) & 3);
6515 mask [4] = 4 + 0;
6516 mask [5] = 4 + 1;
6517 mask [6] = 4 + 2;
6518 mask [7] = 4 + 3;
6519 v1 = values [ins->sreg1];
6520 v2 = LLVMGetUndef (LLVMTypeOf (v1));
6521 break;
6522 case OP_PSHUFLEW_HIGH:
6523 mask_size = 8;
6524 mask [0] = 0;
6525 mask [1] = 1;
6526 mask [2] = 2;
6527 mask [3] = 3;
6528 mask [4] = 4 + ((imask >> 0) & 3);
6529 mask [5] = 4 + ((imask >> 2) & 3);
6530 mask [6] = 4 + ((imask >> 4) & 3);
6531 mask [7] = 4 + ((imask >> 6) & 3);
6532 v1 = values [ins->sreg1];
6533 v2 = LLVMGetUndef (LLVMTypeOf (v1));
6534 break;
6535 case OP_PSHUFLED:
6536 mask_size = 4;
6537 mask [0] = ((imask >> 0) & 3);
6538 mask [1] = ((imask >> 2) & 3);
6539 mask [2] = ((imask >> 4) & 3);
6540 mask [3] = ((imask >> 6) & 3);
6541 v1 = values [ins->sreg1];
6542 v2 = LLVMGetUndef (LLVMTypeOf (v1));
6543 break;
6544 default:
6545 g_assert_not_reached ();
6547 for (i = 0; i < mask_size; ++i)
6548 mask_values [i] = LLVMConstInt (LLVMInt32Type (), mask [i], FALSE);
6550 values [ins->dreg] =
6551 LLVMBuildShuffleVector (builder, v1, v2,
6552 LLVMConstVector (mask_values, mask_size), dname);
6553 break;
6556 case OP_UNPACK_LOWB:
6557 case OP_UNPACK_LOWW:
6558 case OP_UNPACK_LOWD:
6559 case OP_UNPACK_LOWQ:
6560 case OP_UNPACK_LOWPS:
6561 case OP_UNPACK_LOWPD:
6562 case OP_UNPACK_HIGHB:
6563 case OP_UNPACK_HIGHW:
6564 case OP_UNPACK_HIGHD:
6565 case OP_UNPACK_HIGHQ:
6566 case OP_UNPACK_HIGHPS:
6567 case OP_UNPACK_HIGHPD: {
6568 int mask [16];
6569 LLVMValueRef mask_values [16];
6570 int i, mask_size = 0;
6571 gboolean low = FALSE;
6573 switch (ins->opcode) {
6574 case OP_UNPACK_LOWB:
6575 mask_size = 16;
6576 low = TRUE;
6577 break;
6578 case OP_UNPACK_LOWW:
6579 mask_size = 8;
6580 low = TRUE;
6581 break;
6582 case OP_UNPACK_LOWD:
6583 case OP_UNPACK_LOWPS:
6584 mask_size = 4;
6585 low = TRUE;
6586 break;
6587 case OP_UNPACK_LOWQ:
6588 case OP_UNPACK_LOWPD:
6589 mask_size = 2;
6590 low = TRUE;
6591 break;
6592 case OP_UNPACK_HIGHB:
6593 mask_size = 16;
6594 break;
6595 case OP_UNPACK_HIGHW:
6596 mask_size = 8;
6597 break;
6598 case OP_UNPACK_HIGHD:
6599 case OP_UNPACK_HIGHPS:
6600 mask_size = 4;
6601 break;
6602 case OP_UNPACK_HIGHQ:
6603 case OP_UNPACK_HIGHPD:
6604 mask_size = 2;
6605 break;
6606 default:
6607 g_assert_not_reached ();
6610 if (low) {
6611 for (i = 0; i < (mask_size / 2); ++i) {
6612 mask [(i * 2)] = i;
6613 mask [(i * 2) + 1] = mask_size + i;
6615 } else {
6616 for (i = 0; i < (mask_size / 2); ++i) {
6617 mask [(i * 2)] = (mask_size / 2) + i;
6618 mask [(i * 2) + 1] = mask_size + (mask_size / 2) + i;
6622 for (i = 0; i < mask_size; ++i)
6623 mask_values [i] = LLVMConstInt (LLVMInt32Type (), mask [i], FALSE);
6625 values [ins->dreg] =
6626 LLVMBuildShuffleVector (builder, values [ins->sreg1], values [ins->sreg2],
6627 LLVMConstVector (mask_values, mask_size), dname);
6628 break;
6631 case OP_DUPPD: {
6632 LLVMTypeRef t = simd_op_to_llvm_type (ins->opcode);
6633 LLVMValueRef v, val;
6635 v = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6636 val = LLVMConstNull (t);
6637 val = LLVMBuildInsertElement (builder, val, v, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6638 val = LLVMBuildInsertElement (builder, val, v, LLVMConstInt (LLVMInt32Type (), 1, FALSE), dname);
6640 values [ins->dreg] = val;
6641 break;
6643 case OP_DUPPS_LOW:
6644 case OP_DUPPS_HIGH: {
6645 LLVMTypeRef t = simd_op_to_llvm_type (ins->opcode);
6646 LLVMValueRef v1, v2, val;
6649 if (ins->opcode == OP_DUPPS_LOW) {
6650 v1 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6651 v2 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 2, FALSE), "");
6652 } else {
6653 v1 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 1, FALSE), "");
6654 v2 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 3, FALSE), "");
6656 val = LLVMConstNull (t);
6657 val = LLVMBuildInsertElement (builder, val, v1, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6658 val = LLVMBuildInsertElement (builder, val, v1, LLVMConstInt (LLVMInt32Type (), 1, FALSE), "");
6659 val = LLVMBuildInsertElement (builder, val, v2, LLVMConstInt (LLVMInt32Type (), 2, FALSE), "");
6660 val = LLVMBuildInsertElement (builder, val, v2, LLVMConstInt (LLVMInt32Type (), 3, FALSE), "");
6662 values [ins->dreg] = val;
6663 break;
6666 case OP_DPPS: {
6667 LLVMValueRef args [3];
6669 args [0] = lhs;
6670 args [1] = rhs;
6671 /* 0xf1 == multiply all 4 elements, add them together, and store the result to the lowest element */
6672 #if LLVM_API_VERSION >= 500
6673 args [2] = LLVMConstInt (LLVMInt8Type (), 0xf1, FALSE);
6674 #else
6675 args [2] = LLVMConstInt (LLVMInt32Type (), 0xf1, FALSE);
6676 #endif
6678 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 3, dname);
6679 break;
6682 case OP_FCONV_TO_R8_X: {
6683 values [ins->dreg] = LLVMBuildInsertElement (builder, LLVMConstNull (type_to_simd_type (MONO_TYPE_R8)), lhs, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6684 break;
6687 case OP_SSE41_ROUNDPD: {
6688 LLVMValueRef args [3];
6690 args [0] = lhs;
6691 args [1] = LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE);
6693 values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.x86.sse41.round.pd"), args, 2, dname);
6694 break;
6697 #endif /* SIMD */
6699 case OP_DUMMY_USE:
6700 break;
6703 * EXCEPTION HANDLING
6705 case OP_IMPLICIT_EXCEPTION:
6706 /* This marks a place where an implicit exception can happen */
6707 if (bb->region != -1)
6708 set_failure (ctx, "implicit-exception");
6709 break;
6710 case OP_THROW:
6711 case OP_RETHROW: {
6712 gboolean rethrow = (ins->opcode == OP_RETHROW);
6713 if (ctx->llvm_only) {
6714 emit_llvmonly_throw (ctx, bb, rethrow, lhs);
6715 has_terminator = TRUE;
6716 ctx->unreachable [bb->block_num] = TRUE;
6717 } else {
6718 emit_throw (ctx, bb, rethrow, lhs);
6719 builder = ctx->builder;
6721 break;
6723 case OP_CALL_HANDLER: {
6725 * We don't 'call' handlers, but instead simply branch to them.
6726 * The code generated by ENDFINALLY will branch back to us.
6728 LLVMBasicBlockRef noex_bb;
6729 GSList *bb_list;
6730 BBInfo *info = &bblocks [ins->inst_target_bb->block_num];
6732 bb_list = info->call_handler_return_bbs;
6735 * Set the indicator variable for the finally clause.
6737 lhs = info->finally_ind;
6738 g_assert (lhs);
6739 LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), g_slist_length (bb_list) + 1, FALSE), lhs);
6741 /* Branch to the finally clause */
6742 LLVMBuildBr (builder, info->call_handler_target_bb);
6744 noex_bb = gen_bb (ctx, "CALL_HANDLER_CONT_BB");
6745 info->call_handler_return_bbs = g_slist_append_mempool (cfg->mempool, info->call_handler_return_bbs, noex_bb);
6747 builder = ctx->builder = create_builder (ctx);
6748 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
6750 bblocks [bb->block_num].end_bblock = noex_bb;
6751 break;
6753 case OP_START_HANDLER: {
6754 break;
6756 case OP_ENDFINALLY: {
6757 LLVMBasicBlockRef resume_bb;
6758 MonoBasicBlock *handler_bb;
6759 LLVMValueRef val, switch_ins, callee;
6760 GSList *bb_list;
6761 BBInfo *info;
6762 gboolean is_fault = MONO_REGION_FLAGS (bb->region) == MONO_EXCEPTION_CLAUSE_FAULT;
6765 * Fault clauses are like finally clauses, but they are only called if an exception is thrown.
6767 if (!is_fault) {
6768 handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)));
6769 g_assert (handler_bb);
6770 info = &bblocks [handler_bb->block_num];
6771 lhs = info->finally_ind;
6772 g_assert (lhs);
6774 bb_list = info->call_handler_return_bbs;
6776 resume_bb = gen_bb (ctx, "ENDFINALLY_RESUME_BB");
6778 /* Load the finally variable */
6779 val = LLVMBuildLoad (builder, lhs, "");
6781 /* Reset the variable */
6782 LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), lhs);
6784 /* Branch to either resume_bb, or to the bblocks in bb_list */
6785 switch_ins = LLVMBuildSwitch (builder, val, resume_bb, g_slist_length (bb_list));
6787 * The other targets are added at the end to handle OP_CALL_HANDLER
6788 * opcodes processed later.
6790 info->endfinally_switch_ins_list = g_slist_append_mempool (cfg->mempool, info->endfinally_switch_ins_list, switch_ins);
6792 builder = ctx->builder = create_builder (ctx);
6793 LLVMPositionBuilderAtEnd (ctx->builder, resume_bb);
6796 if (ctx->llvm_only) {
6797 emit_resume_eh (ctx, bb);
6798 } else {
6799 if (ctx->cfg->compile_aot) {
6800 callee = get_callee (ctx, LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE), MONO_PATCH_INFO_INTERNAL_METHOD, "llvm_resume_unwind_trampoline");
6801 } else {
6802 #if LLVM_API_VERSION > 100
6803 MonoJitICallInfo *info;
6805 info = mono_find_jit_icall_by_name ("llvm_resume_unwind_trampoline");
6806 g_assert (info);
6807 gpointer target = (void*)info->func;
6808 LLVMTypeRef icall_sig = LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE);
6809 callee = emit_jit_callee (ctx, "llvm_resume_unwind_trampoline", icall_sig, target);
6810 #else
6811 callee = LLVMGetNamedFunction (ctx->lmodule, "llvm_resume_unwind_trampoline");
6812 #endif
6814 LLVMBuildCall (builder, callee, NULL, 0, "");
6815 LLVMBuildUnreachable (builder);
6818 has_terminator = TRUE;
6819 break;
6821 case OP_IL_SEQ_POINT:
6822 break;
6823 default: {
6824 char reason [128];
6826 sprintf (reason, "opcode %s", mono_inst_name (ins->opcode));
6827 set_failure (ctx, reason);
6828 break;
6832 if (!ctx_ok (ctx))
6833 break;
6835 /* Convert the value to the type required by phi nodes */
6836 if (spec [MONO_INST_DEST] != ' ' && !MONO_IS_STORE_MEMBASE (ins) && ctx->vreg_types [ins->dreg]) {
6837 if (ctx->is_vphi [ins->dreg])
6838 /* vtypes */
6839 values [ins->dreg] = addresses [ins->dreg];
6840 else
6841 values [ins->dreg] = convert (ctx, values [ins->dreg], ctx->vreg_types [ins->dreg]);
6844 /* Add stores for volatile variables */
6845 if (spec [MONO_INST_DEST] != ' ' && spec [MONO_INST_DEST] != 'v' && !MONO_IS_STORE_MEMBASE (ins))
6846 emit_volatile_store (ctx, ins->dreg);
6849 if (!ctx_ok (ctx))
6850 return;
6852 if (!has_terminator && bb->next_bb && (bb == cfg->bb_entry || bb->in_count > 0)) {
6853 LLVMBuildBr (builder, get_bb (ctx, bb->next_bb));
6856 if (bb == cfg->bb_exit && sig->ret->type == MONO_TYPE_VOID) {
6857 emit_dbg_loc (ctx, builder, cfg->header->code + cfg->header->code_size - 1);
6858 LLVMBuildRetVoid (builder);
6861 if (bb == cfg->bb_entry)
6862 ctx->last_alloca = LLVMGetLastInstruction (get_bb (ctx, cfg->bb_entry));
6866 * mono_llvm_check_method_supported:
6868 * Do some quick checks to decide whenever cfg->method can be compiled by LLVM, to avoid
6869 * compiling a method twice.
6871 void
6872 mono_llvm_check_method_supported (MonoCompile *cfg)
6874 int i, j;
6876 #ifdef TARGET_WASM
6877 if (mono_method_signature_internal (cfg->method)->call_convention == MONO_CALL_VARARG) {
6878 cfg->exception_message = g_strdup ("vararg callconv");
6879 cfg->disable_llvm = TRUE;
6880 return;
6882 #endif
6884 if (cfg->llvm_only)
6885 return;
6887 if (cfg->method->save_lmf) {
6888 cfg->exception_message = g_strdup ("lmf");
6889 cfg->disable_llvm = TRUE;
6891 if (cfg->disable_llvm)
6892 return;
6895 * Nested clauses where one of the clauses is a finally clause is
6896 * not supported, because LLVM can't figure out the control flow,
6897 * probably because we resume exception handling by calling our
6898 * own function instead of using the 'resume' llvm instruction.
6900 for (i = 0; i < cfg->header->num_clauses; ++i) {
6901 for (j = 0; j < cfg->header->num_clauses; ++j) {
6902 MonoExceptionClause *clause1 = &cfg->header->clauses [i];
6903 MonoExceptionClause *clause2 = &cfg->header->clauses [j];
6905 // FIXME: Nested try clauses fail in some cases too, i.e. #37273
6906 if (i != j && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
6907 //(clause1->flags == MONO_EXCEPTION_CLAUSE_FINALLY || clause2->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
6908 cfg->exception_message = g_strdup ("nested clauses");
6909 cfg->disable_llvm = TRUE;
6910 break;
6914 if (cfg->disable_llvm)
6915 return;
6917 /* FIXME: */
6918 if (cfg->method->dynamic) {
6919 cfg->exception_message = g_strdup ("dynamic.");
6920 cfg->disable_llvm = TRUE;
6922 if (cfg->disable_llvm)
6923 return;
6926 static LLVMCallInfo*
6927 get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
6929 LLVMCallInfo *linfo;
6930 int i;
6932 if (cfg->gsharedvt && cfg->llvm_only && mini_is_gsharedvt_variable_signature (sig)) {
6933 int i, n, pindex;
6936 * Gsharedvt methods have the following calling convention:
6937 * - all arguments are passed by ref, even non generic ones
6938 * - the return value is returned by ref too, using a vret
6939 * argument passed after 'this'.
6941 n = sig->param_count + sig->hasthis;
6942 linfo = (LLVMCallInfo*)mono_mempool_alloc0 (cfg->mempool, sizeof (LLVMCallInfo) + (sizeof (LLVMArgInfo) * n));
6944 pindex = 0;
6945 if (sig->hasthis)
6946 linfo->args [pindex ++].storage = LLVMArgNormal;
6948 if (sig->ret->type != MONO_TYPE_VOID) {
6949 if (mini_is_gsharedvt_variable_type (sig->ret))
6950 linfo->ret.storage = LLVMArgGsharedvtVariable;
6951 else if (mini_type_is_vtype (sig->ret))
6952 linfo->ret.storage = LLVMArgGsharedvtFixedVtype;
6953 else
6954 linfo->ret.storage = LLVMArgGsharedvtFixed;
6955 linfo->vret_arg_index = pindex;
6956 } else {
6957 linfo->ret.storage = LLVMArgNone;
6960 for (i = 0; i < sig->param_count; ++i) {
6961 if (sig->params [i]->byref)
6962 linfo->args [pindex].storage = LLVMArgNormal;
6963 else if (mini_is_gsharedvt_variable_type (sig->params [i]))
6964 linfo->args [pindex].storage = LLVMArgGsharedvtVariable;
6965 else if (mini_type_is_vtype (sig->params [i]))
6966 linfo->args [pindex].storage = LLVMArgGsharedvtFixedVtype;
6967 else
6968 linfo->args [pindex].storage = LLVMArgGsharedvtFixed;
6969 linfo->args [pindex].type = sig->params [i];
6970 pindex ++;
6972 return linfo;
6975 linfo = mono_arch_get_llvm_call_info (cfg, sig);
6976 linfo->dummy_arg_pindex = -1;
6977 for (i = 0; i < sig->param_count; ++i)
6978 linfo->args [i + sig->hasthis].type = sig->params [i];
6980 return linfo;
6983 static void
6984 emit_method_inner (EmitContext *ctx);
6986 static void
6987 free_ctx (EmitContext *ctx)
6989 GSList *l;
6991 g_free (ctx->values);
6992 g_free (ctx->addresses);
6993 g_free (ctx->vreg_types);
6994 g_free (ctx->is_vphi);
6995 g_free (ctx->vreg_cli_types);
6996 g_free (ctx->is_dead);
6997 g_free (ctx->unreachable);
6998 g_ptr_array_free (ctx->phi_values, TRUE);
6999 g_free (ctx->bblocks);
7000 g_hash_table_destroy (ctx->region_to_handler);
7001 g_hash_table_destroy (ctx->clause_to_handler);
7002 g_hash_table_destroy (ctx->jit_callees);
7004 GHashTableIter iter;
7005 g_hash_table_iter_init (&iter, ctx->method_to_callers);
7006 while (g_hash_table_iter_next (&iter, NULL, (gpointer*)&l))
7007 g_slist_free (l);
7009 g_hash_table_destroy (ctx->method_to_callers);
7011 g_free (ctx->method_name);
7012 g_ptr_array_free (ctx->bblock_list, TRUE);
7014 for (l = ctx->builders; l; l = l->next) {
7015 LLVMBuilderRef builder = (LLVMBuilderRef)l->data;
7016 LLVMDisposeBuilder (builder);
7019 g_free (ctx);
7023 * mono_llvm_emit_method:
7025 * Emit LLVM IL from the mono IL, and compile it to native code using LLVM.
7027 void
7028 mono_llvm_emit_method (MonoCompile *cfg)
7030 EmitContext *ctx;
7031 char *method_name;
7032 gboolean is_linkonce = FALSE;
7033 int i;
7035 if (cfg->skip)
7036 return;
7038 /* The code below might acquire the loader lock, so use it for global locking */
7039 mono_loader_lock ();
7041 /* Used to communicate with the callbacks */
7042 mono_native_tls_set_value (current_cfg_tls_id, cfg);
7044 ctx = g_new0 (EmitContext, 1);
7045 ctx->cfg = cfg;
7046 ctx->mempool = cfg->mempool;
7049 * This maps vregs to the LLVM instruction defining them
7051 ctx->values = g_new0 (LLVMValueRef, cfg->next_vreg);
7053 * This maps vregs for volatile variables to the LLVM instruction defining their
7054 * address.
7056 ctx->addresses = g_new0 (LLVMValueRef, cfg->next_vreg);
7057 ctx->vreg_types = g_new0 (LLVMTypeRef, cfg->next_vreg);
7058 ctx->is_vphi = g_new0 (gboolean, cfg->next_vreg);
7059 ctx->vreg_cli_types = g_new0 (MonoType*, cfg->next_vreg);
7060 ctx->phi_values = g_ptr_array_sized_new (256);
7062 * This signals whenever the vreg was defined by a phi node with no input vars
7063 * (i.e. all its input bblocks end with NOT_REACHABLE).
7065 ctx->is_dead = g_new0 (gboolean, cfg->next_vreg);
7066 /* Whenever the bblock is unreachable */
7067 ctx->unreachable = g_new0 (gboolean, cfg->max_block_num);
7068 ctx->bblock_list = g_ptr_array_sized_new (256);
7070 ctx->region_to_handler = g_hash_table_new (NULL, NULL);
7071 ctx->clause_to_handler = g_hash_table_new (NULL, NULL);
7072 ctx->method_to_callers = g_hash_table_new (NULL, NULL);
7073 ctx->jit_callees = g_hash_table_new (NULL, NULL);
7074 if (cfg->compile_aot) {
7075 ctx->module = &aot_module;
7077 method_name = NULL;
7079 * Allow the linker to discard duplicate copies of wrappers, generic instances etc. by using the 'linkonce'
7080 * linkage for them. This requires the following:
7081 * - the method needs to have a unique mangled name
7082 * - llvmonly mode, since the code in aot-runtime.c would initialize got slots in the wrong aot image etc.
7084 is_linkonce = ctx->module->llvm_only && ctx->module->static_link && mono_aot_can_dedup (cfg->method) && FALSE;
7085 if (is_linkonce) {
7086 method_name = mono_aot_get_mangled_method_name (cfg->method);
7087 if (!method_name)
7088 is_linkonce = FALSE;
7090 if (method_name)
7091 printf ("%s %s\n", mono_method_full_name (cfg->method, 1), method_name);
7092 else
7093 printf ("%s\n", mono_method_full_name (cfg->method, 1));
7096 if (!method_name)
7097 method_name = mono_aot_get_method_name (cfg);
7098 cfg->llvm_method_name = g_strdup (method_name);
7099 } else {
7100 init_jit_module (cfg->domain);
7101 ctx->module = (MonoLLVMModule*)domain_jit_info (cfg->domain)->llvm_module;
7102 method_name = mono_method_full_name (cfg->method, TRUE);
7104 ctx->method_name = method_name;
7105 ctx->is_linkonce = is_linkonce;
7107 #if LLVM_API_VERSION > 100
7108 if (cfg->compile_aot)
7109 ctx->lmodule = ctx->module->lmodule;
7110 else
7111 ctx->lmodule = LLVMModuleCreateWithName (g_strdup_printf ("jit-module-%s", cfg->method->name));
7112 #else
7113 ctx->lmodule = ctx->module->lmodule;
7114 #endif
7115 ctx->llvm_only = ctx->module->llvm_only;
7116 #ifdef TARGET_WASM
7117 ctx->emit_dummy_arg = TRUE;
7118 #endif
7120 emit_method_inner (ctx);
7122 if (!ctx_ok (ctx)) {
7123 if (ctx->lmethod) {
7124 /* Need to add unused phi nodes as they can be referenced by other values */
7125 LLVMBasicBlockRef phi_bb = LLVMAppendBasicBlock (ctx->lmethod, "PHI_BB");
7126 LLVMBuilderRef builder;
7128 builder = create_builder (ctx);
7129 LLVMPositionBuilderAtEnd (builder, phi_bb);
7131 for (i = 0; i < ctx->phi_values->len; ++i) {
7132 LLVMValueRef v = (LLVMValueRef)g_ptr_array_index (ctx->phi_values, i);
7133 if (LLVMGetInstructionParent (v) == NULL)
7134 LLVMInsertIntoBuilder (builder, v);
7137 LLVMDeleteFunction (ctx->lmethod);
7141 free_ctx (ctx);
7143 mono_native_tls_set_value (current_cfg_tls_id, NULL);
7145 mono_loader_unlock ();
7148 static void
7149 emit_method_inner (EmitContext *ctx)
7151 MonoCompile *cfg = ctx->cfg;
7152 MonoMethodSignature *sig;
7153 MonoBasicBlock *bb;
7154 LLVMTypeRef method_type;
7155 LLVMValueRef method = NULL;
7156 LLVMValueRef *values = ctx->values;
7157 int i, max_block_num, bb_index;
7158 gboolean last = FALSE;
7159 LLVMCallInfo *linfo;
7160 LLVMModuleRef lmodule = ctx->lmodule;
7161 BBInfo *bblocks;
7162 GPtrArray *bblock_list = ctx->bblock_list;
7163 MonoMethodHeader *header;
7164 MonoExceptionClause *clause;
7165 char **names;
7167 if (cfg->gsharedvt && !cfg->llvm_only) {
7168 set_failure (ctx, "gsharedvt");
7169 return;
7172 #if 1
7174 static int count = 0;
7175 count ++;
7177 char *llvm_count_str = g_getenv ("LLVM_COUNT");
7178 if (llvm_count_str) {
7179 int lcount = atoi (llvm_count_str);
7180 g_free (llvm_count_str);
7181 if (count == lcount) {
7182 printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
7183 fflush (stdout);
7184 last = TRUE;
7186 if (count > lcount) {
7187 set_failure (ctx, "count");
7188 return;
7192 #endif
7194 sig = mono_method_signature_internal (cfg->method);
7195 ctx->sig = sig;
7197 linfo = get_llvm_call_info (cfg, sig);
7198 ctx->linfo = linfo;
7199 if (!ctx_ok (ctx))
7200 return;
7202 if (cfg->rgctx_var)
7203 linfo->rgctx_arg = TRUE;
7204 else if (needs_extra_arg (ctx, cfg->method))
7205 linfo->dummy_arg = TRUE;
7206 ctx->method_type = method_type = sig_to_llvm_sig_full (ctx, sig, linfo);
7207 if (!ctx_ok (ctx))
7208 return;
7210 method = LLVMAddFunction (lmodule, ctx->method_name, method_type);
7211 ctx->lmethod = method;
7213 if (!cfg->llvm_only)
7214 LLVMSetFunctionCallConv (method, LLVMMono1CallConv);
7215 LLVMSetLinkage (method, LLVMPrivateLinkage);
7217 mono_llvm_add_func_attr (method, LLVM_ATTR_UW_TABLE);
7219 if (cfg->compile_aot) {
7220 LLVMSetLinkage (method, LLVMInternalLinkage);
7221 //all methods have internal visibility when doing llvm_only
7222 if (!cfg->llvm_only && ctx->module->external_symbols) {
7223 LLVMSetLinkage (method, LLVMExternalLinkage);
7224 LLVMSetVisibility (method, LLVMHiddenVisibility);
7226 if (ctx->is_linkonce) {
7227 LLVMSetLinkage (method, LLVMLinkOnceAnyLinkage);
7228 LLVMSetVisibility (method, LLVMDefaultVisibility);
7230 } else {
7231 #if LLVM_API_VERSION > 100
7232 LLVMSetLinkage (method, LLVMExternalLinkage);
7233 #else
7234 LLVMSetLinkage (method, LLVMPrivateLinkage);
7235 #endif
7238 if (cfg->method->save_lmf && !cfg->llvm_only) {
7239 set_failure (ctx, "lmf");
7240 return;
7243 if (sig->pinvoke && cfg->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && !cfg->llvm_only) {
7244 set_failure (ctx, "pinvoke signature");
7245 return;
7248 header = cfg->header;
7249 for (i = 0; i < header->num_clauses; ++i) {
7250 clause = &header->clauses [i];
7251 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_FAULT && clause->flags != MONO_EXCEPTION_CLAUSE_NONE) {
7252 set_failure (ctx, "non-finally/catch/fault clause.");
7253 return;
7256 if (header->num_clauses || (cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING) || cfg->no_inline)
7257 /* We can't handle inlined methods with clauses */
7258 mono_llvm_add_func_attr (method, LLVM_ATTR_NO_INLINE);
7260 if (linfo->rgctx_arg) {
7261 ctx->rgctx_arg = LLVMGetParam (method, linfo->rgctx_arg_pindex);
7262 ctx->rgctx_arg_pindex = linfo->rgctx_arg_pindex;
7264 * We mark the rgctx parameter with the inreg attribute, which is mapped to
7265 * MONO_ARCH_RGCTX_REG in the Mono calling convention in llvm, i.e.
7266 * CC_X86_64_Mono in X86CallingConv.td.
7268 if (!ctx->llvm_only)
7269 mono_llvm_add_param_attr (ctx->rgctx_arg, LLVM_ATTR_IN_REG);
7270 LLVMSetValueName (ctx->rgctx_arg, "rgctx");
7271 } else {
7272 ctx->rgctx_arg_pindex = -1;
7274 if (cfg->vret_addr) {
7275 values [cfg->vret_addr->dreg] = LLVMGetParam (method, linfo->vret_arg_pindex);
7276 LLVMSetValueName (values [cfg->vret_addr->dreg], "vret");
7277 if (linfo->ret.storage == LLVMArgVtypeByRef) {
7278 mono_llvm_add_param_attr (LLVMGetParam (method, linfo->vret_arg_pindex), LLVM_ATTR_STRUCT_RET);
7279 mono_llvm_add_param_attr (LLVMGetParam (method, linfo->vret_arg_pindex), LLVM_ATTR_NO_ALIAS);
7283 if (sig->hasthis) {
7284 ctx->this_arg_pindex = linfo->this_arg_pindex;
7285 ctx->this_arg = LLVMGetParam (method, linfo->this_arg_pindex);
7286 values [cfg->args [0]->dreg] = ctx->this_arg;
7287 LLVMSetValueName (values [cfg->args [0]->dreg], "this");
7289 if (linfo->dummy_arg)
7290 LLVMSetValueName (LLVMGetParam (method, linfo->dummy_arg_pindex), "dummy_arg");
7292 names = g_new (char *, sig->param_count);
7293 mono_method_get_param_names (cfg->method, (const char **) names);
7295 /* Set parameter names/attributes */
7296 for (i = 0; i < sig->param_count; ++i) {
7297 LLVMArgInfo *ainfo = &linfo->args [i + sig->hasthis];
7298 char *name;
7299 int pindex = ainfo->pindex + ainfo->ndummy_fpargs;
7300 int j;
7302 for (j = 0; j < ainfo->ndummy_fpargs; ++j) {
7303 name = g_strdup_printf ("dummy_%d_%d", i, j);
7304 LLVMSetValueName (LLVMGetParam (method, ainfo->pindex + j), name);
7305 g_free (name);
7308 if (ainfo->storage == LLVMArgVtypeInReg && ainfo->pair_storage [0] == LLVMArgNone && ainfo->pair_storage [1] == LLVMArgNone)
7309 continue;
7311 values [cfg->args [i + sig->hasthis]->dreg] = LLVMGetParam (method, pindex);
7312 if (ainfo->storage == LLVMArgGsharedvtFixed || ainfo->storage == LLVMArgGsharedvtFixedVtype) {
7313 if (names [i] && names [i][0] != '\0')
7314 name = g_strdup_printf ("p_arg_%s", names [i]);
7315 else
7316 name = g_strdup_printf ("p_arg_%d", i);
7317 } else {
7318 if (names [i] && names [i][0] != '\0')
7319 name = g_strdup_printf ("arg_%s", names [i]);
7320 else
7321 name = g_strdup_printf ("arg_%d", i);
7323 LLVMSetValueName (LLVMGetParam (method, pindex), name);
7324 g_free (name);
7325 if (ainfo->storage == LLVMArgVtypeByVal)
7326 mono_llvm_add_param_attr (LLVMGetParam (method, pindex), LLVM_ATTR_BY_VAL);
7328 if (ainfo->storage == LLVMArgVtypeByRef) {
7329 /* For OP_LDADDR */
7330 cfg->args [i + sig->hasthis]->opcode = OP_VTARG_ADDR;
7333 g_free (names);
7335 if (ctx->module->emit_dwarf && cfg->compile_aot && mono_debug_enabled ()) {
7336 ctx->minfo = mono_debug_lookup_method (cfg->method);
7337 ctx->dbg_md = emit_dbg_subprogram (ctx, cfg, method, ctx->method_name);
7340 max_block_num = 0;
7341 for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
7342 max_block_num = MAX (max_block_num, bb->block_num);
7343 ctx->bblocks = bblocks = g_new0 (BBInfo, max_block_num + 1);
7345 /* Add branches between non-consecutive bblocks */
7346 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7347 if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins) &&
7348 bb->next_bb != bb->last_ins->inst_false_bb) {
7350 MonoInst *inst = (MonoInst*)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
7351 inst->opcode = OP_BR;
7352 inst->inst_target_bb = bb->last_ins->inst_false_bb;
7353 mono_bblock_add_inst (bb, inst);
7358 * Make a first pass over the code to precreate PHI nodes/set INDIRECT flags.
7360 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7361 MonoInst *ins;
7362 LLVMBuilderRef builder;
7363 char *dname;
7364 char dname_buf[128];
7366 builder = create_builder (ctx);
7368 for (ins = bb->code; ins; ins = ins->next) {
7369 switch (ins->opcode) {
7370 case OP_PHI:
7371 case OP_FPHI:
7372 case OP_VPHI:
7373 case OP_XPHI: {
7374 LLVMTypeRef phi_type = llvm_type_to_stack_type (cfg, type_to_llvm_type (ctx, m_class_get_byval_arg (ins->klass)));
7376 if (!ctx_ok (ctx))
7377 return;
7379 if (ins->opcode == OP_VPHI) {
7380 /* Treat valuetype PHI nodes as operating on the address itself */
7381 g_assert (ins->klass);
7382 phi_type = LLVMPointerType (type_to_llvm_type (ctx, m_class_get_byval_arg (ins->klass)), 0);
7386 * Have to precreate these, as they can be referenced by
7387 * earlier instructions.
7389 sprintf (dname_buf, "t%d", ins->dreg);
7390 dname = dname_buf;
7391 values [ins->dreg] = LLVMBuildPhi (builder, phi_type, dname);
7393 if (ins->opcode == OP_VPHI)
7394 ctx->addresses [ins->dreg] = values [ins->dreg];
7396 g_ptr_array_add (ctx->phi_values, values [ins->dreg]);
7399 * Set the expected type of the incoming arguments since these have
7400 * to have the same type.
7402 for (i = 0; i < ins->inst_phi_args [0]; i++) {
7403 int sreg1 = ins->inst_phi_args [i + 1];
7405 if (sreg1 != -1) {
7406 if (ins->opcode == OP_VPHI)
7407 ctx->is_vphi [sreg1] = TRUE;
7408 ctx->vreg_types [sreg1] = phi_type;
7411 break;
7413 case OP_LDADDR:
7414 ((MonoInst*)ins->inst_p0)->flags |= MONO_INST_INDIRECT;
7415 break;
7416 default:
7417 break;
7423 * Create an ordering for bblocks, use the depth first order first, then
7424 * put the exception handling bblocks last.
7426 for (bb_index = 0; bb_index < cfg->num_bblocks; ++bb_index) {
7427 bb = cfg->bblocks [bb_index];
7428 if (!(bb->region != -1 && !MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY))) {
7429 g_ptr_array_add (bblock_list, bb);
7430 bblocks [bb->block_num].added = TRUE;
7434 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7435 if (!bblocks [bb->block_num].added)
7436 g_ptr_array_add (bblock_list, bb);
7440 * Second pass: generate code.
7442 // Emit entry point
7443 LLVMBuilderRef entry_builder = create_builder (ctx);
7444 LLVMBasicBlockRef entry_bb = get_bb (ctx, cfg->bb_entry);
7445 LLVMPositionBuilderAtEnd (entry_builder, entry_bb);
7446 emit_entry_bb (ctx, entry_builder);
7448 // Make landing pads first
7449 ctx->exc_meta = g_hash_table_new_full (NULL, NULL, NULL, NULL);
7451 if (ctx->llvm_only) {
7452 size_t group_index = 0;
7453 while (group_index < cfg->header->num_clauses) {
7454 int count = 0;
7455 size_t cursor = group_index;
7456 while (cursor < cfg->header->num_clauses &&
7457 CLAUSE_START (&cfg->header->clauses [cursor]) == CLAUSE_START (&cfg->header->clauses [group_index]) &&
7458 CLAUSE_END (&cfg->header->clauses [cursor]) == CLAUSE_END (&cfg->header->clauses [group_index])) {
7459 count++;
7460 cursor++;
7463 LLVMBasicBlockRef lpad_bb = emit_landing_pad (ctx, group_index, count);
7464 intptr_t key = CLAUSE_END (&cfg->header->clauses [group_index]);
7465 g_hash_table_insert (ctx->exc_meta, (gpointer)key, lpad_bb);
7467 group_index = cursor;
7471 for (bb_index = 0; bb_index < bblock_list->len; ++bb_index) {
7472 bb = (MonoBasicBlock*)g_ptr_array_index (bblock_list, bb_index);
7474 // Prune unreachable mono BBs.
7475 if (!(bb == cfg->bb_entry || bb->in_count > 0))
7476 continue;
7478 process_bb (ctx, bb);
7479 if (!ctx_ok (ctx))
7480 return;
7482 g_hash_table_destroy (ctx->exc_meta);
7484 mono_memory_barrier ();
7486 /* Add incoming phi values */
7487 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7488 GSList *l, *ins_list;
7490 ins_list = bblocks [bb->block_num].phi_nodes;
7492 for (l = ins_list; l; l = l->next) {
7493 PhiNode *node = (PhiNode*)l->data;
7494 MonoInst *phi = node->phi;
7495 int sreg1 = node->sreg;
7496 LLVMBasicBlockRef in_bb;
7498 if (sreg1 == -1)
7499 continue;
7501 in_bb = get_end_bb (ctx, node->in_bb);
7503 if (ctx->unreachable [node->in_bb->block_num])
7504 continue;
7506 if (!values [sreg1]) {
7507 /* Can happen with values in EH clauses */
7508 set_failure (ctx, "incoming phi sreg1");
7509 return;
7512 if (phi->opcode == OP_VPHI) {
7513 g_assert (LLVMTypeOf (ctx->addresses [sreg1]) == LLVMTypeOf (values [phi->dreg]));
7514 LLVMAddIncoming (values [phi->dreg], &ctx->addresses [sreg1], &in_bb, 1);
7515 } else {
7516 if (LLVMTypeOf (values [sreg1]) != LLVMTypeOf (values [phi->dreg])) {
7517 set_failure (ctx, "incoming phi arg type mismatch");
7518 return;
7520 g_assert (LLVMTypeOf (values [sreg1]) == LLVMTypeOf (values [phi->dreg]));
7521 LLVMAddIncoming (values [phi->dreg], &values [sreg1], &in_bb, 1);
7526 /* Nullify empty phi instructions */
7527 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7528 GSList *l, *ins_list;
7530 ins_list = bblocks [bb->block_num].phi_nodes;
7532 for (l = ins_list; l; l = l->next) {
7533 PhiNode *node = (PhiNode*)l->data;
7534 MonoInst *phi = node->phi;
7535 LLVMValueRef phi_ins = values [phi->dreg];
7537 if (!phi_ins)
7538 /* Already removed */
7539 continue;
7541 if (LLVMCountIncoming (phi_ins) == 0) {
7542 mono_llvm_replace_uses_of (phi_ins, LLVMConstNull (LLVMTypeOf (phi_ins)));
7543 LLVMInstructionEraseFromParent (phi_ins);
7544 values [phi->dreg] = NULL;
7549 /* Create the SWITCH statements for ENDFINALLY instructions */
7550 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7551 BBInfo *info = &bblocks [bb->block_num];
7552 GSList *l;
7553 for (l = info->endfinally_switch_ins_list; l; l = l->next) {
7554 LLVMValueRef switch_ins = (LLVMValueRef)l->data;
7555 GSList *bb_list = info->call_handler_return_bbs;
7557 GSList *bb_list_iter;
7558 i = 0;
7559 for (bb_list_iter = bb_list; bb_list_iter; bb_list_iter = g_slist_next (bb_list_iter)) {
7560 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i + 1, FALSE), (LLVMBasicBlockRef)bb_list_iter->data);
7561 i ++;
7566 /* Initialize the method if needed */
7567 if (cfg->compile_aot && ctx->llvm_only) {
7568 // FIXME: Add more shared got entries
7569 ctx->builder = create_builder (ctx);
7570 LLVMPositionBuilderAtEnd (ctx->builder, ctx->init_bb);
7572 ctx->module->max_method_idx = MAX (ctx->module->max_method_idx, cfg->method_index);
7574 // FIXME: beforefieldinit
7576 * NATIVE_TO_MANAGED methods might be called on a thread not attached to the runtime, so they are initialized when loaded
7577 * in load_method ().
7579 if ((ctx->has_got_access || mono_class_get_cctor (cfg->method->klass)) && !(cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED)) {
7581 * linkonce methods shouldn't have initialization,
7582 * because they might belong to assemblies which
7583 * haven't been loaded yet.
7585 g_assert (!ctx->is_linkonce);
7586 emit_init_method (ctx);
7587 } else {
7588 LLVMBuildBr (ctx->builder, ctx->inited_bb);
7592 if (cfg->llvm_only) {
7593 GHashTableIter iter;
7594 MonoMethod *method;
7595 GSList *callers, *l, *l2;
7598 * Add the contents of ctx->method_to_callers to module->method_to_callers.
7599 * We can't do this earlier, as it contains llvm instructions which can be
7600 * freed if compilation fails.
7601 * FIXME: Get rid of this when all methods can be llvm compiled.
7603 g_hash_table_iter_init (&iter, ctx->method_to_callers);
7604 while (g_hash_table_iter_next (&iter, (void**)&method, (void**)&callers)) {
7605 for (l = callers; l; l = l->next) {
7606 l2 = (GSList*)g_hash_table_lookup (ctx->module->method_to_callers, method);
7607 l2 = g_slist_prepend (l2, l->data);
7608 g_hash_table_insert (ctx->module->method_to_callers, method, l2);
7613 if (cfg->verbose_level > 1)
7614 mono_llvm_dump_value (method);
7616 if (cfg->compile_aot && !cfg->llvm_only)
7617 mark_as_used (ctx->module, method);
7619 if (!cfg->llvm_only) {
7620 LLVMValueRef md_args [16];
7621 LLVMValueRef md_node;
7622 int method_index;
7624 if (cfg->compile_aot)
7625 method_index = mono_aot_get_method_index (cfg->orig_method);
7626 else
7627 method_index = 1;
7628 md_args [0] = LLVMMDString (ctx->method_name, strlen (ctx->method_name));
7629 md_args [1] = LLVMConstInt (LLVMInt32Type (), method_index, FALSE);
7630 md_node = LLVMMDNode (md_args, 2);
7631 LLVMAddNamedMetadataOperand (lmodule, "mono.function_indexes", md_node);
7632 //LLVMSetMetadata (method, md_kind, LLVMMDNode (&md_arg, 1));
7635 if (cfg->compile_aot) {
7636 /* Don't generate native code, keep the LLVM IR */
7637 if (cfg->verbose_level)
7638 printf ("%s emitted as %s\n", mono_method_full_name (cfg->method, TRUE), ctx->method_name);
7640 //LLVMDumpValue (ctx->lmethod);
7641 #if LLVM_API_VERSION < 100
7642 /* VerifyFunction can't handle some of the debug info created by DIBuilder in llvm 3.9 */
7643 int err = LLVMVerifyFunction(ctx->lmethod, LLVMPrintMessageAction);
7644 g_assert (err == 0);
7645 #endif
7646 } else {
7647 //LLVMVerifyFunction (method, 0);
7648 #if LLVM_API_VERSION > 100
7649 MonoDomain *domain = mono_domain_get ();
7650 MonoJitDomainInfo *domain_info;
7651 int nvars = g_hash_table_size (ctx->jit_callees);
7652 LLVMValueRef *callee_vars = g_new0 (LLVMValueRef, nvars);
7653 gpointer *callee_addrs = g_new0 (gpointer, nvars);
7654 GHashTableIter iter;
7655 LLVMValueRef var;
7656 MonoMethod *callee;
7657 gpointer eh_frame;
7660 * Compute the addresses of the LLVM globals pointing to the
7661 * methods called by the current method. Pass it to the trampoline
7662 * code so it can update them after their corresponding method was
7663 * compiled.
7665 g_hash_table_iter_init (&iter, ctx->jit_callees);
7666 i = 0;
7667 while (g_hash_table_iter_next (&iter, NULL, (void**)&var))
7668 callee_vars [i ++] = var;
7670 cfg->native_code = (guint8*)mono_llvm_compile_method (ctx->module->mono_ee, ctx->lmethod, nvars, callee_vars, callee_addrs, &eh_frame);
7672 decode_llvm_eh_info (ctx, eh_frame);
7674 mono_domain_lock (domain);
7675 domain_info = domain_jit_info (domain);
7676 if (!domain_info->llvm_jit_callees)
7677 domain_info->llvm_jit_callees = g_hash_table_new (NULL, NULL);
7678 g_hash_table_iter_init (&iter, ctx->jit_callees);
7679 i = 0;
7680 while (g_hash_table_iter_next (&iter, (void**)&callee, (void**)&var)) {
7681 GSList *addrs = (GSList*)g_hash_table_lookup (domain_info->llvm_jit_callees, callee);
7682 addrs = g_slist_prepend (addrs, callee_addrs [i]);
7683 g_hash_table_insert (domain_info->llvm_jit_callees, callee, addrs);
7684 i ++;
7686 mono_domain_unlock (domain);
7687 #else
7688 mono_llvm_optimize_method (ctx->module->mono_ee, ctx->lmethod);
7690 if (cfg->verbose_level > 1)
7691 mono_llvm_dump_value (ctx->lmethod);
7693 cfg->native_code = (unsigned char*)LLVMGetPointerToGlobal (ctx->module->ee, ctx->lmethod);
7695 /* Set by emit_cb */
7696 g_assert (cfg->code_len);
7697 #endif
7700 if (ctx->module->method_to_lmethod)
7701 g_hash_table_insert (ctx->module->method_to_lmethod, cfg->method, ctx->lmethod);
7702 if (ctx->module->idx_to_lmethod)
7703 g_hash_table_insert (ctx->module->idx_to_lmethod, GINT_TO_POINTER (cfg->method_index), ctx->lmethod);
7705 if (ctx->llvm_only && m_class_is_valuetype (cfg->orig_method->klass) && !(cfg->orig_method->flags & METHOD_ATTRIBUTE_STATIC))
7706 emit_unbox_tramp (ctx, ctx->method_name, ctx->method_type, ctx->lmethod, cfg->method_index);
7710 * mono_llvm_create_vars:
7712 * Same as mono_arch_create_vars () for LLVM.
7714 void
7715 mono_llvm_create_vars (MonoCompile *cfg)
7717 MonoMethodSignature *sig;
7719 sig = mono_method_signature_internal (cfg->method);
7720 if (cfg->gsharedvt && cfg->llvm_only) {
7721 gboolean vretaddr = FALSE;
7723 if (mini_is_gsharedvt_variable_signature (sig) && sig->ret->type != MONO_TYPE_VOID) {
7724 vretaddr = TRUE;
7725 } else {
7726 MonoMethodSignature *sig = mono_method_signature_internal (cfg->method);
7727 LLVMCallInfo *linfo;
7729 linfo = get_llvm_call_info (cfg, sig);
7730 vretaddr = (linfo->ret.storage == LLVMArgVtypeRetAddr || linfo->ret.storage == LLVMArgVtypeByRef || linfo->ret.storage == LLVMArgGsharedvtFixed || linfo->ret.storage == LLVMArgGsharedvtVariable || linfo->ret.storage == LLVMArgGsharedvtFixedVtype);
7732 if (vretaddr) {
7734 * Creating vret_addr forces CEE_SETRET to store the result into it,
7735 * so we don't have to generate any code in our OP_SETRET case.
7737 cfg->vret_addr = mono_compile_create_var (cfg, m_class_get_byval_arg (mono_get_intptr_class ()), OP_ARG);
7738 if (G_UNLIKELY (cfg->verbose_level > 1)) {
7739 printf ("vret_addr = ");
7740 mono_print_ins (cfg->vret_addr);
7743 } else {
7744 mono_arch_create_vars (cfg);
7749 * mono_llvm_emit_call:
7751 * Same as mono_arch_emit_call () for LLVM.
7753 void
7754 mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call)
7756 MonoInst *in;
7757 MonoMethodSignature *sig;
7758 int i, n, stack_size;
7759 LLVMArgInfo *ainfo;
7761 stack_size = 0;
7763 sig = call->signature;
7764 n = sig->param_count + sig->hasthis;
7766 call->cinfo = get_llvm_call_info (cfg, sig);
7768 if (cfg->disable_llvm)
7769 return;
7771 if (sig->call_convention == MONO_CALL_VARARG) {
7772 cfg->exception_message = g_strdup ("varargs");
7773 cfg->disable_llvm = TRUE;
7776 for (i = 0; i < n; ++i) {
7777 MonoInst *ins;
7779 ainfo = call->cinfo->args + i;
7781 in = call->args [i];
7783 /* Simply remember the arguments */
7784 switch (ainfo->storage) {
7785 case LLVMArgNormal: {
7786 MonoType *t = (sig->hasthis && i == 0) ? m_class_get_byval_arg (mono_get_intptr_class ()) : ainfo->type;
7787 int opcode;
7789 opcode = mono_type_to_regmove (cfg, t);
7790 if (opcode == OP_FMOVE) {
7791 MONO_INST_NEW (cfg, ins, OP_FMOVE);
7792 ins->dreg = mono_alloc_freg (cfg);
7793 } else if (opcode == OP_LMOVE) {
7794 MONO_INST_NEW (cfg, ins, OP_LMOVE);
7795 ins->dreg = mono_alloc_lreg (cfg);
7796 } else if (opcode == OP_RMOVE) {
7797 MONO_INST_NEW (cfg, ins, OP_RMOVE);
7798 ins->dreg = mono_alloc_freg (cfg);
7799 } else {
7800 MONO_INST_NEW (cfg, ins, OP_MOVE);
7801 ins->dreg = mono_alloc_ireg (cfg);
7803 ins->sreg1 = in->dreg;
7804 break;
7806 case LLVMArgVtypeByVal:
7807 case LLVMArgVtypeByRef:
7808 case LLVMArgVtypeInReg:
7809 case LLVMArgVtypeAsScalar:
7810 case LLVMArgAsIArgs:
7811 case LLVMArgAsFpArgs:
7812 case LLVMArgGsharedvtVariable:
7813 case LLVMArgGsharedvtFixed:
7814 case LLVMArgGsharedvtFixedVtype:
7815 MONO_INST_NEW (cfg, ins, OP_LLVM_OUTARG_VT);
7816 ins->dreg = mono_alloc_ireg (cfg);
7817 ins->sreg1 = in->dreg;
7818 ins->inst_p0 = mono_mempool_alloc0 (cfg->mempool, sizeof (LLVMArgInfo));
7819 memcpy (ins->inst_p0, ainfo, sizeof (LLVMArgInfo));
7820 ins->inst_vtype = ainfo->type;
7821 ins->klass = mono_class_from_mono_type_internal (ainfo->type);
7822 break;
7823 default:
7824 cfg->exception_message = g_strdup ("ainfo->storage");
7825 cfg->disable_llvm = TRUE;
7826 return;
7829 if (!cfg->disable_llvm) {
7830 MONO_ADD_INS (cfg->cbb, ins);
7831 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, 0, FALSE);
7836 static unsigned char*
7837 alloc_cb (LLVMValueRef function, int size)
7839 MonoCompile *cfg;
7841 cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
7843 if (cfg) {
7844 // FIXME: dynamic
7845 return (unsigned char*)mono_domain_code_reserve (cfg->domain, size);
7846 } else {
7847 return (unsigned char*)mono_domain_code_reserve (mono_domain_get (), size);
7851 static void
7852 emitted_cb (LLVMValueRef function, void *start, void *end)
7854 MonoCompile *cfg;
7856 cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
7857 g_assert (cfg);
7858 cfg->code_len = (guint8*)end - (guint8*)start;
7861 static void
7862 exception_cb (void *data)
7864 MonoCompile *cfg;
7865 MonoJitExceptionInfo *ei;
7866 guint32 ei_len, i, j, nested_len, nindex;
7867 gpointer *type_info;
7868 int this_reg, this_offset;
7870 cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
7871 g_assert (cfg);
7874 * data points to a DWARF FDE structure, convert it to our unwind format and
7875 * save it.
7876 * An alternative would be to save it directly, and modify our unwinder to work
7877 * with it.
7879 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);
7880 if (cfg->verbose_level > 1)
7881 mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
7883 /* Count nested clauses */
7884 nested_len = 0;
7885 for (i = 0; i < ei_len; ++i) {
7886 gint32 cindex1 = *(gint32*)type_info [i];
7887 MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];
7889 for (j = 0; j < cfg->header->num_clauses; ++j) {
7890 int cindex2 = j;
7891 MonoExceptionClause *clause2 = &cfg->header->clauses [cindex2];
7893 if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
7894 nested_len ++;
7899 cfg->llvm_ex_info = (MonoJitExceptionInfo*)mono_mempool_alloc0 (cfg->mempool, (ei_len + nested_len) * sizeof (MonoJitExceptionInfo));
7900 cfg->llvm_ex_info_len = ei_len + nested_len;
7901 memcpy (cfg->llvm_ex_info, ei, ei_len * sizeof (MonoJitExceptionInfo));
7902 /* Fill the rest of the information from the type info */
7903 for (i = 0; i < ei_len; ++i) {
7904 gint32 clause_index = *(gint32*)type_info [i];
7905 MonoExceptionClause *clause = &cfg->header->clauses [clause_index];
7907 cfg->llvm_ex_info [i].flags = clause->flags;
7908 cfg->llvm_ex_info [i].data.catch_class = clause->data.catch_class;
7909 cfg->llvm_ex_info [i].clause_index = clause_index;
7913 * For nested clauses, the LLVM produced exception info associates the try interval with
7914 * the innermost handler, while mono expects it to be associated with all nesting clauses.
7915 * So add new clauses which use the IL info (catch class etc.) from the nesting clause,
7916 * and everything else from the nested clause.
7918 nindex = ei_len;
7919 for (i = 0; i < ei_len; ++i) {
7920 gint32 cindex1 = *(gint32*)type_info [i];
7921 MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];
7923 for (j = 0; j < cfg->header->num_clauses; ++j) {
7924 int cindex2 = j;
7925 MonoExceptionClause *clause2 = &cfg->header->clauses [cindex2];
7926 MonoJitExceptionInfo *nesting_ei, *nested_ei;
7928 if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
7929 /* clause1 is the nested clause */
7930 nested_ei = &cfg->llvm_ex_info [i];
7931 nesting_ei = &cfg->llvm_ex_info [nindex];
7932 nindex ++;
7934 memcpy (nesting_ei, nested_ei, sizeof (MonoJitExceptionInfo));
7936 nesting_ei->flags = clause2->flags;
7937 nesting_ei->data.catch_class = clause2->data.catch_class;
7938 nesting_ei->clause_index = cindex2;
7942 g_assert (nindex == ei_len + nested_len);
7943 cfg->llvm_this_reg = this_reg;
7944 cfg->llvm_this_offset = this_offset;
7946 /* type_info [i] is cfg mempool allocated, no need to free it */
7948 g_free (ei);
7949 g_free (type_info);
7952 #if LLVM_API_VERSION > 100
7954 * decode_llvm_eh_info:
7956 * Decode the EH table emitted by llvm in jit mode, and store
7957 * the result into cfg.
7959 static void
7960 decode_llvm_eh_info (EmitContext *ctx, gpointer eh_frame)
7962 MonoCompile *cfg = ctx->cfg;
7963 guint8 *cie, *fde;
7964 int fde_len;
7965 MonoLLVMFDEInfo info;
7966 MonoJitExceptionInfo *ei;
7967 guint8 *p = (guint8*)eh_frame;
7968 int version, fde_count, fde_offset;
7969 guint32 ei_len, i, nested_len;
7970 gpointer *type_info;
7971 gint32 *table;
7972 guint8 *unw_info;
7975 * Decode the one element EH table emitted by the MonoException class
7976 * in llvm.
7979 /* Similar to decode_llvm_mono_eh_frame () in aot-runtime.c */
7981 version = *p;
7982 g_assert (version == 3);
7983 p ++;
7984 p ++;
7985 p = (guint8 *)ALIGN_PTR_TO (p, 4);
7987 fde_count = *(guint32*)p;
7988 p += 4;
7989 table = (gint32*)p;
7991 g_assert (fde_count <= 2);
7993 /* The first entry is the real method */
7994 g_assert (table [0] == 1);
7995 fde_offset = table [1];
7996 table += fde_count * 2;
7997 /* Extra entry */
7998 cfg->code_len = table [0];
7999 fde_len = table [1] - fde_offset;
8000 table += 2;
8002 fde = (guint8*)eh_frame + fde_offset;
8003 cie = (guint8*)table;
8005 /* Compute lengths */
8006 mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info, NULL, NULL, NULL);
8008 ei = (MonoJitExceptionInfo *)g_malloc0 (info.ex_info_len * sizeof (MonoJitExceptionInfo));
8009 type_info = (gpointer *)g_malloc0 (info.ex_info_len * sizeof (gpointer));
8010 unw_info = (guint8*)g_malloc0 (info.unw_info_len);
8012 mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info, ei, type_info, unw_info);
8014 cfg->encoded_unwind_ops = unw_info;
8015 cfg->encoded_unwind_ops_len = info.unw_info_len;
8016 if (cfg->verbose_level > 1)
8017 mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
8018 if (info.this_reg != -1) {
8019 cfg->llvm_this_reg = info.this_reg;
8020 cfg->llvm_this_offset = info.this_offset;
8023 ei_len = info.ex_info_len;
8025 // Nested clauses are currently disabled
8026 nested_len = 0;
8028 cfg->llvm_ex_info = (MonoJitExceptionInfo*)mono_mempool_alloc0 (cfg->mempool, (ei_len + nested_len) * sizeof (MonoJitExceptionInfo));
8029 cfg->llvm_ex_info_len = ei_len + nested_len;
8030 memcpy (cfg->llvm_ex_info, ei, ei_len * sizeof (MonoJitExceptionInfo));
8031 /* Fill the rest of the information from the type info */
8032 for (i = 0; i < ei_len; ++i) {
8033 gint32 clause_index = *(gint32*)type_info [i];
8034 MonoExceptionClause *clause = &cfg->header->clauses [clause_index];
8036 cfg->llvm_ex_info [i].flags = clause->flags;
8037 cfg->llvm_ex_info [i].data.catch_class = clause->data.catch_class;
8038 cfg->llvm_ex_info [i].clause_index = clause_index;
8041 #endif
8043 static char*
8044 dlsym_cb (const char *name, void **symbol)
8046 MonoDl *current;
8047 char *err;
8049 err = NULL;
8050 if (!strcmp (name, "__bzero")) {
8051 *symbol = (void*)bzero;
8052 } else {
8053 current = mono_dl_open (NULL, 0, NULL);
8054 g_assert (current);
8056 err = mono_dl_symbol (current, name, symbol);
8058 mono_dl_close (current);
8060 #ifdef MONO_ARCH_HAVE_CREATE_LLVM_NATIVE_THUNK
8061 *symbol = (char*)mono_arch_create_llvm_native_thunk (mono_domain_get (), (guint8*)(*symbol));
8062 #endif
8063 return err;
8066 static inline void
8067 AddFunc (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeRef *param_types, int nparams)
8069 LLVMAddFunction (module, name, LLVMFunctionType (ret_type, param_types, nparams, FALSE));
8072 static inline void
8073 AddFunc2 (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeRef param_type1, LLVMTypeRef param_type2)
8075 LLVMTypeRef param_types [4];
8077 param_types [0] = param_type1;
8078 param_types [1] = param_type2;
8080 AddFunc (module, name, ret_type, param_types, 2);
8083 typedef enum {
8084 INTRINS_MEMSET,
8085 INTRINS_MEMCPY,
8086 INTRINS_SADD_OVF_I32,
8087 INTRINS_UADD_OVF_I32,
8088 INTRINS_SSUB_OVF_I32,
8089 INTRINS_USUB_OVF_I32,
8090 INTRINS_SMUL_OVF_I32,
8091 INTRINS_UMUL_OVF_I32,
8092 INTRINS_SADD_OVF_I64,
8093 INTRINS_UADD_OVF_I64,
8094 INTRINS_SSUB_OVF_I64,
8095 INTRINS_USUB_OVF_I64,
8096 INTRINS_SMUL_OVF_I64,
8097 INTRINS_UMUL_OVF_I64,
8098 INTRINS_SIN,
8099 INTRINS_COS,
8100 INTRINS_SQRT,
8101 INTRINS_FABS,
8102 INTRINS_ABSF,
8103 INTRINS_SINF,
8104 INTRINS_COSF,
8105 INTRINS_SQRTF,
8106 INTRINS_POWF,
8107 INTRINS_EXPECT_I8,
8108 INTRINS_EXPECT_I1,
8109 #if defined(TARGET_AMD64) || defined(TARGET_X86)
8110 INTRINS_SSE_PMOVMSKB,
8111 INTRINS_SSE_PSRLI_W,
8112 INTRINS_SSE_PSRAI_W,
8113 INTRINS_SSE_PSLLI_W,
8114 INTRINS_SSE_PSRLI_D,
8115 INTRINS_SSE_PSRAI_D,
8116 INTRINS_SSE_PSLLI_D,
8117 INTRINS_SSE_PSRLI_Q,
8118 INTRINS_SSE_PSLLI_Q,
8119 INTRINS_SSE_SQRT_PD,
8120 INTRINS_SSE_SQRT_PS,
8121 INTRINS_SSE_RSQRT_PS,
8122 INTRINS_SSE_RCP_PS,
8123 INTRINS_SSE_CVTTPD2DQ,
8124 INTRINS_SSE_CVTTPS2DQ,
8125 INTRINS_SSE_CVTDQ2PD,
8126 INTRINS_SSE_CVTDQ2PS,
8127 INTRINS_SSE_CVTPD2DQ,
8128 INTRINS_SSE_CVTPS2DQ,
8129 INTRINS_SSE_CVTPD2PS,
8130 INTRINS_SSE_CVTPS2PD,
8131 INTRINS_SSE_CMPPD,
8132 INTRINS_SSE_CMPPS,
8133 INTRINS_SSE_PACKSSWB,
8134 INTRINS_SSE_PACKUSWB,
8135 INTRINS_SSE_PACKSSDW,
8136 INTRINS_SSE_PACKUSDW,
8137 INTRINS_SSE_MINPS,
8138 INTRINS_SSE_MAXPS,
8139 INTRINS_SSE_HADDPS,
8140 INTRINS_SSE_HSUBPS,
8141 INTRINS_SSE_ADDSUBPS,
8142 INTRINS_SSE_MINPD,
8143 INTRINS_SSE_MAXPD,
8144 INTRINS_SSE_HADDPD,
8145 INTRINS_SSE_HSUBPD,
8146 INTRINS_SSE_ADDSUBPD,
8147 INTRINS_SSE_PADDSW,
8148 INTRINS_SSE_PSUBSW,
8149 INTRINS_SSE_PADDUSW,
8150 INTRINS_SSE_PSUBUSW,
8151 INTRINS_SSE_PAVGW,
8152 INTRINS_SSE_PMULHW,
8153 INTRINS_SSE_PMULHU,
8154 INTRINS_SE_PADDSB,
8155 INTRINS_SSE_PSUBSB,
8156 INTRINS_SSE_PADDUSB,
8157 INTRINS_SSE_PSUBUSB,
8158 INTRINS_SSE_PAVGB,
8159 INTRINS_SSE_PAUSE,
8160 INTRINS_SSE_DPPS,
8161 INTRINS_SSE_ROUNDPD,
8162 #endif
8163 INTRINS_NUM
8164 } IntrinsicId;
8166 typedef struct {
8167 IntrinsicId id;
8168 const char *name;
8169 } IntrinsicDesc;
8171 static IntrinsicDesc intrinsics[] = {
8172 {INTRINS_MEMSET, "llvm.memset.p0i8.i32"},
8173 {INTRINS_MEMCPY, "llvm.memcpy.p0i8.p0i8.i32"},
8174 {INTRINS_SADD_OVF_I32, "llvm.sadd.with.overflow.i32"},
8175 {INTRINS_UADD_OVF_I32, "llvm.uadd.with.overflow.i32"},
8176 {INTRINS_SSUB_OVF_I32, "llvm.ssub.with.overflow.i32"},
8177 {INTRINS_USUB_OVF_I32, "llvm.usub.with.overflow.i32"},
8178 {INTRINS_SMUL_OVF_I32, "llvm.smul.with.overflow.i32"},
8179 {INTRINS_UMUL_OVF_I32, "llvm.umul.with.overflow.i32"},
8180 {INTRINS_SADD_OVF_I64, "llvm.sadd.with.overflow.i64"},
8181 {INTRINS_UADD_OVF_I64, "llvm.uadd.with.overflow.i64"},
8182 {INTRINS_SSUB_OVF_I64, "llvm.ssub.with.overflow.i64"},
8183 {INTRINS_USUB_OVF_I64, "llvm.usub.with.overflow.i64"},
8184 {INTRINS_SMUL_OVF_I64, "llvm.smul.with.overflow.i64"},
8185 {INTRINS_UMUL_OVF_I64, "llvm.umul.with.overflow.i64"},
8186 {INTRINS_SIN, "llvm.sin.f64"},
8187 {INTRINS_COS, "llvm.cos.f64"},
8188 {INTRINS_SQRT, "llvm.sqrt.f64"},
8189 /* This isn't an intrinsic, instead llvm seems to special case it by name */
8190 {INTRINS_FABS, "fabs"},
8191 {INTRINS_ABSF, "llvm.fabs.f32"},
8192 {INTRINS_SINF, "llvm.sin.f32"},
8193 {INTRINS_COSF, "llvm.cos.f32"},
8194 {INTRINS_SQRTF, "llvm.sqrt.f32"},
8195 {INTRINS_POWF, "llvm.pow.f32"},
8196 {INTRINS_EXPECT_I8, "llvm.expect.i8"},
8197 {INTRINS_EXPECT_I1, "llvm.expect.i1"},
8198 #if defined(TARGET_AMD64) || defined(TARGET_X86)
8199 {INTRINS_SSE_PMOVMSKB, "llvm.x86.sse2.pmovmskb.128"},
8200 {INTRINS_SSE_PSRLI_W, "llvm.x86.sse2.psrli.w"},
8201 {INTRINS_SSE_PSRAI_W, "llvm.x86.sse2.psrai.w"},
8202 {INTRINS_SSE_PSLLI_W, "llvm.x86.sse2.pslli.w"},
8203 {INTRINS_SSE_PSRLI_D, "llvm.x86.sse2.psrli.d"},
8204 {INTRINS_SSE_PSRAI_D, "llvm.x86.sse2.psrai.d"},
8205 {INTRINS_SSE_PSLLI_D, "llvm.x86.sse2.pslli.d"},
8206 {INTRINS_SSE_PSRLI_Q, "llvm.x86.sse2.psrli.q"},
8207 {INTRINS_SSE_PSLLI_Q, "llvm.x86.sse2.pslli.q"},
8208 {INTRINS_SSE_SQRT_PD, "llvm.x86.sse2.sqrt.pd"},
8209 {INTRINS_SSE_SQRT_PS, "llvm.x86.sse.sqrt.ps"},
8210 {INTRINS_SSE_RSQRT_PS, "llvm.x86.sse.rsqrt.ps"},
8211 {INTRINS_SSE_RCP_PS, "llvm.x86.sse.rcp.ps"},
8212 {INTRINS_SSE_CVTTPD2DQ, "llvm.x86.sse2.cvttpd2dq"},
8213 {INTRINS_SSE_CVTTPS2DQ, "llvm.x86.sse2.cvttps2dq"},
8214 {INTRINS_SSE_CVTDQ2PD, "llvm.x86.sse2.cvtdq2pd"},
8215 {INTRINS_SSE_CVTDQ2PS, "llvm.x86.sse2.cvtdq2ps"},
8216 {INTRINS_SSE_CVTPD2DQ, "llvm.x86.sse2.cvtpd2dq"},
8217 {INTRINS_SSE_CVTPS2DQ, "llvm.x86.sse2.cvtps2dq"},
8218 {INTRINS_SSE_CVTPD2PS, "llvm.x86.sse2.cvtpd2ps"},
8219 {INTRINS_SSE_CVTPS2PD, "llvm.x86.sse2.cvtps2pd"},
8220 {INTRINS_SSE_CMPPD, "llvm.x86.sse2.cmp.pd"},
8221 {INTRINS_SSE_CMPPS, "llvm.x86.sse.cmp.ps"},
8222 {INTRINS_SSE_PACKSSWB, "llvm.x86.sse2.packsswb.128"},
8223 {INTRINS_SSE_PACKUSWB, "llvm.x86.sse2.packuswb.128"},
8224 {INTRINS_SSE_PACKSSDW, "llvm.x86.sse2.packssdw.128"},
8225 {INTRINS_SSE_PACKUSDW, "llvm.x86.sse41.packusdw"},
8226 {INTRINS_SSE_MINPS, "llvm.x86.sse.min.ps"},
8227 {INTRINS_SSE_MAXPS, "llvm.x86.sse.max.ps"},
8228 {INTRINS_SSE_HADDPS, "llvm.x86.sse3.hadd.ps"},
8229 {INTRINS_SSE_HSUBPS, "llvm.x86.sse3.hsub.ps"},
8230 {INTRINS_SSE_ADDSUBPS, "llvm.x86.sse3.addsub.ps"},
8231 {INTRINS_SSE_MINPD, "llvm.x86.sse2.min.pd"},
8232 {INTRINS_SSE_MAXPD, "llvm.x86.sse2.max.pd"},
8233 {INTRINS_SSE_HADDPD, "llvm.x86.sse3.hadd.pd"},
8234 {INTRINS_SSE_HSUBPD, "llvm.x86.sse3.hsub.pd"},
8235 {INTRINS_SSE_ADDSUBPD, "llvm.x86.sse3.addsub.pd"},
8236 {INTRINS_SSE_PADDSW, "llvm.x86.sse2.padds.w"},
8237 {INTRINS_SSE_PSUBSW, "llvm.x86.sse2.psubs.w"},
8238 {INTRINS_SSE_PADDUSW, "llvm.x86.sse2.paddus.w"},
8239 {INTRINS_SSE_PSUBUSW, "llvm.x86.sse2.psubus.w"},
8240 {INTRINS_SSE_PAVGW, "llvm.x86.sse2.pavg.w"},
8241 {INTRINS_SSE_PMULHW, "llvm.x86.sse2.pmulh.w"},
8242 {INTRINS_SSE_PMULHU, "llvm.x86.sse2.pmulhu.w"},
8243 {INTRINS_SE_PADDSB, "llvm.x86.sse2.padds.b"},
8244 {INTRINS_SSE_PSUBSB, "llvm.x86.sse2.psubs.b"},
8245 {INTRINS_SSE_PADDUSB, "llvm.x86.sse2.paddus.b"},
8246 {INTRINS_SSE_PSUBUSB, "llvm.x86.sse2.psubus.b"},
8247 {INTRINS_SSE_PAVGB, "llvm.x86.sse2.pavg.b"},
8248 {INTRINS_SSE_PAUSE, "llvm.x86.sse2.pause"},
8249 {INTRINS_SSE_DPPS, "llvm.x86.sse41.dpps"},
8250 {INTRINS_SSE_ROUNDPD, "llvm.x86.sse41.round.pd"}
8251 #endif
8254 static void
8255 add_sse_binary (LLVMModuleRef module, const char *name, int type)
8257 LLVMTypeRef ret_type = type_to_simd_type (type);
8258 AddFunc2 (module, name, ret_type, ret_type, ret_type);
8261 static void
8262 add_intrinsic (LLVMModuleRef module, int id)
8264 const char *name;
8265 #if defined(TARGET_AMD64) || defined(TARGET_X86)
8266 LLVMTypeRef ret_type, arg_types [16];
8267 #endif
8269 name = (const char*)g_hash_table_lookup (intrins_id_to_name, GINT_TO_POINTER (id));
8270 g_assert (name);
8272 switch (id) {
8273 case INTRINS_MEMSET: {
8274 LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMInt8Type (), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
8276 AddFunc (module, name, LLVMVoidType (), params, 5);
8277 break;
8279 case INTRINS_MEMCPY: {
8280 LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMPointerType (LLVMInt8Type (), 0), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
8282 AddFunc (module, name, LLVMVoidType (), params, 5);
8283 break;
8285 case INTRINS_SADD_OVF_I32:
8286 case INTRINS_UADD_OVF_I32:
8287 case INTRINS_SSUB_OVF_I32:
8288 case INTRINS_USUB_OVF_I32:
8289 case INTRINS_SMUL_OVF_I32:
8290 case INTRINS_UMUL_OVF_I32: {
8291 LLVMTypeRef ovf_res_i32 [] = { LLVMInt32Type (), LLVMInt1Type () };
8292 LLVMTypeRef params [] = { LLVMInt32Type (), LLVMInt32Type () };
8293 LLVMTypeRef ret_type = LLVMStructType (ovf_res_i32, 2, FALSE);
8295 AddFunc (module, name, ret_type, params, 2);
8296 break;
8298 case INTRINS_SADD_OVF_I64:
8299 case INTRINS_UADD_OVF_I64:
8300 case INTRINS_SSUB_OVF_I64:
8301 case INTRINS_USUB_OVF_I64:
8302 case INTRINS_SMUL_OVF_I64:
8303 case INTRINS_UMUL_OVF_I64: {
8304 LLVMTypeRef ovf_res_i64 [] = { LLVMInt64Type (), LLVMInt1Type () };
8305 LLVMTypeRef params [] = { LLVMInt64Type (), LLVMInt64Type () };
8306 LLVMTypeRef ret_type = LLVMStructType (ovf_res_i64, 2, FALSE);
8308 AddFunc (module, name, ret_type, params, 2);
8309 break;
8311 case INTRINS_SIN:
8312 case INTRINS_COS:
8313 case INTRINS_SQRT:
8314 case INTRINS_FABS: {
8315 LLVMTypeRef params [] = { LLVMDoubleType () };
8317 AddFunc (module, name, LLVMDoubleType (), params, 1);
8318 break;
8320 case INTRINS_SINF:
8321 case INTRINS_COSF:
8322 case INTRINS_SQRTF:
8323 case INTRINS_ABSF: {
8324 LLVMTypeRef params [] = { LLVMFloatType () };
8326 AddFunc (module, name, LLVMFloatType (), params, 1);
8327 break;
8329 case INTRINS_POWF: {
8330 LLVMTypeRef params [] = { LLVMFloatType (), LLVMFloatType () };
8332 AddFunc (module, name, LLVMFloatType (), params, 2);
8333 break;
8335 case INTRINS_EXPECT_I8:
8336 AddFunc2 (module, name, LLVMInt8Type (), LLVMInt8Type (), LLVMInt8Type ());
8337 break;
8338 case INTRINS_EXPECT_I1:
8339 AddFunc2 (module, name, LLVMInt1Type (), LLVMInt1Type (), LLVMInt1Type ());
8340 break;
8341 #if defined(TARGET_AMD64) || defined(TARGET_X86)
8342 case INTRINS_SSE_PMOVMSKB:
8343 /* pmovmskb */
8344 ret_type = LLVMInt32Type ();
8345 arg_types [0] = type_to_simd_type (MONO_TYPE_I1);
8346 AddFunc (module, name, ret_type, arg_types, 1);
8347 break;
8348 case INTRINS_SSE_PSRLI_W:
8349 case INTRINS_SSE_PSRAI_W:
8350 case INTRINS_SSE_PSLLI_W:
8351 /* shifts */
8352 ret_type = type_to_simd_type (MONO_TYPE_I2);
8353 arg_types [0] = ret_type;
8354 arg_types [1] = LLVMInt32Type ();
8355 AddFunc (module, name, ret_type, arg_types, 2);
8356 break;
8357 case INTRINS_SSE_PSRLI_D:
8358 case INTRINS_SSE_PSRAI_D:
8359 case INTRINS_SSE_PSLLI_D:
8360 ret_type = type_to_simd_type (MONO_TYPE_I4);
8361 arg_types [0] = ret_type;
8362 arg_types [1] = LLVMInt32Type ();
8363 AddFunc (module, name, ret_type, arg_types, 2);
8364 break;
8365 case INTRINS_SSE_PSRLI_Q:
8366 case INTRINS_SSE_PSLLI_Q:
8367 ret_type = type_to_simd_type (MONO_TYPE_I8);
8368 arg_types [0] = ret_type;
8369 arg_types [1] = LLVMInt32Type ();
8370 AddFunc (module, name, ret_type, arg_types, 2);
8371 break;
8372 case INTRINS_SSE_SQRT_PD:
8373 /* Unary ops */
8374 ret_type = type_to_simd_type (MONO_TYPE_R8);
8375 arg_types [0] = ret_type;
8376 AddFunc (module, name, ret_type, arg_types, 1);
8377 break;
8378 case INTRINS_SSE_SQRT_PS:
8379 ret_type = type_to_simd_type (MONO_TYPE_R4);
8380 arg_types [0] = ret_type;
8381 AddFunc (module, name, ret_type, arg_types, 1);
8382 break;
8383 case INTRINS_SSE_RSQRT_PS:
8384 ret_type = type_to_simd_type (MONO_TYPE_R4);
8385 arg_types [0] = ret_type;
8386 AddFunc (module, name, ret_type, arg_types, 1);
8387 break;
8388 case INTRINS_SSE_RCP_PS:
8389 ret_type = type_to_simd_type (MONO_TYPE_R4);
8390 arg_types [0] = ret_type;
8391 AddFunc (module, name, ret_type, arg_types, 1);
8392 break;
8393 case INTRINS_SSE_CVTTPD2DQ:
8394 ret_type = type_to_simd_type (MONO_TYPE_I4);
8395 arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
8396 AddFunc (module, name, ret_type, arg_types, 1);
8397 break;
8398 case INTRINS_SSE_CVTTPS2DQ:
8399 ret_type = type_to_simd_type (MONO_TYPE_I4);
8400 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8401 AddFunc (module, name, ret_type, arg_types, 1);
8402 break;
8403 case INTRINS_SSE_CVTDQ2PD:
8404 /* Conversion ops */
8405 ret_type = type_to_simd_type (MONO_TYPE_R8);
8406 arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
8407 AddFunc (module, name, ret_type, arg_types, 1);
8408 break;
8409 case INTRINS_SSE_CVTDQ2PS:
8410 ret_type = type_to_simd_type (MONO_TYPE_R4);
8411 arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
8412 AddFunc (module, name, ret_type, arg_types, 1);
8413 break;
8414 case INTRINS_SSE_CVTPD2DQ:
8415 ret_type = type_to_simd_type (MONO_TYPE_I4);
8416 arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
8417 AddFunc (module, name, ret_type, arg_types, 1);
8418 break;
8419 case INTRINS_SSE_CVTPS2DQ:
8420 ret_type = type_to_simd_type (MONO_TYPE_I4);
8421 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8422 AddFunc (module, name, ret_type, arg_types, 1);
8423 break;
8424 case INTRINS_SSE_CVTPD2PS:
8425 ret_type = type_to_simd_type (MONO_TYPE_R4);
8426 arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
8427 AddFunc (module, name, ret_type, arg_types, 1);
8428 break;
8429 case INTRINS_SSE_CVTPS2PD:
8430 ret_type = type_to_simd_type (MONO_TYPE_R8);
8431 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8432 AddFunc (module, name, ret_type, arg_types, 1);
8433 break;
8434 case INTRINS_SSE_CMPPD:
8435 /* cmp pd/ps */
8436 ret_type = type_to_simd_type (MONO_TYPE_R8);
8437 arg_types [0] = ret_type;
8438 arg_types [1] = ret_type;
8439 arg_types [2] = LLVMInt8Type ();
8440 AddFunc (module, name, ret_type, arg_types, 3);
8441 break;
8442 case INTRINS_SSE_CMPPS:
8443 ret_type = type_to_simd_type (MONO_TYPE_R4);
8444 arg_types [0] = ret_type;
8445 arg_types [1] = ret_type;
8446 arg_types [2] = LLVMInt8Type ();
8447 AddFunc (module, name, ret_type, arg_types, 3);
8448 break;
8449 case INTRINS_SSE_PACKSSWB:
8450 case INTRINS_SSE_PACKUSWB:
8451 case INTRINS_SSE_PACKSSDW:
8452 /* pack */
8453 ret_type = type_to_simd_type (MONO_TYPE_I1);
8454 arg_types [0] = type_to_simd_type (MONO_TYPE_I2);
8455 arg_types [1] = type_to_simd_type (MONO_TYPE_I2);
8456 AddFunc (module, name, ret_type, arg_types, 2);
8457 break;
8458 case INTRINS_SSE_PACKUSDW:
8459 ret_type = type_to_simd_type (MONO_TYPE_I2);
8460 arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
8461 arg_types [1] = type_to_simd_type (MONO_TYPE_I4);
8462 AddFunc (module, name, ret_type, arg_types, 2);
8463 break;
8464 /* SSE Binary ops */
8465 case INTRINS_SSE_PADDSW:
8466 case INTRINS_SSE_PSUBSW:
8467 case INTRINS_SSE_PADDUSW:
8468 case INTRINS_SSE_PSUBUSW:
8469 case INTRINS_SSE_PAVGW:
8470 case INTRINS_SSE_PMULHW:
8471 case INTRINS_SSE_PMULHU:
8472 add_sse_binary (module, name, MONO_TYPE_I2);
8473 break;
8474 case INTRINS_SSE_MINPS:
8475 case INTRINS_SSE_MAXPS:
8476 case INTRINS_SSE_HADDPS:
8477 case INTRINS_SSE_HSUBPS:
8478 case INTRINS_SSE_ADDSUBPS:
8479 add_sse_binary (module, name, MONO_TYPE_R4);
8480 break;
8481 case INTRINS_SSE_MINPD:
8482 case INTRINS_SSE_MAXPD:
8483 case INTRINS_SSE_HADDPD:
8484 case INTRINS_SSE_HSUBPD:
8485 case INTRINS_SSE_ADDSUBPD:
8486 add_sse_binary (module, name, MONO_TYPE_R8);
8487 break;
8488 case INTRINS_SE_PADDSB:
8489 case INTRINS_SSE_PSUBSB:
8490 case INTRINS_SSE_PADDUSB:
8491 case INTRINS_SSE_PSUBUSB:
8492 case INTRINS_SSE_PAVGB:
8493 add_sse_binary (module, name, MONO_TYPE_I1);
8494 break;
8495 case INTRINS_SSE_PAUSE:
8496 AddFunc (module, "llvm.x86.sse2.pause", LLVMVoidType (), NULL, 0);
8497 break;
8498 case INTRINS_SSE_DPPS:
8499 ret_type = type_to_simd_type (MONO_TYPE_R4);
8500 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8501 arg_types [1] = type_to_simd_type (MONO_TYPE_R4);
8502 #if LLVM_API_VERSION >= 500
8503 arg_types [2] = LLVMInt8Type ();
8504 #else
8505 arg_types [2] = LLVMInt32Type ();
8506 #endif
8507 AddFunc (module, name, ret_type, arg_types, 3);
8508 break;
8509 case INTRINS_SSE_ROUNDPD:
8510 ret_type = type_to_simd_type (MONO_TYPE_R8);
8511 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8512 arg_types [1] = LLVMInt32Type ();
8513 AddFunc (module, name, ret_type, arg_types, 2);
8514 break;
8515 #endif /* AMD64 || X86 */
8516 default:
8517 g_assert_not_reached ();
8518 break;
8522 static LLVMValueRef
8523 get_intrinsic (EmitContext *ctx, const char *name)
8525 #if LLVM_API_VERSION > 100
8526 LLVMValueRef res;
8529 * Every method is emitted into its own module so
8530 * we can add intrinsics on demand.
8532 res = LLVMGetNamedFunction (ctx->lmodule, name);
8533 if (!res) {
8534 int id = -1;
8536 /* No locking needed */
8537 id = GPOINTER_TO_INT (g_hash_table_lookup (intrins_name_to_id, name));
8538 id --;
8539 if (id == -1)
8540 printf ("%s\n", name);
8541 g_assert (id != -1);
8542 add_intrinsic (ctx->lmodule, id);
8543 res = LLVMGetNamedFunction (ctx->lmodule, name);
8544 g_assert (res);
8547 return res;
8548 #else
8549 LLVMValueRef res;
8551 res = LLVMGetNamedFunction (ctx->lmodule, name);
8552 g_assert (res);
8553 return res;
8554 #endif
8557 static void
8558 add_intrinsics (LLVMModuleRef module)
8560 int i;
8562 /* Emit declarations of instrinsics */
8564 * It would be nicer to emit only the intrinsics actually used, but LLVM's Module
8565 * type doesn't seem to do any locking.
8567 for (i = 0; i < INTRINS_NUM; ++i)
8568 add_intrinsic (module, i);
8570 /* EH intrinsics */
8572 AddFunc (module, "mono_personality", LLVMVoidType (), NULL, 0);
8574 AddFunc (module, "llvm_resume_unwind_trampoline", LLVMVoidType (), NULL, 0);
8577 /* Load/Store intrinsics */
8579 LLVMTypeRef arg_types [5];
8580 int i;
8581 char name [128];
8583 for (i = 1; i <= 8; i *= 2) {
8584 arg_types [0] = LLVMPointerType (LLVMIntType (i * 8), 0);
8585 arg_types [1] = LLVMInt32Type ();
8586 arg_types [2] = LLVMInt1Type ();
8587 arg_types [3] = LLVMInt32Type ();
8588 sprintf (name, "llvm.mono.load.i%d.p0i%d", i * 8, i * 8);
8589 AddFunc (module, name, LLVMIntType (i * 8), arg_types, 4);
8591 arg_types [0] = LLVMIntType (i * 8);
8592 arg_types [1] = LLVMPointerType (LLVMIntType (i * 8), 0);
8593 arg_types [2] = LLVMInt32Type ();
8594 arg_types [3] = LLVMInt1Type ();
8595 arg_types [4] = LLVMInt32Type ();
8596 sprintf (name, "llvm.mono.store.i%d.p0i%d", i * 8, i * 8);
8597 AddFunc (module, name, LLVMVoidType (), arg_types, 5);
8602 static void
8603 add_types (MonoLLVMModule *module)
8605 module->ptr_type = LLVMPointerType (sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type (), 0);
8608 void
8609 mono_llvm_init (void)
8611 GHashTable *h;
8612 int i;
8614 mono_native_tls_alloc (&current_cfg_tls_id, NULL);
8616 h = g_hash_table_new (NULL, NULL);
8617 for (i = 0; i < INTRINS_NUM; ++i)
8618 g_hash_table_insert (h, GINT_TO_POINTER (intrinsics [i].id), (gpointer)intrinsics [i].name);
8619 intrins_id_to_name = h;
8621 h = g_hash_table_new (g_str_hash, g_str_equal);
8622 for (i = 0; i < INTRINS_NUM; ++i)
8623 g_hash_table_insert (h, (gpointer)intrinsics [i].name, GINT_TO_POINTER (intrinsics [i].id + 1));
8624 intrins_name_to_id = h;
8627 static void
8628 init_jit_module (MonoDomain *domain)
8630 MonoJitDomainInfo *dinfo;
8631 MonoLLVMModule *module;
8632 char *name;
8634 dinfo = domain_jit_info (domain);
8635 if (dinfo->llvm_module)
8636 return;
8638 mono_loader_lock ();
8640 if (dinfo->llvm_module) {
8641 mono_loader_unlock ();
8642 return;
8645 module = g_new0 (MonoLLVMModule, 1);
8647 name = g_strdup_printf ("mono-%s", domain->friendly_name);
8648 module->lmodule = LLVMModuleCreateWithName (name);
8649 module->context = LLVMGetGlobalContext ();
8651 module->mono_ee = (MonoEERef*)mono_llvm_create_ee (LLVMCreateModuleProviderForExistingModule (module->lmodule), alloc_cb, emitted_cb, exception_cb, dlsym_cb, &module->ee);
8653 add_intrinsics (module->lmodule);
8654 add_types (module);
8656 module->llvm_types = g_hash_table_new (NULL, NULL);
8658 #if LLVM_API_VERSION < 100
8659 MonoJitICallInfo *info;
8661 info = mono_find_jit_icall_by_name ("llvm_resume_unwind_trampoline");
8662 g_assert (info);
8663 LLVMAddGlobalMapping (module->ee, LLVMGetNamedFunction (module->lmodule, "llvm_resume_unwind_trampoline"), (void*)info->func);
8664 #endif
8666 mono_memory_barrier ();
8668 dinfo->llvm_module = module;
8670 mono_loader_unlock ();
8673 void
8674 mono_llvm_cleanup (void)
8676 MonoLLVMModule *module = &aot_module;
8678 if (module->lmodule)
8679 LLVMDisposeModule (module->lmodule);
8681 if (module->context)
8682 LLVMContextDispose (module->context);
8685 void
8686 mono_llvm_free_domain_info (MonoDomain *domain)
8688 MonoJitDomainInfo *info = domain_jit_info (domain);
8689 MonoLLVMModule *module = (MonoLLVMModule*)info->llvm_module;
8690 int i;
8692 if (!module)
8693 return;
8695 g_hash_table_destroy (module->llvm_types);
8697 mono_llvm_dispose_ee (module->mono_ee);
8699 if (module->bb_names) {
8700 for (i = 0; i < module->bb_names_len; ++i)
8701 g_free (module->bb_names [i]);
8702 g_free (module->bb_names);
8704 //LLVMDisposeModule (module->module);
8706 g_free (module);
8708 info->llvm_module = NULL;
8711 void
8712 mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, int initial_got_size, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only)
8714 MonoLLVMModule *module = &aot_module;
8716 /* Delete previous module */
8717 g_hash_table_destroy (module->plt_entries);
8718 if (module->lmodule)
8719 LLVMDisposeModule (module->lmodule);
8721 memset (module, 0, sizeof (aot_module));
8723 module->lmodule = LLVMModuleCreateWithName ("aot");
8724 module->assembly = assembly;
8725 module->global_prefix = g_strdup (global_prefix);
8726 module->got_symbol = g_strdup_printf ("%s_llvm_got", global_prefix);
8727 module->eh_frame_symbol = g_strdup_printf ("%s_eh_frame", global_prefix);
8728 module->get_method_symbol = g_strdup_printf ("%s_get_method", global_prefix);
8729 module->get_unbox_tramp_symbol = g_strdup_printf ("%s_get_unbox_tramp", global_prefix);
8730 module->external_symbols = TRUE;
8731 module->emit_dwarf = emit_dwarf;
8732 module->static_link = static_link;
8733 module->llvm_only = llvm_only;
8734 /* The first few entries are reserved */
8735 module->max_got_offset = initial_got_size;
8736 module->context = LLVMGetGlobalContext ();
8738 if (llvm_only)
8739 /* clang ignores our debug info because it has an invalid version */
8740 module->emit_dwarf = FALSE;
8742 add_intrinsics (module->lmodule);
8743 add_types (module);
8745 #if LLVM_API_VERSION > 100
8746 if (module->emit_dwarf) {
8747 char *dir, *build_info, *s, *cu_name;
8749 module->di_builder = mono_llvm_create_di_builder (module->lmodule);
8751 // FIXME:
8752 dir = g_strdup (".");
8753 build_info = mono_get_runtime_build_info ();
8754 s = g_strdup_printf ("Mono AOT Compiler %s (LLVM)", build_info);
8755 cu_name = g_path_get_basename (assembly->image->name);
8756 module->cu = mono_llvm_di_create_compile_unit (module->di_builder, cu_name, dir, s);
8757 g_free (dir);
8758 g_free (build_info);
8759 g_free (s);
8761 #endif
8763 #if defined(TARGET_AMD64) && defined(TARGET_WIN32) && defined(HOST_WIN32) && defined(_MSC_VER)
8764 const char linker_options[] = "Linker Options";
8765 const char *default_static_lib_names[] = { "/DEFAULTLIB:libcmt",
8766 "/DEFAULTLIB:libucrt.lib",
8767 "/DEFAULTLIB:libvcruntime.lib" };
8768 const char *default_dynamic_lib_names[] = { "/DEFAULTLIB:msvcrt",
8769 "/DEFAULTLIB:ucrt.lib",
8770 "/DEFAULTLIB:vcruntime.lib" };
8772 LLVMValueRef linker_option_args[3];
8773 LLVMValueRef default_lib_args[G_N_ELEMENTS (default_static_lib_names)];
8774 LLVMValueRef default_lib_nodes[G_N_ELEMENTS(default_dynamic_lib_names)];
8776 g_assert (G_N_ELEMENTS (default_static_lib_names) == G_N_ELEMENTS (default_dynamic_lib_names));
8778 const char *default_lib_name = NULL;
8779 for (int i = 0; i < G_N_ELEMENTS (default_static_lib_names); ++i) {
8780 const char *default_lib_name = NULL;
8782 if (static_link)
8783 default_lib_name = default_static_lib_names[i];
8784 else
8785 default_lib_name = default_dynamic_lib_names[i];
8787 default_lib_args[i] = LLVMMDString (default_lib_name, strlen (default_lib_name));
8788 default_lib_nodes[i] = LLVMMDNode (default_lib_args + i, 1);
8791 linker_option_args[0] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
8792 linker_option_args[1] = LLVMMDString (linker_options, G_N_ELEMENTS (linker_options) - 1);
8793 linker_option_args[2] = LLVMMDNode (default_lib_nodes, G_N_ELEMENTS (default_lib_nodes));
8795 LLVMAddNamedMetadataOperand (module->lmodule, "llvm.module.flags", LLVMMDNode (linker_option_args, G_N_ELEMENTS (linker_option_args)));
8796 #endif
8798 /* Add GOT */
8800 * We couldn't compute the type of the LLVM global representing the got because
8801 * its size is only known after all the methods have been emitted. So create
8802 * a dummy variable, and replace all uses it with the real got variable when
8803 * its size is known in mono_llvm_emit_aot_module ().
8806 LLVMTypeRef got_type = LLVMArrayType (module->ptr_type, 0);
8808 module->got_var = LLVMAddGlobal (module->lmodule, got_type, "mono_dummy_got");
8809 LLVMSetInitializer (module->got_var, LLVMConstNull (got_type));
8812 /* Add initialization array */
8813 if (llvm_only) {
8814 LLVMTypeRef inited_type = LLVMArrayType (LLVMInt8Type (), 0);
8816 module->inited_var = LLVMAddGlobal (aot_module.lmodule, inited_type, "mono_inited_tmp");
8817 LLVMSetInitializer (module->inited_var, LLVMConstNull (inited_type));
8820 if (llvm_only)
8821 emit_init_icall_wrappers (module);
8823 emit_llvm_code_start (module);
8825 /* Add a dummy personality function */
8826 if (!use_debug_personality) {
8827 LLVMValueRef personality = LLVMAddFunction (module->lmodule, default_personality_name, LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE));
8828 LLVMSetLinkage (personality, LLVMExternalLinkage);
8830 //EMCC chockes if the personality function is referenced in the 'used' array
8831 #ifndef TARGET_WASM
8832 mark_as_used (module, personality);
8833 #endif
8836 /* Add a reference to the c++ exception we throw/catch */
8838 LLVMTypeRef exc = LLVMPointerType (LLVMInt8Type (), 0);
8839 module->sentinel_exception = LLVMAddGlobal (module->lmodule, exc, "_ZTIPi");
8840 LLVMSetLinkage (module->sentinel_exception, LLVMExternalLinkage);
8841 mono_llvm_set_is_constant (module->sentinel_exception);
8844 module->llvm_types = g_hash_table_new (NULL, NULL);
8845 module->plt_entries = g_hash_table_new (g_str_hash, g_str_equal);
8846 module->plt_entries_ji = g_hash_table_new (NULL, NULL);
8847 module->direct_callables = g_hash_table_new (g_str_hash, g_str_equal);
8848 module->method_to_lmethod = g_hash_table_new (NULL, NULL);
8849 module->idx_to_lmethod = g_hash_table_new (NULL, NULL);
8850 module->idx_to_unbox_tramp = g_hash_table_new (NULL, NULL);
8851 module->method_to_callers = g_hash_table_new (NULL, NULL);
8854 static LLVMValueRef
8855 llvm_array_from_uints (LLVMTypeRef el_type, guint32 *values, int nvalues)
8857 int i;
8858 LLVMValueRef res, *vals;
8860 vals = g_new0 (LLVMValueRef, nvalues);
8861 for (i = 0; i < nvalues; ++i)
8862 vals [i] = LLVMConstInt (LLVMInt32Type (), values [i], FALSE);
8863 res = LLVMConstArray (LLVMInt32Type (), vals, nvalues);
8864 g_free (vals);
8865 return res;
8868 static LLVMValueRef
8869 llvm_array_from_bytes (guint8 *values, int nvalues)
8871 int i;
8872 LLVMValueRef res, *vals;
8874 vals = g_new0 (LLVMValueRef, nvalues);
8875 for (i = 0; i < nvalues; ++i)
8876 vals [i] = LLVMConstInt (LLVMInt8Type (), values [i], FALSE);
8877 res = LLVMConstArray (LLVMInt8Type (), vals, nvalues);
8878 g_free (vals);
8879 return res;
8882 * mono_llvm_emit_aot_file_info:
8884 * Emit the MonoAotFileInfo structure.
8885 * Same as emit_aot_file_info () in aot-compiler.c.
8887 void
8888 mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code)
8890 MonoLLVMModule *module = &aot_module;
8892 /* Save these for later */
8893 memcpy (&module->aot_info, info, sizeof (MonoAotFileInfo));
8894 module->has_jitted_code = has_jitted_code;
8898 * mono_llvm_emit_aot_data:
8900 * Emit the binary data DATA pointed to by symbol SYMBOL.
8902 void
8903 mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
8905 MonoLLVMModule *module = &aot_module;
8906 LLVMTypeRef type;
8907 LLVMValueRef d;
8909 type = LLVMArrayType (LLVMInt8Type (), data_len);
8910 d = LLVMAddGlobal (module->lmodule, type, symbol);
8911 LLVMSetVisibility (d, LLVMHiddenVisibility);
8912 LLVMSetLinkage (d, LLVMInternalLinkage);
8913 LLVMSetInitializer (d, mono_llvm_create_constant_data_array (data, data_len));
8914 LLVMSetAlignment (d, 8);
8915 mono_llvm_set_is_constant (d);
8918 /* Add a reference to a global defined in JITted code */
8919 static LLVMValueRef
8920 AddJitGlobal (MonoLLVMModule *module, LLVMTypeRef type, const char *name)
8922 char *s;
8923 LLVMValueRef v;
8925 s = g_strdup_printf ("%s%s", module->global_prefix, name);
8926 v = LLVMAddGlobal (module->lmodule, LLVMInt8Type (), s);
8927 LLVMSetVisibility (v, LLVMHiddenVisibility);
8928 g_free (s);
8929 return v;
8932 static void
8933 emit_aot_file_info (MonoLLVMModule *module)
8935 LLVMTypeRef file_info_type;
8936 LLVMTypeRef *eltypes, eltype;
8937 LLVMValueRef info_var;
8938 LLVMValueRef *fields;
8939 int i, nfields, tindex;
8940 MonoAotFileInfo *info;
8941 LLVMModuleRef lmodule = module->lmodule;
8943 info = &module->aot_info;
8945 /* Create an LLVM type to represent MonoAotFileInfo */
8946 nfields = 2 + MONO_AOT_FILE_INFO_NUM_SYMBOLS + 19 + 5;
8947 eltypes = g_new (LLVMTypeRef, nfields);
8948 tindex = 0;
8949 eltypes [tindex ++] = LLVMInt32Type ();
8950 eltypes [tindex ++] = LLVMInt32Type ();
8951 /* Symbols */
8952 for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i)
8953 eltypes [tindex ++] = LLVMPointerType (LLVMInt8Type (), 0);
8954 /* Scalars */
8955 for (i = 0; i < 18; ++i)
8956 eltypes [tindex ++] = LLVMInt32Type ();
8957 /* Arrays */
8958 eltypes [tindex ++] = LLVMArrayType (LLVMInt32Type (), MONO_AOT_TABLE_NUM);
8959 for (i = 0; i < 4; ++i)
8960 eltypes [tindex ++] = LLVMArrayType (LLVMInt32Type (), MONO_AOT_TRAMP_NUM);
8961 eltypes [tindex ++] = LLVMArrayType (LLVMInt8Type (), 16);
8962 g_assert (tindex == nfields);
8963 file_info_type = LLVMStructCreateNamed (module->context, "MonoAotFileInfo");
8964 LLVMStructSetBody (file_info_type, eltypes, nfields, FALSE);
8966 info_var = LLVMAddGlobal (lmodule, file_info_type, "mono_aot_file_info");
8967 if (module->static_link) {
8968 LLVMSetVisibility (info_var, LLVMHiddenVisibility);
8969 LLVMSetLinkage (info_var, LLVMInternalLinkage);
8972 #ifdef TARGET_WIN32
8973 if (!module->static_link) {
8974 LLVMSetDLLStorageClass (info_var, LLVMDLLExportStorageClass);
8976 #endif
8978 fields = g_new (LLVMValueRef, nfields);
8979 tindex = 0;
8980 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->version, FALSE);
8981 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->dummy, FALSE);
8983 /* Symbols */
8985 * We use LLVMGetNamedGlobal () for symbol which are defined in LLVM code, and LLVMAddGlobal ()
8986 * for symbols defined in the .s file emitted by the aot compiler.
8988 eltype = eltypes [tindex];
8989 if (module->llvm_only)
8990 fields [tindex ++] = LLVMConstNull (eltype);
8991 else
8992 fields [tindex ++] = AddJitGlobal (module, eltype, "jit_got");
8993 fields [tindex ++] = module->got_var;
8994 /* llc defines this directly */
8995 if (!module->llvm_only) {
8996 fields [tindex ++] = LLVMAddGlobal (lmodule, eltype, module->eh_frame_symbol);
8997 fields [tindex ++] = LLVMConstNull (eltype);
8998 fields [tindex ++] = LLVMConstNull (eltype);
8999 } else {
9000 fields [tindex ++] = LLVMConstNull (eltype);
9001 fields [tindex ++] = module->get_method;
9002 fields [tindex ++] = module->get_unbox_tramp;
9004 if (module->has_jitted_code) {
9005 fields [tindex ++] = AddJitGlobal (module, eltype, "jit_code_start");
9006 fields [tindex ++] = AddJitGlobal (module, eltype, "jit_code_end");
9007 } else {
9008 fields [tindex ++] = LLVMConstNull (eltype);
9009 fields [tindex ++] = LLVMConstNull (eltype);
9011 if (!module->llvm_only)
9012 fields [tindex ++] = AddJitGlobal (module, eltype, "method_addresses");
9013 else
9014 fields [tindex ++] = LLVMConstNull (eltype);
9015 if (info->flags & MONO_AOT_FILE_FLAG_SEPARATE_DATA) {
9016 for (i = 0; i < MONO_AOT_TABLE_NUM; ++i)
9017 fields [tindex ++] = LLVMConstNull (eltype);
9018 } else {
9019 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "blob");
9020 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "class_name_table");
9021 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "class_info_offsets");
9022 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "method_info_offsets");
9023 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "ex_info_offsets");
9024 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "extra_method_info_offsets");
9025 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "extra_method_table");
9026 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "got_info_offsets");
9027 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "llvm_got_info_offsets");
9028 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "image_table");
9029 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "weak_field_indexes");
9031 /* Not needed (mem_end) */
9032 fields [tindex ++] = LLVMConstNull (eltype);
9033 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "assembly_guid");
9034 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "runtime_version");
9035 if (info->trampoline_size [0]) {
9036 fields [tindex ++] = AddJitGlobal (module, eltype, "specific_trampolines");
9037 fields [tindex ++] = AddJitGlobal (module, eltype, "static_rgctx_trampolines");
9038 fields [tindex ++] = AddJitGlobal (module, eltype, "imt_trampolines");
9039 fields [tindex ++] = AddJitGlobal (module, eltype, "gsharedvt_arg_trampolines");
9040 fields [tindex ++] = AddJitGlobal (module, eltype, "ftnptr_arg_trampolines");
9041 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_arbitrary_trampolines");
9042 } else {
9043 fields [tindex ++] = LLVMConstNull (eltype);
9044 fields [tindex ++] = LLVMConstNull (eltype);
9045 fields [tindex ++] = LLVMConstNull (eltype);
9046 fields [tindex ++] = LLVMConstNull (eltype);
9047 fields [tindex ++] = LLVMConstNull (eltype);
9048 fields [tindex ++] = LLVMConstNull (eltype);
9050 if (module->static_link && !module->llvm_only)
9051 fields [tindex ++] = AddJitGlobal (module, eltype, "globals");
9052 else
9053 fields [tindex ++] = LLVMConstNull (eltype);
9054 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "assembly_name");
9055 if (!module->llvm_only) {
9056 fields [tindex ++] = AddJitGlobal (module, eltype, "plt");
9057 fields [tindex ++] = AddJitGlobal (module, eltype, "plt_end");
9058 fields [tindex ++] = AddJitGlobal (module, eltype, "unwind_info");
9059 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_trampolines");
9060 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_trampolines_end");
9061 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_trampoline_addresses");
9062 } else {
9063 fields [tindex ++] = LLVMConstNull (eltype);
9064 fields [tindex ++] = LLVMConstNull (eltype);
9065 fields [tindex ++] = LLVMConstNull (eltype);
9066 fields [tindex ++] = LLVMConstNull (eltype);
9067 fields [tindex ++] = LLVMConstNull (eltype);
9068 fields [tindex ++] = LLVMConstNull (eltype);
9071 for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i) {
9072 g_assert (fields [2 + i]);
9073 fields [2 + i] = LLVMConstBitCast (fields [2 + i], eltype);
9076 /* Scalars */
9077 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->plt_got_offset_base, FALSE);
9078 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->got_size, FALSE);
9079 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->plt_size, FALSE);
9080 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nmethods, FALSE);
9081 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nextra_methods, FALSE);
9082 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->flags, FALSE);
9083 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->opts, FALSE);
9084 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->simd_opts, FALSE);
9085 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->gc_name_index, FALSE);
9086 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->num_rgctx_fetch_trampolines, FALSE);
9087 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->double_align, FALSE);
9088 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->long_align, FALSE);
9089 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->generic_tramp_num, FALSE);
9090 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->card_table_shift_bits, FALSE);
9091 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->card_table_mask, FALSE);
9092 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->tramp_page_size, FALSE);
9093 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nshared_got_entries, FALSE);
9094 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->datafile_size, FALSE);
9095 /* Arrays */
9096 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->table_offsets, MONO_AOT_TABLE_NUM);
9097 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->num_trampolines, MONO_AOT_TRAMP_NUM);
9098 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->trampoline_got_offset_base, MONO_AOT_TRAMP_NUM);
9099 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->trampoline_size, MONO_AOT_TRAMP_NUM);
9100 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->tramp_page_code_offsets, MONO_AOT_TRAMP_NUM);
9102 fields [tindex ++] = llvm_array_from_bytes (info->aotid, 16);
9103 g_assert (tindex == nfields);
9105 LLVMSetInitializer (info_var, LLVMConstNamedStruct (file_info_type, fields, nfields));
9107 if (module->static_link) {
9108 char *s, *p;
9109 LLVMValueRef var;
9111 s = g_strdup_printf ("mono_aot_module_%s_info", module->assembly->aname.name);
9112 /* Get rid of characters which cannot occur in symbols */
9113 p = s;
9114 for (p = s; *p; ++p) {
9115 if (!(isalnum (*p) || *p == '_'))
9116 *p = '_';
9118 var = LLVMAddGlobal (module->lmodule, LLVMPointerType (LLVMInt8Type (), 0), s);
9119 g_free (s);
9120 LLVMSetInitializer (var, LLVMConstBitCast (LLVMGetNamedGlobal (module->lmodule, "mono_aot_file_info"), LLVMPointerType (LLVMInt8Type (), 0)));
9121 LLVMSetLinkage (var, LLVMExternalLinkage);
9126 * Emit the aot module into the LLVM bitcode file FILENAME.
9128 void
9129 mono_llvm_emit_aot_module (const char *filename, const char *cu_name)
9131 LLVMTypeRef got_type, inited_type;
9132 LLVMValueRef real_got, real_inited;
9133 MonoLLVMModule *module = &aot_module;
9135 emit_llvm_code_end (module);
9138 * Create the real got variable and replace all uses of the dummy variable with
9139 * the real one.
9141 got_type = LLVMArrayType (module->ptr_type, module->max_got_offset + 1);
9142 real_got = LLVMAddGlobal (module->lmodule, got_type, module->got_symbol);
9143 LLVMSetInitializer (real_got, LLVMConstNull (got_type));
9144 if (module->external_symbols) {
9145 LLVMSetLinkage (real_got, LLVMExternalLinkage);
9146 LLVMSetVisibility (real_got, LLVMHiddenVisibility);
9147 } else {
9148 LLVMSetLinkage (real_got, LLVMInternalLinkage);
9150 mono_llvm_replace_uses_of (module->got_var, real_got);
9152 mark_as_used (&aot_module, real_got);
9154 /* Delete the dummy got so it doesn't become a global */
9155 LLVMDeleteGlobal (module->got_var);
9156 module->got_var = real_got;
9159 * Same for the init_var
9161 if (module->llvm_only) {
9162 inited_type = LLVMArrayType (LLVMInt8Type (), module->max_inited_idx + 1);
9163 real_inited = LLVMAddGlobal (module->lmodule, inited_type, "mono_inited");
9164 LLVMSetInitializer (real_inited, LLVMConstNull (inited_type));
9165 LLVMSetLinkage (real_inited, LLVMInternalLinkage);
9166 mono_llvm_replace_uses_of (module->inited_var, real_inited);
9167 LLVMDeleteGlobal (module->inited_var);
9170 if (module->llvm_only) {
9171 emit_get_method (&aot_module);
9172 emit_get_unbox_tramp (&aot_module);
9175 emit_llvm_used (&aot_module);
9176 emit_dbg_info (&aot_module, filename, cu_name);
9177 emit_aot_file_info (&aot_module);
9180 * Replace GOT entries for directly callable methods with the methods themselves.
9181 * It would be easier to implement this by predefining all methods before compiling
9182 * their bodies, but that couldn't handle the case when a method fails to compile
9183 * with llvm.
9185 if (module->llvm_only) {
9186 GHashTableIter iter;
9187 MonoMethod *method;
9188 GSList *callers, *l;
9190 g_hash_table_iter_init (&iter, module->method_to_callers);
9191 while (g_hash_table_iter_next (&iter, (void**)&method, (void**)&callers)) {
9192 LLVMValueRef lmethod;
9194 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
9195 continue;
9197 lmethod = (LLVMValueRef)g_hash_table_lookup (module->method_to_lmethod, method);
9198 if (lmethod) {
9199 for (l = callers; l; l = l->next) {
9200 LLVMValueRef caller = (LLVMValueRef)l->data;
9202 mono_llvm_replace_uses_of (caller, lmethod);
9208 /* Replace PLT entries for directly callable methods with the methods themselves */
9210 GHashTableIter iter;
9211 MonoJumpInfo *ji;
9212 LLVMValueRef callee;
9214 g_hash_table_iter_init (&iter, module->plt_entries_ji);
9215 while (g_hash_table_iter_next (&iter, (void**)&ji, (void**)&callee)) {
9216 if (mono_aot_is_direct_callable (ji)) {
9217 LLVMValueRef lmethod;
9219 lmethod = (LLVMValueRef)g_hash_table_lookup (module->method_to_lmethod, ji->data.method);
9220 /* The types might not match because the caller might pass an rgctx */
9221 if (lmethod && LLVMTypeOf (callee) == LLVMTypeOf (lmethod)) {
9222 mono_llvm_replace_uses_of (callee, lmethod);
9223 mono_aot_mark_unused_llvm_plt_entry (ji);
9229 #if 1
9231 char *verifier_err;
9233 if (LLVMVerifyModule (module->lmodule, LLVMReturnStatusAction, &verifier_err)) {
9234 printf ("%s\n", verifier_err);
9235 g_assert_not_reached ();
9238 #endif
9240 LLVMWriteBitcodeToFile (module->lmodule, filename);
9244 static LLVMValueRef
9245 md_string (const char *s)
9247 return LLVMMDString (s, strlen (s));
9250 /* Debugging support */
9252 static void
9253 emit_dbg_info (MonoLLVMModule *module, const char *filename, const char *cu_name)
9255 LLVMModuleRef lmodule = module->lmodule;
9256 LLVMValueRef args [16], ver;
9259 * This can only be enabled when LLVM code is emitted into a separate object
9260 * file, since the AOT compiler also emits dwarf info,
9261 * and the abbrev indexes will not be correct since llvm has added its own
9262 * abbrevs.
9264 if (!module->emit_dwarf)
9265 return;
9267 #if LLVM_API_VERSION > 100
9268 mono_llvm_di_builder_finalize (module->di_builder);
9269 #else
9270 LLVMValueRef cu_args [16], cu;
9271 int n_cuargs;
9272 char *build_info, *s, *dir;
9275 * Emit dwarf info in the form of LLVM metadata. There is some
9276 * out-of-date documentation at:
9277 * http://llvm.org/docs/SourceLevelDebugging.html
9278 * but most of this was gathered from the llvm and
9279 * clang sources.
9282 n_cuargs = 0;
9283 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), DW_TAG_compile_unit, FALSE);
9284 /* CU name/compilation dir */
9285 dir = g_path_get_dirname (filename);
9286 args [0] = LLVMMDString (cu_name, strlen (cu_name));
9287 args [1] = LLVMMDString (dir, strlen (dir));
9288 cu_args [n_cuargs ++] = LLVMMDNode (args, 2);
9289 g_free (dir);
9290 /* Language */
9291 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), DW_LANG_C99, FALSE);
9292 /* Producer */
9293 build_info = mono_get_runtime_build_info ();
9294 s = g_strdup_printf ("Mono AOT Compiler %s (LLVM)", build_info);
9295 cu_args [n_cuargs ++] = LLVMMDString (s, strlen (s));
9296 g_free (build_info);
9297 /* Optimized */
9298 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9299 /* Flags */
9300 cu_args [n_cuargs ++] = LLVMMDString ("", strlen (""));
9301 /* Runtime version */
9302 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9303 /* Enums */
9304 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
9305 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
9306 /* Subprograms */
9307 if (module->subprogram_mds) {
9308 LLVMValueRef *mds;
9309 int i;
9311 mds = g_new0 (LLVMValueRef, module->subprogram_mds->len);
9312 for (i = 0; i < module->subprogram_mds->len; ++i)
9313 mds [i] = (LLVMValueRef)g_ptr_array_index (module->subprogram_mds, i);
9314 cu_args [n_cuargs ++] = LLVMMDNode (mds, module->subprogram_mds->len);
9315 } else {
9316 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
9318 /* GVs */
9319 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
9320 /* Imported modules */
9321 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
9322 /* SplitName */
9323 cu_args [n_cuargs ++] = LLVMMDString ("", strlen (""));
9324 /* DebugEmissionKind = FullDebug */
9325 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9326 cu = LLVMMDNode (cu_args, n_cuargs);
9327 LLVMAddNamedMetadataOperand (lmodule, "llvm.dbg.cu", cu);
9328 #endif
9330 #if LLVM_API_VERSION > 100
9331 args [0] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
9332 args [1] = LLVMMDString ("Dwarf Version", strlen ("Dwarf Version"));
9333 args [2] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
9334 ver = LLVMMDNode (args, 3);
9335 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
9337 args [0] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
9338 args [1] = LLVMMDString ("Debug Info Version", strlen ("Debug Info Version"));
9339 args [2] = LLVMConstInt (LLVMInt64Type (), 3, FALSE);
9340 ver = LLVMMDNode (args, 3);
9341 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
9342 #else
9343 args [0] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9344 args [1] = LLVMMDString ("Dwarf Version", strlen ("Dwarf Version"));
9345 args [2] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
9346 ver = LLVMMDNode (args, 3);
9347 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
9349 args [0] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9350 args [1] = LLVMMDString ("Debug Info Version", strlen ("Debug Info Version"));
9351 args [2] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9352 ver = LLVMMDNode (args, 3);
9353 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
9354 #endif
9357 static LLVMValueRef
9358 emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, const char *name)
9360 MonoLLVMModule *module = ctx->module;
9361 MonoDebugMethodInfo *minfo = ctx->minfo;
9362 char *source_file, *dir, *filename;
9363 LLVMValueRef md, args [16], ctx_args [16], md_args [64], type_args [16], ctx_md, type_md;
9364 MonoSymSeqPoint *sym_seq_points;
9365 int n_seq_points;
9367 if (!minfo)
9368 return NULL;
9370 mono_debug_get_seq_points (minfo, &source_file, NULL, NULL, &sym_seq_points, &n_seq_points);
9371 if (!source_file)
9372 source_file = g_strdup ("<unknown>");
9373 dir = g_path_get_dirname (source_file);
9374 filename = g_path_get_basename (source_file);
9376 #if LLVM_API_VERSION > 100
9377 return (LLVMValueRef)mono_llvm_di_create_function (module->di_builder, module->cu, method, cfg->method->name, name, dir, filename, n_seq_points ? sym_seq_points [0].line : 1);
9378 #endif
9380 ctx_args [0] = LLVMConstInt (LLVMInt32Type (), 0x29, FALSE);
9381 args [0] = md_string (filename);
9382 args [1] = md_string (dir);
9383 ctx_args [1] = LLVMMDNode (args, 2);
9384 ctx_md = LLVMMDNode (ctx_args, 2);
9386 type_args [0] = LLVMConstInt (LLVMInt32Type (), DW_TAG_subroutine_type, FALSE);
9387 type_args [1] = NULL;
9388 type_args [2] = NULL;
9389 type_args [3] = LLVMMDString ("", 0);
9390 type_args [4] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9391 type_args [5] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
9392 type_args [6] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
9393 type_args [7] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
9394 type_args [8] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9395 type_args [9] = NULL;
9396 type_args [10] = NULL;
9397 type_args [11] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9398 type_args [12] = NULL;
9399 type_args [13] = NULL;
9400 type_args [14] = NULL;
9401 type_md = LLVMMDNode (type_args, 14);
9403 /* http://llvm.org/docs/SourceLevelDebugging.html#subprogram-descriptors */
9404 md_args [0] = LLVMConstInt (LLVMInt32Type (), DW_TAG_subprogram, FALSE);
9405 /* Source directory + file pair */
9406 args [0] = md_string (filename);
9407 args [1] = md_string (dir);
9408 md_args [1] = LLVMMDNode (args ,2);
9409 md_args [2] = ctx_md;
9410 md_args [3] = md_string (cfg->method->name);
9411 md_args [4] = md_string (name);
9412 md_args [5] = md_string (name);
9413 /* Line number */
9414 if (n_seq_points)
9415 md_args [6] = LLVMConstInt (LLVMInt32Type (), sym_seq_points [0].line, FALSE);
9416 else
9417 md_args [6] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9418 /* Type */
9419 md_args [7] = type_md;
9420 /* static */
9421 md_args [8] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
9422 /* not extern */
9423 md_args [9] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
9424 /* Virtuality */
9425 md_args [10] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9426 /* Index into a virtual function */
9427 md_args [11] = NULL;
9428 md_args [12] = NULL;
9429 /* Flags */
9430 md_args [13] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
9431 /* isOptimized */
9432 md_args [14] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
9433 /* Pointer to LLVM function */
9434 md_args [15] = method;
9435 /* Function template parameter */
9436 md_args [16] = NULL;
9437 /* Function declaration descriptor */
9438 md_args [17] = NULL;
9439 /* List of function variables */
9440 md_args [18] = LLVMMDNode (args, 0);
9441 /* Line number */
9442 md_args [19] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9443 md = LLVMMDNode (md_args, 20);
9445 if (!module->subprogram_mds)
9446 module->subprogram_mds = g_ptr_array_new ();
9447 g_ptr_array_add (module->subprogram_mds, md);
9449 g_free (dir);
9450 g_free (filename);
9451 g_free (source_file);
9452 g_free (sym_seq_points);
9454 return md;
9457 static void
9458 emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil_code)
9460 MonoCompile *cfg = ctx->cfg;
9462 if (ctx->minfo && cil_code && cil_code >= cfg->header->code && cil_code < cfg->header->code + cfg->header->code_size) {
9463 MonoDebugSourceLocation *loc;
9464 LLVMValueRef loc_md;
9466 loc = mono_debug_method_lookup_location (ctx->minfo, cil_code - cfg->header->code);
9468 if (loc) {
9469 #if LLVM_API_VERSION > 100
9470 loc_md = (LLVMValueRef)mono_llvm_di_create_location (ctx->module->di_builder, ctx->dbg_md, loc->row, loc->column);
9471 mono_llvm_di_set_location (builder, loc_md);
9472 #else
9473 LLVMValueRef md_args [16];
9474 int nmd_args;
9476 nmd_args = 0;
9477 md_args [nmd_args ++] = LLVMConstInt (LLVMInt32Type (), loc->row, FALSE);
9478 md_args [nmd_args ++] = LLVMConstInt (LLVMInt32Type (), loc->column, FALSE);
9479 md_args [nmd_args ++] = ctx->dbg_md;
9480 md_args [nmd_args ++] = NULL;
9481 loc_md = LLVMMDNode (md_args, nmd_args);
9482 LLVMSetCurrentDebugLocation (builder, loc_md);
9483 #endif
9484 mono_debug_free_source_location (loc);
9489 static void
9490 emit_default_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder)
9492 #if LLVM_API_VERSION > 100
9493 if (ctx->minfo) {
9494 LLVMValueRef loc_md;
9495 loc_md = (LLVMValueRef)mono_llvm_di_create_location (ctx->module->di_builder, ctx->dbg_md, 0, 0);
9496 mono_llvm_di_set_location (builder, loc_md);
9498 #else
9499 /* Older llvm versions don't require this */
9500 #endif
9503 void
9504 default_mono_llvm_unhandled_exception (void)
9506 MonoJitTlsData *jit_tls = mono_get_jit_tls ();
9507 MonoObject *target = mono_gchandle_get_target_internal (jit_tls->thrown_exc);
9509 mono_unhandled_exception_internal (target);
9510 mono_invoke_unhandled_exception_hook (target);
9511 g_assert_not_reached ();
9515 DESIGN:
9516 - Emit LLVM IR from the mono IR using the LLVM C API.
9517 - The original arch specific code remains, so we can fall back to it if we run
9518 into something we can't handle.
9522 A partial list of issues:
9523 - Handling of opcodes which can throw exceptions.
9525 In the mono JIT, these are implemented using code like this:
9526 method:
9527 <compare>
9528 throw_pos:
9529 b<cond> ex_label
9530 <rest of code>
9531 ex_label:
9532 push throw_pos - method
9533 call <exception trampoline>
9535 The problematic part is push throw_pos - method, which cannot be represented
9536 in the LLVM IR, since it does not support label values.
9537 -> this can be implemented in AOT mode using inline asm + labels, but cannot
9538 be implemented in JIT mode ?
9539 -> a possible but slower implementation would use the normal exception
9540 throwing code but it would need to control the placement of the throw code
9541 (it needs to be exactly after the compare+branch).
9542 -> perhaps add a PC offset intrinsics ?
9544 - efficient implementation of .ovf opcodes.
9546 These are currently implemented as:
9547 <ins which sets the condition codes>
9548 b<cond> ex_label
9550 Some overflow opcodes are now supported by LLVM SVN.
9552 - exception handling, unwinding.
9553 - SSA is disabled for methods with exception handlers
9554 - How to obtain unwind info for LLVM compiled methods ?
9555 -> this is now solved by converting the unwind info generated by LLVM
9556 into our format.
9557 - LLVM uses the c++ exception handling framework, while we use our home grown
9558 code, and couldn't use the c++ one:
9559 - its not supported under VC++, other exotic platforms.
9560 - it might be impossible to support filter clauses with it.
9562 - trampolines.
9564 The trampolines need a predictable call sequence, since they need to disasm
9565 the calling code to obtain register numbers / offsets.
9567 LLVM currently generates this code in non-JIT mode:
9568 mov -0x98(%rax),%eax
9569 callq *%rax
9570 Here, the vtable pointer is lost.
9571 -> solution: use one vtable trampoline per class.
9573 - passing/receiving the IMT pointer/RGCTX.
9574 -> solution: pass them as normal arguments ?
9576 - argument passing.
9578 LLVM does not allow the specification of argument registers etc. This means
9579 that all calls are made according to the platform ABI.
9581 - passing/receiving vtypes.
9583 Vtypes passed/received in registers are handled by the front end by using
9584 a signature with scalar arguments, and loading the parts of the vtype into those
9585 arguments.
9587 Vtypes passed on the stack are handled using the 'byval' attribute.
9589 - ldaddr.
9591 Supported though alloca, we need to emit the load/store code.
9593 - types.
9595 The mono JIT uses pointer sized iregs/double fregs, while LLVM uses precisely
9596 typed registers, so we have to keep track of the precise LLVM type of each vreg.
9597 This is made easier because the IR is already in SSA form.
9598 An additional problem is that our IR is not consistent with types, i.e. i32/i64
9599 types are frequently used incorrectly.
9603 AOT SUPPORT:
9604 Emit LLVM bytecode into a .bc file, compile it using llc into a .s file, then link
9605 it with the file containing the methods emitted by the JIT and the AOT data
9606 structures.
9609 /* FIXME: Normalize some aspects of the mono IR to allow easier translation, like:
9610 * - each bblock should end with a branch
9611 * - setting the return value, making cfg->ret non-volatile
9612 * - avoid some transformations in the JIT which make it harder for us to generate
9613 * code.
9614 * - use pointer types to help optimizations.
9617 #else /* DISABLE_JIT */
9619 void
9620 mono_llvm_cleanup (void)
9624 void
9625 mono_llvm_free_domain_info (MonoDomain *domain)
9629 void
9630 mono_llvm_init (void)
9634 void
9635 default_mono_llvm_unhandled_exception (void)
9639 #endif /* DISABLE_JIT */