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.
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
26 #ifndef __STDC_CONSTANT_MACROS
27 #define __STDC_CONSTANT_MACROS
30 #include "llvm-c/BitWriter.h"
31 #include "llvm-c/Analysis.h"
33 #include "mini-llvm-cpp.h"
35 #include "aot-compiler.h"
36 #include "mini-llvm.h"
37 #include "mini-runtime.h"
38 #include <mono/utils/mono-math.h>
42 #if defined(__MINGW32__) || defined(_MSC_VER)
45 extern void *memset(void *, int, size_t);
46 void bzero (void *to
, size_t count
) { memset (to
, 0, count
); }
50 #if LLVM_API_VERSION < 4
51 #error "The version of the mono llvm repository is too old."
55 * Information associated by mono with LLVM modules.
58 LLVMModuleRef lmodule
;
59 LLVMValueRef throw_icall
, rethrow
, match_exc
, throw_corlib_exception
, resume_eh
;
60 GHashTable
*llvm_types
;
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
;
73 GPtrArray
*subprogram_mds
;
75 LLVMExecutionEngineRef ee
;
76 gboolean external_symbols
;
79 LLVMValueRef personality
;
82 MonoAssembly
*assembly
;
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
;
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
;
106 * Information associated by the backend with mono basic blocks.
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
;
128 * Structure containing emit state
131 MonoMemPool
*mempool
;
133 /* Maps method names to the corresponding LLVMValueRef */
134 GHashTable
*emitted_method_decls
;
137 LLVMValueRef lmethod
;
138 MonoLLVMModule
*module
;
139 LLVMModuleRef lmodule
;
141 int sindex
, default_index
, ex_index
;
142 LLVMBuilderRef builder
;
143 LLVMValueRef
*values
, *addresses
;
144 MonoType
**vreg_cli_types
;
146 MonoMethodSignature
*sig
;
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
;
156 LLVMTypeRef method_type
;
157 LLVMBasicBlockRef init_bb
, inited_bb
;
159 gboolean
*unreachable
;
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
;
168 MonoDebugMethodInfo
*minfo
;
169 /* For every clause, the clauses it is nested in */
172 GHashTable
*exc_meta
;
173 GHashTable
*method_to_callers
;
174 GPtrArray
*phi_values
;
175 GPtrArray
*bblock_list
;
177 GHashTable
*jit_callees
;
178 LLVMValueRef long_bb_break_var
;
184 MonoBasicBlock
*in_bb
;
189 * Instruction metadata
190 * This is the same as ins_info, but LREG != IREG.
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,
206 /* keep in sync with the enum in mini.h */
208 mini_llvm_ins_info
[] = {
209 #include "mini-ops.h"
214 #if TARGET_SIZEOF_VOID_P == 4
215 #define GET_LONG_IMM(ins) ((ins)->inst_l)
217 #define GET_LONG_IMM(ins) ((ins)->inst_imm)
220 #define LLVM_INS_INFO(opcode) (&mini_llvm_ins_info [((opcode) - OP_START - 1) * 4])
223 #define TRACE_FAILURE(msg) do { printf ("%s\n", msg); } while (0)
225 #define TRACE_FAILURE(msg)
229 #define IS_TARGET_X86 1
231 #define IS_TARGET_X86 0
235 #define IS_TARGET_AMD64 1
237 #define IS_TARGET_AMD64 0
240 #define ctx_ok(ctx) (!(ctx)->cfg->disable_llvm)
242 static LLVMIntPredicate cond_to_llvm_cond
[] = {
255 static LLVMRealPredicate fpcond_to_llvm_cond
[] = {
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
);
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
;
296 * The LLVM type with width == sizeof (gpointer)
301 return sizeof (gpointer
) == 8 ? LLVMInt64Type () : LLVMInt32Type ();
307 return sizeof (gpointer
) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
313 return sizeof (gpointer
) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
319 * Return the size of the LLVM representation of the vtype T.
322 get_vtype_size (MonoType
*t
)
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)
336 * simd_class_to_llvm_type:
338 * Return the LLVM type corresponding to the Mono.SIMD class KLASS
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
) {
376 return LLVMVectorType (LLVMInt8Type (), 16);
379 return LLVMVectorType (LLVMInt16Type (), 8);
382 return LLVMVectorType (LLVMInt32Type (), 4);
385 return LLVMVectorType (LLVMInt64Type (), 2);
387 return LLVMVectorType (LLVMFloatType (), 4);
389 return LLVMVectorType (LLVMDoubleType (), 2);
391 g_assert_not_reached ();
395 printf ("%s\n", klass_name
);
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
)
407 return LLVMVectorType (LLVMInt8Type (), 16);
409 return LLVMVectorType (LLVMInt16Type (), 8);
411 return LLVMVectorType (LLVMInt32Type (), 4);
413 return LLVMVectorType (LLVMInt64Type (), 2);
415 return LLVMVectorType (LLVMDoubleType (), 2);
417 return LLVMVectorType (LLVMFloatType (), 4);
419 g_assert_not_reached ();
425 create_llvm_type_for_type (MonoLLVMModule
*module
, MonoClass
*klass
)
427 int i
, size
, nfields
, esize
;
428 LLVMTypeRef
*eltypes
;
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
440 /* SIMD types have size 16 in mono_class_value_size () */
441 if (m_class_is_simd_type (klass
))
444 eltypes
= g_new (LLVMTypeRef
, size
);
445 for (i
= 0; i
< size
; ++i
)
446 eltypes
[i
] = esize
== 4 ? LLVMFloatType () : LLVMDoubleType ();
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
);
467 * Return the LLVM type corresponding to T.
470 type_to_llvm_type (EmitContext
*ctx
, MonoType
*t
)
475 t
= mini_get_underlying_type (t
);
479 return LLVMVoidType ();
481 return LLVMInt8Type ();
483 return LLVMInt16Type ();
485 return LLVMInt32Type ();
487 return LLVMInt8Type ();
489 return LLVMInt16Type ();
491 return LLVMInt32Type ();
494 return LLVMInt64Type ();
496 return LLVMFloatType ();
498 return LLVMDoubleType ();
501 return IntPtrType ();
502 case MONO_TYPE_OBJECT
:
504 return ObjRefType ();
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 ();
513 case MONO_TYPE_VALUETYPE
:
514 case MONO_TYPE_TYPEDBYREF
: {
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
);
528 ltype
= create_llvm_type_for_type (ctx
->module
, klass
);
529 g_hash_table_insert (ctx
->module
->llvm_types
, klass
, ltype
);
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
;
545 * Return whenever T is an unsigned int type.
548 type_is_unsigned (EmitContext
*ctx
, MonoType
*t
)
550 t
= mini_get_underlying_type (t
);
566 * type_to_llvm_arg_type:
568 * Same as type_to_llvm_type, but treat i8/i16 as i32.
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
)
579 * This works on all abis except arm64/ios which passes multiple
580 * arguments in one stack slot.
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 ();
596 * llvm_type_to_stack_type:
598 * Return the LLVM type which needs to be used when a value of type TYPE is pushed
601 static G_GNUC_UNUSED LLVMTypeRef
602 llvm_type_to_stack_type (MonoCompile
*cfg
, LLVMTypeRef type
)
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 ();
617 * regtype_to_llvm_type:
619 * Return the LLVM type corresponding to the regtype C used in instruction
623 regtype_to_llvm_type (char c
)
627 return LLVMInt32Type ();
629 return LLVMInt64Type ();
631 return LLVMDoubleType ();
640 * Return the LLVM type corresponding to the unary/binary opcode OPCODE.
643 op_to_llvm_type (int opcode
)
648 return LLVMInt8Type ();
651 return LLVMInt8Type ();
654 return LLVMInt16Type ();
657 return LLVMInt16Type ();
660 return LLVMInt32Type ();
663 return LLVMInt32Type ();
665 return LLVMInt64Type ();
667 return LLVMFloatType ();
669 return LLVMDoubleType ();
671 return LLVMInt64Type ();
673 return LLVMInt32Type ();
675 return LLVMInt64Type ();
680 return LLVMInt8Type ();
685 return LLVMInt16Type ();
687 return LLVMInt32Type ();
690 return sizeof (gpointer
) == 8 ? LLVMInt64Type () : LLVMInt32Type ();
697 return LLVMInt32Type ();
704 return LLVMInt64Type ();
706 printf ("%s\n", mono_inst_name (opcode
));
707 g_assert_not_reached ();
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
722 load_store_to_llvm_type (int opcode
, int *size
, gboolean
*sext
, gboolean
*zext
)
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
:
735 return LLVMInt8Type ();
736 case OP_LOADU1_MEMBASE
:
738 case OP_ATOMIC_LOAD_U1
:
739 case OP_ATOMIC_STORE_U1
:
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
:
750 return LLVMInt16Type ();
751 case OP_LOADU2_MEMBASE
:
753 case OP_ATOMIC_LOAD_U2
:
754 case OP_ATOMIC_STORE_U2
:
757 return LLVMInt16Type ();
758 case OP_LOADI4_MEMBASE
:
759 case OP_LOADU4_MEMBASE
:
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
:
769 return LLVMInt32Type ();
770 case OP_LOADI8_MEMBASE
:
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
:
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
:
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
:
791 return LLVMDoubleType ();
792 case OP_LOAD_MEMBASE
:
794 case OP_STORE_MEMBASE_REG
:
795 case OP_STORE_MEMBASE_IMM
:
796 *size
= sizeof (gpointer
);
797 return IntPtrType ();
799 g_assert_not_reached ();
807 * Return the LLVM intrinsics corresponding to the overflow opcode OPCODE.
810 ovf_op_to_intrins (int opcode
)
814 return "llvm.sadd.with.overflow.i32";
816 return "llvm.uadd.with.overflow.i32";
818 return "llvm.ssub.with.overflow.i32";
820 return "llvm.usub.with.overflow.i32";
822 return "llvm.smul.with.overflow.i32";
824 return "llvm.umul.with.overflow.i32";
826 return "llvm.sadd.with.overflow.i64";
828 return "llvm.uadd.with.overflow.i64";
830 return "llvm.ssub.with.overflow.i64";
832 return "llvm.usub.with.overflow.i64";
834 return "llvm.smul.with.overflow.i64";
836 return "llvm.umul.with.overflow.i64";
838 g_assert_not_reached ();
844 simd_op_to_intrins (int opcode
)
847 #if defined(TARGET_X86) || defined(TARGET_AMD64)
849 return "llvm.x86.sse2.min.pd";
851 return "llvm.x86.sse.min.ps";
853 return "llvm.x86.sse2.max.pd";
855 return "llvm.x86.sse.max.ps";
857 return "llvm.x86.sse3.hadd.pd";
859 return "llvm.x86.sse3.hadd.ps";
861 return "llvm.x86.sse3.hsub.pd";
863 return "llvm.x86.sse3.hsub.ps";
865 return "llvm.x86.sse3.addsub.ps";
867 return "llvm.x86.sse3.addsub.pd";
868 case OP_EXTRACT_MASK
:
869 return "llvm.x86.sse2.pmovmskb.128";
872 return "llvm.x86.sse2.psrli.w";
875 return "llvm.x86.sse2.psrli.d";
878 return "llvm.x86.sse2.psrli.q";
881 return "llvm.x86.sse2.pslli.w";
884 return "llvm.x86.sse2.pslli.d";
887 return "llvm.x86.sse2.pslli.q";
890 return "llvm.x86.sse2.psrai.w";
893 return "llvm.x86.sse2.psrai.d";
895 return "llvm.x86.sse2.padds.b";
897 return "llvm.x86.sse2.padds.w";
899 return "llvm.x86.sse2.psubs.b";
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";
911 return "llvm.x86.sse2.pavg.b";
913 return "llvm.x86.sse2.pavg.w";
915 return "llvm.x86.sse.sqrt.ps";
917 return "llvm.x86.sse2.sqrt.pd";
919 return "llvm.x86.sse.rsqrt.ps";
921 return "llvm.x86.sse.rcp.ps";
923 return "llvm.x86.sse2.cvtdq2pd";
925 return "llvm.x86.sse2.cvtdq2ps";
927 return "llvm.x86.sse2.cvtpd2dq";
929 return "llvm.x86.sse2.cvtps2dq";
931 return "llvm.x86.sse2.cvtpd2ps";
933 return "llvm.x86.sse2.cvtps2pd";
935 return "llvm.x86.sse2.cvttpd2dq";
937 return "llvm.x86.sse2.cvttps2dq";
939 return "llvm.x86.sse2.packsswb.128";
941 return "llvm.x86.sse2.packssdw.128";
943 return "llvm.x86.sse2.packuswb.128";
945 return "llvm.x86.sse41.packusdw";
947 return "llvm.x86.sse2.pmulh.w";
948 case OP_PMULW_HIGH_UN
:
949 return "llvm.x86.sse2.pmulhu.w";
951 return "llvm.x86.sse41.dpps";
954 g_assert_not_reached ();
960 simd_op_to_llvm_type (int opcode
)
962 #if defined(TARGET_X86) || defined(TARGET_AMD64)
966 return type_to_simd_type (MONO_TYPE_R8
);
969 return type_to_simd_type (MONO_TYPE_I8
);
972 return type_to_simd_type (MONO_TYPE_I4
);
977 return type_to_simd_type (MONO_TYPE_I2
);
981 return type_to_simd_type (MONO_TYPE_I1
);
983 return type_to_simd_type (MONO_TYPE_R4
);
986 return type_to_simd_type (MONO_TYPE_I4
);
990 return type_to_simd_type (MONO_TYPE_R8
);
994 return type_to_simd_type (MONO_TYPE_R4
);
995 case OP_EXTRACT_MASK
:
996 return type_to_simd_type (MONO_TYPE_I1
);
1002 return type_to_simd_type (MONO_TYPE_R4
);
1005 return type_to_simd_type (MONO_TYPE_R8
);
1007 g_assert_not_reached ();
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
);
1028 set_call_preserveall_cc (LLVMValueRef func
)
1030 #ifndef TARGET_WATCHOS
1031 mono_llvm_set_call_preserveall_cc (func
);
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];
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
]) {
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
];
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
;
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
)
1087 return ctx
->bblocks
[bb
->block_num
].end_bblock
;
1090 static LLVMBasicBlockRef
1091 gen_bb (EmitContext
*ctx
, const char *prefix
)
1095 sprintf (bb_name
, "%s%d", prefix
, ++ ctx
->ex_index
);
1096 return LLVMAppendBasicBlock (ctx
->lmethod
, bb_name
);
1102 * Return the target of the patch identified by TYPE and TARGET.
1105 resolve_patch (MonoCompile
*cfg
, MonoJumpInfoType type
, gconstpointer target
)
1111 memset (&ji
, 0, sizeof (ji
));
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
);
1124 * Emit code to convert the LLVM value V to DTYPE.
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
;
1135 if (dtype
== LLVMInt64Type () && (stype
== LLVMInt32Type () || stype
== LLVMInt16Type () || stype
== LLVMInt8Type ()))
1137 else if (dtype
== LLVMInt32Type () && (stype
== LLVMInt16Type () || stype
== LLVMInt8Type ()))
1139 else if (dtype
== LLVMInt16Type () && (stype
== LLVMInt8Type ()))
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
, "");
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
, "");
1176 LLVMDumpValue (LLVMConstNull (dtype
));
1177 g_assert_not_reached ();
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.
1196 emit_volatile_load (EmitContext
*ctx
, int vreg
)
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
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 (), "");
1224 * emit_volatile_store:
1226 * If VREG is volatile, emit a store from its value to its address.
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
]);
1240 sig_to_llvm_sig_no_cinfo (EmitContext
*ctx
, MonoMethodSignature
*sig
)
1242 LLVMTypeRef ret_type
;
1243 LLVMTypeRef
*param_types
= NULL
;
1248 ret_type
= type_to_llvm_type (ctx
, sig
->ret
);
1251 rtype
= mini_get_underlying_type (sig
->ret
);
1253 param_types
= g_new0 (LLVMTypeRef
, (sig
->param_count
* 8) + 3);
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
);
1266 res
= LLVMFunctionType (ret_type
, param_types
, pindex
, FALSE
);
1267 g_free (param_types
);
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.
1279 sig_to_llvm_sig_full (EmitContext
*ctx
, MonoMethodSignature
*sig
, LLVMCallInfo
*cinfo
)
1281 LLVMTypeRef ret_type
;
1282 LLVMTypeRef
*param_types
= NULL
;
1284 int i
, j
, pindex
, vret_arg_pindex
= 0;
1285 gboolean vretaddr
= FALSE
;
1289 return sig_to_llvm_sig_no_cinfo (ctx
, sig
);
1291 ret_type
= type_to_llvm_type (ctx
, sig
->ret
);
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
) {
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
);
1314 g_assert_not_reached ();
1317 case LLVMArgVtypeByVal
:
1318 /* Vtype returned normally by val */
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);
1327 g_assert (cinfo
->ret
.nslots
== 1 || cinfo
->ret
.nslots
== 2);
1328 ret_type
= LLVMIntType (cinfo
->ret
.nslots
* sizeof (mgreg_t
) * 8);
1332 case LLVMArgAsIArgs
:
1333 ret_type
= LLVMArrayType (IntPtrType (), cinfo
->ret
.nslots
);
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
);
1345 case LLVMArgVtypeByRef
:
1346 /* Vtype returned using a hidden argument */
1347 ret_type
= LLVMVoidType ();
1349 case LLVMArgVtypeRetAddr
:
1350 case LLVMArgGsharedvtFixed
:
1351 case LLVMArgGsharedvtFixedVtype
:
1352 case LLVMArgGsharedvtVariable
:
1354 ret_type
= LLVMVoidType ();
1360 param_types
= g_new0 (LLVMTypeRef
, (sig
->param_count
* 8) + 3);
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
);
1374 param_types
[pindex
] = LLVMPointerType (param_types
[pindex
], 0);
1377 if (!ctx
->llvm_only
&& cinfo
->rgctx_arg
) {
1378 cinfo
->rgctx_arg_pindex
= pindex
;
1379 param_types
[pindex
] = ctx
->module
->ptr_type
;
1382 if (cinfo
->imt_arg
) {
1383 cinfo
->imt_arg_pindex
= pindex
;
1384 param_types
[pindex
] = ctx
->module
->ptr_type
;
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
)
1405 cinfo
->vret_arg_pindex
= vret_arg_pindex
;
1408 if (vretaddr
&& vret_arg_pindex
== pindex
)
1409 param_types
[pindex
++] = IntPtrType ();
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
]) {
1429 param_types
[pindex
++] = LLVMIntType (sizeof (gpointer
) * 8);
1434 g_assert_not_reached ();
1438 case LLVMArgVtypeByVal
:
1439 param_types
[pindex
] = type_to_llvm_arg_type (ctx
, ainfo
->type
);
1442 param_types
[pindex
] = LLVMPointerType (param_types
[pindex
], 0);
1445 case LLVMArgAsIArgs
:
1446 if (ainfo
->esize
== 8)
1447 param_types
[pindex
] = LLVMArrayType (LLVMInt64Type (), ainfo
->nslots
);
1449 param_types
[pindex
] = LLVMArrayType (IntPtrType (), ainfo
->nslots
);
1452 case LLVMArgVtypeByRef
:
1453 param_types
[pindex
] = type_to_llvm_arg_type (ctx
, ainfo
->type
);
1456 param_types
[pindex
] = LLVMPointerType (param_types
[pindex
], 0);
1459 case LLVMArgAsFpArgs
: {
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 ();
1469 case LLVMArgVtypeAsScalar
:
1470 g_assert_not_reached ();
1472 case LLVMArgGsharedvtFixed
:
1473 case LLVMArgGsharedvtFixedVtype
:
1474 param_types
[pindex
++] = LLVMPointerType (type_to_llvm_arg_type (ctx
, ainfo
->type
), 0);
1476 case LLVMArgGsharedvtVariable
:
1477 param_types
[pindex
++] = LLVMPointerType (IntPtrType (), 0);
1480 param_types
[pindex
++] = type_to_llvm_arg_type (ctx
, ainfo
->type
);
1484 if (!ctx_ok (ctx
)) {
1485 g_free (param_types
);
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
;
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
;
1502 res
= LLVMFunctionType (ret_type
, param_types
, pindex
, FALSE
);
1503 g_free (param_types
);
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
,
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
,
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
,
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
,
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
,
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
);
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
);
1621 get_aotconst_name (MonoJumpInfoType type
, gconstpointer data
, int got_offset
)
1626 case MONO_PATCH_INFO_INTERNAL_METHOD
:
1627 name
= g_strdup_printf ("jit_icall_%s", data
);
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
));
1635 name
= g_strdup_printf ("%s_%d", mono_ji_type_to_string (type
), got_offset
);
1643 get_aotconst_typed (EmitContext
*ctx
, MonoJumpInfoType type
, gconstpointer data
, LLVMTypeRef llvm_type
)
1647 LLVMValueRef indexes
[2];
1648 LLVMValueRef got_entry_addr
, load
;
1649 LLVMBuilderRef builder
= ctx
->builder
;
1654 MonoJumpInfo tmp_ji
;
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);
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
);
1681 load
= LLVMBuildLoad (builder
, got_entry_addr
, "");
1682 load
= convert (ctx
, load
, llvm_type
);
1683 LLVMSetValueName (load
, name
? name
: "");
1685 load
= LLVMBuildLoad (builder
, got_entry_addr
, name
? name
: "");
1688 //set_invariant_load_flag (load);
1694 get_aotconst (EmitContext
*ctx
, MonoJumpInfoType type
, gconstpointer data
)
1696 return get_aotconst_typed (ctx
, type
, data
, NULL
);
1700 get_callee (EmitContext
*ctx
, LLVMTypeRef llvm_sig
, MonoJumpInfoType type
, gconstpointer data
)
1702 LLVMValueRef callee
;
1704 if (ctx
->llvm_only
) {
1705 callee_name
= mono_aot_get_direct_call_symbol (type
, data
);
1707 /* Directly callable */
1709 callee
= (LLVMValueRef
)g_hash_table_lookup (ctx
->module
->direct_callables
, callee_name
);
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
);
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
);
1727 * Calls are made through the GOT.
1729 return get_aotconst_typed (ctx
, type
, data
, LLVMPointerType (llvm_sig
, 0));
1731 MonoJumpInfo
*ji
= NULL
;
1733 callee_name
= mono_aot_get_plt_symbol (type
, data
);
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
);
1742 callee
= (LLVMValueRef
)g_hash_table_lookup (ctx
->module
->plt_entries
, callee_name
);
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);
1754 ji
->data
.target
= data
;
1756 g_hash_table_insert (ctx
->module
->plt_entries_ji
, ji
, callee
);
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
, "");
1773 LLVMValueRef callee
= LLVMAddFunction (ctx
->lmodule
, "", llvm_sig
);
1774 LLVMAddGlobalMapping (ctx
->module
->ee
, callee
, target
);
1780 get_handler_clause (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
1782 MonoMethodHeader
*header
= cfg
->header
;
1783 MonoExceptionClause
*clause
;
1787 if (bb
->region
!= -1 && MONO_BBLOCK_IS_IN_REGION (bb
, MONO_REGION_TRY
))
1788 return (bb
->region
>> 8) - 1;
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
)
1801 static MonoExceptionClause
*
1802 get_most_deep_clause (MonoCompile
*cfg
, EmitContext
*ctx
, MonoBasicBlock
*bb
)
1804 if (bb
== cfg
->bb_init
)
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
))
1819 set_metadata_flag (LLVMValueRef v
, const char *flag_name
)
1821 LLVMValueRef md_arg
;
1824 md_kind
= LLVMGetMDKindID (flag_name
, strlen (flag_name
));
1825 md_arg
= LLVMMDString ("mono", 4);
1826 LLVMSetMetadata (v
, md_kind
, LLVMMDNode (&md_arg
, 1));
1830 set_invariant_load_flag (LLVMValueRef v
)
1832 LLVMValueRef md_arg
;
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));
1846 * Emit an LLVM call or invoke instruction depending on whenever the call is inside
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
);
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
1875 LLVMBasicBlockRef noex_bb
= gen_bb (ctx
, "CALL_NOEX_BB");
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
;
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
];
1905 ctx
->bblocks
[tblock
->block_num
].invoke_target
= TRUE
;
1907 ex_bb
= get_bb (ctx
, tblock
);
1909 noex_bb
= gen_bb (ctx
, "NOEX_BB");
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
;
1922 lcall
= LLVMBuildCall (builder
, callee
, args
, pindex
, "");
1923 ctx
->builder
= builder
;
1927 *builder_ref
= ctx
->builder
;
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 */
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
;
1952 if (is_faulting
&& bb
->region
!= -1 && !ctx
->cfg
->llvm_only
&& use_intrinsics
) {
1953 LLVMAtomicOrdering ordering
;
1956 case LLVM_BARRIER_NONE
:
1957 ordering
= LLVMAtomicOrderingNotAtomic
;
1959 case LLVM_BARRIER_ACQ
:
1960 ordering
= LLVMAtomicOrderingAcquire
;
1962 case LLVM_BARRIER_SEQ
:
1963 ordering
= LLVMAtomicOrderingSequentiallyConsistent
;
1966 g_assert_not_reached ();
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.
1978 intrins_name
= "llvm.mono.load.i8.p0i8";
1981 intrins_name
= "llvm.mono.load.i16.p0i16";
1984 intrins_name
= "llvm.mono.load.i32.p0i32";
1987 intrins_name
= "llvm.mono.load.i64.p0i64";
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), "");
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 (), "");
2013 * We emit volatile loads for loads which can fault, because otherwise
2014 * LLVM will generate invalid code when encountering a load from a
2017 if (barrier
!= LLVM_BARRIER_NONE
)
2018 res
= mono_llvm_build_atomic_load (*builder_ref
, addr
, name
, is_faulting
, size
, barrier
);
2020 res
= mono_llvm_build_load (*builder_ref
, addr
, name
, is_faulting
);
2022 /* Mark it with a custom metadata */
2025 set_metadata_flag (res, "mono.faulting.load");
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
);
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
;
2055 if (is_faulting
&& bb
->region
!= -1 && !ctx
->cfg
->llvm_only
&& use_intrinsics
) {
2056 LLVMAtomicOrdering ordering
;
2059 case LLVM_BARRIER_NONE
:
2060 ordering
= LLVMAtomicOrderingNotAtomic
;
2062 case LLVM_BARRIER_REL
:
2063 ordering
= LLVMAtomicOrderingRelease
;
2065 case LLVM_BARRIER_SEQ
:
2066 ordering
= LLVMAtomicOrderingSequentiallyConsistent
;
2069 g_assert_not_reached ();
2075 intrins_name
= "llvm.mono.store.i8.p0i8";
2078 intrins_name
= "llvm.mono.store.i16.p0i16";
2081 intrins_name
= "llvm.mono.store.i32.p0i32";
2084 intrins_name
= "llvm.mono.store.i64.p0i64";
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), "");
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);
2102 if (barrier
!= LLVM_BARRIER_NONE
)
2103 mono_llvm_build_aligned_store (*builder_ref
, value
, addr
, barrier
, size
);
2105 mono_llvm_build_store (*builder_ref
, value
, addr
, is_faulting
, barrier
);
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.
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 */
2135 ex_bb
= gen_bb (ctx
, "EX_BB");
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
;
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
;
2173 callee
= ctx
->module
->throw_corlib_exception
;
2176 const char *icall_name
;
2179 sig
= LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE
);
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
);
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
);
2204 ctx
->builder
= builder
= create_builder (ctx
);
2205 LLVMPositionBuilderAtEnd (ctx
->builder
, ex2_bb
);
2207 mono_memory_barrier ();
2208 ctx
->module
->throw_corlib_exception
= callee
;
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.
2220 emit_call (ctx
, bb
, &builder
, callee
, args
, 1);
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
;
2238 * emit_args_to_vtype:
2240 * Emit code to store the vtype in the arguments args to the address ADDRESS.
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
;
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)
2266 if (ainfo
->pair_storage
[j
] == LLVMArgNone
)
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, "");
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), ""));
2283 case LLVMArgInFPReg
: {
2284 LLVMTypeRef arg_type
;
2286 if (ainfo
->esize
== 8)
2287 arg_type
= LLVMDoubleType ();
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
);
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.
2314 emit_vtype_to_args (EmitContext
*ctx
, LLVMBuilderRef builder
, MonoType
*t
, LLVMValueRef address
, LLVMArgInfo
*ainfo
, LLVMValueRef
*args
, guint32
*nargs
)
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
;
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
)
2336 switch (ainfo
->pair_storage
[j
]) {
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, "");
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 ());
2348 case LLVMArgInFPReg
:
2349 if (ainfo
->esize
== 8)
2350 arg_type
= LLVMDoubleType ();
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
, "");
2361 g_assert_not_reached ();
2363 size
-= sizeof (gpointer
);
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
;
2383 build_alloca_llvm_type (EmitContext
*ctx
, LLVMTypeRef t
, int align
)
2385 return build_alloca_llvm_type_name (ctx
, t
, align
, "");
2389 build_alloca (EmitContext
*ctx
, MonoType
*t
)
2391 MonoClass
*k
= mono_class_from_mono_type_internal (t
);
2394 g_assert (!mini_is_gsharedvt_variable_type (t
));
2396 if (MONO_CLASS_IS_SIMD (ctx
->cfg
, k
))
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)
2405 return build_alloca_llvm_type (ctx
, type_to_llvm_type (ctx
, t
), align
);
2409 emit_gsharedvt_ldaddr (EmitContext
*ctx
, int vreg
)
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
];
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.
2441 mark_as_used (MonoLLVMModule
*module
, LLVMValueRef global
)
2444 module
->used
= g_ptr_array_sized_new (16);
2445 g_ptr_array_add (module
->used
, global
);
2449 emit_llvm_used (MonoLLVMModule
*module
)
2451 LLVMModuleRef lmodule
= module
->lmodule
;
2452 LLVMTypeRef used_type
;
2453 LLVMValueRef used
, *used_elem
;
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");
2472 * Emit a function mapping method indexes to their code
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
;
2482 LLVMBuilderRef builder
= LLVMCreateBuilder ();
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
);
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
);
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
);
2524 LLVMPositionBuilderAtEnd (builder
, bb
);
2526 m
= (LLVMValueRef
)g_hash_table_lookup (module
->idx_to_lmethod
, GINT_TO_POINTER (i
));
2528 LLVMBuildRet (builder
, LLVMBuildBitCast (builder
, m
, rtype
, ""));
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
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
;
2564 LLVMBuilderRef builder
= LLVMCreateBuilder ();
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
));
2585 name
= g_strdup_printf ("BB_%d", i
);
2586 bb
= LLVMAppendBasicBlock (func
, name
);
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
));
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 */
2616 emit_llvm_code_start (MonoLLVMModule
*module
)
2618 LLVMModuleRef lmodule
= module
->lmodule
;
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
);
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
;
2647 func
= LLVMAddFunction (lmodule
, name
, LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE
));
2648 sig
= LLVMFunctionType2 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), FALSE
);
2653 func
= LLVMAddFunction (lmodule
, name
, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), IntPtrType (), FALSE
));
2654 sig
= LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), IntPtrType (), FALSE
);
2657 func
= LLVMAddFunction (lmodule
, name
, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), ObjRefType (), FALSE
));
2658 sig
= LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), ObjRefType (), FALSE
);
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
);
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);
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
);
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.
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);
2724 emit_llvm_code_end (MonoLLVMModule
*module
)
2726 LLVMModuleRef lmodule
= module
->lmodule
;
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
);
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
;
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
)
2754 switch (ins
->opcode
) {
2767 case OP_IDIV_UN_IMM
:
2768 case OP_LDIV_UN_IMM
:
2769 case OP_IREM_UN_IMM
:
2770 case OP_LREM_UN_IMM
: {
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
);
2779 builder
= ctx
->builder
;
2781 /* b == -1 && a == 0x80000000 */
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
);
2791 builder
= ctx
->builder
;
2803 * Emit code to initialize the GOT slots used by the method.
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
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, "");
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
);
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, "");
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
);
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
;
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);
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
);
2930 LLVMBuildRet (builder
, call
);
2932 g_hash_table_insert (ctx
->module
->idx_to_unbox_tramp
, GINT_TO_POINTER (method_index
), tramp
);
2933 LLVMDisposeBuilder (builder
);
2939 * Emit code to load/convert arguments.
2942 emit_entry_bb (EmitContext
*ctx
, LLVMBuilderRef builder
)
2945 MonoCompile
*cfg
= ctx
->cfg
;
2946 MonoMethodSignature
*sig
= ctx
->sig
;
2947 LLVMCallInfo
*linfo
= ctx
->linfo
;
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
];
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
);
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
;
2986 pindex
= ainfo
->pindex
;
2988 switch (ainfo
->storage
) {
2989 case LLVMArgVtypeInReg
:
2990 case LLVMArgAsFpArgs
: {
2991 LLVMValueRef args
[8];
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);
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
], "");
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
], "");
3026 case LLVMArgVtypeByRef
: {
3027 /* The argument is passed by ref */
3028 ctx
->addresses
[reg
] = LLVMGetParam (ctx
->lmethod
, pindex
);
3031 case LLVMArgAsIArgs
: {
3032 LLVMValueRef arg
= LLVMGetParam (ctx
->lmethod
, pindex
);
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
);
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
);
3046 LLVMBuildStore (ctx
->builder
, arg
, convert (ctx
, ctx
->addresses
[reg
], LLVMPointerType (LLVMTypeOf (arg
), 0)));
3050 case LLVMArgVtypeAsScalar
:
3051 g_assert_not_reached ();
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
);
3058 name
= g_strdup_printf ("arg_%s", names
[i
]);
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
);
3065 case LLVMArgGsharedvtFixedVtype
: {
3066 LLVMValueRef arg
= LLVMGetParam (ctx
->lmethod
, pindex
);
3069 name
= g_strdup_printf ("vtype_arg_%s", names
[i
]);
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
]);
3079 case LLVMArgGsharedvtVariable
:
3080 /* The IR treats these as variables with addresses */
3081 ctx
->addresses
[reg
] = LLVMGetParam (ctx
->lmethod
, pindex
);
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
));
3091 emit_volatile_store (ctx
, cfg
->vret_addr
->dreg
);
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
) {
3160 if (!(bb
->region
!= -1 && (bb
->flags
& BB_EXCEPTION_HANDLER
)))
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) {
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
;
3176 /* Create a variable to hold the exception 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
;
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
)
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 */
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 */
3217 /* Normal icalls can be virtual methods which need an extra arg */
3219 case MONO_WRAPPER_RUNTIME_INVOKE
:
3220 case MONO_WRAPPER_ALLOC
:
3221 case MONO_WRAPPER_CASTCLASS
:
3222 case MONO_WRAPPER_WRITE_BARRIER
:
3224 case MONO_WRAPPER_STELEMREF
:
3225 if (info
->subtype
!= WRAPPER_SUBTYPE_VIRTUAL_STELEMREF
)
3228 case MONO_WRAPPER_MANAGED_TO_MANAGED
:
3229 if (info
->subtype
== WRAPPER_SUBTYPE_STRING_CTOR
)
3235 if (method
->string_ctor
)
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")))
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
;
3254 LLVMCallInfo
*cinfo
;
3258 LLVMTypeRef llvm_sig
;
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");
3272 cinfo
= call
->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
);
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
);
3298 preserveall
= FALSE
;
3300 /* FIXME: Avoid creating duplicate methods */
3302 if (ins
->flags
& MONO_INST_HAS_METHOD
) {
3306 if (cfg
->compile_aot
) {
3307 callee
= get_callee (ctx
, llvm_sig
, MONO_PATCH_INFO_METHOD
, call
->method
);
3309 set_failure (ctx
, "can't encode patch");
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
);
3324 static int tramp_index
;
3327 name
= g_strdup_printf ("tramp_%d", 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
3337 LLVMValueRef tramp_var
= (LLVMValueRef
)g_hash_table_lookup (ctx
->jit_callees
, call
->method
);
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
);
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
, "");
3356 mono_create_jit_trampoline (mono_domain_get (),
3357 call
->method
, error
);
3358 if (!is_ok (error
)) {
3360 set_failure (ctx
, mono_error_get_message (error
));
3361 mono_error_cleanup (error
);
3365 callee
= LLVMAddFunction (ctx
->lmodule
, name
, llvm_sig
);
3368 LLVMAddGlobalMapping (ctx
->module
->ee
, callee
, target
);
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");
3380 MonoJitICallInfo
*info
= mono_find_jit_icall_by_addr (call
->fptr
);
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
);
3395 set_failure (ctx
, "can't encode patch");
3399 target
= (gpointer
)mono_icall_get_wrapper (info
);
3400 callee
= emit_jit_callee (ctx
, "", llvm_sig
, target
);
3403 if (cfg
->compile_aot
) {
3405 if (cfg
->abs_patches
) {
3406 MonoJumpInfo
*abs_ji
= (MonoJumpInfo
*)g_hash_table_lookup (cfg
->abs_patches
, call
->fptr
);
3408 callee
= get_callee (ctx
, llvm_sig
, abs_ji
->type
, abs_ji
->data
.target
);
3410 set_failure (ctx
, "can't encode patch");
3416 set_failure (ctx
, "aot");
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
);
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
);
3430 g_assert_not_reached ();
3433 g_assert_not_reached ();
3436 callee
= LLVMAddFunction (ctx
->lmodule
, "", llvm_sig
);
3438 if (cfg
->abs_patches
) {
3439 MonoJumpInfo
*abs_ji
= (MonoJumpInfo
*)g_hash_table_lookup (cfg
->abs_patches
, call
->fptr
);
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
);
3453 LLVMAddGlobalMapping (ctx
->module
->ee
, callee
, (gpointer
)call
->fptr
);
3460 int size
= sizeof (gpointer
);
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));
3468 callee
= convert (ctx
, values
[ins
->sreg1
], LLVMPointerType (llvm_sig
, 0));
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.
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
);
3497 args
[cinfo
->rgctx_arg_pindex
] = convert (ctx
, values
[call
->rgctx_arg_reg
], ctx
->module
->ptr_type
);
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
);
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
);
3510 args
[cinfo
->imt_arg_pindex
] = convert (ctx
, values
[call
->imt_arg_reg
], ctx
->module
->ptr_type
);
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 ());
3520 g_assert (addresses
[call
->inst
.dreg
]);
3521 args
[cinfo
->vret_arg_pindex
] = convert (ctx
, addresses
[call
->inst
.dreg
], IntPtrType ());
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
];
3533 args
[cinfo
->vret_arg_pindex
] = LLVMBuildPtrToInt (builder
, addresses
[call
->inst
.dreg
], IntPtrType (), "");
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
) {
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
: {
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
);
3571 // FIXME: Get rid of the VMOVE
3574 case LLVMArgVtypeByVal
:
3575 g_assert (addresses
[reg
]);
3576 args
[pindex
] = addresses
[reg
];
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));
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)), "");
3588 args
[pindex
] = LLVMBuildLoad (ctx
->builder
, convert (ctx
, addresses
[reg
], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo
->nslots
), 0)), "");
3590 case LLVMArgVtypeAsScalar
:
3591 g_assert_not_reached ();
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));
3598 case LLVMArgGsharedvtVariable
:
3599 g_assert (addresses
[reg
]);
3600 args
[pindex
] = convert (ctx
, addresses
[reg
], LLVMPointerType (IntPtrType (), 0));
3603 g_assert (args
[pindex
]);
3604 if (i
== 0 && sig
->hasthis
)
3605 args
[pindex
] = convert (ctx
, args
[pindex
], param_types
[pindex
]);
3607 args
[pindex
] = convert (ctx
, args
[pindex
], type_to_llvm_arg_type (ctx
, ainfo
->type
));
3610 g_assert (pindex
<= nargs
);
3614 if (call
->cinfo
->dummy_arg
)
3615 args
[call
->cinfo
->dummy_arg_pindex
] = LLVMConstNull (ctx
->module
->ptr_type
);
3617 // FIXME: Align call sites
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
);
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
);
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 ())
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
);
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
]);
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
));
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
));
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
), "");
3699 case LLVMArgGsharedvtVariable
:
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
), "");
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
));
3712 *builder_ref
= ctx
->builder
;
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 ()));
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
);
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 ();
3734 ctx
->module
->rethrow
= callee
;
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
);
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";
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
);
3770 * LLVM doesn't push the exception argument, so we need a different
3773 target
= resolve_patch (ctx
->cfg
, MONO_PATCH_INFO_INTERNAL_METHOD
, rethrow
? "llvm_rethrow_exception_trampoline" : "llvm_throw_exception_trampoline");
3775 target
= resolve_patch (ctx
->cfg
, MONO_PATCH_INFO_INTERNAL_METHOD
, icall_name
);
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
3783 ctx
->module
->rethrow
= callee
;
3785 ctx
->module
->throw_icall
= callee
;
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);
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
);
3801 if (ctx
->cfg
->compile_aot
) {
3802 callee
= get_callee (ctx
, fun_sig
, MONO_PATCH_INFO_INTERNAL_METHOD
, icall_name
);
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
);
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
;
3828 if (ctx
->cfg
->compile_aot
) {
3829 callee
= get_callee (ctx
, call_sig
, MONO_PATCH_INFO_INTERNAL_METHOD
, icall_name
);
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, "");
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
;
3850 if (ctx
->cfg
->compile_aot
) {
3851 callee
= get_callee (ctx
, call_sig
, MONO_PATCH_INFO_INTERNAL_METHOD
, icall_name
);
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
);
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)), "");
3882 args
[3] = LLVMConstInt (IntPtrType (), 0, 0);
3885 args
[4] = convert (ctx
, ctx
->this_arg
, IntPtrType ());
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
;
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
);
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
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";
3920 static const gboolean use_debug_personality
= FALSE
;
3921 static const char *default_personality_name
= "__gxx_personality_v0";
3925 default_cpp_lpad_exc_signature (void)
3927 static gboolean inited
= FALSE
;
3928 static LLVMTypeRef sig
;
3931 LLVMTypeRef signature
[2];
3932 signature
[0] = LLVMPointerType (LLVMInt8Type (), 0);
3933 signature
[1] = LLVMInt32Type ();
3934 sig
= LLVMStructType (signature
, 2, FALSE
);
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
);
3956 if (ctx
->cfg
->compile_aot
) {
3957 personality
= get_callee (ctx
, personality_type
, MONO_PATCH_INFO_INTERNAL_METHOD
, default_personality_name
);
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
);
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
);
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
);
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
;
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
);
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
;
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
);
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
;
4094 LLVMValueRef personality
;
4095 LLVMValueRef landing_pad
;
4096 LLVMBasicBlockRef target_bb
;
4098 static int ti_generator
;
4100 LLVMValueRef type_info
;
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
);
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
);
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
);
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
);
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
);
4151 #if LLVM_API_VERSION > 100
4152 type_info
= LLVMAddGlobal (lmodule
, LLVMInt32Type (), ti_name
);
4153 LLVMSetInitializer (type_info
, LLVMConstInt (LLVMInt32Type (), clause_index
, FALSE
));
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
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
);
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 */
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.
4239 get_double_const (MonoCompile
*cfg
, double val
)
4242 if (mono_isnan (val
))
4243 *(gint64
*)&val
= 0x7FF8000000000000ll
;
4245 return LLVMConstReal (LLVMDoubleType (), val
);
4249 get_float_const (MonoCompile
*cfg
, float val
)
4252 if (mono_isnan (val
))
4253 *(int *)&val
= 0x7FC00000;
4256 return LLVMConstReal (LLVMFloatType (), val
);
4258 return LLVMConstFPExt (LLVMConstReal (LLVMFloatType (), val
), LLVMDoubleType ());
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
;
4272 LLVMBasicBlockRef cbb
;
4273 LLVMBuilderRef builder
, starting_builder
;
4274 gboolean has_terminator
;
4276 LLVMValueRef lhs
, rhs
;
4279 cbb
= get_end_bb (ctx
, bb
);
4281 builder
= create_builder (ctx
);
4282 ctx
->builder
= builder
;
4283 LLVMPositionBuilderAtEnd (builder
, cbb
);
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");
4295 emit_llvmonly_handler_start (ctx
, bb
, cbb
);
4297 emit_handler_start (ctx
, bb
, builder
);
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
);
4308 char dname_buf
[128];
4310 emit_dbg_loc (ctx
, builder
, ins
->cil_code
);
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
;
4351 emit_dbg_loc (ctx
, builder
, ins
->cil_code
);
4355 /* There could be instructions after a terminator, skip them */
4358 if (spec
[MONO_INST_DEST
] != ' ' && !MONO_IS_STORE_MEMBASE (ins
)) {
4359 sprintf (dname_buf
, "t%d", ins
->dreg
);
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
);
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");
4374 lhs
= values
[ins
->sreg1
];
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
);
4385 if (!values
[ins
->sreg2
]) {
4386 set_failure (ctx
, "sreg2");
4389 rhs
= values
[ins
->sreg2
];
4395 //mono_print_ins (ins);
4396 switch (ins
->opcode
) {
4399 case OP_LIVERANGE_START
:
4400 case OP_LIVERANGE_END
:
4403 values
[ins
->dreg
] = LLVMConstInt (LLVMInt32Type (), ins
->inst_c0
, FALSE
);
4406 #if TARGET_SIZEOF_VOID_P == 4
4407 values
[ins
->dreg
] = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins
), FALSE
);
4409 values
[ins
->dreg
] = LLVMConstInt (LLVMInt64Type (), (gint64
)ins
->inst_c0
, FALSE
);
4413 values
[ins
->dreg
] = get_double_const (cfg
, *(double*)ins
->inst_p0
);
4416 values
[ins
->dreg
] = get_float_const (cfg
, *(float*)ins
->inst_p0
);
4418 case OP_DUMMY_ICONST
:
4419 values
[ins
->dreg
] = LLVMConstInt (LLVMInt32Type (), 0, FALSE
);
4421 case OP_DUMMY_I8CONST
:
4422 values
[ins
->dreg
] = LLVMConstInt (LLVMInt64Type (), 0, FALSE
);
4424 case OP_DUMMY_R8CONST
:
4425 values
[ins
->dreg
] = LLVMConstReal (LLVMDoubleType (), 0.0f
);
4428 LLVMBasicBlockRef target_bb
= get_bb (ctx
, ins
->inst_target_bb
);
4429 LLVMBuildBr (builder
, target_bb
);
4430 has_terminator
= TRUE
;
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
);
4466 switch (linfo
->ret
.storage
) {
4467 case LLVMArgVtypeInReg
: {
4468 LLVMTypeRef ret_type
= LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method
)));
4469 LLVMValueRef val
, addr
, retval
;
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
, "");
4487 g_assert (linfo
->ret
.pair_storage
[i
] == LLVMArgNone
);
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
, "");
4502 g_assert (linfo
->ret
.pair_storage
[i
] == LLVMArgNone
);
4506 LLVMBuildRet (builder
, retval
);
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
);
4519 case LLVMArgVtypeByVal
: {
4520 LLVMValueRef retval
;
4522 g_assert (addresses
[ins
->sreg1
]);
4523 retval
= LLVMBuildLoad (builder
, addresses
[ins
->sreg1
], "");
4524 LLVMBuildRet (builder
, retval
);
4527 case LLVMArgVtypeByRef
: {
4528 LLVMBuildRetVoid (builder
);
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 */
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
);
4543 case LLVMArgGsharedvtFixedVtype
: {
4545 LLVMBuildRetVoid (builder
);
4548 case LLVMArgGsharedvtVariable
: {
4550 LLVMBuildRetVoid (builder
);
4553 case LLVMArgVtypeRetAddr
: {
4554 LLVMBuildRetVoid (builder
);
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
);
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.
4575 LLVMBuildRetVoid (builder
);
4577 LLVMBuildRet (builder
, LLVMConstNull (type_to_llvm_type (ctx
, sig
->ret
)));
4579 LLVMBuildRet (builder
, convert (ctx
, lhs
, type_to_llvm_type (ctx
, sig
->ret
)));
4581 has_terminator
= TRUE
;
4585 g_assert_not_reached ();
4594 case OP_ICOMPARE_IMM
:
4595 case OP_LCOMPARE_IMM
:
4596 case OP_COMPARE_IMM
: {
4598 LLVMValueRef cmp
, args
[16];
4599 gboolean likely
= (ins
->flags
& MONO_INST_LIKELY
) != 0;
4601 if (ins
->next
->opcode
== OP_NOP
)
4604 if (ins
->next
->opcode
== OP_BR
)
4605 /* The comparison result is not needed */
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 ());
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
)), "");
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
, "");
4651 cmp
= LLVMBuildICmp (builder
, cond_to_llvm_cond
[rel
], convert (ctx
, lhs
, IntPtrType ()), convert (ctx
, rhs
, IntPtrType ()), "");
4653 cmp
= LLVMBuildICmp (builder
, cond_to_llvm_cond
[rel
], lhs
, rhs
, "");
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
));
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
);
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
);
4684 builder
= ctx
->builder
;
4686 set_failure (ctx
, "next");
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
);
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
);
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;
4741 /* LLVM doesn't like phi instructions with zero operands */
4742 ctx
->is_dead
[ins
->dreg
] = TRUE
;
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];
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
;
4761 for (j
= 0; j
< GPOINTER_TO_UINT (switch_ins
->klass
); ++j
) {
4762 if (switch_ins
->inst_many_bb
[j
] == bb
)
4769 /* Remember for later */
4770 for (j
= 0; j
< count
; ++j
) {
4771 PhiNode
*node
= (PhiNode
*)mono_mempool_alloc0 (ctx
->mempool
, sizeof (PhiNode
));
4774 node
->in_bb
= bb
->in_bb
[i
];
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
);
4786 values
[ins
->dreg
] = lhs
;
4790 MonoInst
*var
= get_vreg_to_inst (cfg
, ins
->dreg
);
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 ());
4804 case OP_MOVE_F_TO_I4
: {
4805 values
[ins
->dreg
] = LLVMBuildBitCast (builder
, LLVMBuildFPTrunc (builder
, lhs
, LLVMFloatType (), ""), LLVMInt32Type (), "");
4808 case OP_MOVE_I4_TO_F
: {
4809 values
[ins
->dreg
] = LLVMBuildFPExt (builder
, LLVMBuildBitCast (builder
, lhs
, LLVMFloatType (), ""), LLVMDoubleType (), "");
4812 case OP_MOVE_F_TO_I8
: {
4813 values
[ins
->dreg
] = LLVMBuildBitCast (builder
, lhs
, LLVMInt64Type (), "");
4816 case OP_MOVE_I8_TO_F
: {
4817 values
[ins
->dreg
] = LLVMBuildBitCast (builder
, lhs
, LLVMDoubleType (), "");
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
);
4856 builder
= ctx
->builder
;
4858 switch (ins
->opcode
) {
4861 values
[ins
->dreg
] = LLVMBuildAdd (builder
, lhs
, rhs
, dname
);
4865 values
[ins
->dreg
] = LLVMBuildSub (builder
, lhs
, rhs
, dname
);
4869 values
[ins
->dreg
] = LLVMBuildMul (builder
, lhs
, rhs
, dname
);
4873 values
[ins
->dreg
] = LLVMBuildSRem (builder
, lhs
, rhs
, dname
);
4877 values
[ins
->dreg
] = LLVMBuildURem (builder
, lhs
, rhs
, dname
);
4881 values
[ins
->dreg
] = LLVMBuildSDiv (builder
, lhs
, rhs
, dname
);
4885 values
[ins
->dreg
] = LLVMBuildUDiv (builder
, lhs
, rhs
, dname
);
4889 values
[ins
->dreg
] = LLVMBuildFDiv (builder
, lhs
, rhs
, dname
);
4893 values
[ins
->dreg
] = LLVMBuildAnd (builder
, lhs
, rhs
, dname
);
4897 values
[ins
->dreg
] = LLVMBuildOr (builder
, lhs
, rhs
, dname
);
4901 values
[ins
->dreg
] = LLVMBuildXor (builder
, lhs
, rhs
, dname
);
4905 values
[ins
->dreg
] = LLVMBuildShl (builder
, lhs
, rhs
, dname
);
4909 values
[ins
->dreg
] = LLVMBuildAShr (builder
, lhs
, rhs
, dname
);
4913 values
[ins
->dreg
] = LLVMBuildLShr (builder
, lhs
, rhs
, dname
);
4917 values
[ins
->dreg
] = LLVMBuildFAdd (builder
, lhs
, rhs
, dname
);
4920 values
[ins
->dreg
] = LLVMBuildFSub (builder
, lhs
, rhs
, dname
);
4923 values
[ins
->dreg
] = LLVMBuildFMul (builder
, lhs
, rhs
, dname
);
4927 g_assert_not_reached ();
4934 lhs
= convert (ctx
, lhs
, LLVMFloatType ());
4935 rhs
= convert (ctx
, rhs
, LLVMFloatType ());
4936 switch (ins
->opcode
) {
4938 values
[ins
->dreg
] = LLVMBuildFAdd (builder
, lhs
, rhs
, dname
);
4941 values
[ins
->dreg
] = LLVMBuildFSub (builder
, lhs
, rhs
, dname
);
4944 values
[ins
->dreg
] = LLVMBuildFMul (builder
, lhs
, rhs
, dname
);
4947 values
[ins
->dreg
] = LLVMBuildFDiv (builder
, lhs
, rhs
, dname
);
4950 g_assert_not_reached ();
4959 case OP_IREM_UN_IMM
:
4961 case OP_IDIV_UN_IMM
:
4967 case OP_ISHR_UN_IMM
:
4977 case OP_LSHR_UN_IMM
:
4983 case OP_SHR_UN_IMM
: {
4986 if (spec
[MONO_INST_SRC1
] == 'l') {
4987 imm
= LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins
), FALSE
);
4989 imm
= LLVMConstInt (LLVMInt32Type (), ins
->inst_imm
, FALSE
);
4992 emit_div_check (ctx
, builder
, bb
, ins
, lhs
, imm
);
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
);
5002 if (LLVMGetTypeKind (LLVMTypeOf (lhs
)) == LLVMPointerTypeKind
)
5003 lhs
= convert (ctx
, lhs
, IntPtrType ());
5004 imm
= convert (ctx
, imm
, LLVMTypeOf (lhs
));
5005 switch (ins
->opcode
) {
5009 values
[ins
->dreg
] = LLVMBuildAdd (builder
, lhs
, imm
, dname
);
5013 values
[ins
->dreg
] = LLVMBuildSub (builder
, lhs
, imm
, dname
);
5018 values
[ins
->dreg
] = LLVMBuildMul (builder
, lhs
, imm
, dname
);
5022 values
[ins
->dreg
] = LLVMBuildSDiv (builder
, lhs
, imm
, dname
);
5024 case OP_IDIV_UN_IMM
:
5025 case OP_LDIV_UN_IMM
:
5026 values
[ins
->dreg
] = LLVMBuildUDiv (builder
, lhs
, imm
, dname
);
5030 values
[ins
->dreg
] = LLVMBuildSRem (builder
, lhs
, imm
, dname
);
5032 case OP_IREM_UN_IMM
:
5033 values
[ins
->dreg
] = LLVMBuildURem (builder
, lhs
, imm
, dname
);
5038 values
[ins
->dreg
] = LLVMBuildAnd (builder
, lhs
, imm
, dname
);
5042 values
[ins
->dreg
] = LLVMBuildOr (builder
, lhs
, imm
, dname
);
5046 values
[ins
->dreg
] = LLVMBuildXor (builder
, lhs
, imm
, dname
);
5050 values
[ins
->dreg
] = LLVMBuildShl (builder
, lhs
, imm
, dname
);
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
);
5063 values
[ins
->dreg
] = LLVMBuildAShr (builder
, lhs
, imm
, dname
);
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
);
5071 case OP_LSHR_UN_IMM
:
5073 values
[ins
->dreg
] = LLVMBuildLShr (builder
, lhs
, imm
, dname
);
5076 g_assert_not_reached ();
5081 values
[ins
->dreg
] = LLVMBuildSub (builder
, LLVMConstInt (LLVMInt32Type (), 0, FALSE
), convert (ctx
, lhs
, LLVMInt32Type ()), dname
);
5084 values
[ins
->dreg
] = LLVMBuildSub (builder
, LLVMConstInt (LLVMInt64Type (), 0, FALSE
), lhs
, dname
);
5087 lhs
= convert (ctx
, lhs
, LLVMDoubleType ());
5088 values
[ins
->dreg
] = LLVMBuildFSub (builder
, LLVMConstReal (LLVMDoubleType (), 0.0), lhs
, dname
);
5091 lhs
= convert (ctx
, lhs
, LLVMFloatType ());
5092 values
[ins
->dreg
] = LLVMBuildFSub (builder
, LLVMConstReal (LLVMFloatType (), 0.0), lhs
, dname
);
5095 guint32 v
= 0xffffffff;
5096 values
[ins
->dreg
] = LLVMBuildXor (builder
, LLVMConstInt (LLVMInt32Type (), v
, FALSE
), convert (ctx
, lhs
, LLVMInt32Type ()), dname
);
5100 guint64 v
= 0xffffffffffffffffLL
;
5101 values
[ins
->dreg
] = LLVMBuildXor (builder
, LLVMConstInt (LLVMInt64Type (), v
, FALSE
), lhs
, dname
);
5104 #if defined(TARGET_X86) || defined(TARGET_AMD64)
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
);
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
: {
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
), "");
5135 values
[ins
->dreg
] = LLVMBuildSExt (builder
, v
, LLVMInt32Type (), dname
);
5137 values
[ins
->dreg
] = LLVMBuildZExt (builder
, v
, LLVMInt32Type (), dname
);
5140 case OP_ICONV_TO_I8
:
5141 values
[ins
->dreg
] = LLVMBuildSExt (builder
, lhs
, LLVMInt64Type (), dname
);
5143 case OP_ICONV_TO_U8
:
5144 values
[ins
->dreg
] = LLVMBuildZExt (builder
, lhs
, LLVMInt64Type (), dname
);
5146 case OP_FCONV_TO_I4
:
5147 case OP_RCONV_TO_I4
:
5148 values
[ins
->dreg
] = LLVMBuildFPToSI (builder
, lhs
, LLVMInt32Type (), dname
);
5150 case OP_FCONV_TO_I1
:
5151 case OP_RCONV_TO_I1
:
5152 values
[ins
->dreg
] = LLVMBuildSExt (builder
, LLVMBuildFPToSI (builder
, lhs
, LLVMInt8Type (), dname
), LLVMInt32Type (), "");
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 (), "");
5158 case OP_FCONV_TO_I2
:
5159 case OP_RCONV_TO_I2
:
5160 values
[ins
->dreg
] = LLVMBuildSExt (builder
, LLVMBuildFPToSI (builder
, lhs
, LLVMInt16Type (), dname
), LLVMInt32Type (), "");
5162 case OP_FCONV_TO_U2
:
5163 case OP_RCONV_TO_U2
:
5164 values
[ins
->dreg
] = LLVMBuildZExt (builder
, LLVMBuildFPToUI (builder
, lhs
, LLVMInt16Type (), dname
), LLVMInt32Type (), "");
5166 case OP_RCONV_TO_U4
:
5167 values
[ins
->dreg
] = LLVMBuildFPToUI (builder
, lhs
, LLVMInt32Type (), dname
);
5169 case OP_FCONV_TO_I8
:
5170 case OP_RCONV_TO_I8
:
5171 values
[ins
->dreg
] = LLVMBuildFPToSI (builder
, lhs
, LLVMInt64Type (), dname
);
5174 values
[ins
->dreg
] = LLVMBuildFPToSI (builder
, lhs
, IntPtrType (), dname
);
5176 case OP_ICONV_TO_R8
:
5177 case OP_LCONV_TO_R8
:
5178 values
[ins
->dreg
] = LLVMBuildSIToFP (builder
, lhs
, LLVMDoubleType (), dname
);
5180 case OP_ICONV_TO_R_UN
:
5181 case OP_LCONV_TO_R_UN
:
5182 values
[ins
->dreg
] = LLVMBuildUIToFP (builder
, lhs
, LLVMDoubleType (), dname
);
5184 #if TARGET_SIZEOF_VOID_P == 4
5187 case OP_LCONV_TO_I4
:
5188 values
[ins
->dreg
] = LLVMBuildTrunc (builder
, lhs
, LLVMInt32Type (), dname
);
5190 case OP_ICONV_TO_R4
:
5191 case OP_LCONV_TO_R4
:
5192 v
= LLVMBuildSIToFP (builder
, lhs
, LLVMFloatType (), "");
5194 values
[ins
->dreg
] = v
;
5196 values
[ins
->dreg
] = LLVMBuildFPExt (builder
, v
, LLVMDoubleType (), dname
);
5198 case OP_FCONV_TO_R4
:
5199 v
= LLVMBuildFPTrunc (builder
, lhs
, LLVMFloatType (), "");
5201 values
[ins
->dreg
] = v
;
5203 values
[ins
->dreg
] = LLVMBuildFPExt (builder
, v
, LLVMDoubleType (), dname
);
5205 case OP_RCONV_TO_R8
:
5206 values
[ins
->dreg
] = LLVMBuildFPExt (builder
, lhs
, LLVMDoubleType (), dname
);
5208 case OP_RCONV_TO_R4
:
5209 values
[ins
->dreg
] = lhs
;
5212 values
[ins
->dreg
] = LLVMBuildSExt (builder
, convert (ctx
, lhs
, LLVMInt32Type ()), LLVMInt64Type (), dname
);
5215 values
[ins
->dreg
] = LLVMBuildZExt (builder
, convert (ctx
, lhs
, LLVMInt32Type ()), LLVMInt64Type (), dname
);
5218 values
[ins
->dreg
] = LLVMBuildTrunc (builder
, lhs
, LLVMInt32Type (), dname
);
5220 case OP_LOCALLOC_IMM
: {
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];
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
;
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];
5253 args
[1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE
);
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
;
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
:
5280 LLVMValueRef base
, index
, addr
;
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
);
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
);
5297 if (ins
->inst_offset
== 0) {
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, "");
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");
5325 values
[ins
->dreg
] = LLVMBuildSExt (builder
, values
[ins
->dreg
], LLVMInt32Type (), dname
);
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
);
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
: {
5341 LLVMValueRef index
, addr
, base
;
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");
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, "");
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
);
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
: {
5372 LLVMValueRef index
, addr
, base
;
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, "");
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
);
5393 emit_load_general (ctx
, bb
, &builder
, sizeof (gpointer
), convert (ctx
, lhs
, LLVMPointerType (IntPtrType (), 0)), lhs
, "", TRUE
, LLVM_BARRIER_NONE
);
5395 case OP_OUTARG_VTRETADDR
:
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
:
5414 case OP_VCALL_REG
: {
5415 process_call (ctx
, bb
, &builder
, ins
);
5420 LLVMValueRef indexes
[2];
5421 MonoJumpInfo
*tmp_ji
, *ji
;
5422 LLVMValueRef got_entry_addr
;
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
);
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
);
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 ().
5444 values
[ins
->dreg
] = LLVMConstInt (IntPtrType (), 0, FALSE
);
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);
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
);
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
]);
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 */
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
);
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
);
5497 values
[ins
->dreg
] = addresses
[var
->dreg
];
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
);
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
);
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
);
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
);
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
);
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
);
5544 LLVMValueRef args
[1];
5546 args
[0] = convert (ctx
, lhs
, LLVMDoubleType ());
5547 values
[ins
->dreg
] = LLVMBuildCall (builder
, get_intrinsic (ctx
, "fabs"), args
, 1, dname
);
5551 LLVMValueRef args
[1];
5554 args
[0] = convert (ctx
, lhs
, LLVMFloatType ());
5555 values
[ins
->dreg
] = LLVMBuildCall (builder
, get_intrinsic (ctx
, "llvm.fabs.f32"), args
, 1, dname
);
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 ());
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
);
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
) {
5590 v
= LLVMBuildICmp (builder
, LLVMIntSLE
, lhs
, rhs
, "");
5594 v
= LLVMBuildICmp (builder
, LLVMIntSGE
, lhs
, rhs
, "");
5598 v
= LLVMBuildICmp (builder
, LLVMIntULE
, lhs
, rhs
, "");
5602 v
= LLVMBuildICmp (builder
, LLVMIntUGE
, lhs
, rhs
, "");
5605 v
= LLVMBuildFCmp (builder
, LLVMRealUGE
, lhs
, rhs
, "");
5608 g_assert_not_reached ();
5611 values
[ins
->dreg
] = LLVMBuildSelect (builder
, v
, lhs
, rhs
, dname
);
5616 * See the ARM64 comment in mono/utils/atomic.h for an explanation of why this
5617 * hack is necessary (for now).
5620 #define ARM64_ATOMIC_FENCE_FIX mono_llvm_build_fence (builder, LLVM_BARRIER_SEQ)
5622 #define ARM64_ATOMIC_FENCE_FIX
5625 case OP_ATOMIC_EXCHANGE_I4
:
5626 case OP_ATOMIC_EXCHANGE_I8
: {
5627 LLVMValueRef args
[2];
5630 if (ins
->opcode
== OP_ATOMIC_EXCHANGE_I4
)
5631 t
= LLVMInt32Type ();
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
;
5645 case OP_ATOMIC_ADD_I4
:
5646 case OP_ATOMIC_ADD_I8
: {
5647 LLVMValueRef args
[2];
5650 if (ins
->opcode
== OP_ATOMIC_ADD_I4
)
5651 t
= LLVMInt32Type ();
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
;
5664 case OP_ATOMIC_CAS_I4
:
5665 case OP_ATOMIC_CAS_I8
: {
5666 LLVMValueRef args
[3], val
;
5669 if (ins
->opcode
== OP_ATOMIC_CAS_I4
)
5670 t
= LLVMInt32Type ();
5672 t
= LLVMInt64Type ();
5674 args
[0] = convert (ctx
, lhs
, LLVMPointerType (t
, 0));
5676 args
[1] = convert (ctx
, values
[ins
->sreg3
], t
);
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, "");
5686 case OP_MEMORY_BARRIER
: {
5687 mono_llvm_build_fence (builder
, (BarrierKind
) ins
->backend
.memory_barrier_kind
);
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
5702 gboolean sext
, zext
;
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
);
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, "");
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
;
5727 values
[ins
->dreg
] = LLVMBuildSExt (builder
, values
[ins
->dreg
], LLVMInt32Type (), dname
);
5729 values
[ins
->dreg
] = LLVMBuildZExt (builder
, values
[ins
->dreg
], LLVMInt32Type (), dname
);
5732 set_failure (ctx
, "atomic mono.load intrinsic");
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
: {
5747 gboolean sext
, zext
;
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");
5760 if (!values
[ins
->inst_destbasereg
]) {
5761 set_failure (ctx
, "inst_destbasereg");
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
;
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);
5786 #if (defined(TARGET_AMD64) || defined(TARGET_X86)) && defined(__linux__)
5788 // 257 == FS segment register
5789 LLVMTypeRef ptrtype
= LLVMPointerType (IntPtrType (), 257);
5791 // 256 == GS segment register
5792 LLVMTypeRef ptrtype
= LLVMPointerType (IntPtrType (), 256);
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
, ""), "");
5804 set_failure (ctx
, "opcode tls-get");
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";
5817 sig
= LLVMFunctionType0 (LLVMVoidType (), FALSE
);
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
);
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
;
5852 case OP_IADD_OVF_UN
:
5854 case OP_ISUB_OVF_UN
:
5856 case OP_IMUL_OVF_UN
:
5858 case OP_LADD_OVF_UN
:
5860 case OP_LSUB_OVF_UN
:
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
));
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
);
5876 builder
= ctx
->builder
;
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 ?
5888 MonoClass
*klass
= ins
->klass
;
5889 LLVMValueRef args
[5];
5893 set_failure (ctx
, "!klass");
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
);
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, "");
5908 case OP_DUMMY_VZERO
:
5911 case OP_STOREV_MEMBASE
:
5912 case OP_LOADV_MEMBASE
:
5914 MonoClass
*klass
= ins
->klass
;
5915 LLVMValueRef src
= NULL
, dst
, args
[5];
5916 gboolean done
= FALSE
;
5920 set_failure (ctx
, "!klass");
5924 if (mini_is_gsharedvt_klass (klass
)) {
5926 set_failure (ctx
, "gsharedvt");
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 ();
5938 if (!addresses
[ins
->sreg1
]) {
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
);
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));
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), "");
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), "");
5964 g_assert_not_reached ();
5974 args
[2] = LLVMConstInt (LLVMInt32Type (), mono_class_value_size (klass
, NULL
), FALSE
);
5975 args
[3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE
);
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, "");
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));
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
];
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
]);
6014 addresses
[ins
->dreg
] = addresses
[ins
->sreg1
];
6019 case OP_OBJC_GET_SELECTOR
: {
6020 const char *name
= (const char*)ins
->inst_p0
;
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
);
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
);
6061 values
[ins
->dreg
] = LLVMBuildLoad (builder
, var
, "");
6068 #if defined(TARGET_X86) || defined(TARGET_AMD64)
6070 values
[ins
->dreg
] = LLVMConstNull (type_to_llvm_type (ctx
, m_class_get_byval_arg (ins
->klass
)));
6073 case OP_LOADX_MEMBASE
: {
6074 LLVMTypeRef t
= type_to_llvm_type (ctx
, m_class_get_byval_arg (ins
->klass
));
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);
6081 case OP_STOREX_MEMBASE
: {
6082 LLVMTypeRef t
= LLVMTypeOf (values
[ins
->sreg1
]);
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);
6093 values
[ins
->dreg
] = LLVMBuildAdd (builder
, lhs
, rhs
, "");
6097 values
[ins
->dreg
] = LLVMBuildFAdd (builder
, lhs
, rhs
, "");
6103 values
[ins
->dreg
] = LLVMBuildSub (builder
, lhs
, rhs
, "");
6107 values
[ins
->dreg
] = LLVMBuildFSub (builder
, lhs
, rhs
, "");
6111 values
[ins
->dreg
] = LLVMBuildFMul (builder
, lhs
, rhs
, "");
6115 values
[ins
->dreg
] = LLVMBuildFDiv (builder
, lhs
, rhs
, "");
6118 values
[ins
->dreg
] = LLVMBuildAnd (builder
, lhs
, rhs
, "");
6121 values
[ins
->dreg
] = LLVMBuildOr (builder
, lhs
, rhs
, "");
6124 values
[ins
->dreg
] = LLVMBuildXor (builder
, lhs
, rhs
, "");
6128 values
[ins
->dreg
] = LLVMBuildMul (builder
, lhs
, rhs
, "");
6139 LLVMValueRef v
= NULL
;
6141 switch (ins
->opcode
) {
6146 t
= LLVMVectorType (LLVMInt32Type (), 4);
6147 rt
= LLVMVectorType (LLVMFloatType (), 4);
6153 t
= LLVMVectorType (LLVMInt64Type (), 2);
6154 rt
= LLVMVectorType (LLVMDoubleType (), 2);
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
) {
6167 v
= LLVMBuildAnd (builder
, lhs
, rhs
, "");
6171 v
= LLVMBuildOr (builder
, lhs
, rhs
, "");
6175 v
= LLVMBuildXor (builder
, lhs
, rhs
, "");
6179 v
= LLVMBuildAnd (builder
, rhs
, LLVMBuildNot (builder
, lhs
, ""), "");
6182 values
[ins
->dreg
] = LLVMBuildBitCast (builder
, v
, rt
, "");
6188 LLVMValueRef cmp
= LLVMBuildICmp (builder
, LLVMIntULT
, lhs
, rhs
, "");
6189 values
[ins
->dreg
] = LLVMBuildSelect (builder
, cmp
, lhs
, rhs
, "");
6195 LLVMValueRef cmp
= LLVMBuildICmp (builder
, LLVMIntUGT
, lhs
, rhs
, "");
6196 values
[ins
->dreg
] = LLVMBuildSelect (builder
, cmp
, lhs
, rhs
, "");
6200 LLVMValueRef cmp
= LLVMBuildICmp (builder
, LLVMIntSLT
, lhs
, rhs
, "");
6201 values
[ins
->dreg
] = LLVMBuildSelect (builder
, cmp
, lhs
, rhs
, "");
6218 case OP_PADDB_SAT_UN
:
6219 case OP_PADDW_SAT_UN
:
6220 case OP_PSUBB_SAT_UN
:
6221 case OP_PSUBW_SAT_UN
:
6227 case OP_PMULW_HIGH_UN
: {
6228 LLVMValueRef args
[2];
6233 values
[ins
->dreg
] = LLVMBuildCall (builder
, get_intrinsic (ctx
, simd_op_to_intrins (ins
->opcode
)), args
, 2, dname
);
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
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
), "");
6258 LLVMValueRef args
[2];
6263 values
[ins
->dreg
] = LLVMBuildCall (builder
, get_intrinsic (ctx
, simd_op_to_intrins (ins
->opcode
)), args
, 2, dname
);
6271 values
[ins
->dreg
] = LLVMBuildSExt (builder
, LLVMBuildICmp (builder
, LLVMIntEQ
, lhs
, rhs
, ""), LLVMTypeOf (lhs
), "");
6275 values
[ins
->dreg
] = LLVMBuildSExt (builder
, LLVMBuildICmp (builder
, LLVMIntSGT
, lhs
, rhs
, ""), LLVMTypeOf (lhs
), "");
6283 case OP_EXTRACTX_U2
:
6285 case OP_EXTRACT_U1
: {
6287 gboolean zext
= FALSE
;
6289 t
= simd_op_to_llvm_type (ins
->opcode
);
6291 switch (ins
->opcode
) {
6299 case OP_EXTRACTX_U2
:
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
), "");
6311 values
[ins
->dreg
] = LLVMBuildZExt (builder
, values
[ins
->dreg
], LLVMInt32Type (), "");
6320 case OP_EXPAND_R8
: {
6321 LLVMTypeRef t
= simd_op_to_llvm_type (ins
->opcode
);
6322 LLVMValueRef mask
[16], v
;
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
)), "");
6336 values
[ins
->dreg
] = LLVMBuildInsertElement (builder
, values
[ins
->sreg1
], convert (ctx
, values
[ins
->sreg2
], LLVMInt8Type ()), LLVMConstInt (LLVMInt32Type (), ins
->inst_c0
, FALSE
), dname
);
6339 values
[ins
->dreg
] = LLVMBuildInsertElement (builder
, values
[ins
->sreg1
], convert (ctx
, values
[ins
->sreg2
], LLVMInt16Type ()), LLVMConstInt (LLVMInt32Type (), ins
->inst_c0
, FALSE
), dname
);
6342 values
[ins
->dreg
] = LLVMBuildInsertElement (builder
, values
[ins
->sreg1
], convert (ctx
, values
[ins
->sreg2
], LLVMInt32Type ()), LLVMConstInt (LLVMInt32Type (), ins
->inst_c0
, FALSE
), dname
);
6345 values
[ins
->dreg
] = LLVMBuildInsertElement (builder
, values
[ins
->sreg1
], convert (ctx
, values
[ins
->sreg2
], LLVMInt64Type ()), LLVMConstInt (LLVMInt32Type (), ins
->inst_c0
, FALSE
), dname
);
6348 values
[ins
->dreg
] = LLVMBuildInsertElement (builder
, values
[ins
->sreg1
], convert (ctx
, values
[ins
->sreg2
], LLVMFloatType ()), LLVMConstInt (LLVMInt32Type (), ins
->inst_c0
, FALSE
), dname
);
6351 values
[ins
->dreg
] = LLVMBuildInsertElement (builder
, values
[ins
->sreg1
], convert (ctx
, values
[ins
->sreg2
], LLVMDoubleType ()), LLVMConstInt (LLVMInt32Type (), ins
->inst_c0
, FALSE
), dname
);
6354 #if LLVM_API_VERSION > 100
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
);
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
);
6376 values
[ins
->dreg
] = LLVMBuildFPToSI (builder
, lhs
, LLVMVectorType (LLVMInt32Type (), 4), dname
);
6380 #if LLVM_API_VERSION <= 100
6390 case OP_EXTRACT_MASK
:
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
);
6404 LLVMRealPredicate op
;
6406 switch (ins
->inst_c0
) {
6416 case SIMD_COMP_UNORD
:
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
), "");
6439 values
[ins
->dreg
] = LLVMBuildBitCast (builder
, LLVMBuildSExt (builder
, cmp
, LLVMVectorType (LLVMInt32Type (), 4), ""), LLVMTypeOf (lhs
), "");
6443 /* This is only used for implementing shifts by non-immediate */
6444 values
[ins
->dreg
] = lhs
;
6455 LLVMValueRef args
[3];
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
);
6471 case OP_PSHLQ_REG
: {
6472 LLVMValueRef args
[3];
6475 args
[1] = values
[ins
->sreg2
];
6477 values
[ins
->dreg
] = LLVMBuildCall (builder
, get_intrinsic (ctx
, simd_op_to_intrins (ins
->opcode
)), args
, 2, dname
);
6484 case OP_PSHUFLEW_LOW
:
6485 case OP_PSHUFLEW_HIGH
: {
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
) {
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
];
6504 mask
[0] = ((imask
>> 0) & 1);
6505 mask
[1] = ((imask
>> 1) & 1) + 2;
6506 v1
= values
[ins
->sreg1
];
6507 v2
= values
[ins
->sreg2
];
6509 case OP_PSHUFLEW_LOW
:
6511 mask
[0] = ((imask
>> 0) & 3);
6512 mask
[1] = ((imask
>> 2) & 3);
6513 mask
[2] = ((imask
>> 4) & 3);
6514 mask
[3] = ((imask
>> 6) & 3);
6519 v1
= values
[ins
->sreg1
];
6520 v2
= LLVMGetUndef (LLVMTypeOf (v1
));
6522 case OP_PSHUFLEW_HIGH
:
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
));
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
));
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
);
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
: {
6569 LLVMValueRef mask_values
[16];
6570 int i
, mask_size
= 0;
6571 gboolean low
= FALSE
;
6573 switch (ins
->opcode
) {
6574 case OP_UNPACK_LOWB
:
6578 case OP_UNPACK_LOWW
:
6582 case OP_UNPACK_LOWD
:
6583 case OP_UNPACK_LOWPS
:
6587 case OP_UNPACK_LOWQ
:
6588 case OP_UNPACK_LOWPD
:
6592 case OP_UNPACK_HIGHB
:
6595 case OP_UNPACK_HIGHW
:
6598 case OP_UNPACK_HIGHD
:
6599 case OP_UNPACK_HIGHPS
:
6602 case OP_UNPACK_HIGHQ
:
6603 case OP_UNPACK_HIGHPD
:
6607 g_assert_not_reached ();
6611 for (i
= 0; i
< (mask_size
/ 2); ++i
) {
6613 mask
[(i
* 2) + 1] = mask_size
+ i
;
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
);
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
;
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
), "");
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
;
6667 LLVMValueRef args
[3];
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
);
6675 args
[2] = LLVMConstInt (LLVMInt32Type (), 0xf1, FALSE
);
6678 values
[ins
->dreg
] = LLVMBuildCall (builder
, get_intrinsic (ctx
, simd_op_to_intrins (ins
->opcode
)), args
, 3, dname
);
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
), "");
6687 case OP_SSE41_ROUNDPD
: {
6688 LLVMValueRef args
[3];
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
);
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");
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
;
6718 emit_throw (ctx
, bb
, rethrow
, lhs
);
6719 builder
= ctx
->builder
;
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
;
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
;
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
;
6753 case OP_START_HANDLER
: {
6756 case OP_ENDFINALLY
: {
6757 LLVMBasicBlockRef resume_bb
;
6758 MonoBasicBlock
*handler_bb
;
6759 LLVMValueRef val
, switch_ins
, callee
;
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.
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
;
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
);
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");
6802 #if LLVM_API_VERSION > 100
6803 MonoJitICallInfo
*info
;
6805 info
= mono_find_jit_icall_by_name ("llvm_resume_unwind_trampoline");
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
);
6811 callee
= LLVMGetNamedFunction (ctx
->lmodule
, "llvm_resume_unwind_trampoline");
6814 LLVMBuildCall (builder
, callee
, NULL
, 0, "");
6815 LLVMBuildUnreachable (builder
);
6818 has_terminator
= TRUE
;
6821 case OP_IL_SEQ_POINT
:
6826 sprintf (reason
, "opcode %s", mono_inst_name (ins
->opcode
));
6827 set_failure (ctx
, reason
);
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
])
6839 values
[ins
->dreg
] = addresses
[ins
->dreg
];
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
);
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.
6872 mono_llvm_check_method_supported (MonoCompile
*cfg
)
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
;
6887 if (cfg
->method
->save_lmf
) {
6888 cfg
->exception_message
= g_strdup ("lmf");
6889 cfg
->disable_llvm
= TRUE
;
6891 if (cfg
->disable_llvm
)
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
;
6914 if (cfg
->disable_llvm
)
6918 if (cfg
->method
->dynamic
) {
6919 cfg
->exception_message
= g_strdup ("dynamic.");
6920 cfg
->disable_llvm
= TRUE
;
6922 if (cfg
->disable_llvm
)
6926 static LLVMCallInfo
*
6927 get_llvm_call_info (MonoCompile
*cfg
, MonoMethodSignature
*sig
)
6929 LLVMCallInfo
*linfo
;
6932 if (cfg
->gsharedvt
&& cfg
->llvm_only
&& mini_is_gsharedvt_variable_signature (sig
)) {
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
));
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
;
6954 linfo
->ret
.storage
= LLVMArgGsharedvtFixed
;
6955 linfo
->vret_arg_index
= pindex
;
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
;
6968 linfo
->args
[pindex
].storage
= LLVMArgGsharedvtFixed
;
6969 linfo
->args
[pindex
].type
= sig
->params
[i
];
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
];
6984 emit_method_inner (EmitContext
*ctx
);
6987 free_ctx (EmitContext
*ctx
)
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
))
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
);
7023 * mono_llvm_emit_method:
7025 * Emit LLVM IL from the mono IL, and compile it to native code using LLVM.
7028 mono_llvm_emit_method (MonoCompile
*cfg
)
7032 gboolean is_linkonce
= FALSE
;
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);
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
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
;
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
;
7086 method_name
= mono_aot_get_mangled_method_name (cfg
->method
);
7088 is_linkonce
= FALSE
;
7091 printf ("%s %s\n", mono_method_full_name (cfg->method, 1), method_name);
7093 printf ("%s\n", mono_method_full_name (cfg->method, 1));
7097 method_name
= mono_aot_get_method_name (cfg
);
7098 cfg
->llvm_method_name
= g_strdup (method_name
);
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
;
7111 ctx
->lmodule
= LLVMModuleCreateWithName (g_strdup_printf ("jit-module-%s", cfg
->method
->name
));
7113 ctx
->lmodule
= ctx
->module
->lmodule
;
7115 ctx
->llvm_only
= ctx
->module
->llvm_only
;
7117 ctx
->emit_dummy_arg
= TRUE
;
7120 emit_method_inner (ctx
);
7122 if (!ctx_ok (ctx
)) {
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
);
7143 mono_native_tls_set_value (current_cfg_tls_id
, NULL
);
7145 mono_loader_unlock ();
7149 emit_method_inner (EmitContext
*ctx
)
7151 MonoCompile
*cfg
= ctx
->cfg
;
7152 MonoMethodSignature
*sig
;
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
;
7162 GPtrArray
*bblock_list
= ctx
->bblock_list
;
7163 MonoMethodHeader
*header
;
7164 MonoExceptionClause
*clause
;
7167 if (cfg
->gsharedvt
&& !cfg
->llvm_only
) {
7168 set_failure (ctx
, "gsharedvt");
7174 static int count
= 0;
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
));
7186 if (count
> lcount
) {
7187 set_failure (ctx
, "count");
7194 sig
= mono_method_signature_internal (cfg
->method
);
7197 linfo
= get_llvm_call_info (cfg
, sig
);
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
);
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
);
7231 #if LLVM_API_VERSION > 100
7232 LLVMSetLinkage (method
, LLVMExternalLinkage
);
7234 LLVMSetLinkage (method
, LLVMPrivateLinkage
);
7238 if (cfg
->method
->save_lmf
&& !cfg
->llvm_only
) {
7239 set_failure (ctx
, "lmf");
7243 if (sig
->pinvoke
&& cfg
->method
->wrapper_type
!= MONO_WRAPPER_RUNTIME_INVOKE
&& !cfg
->llvm_only
) {
7244 set_failure (ctx
, "pinvoke signature");
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.");
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");
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
);
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
];
7299 int pindex
= ainfo
->pindex
+ ainfo
->ndummy_fpargs
;
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
);
7308 if (ainfo
->storage
== LLVMArgVtypeInReg
&& ainfo
->pair_storage
[0] == LLVMArgNone
&& ainfo
->pair_storage
[1] == LLVMArgNone
)
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
]);
7316 name
= g_strdup_printf ("p_arg_%d", i
);
7318 if (names
[i
] && names
[i
][0] != '\0')
7319 name
= g_strdup_printf ("arg_%s", names
[i
]);
7321 name
= g_strdup_printf ("arg_%d", i
);
7323 LLVMSetValueName (LLVMGetParam (method
, pindex
), name
);
7325 if (ainfo
->storage
== LLVMArgVtypeByVal
)
7326 mono_llvm_add_param_attr (LLVMGetParam (method
, pindex
), LLVM_ATTR_BY_VAL
);
7328 if (ainfo
->storage
== LLVMArgVtypeByRef
) {
7330 cfg
->args
[i
+ sig
->hasthis
]->opcode
= OP_VTARG_ADDR
;
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
);
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
) {
7362 LLVMBuilderRef builder
;
7364 char dname_buf
[128];
7366 builder
= create_builder (ctx
);
7368 for (ins
= bb
->code
; ins
; ins
= ins
->next
) {
7369 switch (ins
->opcode
) {
7374 LLVMTypeRef phi_type
= llvm_type_to_stack_type (cfg
, type_to_llvm_type (ctx
, m_class_get_byval_arg (ins
->klass
)));
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
);
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];
7406 if (ins
->opcode
== OP_VPHI
)
7407 ctx
->is_vphi
[sreg1
] = TRUE
;
7408 ctx
->vreg_types
[sreg1
] = phi_type
;
7414 ((MonoInst
*)ins
->inst_p0
)->flags
|= MONO_INST_INDIRECT
;
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.
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
) {
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
])) {
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))
7478 process_bb (ctx
, bb
);
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
;
7501 in_bb
= get_end_bb (ctx
, node
->in_bb
);
7503 if (ctx
->unreachable
[node
->in_bb
->block_num
])
7506 if (!values
[sreg1
]) {
7507 /* Can happen with values in EH clauses */
7508 set_failure (ctx
, "incoming phi sreg1");
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);
7516 if (LLVMTypeOf (values
[sreg1
]) != LLVMTypeOf (values
[phi
->dreg
])) {
7517 set_failure (ctx
, "incoming phi arg type mismatch");
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
];
7538 /* Already removed */
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
];
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
;
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
);
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
);
7588 LLVMBuildBr (ctx
->builder
, ctx
->inited_bb
);
7592 if (cfg
->llvm_only
) {
7593 GHashTableIter iter
;
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
;
7624 if (cfg
->compile_aot
)
7625 method_index
= mono_aot_get_method_index (cfg
->orig_method
);
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);
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
;
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
7665 g_hash_table_iter_init (&iter
, ctx
->jit_callees
);
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
);
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
);
7686 mono_domain_unlock (domain
);
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
);
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.
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
) {
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
);
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
);
7744 mono_arch_create_vars (cfg
);
7749 * mono_llvm_emit_call:
7751 * Same as mono_arch_emit_call () for LLVM.
7754 mono_llvm_emit_call (MonoCompile
*cfg
, MonoCallInst
*call
)
7757 MonoMethodSignature
*sig
;
7758 int i
, n
, stack_size
;
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
)
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
) {
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
;
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
);
7800 MONO_INST_NEW (cfg
, ins
, OP_MOVE
);
7801 ins
->dreg
= mono_alloc_ireg (cfg
);
7803 ins
->sreg1
= in
->dreg
;
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
);
7824 cfg
->exception_message
= g_strdup ("ainfo->storage");
7825 cfg
->disable_llvm
= TRUE
;
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
)
7841 cfg
= (MonoCompile
*)mono_native_tls_get_value (current_cfg_tls_id
);
7845 return (unsigned char*)mono_domain_code_reserve (cfg
->domain
, size
);
7847 return (unsigned char*)mono_domain_code_reserve (mono_domain_get (), size
);
7852 emitted_cb (LLVMValueRef function
, void *start
, void *end
)
7856 cfg
= (MonoCompile
*)mono_native_tls_get_value (current_cfg_tls_id
);
7858 cfg
->code_len
= (guint8
*)end
- (guint8
*)start
;
7862 exception_cb (void *data
)
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
);
7874 * data points to a DWARF FDE structure, convert it to our unwind format and
7876 * An alternative would be to save it directly, and modify our unwinder to work
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 */
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
) {
7891 MonoExceptionClause
*clause2
= &cfg
->header
->clauses
[cindex2
];
7893 if (cindex1
!= cindex2
&& clause1
->try_offset
>= clause2
->try_offset
&& clause1
->handler_offset
<= clause2
->handler_offset
) {
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.
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
) {
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
];
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 */
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.
7960 decode_llvm_eh_info (EmitContext
*ctx
, gpointer eh_frame
)
7962 MonoCompile
*cfg
= ctx
->cfg
;
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
;
7975 * Decode the one element EH table emitted by the MonoException class
7979 /* Similar to decode_llvm_mono_eh_frame () in aot-runtime.c */
7982 g_assert (version
== 3);
7985 p
= (guint8
*)ALIGN_PTR_TO (p
, 4);
7987 fde_count
= *(guint32
*)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;
7998 cfg
->code_len
= table
[0];
7999 fde_len
= table
[1] - fde_offset
;
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
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
;
8044 dlsym_cb (const char *name
, void **symbol
)
8050 if (!strcmp (name
, "__bzero")) {
8051 *symbol
= (void*)bzero
;
8053 current
= mono_dl_open (NULL
, 0, NULL
);
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
));
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
));
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);
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
,
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
,
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
,
8133 INTRINS_SSE_PACKSSWB
,
8134 INTRINS_SSE_PACKUSWB
,
8135 INTRINS_SSE_PACKSSDW
,
8136 INTRINS_SSE_PACKUSDW
,
8141 INTRINS_SSE_ADDSUBPS
,
8146 INTRINS_SSE_ADDSUBPD
,
8149 INTRINS_SSE_PADDUSW
,
8150 INTRINS_SSE_PSUBUSW
,
8156 INTRINS_SSE_PADDUSB
,
8157 INTRINS_SSE_PSUBUSB
,
8161 INTRINS_SSE_ROUNDPD
,
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"}
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
);
8262 add_intrinsic (LLVMModuleRef module
, int id
)
8265 #if defined(TARGET_AMD64) || defined(TARGET_X86)
8266 LLVMTypeRef ret_type
, arg_types
[16];
8269 name
= (const char*)g_hash_table_lookup (intrins_id_to_name
, GINT_TO_POINTER (id
));
8273 case INTRINS_MEMSET
: {
8274 LLVMTypeRef params
[] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMInt8Type (), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
8276 AddFunc (module
, name
, LLVMVoidType (), params
, 5);
8279 case INTRINS_MEMCPY
: {
8280 LLVMTypeRef params
[] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMPointerType (LLVMInt8Type (), 0), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
8282 AddFunc (module
, name
, LLVMVoidType (), params
, 5);
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);
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);
8314 case INTRINS_FABS
: {
8315 LLVMTypeRef params
[] = { LLVMDoubleType () };
8317 AddFunc (module
, name
, LLVMDoubleType (), params
, 1);
8323 case INTRINS_ABSF
: {
8324 LLVMTypeRef params
[] = { LLVMFloatType () };
8326 AddFunc (module
, name
, LLVMFloatType (), params
, 1);
8329 case INTRINS_POWF
: {
8330 LLVMTypeRef params
[] = { LLVMFloatType (), LLVMFloatType () };
8332 AddFunc (module
, name
, LLVMFloatType (), params
, 2);
8335 case INTRINS_EXPECT_I8
:
8336 AddFunc2 (module
, name
, LLVMInt8Type (), LLVMInt8Type (), LLVMInt8Type ());
8338 case INTRINS_EXPECT_I1
:
8339 AddFunc2 (module
, name
, LLVMInt1Type (), LLVMInt1Type (), LLVMInt1Type ());
8341 #if defined(TARGET_AMD64) || defined(TARGET_X86)
8342 case INTRINS_SSE_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);
8348 case INTRINS_SSE_PSRLI_W
:
8349 case INTRINS_SSE_PSRAI_W
:
8350 case INTRINS_SSE_PSLLI_W
:
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);
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);
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);
8372 case INTRINS_SSE_SQRT_PD
:
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
8434 case INTRINS_SSE_CMPPD
:
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);
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);
8449 case INTRINS_SSE_PACKSSWB
:
8450 case INTRINS_SSE_PACKUSWB
:
8451 case INTRINS_SSE_PACKSSDW
:
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);
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);
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
);
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
);
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
);
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
);
8495 case INTRINS_SSE_PAUSE
:
8496 AddFunc (module
, "llvm.x86.sse2.pause", LLVMVoidType (), NULL
, 0);
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 ();
8505 arg_types
[2] = LLVMInt32Type ();
8507 AddFunc (module
, name
, ret_type
, arg_types
, 3);
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);
8515 #endif /* AMD64 || X86 */
8517 g_assert_not_reached ();
8523 get_intrinsic (EmitContext
*ctx
, const char *name
)
8525 #if LLVM_API_VERSION > 100
8529 * Every method is emitted into its own module so
8530 * we can add intrinsics on demand.
8532 res
= LLVMGetNamedFunction (ctx
->lmodule
, name
);
8536 /* No locking needed */
8537 id
= GPOINTER_TO_INT (g_hash_table_lookup (intrins_name_to_id
, name
));
8540 printf ("%s\n", name
);
8541 g_assert (id
!= -1);
8542 add_intrinsic (ctx
->lmodule
, id
);
8543 res
= LLVMGetNamedFunction (ctx
->lmodule
, name
);
8551 res
= LLVMGetNamedFunction (ctx
->lmodule
, name
);
8558 add_intrinsics (LLVMModuleRef module
)
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
);
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];
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);
8603 add_types (MonoLLVMModule
*module
)
8605 module
->ptr_type
= LLVMPointerType (sizeof (gpointer
) == 8 ? LLVMInt64Type () : LLVMInt32Type (), 0);
8609 mono_llvm_init (void)
8614 mono_native_tls_alloc (¤t_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
;
8628 init_jit_module (MonoDomain
*domain
)
8630 MonoJitDomainInfo
*dinfo
;
8631 MonoLLVMModule
*module
;
8634 dinfo
= domain_jit_info (domain
);
8635 if (dinfo
->llvm_module
)
8638 mono_loader_lock ();
8640 if (dinfo
->llvm_module
) {
8641 mono_loader_unlock ();
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
);
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");
8663 LLVMAddGlobalMapping (module
->ee
, LLVMGetNamedFunction (module
->lmodule
, "llvm_resume_unwind_trampoline"), (void*)info
->func
);
8666 mono_memory_barrier ();
8668 dinfo
->llvm_module
= module
;
8670 mono_loader_unlock ();
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
);
8686 mono_llvm_free_domain_info (MonoDomain
*domain
)
8688 MonoJitDomainInfo
*info
= domain_jit_info (domain
);
8689 MonoLLVMModule
*module
= (MonoLLVMModule
*)info
->llvm_module
;
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);
8708 info
->llvm_module
= NULL
;
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 ();
8739 /* clang ignores our debug info because it has an invalid version */
8740 module
->emit_dwarf
= FALSE
;
8742 add_intrinsics (module
->lmodule
);
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
);
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
);
8758 g_free (build_info
);
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
;
8783 default_lib_name
= default_static_lib_names
[i
];
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
)));
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 */
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
));
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
8832 mark_as_used (module
, personality
);
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
);
8855 llvm_array_from_uints (LLVMTypeRef el_type
, guint32
*values
, int nvalues
)
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
);
8869 llvm_array_from_bytes (guint8
*values
, int nvalues
)
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
);
8882 * mono_llvm_emit_aot_file_info:
8884 * Emit the MonoAotFileInfo structure.
8885 * Same as emit_aot_file_info () in aot-compiler.c.
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.
8903 mono_llvm_emit_aot_data (const char *symbol
, guint8
*data
, int data_len
)
8905 MonoLLVMModule
*module
= &aot_module
;
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 */
8920 AddJitGlobal (MonoLLVMModule
*module
, LLVMTypeRef type
, const char *name
)
8925 s
= g_strdup_printf ("%s%s", module
->global_prefix
, name
);
8926 v
= LLVMAddGlobal (module
->lmodule
, LLVMInt8Type (), s
);
8927 LLVMSetVisibility (v
, LLVMHiddenVisibility
);
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
);
8949 eltypes
[tindex
++] = LLVMInt32Type ();
8950 eltypes
[tindex
++] = LLVMInt32Type ();
8952 for (i
= 0; i
< MONO_AOT_FILE_INFO_NUM_SYMBOLS
; ++i
)
8953 eltypes
[tindex
++] = LLVMPointerType (LLVMInt8Type (), 0);
8955 for (i
= 0; i
< 18; ++i
)
8956 eltypes
[tindex
++] = LLVMInt32Type ();
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
);
8973 if (!module
->static_link
) {
8974 LLVMSetDLLStorageClass (info_var
, LLVMDLLExportStorageClass
);
8978 fields
= g_new (LLVMValueRef
, nfields
);
8980 fields
[tindex
++] = LLVMConstInt (LLVMInt32Type (), info
->version
, FALSE
);
8981 fields
[tindex
++] = LLVMConstInt (LLVMInt32Type (), info
->dummy
, FALSE
);
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
);
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
);
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");
9008 fields
[tindex
++] = LLVMConstNull (eltype
);
9009 fields
[tindex
++] = LLVMConstNull (eltype
);
9011 if (!module
->llvm_only
)
9012 fields
[tindex
++] = AddJitGlobal (module
, eltype
, "method_addresses");
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
);
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");
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");
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");
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
);
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
);
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
) {
9111 s
= g_strdup_printf ("mono_aot_module_%s_info", module
->assembly
->aname
.name
);
9112 /* Get rid of characters which cannot occur in symbols */
9114 for (p
= s
; *p
; ++p
) {
9115 if (!(isalnum (*p
) || *p
== '_'))
9118 var
= LLVMAddGlobal (module
->lmodule
, LLVMPointerType (LLVMInt8Type (), 0), 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.
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
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
);
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
9185 if (module
->llvm_only
) {
9186 GHashTableIter iter
;
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
)
9197 lmethod
= (LLVMValueRef
)g_hash_table_lookup (module
->method_to_lmethod
, method
);
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
;
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
);
9233 if (LLVMVerifyModule (module
->lmodule
, LLVMReturnStatusAction
, &verifier_err
)) {
9234 printf ("%s\n", verifier_err
);
9235 g_assert_not_reached ();
9240 LLVMWriteBitcodeToFile (module
->lmodule
, filename
);
9245 md_string (const char *s
)
9247 return LLVMMDString (s
, strlen (s
));
9250 /* Debugging support */
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
9264 if (!module
->emit_dwarf
)
9267 #if LLVM_API_VERSION > 100
9268 mono_llvm_di_builder_finalize (module
->di_builder
);
9270 LLVMValueRef cu_args
[16], cu
;
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
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);
9291 cu_args
[n_cuargs
++] = LLVMConstInt (LLVMInt32Type (), DW_LANG_C99
, FALSE
);
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
);
9298 cu_args
[n_cuargs
++] = LLVMConstInt (LLVMInt32Type (), 1, FALSE
);
9300 cu_args
[n_cuargs
++] = LLVMMDString ("", strlen (""));
9301 /* Runtime version */
9302 cu_args
[n_cuargs
++] = LLVMConstInt (LLVMInt32Type (), 0, FALSE
);
9304 cu_args
[n_cuargs
++] = LLVMMDNode (args
, 0);
9305 cu_args
[n_cuargs
++] = LLVMMDNode (args
, 0);
9307 if (module
->subprogram_mds
) {
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
);
9316 cu_args
[n_cuargs
++] = LLVMMDNode (args
, 0);
9319 cu_args
[n_cuargs
++] = LLVMMDNode (args
, 0);
9320 /* Imported modules */
9321 cu_args
[n_cuargs
++] = LLVMMDNode (args
, 0);
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
);
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
);
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
);
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
;
9370 mono_debug_get_seq_points (minfo
, &source_file
, NULL
, NULL
, &sym_seq_points
, &n_seq_points
);
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);
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
);
9415 md_args
[6] = LLVMConstInt (LLVMInt32Type (), sym_seq_points
[0].line
, FALSE
);
9417 md_args
[6] = LLVMConstInt (LLVMInt32Type (), 1, FALSE
);
9419 md_args
[7] = type_md
;
9421 md_args
[8] = LLVMConstInt (LLVMInt1Type (), 0, FALSE
);
9423 md_args
[9] = LLVMConstInt (LLVMInt1Type (), 1, FALSE
);
9425 md_args
[10] = LLVMConstInt (LLVMInt32Type (), 0, FALSE
);
9426 /* Index into a virtual function */
9427 md_args
[11] = NULL
;
9428 md_args
[12] = NULL
;
9430 md_args
[13] = LLVMConstInt (LLVMInt1Type (), 0, FALSE
);
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);
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
);
9451 g_free (source_file
);
9452 g_free (sym_seq_points
);
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
);
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
);
9473 LLVMValueRef md_args
[16];
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
);
9484 mono_debug_free_source_location (loc
);
9490 emit_default_dbg_loc (EmitContext
*ctx
, LLVMBuilderRef builder
)
9492 #if LLVM_API_VERSION > 100
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
);
9499 /* Older llvm versions don't require this */
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 ();
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:
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>
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
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.
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
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 ?
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
9587 Vtypes passed on the stack are handled using the 'byval' attribute.
9591 Supported though alloca, we need to emit the load/store code.
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.
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
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
9614 * - use pointer types to help optimizations.
9617 #else /* DISABLE_JIT */
9620 mono_llvm_cleanup (void)
9625 mono_llvm_free_domain_info (MonoDomain
*domain
)
9630 mono_llvm_init (void)
9635 default_mono_llvm_unhandled_exception (void)
9639 #endif /* DISABLE_JIT */