[llvmonly] Enable invariant loads from preinited got slots. (#14027)
[mono-project.git] / mono / mini / mini-llvm.c
blobcf1f2cea63d1cec3bb7fa08f2e76772b5fa1e1d0
1 /**
2 * \file
3 * llvm "Backend" for the mono JIT
5 * Copyright 2009-2011 Novell Inc (http://www.novell.com)
6 * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
7 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
8 */
10 #include "config.h"
12 #include <mono/metadata/debug-helpers.h>
13 #include <mono/metadata/debug-internals.h>
14 #include <mono/metadata/mempool-internals.h>
15 #include <mono/metadata/environment.h>
16 #include <mono/metadata/object-internals.h>
17 #include <mono/metadata/abi-details.h>
18 #include <mono/utils/mono-tls.h>
19 #include <mono/utils/mono-dl.h>
20 #include <mono/utils/mono-time.h>
21 #include <mono/utils/freebsd-dwarf.h>
23 #ifndef __STDC_LIMIT_MACROS
24 #define __STDC_LIMIT_MACROS
25 #endif
26 #ifndef __STDC_CONSTANT_MACROS
27 #define __STDC_CONSTANT_MACROS
28 #endif
30 #include "llvm-c/BitWriter.h"
31 #include "llvm-c/Analysis.h"
33 #include "mini-llvm-cpp.h"
34 #include "llvm-jit.h"
35 #include "aot-compiler.h"
36 #include "mini-llvm.h"
37 #include "mini-runtime.h"
38 #include <mono/utils/mono-math.h>
40 #ifndef DISABLE_JIT
42 #if defined(TARGET_AMD64) && defined(TARGET_WIN32) && defined(HOST_WIN32) && defined(_MSC_VER)
43 #define TARGET_X86_64_WIN32_MSVC
44 #endif
46 #if defined(TARGET_X86_64_WIN32_MSVC)
47 #define TARGET_WIN32_MSVC
48 #endif
50 #if LLVM_API_VERSION < 4
51 #error "The version of the mono llvm repository is too old."
52 #endif
55 * Information associated by mono with LLVM modules.
57 typedef struct {
58 LLVMModuleRef lmodule;
59 LLVMValueRef throw_icall, rethrow, throw_corlib_exception;
60 GHashTable *llvm_types;
61 LLVMValueRef got_var;
62 const char *got_symbol;
63 const char *get_method_symbol;
64 const char *get_unbox_tramp_symbol;
65 GHashTable *plt_entries;
66 GHashTable *plt_entries_ji;
67 GHashTable *method_to_lmethod;
68 GHashTable *direct_callables;
69 char **bb_names;
70 int bb_names_len;
71 GPtrArray *used;
72 LLVMTypeRef ptr_type;
73 GPtrArray *subprogram_mds;
74 MonoEERef *mono_ee;
75 LLVMExecutionEngineRef ee;
76 gboolean external_symbols;
77 gboolean emit_dwarf;
78 int max_got_offset;
79 LLVMValueRef personality;
80 LLVMValueRef *intrins_by_id;
82 /* For AOT */
83 MonoAssembly *assembly;
84 char *global_prefix;
85 MonoAotFileInfo aot_info;
86 const char *jit_got_symbol;
87 const char *eh_frame_symbol;
88 LLVMValueRef get_method, get_unbox_tramp;
89 LLVMValueRef init_method, init_method_gshared_mrgctx, init_method_gshared_this, init_method_gshared_vtable;
90 LLVMValueRef code_start, code_end;
91 LLVMValueRef inited_var;
92 LLVMValueRef unbox_tramp_indexes;
93 LLVMValueRef unbox_trampolines;
94 int max_inited_idx, max_method_idx;
95 gboolean has_jitted_code;
96 gboolean static_link;
97 gboolean llvm_only;
98 gboolean llvm_disable_self_init;
99 gboolean interp;
100 GHashTable *idx_to_lmethod;
101 GHashTable *idx_to_unbox_tramp;
102 GPtrArray *callsite_list;
103 LLVMContextRef context;
104 LLVMValueRef sentinel_exception;
105 void *di_builder, *cu;
106 GHashTable *objc_selector_to_var;
107 GPtrArray *cfgs;
108 int unbox_tramp_num, unbox_tramp_elemsize;
109 GHashTable *got_idx_to_type;
110 } MonoLLVMModule;
113 * Information associated by the backend with mono basic blocks.
115 typedef struct {
116 LLVMBasicBlockRef bblock, end_bblock;
117 LLVMValueRef finally_ind;
118 gboolean added, invoke_target;
120 * If this bblock is the start of a finally clause, this is a list of bblocks it
121 * needs to branch to in ENDFINALLY.
123 GSList *call_handler_return_bbs;
125 * If this bblock is the start of a finally clause, this is the bblock that
126 * CALL_HANDLER needs to branch to.
128 LLVMBasicBlockRef call_handler_target_bb;
129 /* The list of switch statements generated by ENDFINALLY instructions */
130 GSList *endfinally_switch_ins_list;
131 GSList *phi_nodes;
132 } BBInfo;
135 * Structure containing emit state
137 typedef struct {
138 MonoMemPool *mempool;
140 /* Maps method names to the corresponding LLVMValueRef */
141 GHashTable *emitted_method_decls;
143 MonoCompile *cfg;
144 LLVMValueRef lmethod;
145 MonoLLVMModule *module;
146 LLVMModuleRef lmodule;
147 BBInfo *bblocks;
148 int sindex, default_index, ex_index;
149 LLVMBuilderRef builder;
150 LLVMValueRef *values, *addresses;
151 MonoType **vreg_cli_types;
152 LLVMCallInfo *linfo;
153 MonoMethodSignature *sig;
154 GSList *builders;
155 GHashTable *region_to_handler;
156 GHashTable *clause_to_handler;
157 LLVMBuilderRef alloca_builder;
158 LLVMValueRef last_alloca;
159 LLVMValueRef rgctx_arg;
160 LLVMValueRef this_arg;
161 LLVMTypeRef *vreg_types;
162 gboolean *is_vphi;
163 LLVMTypeRef method_type;
164 LLVMBasicBlockRef init_bb, inited_bb;
165 gboolean *is_dead;
166 gboolean *unreachable;
167 gboolean llvm_only;
168 gboolean has_got_access;
169 gboolean emit_dummy_arg;
170 int this_arg_pindex, rgctx_arg_pindex;
171 LLVMValueRef imt_rgctx_loc;
172 GHashTable *llvm_types;
173 LLVMValueRef dbg_md;
174 MonoDebugMethodInfo *minfo;
175 /* For every clause, the clauses it is nested in */
176 GSList **nested_in;
177 LLVMValueRef ex_var;
178 GHashTable *exc_meta;
179 GPtrArray *callsite_list;
180 GPtrArray *phi_values;
181 GPtrArray *bblock_list;
182 char *method_name;
183 GHashTable *jit_callees;
184 LLVMValueRef long_bb_break_var;
185 } EmitContext;
187 typedef struct {
188 MonoBasicBlock *bb;
189 MonoInst *phi;
190 MonoBasicBlock *in_bb;
191 int sreg;
192 } PhiNode;
195 * Instruction metadata
196 * This is the same as ins_info, but LREG != IREG.
198 #ifdef MINI_OP
199 #undef MINI_OP
200 #endif
201 #ifdef MINI_OP3
202 #undef MINI_OP3
203 #endif
204 #define MINI_OP(a,b,dest,src1,src2) dest, src1, src2, ' ',
205 #define MINI_OP3(a,b,dest,src1,src2,src3) dest, src1, src2, src3,
206 #define NONE ' '
207 #define IREG 'i'
208 #define FREG 'f'
209 #define VREG 'v'
210 #define XREG 'x'
211 #define LREG 'l'
212 /* keep in sync with the enum in mini.h */
213 const char
214 mini_llvm_ins_info[] = {
215 #include "mini-ops.h"
217 #undef MINI_OP
218 #undef MINI_OP3
220 #if TARGET_SIZEOF_VOID_P == 4
221 #define GET_LONG_IMM(ins) ((ins)->inst_l)
222 #else
223 #define GET_LONG_IMM(ins) ((ins)->inst_imm)
224 #endif
226 #define LLVM_INS_INFO(opcode) (&mini_llvm_ins_info [((opcode) - OP_START - 1) * 4])
228 #if 0
229 #define TRACE_FAILURE(msg) do { printf ("%s\n", msg); } while (0)
230 #else
231 #define TRACE_FAILURE(msg)
232 #endif
234 #ifdef TARGET_X86
235 #define IS_TARGET_X86 1
236 #else
237 #define IS_TARGET_X86 0
238 #endif
240 #ifdef TARGET_AMD64
241 #define IS_TARGET_AMD64 1
242 #else
243 #define IS_TARGET_AMD64 0
244 #endif
246 #define ctx_ok(ctx) (!(ctx)->cfg->disable_llvm)
248 static LLVMIntPredicate cond_to_llvm_cond [] = {
249 LLVMIntEQ,
250 LLVMIntNE,
251 LLVMIntSLE,
252 LLVMIntSGE,
253 LLVMIntSLT,
254 LLVMIntSGT,
255 LLVMIntULE,
256 LLVMIntUGE,
257 LLVMIntULT,
258 LLVMIntUGT,
261 static LLVMRealPredicate fpcond_to_llvm_cond [] = {
262 LLVMRealOEQ,
263 LLVMRealUNE,
264 LLVMRealOLE,
265 LLVMRealOGE,
266 LLVMRealOLT,
267 LLVMRealOGT,
268 LLVMRealULE,
269 LLVMRealUGE,
270 LLVMRealULT,
271 LLVMRealUGT,
274 typedef enum {
275 INTRINS_MEMSET,
276 INTRINS_MEMCPY,
277 INTRINS_SADD_OVF_I32,
278 INTRINS_UADD_OVF_I32,
279 INTRINS_SSUB_OVF_I32,
280 INTRINS_USUB_OVF_I32,
281 INTRINS_SMUL_OVF_I32,
282 INTRINS_UMUL_OVF_I32,
283 INTRINS_SADD_OVF_I64,
284 INTRINS_UADD_OVF_I64,
285 INTRINS_SSUB_OVF_I64,
286 INTRINS_USUB_OVF_I64,
287 INTRINS_SMUL_OVF_I64,
288 INTRINS_UMUL_OVF_I64,
289 INTRINS_SIN,
290 INTRINS_COS,
291 INTRINS_SQRT,
292 INTRINS_FABS,
293 INTRINS_ABSF,
294 INTRINS_SINF,
295 INTRINS_COSF,
296 INTRINS_SQRTF,
297 INTRINS_POWF,
298 INTRINS_EXPECT_I8,
299 INTRINS_EXPECT_I1,
300 #if defined(TARGET_AMD64) || defined(TARGET_X86)
301 INTRINS_SSE_PMOVMSKB,
302 INTRINS_SSE_PSRLI_W,
303 INTRINS_SSE_PSRAI_W,
304 INTRINS_SSE_PSLLI_W,
305 INTRINS_SSE_PSRLI_D,
306 INTRINS_SSE_PSRAI_D,
307 INTRINS_SSE_PSLLI_D,
308 INTRINS_SSE_PSRLI_Q,
309 INTRINS_SSE_PSLLI_Q,
310 INTRINS_SSE_SQRT_PD,
311 INTRINS_SSE_SQRT_PS,
312 INTRINS_SSE_RSQRT_PS,
313 INTRINS_SSE_RCP_PS,
314 INTRINS_SSE_CVTTPD2DQ,
315 INTRINS_SSE_CVTTPS2DQ,
316 INTRINS_SSE_CVTDQ2PD,
317 INTRINS_SSE_CVTDQ2PS,
318 INTRINS_SSE_CVTPD2DQ,
319 INTRINS_SSE_CVTPS2DQ,
320 INTRINS_SSE_CVTPD2PS,
321 INTRINS_SSE_CVTPS2PD,
322 INTRINS_SSE_CMPPD,
323 INTRINS_SSE_CMPPS,
324 INTRINS_SSE_PACKSSWB,
325 INTRINS_SSE_PACKUSWB,
326 INTRINS_SSE_PACKSSDW,
327 INTRINS_SSE_PACKUSDW,
328 INTRINS_SSE_MINPS,
329 INTRINS_SSE_MAXPS,
330 INTRINS_SSE_HADDPS,
331 INTRINS_SSE_HSUBPS,
332 INTRINS_SSE_ADDSUBPS,
333 INTRINS_SSE_MINPD,
334 INTRINS_SSE_MAXPD,
335 INTRINS_SSE_HADDPD,
336 INTRINS_SSE_HSUBPD,
337 INTRINS_SSE_ADDSUBPD,
338 INTRINS_SSE_PADDSW,
339 INTRINS_SSE_PSUBSW,
340 INTRINS_SSE_PADDUSW,
341 INTRINS_SSE_PSUBUSW,
342 INTRINS_SSE_PAVGW,
343 INTRINS_SSE_PMULHW,
344 INTRINS_SSE_PMULHU,
345 INTRINS_SE_PADDSB,
346 INTRINS_SSE_PSUBSB,
347 INTRINS_SSE_PADDUSB,
348 INTRINS_SSE_PSUBUSB,
349 INTRINS_SSE_PAVGB,
350 INTRINS_SSE_PAUSE,
351 INTRINS_SSE_DPPS,
352 INTRINS_SSE_ROUNDPD,
353 #endif
354 INTRINS_NUM
355 } IntrinsicId;
357 static MonoNativeTlsKey current_cfg_tls_id;
359 static MonoLLVMModule aot_module;
361 static GHashTable *intrins_id_to_name;
362 static GHashTable *intrins_name_to_id;
364 static void init_jit_module (MonoDomain *domain);
366 static void emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil_code);
367 static void emit_default_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder);
368 static LLVMValueRef emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, const char *name);
369 static void emit_dbg_info (MonoLLVMModule *module, const char *filename, const char *cu_name);
370 static void emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *exc_type, LLVMValueRef cmp);
371 static LLVMValueRef get_intrins_by_name (EmitContext *ctx, const char *name);
372 static LLVMValueRef get_intrins (EmitContext *ctx, int id);
373 static void llvm_jit_finalize_method (EmitContext *ctx);
375 static inline void
376 set_failure (EmitContext *ctx, const char *message)
378 TRACE_FAILURE (reason);
379 ctx->cfg->exception_message = g_strdup (message);
380 ctx->cfg->disable_llvm = TRUE;
384 * IntPtrType:
386 * The LLVM type with width == TARGET_SIZEOF_VOID_P
388 static LLVMTypeRef
389 IntPtrType (void)
391 return TARGET_SIZEOF_VOID_P == 8 ? LLVMInt64Type () : LLVMInt32Type ();
394 static LLVMTypeRef
395 ObjRefType (void)
397 return TARGET_SIZEOF_VOID_P == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
400 static LLVMTypeRef
401 ThisType (void)
403 return TARGET_SIZEOF_VOID_P == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
407 * get_vtype_size:
409 * Return the size of the LLVM representation of the vtype T.
411 static guint32
412 get_vtype_size (MonoType *t)
414 int size;
416 size = mono_class_value_size (mono_class_from_mono_type_internal (t), NULL);
418 /* LLVMArgAsIArgs depends on this since it stores whole words */
419 while (size < 2 * TARGET_SIZEOF_VOID_P && mono_is_power_of_two (size) == -1)
420 size ++;
422 return size;
426 * simd_class_to_llvm_type:
428 * Return the LLVM type corresponding to the Mono.SIMD class KLASS
430 static LLVMTypeRef
431 simd_class_to_llvm_type (EmitContext *ctx, MonoClass *klass)
433 const char *klass_name = m_class_get_name (klass);
434 if (!strcmp (klass_name, "Vector2d")) {
435 return LLVMVectorType (LLVMDoubleType (), 2);
436 } else if (!strcmp (klass_name, "Vector2l")) {
437 return LLVMVectorType (LLVMInt64Type (), 2);
438 } else if (!strcmp (klass_name, "Vector2ul")) {
439 return LLVMVectorType (LLVMInt64Type (), 2);
440 } else if (!strcmp (klass_name, "Vector4i")) {
441 return LLVMVectorType (LLVMInt32Type (), 4);
442 } else if (!strcmp (klass_name, "Vector4ui")) {
443 return LLVMVectorType (LLVMInt32Type (), 4);
444 } else if (!strcmp (klass_name, "Vector4f")) {
445 return LLVMVectorType (LLVMFloatType (), 4);
446 } else if (!strcmp (klass_name, "Vector8s")) {
447 return LLVMVectorType (LLVMInt16Type (), 8);
448 } else if (!strcmp (klass_name, "Vector8us")) {
449 return LLVMVectorType (LLVMInt16Type (), 8);
450 } else if (!strcmp (klass_name, "Vector16sb")) {
451 return LLVMVectorType (LLVMInt8Type (), 16);
452 } else if (!strcmp (klass_name, "Vector16b")) {
453 return LLVMVectorType (LLVMInt8Type (), 16);
454 } else if (!strcmp (klass_name, "Vector2")) {
455 /* System.Numerics */
456 return LLVMVectorType (LLVMFloatType (), 4);
457 } else if (!strcmp (klass_name, "Vector3")) {
458 return LLVMVectorType (LLVMFloatType (), 4);
459 } else if (!strcmp (klass_name, "Vector4")) {
460 return LLVMVectorType (LLVMFloatType (), 4);
461 } else if (!strcmp (klass_name, "Vector`1")) {
462 MonoType *etype = mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
463 switch (etype->type) {
464 case MONO_TYPE_I1:
465 case MONO_TYPE_U1:
466 return LLVMVectorType (LLVMInt8Type (), 16);
467 case MONO_TYPE_I2:
468 case MONO_TYPE_U2:
469 return LLVMVectorType (LLVMInt16Type (), 8);
470 case MONO_TYPE_I4:
471 case MONO_TYPE_U4:
472 return LLVMVectorType (LLVMInt32Type (), 4);
473 case MONO_TYPE_I8:
474 case MONO_TYPE_U8:
475 return LLVMVectorType (LLVMInt64Type (), 2);
476 case MONO_TYPE_R4:
477 return LLVMVectorType (LLVMFloatType (), 4);
478 case MONO_TYPE_R8:
479 return LLVMVectorType (LLVMDoubleType (), 2);
480 default:
481 g_assert_not_reached ();
482 return NULL;
484 } else {
485 printf ("%s\n", klass_name);
486 NOT_IMPLEMENTED;
487 return NULL;
491 /* Return the 128 bit SIMD type corresponding to the mono type TYPE */
492 static inline G_GNUC_UNUSED LLVMTypeRef
493 type_to_simd_type (int type)
495 switch (type) {
496 case MONO_TYPE_I1:
497 return LLVMVectorType (LLVMInt8Type (), 16);
498 case MONO_TYPE_I2:
499 return LLVMVectorType (LLVMInt16Type (), 8);
500 case MONO_TYPE_I4:
501 return LLVMVectorType (LLVMInt32Type (), 4);
502 case MONO_TYPE_I8:
503 return LLVMVectorType (LLVMInt64Type (), 2);
504 case MONO_TYPE_R8:
505 return LLVMVectorType (LLVMDoubleType (), 2);
506 case MONO_TYPE_R4:
507 return LLVMVectorType (LLVMFloatType (), 4);
508 default:
509 g_assert_not_reached ();
510 return NULL;
514 static LLVMTypeRef
515 create_llvm_type_for_type (MonoLLVMModule *module, MonoClass *klass)
517 int i, size, nfields, esize;
518 LLVMTypeRef *eltypes;
519 char *name;
520 MonoType *t;
521 LLVMTypeRef ltype;
523 t = m_class_get_byval_arg (klass);
525 if (mini_type_is_hfa (t, &nfields, &esize)) {
527 * This is needed on arm64 where HFAs are returned in
528 * registers.
530 /* SIMD types have size 16 in mono_class_value_size () */
531 if (m_class_is_simd_type (klass))
532 nfields = 16/ esize;
533 size = nfields;
534 eltypes = g_new (LLVMTypeRef, size);
535 for (i = 0; i < size; ++i)
536 eltypes [i] = esize == 4 ? LLVMFloatType () : LLVMDoubleType ();
537 } else {
538 size = get_vtype_size (t);
540 eltypes = g_new (LLVMTypeRef, size);
541 for (i = 0; i < size; ++i)
542 eltypes [i] = LLVMInt8Type ();
545 name = mono_type_full_name (m_class_get_byval_arg (klass));
546 ltype = LLVMStructCreateNamed (module->context, name);
547 LLVMStructSetBody (ltype, eltypes, size, FALSE);
548 g_free (eltypes);
549 g_free (name);
551 return ltype;
555 * type_to_llvm_type:
557 * Return the LLVM type corresponding to T.
559 static LLVMTypeRef
560 type_to_llvm_type (EmitContext *ctx, MonoType *t)
562 if (t->byref)
563 return ThisType ();
565 t = mini_get_underlying_type (t);
567 switch (t->type) {
568 case MONO_TYPE_VOID:
569 return LLVMVoidType ();
570 case MONO_TYPE_I1:
571 return LLVMInt8Type ();
572 case MONO_TYPE_I2:
573 return LLVMInt16Type ();
574 case MONO_TYPE_I4:
575 return LLVMInt32Type ();
576 case MONO_TYPE_U1:
577 return LLVMInt8Type ();
578 case MONO_TYPE_U2:
579 return LLVMInt16Type ();
580 case MONO_TYPE_U4:
581 return LLVMInt32Type ();
582 case MONO_TYPE_I8:
583 case MONO_TYPE_U8:
584 return LLVMInt64Type ();
585 case MONO_TYPE_R4:
586 return LLVMFloatType ();
587 case MONO_TYPE_R8:
588 return LLVMDoubleType ();
589 case MONO_TYPE_I:
590 case MONO_TYPE_U:
591 return IntPtrType ();
592 case MONO_TYPE_OBJECT:
593 case MONO_TYPE_PTR:
594 return ObjRefType ();
595 case MONO_TYPE_VAR:
596 case MONO_TYPE_MVAR:
597 /* Because of generic sharing */
598 return ObjRefType ();
599 case MONO_TYPE_GENERICINST:
600 if (!mono_type_generic_inst_is_valuetype (t))
601 return ObjRefType ();
602 /* Fall through */
603 case MONO_TYPE_VALUETYPE:
604 case MONO_TYPE_TYPEDBYREF: {
605 MonoClass *klass;
606 LLVMTypeRef ltype;
608 klass = mono_class_from_mono_type_internal (t);
610 if (MONO_CLASS_IS_SIMD (ctx->cfg, klass))
611 return simd_class_to_llvm_type (ctx, klass);
613 if (m_class_is_enumtype (klass))
614 return type_to_llvm_type (ctx, mono_class_enum_basetype_internal (klass));
616 ltype = (LLVMTypeRef)g_hash_table_lookup (ctx->module->llvm_types, klass);
617 if (!ltype) {
618 ltype = create_llvm_type_for_type (ctx->module, klass);
619 g_hash_table_insert (ctx->module->llvm_types, klass, ltype);
621 return ltype;
624 default:
625 printf ("X: %d\n", t->type);
626 ctx->cfg->exception_message = g_strdup_printf ("type %s", mono_type_full_name (t));
627 ctx->cfg->disable_llvm = TRUE;
628 return NULL;
633 * type_is_unsigned:
635 * Return whenever T is an unsigned int type.
637 static gboolean
638 type_is_unsigned (EmitContext *ctx, MonoType *t)
640 t = mini_get_underlying_type (t);
641 if (t->byref)
642 return FALSE;
643 switch (t->type) {
644 case MONO_TYPE_U1:
645 case MONO_TYPE_U2:
646 case MONO_TYPE_CHAR:
647 case MONO_TYPE_U4:
648 case MONO_TYPE_U8:
649 return TRUE;
650 default:
651 return FALSE;
656 * type_to_llvm_arg_type:
658 * Same as type_to_llvm_type, but treat i8/i16 as i32.
660 static LLVMTypeRef
661 type_to_llvm_arg_type (EmitContext *ctx, MonoType *t)
663 LLVMTypeRef ptype = type_to_llvm_type (ctx, t);
665 if (ctx->cfg->llvm_only)
666 return ptype;
669 * This works on all abis except arm64/ios which passes multiple
670 * arguments in one stack slot.
672 #ifndef TARGET_ARM64
673 if (ptype == LLVMInt8Type () || ptype == LLVMInt16Type ()) {
675 * LLVM generates code which only sets the lower bits, while JITted
676 * code expects all the bits to be set.
678 ptype = LLVMInt32Type ();
680 #endif
682 return ptype;
686 * llvm_type_to_stack_type:
688 * Return the LLVM type which needs to be used when a value of type TYPE is pushed
689 * on the IL stack.
691 static G_GNUC_UNUSED LLVMTypeRef
692 llvm_type_to_stack_type (MonoCompile *cfg, LLVMTypeRef type)
694 if (type == NULL)
695 return NULL;
696 if (type == LLVMInt8Type ())
697 return LLVMInt32Type ();
698 else if (type == LLVMInt16Type ())
699 return LLVMInt32Type ();
700 else if (!cfg->r4fp && type == LLVMFloatType ())
701 return LLVMDoubleType ();
702 else
703 return type;
707 * regtype_to_llvm_type:
709 * Return the LLVM type corresponding to the regtype C used in instruction
710 * descriptions.
712 static LLVMTypeRef
713 regtype_to_llvm_type (char c)
715 switch (c) {
716 case 'i':
717 return LLVMInt32Type ();
718 case 'l':
719 return LLVMInt64Type ();
720 case 'f':
721 return LLVMDoubleType ();
722 default:
723 return NULL;
728 * op_to_llvm_type:
730 * Return the LLVM type corresponding to the unary/binary opcode OPCODE.
732 static LLVMTypeRef
733 op_to_llvm_type (int opcode)
735 switch (opcode) {
736 case OP_ICONV_TO_I1:
737 case OP_LCONV_TO_I1:
738 return LLVMInt8Type ();
739 case OP_ICONV_TO_U1:
740 case OP_LCONV_TO_U1:
741 return LLVMInt8Type ();
742 case OP_ICONV_TO_I2:
743 case OP_LCONV_TO_I2:
744 return LLVMInt16Type ();
745 case OP_ICONV_TO_U2:
746 case OP_LCONV_TO_U2:
747 return LLVMInt16Type ();
748 case OP_ICONV_TO_I4:
749 case OP_LCONV_TO_I4:
750 return LLVMInt32Type ();
751 case OP_ICONV_TO_U4:
752 case OP_LCONV_TO_U4:
753 return LLVMInt32Type ();
754 case OP_ICONV_TO_I8:
755 return LLVMInt64Type ();
756 case OP_ICONV_TO_R4:
757 return LLVMFloatType ();
758 case OP_ICONV_TO_R8:
759 return LLVMDoubleType ();
760 case OP_ICONV_TO_U8:
761 return LLVMInt64Type ();
762 case OP_FCONV_TO_I4:
763 return LLVMInt32Type ();
764 case OP_FCONV_TO_I8:
765 return LLVMInt64Type ();
766 case OP_FCONV_TO_I1:
767 case OP_FCONV_TO_U1:
768 case OP_RCONV_TO_I1:
769 case OP_RCONV_TO_U1:
770 return LLVMInt8Type ();
771 case OP_FCONV_TO_I2:
772 case OP_FCONV_TO_U2:
773 case OP_RCONV_TO_I2:
774 case OP_RCONV_TO_U2:
775 return LLVMInt16Type ();
776 case OP_RCONV_TO_U4:
777 return LLVMInt32Type ();
778 case OP_FCONV_TO_I:
779 case OP_FCONV_TO_U:
780 return TARGET_SIZEOF_VOID_P == 8 ? LLVMInt64Type () : LLVMInt32Type ();
781 case OP_IADD_OVF:
782 case OP_IADD_OVF_UN:
783 case OP_ISUB_OVF:
784 case OP_ISUB_OVF_UN:
785 case OP_IMUL_OVF:
786 case OP_IMUL_OVF_UN:
787 return LLVMInt32Type ();
788 case OP_LADD_OVF:
789 case OP_LADD_OVF_UN:
790 case OP_LSUB_OVF:
791 case OP_LSUB_OVF_UN:
792 case OP_LMUL_OVF:
793 case OP_LMUL_OVF_UN:
794 return LLVMInt64Type ();
795 default:
796 printf ("%s\n", mono_inst_name (opcode));
797 g_assert_not_reached ();
798 return NULL;
802 #define CLAUSE_START(clause) ((clause)->try_offset)
803 #define CLAUSE_END(clause) (((clause))->try_offset + ((clause))->try_len)
806 * load_store_to_llvm_type:
808 * Return the size/sign/zero extension corresponding to the load/store opcode
809 * OPCODE.
811 static LLVMTypeRef
812 load_store_to_llvm_type (int opcode, int *size, gboolean *sext, gboolean *zext)
814 *sext = FALSE;
815 *zext = FALSE;
817 switch (opcode) {
818 case OP_LOADI1_MEMBASE:
819 case OP_STOREI1_MEMBASE_REG:
820 case OP_STOREI1_MEMBASE_IMM:
821 case OP_ATOMIC_LOAD_I1:
822 case OP_ATOMIC_STORE_I1:
823 *size = 1;
824 *sext = TRUE;
825 return LLVMInt8Type ();
826 case OP_LOADU1_MEMBASE:
827 case OP_LOADU1_MEM:
828 case OP_ATOMIC_LOAD_U1:
829 case OP_ATOMIC_STORE_U1:
830 *size = 1;
831 *zext = TRUE;
832 return LLVMInt8Type ();
833 case OP_LOADI2_MEMBASE:
834 case OP_STOREI2_MEMBASE_REG:
835 case OP_STOREI2_MEMBASE_IMM:
836 case OP_ATOMIC_LOAD_I2:
837 case OP_ATOMIC_STORE_I2:
838 *size = 2;
839 *sext = TRUE;
840 return LLVMInt16Type ();
841 case OP_LOADU2_MEMBASE:
842 case OP_LOADU2_MEM:
843 case OP_ATOMIC_LOAD_U2:
844 case OP_ATOMIC_STORE_U2:
845 *size = 2;
846 *zext = TRUE;
847 return LLVMInt16Type ();
848 case OP_LOADI4_MEMBASE:
849 case OP_LOADU4_MEMBASE:
850 case OP_LOADI4_MEM:
851 case OP_LOADU4_MEM:
852 case OP_STOREI4_MEMBASE_REG:
853 case OP_STOREI4_MEMBASE_IMM:
854 case OP_ATOMIC_LOAD_I4:
855 case OP_ATOMIC_STORE_I4:
856 case OP_ATOMIC_LOAD_U4:
857 case OP_ATOMIC_STORE_U4:
858 *size = 4;
859 return LLVMInt32Type ();
860 case OP_LOADI8_MEMBASE:
861 case OP_LOADI8_MEM:
862 case OP_STOREI8_MEMBASE_REG:
863 case OP_STOREI8_MEMBASE_IMM:
864 case OP_ATOMIC_LOAD_I8:
865 case OP_ATOMIC_STORE_I8:
866 case OP_ATOMIC_LOAD_U8:
867 case OP_ATOMIC_STORE_U8:
868 *size = 8;
869 return LLVMInt64Type ();
870 case OP_LOADR4_MEMBASE:
871 case OP_STORER4_MEMBASE_REG:
872 case OP_ATOMIC_LOAD_R4:
873 case OP_ATOMIC_STORE_R4:
874 *size = 4;
875 return LLVMFloatType ();
876 case OP_LOADR8_MEMBASE:
877 case OP_STORER8_MEMBASE_REG:
878 case OP_ATOMIC_LOAD_R8:
879 case OP_ATOMIC_STORE_R8:
880 *size = 8;
881 return LLVMDoubleType ();
882 case OP_LOAD_MEMBASE:
883 case OP_LOAD_MEM:
884 case OP_STORE_MEMBASE_REG:
885 case OP_STORE_MEMBASE_IMM:
886 *size = TARGET_SIZEOF_VOID_P;
887 return IntPtrType ();
888 default:
889 g_assert_not_reached ();
890 return NULL;
895 * ovf_op_to_intrins:
897 * Return the LLVM intrinsics corresponding to the overflow opcode OPCODE.
899 static const char*
900 ovf_op_to_intrins (int opcode)
902 switch (opcode) {
903 case OP_IADD_OVF:
904 return "llvm.sadd.with.overflow.i32";
905 case OP_IADD_OVF_UN:
906 return "llvm.uadd.with.overflow.i32";
907 case OP_ISUB_OVF:
908 return "llvm.ssub.with.overflow.i32";
909 case OP_ISUB_OVF_UN:
910 return "llvm.usub.with.overflow.i32";
911 case OP_IMUL_OVF:
912 return "llvm.smul.with.overflow.i32";
913 case OP_IMUL_OVF_UN:
914 return "llvm.umul.with.overflow.i32";
915 case OP_LADD_OVF:
916 return "llvm.sadd.with.overflow.i64";
917 case OP_LADD_OVF_UN:
918 return "llvm.uadd.with.overflow.i64";
919 case OP_LSUB_OVF:
920 return "llvm.ssub.with.overflow.i64";
921 case OP_LSUB_OVF_UN:
922 return "llvm.usub.with.overflow.i64";
923 case OP_LMUL_OVF:
924 return "llvm.smul.with.overflow.i64";
925 case OP_LMUL_OVF_UN:
926 return "llvm.umul.with.overflow.i64";
927 default:
928 g_assert_not_reached ();
929 return NULL;
933 static const char*
934 simd_op_to_intrins (int opcode)
936 switch (opcode) {
937 #if defined(TARGET_X86) || defined(TARGET_AMD64)
938 case OP_MINPD:
939 return "llvm.x86.sse2.min.pd";
940 case OP_MINPS:
941 return "llvm.x86.sse.min.ps";
942 case OP_MAXPD:
943 return "llvm.x86.sse2.max.pd";
944 case OP_MAXPS:
945 return "llvm.x86.sse.max.ps";
946 case OP_HADDPD:
947 return "llvm.x86.sse3.hadd.pd";
948 case OP_HADDPS:
949 return "llvm.x86.sse3.hadd.ps";
950 case OP_HSUBPD:
951 return "llvm.x86.sse3.hsub.pd";
952 case OP_HSUBPS:
953 return "llvm.x86.sse3.hsub.ps";
954 case OP_ADDSUBPS:
955 return "llvm.x86.sse3.addsub.ps";
956 case OP_ADDSUBPD:
957 return "llvm.x86.sse3.addsub.pd";
958 case OP_EXTRACT_MASK:
959 return "llvm.x86.sse2.pmovmskb.128";
960 case OP_PSHRW:
961 case OP_PSHRW_REG:
962 return "llvm.x86.sse2.psrli.w";
963 case OP_PSHRD:
964 case OP_PSHRD_REG:
965 return "llvm.x86.sse2.psrli.d";
966 case OP_PSHRQ:
967 case OP_PSHRQ_REG:
968 return "llvm.x86.sse2.psrli.q";
969 case OP_PSHLW:
970 case OP_PSHLW_REG:
971 return "llvm.x86.sse2.pslli.w";
972 case OP_PSHLD:
973 case OP_PSHLD_REG:
974 return "llvm.x86.sse2.pslli.d";
975 case OP_PSHLQ:
976 case OP_PSHLQ_REG:
977 return "llvm.x86.sse2.pslli.q";
978 case OP_PSARW:
979 case OP_PSARW_REG:
980 return "llvm.x86.sse2.psrai.w";
981 case OP_PSARD:
982 case OP_PSARD_REG:
983 return "llvm.x86.sse2.psrai.d";
984 case OP_PADDB_SAT:
985 return "llvm.x86.sse2.padds.b";
986 case OP_PADDW_SAT:
987 return "llvm.x86.sse2.padds.w";
988 case OP_PSUBB_SAT:
989 return "llvm.x86.sse2.psubs.b";
990 case OP_PSUBW_SAT:
991 return "llvm.x86.sse2.psubs.w";
992 case OP_PADDB_SAT_UN:
993 return "llvm.x86.sse2.paddus.b";
994 case OP_PADDW_SAT_UN:
995 return "llvm.x86.sse2.paddus.w";
996 case OP_PSUBB_SAT_UN:
997 return "llvm.x86.sse2.psubus.b";
998 case OP_PSUBW_SAT_UN:
999 return "llvm.x86.sse2.psubus.w";
1000 case OP_PAVGB_UN:
1001 return "llvm.x86.sse2.pavg.b";
1002 case OP_PAVGW_UN:
1003 return "llvm.x86.sse2.pavg.w";
1004 case OP_SQRTPS:
1005 return "llvm.x86.sse.sqrt.ps";
1006 case OP_SQRTPD:
1007 return "llvm.x86.sse2.sqrt.pd";
1008 case OP_RSQRTPS:
1009 return "llvm.x86.sse.rsqrt.ps";
1010 case OP_RCPPS:
1011 return "llvm.x86.sse.rcp.ps";
1012 case OP_CVTDQ2PD:
1013 return "llvm.x86.sse2.cvtdq2pd";
1014 case OP_CVTDQ2PS:
1015 return "llvm.x86.sse2.cvtdq2ps";
1016 case OP_CVTPD2DQ:
1017 return "llvm.x86.sse2.cvtpd2dq";
1018 case OP_CVTPS2DQ:
1019 return "llvm.x86.sse2.cvtps2dq";
1020 case OP_CVTPD2PS:
1021 return "llvm.x86.sse2.cvtpd2ps";
1022 case OP_CVTPS2PD:
1023 return "llvm.x86.sse2.cvtps2pd";
1024 case OP_CVTTPD2DQ:
1025 return "llvm.x86.sse2.cvttpd2dq";
1026 case OP_CVTTPS2DQ:
1027 return "llvm.x86.sse2.cvttps2dq";
1028 case OP_PACKW:
1029 return "llvm.x86.sse2.packsswb.128";
1030 case OP_PACKD:
1031 return "llvm.x86.sse2.packssdw.128";
1032 case OP_PACKW_UN:
1033 return "llvm.x86.sse2.packuswb.128";
1034 case OP_PACKD_UN:
1035 return "llvm.x86.sse41.packusdw";
1036 case OP_PMULW_HIGH:
1037 return "llvm.x86.sse2.pmulh.w";
1038 case OP_PMULW_HIGH_UN:
1039 return "llvm.x86.sse2.pmulhu.w";
1040 case OP_DPPS:
1041 return "llvm.x86.sse41.dpps";
1042 #endif
1043 default:
1044 g_assert_not_reached ();
1045 return NULL;
1049 static LLVMTypeRef
1050 simd_op_to_llvm_type (int opcode)
1052 #if defined(TARGET_X86) || defined(TARGET_AMD64)
1053 switch (opcode) {
1054 case OP_EXTRACT_R8:
1055 case OP_EXPAND_R8:
1056 return type_to_simd_type (MONO_TYPE_R8);
1057 case OP_EXTRACT_I8:
1058 case OP_EXPAND_I8:
1059 return type_to_simd_type (MONO_TYPE_I8);
1060 case OP_EXTRACT_I4:
1061 case OP_EXPAND_I4:
1062 return type_to_simd_type (MONO_TYPE_I4);
1063 case OP_EXTRACT_I2:
1064 case OP_EXTRACT_U2:
1065 case OP_EXTRACTX_U2:
1066 case OP_EXPAND_I2:
1067 return type_to_simd_type (MONO_TYPE_I2);
1068 case OP_EXTRACT_I1:
1069 case OP_EXTRACT_U1:
1070 case OP_EXPAND_I1:
1071 return type_to_simd_type (MONO_TYPE_I1);
1072 case OP_EXPAND_R4:
1073 return type_to_simd_type (MONO_TYPE_R4);
1074 case OP_CVTDQ2PD:
1075 case OP_CVTDQ2PS:
1076 return type_to_simd_type (MONO_TYPE_I4);
1077 case OP_CVTPD2DQ:
1078 case OP_CVTPD2PS:
1079 case OP_CVTTPD2DQ:
1080 return type_to_simd_type (MONO_TYPE_R8);
1081 case OP_CVTPS2DQ:
1082 case OP_CVTPS2PD:
1083 case OP_CVTTPS2DQ:
1084 return type_to_simd_type (MONO_TYPE_R4);
1085 case OP_EXTRACT_MASK:
1086 return type_to_simd_type (MONO_TYPE_I1);
1087 case OP_SQRTPS:
1088 case OP_RSQRTPS:
1089 case OP_RCPPS:
1090 case OP_DUPPS_LOW:
1091 case OP_DUPPS_HIGH:
1092 return type_to_simd_type (MONO_TYPE_R4);
1093 case OP_SQRTPD:
1094 case OP_DUPPD:
1095 return type_to_simd_type (MONO_TYPE_R8);
1096 default:
1097 g_assert_not_reached ();
1098 return NULL;
1100 #else
1101 return NULL;
1102 #endif
1105 static void
1106 set_preserveall_cc (LLVMValueRef func)
1109 * xcode10 (watchOS) and ARM/ARM64 doesn't seem to support preserveall, it fails with:
1110 * fatal error: error in backend: Unsupported calling convention
1112 #if !defined(TARGET_WATCHOS) && !defined(TARGET_ARM) && !defined(TARGET_ARM64)
1113 mono_llvm_set_preserveall_cc (func);
1114 #endif
1117 static void
1118 set_call_preserveall_cc (LLVMValueRef func)
1120 #if !defined(TARGET_WATCHOS) && !defined(TARGET_ARM) && !defined(TARGET_ARM64)
1121 mono_llvm_set_call_preserveall_cc (func);
1122 #endif
1126 * get_bb:
1128 * Return the LLVM basic block corresponding to BB.
1130 static LLVMBasicBlockRef
1131 get_bb (EmitContext *ctx, MonoBasicBlock *bb)
1133 char bb_name_buf [128];
1134 char *bb_name;
1136 if (ctx->bblocks [bb->block_num].bblock == NULL) {
1137 if (bb->flags & BB_EXCEPTION_HANDLER) {
1138 int clause_index = (mono_get_block_region_notry (ctx->cfg, bb->region) >> 8) - 1;
1139 sprintf (bb_name_buf, "EH_CLAUSE%d_BB%d", clause_index, bb->block_num);
1140 bb_name = bb_name_buf;
1141 } else if (bb->block_num < 256) {
1142 if (!ctx->module->bb_names) {
1143 ctx->module->bb_names_len = 256;
1144 ctx->module->bb_names = g_new0 (char*, ctx->module->bb_names_len);
1146 if (!ctx->module->bb_names [bb->block_num]) {
1147 char *n;
1149 n = g_strdup_printf ("BB%d", bb->block_num);
1150 mono_memory_barrier ();
1151 ctx->module->bb_names [bb->block_num] = n;
1153 bb_name = ctx->module->bb_names [bb->block_num];
1154 } else {
1155 sprintf (bb_name_buf, "BB%d", bb->block_num);
1156 bb_name = bb_name_buf;
1159 ctx->bblocks [bb->block_num].bblock = LLVMAppendBasicBlock (ctx->lmethod, bb_name);
1160 ctx->bblocks [bb->block_num].end_bblock = ctx->bblocks [bb->block_num].bblock;
1163 return ctx->bblocks [bb->block_num].bblock;
1167 * get_end_bb:
1169 * Return the last LLVM bblock corresponding to BB.
1170 * This might not be equal to the bb returned by get_bb () since we need to generate
1171 * multiple LLVM bblocks for a mono bblock to handle throwing exceptions.
1173 static LLVMBasicBlockRef
1174 get_end_bb (EmitContext *ctx, MonoBasicBlock *bb)
1176 get_bb (ctx, bb);
1177 return ctx->bblocks [bb->block_num].end_bblock;
1180 static LLVMBasicBlockRef
1181 gen_bb (EmitContext *ctx, const char *prefix)
1183 char bb_name [128];
1185 sprintf (bb_name, "%s%d", prefix, ++ ctx->ex_index);
1186 return LLVMAppendBasicBlock (ctx->lmethod, bb_name);
1190 * resolve_patch:
1192 * Return the target of the patch identified by TYPE and TARGET.
1194 static gpointer
1195 resolve_patch (MonoCompile *cfg, MonoJumpInfoType type, gconstpointer target)
1197 MonoJumpInfo ji;
1198 ERROR_DECL (error);
1199 gpointer res;
1201 memset (&ji, 0, sizeof (ji));
1202 ji.type = type;
1203 ji.data.target = target;
1205 res = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, &ji, FALSE, error);
1206 mono_error_assert_ok (error);
1208 return res;
1212 * convert_full:
1214 * Emit code to convert the LLVM value V to DTYPE.
1216 static LLVMValueRef
1217 convert_full (EmitContext *ctx, LLVMValueRef v, LLVMTypeRef dtype, gboolean is_unsigned)
1219 LLVMTypeRef stype = LLVMTypeOf (v);
1221 if (stype != dtype) {
1222 gboolean ext = FALSE;
1224 /* Extend */
1225 if (dtype == LLVMInt64Type () && (stype == LLVMInt32Type () || stype == LLVMInt16Type () || stype == LLVMInt8Type ()))
1226 ext = TRUE;
1227 else if (dtype == LLVMInt32Type () && (stype == LLVMInt16Type () || stype == LLVMInt8Type ()))
1228 ext = TRUE;
1229 else if (dtype == LLVMInt16Type () && (stype == LLVMInt8Type ()))
1230 ext = TRUE;
1232 if (ext)
1233 return is_unsigned ? LLVMBuildZExt (ctx->builder, v, dtype, "") : LLVMBuildSExt (ctx->builder, v, dtype, "");
1235 if (dtype == LLVMDoubleType () && stype == LLVMFloatType ())
1236 return LLVMBuildFPExt (ctx->builder, v, dtype, "");
1238 /* Trunc */
1239 if (stype == LLVMInt64Type () && (dtype == LLVMInt32Type () || dtype == LLVMInt16Type () || dtype == LLVMInt8Type ()))
1240 return LLVMBuildTrunc (ctx->builder, v, dtype, "");
1241 if (stype == LLVMInt32Type () && (dtype == LLVMInt16Type () || dtype == LLVMInt8Type ()))
1242 return LLVMBuildTrunc (ctx->builder, v, dtype, "");
1243 if (stype == LLVMInt16Type () && dtype == LLVMInt8Type ())
1244 return LLVMBuildTrunc (ctx->builder, v, dtype, "");
1245 if (stype == LLVMDoubleType () && dtype == LLVMFloatType ())
1246 return LLVMBuildFPTrunc (ctx->builder, v, dtype, "");
1248 if (LLVMGetTypeKind (stype) == LLVMPointerTypeKind && LLVMGetTypeKind (dtype) == LLVMPointerTypeKind)
1249 return LLVMBuildBitCast (ctx->builder, v, dtype, "");
1250 if (LLVMGetTypeKind (dtype) == LLVMPointerTypeKind)
1251 return LLVMBuildIntToPtr (ctx->builder, v, dtype, "");
1252 if (LLVMGetTypeKind (stype) == LLVMPointerTypeKind)
1253 return LLVMBuildPtrToInt (ctx->builder, v, dtype, "");
1255 if (mono_arch_is_soft_float ()) {
1256 if (stype == LLVMInt32Type () && dtype == LLVMFloatType ())
1257 return LLVMBuildBitCast (ctx->builder, v, dtype, "");
1258 if (stype == LLVMInt32Type () && dtype == LLVMDoubleType ())
1259 return LLVMBuildBitCast (ctx->builder, LLVMBuildZExt (ctx->builder, v, LLVMInt64Type (), ""), dtype, "");
1262 if (LLVMGetTypeKind (stype) == LLVMVectorTypeKind && LLVMGetTypeKind (dtype) == LLVMVectorTypeKind)
1263 return LLVMBuildBitCast (ctx->builder, v, dtype, "");
1265 LLVMDumpValue (v);
1266 LLVMDumpValue (LLVMConstNull (dtype));
1267 g_assert_not_reached ();
1268 return NULL;
1269 } else {
1270 return v;
1274 static LLVMValueRef
1275 convert (EmitContext *ctx, LLVMValueRef v, LLVMTypeRef dtype)
1277 return convert_full (ctx, v, dtype, FALSE);
1281 * emit_volatile_load:
1283 * If vreg is volatile, emit a load from its address.
1285 static LLVMValueRef
1286 emit_volatile_load (EmitContext *ctx, int vreg)
1288 MonoType *t;
1289 LLVMValueRef v;
1291 // On arm64, we pass the rgctx in a callee saved
1292 // register on arm64 (x15), and llvm might keep the value in that register
1293 // even through the register is marked as 'reserved' inside llvm.
1295 v = mono_llvm_build_load (ctx->builder, ctx->addresses [vreg], "", TRUE);
1296 t = ctx->vreg_cli_types [vreg];
1297 if (t && !t->byref) {
1299 * Might have to zero extend since llvm doesn't have
1300 * unsigned types.
1302 if (t->type == MONO_TYPE_U1 || t->type == MONO_TYPE_U2 || t->type == MONO_TYPE_CHAR || t->type == MONO_TYPE_BOOLEAN)
1303 v = LLVMBuildZExt (ctx->builder, v, LLVMInt32Type (), "");
1304 else if (t->type == MONO_TYPE_I1 || t->type == MONO_TYPE_I2)
1305 v = LLVMBuildSExt (ctx->builder, v, LLVMInt32Type (), "");
1306 else if (t->type == MONO_TYPE_U8)
1307 v = LLVMBuildZExt (ctx->builder, v, LLVMInt64Type (), "");
1310 return v;
1314 * emit_volatile_store:
1316 * If VREG is volatile, emit a store from its value to its address.
1318 static void
1319 emit_volatile_store (EmitContext *ctx, int vreg)
1321 MonoInst *var = get_vreg_to_inst (ctx->cfg, vreg);
1323 if (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) {
1324 g_assert (ctx->addresses [vreg]);
1325 LLVMBuildStore (ctx->builder, convert (ctx, ctx->values [vreg], type_to_llvm_type (ctx, var->inst_vtype)), ctx->addresses [vreg]);
1329 static LLVMTypeRef
1330 sig_to_llvm_sig_no_cinfo (EmitContext *ctx, MonoMethodSignature *sig)
1332 LLVMTypeRef ret_type;
1333 LLVMTypeRef *param_types = NULL;
1334 LLVMTypeRef res;
1335 int i, pindex;
1336 MonoType *rtype;
1338 ret_type = type_to_llvm_type (ctx, sig->ret);
1339 if (!ctx_ok (ctx))
1340 return NULL;
1341 rtype = mini_get_underlying_type (sig->ret);
1343 param_types = g_new0 (LLVMTypeRef, (sig->param_count * 8) + 3);
1344 pindex = 0;
1346 if (sig->hasthis)
1347 param_types [pindex ++] = ThisType ();
1348 for (i = 0; i < sig->param_count; ++i)
1349 param_types [pindex ++] = type_to_llvm_arg_type (ctx, sig->params [i]);
1351 if (!ctx_ok (ctx)) {
1352 g_free (param_types);
1353 return NULL;
1356 res = LLVMFunctionType (ret_type, param_types, pindex, FALSE);
1357 g_free (param_types);
1359 return res;
1363 * sig_to_llvm_sig_full:
1365 * Return the LLVM signature corresponding to the mono signature SIG using the
1366 * calling convention information in CINFO. Fill out the parameter mapping information in CINFO.
1368 static LLVMTypeRef
1369 sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *cinfo)
1371 LLVMTypeRef ret_type;
1372 LLVMTypeRef *param_types = NULL;
1373 LLVMTypeRef res;
1374 int i, j, pindex, vret_arg_pindex = 0;
1375 gboolean vretaddr = FALSE;
1376 MonoType *rtype;
1378 if (!cinfo)
1379 return sig_to_llvm_sig_no_cinfo (ctx, sig);
1381 ret_type = type_to_llvm_type (ctx, sig->ret);
1382 if (!ctx_ok (ctx))
1383 return NULL;
1384 rtype = mini_get_underlying_type (sig->ret);
1386 switch (cinfo->ret.storage) {
1387 case LLVMArgVtypeInReg:
1388 /* LLVM models this by returning an aggregate value */
1389 if (cinfo->ret.pair_storage [0] == LLVMArgInIReg && cinfo->ret.pair_storage [1] == LLVMArgNone) {
1390 LLVMTypeRef members [2];
1392 members [0] = IntPtrType ();
1393 ret_type = LLVMStructType (members, 1, FALSE);
1394 } else if (cinfo->ret.pair_storage [0] == LLVMArgNone && cinfo->ret.pair_storage [1] == LLVMArgNone) {
1395 /* Empty struct */
1396 ret_type = LLVMVoidType ();
1397 } else if (cinfo->ret.pair_storage [0] == LLVMArgInIReg && cinfo->ret.pair_storage [1] == LLVMArgInIReg) {
1398 LLVMTypeRef members [2];
1400 members [0] = IntPtrType ();
1401 members [1] = IntPtrType ();
1402 ret_type = LLVMStructType (members, 2, FALSE);
1403 } else {
1404 g_assert_not_reached ();
1406 break;
1407 case LLVMArgVtypeByVal:
1408 /* Vtype returned normally by val */
1409 break;
1410 case LLVMArgVtypeAsScalar: {
1411 int size = mono_class_value_size (mono_class_from_mono_type_internal (rtype), NULL);
1412 /* LLVM models this by returning an int */
1413 if (size < TARGET_SIZEOF_VOID_P) {
1414 g_assert (cinfo->ret.nslots == 1);
1415 ret_type = LLVMIntType (size * 8);
1416 } else {
1417 g_assert (cinfo->ret.nslots == 1 || cinfo->ret.nslots == 2);
1418 ret_type = LLVMIntType (cinfo->ret.nslots * sizeof (target_mgreg_t) * 8);
1420 break;
1422 case LLVMArgAsIArgs:
1423 ret_type = LLVMArrayType (IntPtrType (), cinfo->ret.nslots);
1424 break;
1425 case LLVMArgFpStruct: {
1426 /* Vtype returned as a fp struct */
1427 LLVMTypeRef members [16];
1429 /* Have to create our own structure since we don't map fp structures to LLVM fp structures yet */
1430 for (i = 0; i < cinfo->ret.nslots; ++i)
1431 members [i] = cinfo->ret.esize == 8 ? LLVMDoubleType () : LLVMFloatType ();
1432 ret_type = LLVMStructType (members, cinfo->ret.nslots, FALSE);
1433 break;
1435 case LLVMArgVtypeByRef:
1436 /* Vtype returned using a hidden argument */
1437 ret_type = LLVMVoidType ();
1438 break;
1439 case LLVMArgVtypeRetAddr:
1440 case LLVMArgGsharedvtFixed:
1441 case LLVMArgGsharedvtFixedVtype:
1442 case LLVMArgGsharedvtVariable:
1443 vretaddr = TRUE;
1444 ret_type = LLVMVoidType ();
1445 break;
1446 default:
1447 break;
1450 param_types = g_new0 (LLVMTypeRef, (sig->param_count * 8) + 3);
1451 pindex = 0;
1452 if (cinfo->ret.storage == LLVMArgVtypeByRef) {
1454 * Has to be the first argument because of the sret argument attribute
1455 * FIXME: This might conflict with passing 'this' as the first argument, but
1456 * this is only used on arm64 which has a dedicated struct return register.
1458 cinfo->vret_arg_pindex = pindex;
1459 param_types [pindex] = type_to_llvm_arg_type (ctx, sig->ret);
1460 if (!ctx_ok (ctx)) {
1461 g_free (param_types);
1462 return NULL;
1464 param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
1465 pindex ++;
1467 if (!ctx->llvm_only && cinfo->rgctx_arg) {
1468 cinfo->rgctx_arg_pindex = pindex;
1469 param_types [pindex] = ctx->module->ptr_type;
1470 pindex ++;
1472 if (cinfo->imt_arg) {
1473 cinfo->imt_arg_pindex = pindex;
1474 param_types [pindex] = ctx->module->ptr_type;
1475 pindex ++;
1477 if (vretaddr) {
1478 /* Compute the index in the LLVM signature where the vret arg needs to be passed */
1479 vret_arg_pindex = pindex;
1480 if (cinfo->vret_arg_index == 1) {
1481 /* Add the slots consumed by the first argument */
1482 LLVMArgInfo *ainfo = &cinfo->args [0];
1483 switch (ainfo->storage) {
1484 case LLVMArgVtypeInReg:
1485 for (j = 0; j < 2; ++j) {
1486 if (ainfo->pair_storage [j] == LLVMArgInIReg)
1487 vret_arg_pindex ++;
1489 break;
1490 default:
1491 vret_arg_pindex ++;
1495 cinfo->vret_arg_pindex = vret_arg_pindex;
1498 if (vretaddr && vret_arg_pindex == pindex)
1499 param_types [pindex ++] = IntPtrType ();
1500 if (sig->hasthis) {
1501 cinfo->this_arg_pindex = pindex;
1502 param_types [pindex ++] = ThisType ();
1503 cinfo->args [0].pindex = cinfo->this_arg_pindex;
1505 if (vretaddr && vret_arg_pindex == pindex)
1506 param_types [pindex ++] = IntPtrType ();
1507 for (i = 0; i < sig->param_count; ++i) {
1508 LLVMArgInfo *ainfo = &cinfo->args [i + sig->hasthis];
1510 if (vretaddr && vret_arg_pindex == pindex)
1511 param_types [pindex ++] = IntPtrType ();
1512 ainfo->pindex = pindex;
1514 switch (ainfo->storage) {
1515 case LLVMArgVtypeInReg:
1516 for (j = 0; j < 2; ++j) {
1517 switch (ainfo->pair_storage [j]) {
1518 case LLVMArgInIReg:
1519 param_types [pindex ++] = LLVMIntType (TARGET_SIZEOF_VOID_P * 8);
1520 break;
1521 case LLVMArgNone:
1522 break;
1523 default:
1524 g_assert_not_reached ();
1527 break;
1528 case LLVMArgVtypeByVal:
1529 param_types [pindex] = type_to_llvm_arg_type (ctx, ainfo->type);
1530 if (!ctx_ok (ctx))
1531 break;
1532 param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
1533 pindex ++;
1534 break;
1535 case LLVMArgAsIArgs:
1536 if (ainfo->esize == 8)
1537 param_types [pindex] = LLVMArrayType (LLVMInt64Type (), ainfo->nslots);
1538 else
1539 param_types [pindex] = LLVMArrayType (IntPtrType (), ainfo->nslots);
1540 pindex ++;
1541 break;
1542 case LLVMArgVtypeByRef:
1543 param_types [pindex] = type_to_llvm_arg_type (ctx, ainfo->type);
1544 if (!ctx_ok (ctx))
1545 break;
1546 param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
1547 pindex ++;
1548 break;
1549 case LLVMArgAsFpArgs: {
1550 int j;
1552 /* Emit dummy fp arguments if needed so the rest is passed on the stack */
1553 for (j = 0; j < ainfo->ndummy_fpargs; ++j)
1554 param_types [pindex ++] = LLVMDoubleType ();
1555 for (j = 0; j < ainfo->nslots; ++j)
1556 param_types [pindex ++] = ainfo->esize == 8 ? LLVMDoubleType () : LLVMFloatType ();
1557 break;
1559 case LLVMArgVtypeAsScalar:
1560 g_assert_not_reached ();
1561 break;
1562 case LLVMArgGsharedvtFixed:
1563 case LLVMArgGsharedvtFixedVtype:
1564 param_types [pindex ++] = LLVMPointerType (type_to_llvm_arg_type (ctx, ainfo->type), 0);
1565 break;
1566 case LLVMArgGsharedvtVariable:
1567 param_types [pindex ++] = LLVMPointerType (IntPtrType (), 0);
1568 break;
1569 default:
1570 param_types [pindex ++] = type_to_llvm_arg_type (ctx, ainfo->type);
1571 break;
1574 if (!ctx_ok (ctx)) {
1575 g_free (param_types);
1576 return NULL;
1578 if (vretaddr && vret_arg_pindex == pindex)
1579 param_types [pindex ++] = IntPtrType ();
1580 if (ctx->llvm_only && cinfo->rgctx_arg) {
1581 /* Pass the rgctx as the last argument */
1582 cinfo->rgctx_arg_pindex = pindex;
1583 param_types [pindex] = ctx->module->ptr_type;
1584 pindex ++;
1585 } else if (ctx->llvm_only && cinfo->dummy_arg) {
1586 /* Pass a dummy arg last */
1587 cinfo->dummy_arg_pindex = pindex;
1588 param_types [pindex] = ctx->module->ptr_type;
1589 pindex ++;
1592 res = LLVMFunctionType (ret_type, param_types, pindex, FALSE);
1593 g_free (param_types);
1595 return res;
1598 static LLVMTypeRef
1599 sig_to_llvm_sig (EmitContext *ctx, MonoMethodSignature *sig)
1601 return sig_to_llvm_sig_full (ctx, sig, NULL);
1605 * LLVMFunctionType1:
1607 * Create an LLVM function type from the arguments.
1609 static G_GNUC_UNUSED LLVMTypeRef
1610 LLVMFunctionType0 (LLVMTypeRef ReturnType,
1611 int IsVarArg)
1613 return LLVMFunctionType (ReturnType, NULL, 0, IsVarArg);
1617 * LLVMFunctionType1:
1619 * Create an LLVM function type from the arguments.
1621 static G_GNUC_UNUSED LLVMTypeRef
1622 LLVMFunctionType1 (LLVMTypeRef ReturnType,
1623 LLVMTypeRef ParamType1,
1624 int IsVarArg)
1626 LLVMTypeRef param_types [1];
1628 param_types [0] = ParamType1;
1630 return LLVMFunctionType (ReturnType, param_types, 1, IsVarArg);
1634 * LLVMFunctionType2:
1636 * Create an LLVM function type from the arguments.
1638 static G_GNUC_UNUSED LLVMTypeRef
1639 LLVMFunctionType2 (LLVMTypeRef ReturnType,
1640 LLVMTypeRef ParamType1,
1641 LLVMTypeRef ParamType2,
1642 int IsVarArg)
1644 LLVMTypeRef param_types [2];
1646 param_types [0] = ParamType1;
1647 param_types [1] = ParamType2;
1649 return LLVMFunctionType (ReturnType, param_types, 2, IsVarArg);
1653 * LLVMFunctionType3:
1655 * Create an LLVM function type from the arguments.
1657 static G_GNUC_UNUSED LLVMTypeRef
1658 LLVMFunctionType3 (LLVMTypeRef ReturnType,
1659 LLVMTypeRef ParamType1,
1660 LLVMTypeRef ParamType2,
1661 LLVMTypeRef ParamType3,
1662 int IsVarArg)
1664 LLVMTypeRef param_types [3];
1666 param_types [0] = ParamType1;
1667 param_types [1] = ParamType2;
1668 param_types [2] = ParamType3;
1670 return LLVMFunctionType (ReturnType, param_types, 3, IsVarArg);
1673 static G_GNUC_UNUSED LLVMTypeRef
1674 LLVMFunctionType5 (LLVMTypeRef ReturnType,
1675 LLVMTypeRef ParamType1,
1676 LLVMTypeRef ParamType2,
1677 LLVMTypeRef ParamType3,
1678 LLVMTypeRef ParamType4,
1679 LLVMTypeRef ParamType5,
1680 int IsVarArg)
1682 LLVMTypeRef param_types [5];
1684 param_types [0] = ParamType1;
1685 param_types [1] = ParamType2;
1686 param_types [2] = ParamType3;
1687 param_types [3] = ParamType4;
1688 param_types [4] = ParamType5;
1690 return LLVMFunctionType (ReturnType, param_types, 5, IsVarArg);
1694 * create_builder:
1696 * Create an LLVM builder and remember it so it can be freed later.
1698 static LLVMBuilderRef
1699 create_builder (EmitContext *ctx)
1701 LLVMBuilderRef builder = LLVMCreateBuilder ();
1703 ctx->builders = g_slist_prepend_mempool (ctx->cfg->mempool, ctx->builders, builder);
1705 emit_default_dbg_loc (ctx, builder);
1707 return builder;
1710 static char*
1711 get_aotconst_name (MonoJumpInfoType type, gconstpointer data, int got_offset)
1713 char *name;
1715 switch (type) {
1716 case MONO_PATCH_INFO_JIT_ICALL:
1717 name = g_strdup_printf ("jit_icall_%s", data);
1718 break;
1719 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1720 MonoJumpInfoRgctxEntry *entry = (MonoJumpInfoRgctxEntry*)data;
1721 name = g_strdup_printf ("RGCTX_SLOT_INDEX_%s", mono_rgctx_info_type_to_str (entry->info_type));
1722 break;
1724 default:
1725 name = g_strdup_printf ("%s_%d", mono_ji_type_to_string (type), got_offset);
1726 break;
1729 return name;
1732 static int
1733 compute_aot_got_offset (MonoLLVMModule *module, MonoJumpInfo *ji, LLVMTypeRef llvm_type)
1735 guint32 got_offset = mono_aot_get_got_offset (ji);
1737 LLVMTypeRef lookup_type = (LLVMTypeRef) g_hash_table_lookup (module->got_idx_to_type, GINT_TO_POINTER (got_offset));
1739 if (!lookup_type) {
1740 lookup_type = llvm_type;
1741 } else if (llvm_type != lookup_type) {
1742 lookup_type = module->ptr_type;
1743 } else {
1744 return got_offset;
1747 g_hash_table_insert (module->got_idx_to_type, GINT_TO_POINTER (got_offset), lookup_type);
1748 return got_offset;
1751 static LLVMValueRef
1752 get_aotconst_typed (EmitContext *ctx, MonoJumpInfoType type, gconstpointer data, LLVMTypeRef llvm_type)
1754 MonoCompile *cfg;
1755 guint32 got_offset;
1756 LLVMValueRef indexes [2];
1757 LLVMValueRef got_entry_addr, load;
1758 LLVMBuilderRef builder = ctx->builder;
1759 char *name = NULL;
1761 cfg = ctx->cfg;
1763 MonoJumpInfo tmp_ji;
1764 tmp_ji.type = type;
1765 tmp_ji.data.target = data;
1767 MonoJumpInfo *ji = mono_aot_patch_info_dup (&tmp_ji);
1769 ji->next = cfg->patch_info;
1770 cfg->patch_info = ji;
1772 got_offset = compute_aot_got_offset (ctx->module, cfg->patch_info, llvm_type);
1773 ctx->module->max_got_offset = MAX (ctx->module->max_got_offset, got_offset);
1775 * If the got slot is shared, it means its initialized when the aot image is loaded, so we don't need to
1776 * explicitly initialize it.
1778 if (!mono_aot_is_shared_got_offset (got_offset)) {
1779 //mono_print_ji (ji);
1780 //printf ("\n");
1781 ctx->cfg->got_access_count ++;
1784 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
1785 indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
1786 got_entry_addr = LLVMBuildGEP (builder, ctx->module->got_var, indexes, 2, "");
1788 name = get_aotconst_name (type, data, got_offset);
1789 if (llvm_type) {
1790 load = LLVMBuildLoad (builder, got_entry_addr, "");
1791 load = convert (ctx, load, llvm_type);
1792 LLVMSetValueName (load, name ? name : "");
1793 } else {
1794 load = LLVMBuildLoad (builder, got_entry_addr, name ? name : "");
1796 g_free (name);
1797 //set_invariant_load_flag (load);
1799 return load;
1802 static LLVMValueRef
1803 get_aotconst (EmitContext *ctx, MonoJumpInfoType type, gconstpointer data)
1805 return get_aotconst_typed (ctx, type, data, NULL);
1808 typedef struct {
1809 MonoJumpInfo *ji;
1810 MonoMethod *method;
1811 LLVMValueRef load;
1812 LLVMTypeRef type;
1813 } CallSite;
1815 static gboolean
1816 method_is_direct_callable (MonoMethod *method)
1818 if (method->wrapper_type == MONO_WRAPPER_ALLOC)
1819 return TRUE;
1820 if (method->string_ctor)
1821 return FALSE;
1822 if (method->wrapper_type)
1823 return FALSE;
1824 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
1825 return FALSE;
1826 /* Can't enable this as the callee might fail llvm compilation */
1828 if (!method->is_inflated && (mono_class_get_flags (method->klass) & TYPE_ATTRIBUTE_PUBLIC) && (method->flags & METHOD_ATTRIBUTE_PUBLIC))
1829 return TRUE;
1831 return FALSE;
1834 static LLVMValueRef
1835 get_callee_llvmonly (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gconstpointer data)
1837 LLVMValueRef callee;
1838 char *callee_name = NULL;
1840 if (ctx->module->static_link && ctx->module->assembly->image != mono_get_corlib ()) {
1841 if (type == MONO_PATCH_INFO_JIT_ICALL) {
1842 MonoJitICallInfo *info = mono_find_jit_icall_by_name ((const char*)data);
1843 g_assert (info);
1845 if (info->func != info->wrapper) {
1846 type = MONO_PATCH_INFO_METHOD;
1847 data = mono_icall_get_wrapper_method (info);
1848 callee_name = mono_aot_get_mangled_method_name ((MonoMethod*)data);
1850 } else if (type == MONO_PATCH_INFO_METHOD) {
1851 MonoMethod *method = (MonoMethod*)data;
1852 if (m_class_get_image (method->klass) != ctx->module->assembly->image && method_is_direct_callable (method))
1853 callee_name = mono_aot_get_mangled_method_name (method);
1857 if (!callee_name)
1858 callee_name = mono_aot_get_direct_call_symbol (type, data);
1859 if (callee_name) {
1860 /* Directly callable */
1861 // FIXME: Locking
1862 callee = (LLVMValueRef)g_hash_table_lookup (ctx->module->direct_callables, callee_name);
1863 if (!callee) {
1864 callee = LLVMAddFunction (ctx->lmodule, callee_name, llvm_sig);
1866 LLVMSetVisibility (callee, LLVMHiddenVisibility);
1868 g_hash_table_insert (ctx->module->direct_callables, (char*)callee_name, callee);
1869 } else {
1870 /* LLVMTypeRef's are uniqued */
1871 if (LLVMGetElementType (LLVMTypeOf (callee)) != llvm_sig)
1872 return LLVMConstBitCast (callee, LLVMPointerType (llvm_sig, 0));
1874 g_free (callee_name);
1876 return callee;
1880 * Change references to jit icalls to the icall wrappers when in corlib, so
1881 * they can be called directly.
1883 if (ctx->module->assembly->image == mono_get_corlib () && type == MONO_PATCH_INFO_JIT_ICALL) {
1884 MonoJitICallInfo *info = mono_find_jit_icall_by_name ((const char*)data);
1885 g_assert (info);
1887 if (info->func != info->wrapper) {
1888 type = MONO_PATCH_INFO_METHOD;
1889 data = mono_icall_get_wrapper_method (info);
1894 * Instead of emitting an indirect call through a got slot, emit a placeholder, and
1895 * replace it with a direct call or an indirect call in mono_llvm_fixup_aot_module ()
1896 * after all methods have been emitted.
1898 if (type == MONO_PATCH_INFO_METHOD) {
1899 MonoMethod *method = (MonoMethod*)data;
1900 if (m_class_get_image (method->klass)->assembly == ctx->module->assembly) {
1901 MonoJumpInfo tmp_ji;
1902 tmp_ji.type = type;
1903 tmp_ji.data.target = data;
1905 MonoJumpInfo *ji = mono_aot_patch_info_dup (&tmp_ji);
1906 ji->next = ctx->cfg->patch_info;
1907 ctx->cfg->patch_info = ji;
1908 LLVMTypeRef llvm_type = LLVMPointerType (llvm_sig, 0);
1910 ctx->cfg->got_access_count ++;
1912 CallSite *info = g_new0 (CallSite, 1);
1913 info->method = method;
1914 info->ji = ji;
1915 info->type = llvm_type;
1918 * Emit a dummy load to represent the callee, and either replace it with
1919 * a reference to the llvm method for the callee, or from a load from the
1920 * GOT.
1922 LLVMValueRef indexes [2];
1923 LLVMValueRef got_entry_addr, load;
1925 LLVMBuilderRef builder = ctx->builder;
1926 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
1927 indexes [1] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
1928 got_entry_addr = LLVMBuildGEP (builder, ctx->module->got_var, indexes, 2, "");
1930 load = LLVMBuildLoad (builder, got_entry_addr, "");
1931 load = convert (ctx, load, llvm_type);
1932 info->load = load;
1934 g_ptr_array_add (ctx->callsite_list, info);
1936 return load;
1941 * Calls are made through the GOT.
1943 callee = get_aotconst_typed (ctx, type, data, LLVMPointerType (llvm_sig, 0));
1945 return callee;
1949 * get_callee:
1951 * Return an llvm value representing the callee given by the arguments.
1953 static LLVMValueRef
1954 get_callee (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gconstpointer data)
1956 LLVMValueRef callee;
1957 char *callee_name;
1958 MonoJumpInfo *ji = NULL;
1960 if (ctx->llvm_only)
1961 return get_callee_llvmonly (ctx, llvm_sig, type, data);
1963 callee_name = mono_aot_get_plt_symbol (type, data);
1964 if (!callee_name)
1965 return NULL;
1967 if (ctx->cfg->compile_aot)
1968 /* Add a patch so referenced wrappers can be compiled in full aot mode */
1969 mono_add_patch_info (ctx->cfg, 0, type, data);
1971 // FIXME: Locking
1972 callee = (LLVMValueRef)g_hash_table_lookup (ctx->module->plt_entries, callee_name);
1973 if (!callee) {
1974 callee = LLVMAddFunction (ctx->lmodule, callee_name, llvm_sig);
1976 LLVMSetVisibility (callee, LLVMHiddenVisibility);
1978 g_hash_table_insert (ctx->module->plt_entries, (char*)callee_name, callee);
1981 if (ctx->cfg->compile_aot) {
1982 ji = g_new0 (MonoJumpInfo, 1);
1983 ji->type = type;
1984 ji->data.target = data;
1986 g_hash_table_insert (ctx->module->plt_entries_ji, ji, callee);
1989 return callee;
1992 static LLVMValueRef
1993 emit_jit_callee (EmitContext *ctx, const char *name, LLVMTypeRef llvm_sig, gpointer target)
1995 #if LLVM_API_VERSION > 100
1996 LLVMValueRef tramp_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (llvm_sig, 0), name);
1997 LLVMSetInitializer (tramp_var, LLVMConstIntToPtr (LLVMConstInt (LLVMInt64Type (), (guint64)(size_t)target, FALSE), LLVMPointerType (llvm_sig, 0)));
1998 LLVMSetLinkage (tramp_var, LLVMExternalLinkage);
1999 LLVMValueRef callee = LLVMBuildLoad (ctx->builder, tramp_var, "");
2000 return callee;
2001 #else
2002 g_assert_not_reached ();
2003 return NULL;
2004 #endif
2007 static int
2008 get_handler_clause (MonoCompile *cfg, MonoBasicBlock *bb)
2010 MonoMethodHeader *header = cfg->header;
2011 MonoExceptionClause *clause;
2012 int i;
2014 /* Directly */
2015 if (bb->region != -1 && MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY))
2016 return (bb->region >> 8) - 1;
2018 /* Indirectly */
2019 for (i = 0; i < header->num_clauses; ++i) {
2020 clause = &header->clauses [i];
2022 if (MONO_OFFSET_IN_CLAUSE (clause, bb->real_offset) && clause->flags == MONO_EXCEPTION_CLAUSE_NONE)
2023 return i;
2026 return -1;
2029 static MonoExceptionClause *
2030 get_most_deep_clause (MonoCompile *cfg, EmitContext *ctx, MonoBasicBlock *bb)
2032 if (bb == cfg->bb_init)
2033 return NULL;
2034 // Since they're sorted by nesting we just need
2035 // the first one that the bb is a member of
2036 for (int i = 0; i < cfg->header->num_clauses; i++) {
2037 MonoExceptionClause *curr = &cfg->header->clauses [i];
2039 if (MONO_OFFSET_IN_CLAUSE (curr, bb->real_offset))
2040 return curr;
2043 return NULL;
2046 static void
2047 set_metadata_flag (LLVMValueRef v, const char *flag_name)
2049 LLVMValueRef md_arg;
2050 int md_kind;
2052 md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
2053 md_arg = LLVMMDString ("mono", 4);
2054 LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
2057 static void
2058 set_invariant_load_flag (LLVMValueRef v)
2060 LLVMValueRef md_arg;
2061 int md_kind;
2062 const char *flag_name;
2064 // FIXME: Cache this
2065 flag_name = "invariant.load";
2066 md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
2067 md_arg = LLVMMDString ("<index>", strlen ("<index>"));
2068 LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
2072 * emit_call:
2074 * Emit an LLVM call or invoke instruction depending on whenever the call is inside
2075 * a try region.
2077 static LLVMValueRef
2078 emit_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, LLVMValueRef callee, LLVMValueRef *args, int pindex)
2080 MonoCompile *cfg = ctx->cfg;
2081 LLVMValueRef lcall = NULL;
2082 LLVMBuilderRef builder = *builder_ref;
2083 MonoExceptionClause *clause;
2085 if (ctx->llvm_only) {
2086 clause = get_most_deep_clause (cfg, ctx, bb);
2088 if (clause) {
2089 g_assert (clause->flags == MONO_EXCEPTION_CLAUSE_NONE || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY || clause->flags == MONO_EXCEPTION_CLAUSE_FAULT);
2092 * Have to use an invoke instead of a call, branching to the
2093 * handler bblock of the clause containing this bblock.
2095 intptr_t key = CLAUSE_END(clause);
2097 LLVMBasicBlockRef lpad_bb = (LLVMBasicBlockRef)g_hash_table_lookup (ctx->exc_meta, (gconstpointer)key);
2099 // FIXME: Find the one that has the lowest end bound for the right start address
2100 // FIXME: Finally + nesting
2102 if (lpad_bb) {
2103 LLVMBasicBlockRef noex_bb = gen_bb (ctx, "CALL_NOEX_BB");
2105 /* Use an invoke */
2106 lcall = LLVMBuildInvoke (builder, callee, args, pindex, noex_bb, lpad_bb, "");
2108 builder = ctx->builder = create_builder (ctx);
2109 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
2111 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
2114 } else {
2115 int clause_index = get_handler_clause (cfg, bb);
2117 if (clause_index != -1) {
2118 MonoMethodHeader *header = cfg->header;
2119 MonoExceptionClause *ec = &header->clauses [clause_index];
2120 MonoBasicBlock *tblock;
2121 LLVMBasicBlockRef ex_bb, noex_bb;
2124 * Have to use an invoke instead of a call, branching to the
2125 * handler bblock of the clause containing this bblock.
2128 g_assert (ec->flags == MONO_EXCEPTION_CLAUSE_NONE || ec->flags == MONO_EXCEPTION_CLAUSE_FINALLY || ec->flags == MONO_EXCEPTION_CLAUSE_FAULT);
2130 tblock = cfg->cil_offset_to_bb [ec->handler_offset];
2131 g_assert (tblock);
2133 ctx->bblocks [tblock->block_num].invoke_target = TRUE;
2135 ex_bb = get_bb (ctx, tblock);
2137 noex_bb = gen_bb (ctx, "NOEX_BB");
2139 /* Use an invoke */
2140 lcall = LLVMBuildInvoke (builder, callee, args, pindex, noex_bb, ex_bb, "");
2142 builder = ctx->builder = create_builder (ctx);
2143 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
2145 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
2149 if (!lcall) {
2150 lcall = LLVMBuildCall (builder, callee, args, pindex, "");
2151 ctx->builder = builder;
2154 if (builder_ref)
2155 *builder_ref = ctx->builder;
2157 return lcall;
2160 static LLVMValueRef
2161 emit_load_general (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef addr, LLVMValueRef base, const char *name, gboolean is_faulting, BarrierKind barrier)
2163 const char *intrins_name;
2164 LLVMValueRef args [16], res;
2165 LLVMTypeRef addr_type;
2166 gboolean use_intrinsics = TRUE;
2168 #if LLVM_API_VERSION > 100
2169 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only) {
2170 /* The llvm.mono.load/store intrinsics are not supported by this llvm version, emit an explicit null check instead */
2171 LLVMValueRef cmp;
2173 cmp = LLVMBuildICmp (*builder_ref, LLVMIntEQ, base, LLVMConstNull (LLVMTypeOf (base)), "");
2174 emit_cond_system_exception (ctx, bb, "NullReferenceException", cmp);
2175 *builder_ref = ctx->builder;
2176 use_intrinsics = FALSE;
2178 #endif
2180 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only && use_intrinsics) {
2181 LLVMAtomicOrdering ordering;
2183 switch (barrier) {
2184 case LLVM_BARRIER_NONE:
2185 ordering = LLVMAtomicOrderingNotAtomic;
2186 break;
2187 case LLVM_BARRIER_ACQ:
2188 ordering = LLVMAtomicOrderingAcquire;
2189 break;
2190 case LLVM_BARRIER_SEQ:
2191 ordering = LLVMAtomicOrderingSequentiallyConsistent;
2192 break;
2193 default:
2194 g_assert_not_reached ();
2195 break;
2199 * We handle loads which can fault by calling a mono specific intrinsic
2200 * using an invoke, so they are handled properly inside try blocks.
2201 * We can't use this outside clauses, since LLVM optimizes intrinsics which
2202 * are marked with IntrReadArgMem.
2204 switch (size) {
2205 case 1:
2206 intrins_name = "llvm.mono.load.i8.p0i8";
2207 break;
2208 case 2:
2209 intrins_name = "llvm.mono.load.i16.p0i16";
2210 break;
2211 case 4:
2212 intrins_name = "llvm.mono.load.i32.p0i32";
2213 break;
2214 case 8:
2215 intrins_name = "llvm.mono.load.i64.p0i64";
2216 break;
2217 default:
2218 g_assert_not_reached ();
2221 addr_type = LLVMTypeOf (addr);
2222 if (addr_type == LLVMPointerType (LLVMDoubleType (), 0) || addr_type == LLVMPointerType (LLVMFloatType (), 0))
2223 addr = LLVMBuildBitCast (*builder_ref, addr, LLVMPointerType (LLVMIntType (size * 8), 0), "");
2225 args [0] = addr;
2226 args [1] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2227 args [2] = LLVMConstInt (LLVMInt1Type (), TRUE, FALSE);
2228 args [3] = LLVMConstInt (LLVMInt32Type (), ordering, FALSE);
2229 res = emit_call (ctx, bb, builder_ref, get_intrins_by_name (ctx, intrins_name), args, 4);
2231 if (addr_type == LLVMPointerType (LLVMDoubleType (), 0))
2232 res = LLVMBuildBitCast (*builder_ref, res, LLVMDoubleType (), "");
2233 else if (addr_type == LLVMPointerType (LLVMFloatType (), 0))
2234 res = LLVMBuildBitCast (*builder_ref, res, LLVMFloatType (), "");
2236 return res;
2237 } else {
2238 LLVMValueRef res;
2241 * We emit volatile loads for loads which can fault, because otherwise
2242 * LLVM will generate invalid code when encountering a load from a
2243 * NULL address.
2245 if (barrier != LLVM_BARRIER_NONE)
2246 res = mono_llvm_build_atomic_load (*builder_ref, addr, name, is_faulting, size, barrier);
2247 else
2248 res = mono_llvm_build_load (*builder_ref, addr, name, is_faulting);
2250 /* Mark it with a custom metadata */
2252 if (is_faulting)
2253 set_metadata_flag (res, "mono.faulting.load");
2256 return res;
2260 static LLVMValueRef
2261 emit_load (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef addr, const char *name, gboolean is_faulting)
2263 return emit_load_general (ctx, bb, builder_ref, size, addr, addr, name, is_faulting, LLVM_BARRIER_NONE);
2266 static void
2267 emit_store_general (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef value, LLVMValueRef addr, LLVMValueRef base, gboolean is_faulting, BarrierKind barrier)
2269 const char *intrins_name;
2270 LLVMValueRef args [16];
2271 gboolean use_intrinsics = TRUE;
2273 #if LLVM_API_VERSION > 100
2274 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only) {
2275 /* The llvm.mono.load/store intrinsics are not supported by this llvm version, emit an explicit null check instead */
2276 LLVMValueRef cmp = LLVMBuildICmp (*builder_ref, LLVMIntEQ, base, LLVMConstNull (LLVMTypeOf (base)), "");
2277 emit_cond_system_exception (ctx, bb, "NullReferenceException", cmp);
2278 *builder_ref = ctx->builder;
2279 use_intrinsics = FALSE;
2281 #endif
2283 if (is_faulting && bb->region != -1 && !ctx->cfg->llvm_only && use_intrinsics) {
2284 LLVMAtomicOrdering ordering;
2286 switch (barrier) {
2287 case LLVM_BARRIER_NONE:
2288 ordering = LLVMAtomicOrderingNotAtomic;
2289 break;
2290 case LLVM_BARRIER_REL:
2291 ordering = LLVMAtomicOrderingRelease;
2292 break;
2293 case LLVM_BARRIER_SEQ:
2294 ordering = LLVMAtomicOrderingSequentiallyConsistent;
2295 break;
2296 default:
2297 g_assert_not_reached ();
2298 break;
2301 switch (size) {
2302 case 1:
2303 intrins_name = "llvm.mono.store.i8.p0i8";
2304 break;
2305 case 2:
2306 intrins_name = "llvm.mono.store.i16.p0i16";
2307 break;
2308 case 4:
2309 intrins_name = "llvm.mono.store.i32.p0i32";
2310 break;
2311 case 8:
2312 intrins_name = "llvm.mono.store.i64.p0i64";
2313 break;
2314 default:
2315 g_assert_not_reached ();
2318 if (LLVMTypeOf (value) == LLVMDoubleType () || LLVMTypeOf (value) == LLVMFloatType ()) {
2319 value = LLVMBuildBitCast (*builder_ref, value, LLVMIntType (size * 8), "");
2320 addr = LLVMBuildBitCast (*builder_ref, addr, LLVMPointerType (LLVMIntType (size * 8), 0), "");
2323 args [0] = value;
2324 args [1] = addr;
2325 args [2] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2326 args [3] = LLVMConstInt (LLVMInt1Type (), TRUE, FALSE);
2327 args [4] = LLVMConstInt (LLVMInt32Type (), ordering, FALSE);
2328 emit_call (ctx, bb, builder_ref, get_intrins_by_name (ctx, intrins_name), args, 5);
2329 } else {
2330 if (barrier != LLVM_BARRIER_NONE)
2331 mono_llvm_build_aligned_store (*builder_ref, value, addr, barrier, size);
2332 else
2333 mono_llvm_build_store (*builder_ref, value, addr, is_faulting, barrier);
2337 static void
2338 emit_store (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, int size, LLVMValueRef value, LLVMValueRef addr, LLVMValueRef base, gboolean is_faulting)
2340 emit_store_general (ctx, bb, builder_ref, size, value, addr, base, is_faulting, LLVM_BARRIER_NONE);
2344 * emit_cond_system_exception:
2346 * Emit code to throw the exception EXC_TYPE if the condition CMP is false.
2347 * Might set the ctx exception.
2349 static void
2350 emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *exc_type, LLVMValueRef cmp)
2352 LLVMBasicBlockRef ex_bb, ex2_bb = NULL, noex_bb;
2353 LLVMBuilderRef builder;
2354 MonoClass *exc_class;
2355 LLVMValueRef args [2];
2356 LLVMValueRef callee;
2357 gboolean no_pc = FALSE;
2358 static MonoClass *exc_classes [MONO_EXC_INTRINS_NUM];
2360 if (IS_TARGET_AMD64)
2361 /* Some platforms don't require the pc argument */
2362 no_pc = TRUE;
2364 int exc_id = mini_exception_id_by_name (exc_type);
2365 if (!exc_classes [exc_id])
2366 exc_classes [exc_id] = mono_class_load_from_name (mono_get_corlib (), "System", exc_type);
2367 exc_class = exc_classes [exc_id];
2369 ex_bb = gen_bb (ctx, "EX_BB");
2370 if (ctx->llvm_only)
2371 ex2_bb = gen_bb (ctx, "EX2_BB");
2372 noex_bb = gen_bb (ctx, "NOEX_BB");
2374 LLVMBuildCondBr (ctx->builder, cmp, ex_bb, noex_bb);
2376 /* Emit exception throwing code */
2377 ctx->builder = builder = create_builder (ctx);
2378 LLVMPositionBuilderAtEnd (builder, ex_bb);
2380 if (ctx->cfg->llvm_only) {
2381 LLVMBuildBr (builder, ex2_bb);
2383 ctx->builder = builder = create_builder (ctx);
2384 LLVMPositionBuilderAtEnd (ctx->builder, ex2_bb);
2386 if (exc_id == MONO_EXC_NULL_REF) {
2387 static LLVMTypeRef sig;
2389 if (!sig)
2390 sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
2391 /* Can't cache this */
2392 callee = get_callee (ctx, sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mini_llvmonly_throw_nullref_exception");
2393 emit_call (ctx, bb, &builder, callee, NULL, 0);
2394 } else {
2395 static LLVMTypeRef sig;
2397 if (!sig)
2398 sig = LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE);
2399 callee = get_callee (ctx, sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_llvm_throw_corlib_exception");
2400 args [0] = LLVMConstInt (LLVMInt32Type (), m_class_get_type_token (exc_class) - MONO_TOKEN_TYPE_DEF, FALSE);
2401 emit_call (ctx, bb, &builder, callee, args, 1);
2404 LLVMBuildUnreachable (builder);
2406 ctx->builder = builder = create_builder (ctx);
2407 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
2409 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
2411 ctx->ex_index ++;
2412 return;
2415 callee = ctx->module->throw_corlib_exception;
2416 if (!callee) {
2417 LLVMTypeRef sig;
2418 const char *icall_name;
2420 if (no_pc)
2421 sig = LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE);
2422 else
2423 sig = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), LLVMPointerType (LLVMInt8Type (), 0), FALSE);
2424 icall_name = "llvm_throw_corlib_exception_abs_trampoline";
2426 if (ctx->cfg->compile_aot) {
2427 callee = get_callee (ctx, sig, MONO_PATCH_INFO_JIT_ICALL, icall_name);
2428 } else {
2430 * Differences between the LLVM/non-LLVM throw corlib exception trampoline:
2431 * - On x86, LLVM generated code doesn't push the arguments
2432 * - The trampoline takes the throw address as an arguments, not a pc offset.
2434 gpointer target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_JIT_ICALL, icall_name);
2435 callee = emit_jit_callee (ctx, "llvm_throw_corlib_exception_trampoline", sig, target);
2437 #if LLVM_API_VERSION > 100
2439 * Make sure that ex_bb starts with the invoke, so the block address points to it, and not to the load
2440 * added by emit_jit_callee ().
2442 ex2_bb = gen_bb (ctx, "EX2_BB");
2443 LLVMBuildBr (builder, ex2_bb);
2444 ex_bb = ex2_bb;
2446 ctx->builder = builder = create_builder (ctx);
2447 LLVMPositionBuilderAtEnd (ctx->builder, ex2_bb);
2448 #else
2449 mono_memory_barrier ();
2450 ctx->module->throw_corlib_exception = callee;
2451 #endif
2455 args [0] = LLVMConstInt (LLVMInt32Type (), m_class_get_type_token (exc_class) - MONO_TOKEN_TYPE_DEF, FALSE);
2458 * The LLVM mono branch contains changes so a block address can be passed as an
2459 * argument to a call.
2461 if (no_pc) {
2462 emit_call (ctx, bb, &builder, callee, args, 1);
2463 } else {
2464 args [1] = LLVMBlockAddress (ctx->lmethod, ex_bb);
2465 emit_call (ctx, bb, &builder, callee, args, 2);
2468 LLVMBuildUnreachable (builder);
2470 ctx->builder = builder = create_builder (ctx);
2471 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
2473 ctx->bblocks [bb->block_num].end_bblock = noex_bb;
2475 ctx->ex_index ++;
2476 return;
2480 * emit_args_to_vtype:
2482 * Emit code to store the vtype in the arguments args to the address ADDRESS.
2484 static void
2485 emit_args_to_vtype (EmitContext *ctx, LLVMBuilderRef builder, MonoType *t, LLVMValueRef address, LLVMArgInfo *ainfo, LLVMValueRef *args)
2487 int j, size, nslots;
2488 MonoClass *klass;
2490 t = mini_get_underlying_type (t);
2491 klass = mono_class_from_mono_type_internal (t);
2492 size = mono_class_value_size (klass, NULL);
2494 if (MONO_CLASS_IS_SIMD (ctx->cfg, klass))
2495 address = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (LLVMInt8Type (), 0), "");
2497 if (ainfo->storage == LLVMArgAsFpArgs)
2498 nslots = ainfo->nslots;
2499 else
2500 nslots = 2;
2502 for (j = 0; j < nslots; ++j) {
2503 LLVMValueRef index [2], addr, daddr;
2504 int part_size = size > TARGET_SIZEOF_VOID_P ? TARGET_SIZEOF_VOID_P : size;
2505 LLVMTypeRef part_type;
2507 while (part_size != 1 && part_size != 2 && part_size != 4 && part_size < 8)
2508 part_size ++;
2510 if (ainfo->pair_storage [j] == LLVMArgNone)
2511 continue;
2513 switch (ainfo->pair_storage [j]) {
2514 case LLVMArgInIReg: {
2515 part_type = LLVMIntType (part_size * 8);
2516 if (MONO_CLASS_IS_SIMD (ctx->cfg, klass)) {
2517 index [0] = LLVMConstInt (LLVMInt32Type (), j * TARGET_SIZEOF_VOID_P, FALSE);
2518 addr = LLVMBuildGEP (builder, address, index, 1, "");
2519 } else {
2520 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (IntPtrType (), 0), "");
2521 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2522 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2524 LLVMBuildStore (builder, convert (ctx, args [j], part_type), LLVMBuildBitCast (ctx->builder, addr, LLVMPointerType (part_type, 0), ""));
2525 break;
2527 case LLVMArgInFPReg: {
2528 LLVMTypeRef arg_type;
2530 if (ainfo->esize == 8)
2531 arg_type = LLVMDoubleType ();
2532 else
2533 arg_type = LLVMFloatType ();
2535 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2536 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (arg_type, 0), "");
2537 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2538 LLVMBuildStore (builder, args [j], addr);
2539 break;
2541 case LLVMArgNone:
2542 break;
2543 default:
2544 g_assert_not_reached ();
2547 size -= TARGET_SIZEOF_VOID_P;
2552 * emit_vtype_to_args:
2554 * Emit code to load a vtype at address ADDRESS into scalar arguments. Store the arguments
2555 * into ARGS, and the number of arguments into NARGS.
2557 static void
2558 emit_vtype_to_args (EmitContext *ctx, LLVMBuilderRef builder, MonoType *t, LLVMValueRef address, LLVMArgInfo *ainfo, LLVMValueRef *args, guint32 *nargs)
2560 int pindex = 0;
2561 int j, size, nslots;
2562 LLVMTypeRef arg_type;
2564 t = mini_get_underlying_type (t);
2565 size = get_vtype_size (t);
2567 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (t)))
2568 address = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (LLVMInt8Type (), 0), "");
2570 if (ainfo->storage == LLVMArgAsFpArgs)
2571 nslots = ainfo->nslots;
2572 else
2573 nslots = 2;
2574 for (j = 0; j < nslots; ++j) {
2575 LLVMValueRef index [2], addr, daddr;
2576 int partsize = size > TARGET_SIZEOF_VOID_P ? TARGET_SIZEOF_VOID_P : size;
2578 if (ainfo->pair_storage [j] == LLVMArgNone)
2579 continue;
2581 switch (ainfo->pair_storage [j]) {
2582 case LLVMArgInIReg:
2583 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (t))) {
2584 index [0] = LLVMConstInt (LLVMInt32Type (), j * TARGET_SIZEOF_VOID_P, FALSE);
2585 addr = LLVMBuildGEP (builder, address, index, 1, "");
2586 } else {
2587 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (IntPtrType (), 0), "");
2588 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2589 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2591 args [pindex ++] = convert (ctx, LLVMBuildLoad (builder, LLVMBuildBitCast (ctx->builder, addr, LLVMPointerType (LLVMIntType (partsize * 8), 0), ""), ""), IntPtrType ());
2592 break;
2593 case LLVMArgInFPReg:
2594 if (ainfo->esize == 8)
2595 arg_type = LLVMDoubleType ();
2596 else
2597 arg_type = LLVMFloatType ();
2598 daddr = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (arg_type, 0), "");
2599 index [0] = LLVMConstInt (LLVMInt32Type (), j, FALSE);
2600 addr = LLVMBuildGEP (builder, daddr, index, 1, "");
2601 args [pindex ++] = LLVMBuildLoad (builder, addr, "");
2602 break;
2603 case LLVMArgNone:
2604 break;
2605 default:
2606 g_assert_not_reached ();
2608 size -= TARGET_SIZEOF_VOID_P;
2611 *nargs = pindex;
2614 static LLVMValueRef
2615 build_alloca_llvm_type_name (EmitContext *ctx, LLVMTypeRef t, int align, const char *name)
2618 * Have to place all alloca's at the end of the entry bb, since otherwise they would
2619 * get executed every time control reaches them.
2621 LLVMPositionBuilder (ctx->alloca_builder, get_bb (ctx, ctx->cfg->bb_entry), ctx->last_alloca);
2623 ctx->last_alloca = mono_llvm_build_alloca (ctx->alloca_builder, t, NULL, align, name);
2624 return ctx->last_alloca;
2627 static LLVMValueRef
2628 build_alloca_llvm_type (EmitContext *ctx, LLVMTypeRef t, int align)
2630 return build_alloca_llvm_type_name (ctx, t, align, "");
2633 static LLVMValueRef
2634 build_alloca (EmitContext *ctx, MonoType *t)
2636 MonoClass *k = mono_class_from_mono_type_internal (t);
2637 int align;
2639 g_assert (!mini_is_gsharedvt_variable_type (t));
2641 if (MONO_CLASS_IS_SIMD (ctx->cfg, k))
2642 align = 16;
2643 else
2644 align = mono_class_min_align (k);
2646 /* Sometimes align is not a power of 2 */
2647 while (mono_is_power_of_two (align) == -1)
2648 align ++;
2650 return build_alloca_llvm_type (ctx, type_to_llvm_type (ctx, t), align);
2653 static LLVMValueRef
2654 emit_gsharedvt_ldaddr (EmitContext *ctx, int vreg)
2657 * gsharedvt local.
2658 * Compute the address of the local as gsharedvt_locals_var + gsharedvt_info_var->locals_offsets [idx].
2660 MonoCompile *cfg = ctx->cfg;
2661 LLVMBuilderRef builder = ctx->builder;
2662 LLVMValueRef offset, offset_var;
2663 LLVMValueRef info_var = ctx->values [cfg->gsharedvt_info_var->dreg];
2664 LLVMValueRef locals_var = ctx->values [cfg->gsharedvt_locals_var->dreg];
2665 LLVMValueRef ptr;
2666 char *name;
2668 g_assert (info_var);
2669 g_assert (locals_var);
2671 int idx = cfg->gsharedvt_vreg_to_idx [vreg] - 1;
2673 offset = LLVMConstInt (LLVMInt32Type (), MONO_STRUCT_OFFSET (MonoGSharedVtMethodRuntimeInfo, entries) + (idx * TARGET_SIZEOF_VOID_P), FALSE);
2674 ptr = LLVMBuildAdd (builder, convert (ctx, info_var, IntPtrType ()), convert (ctx, offset, IntPtrType ()), "");
2676 name = g_strdup_printf ("gsharedvt_local_%d_offset", vreg);
2677 offset_var = LLVMBuildLoad (builder, convert (ctx, ptr, LLVMPointerType (LLVMInt32Type (), 0)), name);
2679 return LLVMBuildAdd (builder, convert (ctx, locals_var, IntPtrType ()), convert (ctx, offset_var, IntPtrType ()), "");
2683 * Put the global into the 'llvm.used' array to prevent it from being optimized away.
2685 static void
2686 mark_as_used (MonoLLVMModule *module, LLVMValueRef global)
2688 if (!module->used)
2689 module->used = g_ptr_array_sized_new (16);
2690 g_ptr_array_add (module->used, global);
2693 static void
2694 emit_llvm_used (MonoLLVMModule *module)
2696 LLVMModuleRef lmodule = module->lmodule;
2697 LLVMTypeRef used_type;
2698 LLVMValueRef used, *used_elem;
2699 int i;
2701 if (!module->used)
2702 return;
2704 used_type = LLVMArrayType (LLVMPointerType (LLVMInt8Type (), 0), module->used->len);
2705 used = LLVMAddGlobal (lmodule, used_type, "llvm.used");
2706 used_elem = g_new0 (LLVMValueRef, module->used->len);
2707 for (i = 0; i < module->used->len; ++i)
2708 used_elem [i] = LLVMConstBitCast ((LLVMValueRef)g_ptr_array_index (module->used, i), LLVMPointerType (LLVMInt8Type (), 0));
2709 LLVMSetInitializer (used, LLVMConstArray (LLVMPointerType (LLVMInt8Type (), 0), used_elem, module->used->len));
2710 LLVMSetLinkage (used, LLVMAppendingLinkage);
2711 LLVMSetSection (used, "llvm.metadata");
2715 * emit_get_method:
2717 * Emit a function mapping method indexes to their code
2719 static void
2720 emit_get_method (MonoLLVMModule *module)
2722 LLVMModuleRef lmodule = module->lmodule;
2723 LLVMValueRef func, switch_ins, m;
2724 LLVMBasicBlockRef entry_bb, fail_bb, bb, code_start_bb, code_end_bb;
2725 LLVMBasicBlockRef *bbs = NULL;
2726 LLVMTypeRef rtype;
2727 LLVMBuilderRef builder = LLVMCreateBuilder ();
2728 LLVMValueRef table = NULL;
2729 char *name;
2730 int i;
2731 gboolean emit_table = FALSE;
2733 #ifdef TARGET_WASM
2735 * Emit a table of functions instead of a switch statement,
2736 * its very efficient on wasm. This might be usable on
2737 * other platforms too.
2739 emit_table = TRUE;
2740 #endif
2742 rtype = LLVMPointerType (LLVMInt8Type (), 0);
2744 if (emit_table) {
2745 LLVMTypeRef table_type;
2746 LLVMValueRef *table_elems;
2747 char *table_name;
2749 int table_len = module->max_method_idx + 1;
2750 table_type = LLVMArrayType (rtype, table_len);
2751 table_name = g_strdup_printf ("%s_method_table", module->assembly->aname.name);
2752 table = LLVMAddGlobal (lmodule, table_type, table_name);
2753 table_elems = g_new0 (LLVMValueRef, table_len);
2754 for (i = 0; i < table_len; ++i) {
2755 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_lmethod, GINT_TO_POINTER (i));
2756 if (m)
2757 table_elems [i] = LLVMBuildBitCast (builder, m, rtype, "");
2758 else
2759 table_elems [i] = LLVMConstNull (rtype);
2761 LLVMSetInitializer (table, LLVMConstArray (LLVMPointerType (LLVMInt8Type (), 0), table_elems, table_len));
2765 * Emit a switch statement. Emitting a table of function addresses is smaller/faster,
2766 * but generating code seems safer.
2768 func = LLVMAddFunction (lmodule, module->get_method_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
2769 LLVMSetLinkage (func, LLVMExternalLinkage);
2770 LLVMSetVisibility (func, LLVMHiddenVisibility);
2771 mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
2772 module->get_method = func;
2774 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2777 * Return llvm_code_start/llvm_code_end when called with -1/-2.
2778 * Hopefully, the toolchain doesn't reorder these functions. If it does,
2779 * then we will have to find another solution.
2782 name = g_strdup_printf ("BB_CODE_START");
2783 code_start_bb = LLVMAppendBasicBlock (func, name);
2784 g_free (name);
2785 LLVMPositionBuilderAtEnd (builder, code_start_bb);
2786 LLVMBuildRet (builder, LLVMBuildBitCast (builder, module->code_start, rtype, ""));
2788 name = g_strdup_printf ("BB_CODE_END");
2789 code_end_bb = LLVMAppendBasicBlock (func, name);
2790 g_free (name);
2791 LLVMPositionBuilderAtEnd (builder, code_end_bb);
2792 LLVMBuildRet (builder, LLVMBuildBitCast (builder, module->code_end, rtype, ""));
2794 if (emit_table) {
2796 * switch (index) {
2797 * case -1: return code_start;
2798 * case -2: return code_end;
2799 * default: return method_table [index];
2801 LLVMBasicBlockRef default_bb = LLVMAppendBasicBlock (func, "DEFAULT");
2802 LLVMPositionBuilderAtEnd (builder, default_bb);
2803 LLVMValueRef base = table;
2804 LLVMValueRef indexes [2];
2805 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
2806 indexes [1] = LLVMGetParam (func, 0);
2807 LLVMValueRef addr = LLVMBuildGEP (builder, base, indexes, 2, "");
2808 LLVMValueRef res = mono_llvm_build_load (builder, addr, "", FALSE);
2809 LLVMBuildRet (builder, res);
2811 LLVMPositionBuilderAtEnd (builder, entry_bb);
2813 switch_ins = LLVMBuildSwitch (builder, LLVMGetParam (func, 0), default_bb, 0);
2814 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), -1, FALSE), code_start_bb);
2815 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), -2, FALSE), code_end_bb);
2816 } else {
2817 bbs = g_new0 (LLVMBasicBlockRef, module->max_method_idx + 1);
2818 for (i = 0; i < module->max_method_idx + 1; ++i) {
2819 name = g_strdup_printf ("BB_%d", i);
2820 bb = LLVMAppendBasicBlock (func, name);
2821 g_free (name);
2822 bbs [i] = bb;
2824 LLVMPositionBuilderAtEnd (builder, bb);
2826 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_lmethod, GINT_TO_POINTER (i));
2827 if (m)
2828 LLVMBuildRet (builder, LLVMBuildBitCast (builder, m, rtype, ""));
2829 else
2830 LLVMBuildRet (builder, LLVMConstNull (rtype));
2833 fail_bb = LLVMAppendBasicBlock (func, "FAIL");
2834 LLVMPositionBuilderAtEnd (builder, fail_bb);
2835 LLVMBuildRet (builder, LLVMConstNull (rtype));
2837 LLVMPositionBuilderAtEnd (builder, entry_bb);
2839 switch_ins = LLVMBuildSwitch (builder, LLVMGetParam (func, 0), fail_bb, 0);
2840 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), -1, FALSE), code_start_bb);
2841 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), -2, FALSE), code_end_bb);
2842 for (i = 0; i < module->max_method_idx + 1; ++i) {
2843 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i, FALSE), bbs [i]);
2847 mark_as_used (module, func);
2849 LLVMDisposeBuilder (builder);
2853 * emit_get_unbox_tramp:
2855 * Emit a function mapping method indexes to their unbox trampoline
2857 static void
2858 emit_get_unbox_tramp (MonoLLVMModule *module)
2860 LLVMModuleRef lmodule = module->lmodule;
2861 LLVMValueRef func, switch_ins, m;
2862 LLVMBasicBlockRef entry_bb, fail_bb, bb;
2863 LLVMBasicBlockRef *bbs;
2864 LLVMTypeRef rtype;
2865 LLVMBuilderRef builder = LLVMCreateBuilder ();
2866 char *name;
2867 int i;
2868 gboolean emit_table = FALSE;
2870 /* Similar to emit_get_method () */
2872 #ifndef TARGET_WATCHOS
2873 emit_table = TRUE;
2874 #endif
2876 rtype = LLVMPointerType (LLVMInt8Type (), 0);
2878 if (emit_table) {
2879 // About 10% of methods have an unbox tramp, so emit a table of indexes for them
2880 // that the runtime can search using a binary search
2881 int len = 0;
2882 for (i = 0; i < module->max_method_idx + 1; ++i) {
2883 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_unbox_tramp, GINT_TO_POINTER (i));
2884 if (m)
2885 len ++;
2888 LLVMTypeRef table_type, elemtype;
2889 LLVMValueRef *table_elems;
2890 LLVMValueRef table;
2891 char *table_name;
2892 int table_len;
2893 int elemsize;
2895 table_len = len;
2896 elemsize = module->max_method_idx < 65000 ? 2 : 4;
2898 // The index table
2899 elemtype = elemsize == 2 ? LLVMInt16Type () : LLVMInt32Type ();
2900 table_type = LLVMArrayType (elemtype, table_len);
2901 table_name = g_strdup_printf ("%s_unbox_tramp_indexes", module->assembly->aname.name);
2902 table = LLVMAddGlobal (lmodule, table_type, table_name);
2903 table_elems = g_new0 (LLVMValueRef, table_len);
2904 int idx = 0;
2905 for (i = 0; i < module->max_method_idx + 1; ++i) {
2906 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_unbox_tramp, GINT_TO_POINTER (i));
2907 if (m)
2908 table_elems [idx ++] = LLVMConstInt (elemtype, i, FALSE);
2910 LLVMSetInitializer (table, LLVMConstArray (elemtype, table_elems, table_len));
2911 module->unbox_tramp_indexes = table;
2913 // The trampoline table
2914 elemtype = rtype;
2915 table_type = LLVMArrayType (elemtype, table_len);
2916 table_name = g_strdup_printf ("%s_unbox_trampolines", module->assembly->aname.name);
2917 table = LLVMAddGlobal (lmodule, table_type, table_name);
2918 table_elems = g_new0 (LLVMValueRef, table_len);
2919 idx = 0;
2920 for (i = 0; i < module->max_method_idx + 1; ++i) {
2921 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_unbox_tramp, GINT_TO_POINTER (i));
2922 if (m)
2923 table_elems [idx ++] = LLVMBuildBitCast (builder, m, rtype, "");
2925 LLVMSetInitializer (table, LLVMConstArray (elemtype, table_elems, table_len));
2926 module->unbox_trampolines = table;
2928 module->unbox_tramp_num = table_len;
2929 module->unbox_tramp_elemsize = elemsize;
2930 return;
2933 func = LLVMAddFunction (lmodule, module->get_unbox_tramp_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
2934 LLVMSetLinkage (func, LLVMExternalLinkage);
2935 LLVMSetVisibility (func, LLVMHiddenVisibility);
2936 mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
2937 module->get_unbox_tramp = func;
2939 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2941 bbs = g_new0 (LLVMBasicBlockRef, module->max_method_idx + 1);
2942 for (i = 0; i < module->max_method_idx + 1; ++i) {
2943 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_unbox_tramp, GINT_TO_POINTER (i));
2944 if (!m)
2945 continue;
2947 name = g_strdup_printf ("BB_%d", i);
2948 bb = LLVMAppendBasicBlock (func, name);
2949 g_free (name);
2950 bbs [i] = bb;
2952 LLVMPositionBuilderAtEnd (builder, bb);
2954 LLVMBuildRet (builder, LLVMBuildBitCast (builder, m, rtype, ""));
2957 fail_bb = LLVMAppendBasicBlock (func, "FAIL");
2958 LLVMPositionBuilderAtEnd (builder, fail_bb);
2959 LLVMBuildRet (builder, LLVMConstNull (rtype));
2961 LLVMPositionBuilderAtEnd (builder, entry_bb);
2963 switch_ins = LLVMBuildSwitch (builder, LLVMGetParam (func, 0), fail_bb, 0);
2964 for (i = 0; i < module->max_method_idx + 1; ++i) {
2965 m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_unbox_tramp, GINT_TO_POINTER (i));
2966 if (!m)
2967 continue;
2969 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i, FALSE), bbs [i]);
2972 mark_as_used (module, func);
2973 LLVMDisposeBuilder (builder);
2976 /* Add a function to mark the beginning of LLVM code */
2977 static void
2978 emit_llvm_code_start (MonoLLVMModule *module)
2980 LLVMModuleRef lmodule = module->lmodule;
2981 LLVMValueRef func;
2982 LLVMBasicBlockRef entry_bb;
2983 LLVMBuilderRef builder;
2985 func = LLVMAddFunction (lmodule, "llvm_code_start", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
2986 LLVMSetLinkage (func, LLVMInternalLinkage);
2987 mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
2988 module->code_start = func;
2989 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
2990 builder = LLVMCreateBuilder ();
2991 LLVMPositionBuilderAtEnd (builder, entry_bb);
2992 LLVMBuildRetVoid (builder);
2993 LLVMDisposeBuilder (builder);
2996 static LLVMValueRef
2997 emit_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
2999 LLVMModuleRef lmodule = module->lmodule;
3000 LLVMValueRef func, indexes [2], got_entry_addr, args [16], callee;
3001 LLVMBasicBlockRef entry_bb;
3002 LLVMBuilderRef builder;
3003 LLVMTypeRef sig;
3004 MonoJumpInfo *ji;
3005 int got_offset;
3006 const char *wrapper_name = mono_marshal_get_aot_init_wrapper_name (subtype);
3007 char *name = g_strdup_printf ("%s%s", module->global_prefix, wrapper_name);
3008 const char *icall_name = NULL;
3010 switch (subtype) {
3011 case AOT_INIT_METHOD:
3012 icall_name = "mini_llvm_init_method";
3013 func = LLVMAddFunction (lmodule, name, LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE));
3014 sig = LLVMFunctionType2 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), FALSE);
3015 break;
3016 case AOT_INIT_METHOD_GSHARED_MRGCTX:
3017 icall_name = "mini_llvm_init_gshared_method_mrgctx"; // Deliberate fall-through
3018 case AOT_INIT_METHOD_GSHARED_VTABLE:
3019 /* mrgctx/vtable */
3020 if (!icall_name)
3021 icall_name = "mini_llvm_init_gshared_method_vtable";
3022 func = LLVMAddFunction (lmodule, name, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), IntPtrType (), FALSE));
3023 sig = LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), IntPtrType (), FALSE);
3024 break;
3025 case AOT_INIT_METHOD_GSHARED_THIS:
3026 icall_name = "mini_llvm_init_gshared_method_this";
3027 func = LLVMAddFunction (lmodule, name, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), ObjRefType (), FALSE));
3028 sig = LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), ObjRefType (), FALSE);
3029 break;
3030 default:
3031 g_assert_not_reached ();
3034 g_assert (icall_name);
3035 LLVMSetLinkage (func, LLVMInternalLinkage);
3037 mono_llvm_add_func_attr (func, LLVM_ATTR_NO_INLINE);
3039 // FIXME? Using this with mono debug info causes unwind.c to explode when
3040 // parsing some of these registers saved by this call. Can't unwind through it.
3041 // Not an issue with llvmonly because it doesn't use that DWARF
3042 if (module->llvm_only)
3043 set_preserveall_cc (func);
3044 else
3045 LLVMSetFunctionCallConv (func, LLVMMono1CallConv);
3047 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
3048 builder = LLVMCreateBuilder ();
3049 LLVMPositionBuilderAtEnd (builder, entry_bb);
3051 /* get_aotconst */
3052 ji = g_new0 (MonoJumpInfo, 1);
3053 ji->type = MONO_PATCH_INFO_AOT_MODULE;
3054 ji = mono_aot_patch_info_dup (ji);
3055 got_offset = compute_aot_got_offset (module, ji, IntPtrType ());
3056 module->max_got_offset = MAX (module->max_got_offset, got_offset);
3057 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
3058 indexes [1] = LLVMConstInt (LLVMInt32Type (), got_offset, FALSE);
3059 got_entry_addr = LLVMBuildGEP (builder, module->got_var, indexes, 2, "");
3060 args [0] = LLVMBuildPtrToInt (builder, LLVMBuildLoad (builder, got_entry_addr, ""), IntPtrType (), "");
3061 args [1] = LLVMGetParam (func, 0);
3062 if (subtype)
3063 args [2] = LLVMGetParam (func, 1);
3065 ji = g_new0 (MonoJumpInfo, 1);
3066 ji->type = MONO_PATCH_INFO_JIT_ICALL;
3067 ji->data.name = icall_name;
3068 ji = mono_aot_patch_info_dup (ji);
3069 got_offset = compute_aot_got_offset (module, ji, sig);
3070 module->max_got_offset = MAX (module->max_got_offset, got_offset);
3071 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
3072 indexes [1] = LLVMConstInt (LLVMInt32Type (), got_offset, FALSE);
3073 got_entry_addr = LLVMBuildGEP (builder, module->got_var, indexes, 2, "");
3074 callee = LLVMBuildLoad (builder, got_entry_addr, "");
3075 callee = LLVMBuildBitCast (builder, callee, LLVMPointerType (sig, 0), "");
3076 LLVMBuildCall (builder, callee, args, LLVMCountParamTypes (sig), "");
3078 // Set the inited flag
3079 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
3080 indexes [1] = LLVMGetParam (func, 0);
3081 LLVMBuildStore (builder, LLVMConstInt (LLVMInt8Type (), 1, FALSE), LLVMBuildGEP (builder, module->inited_var, indexes, 2, ""));
3083 LLVMBuildRetVoid (builder);
3085 LLVMVerifyFunction(func, LLVMAbortProcessAction);
3086 LLVMDisposeBuilder (builder);
3087 return func;
3091 * Emit wrappers around the C icalls used to initialize llvm methods, to
3092 * make the calling code smaller and to enable usage of the llvm
3093 * PreserveAll calling convention.
3095 static void
3096 emit_init_icall_wrappers (MonoLLVMModule *module)
3098 module->init_method = emit_init_icall_wrapper (module, AOT_INIT_METHOD);
3099 module->init_method_gshared_mrgctx = emit_init_icall_wrapper (module, AOT_INIT_METHOD_GSHARED_MRGCTX);
3100 module->init_method_gshared_this = emit_init_icall_wrapper (module, AOT_INIT_METHOD_GSHARED_THIS);
3101 module->init_method_gshared_vtable = emit_init_icall_wrapper (module, AOT_INIT_METHOD_GSHARED_VTABLE);
3104 static LLVMValueRef
3105 get_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
3107 switch (subtype) {
3108 case AOT_INIT_METHOD:
3109 return module->init_method;
3110 case AOT_INIT_METHOD_GSHARED_MRGCTX:
3111 return module->init_method_gshared_mrgctx;
3112 case AOT_INIT_METHOD_GSHARED_THIS:
3113 return module->init_method_gshared_this;
3114 case AOT_INIT_METHOD_GSHARED_VTABLE:
3115 return module->init_method_gshared_vtable;
3116 default:
3117 g_assert_not_reached ();
3121 static void
3122 emit_gc_safepoint_poll (MonoLLVMModule *module)
3124 LLVMModuleRef lmodule = module->lmodule;
3125 LLVMValueRef func, indexes [2], got_entry_addr, flag_addr, val_ptr, callee, val, cmp;
3126 LLVMBasicBlockRef entry_bb, poll_bb, exit_bb;
3127 LLVMBuilderRef builder;
3128 LLVMTypeRef sig;
3129 MonoJumpInfo *ji;
3130 int got_offset;
3132 sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
3133 func = mono_llvm_get_or_insert_gc_safepoint_poll (lmodule);
3134 mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
3135 LLVMSetLinkage (func, LLVMWeakODRLinkage);
3136 // set_preserveall_cc (func);
3138 entry_bb = LLVMAppendBasicBlock (func, "gc.safepoint_poll.entry");
3139 poll_bb = LLVMAppendBasicBlock (func, "gc.safepoint_poll.poll");
3140 exit_bb = LLVMAppendBasicBlock (func, "gc.safepoint_poll.exit");
3142 builder = LLVMCreateBuilder ();
3144 /* entry: */
3145 LLVMPositionBuilderAtEnd (builder, entry_bb);
3147 /* get_aotconst */
3148 ji = g_new0 (MonoJumpInfo, 1);
3149 ji->type = MONO_PATCH_INFO_GC_SAFE_POINT_FLAG;
3150 ji = mono_aot_patch_info_dup (ji);
3151 got_offset = compute_aot_got_offset (module, ji, IntPtrType ());
3152 module->max_got_offset = MAX (module->max_got_offset, got_offset);
3153 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
3154 indexes [1] = LLVMConstInt (LLVMInt32Type (), got_offset, FALSE);
3155 got_entry_addr = LLVMBuildGEP (builder, module->got_var, indexes, 2, "");
3156 flag_addr = LLVMBuildLoad (builder, got_entry_addr, "");
3157 val_ptr = LLVMBuildLoad (builder, flag_addr, "");
3158 val = LLVMBuildPtrToInt (builder, val_ptr, IntPtrType (), "");
3159 cmp = LLVMBuildICmp (builder, LLVMIntEQ, val, LLVMConstNull (LLVMTypeOf (val)), "");
3160 LLVMBuildCondBr (builder, cmp, exit_bb, poll_bb);
3162 /* poll: */
3163 LLVMPositionBuilderAtEnd(builder, poll_bb);
3165 ji = g_new0 (MonoJumpInfo, 1);
3166 ji->type = MONO_PATCH_INFO_JIT_ICALL;
3167 ji->data.name = "mono_threads_state_poll";
3168 ji = mono_aot_patch_info_dup (ji);
3169 got_offset = compute_aot_got_offset (module, ji, sig);
3170 module->max_got_offset = MAX (module->max_got_offset, got_offset);
3171 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
3172 indexes [1] = LLVMConstInt (LLVMInt32Type (), got_offset, FALSE);
3173 got_entry_addr = LLVMBuildGEP (builder, module->got_var, indexes, 2, "");
3174 callee = LLVMBuildLoad (builder, got_entry_addr, "");
3175 callee = LLVMBuildBitCast (builder, callee, LLVMPointerType (sig, 0), "");
3176 LLVMBuildCall (builder, callee, NULL, 0, "");
3177 LLVMBuildBr(builder, exit_bb);
3179 /* exit: */
3180 LLVMPositionBuilderAtEnd(builder, exit_bb);
3182 LLVMBuildRetVoid (builder);
3184 LLVMVerifyFunction(func, LLVMAbortProcessAction);
3185 LLVMDisposeBuilder (builder);
3188 static void
3189 emit_llvm_code_end (MonoLLVMModule *module)
3191 LLVMModuleRef lmodule = module->lmodule;
3192 LLVMValueRef func;
3193 LLVMBasicBlockRef entry_bb;
3194 LLVMBuilderRef builder;
3196 func = LLVMAddFunction (lmodule, "llvm_code_end", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
3197 LLVMSetLinkage (func, LLVMInternalLinkage);
3198 mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
3199 module->code_end = func;
3200 entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
3201 builder = LLVMCreateBuilder ();
3202 LLVMPositionBuilderAtEnd (builder, entry_bb);
3203 LLVMBuildRetVoid (builder);
3204 LLVMDisposeBuilder (builder);
3207 static void
3208 emit_div_check (EmitContext *ctx, LLVMBuilderRef builder, MonoBasicBlock *bb, MonoInst *ins, LLVMValueRef lhs, LLVMValueRef rhs)
3210 gboolean need_div_check = ctx->cfg->backend->need_div_check;
3212 if (bb->region)
3213 /* LLVM doesn't know that these can throw an exception since they are not called through an intrinsic */
3214 need_div_check = TRUE;
3216 if (!need_div_check)
3217 return;
3219 switch (ins->opcode) {
3220 case OP_IDIV:
3221 case OP_LDIV:
3222 case OP_IREM:
3223 case OP_LREM:
3224 case OP_IDIV_UN:
3225 case OP_LDIV_UN:
3226 case OP_IREM_UN:
3227 case OP_LREM_UN:
3228 case OP_IDIV_IMM:
3229 case OP_LDIV_IMM:
3230 case OP_IREM_IMM:
3231 case OP_LREM_IMM:
3232 case OP_IDIV_UN_IMM:
3233 case OP_LDIV_UN_IMM:
3234 case OP_IREM_UN_IMM:
3235 case OP_LREM_UN_IMM: {
3236 LLVMValueRef cmp;
3237 gboolean is_signed = (ins->opcode == OP_IDIV || ins->opcode == OP_LDIV || ins->opcode == OP_IREM || ins->opcode == OP_LREM ||
3238 ins->opcode == OP_IDIV_IMM || ins->opcode == OP_LDIV_IMM || ins->opcode == OP_IREM_IMM || ins->opcode == OP_LREM_IMM);
3240 cmp = LLVMBuildICmp (builder, LLVMIntEQ, rhs, LLVMConstInt (LLVMTypeOf (rhs), 0, FALSE), "");
3241 emit_cond_system_exception (ctx, bb, "DivideByZeroException", cmp);
3242 if (!ctx_ok (ctx))
3243 break;
3244 builder = ctx->builder;
3246 /* b == -1 && a == 0x80000000 */
3247 if (is_signed) {
3248 LLVMValueRef c = (LLVMTypeOf (lhs) == LLVMInt32Type ()) ? LLVMConstInt (LLVMTypeOf (lhs), 0x80000000, FALSE) : LLVMConstInt (LLVMTypeOf (lhs), 0x8000000000000000LL, FALSE);
3249 LLVMValueRef cond1 = LLVMBuildICmp (builder, LLVMIntEQ, rhs, LLVMConstInt (LLVMTypeOf (rhs), -1, FALSE), "");
3250 LLVMValueRef cond2 = LLVMBuildICmp (builder, LLVMIntEQ, lhs, c, "");
3252 cmp = LLVMBuildICmp (builder, LLVMIntEQ, LLVMBuildAnd (builder, cond1, cond2, ""), LLVMConstInt (LLVMInt1Type (), 1, FALSE), "");
3253 emit_cond_system_exception (ctx, bb, "OverflowException", cmp);
3254 if (!ctx_ok (ctx))
3255 break;
3256 builder = ctx->builder;
3258 break;
3260 default:
3261 break;
3266 * emit_init_method:
3268 * Emit code to initialize the GOT slots used by the method.
3270 static void
3271 emit_init_method (EmitContext *ctx)
3273 LLVMValueRef indexes [16], args [16], callee;
3274 LLVMValueRef inited_var, cmp, call;
3275 LLVMBasicBlockRef inited_bb, notinited_bb;
3276 LLVMBuilderRef builder = ctx->builder;
3277 MonoCompile *cfg = ctx->cfg;
3279 ctx->module->max_inited_idx = MAX (ctx->module->max_inited_idx, cfg->method_index);
3281 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
3282 indexes [1] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, FALSE);
3283 inited_var = LLVMBuildLoad (builder, LLVMBuildGEP (builder, ctx->module->inited_var, indexes, 2, ""), "is_inited");
3285 //WASM doesn't support the "llvm.expect.i8" intrinsic
3286 #ifndef TARGET_WASM
3287 args [0] = inited_var;
3288 args [1] = LLVMConstInt (LLVMInt8Type (), 1, FALSE);
3289 inited_var = LLVMBuildCall (ctx->builder, get_intrins (ctx, INTRINS_EXPECT_I8), args, 2, "");
3290 #endif
3292 cmp = LLVMBuildICmp (builder, LLVMIntEQ, inited_var, LLVMConstInt (LLVMTypeOf (inited_var), 0, FALSE), "");
3294 inited_bb = ctx->inited_bb;
3295 notinited_bb = gen_bb (ctx, "NOTINITED_BB");
3297 ctx->cfg->llvmonly_init_cond = LLVMBuildCondBr (ctx->builder, cmp, notinited_bb, inited_bb);
3299 builder = ctx->builder = create_builder (ctx);
3300 LLVMPositionBuilderAtEnd (ctx->builder, notinited_bb);
3302 // FIXME: Cache
3303 if (ctx->rgctx_arg && ((cfg->method->is_inflated && mono_method_get_context (cfg->method)->method_inst) ||
3304 mini_method_is_default_method (cfg->method))) {
3305 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
3306 args [1] = convert (ctx, ctx->rgctx_arg, IntPtrType ());
3307 callee = ctx->module->init_method_gshared_mrgctx;
3308 call = LLVMBuildCall (builder, callee, args, 2, "");
3309 } else if (ctx->rgctx_arg) {
3310 /* A vtable is passed as the rgctx argument */
3311 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
3312 args [1] = convert (ctx, ctx->rgctx_arg, IntPtrType ());
3313 callee = ctx->module->init_method_gshared_vtable;
3314 call = LLVMBuildCall (builder, callee, args, 2, "");
3315 } else if (cfg->gshared) {
3316 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
3317 args [1] = convert (ctx, ctx->this_arg, ObjRefType ());
3318 callee = ctx->module->init_method_gshared_this;
3319 call = LLVMBuildCall (builder, callee, args, 2, "");
3320 } else {
3321 args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
3322 callee = ctx->module->init_method;
3323 call = LLVMBuildCall (builder, callee, args, 1, "");
3327 * This enables llvm to keep arguments in their original registers/
3328 * scratch registers, since the call will not clobber them.
3331 if (ctx->llvm_only)
3332 set_call_preserveall_cc (call);
3333 else
3334 LLVMSetInstructionCallConv (call, LLVMMono1CallConv);
3336 LLVMBuildBr (builder, inited_bb);
3337 ctx->bblocks [cfg->bb_entry->block_num].end_bblock = inited_bb;
3339 builder = ctx->builder = create_builder (ctx);
3340 LLVMPositionBuilderAtEnd (ctx->builder, inited_bb);
3343 static void
3344 emit_unbox_tramp (EmitContext *ctx, const char *method_name, LLVMTypeRef method_type, LLVMValueRef method, int method_index)
3347 * Emit unbox trampoline using a tailcall
3349 LLVMValueRef tramp, call, *args;
3350 LLVMBuilderRef builder;
3351 LLVMBasicBlockRef lbb;
3352 LLVMCallInfo *linfo;
3353 char *tramp_name;
3354 int i, nargs;
3356 tramp_name = g_strdup_printf ("ut_%s", method_name);
3357 tramp = LLVMAddFunction (ctx->module->lmodule, tramp_name, method_type);
3358 LLVMSetLinkage (tramp, LLVMInternalLinkage);
3359 mono_llvm_add_func_attr (tramp, LLVM_ATTR_OPTIMIZE_FOR_SIZE);
3360 //mono_llvm_add_func_attr (tramp, LLVM_ATTR_NO_UNWIND);
3361 linfo = ctx->linfo;
3362 // FIXME: Reduce code duplication with mono_llvm_compile_method () etc.
3363 if (!ctx->llvm_only && ctx->rgctx_arg_pindex != -1)
3364 mono_llvm_add_param_attr (LLVMGetParam (tramp, ctx->rgctx_arg_pindex), LLVM_ATTR_IN_REG);
3365 if (ctx->cfg->vret_addr) {
3366 LLVMSetValueName (LLVMGetParam (tramp, linfo->vret_arg_pindex), "vret");
3367 if (linfo->ret.storage == LLVMArgVtypeByRef) {
3368 mono_llvm_add_param_attr (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVM_ATTR_STRUCT_RET);
3369 mono_llvm_add_param_attr (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVM_ATTR_NO_ALIAS);
3373 lbb = LLVMAppendBasicBlock (tramp, "");
3374 builder = LLVMCreateBuilder ();
3375 LLVMPositionBuilderAtEnd (builder, lbb);
3377 nargs = LLVMCountParamTypes (method_type);
3378 args = g_new0 (LLVMValueRef, nargs);
3379 for (i = 0; i < nargs; ++i) {
3380 args [i] = LLVMGetParam (tramp, i);
3381 if (i == ctx->this_arg_pindex) {
3382 LLVMTypeRef arg_type = LLVMTypeOf (args [i]);
3384 args [i] = LLVMBuildPtrToInt (builder, args [i], IntPtrType (), "");
3385 args [i] = LLVMBuildAdd (builder, args [i], LLVMConstInt (IntPtrType (), MONO_ABI_SIZEOF (MonoObject), FALSE), "");
3386 args [i] = LLVMBuildIntToPtr (builder, args [i], arg_type, "");
3389 call = LLVMBuildCall (builder, method, args, nargs, "");
3390 if (!ctx->llvm_only && ctx->rgctx_arg_pindex != -1)
3391 mono_llvm_add_instr_attr (call, 1 + ctx->rgctx_arg_pindex, LLVM_ATTR_IN_REG);
3392 if (linfo->ret.storage == LLVMArgVtypeByRef)
3393 mono_llvm_add_instr_attr (call, 1 + linfo->vret_arg_pindex, LLVM_ATTR_STRUCT_RET);
3395 // FIXME: This causes assertions in clang
3396 //mono_llvm_set_must_tailcall (call);
3397 if (LLVMGetReturnType (method_type) == LLVMVoidType ())
3398 LLVMBuildRetVoid (builder);
3399 else
3400 LLVMBuildRet (builder, call);
3402 g_hash_table_insert (ctx->module->idx_to_unbox_tramp, GINT_TO_POINTER (method_index), tramp);
3403 LLVMDisposeBuilder (builder);
3407 * emit_entry_bb:
3409 * Emit code to load/convert arguments.
3411 static void
3412 emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
3414 int i, j, pindex;
3415 MonoCompile *cfg = ctx->cfg;
3416 MonoMethodSignature *sig = ctx->sig;
3417 LLVMCallInfo *linfo = ctx->linfo;
3418 MonoBasicBlock *bb;
3419 char **names;
3421 LLVMBuilderRef old_builder = ctx->builder;
3422 ctx->builder = builder;
3424 ctx->alloca_builder = create_builder (ctx);
3427 * Handle indirect/volatile variables by allocating memory for them
3428 * using 'alloca', and storing their address in a temporary.
3430 for (i = 0; i < cfg->num_varinfo; ++i) {
3431 MonoInst *var = cfg->varinfo [i];
3432 LLVMTypeRef vtype;
3434 if (var->opcode == OP_GSHAREDVT_LOCAL || var->opcode == OP_GSHAREDVT_ARG_REGOFFSET) {
3435 } 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))) {
3436 vtype = type_to_llvm_type (ctx, var->inst_vtype);
3437 if (!ctx_ok (ctx))
3438 return;
3439 /* Could be already created by an OP_VPHI */
3440 if (!ctx->addresses [var->dreg]) {
3441 ctx->addresses [var->dreg] = build_alloca (ctx, var->inst_vtype);
3442 //LLVMSetValueName (ctx->addresses [var->dreg], g_strdup_printf ("vreg_loc_%d", var->dreg));
3444 ctx->vreg_cli_types [var->dreg] = var->inst_vtype;
3448 names = g_new (char *, sig->param_count);
3449 mono_method_get_param_names (cfg->method, (const char **) names);
3451 for (i = 0; i < sig->param_count; ++i) {
3452 LLVMArgInfo *ainfo = &linfo->args [i + sig->hasthis];
3453 int reg = cfg->args [i + sig->hasthis]->dreg;
3454 char *name;
3456 pindex = ainfo->pindex;
3458 switch (ainfo->storage) {
3459 case LLVMArgVtypeInReg:
3460 case LLVMArgAsFpArgs: {
3461 LLVMValueRef args [8];
3462 int j;
3464 pindex += ainfo->ndummy_fpargs;
3466 /* The argument is received as a set of int/fp arguments, store them into the real argument */
3467 memset (args, 0, sizeof (args));
3468 if (ainfo->storage == LLVMArgVtypeInReg) {
3469 args [0] = LLVMGetParam (ctx->lmethod, pindex);
3470 if (ainfo->pair_storage [1] != LLVMArgNone)
3471 args [1] = LLVMGetParam (ctx->lmethod, pindex + 1);
3472 } else {
3473 g_assert (ainfo->nslots <= 8);
3474 for (j = 0; j < ainfo->nslots; ++j)
3475 args [j] = LLVMGetParam (ctx->lmethod, pindex + j);
3477 ctx->addresses [reg] = build_alloca (ctx, ainfo->type);
3479 emit_args_to_vtype (ctx, builder, ainfo->type, ctx->addresses [reg], ainfo, args);
3481 if (ainfo->storage == LLVMArgVtypeInReg && MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (ainfo->type))) {
3482 /* Treat these as normal values */
3483 ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "");
3485 break;
3487 case LLVMArgVtypeByVal: {
3488 ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindex);
3490 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (ainfo->type))) {
3491 /* Treat these as normal values */
3492 ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "");
3494 break;
3496 case LLVMArgVtypeByRef: {
3497 /* The argument is passed by ref */
3498 ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindex);
3499 break;
3501 case LLVMArgAsIArgs: {
3502 LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
3503 int size;
3504 MonoType *t = mini_get_underlying_type (ainfo->type);
3506 /* The argument is received as an array of ints, store it into the real argument */
3507 ctx->addresses [reg] = build_alloca (ctx, t);
3509 size = mono_class_value_size (mono_class_from_mono_type_internal (t), NULL);
3510 if (size == 0) {
3511 } else if (size < TARGET_SIZEOF_VOID_P) {
3512 /* The upper bits of the registers might not be valid */
3513 LLVMValueRef val = LLVMBuildExtractValue (builder, arg, 0, "");
3514 LLVMValueRef dest = convert (ctx, ctx->addresses [reg], LLVMPointerType (LLVMIntType (size * 8), 0));
3515 LLVMBuildStore (ctx->builder, LLVMBuildTrunc (builder, val, LLVMIntType (size * 8), ""), dest);
3516 } else {
3517 LLVMBuildStore (ctx->builder, arg, convert (ctx, ctx->addresses [reg], LLVMPointerType (LLVMTypeOf (arg), 0)));
3519 break;
3521 case LLVMArgVtypeAsScalar:
3522 g_assert_not_reached ();
3523 break;
3524 case LLVMArgGsharedvtFixed: {
3525 /* These are non-gsharedvt arguments passed by ref, the rest of the IR treats them as scalars */
3526 LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
3528 if (names [i])
3529 name = g_strdup_printf ("arg_%s", names [i]);
3530 else
3531 name = g_strdup_printf ("arg_%d", i);
3533 ctx->values [reg] = LLVMBuildLoad (builder, convert (ctx, arg, LLVMPointerType (type_to_llvm_type (ctx, ainfo->type), 0)), name);
3534 break;
3536 case LLVMArgGsharedvtFixedVtype: {
3537 LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex);
3539 if (names [i])
3540 name = g_strdup_printf ("vtype_arg_%s", names [i]);
3541 else
3542 name = g_strdup_printf ("vtype_arg_%d", i);
3544 /* Non-gsharedvt vtype argument passed by ref, the rest of the IR treats it as a vtype */
3545 g_assert (ctx->addresses [reg]);
3546 LLVMSetValueName (ctx->addresses [reg], name);
3547 LLVMBuildStore (builder, LLVMBuildLoad (builder, convert (ctx, arg, LLVMPointerType (type_to_llvm_type (ctx, ainfo->type), 0)), ""), ctx->addresses [reg]);
3548 break;
3550 case LLVMArgGsharedvtVariable:
3551 /* The IR treats these as variables with addresses */
3552 ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, pindex);
3553 break;
3554 default:
3555 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));
3556 break;
3559 g_free (names);
3561 if (cfg->vret_addr)
3562 emit_volatile_store (ctx, cfg->vret_addr->dreg);
3563 if (sig->hasthis)
3564 emit_volatile_store (ctx, cfg->args [0]->dreg);
3565 for (i = 0; i < sig->param_count; ++i)
3566 if (!mini_type_is_vtype (sig->params [i]))
3567 emit_volatile_store (ctx, cfg->args [i + sig->hasthis]->dreg);
3569 if (sig->hasthis && !cfg->rgctx_var && cfg->gshared) {
3570 LLVMValueRef this_alloc;
3573 * The exception handling code needs the location where the this argument was
3574 * stored for gshared methods. We create a separate alloca to hold it, and mark it
3575 * with the "mono.this" custom metadata to tell llvm that it needs to save its
3576 * location into the LSDA.
3578 this_alloc = mono_llvm_build_alloca (builder, ThisType (), LLVMConstInt (LLVMInt32Type (), 1, FALSE), 0, "");
3579 /* This volatile store will keep the alloca alive */
3580 mono_llvm_build_store (builder, ctx->values [cfg->args [0]->dreg], this_alloc, TRUE, LLVM_BARRIER_NONE);
3582 set_metadata_flag (this_alloc, "mono.this");
3585 if (cfg->rgctx_var) {
3586 LLVMValueRef rgctx_alloc, store;
3589 * We handle the rgctx arg similarly to the this pointer.
3591 g_assert (ctx->addresses [cfg->rgctx_var->dreg]);
3592 rgctx_alloc = ctx->addresses [cfg->rgctx_var->dreg];
3593 /* This volatile store will keep the alloca alive */
3594 store = mono_llvm_build_store (builder, convert (ctx, ctx->rgctx_arg, IntPtrType ()), rgctx_alloc, TRUE, LLVM_BARRIER_NONE);
3596 set_metadata_flag (rgctx_alloc, "mono.this");
3599 /* Initialize the method if needed */
3600 if (cfg->compile_aot && !ctx->module->llvm_disable_self_init) {
3601 /* Emit a location for the initialization code */
3602 ctx->init_bb = gen_bb (ctx, "INIT_BB");
3603 ctx->inited_bb = gen_bb (ctx, "INITED_BB");
3605 LLVMBuildBr (ctx->builder, ctx->init_bb);
3606 builder = ctx->builder = create_builder (ctx);
3607 LLVMPositionBuilderAtEnd (ctx->builder, ctx->inited_bb);
3608 ctx->bblocks [cfg->bb_entry->block_num].end_bblock = ctx->inited_bb;
3611 /* Compute nesting between clauses */
3612 ctx->nested_in = (GSList**)mono_mempool_alloc0 (cfg->mempool, sizeof (GSList*) * cfg->header->num_clauses);
3613 for (i = 0; i < cfg->header->num_clauses; ++i) {
3614 for (j = 0; j < cfg->header->num_clauses; ++j) {
3615 MonoExceptionClause *clause1 = &cfg->header->clauses [i];
3616 MonoExceptionClause *clause2 = &cfg->header->clauses [j];
3618 if (i != j && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset)
3619 ctx->nested_in [i] = g_slist_prepend_mempool (cfg->mempool, ctx->nested_in [i], GINT_TO_POINTER (j));
3624 * For finally clauses, create an indicator variable telling OP_ENDFINALLY whenever
3625 * it needs to continue normally, or return back to the exception handling system.
3627 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3628 int clause_index;
3629 char name [128];
3631 if (!(bb->region != -1 && (bb->flags & BB_EXCEPTION_HANDLER)))
3632 continue;
3634 clause_index = MONO_REGION_CLAUSE_INDEX (bb->region);
3635 g_hash_table_insert (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)), bb);
3636 g_hash_table_insert (ctx->clause_to_handler, GINT_TO_POINTER (clause_index), bb);
3638 if (bb->in_scount == 0) {
3639 LLVMValueRef val;
3641 sprintf (name, "finally_ind_bb%d", bb->block_num);
3642 val = LLVMBuildAlloca (builder, LLVMInt32Type (), name);
3643 LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), val);
3645 ctx->bblocks [bb->block_num].finally_ind = val;
3646 } else {
3647 /* Create a variable to hold the exception var */
3648 if (!ctx->ex_var)
3649 ctx->ex_var = LLVMBuildAlloca (builder, ObjRefType (), "exvar");
3653 * Create a new bblock which CALL_HANDLER/landing pads can branch to, because branching to the
3654 * LLVM bblock containing a landing pad causes problems for the
3655 * LLVM optimizer passes.
3657 sprintf (name, "BB%d_CALL_HANDLER_TARGET", bb->block_num);
3658 ctx->bblocks [bb->block_num].call_handler_target_bb = LLVMAppendBasicBlock (ctx->lmethod, name);
3660 ctx->builder = old_builder;
3663 static gboolean
3664 needs_extra_arg (EmitContext *ctx, MonoMethod *method)
3666 WrapperInfo *info = NULL;
3669 * When targeting wasm, the caller and callee signature has to match exactly. This means
3670 * that every method which can be called indirectly need an extra arg since the caller
3671 * will call it through an ftnptr and will pass an extra arg.
3673 if (!ctx->cfg->llvm_only || !ctx->emit_dummy_arg)
3674 return FALSE;
3675 if (method->wrapper_type)
3676 info = mono_marshal_get_wrapper_info (method);
3678 switch (method->wrapper_type) {
3679 case MONO_WRAPPER_OTHER:
3680 if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG || info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG)
3681 /* Already have an explicit extra arg */
3682 return FALSE;
3683 break;
3684 case MONO_WRAPPER_MANAGED_TO_NATIVE:
3685 if (strstr (method->name, "icall_wrapper"))
3686 /* These are JIT icall wrappers which are only called from JITted code directly */
3687 return FALSE;
3688 /* Normal icalls can be virtual methods which need an extra arg */
3689 break;
3690 case MONO_WRAPPER_RUNTIME_INVOKE:
3691 case MONO_WRAPPER_ALLOC:
3692 case MONO_WRAPPER_CASTCLASS:
3693 case MONO_WRAPPER_WRITE_BARRIER:
3694 return FALSE;
3695 case MONO_WRAPPER_STELEMREF:
3696 if (info->subtype != WRAPPER_SUBTYPE_VIRTUAL_STELEMREF)
3697 return FALSE;
3698 break;
3699 case MONO_WRAPPER_MANAGED_TO_MANAGED:
3700 if (info->subtype == WRAPPER_SUBTYPE_STRING_CTOR)
3701 return FALSE;
3702 break;
3703 default:
3704 break;
3706 if (method->string_ctor)
3707 return FALSE;
3709 /* These are called from gsharedvt code with an indirect call which doesn't pass an extra arg */
3710 if (method->klass == mono_get_string_class () && (strstr (method->name, "memcpy") || strstr (method->name, "bzero")))
3711 return FALSE;
3712 return TRUE;
3715 static inline gboolean
3716 is_supported_callconv (EmitContext *ctx, MonoCallInst *call)
3718 #if defined(TARGET_WIN32) && defined(TARGET_AMD64)
3719 gboolean result = (call->signature->call_convention == MONO_CALL_DEFAULT) ||
3720 (call->signature->call_convention == MONO_CALL_C) ||
3721 (call->signature->call_convention == MONO_CALL_STDCALL);
3722 #else
3723 gboolean result = (call->signature->call_convention == MONO_CALL_DEFAULT) || ((call->signature->call_convention == MONO_CALL_C) && ctx->llvm_only);
3724 #endif
3725 return result;
3728 static void
3729 process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, MonoInst *ins)
3731 MonoCompile *cfg = ctx->cfg;
3732 LLVMValueRef *values = ctx->values;
3733 LLVMValueRef *addresses = ctx->addresses;
3734 MonoCallInst *call = (MonoCallInst*)ins;
3735 MonoMethodSignature *sig = call->signature;
3736 LLVMValueRef callee = NULL, lcall;
3737 LLVMValueRef *args;
3738 LLVMCallInfo *cinfo;
3739 GSList *l;
3740 int i, len, nargs;
3741 gboolean vretaddr;
3742 LLVMTypeRef llvm_sig;
3743 gpointer target;
3744 gboolean is_virtual, calli, preserveall;
3745 LLVMBuilderRef builder = *builder_ref;
3747 /* If both imt and rgctx arg are required, only pass the imt arg, the rgctx trampoline will pass the rgctx */
3748 if (call->imt_arg_reg)
3749 call->rgctx_arg_reg = 0;
3751 if (!is_supported_callconv (ctx, call)) {
3752 set_failure (ctx, "non-default callconv");
3753 return;
3756 cinfo = call->cinfo;
3757 g_assert (cinfo);
3758 if (call->rgctx_arg_reg)
3759 cinfo->rgctx_arg = TRUE;
3760 if (call->imt_arg_reg)
3761 cinfo->imt_arg = TRUE;
3762 if (!call->rgctx_arg_reg && call->method && needs_extra_arg (ctx, call->method))
3763 cinfo->dummy_arg = TRUE;
3765 vretaddr = (cinfo->ret.storage == LLVMArgVtypeRetAddr || cinfo->ret.storage == LLVMArgVtypeByRef || cinfo->ret.storage == LLVMArgGsharedvtFixed || cinfo->ret.storage == LLVMArgGsharedvtVariable || cinfo->ret.storage == LLVMArgGsharedvtFixedVtype);
3767 llvm_sig = sig_to_llvm_sig_full (ctx, sig, cinfo);
3768 if (!ctx_ok (ctx))
3769 return;
3771 int const opcode = ins->opcode;
3773 is_virtual = opcode == OP_VOIDCALL_MEMBASE || opcode == OP_CALL_MEMBASE
3774 || opcode == OP_VCALL_MEMBASE || opcode == OP_LCALL_MEMBASE
3775 || opcode == OP_FCALL_MEMBASE || opcode == OP_RCALL_MEMBASE
3776 || opcode == OP_TAILCALL_MEMBASE;
3777 calli = !call->fptr_is_patch && (opcode == OP_VOIDCALL_REG || opcode == OP_CALL_REG
3778 || opcode == OP_VCALL_REG || opcode == OP_LCALL_REG || opcode == OP_FCALL_REG
3779 || opcode == OP_RCALL_REG || opcode == OP_TAILCALL_REG);
3781 /* Unused */
3782 preserveall = FALSE;
3784 /* FIXME: Avoid creating duplicate methods */
3786 if (ins->flags & MONO_INST_HAS_METHOD) {
3787 if (is_virtual) {
3788 callee = NULL;
3789 } else {
3790 if (cfg->compile_aot) {
3791 callee = get_callee (ctx, llvm_sig, MONO_PATCH_INFO_METHOD, call->method);
3792 if (!callee) {
3793 set_failure (ctx, "can't encode patch");
3794 return;
3796 } else {
3797 ERROR_DECL (error);
3798 static int tramp_index;
3799 char *name;
3801 name = g_strdup_printf ("tramp_%d", tramp_index);
3802 tramp_index ++;
3804 #if LLVM_API_VERSION > 100
3806 * Use our trampoline infrastructure for lazy compilation instead of llvm's.
3807 * Make all calls through a global. The address of the global will be saved in
3808 * MonoJitDomainInfo.llvm_jit_callees and updated when the method it refers to is
3809 * compiled.
3811 LLVMValueRef tramp_var = (LLVMValueRef)g_hash_table_lookup (ctx->jit_callees, call->method);
3812 if (!tramp_var) {
3813 target =
3814 mono_create_jit_trampoline (mono_domain_get (),
3815 call->method, error);
3816 if (!is_ok (error)) {
3817 set_failure (ctx, mono_error_get_message (error));
3818 mono_error_cleanup (error);
3819 return;
3822 tramp_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (llvm_sig, 0), name);
3823 LLVMSetInitializer (tramp_var, LLVMConstIntToPtr (LLVMConstInt (LLVMInt64Type (), (guint64)(size_t)target, FALSE), LLVMPointerType (llvm_sig, 0)));
3824 LLVMSetLinkage (tramp_var, LLVMExternalLinkage);
3825 g_hash_table_insert (ctx->jit_callees, call->method, tramp_var);
3827 callee = LLVMBuildLoad (builder, tramp_var, "");
3828 #else
3829 g_assert_not_reached ();
3830 #endif
3834 if (!cfg->llvm_only && call->method && strstr (m_class_get_name (call->method->klass), "AsyncVoidMethodBuilder")) {
3835 /* LLVM miscompiles async methods */
3836 set_failure (ctx, "#13734");
3837 return;
3839 } else if (calli) {
3840 } else {
3841 MonoJitICallInfo *info = mono_find_jit_icall_by_addr (call->fptr);
3843 if (info) {
3845 MonoJumpInfo ji;
3847 memset (&ji, 0, sizeof (ji));
3848 ji.type = MONO_PATCH_INFO_JIT_ICALL_ADDR;
3849 ji.data.target = info->name;
3851 target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, &ji, FALSE);
3853 if (cfg->compile_aot) {
3854 callee = get_callee (ctx, llvm_sig, MONO_PATCH_INFO_JIT_ICALL, (char*)info->name);
3855 if (!callee) {
3856 set_failure (ctx, "can't encode patch");
3857 return;
3859 } else {
3860 target = (gpointer)mono_icall_get_wrapper (info);
3861 callee = emit_jit_callee (ctx, "", llvm_sig, target);
3863 } else {
3864 if (cfg->compile_aot) {
3865 callee = NULL;
3866 if (cfg->abs_patches) {
3867 MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
3868 if (abs_ji) {
3869 callee = get_callee (ctx, llvm_sig, abs_ji->type, abs_ji->data.target);
3870 if (!callee) {
3871 set_failure (ctx, "can't encode patch");
3872 return;
3876 if (!callee) {
3877 set_failure (ctx, "aot");
3878 return;
3880 } else {
3881 #if LLVM_API_VERSION > 100
3882 if (cfg->abs_patches) {
3883 MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
3884 if (abs_ji) {
3885 ERROR_DECL (error);
3887 target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, abs_ji, FALSE, error);
3888 mono_error_assert_ok (error);
3889 callee = emit_jit_callee (ctx, "", llvm_sig, target);
3890 } else {
3891 g_assert_not_reached ();
3893 } else {
3894 g_assert_not_reached ();
3896 #else
3897 g_assert_not_reached ();
3898 #endif
3903 if (is_virtual) {
3904 int size = TARGET_SIZEOF_VOID_P;
3905 LLVMValueRef index;
3907 g_assert (ins->inst_offset % size == 0);
3908 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
3910 callee = convert (ctx, LLVMBuildLoad (builder, LLVMBuildGEP (builder, convert (ctx, values [ins->inst_basereg], LLVMPointerType (LLVMPointerType (IntPtrType (), 0), 0)), &index, 1, ""), ""), LLVMPointerType (llvm_sig, 0));
3911 } else if (calli) {
3912 callee = convert (ctx, values [ins->sreg1], LLVMPointerType (llvm_sig, 0));
3913 } else {
3914 if (ins->flags & MONO_INST_HAS_METHOD) {
3919 * Collect and convert arguments
3921 nargs = (sig->param_count * 16) + sig->hasthis + vretaddr + call->rgctx_reg + call->imt_arg_reg + call->cinfo->dummy_arg + 1;
3922 len = sizeof (LLVMValueRef) * nargs;
3923 args = g_newa (LLVMValueRef, nargs);
3924 memset (args, 0, len);
3925 l = call->out_ireg_args;
3927 if (call->rgctx_arg_reg) {
3928 g_assert (values [call->rgctx_arg_reg]);
3929 g_assert (cinfo->rgctx_arg_pindex < nargs);
3931 * On ARM, the imt/rgctx argument is passed in a caller save register, but some of our trampolines etc. clobber it, leading to
3932 * problems is LLVM moves the arg assignment earlier. To work around this, save the argument into a stack slot and load
3933 * it using a volatile load.
3935 #ifdef TARGET_ARM
3936 if (!ctx->imt_rgctx_loc)
3937 ctx->imt_rgctx_loc = build_alloca_llvm_type (ctx, ctx->module->ptr_type, TARGET_SIZEOF_VOID_P);
3938 LLVMBuildStore (builder, convert (ctx, ctx->values [call->rgctx_arg_reg], ctx->module->ptr_type), ctx->imt_rgctx_loc);
3939 args [cinfo->rgctx_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE);
3940 #else
3941 args [cinfo->rgctx_arg_pindex] = convert (ctx, values [call->rgctx_arg_reg], ctx->module->ptr_type);
3942 #endif
3944 if (call->imt_arg_reg) {
3945 g_assert (!ctx->llvm_only);
3946 g_assert (values [call->imt_arg_reg]);
3947 g_assert (cinfo->imt_arg_pindex < nargs);
3948 #ifdef TARGET_ARM
3949 if (!ctx->imt_rgctx_loc)
3950 ctx->imt_rgctx_loc = build_alloca_llvm_type (ctx, ctx->module->ptr_type, TARGET_SIZEOF_VOID_P);
3951 LLVMBuildStore (builder, convert (ctx, ctx->values [call->imt_arg_reg], ctx->module->ptr_type), ctx->imt_rgctx_loc);
3952 args [cinfo->imt_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE);
3953 #else
3954 args [cinfo->imt_arg_pindex] = convert (ctx, values [call->imt_arg_reg], ctx->module->ptr_type);
3955 #endif
3957 switch (cinfo->ret.storage) {
3958 case LLVMArgGsharedvtVariable: {
3959 MonoInst *var = get_vreg_to_inst (cfg, call->inst.dreg);
3961 if (var && var->opcode == OP_GSHAREDVT_LOCAL) {
3962 args [cinfo->vret_arg_pindex] = convert (ctx, emit_gsharedvt_ldaddr (ctx, var->dreg), IntPtrType ());
3963 } else {
3964 g_assert (addresses [call->inst.dreg]);
3965 args [cinfo->vret_arg_pindex] = convert (ctx, addresses [call->inst.dreg], IntPtrType ());
3967 break;
3969 default:
3970 if (vretaddr) {
3971 if (!addresses [call->inst.dreg])
3972 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
3973 g_assert (cinfo->vret_arg_pindex < nargs);
3974 if (cinfo->ret.storage == LLVMArgVtypeByRef)
3975 args [cinfo->vret_arg_pindex] = addresses [call->inst.dreg];
3976 else
3977 args [cinfo->vret_arg_pindex] = LLVMBuildPtrToInt (builder, addresses [call->inst.dreg], IntPtrType (), "");
3979 break;
3983 * Sometimes the same method is called with two different signatures (i.e. with and without 'this'), so
3984 * use the real callee for argument type conversion.
3986 LLVMTypeRef callee_type = LLVMGetElementType (LLVMTypeOf (callee));
3987 LLVMTypeRef *param_types = (LLVMTypeRef*)g_alloca (sizeof (LLVMTypeRef) * LLVMCountParamTypes (callee_type));
3988 LLVMGetParamTypes (callee_type, param_types);
3990 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
3991 guint32 regpair;
3992 int reg, pindex;
3993 LLVMArgInfo *ainfo = &call->cinfo->args [i];
3995 pindex = ainfo->pindex;
3997 regpair = (guint32)(gssize)(l->data);
3998 reg = regpair & 0xffffff;
3999 args [pindex] = values [reg];
4000 switch (ainfo->storage) {
4001 case LLVMArgVtypeInReg:
4002 case LLVMArgAsFpArgs: {
4003 guint32 nargs;
4004 int j;
4006 for (j = 0; j < ainfo->ndummy_fpargs; ++j)
4007 args [pindex + j] = LLVMConstNull (LLVMDoubleType ());
4008 pindex += ainfo->ndummy_fpargs;
4010 g_assert (addresses [reg]);
4011 emit_vtype_to_args (ctx, builder, ainfo->type, addresses [reg], ainfo, args + pindex, &nargs);
4012 pindex += nargs;
4014 // FIXME: alignment
4015 // FIXME: Get rid of the VMOVE
4016 break;
4018 case LLVMArgVtypeByVal:
4019 g_assert (addresses [reg]);
4020 args [pindex] = addresses [reg];
4021 break;
4022 case LLVMArgVtypeByRef: {
4023 g_assert (addresses [reg]);
4024 args [pindex] = convert (ctx, addresses [reg], LLVMPointerType (type_to_llvm_arg_type (ctx, ainfo->type), 0));
4025 break;
4027 case LLVMArgAsIArgs:
4028 g_assert (addresses [reg]);
4029 if (ainfo->esize == 8)
4030 args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (LLVMInt64Type (), ainfo->nslots), 0)), "");
4031 else
4032 args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo->nslots), 0)), "");
4033 break;
4034 case LLVMArgVtypeAsScalar:
4035 g_assert_not_reached ();
4036 break;
4037 case LLVMArgGsharedvtFixed:
4038 case LLVMArgGsharedvtFixedVtype:
4039 g_assert (addresses [reg]);
4040 args [pindex] = convert (ctx, addresses [reg], LLVMPointerType (type_to_llvm_arg_type (ctx, ainfo->type), 0));
4041 break;
4042 case LLVMArgGsharedvtVariable:
4043 g_assert (addresses [reg]);
4044 args [pindex] = convert (ctx, addresses [reg], LLVMPointerType (IntPtrType (), 0));
4045 break;
4046 default:
4047 g_assert (args [pindex]);
4048 if (i == 0 && sig->hasthis)
4049 args [pindex] = convert (ctx, args [pindex], param_types [pindex]);
4050 else
4051 args [pindex] = convert (ctx, args [pindex], type_to_llvm_arg_type (ctx, ainfo->type));
4052 break;
4054 g_assert (pindex <= nargs);
4056 l = l->next;
4060 if (call->cinfo->dummy_arg) {
4061 g_assert (call->cinfo->dummy_arg_pindex < nargs);
4062 args [call->cinfo->dummy_arg_pindex] = LLVMConstNull (ctx->module->ptr_type);
4065 // FIXME: Align call sites
4068 * Emit the call
4070 lcall = emit_call (ctx, bb, &builder, callee, args, LLVMCountParamTypes (llvm_sig));
4072 if (ins->opcode != OP_TAILCALL && ins->opcode != OP_TAILCALL_MEMBASE && LLVMGetInstructionOpcode (lcall) == LLVMCall)
4073 mono_llvm_set_call_notailcall (lcall);
4075 // As per the LLVM docs, a function has a noalias return value if and only if
4076 // it is an allocation function. This is an allocation function.
4077 if (call->method && call->method->wrapper_type == MONO_WRAPPER_ALLOC)
4078 mono_llvm_set_call_noalias_ret (lcall);
4081 * Modify cconv and parameter attributes to pass rgctx/imt correctly.
4083 #if defined(MONO_ARCH_IMT_REG) && defined(MONO_ARCH_RGCTX_REG)
4084 g_assert (MONO_ARCH_IMT_REG == MONO_ARCH_RGCTX_REG);
4085 #endif
4086 /* The two can't be used together, so use only one LLVM calling conv to pass them */
4087 g_assert (!(call->rgctx_arg_reg && call->imt_arg_reg));
4088 if (!sig->pinvoke && !cfg->llvm_only)
4089 LLVMSetInstructionCallConv (lcall, LLVMMono1CallConv);
4090 if (preserveall)
4091 set_call_preserveall_cc (lcall);
4093 if (cinfo->ret.storage == LLVMArgVtypeByRef)
4094 mono_llvm_add_instr_attr (lcall, 1 + cinfo->vret_arg_pindex, LLVM_ATTR_STRUCT_RET);
4095 if (!ctx->llvm_only && call->rgctx_arg_reg)
4096 mono_llvm_add_instr_attr (lcall, 1 + cinfo->rgctx_arg_pindex, LLVM_ATTR_IN_REG);
4097 if (call->imt_arg_reg)
4098 mono_llvm_add_instr_attr (lcall, 1 + cinfo->imt_arg_pindex, LLVM_ATTR_IN_REG);
4100 /* Add byval attributes if needed */
4101 for (i = 0; i < sig->param_count; ++i) {
4102 LLVMArgInfo *ainfo = &call->cinfo->args [i + sig->hasthis];
4104 if (ainfo && ainfo->storage == LLVMArgVtypeByVal)
4105 mono_llvm_add_instr_attr (lcall, 1 + ainfo->pindex, LLVM_ATTR_BY_VAL);
4109 * Convert the result
4111 switch (cinfo->ret.storage) {
4112 case LLVMArgVtypeInReg: {
4113 LLVMValueRef regs [2];
4115 if (LLVMTypeOf (lcall) == LLVMVoidType ())
4116 /* Empty struct */
4117 break;
4119 if (!addresses [ins->dreg])
4120 addresses [ins->dreg] = build_alloca (ctx, sig->ret);
4122 regs [0] = LLVMBuildExtractValue (builder, lcall, 0, "");
4123 if (cinfo->ret.pair_storage [1] != LLVMArgNone)
4124 regs [1] = LLVMBuildExtractValue (builder, lcall, 1, "");
4125 emit_args_to_vtype (ctx, builder, sig->ret, addresses [ins->dreg], &cinfo->ret, regs);
4126 break;
4128 case LLVMArgVtypeByVal:
4129 if (!addresses [call->inst.dreg])
4130 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
4131 LLVMBuildStore (builder, lcall, addresses [call->inst.dreg]);
4132 break;
4133 case LLVMArgAsIArgs:
4134 case LLVMArgFpStruct:
4135 if (!addresses [call->inst.dreg])
4136 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
4137 LLVMBuildStore (builder, lcall, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (LLVMTypeOf (lcall), 0), FALSE));
4138 break;
4139 case LLVMArgVtypeAsScalar:
4140 if (!addresses [call->inst.dreg])
4141 addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
4142 LLVMBuildStore (builder, lcall, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (LLVMTypeOf (lcall), 0), FALSE));
4143 break;
4144 case LLVMArgVtypeRetAddr:
4145 case LLVMArgVtypeByRef:
4146 if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (sig->ret))) {
4147 /* Some opcodes like STOREX_MEMBASE access these by value */
4148 g_assert (addresses [call->inst.dreg]);
4149 values [ins->dreg] = LLVMBuildLoad (builder, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (type_to_llvm_type (ctx, sig->ret), 0), FALSE), "");
4151 break;
4152 case LLVMArgGsharedvtVariable:
4153 break;
4154 case LLVMArgGsharedvtFixed:
4155 case LLVMArgGsharedvtFixedVtype:
4156 values [ins->dreg] = LLVMBuildLoad (builder, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (type_to_llvm_type (ctx, sig->ret), 0), FALSE), "");
4157 break;
4158 default:
4159 if (sig->ret->type != MONO_TYPE_VOID)
4160 /* If the method returns an unsigned value, need to zext it */
4161 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));
4162 break;
4165 *builder_ref = ctx->builder;
4168 static void
4169 emit_llvmonly_throw (EmitContext *ctx, MonoBasicBlock *bb, gboolean rethrow, LLVMValueRef exc)
4171 const char *icall_name = rethrow ? "mono_llvm_rethrow_exception" : "mono_llvm_throw_exception";
4172 LLVMValueRef callee = rethrow ? ctx->module->rethrow : ctx->module->throw_icall;
4174 LLVMTypeRef exc_type = type_to_llvm_type (ctx, m_class_get_byval_arg (mono_get_exception_class ()));
4176 if (!callee) {
4177 LLVMTypeRef fun_sig = LLVMFunctionType1 (LLVMVoidType (), exc_type, FALSE);
4179 g_assert (ctx->cfg->compile_aot);
4180 callee = get_callee (ctx, fun_sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, icall_name);
4183 LLVMValueRef args [2];
4185 args [0] = convert (ctx, exc, exc_type);
4186 emit_call (ctx, bb, &ctx->builder, callee, args, 1);
4188 LLVMBuildUnreachable (ctx->builder);
4190 ctx->builder = create_builder (ctx);
4193 static void
4194 emit_throw (EmitContext *ctx, MonoBasicBlock *bb, gboolean rethrow, LLVMValueRef exc)
4196 MonoMethodSignature *throw_sig;
4197 LLVMValueRef callee, arg;
4198 const char *icall_name;
4200 callee = rethrow ? ctx->module->rethrow : ctx->module->throw_icall;
4201 icall_name = rethrow ? "mono_arch_rethrow_exception" : "mono_arch_throw_exception";
4203 if (!callee) {
4204 throw_sig = mono_metadata_signature_alloc (mono_get_corlib (), 1);
4205 throw_sig->ret = m_class_get_byval_arg (mono_get_void_class ());
4206 throw_sig->params [0] = m_class_get_byval_arg (mono_get_object_class ());
4207 if (ctx->cfg->compile_aot) {
4208 callee = get_callee (ctx, sig_to_llvm_sig (ctx, throw_sig), MONO_PATCH_INFO_JIT_ICALL, icall_name);
4209 } else {
4210 gpointer target;
4211 #ifdef TARGET_X86
4213 * LLVM doesn't push the exception argument, so we need a different
4214 * trampoline.
4216 target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_JIT_ICALL, rethrow ? "llvm_rethrow_exception_trampoline" : "llvm_throw_exception_trampoline");
4217 #else
4218 target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_JIT_ICALL, icall_name);
4219 #endif
4220 callee = emit_jit_callee (ctx, icall_name, sig_to_llvm_sig (ctx, throw_sig), target);
4223 mono_memory_barrier ();
4224 #if LLVM_API_VERSION < 100
4225 if (rethrow)
4226 ctx->module->rethrow = callee;
4227 else
4228 ctx->module->throw_icall = callee;
4229 #endif
4231 arg = convert (ctx, exc, type_to_llvm_type (ctx, m_class_get_byval_arg (mono_get_object_class ())));
4232 emit_call (ctx, bb, &ctx->builder, callee, &arg, 1);
4235 static void
4236 emit_resume_eh (EmitContext *ctx, MonoBasicBlock *bb)
4238 const char *icall_name = "mono_llvm_resume_exception";
4239 LLVMValueRef callee;
4241 LLVMTypeRef fun_sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
4243 g_assert (ctx->cfg->compile_aot);
4244 callee = get_callee (ctx, fun_sig, MONO_PATCH_INFO_JIT_ICALL, icall_name);
4246 emit_call (ctx, bb, &ctx->builder, callee, NULL, 0);
4248 LLVMBuildUnreachable (ctx->builder);
4250 ctx->builder = create_builder (ctx);
4253 static LLVMValueRef
4254 mono_llvm_emit_clear_exception_call (EmitContext *ctx, LLVMBuilderRef builder)
4256 const char *icall_name = "mono_llvm_clear_exception";
4258 LLVMTypeRef call_sig = LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE);
4259 LLVMValueRef callee = NULL;
4261 if (!callee) {
4262 if (ctx->cfg->compile_aot) {
4263 callee = get_callee (ctx, call_sig, MONO_PATCH_INFO_JIT_ICALL, icall_name);
4264 } else {
4265 // FIXME: This is broken.
4266 callee = LLVMAddFunction (ctx->lmodule, icall_name, call_sig);
4270 g_assert (builder && callee);
4272 return LLVMBuildCall (builder, callee, NULL, 0, "");
4275 static LLVMValueRef
4276 mono_llvm_emit_load_exception_call (EmitContext *ctx, LLVMBuilderRef builder)
4278 const char *icall_name = "mono_llvm_load_exception";
4280 LLVMTypeRef call_sig = LLVMFunctionType (ObjRefType (), NULL, 0, FALSE);
4281 LLVMValueRef callee = NULL;
4283 if (!callee) {
4284 if (ctx->cfg->compile_aot) {
4285 callee = get_callee (ctx, call_sig, MONO_PATCH_INFO_JIT_ICALL, icall_name);
4286 } else {
4287 // FIXME: This is broken.
4288 callee = LLVMAddFunction (ctx->lmodule, icall_name, call_sig);
4292 g_assert (builder && callee);
4294 return LLVMBuildCall (builder, callee, NULL, 0, icall_name);
4298 static LLVMValueRef
4299 mono_llvm_emit_match_exception_call (EmitContext *ctx, LLVMBuilderRef builder, gint32 region_start, gint32 region_end)
4301 const char *icall_name = "mono_llvm_match_exception";
4303 ctx->builder = builder;
4305 LLVMValueRef args[5];
4306 const int num_args = G_N_ELEMENTS (args);
4308 args [0] = convert (ctx, get_aotconst (ctx, MONO_PATCH_INFO_AOT_JIT_INFO, GINT_TO_POINTER (ctx->cfg->method_index)), IntPtrType ());
4309 args [1] = LLVMConstInt (LLVMInt32Type (), region_start, 0);
4310 args [2] = LLVMConstInt (LLVMInt32Type (), region_end, 0);
4311 if (ctx->cfg->rgctx_var) {
4312 LLVMValueRef rgctx_alloc = ctx->addresses [ctx->cfg->rgctx_var->dreg];
4313 g_assert (rgctx_alloc);
4314 args [3] = LLVMBuildLoad (builder, convert (ctx, rgctx_alloc, LLVMPointerType (IntPtrType (), 0)), "");
4315 } else {
4316 args [3] = LLVMConstInt (IntPtrType (), 0, 0);
4318 if (ctx->this_arg)
4319 args [4] = convert (ctx, ctx->this_arg, IntPtrType ());
4320 else
4321 args [4] = LLVMConstInt (IntPtrType (), 0, 0);
4323 LLVMTypeRef match_sig = LLVMFunctionType5 (LLVMInt32Type (), IntPtrType (), LLVMInt32Type (), LLVMInt32Type (), IntPtrType (), IntPtrType (), FALSE);
4324 LLVMValueRef callee;
4325 g_assert (ctx->cfg->compile_aot);
4326 ctx->builder = builder;
4327 // get_callee expects ctx->builder to be the emitting builder
4328 callee = get_callee (ctx, match_sig, MONO_PATCH_INFO_JIT_ICALL, icall_name);
4330 g_assert (builder && callee);
4332 g_assert (ctx->ex_var);
4334 return LLVMBuildCall (builder, callee, args, num_args, icall_name);
4337 // FIXME: This won't work because the code-finding makes this
4338 // not a constant.
4339 /*#define MONO_PERSONALITY_DEBUG*/
4341 #ifdef MONO_PERSONALITY_DEBUG
4342 static const gboolean use_debug_personality = TRUE;
4343 static const char *default_personality_name = "mono_debug_personality";
4344 #else
4345 static const gboolean use_debug_personality = FALSE;
4346 static const char *default_personality_name = "__gxx_personality_v0";
4347 #endif
4349 static LLVMTypeRef
4350 default_cpp_lpad_exc_signature (void)
4352 static gboolean inited = FALSE;
4353 static LLVMTypeRef sig;
4355 if (!sig) {
4356 LLVMTypeRef signature [2];
4357 signature [0] = LLVMPointerType (LLVMInt8Type (), 0);
4358 signature [1] = LLVMInt32Type ();
4359 sig = LLVMStructType (signature, 2, FALSE);
4360 inited = TRUE;
4363 return sig;
4366 static LLVMValueRef
4367 get_mono_personality (EmitContext *ctx)
4369 LLVMValueRef personality = NULL;
4370 LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
4372 g_assert (ctx->cfg->compile_aot);
4373 if (!use_debug_personality) {
4374 personality = get_intrins_by_name (ctx, default_personality_name);
4375 } else {
4376 personality = get_callee (ctx, personality_type, MONO_PATCH_INFO_JIT_ICALL, default_personality_name);
4379 g_assert (personality);
4380 return personality;
4383 static LLVMBasicBlockRef
4384 emit_landing_pad (EmitContext *ctx, int group_index, int group_size)
4386 MonoCompile *cfg = ctx->cfg;
4387 LLVMBuilderRef old_builder = ctx->builder;
4388 MonoExceptionClause *group_start = cfg->header->clauses + group_index;
4390 LLVMBuilderRef lpadBuilder = create_builder (ctx);
4391 ctx->builder = lpadBuilder;
4393 MonoBasicBlock *handler_bb = cfg->cil_offset_to_bb [CLAUSE_START (group_start)];
4394 g_assert (handler_bb);
4396 // <resultval> = landingpad <somety> personality <type> <pers_fn> <clause>+
4397 LLVMValueRef personality = get_mono_personality (ctx);
4398 g_assert (personality);
4400 char *bb_name = g_strdup_printf ("LPAD%d_BB", group_index);
4401 LLVMBasicBlockRef lpad_bb = gen_bb (ctx, bb_name);
4402 g_free (bb_name);
4403 LLVMPositionBuilderAtEnd (lpadBuilder, lpad_bb);
4404 LLVMValueRef landing_pad = LLVMBuildLandingPad (lpadBuilder, default_cpp_lpad_exc_signature (), personality, 0, "");
4405 g_assert (landing_pad);
4407 LLVMValueRef cast = LLVMBuildBitCast (lpadBuilder, ctx->module->sentinel_exception, LLVMPointerType (LLVMInt8Type (), 0), "int8TypeInfo");
4408 LLVMAddClause (landing_pad, cast);
4410 LLVMBasicBlockRef resume_bb = gen_bb (ctx, "RESUME_BB");
4411 LLVMBuilderRef resume_builder = create_builder (ctx);
4412 ctx->builder = resume_builder;
4413 LLVMPositionBuilderAtEnd (resume_builder, resume_bb);
4415 emit_resume_eh (ctx, handler_bb);
4417 // Build match
4418 ctx->builder = lpadBuilder;
4419 LLVMPositionBuilderAtEnd (lpadBuilder, lpad_bb);
4421 gboolean finally_only = TRUE;
4423 MonoExceptionClause *group_cursor = group_start;
4425 for (int i = 0; i < group_size; i ++) {
4426 if (!(group_cursor->flags & MONO_EXCEPTION_CLAUSE_FINALLY || group_cursor->flags & MONO_EXCEPTION_CLAUSE_FAULT))
4427 finally_only = FALSE;
4429 group_cursor++;
4432 // FIXME:
4433 // Handle landing pad inlining
4435 if (!finally_only) {
4436 // So at each level of the exception stack we will match the exception again.
4437 // During that match, we need to compare against the handler types for the current
4438 // protected region. We send the try start and end so that we can only check against
4439 // handlers for this lexical protected region.
4440 LLVMValueRef match = mono_llvm_emit_match_exception_call (ctx, lpadBuilder, group_start->try_offset, group_start->try_offset + group_start->try_len);
4442 // if returns -1, resume
4443 LLVMValueRef switch_ins = LLVMBuildSwitch (lpadBuilder, match, resume_bb, group_size);
4445 // else move to that target bb
4446 for (int i = 0; i < group_size; i++) {
4447 MonoExceptionClause *clause = group_start + i;
4448 int clause_index = clause - cfg->header->clauses;
4449 MonoBasicBlock *handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (clause_index));
4450 g_assert (handler_bb);
4451 g_assert (ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
4452 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE), ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
4454 } else {
4455 int clause_index = group_start - cfg->header->clauses;
4456 MonoBasicBlock *finally_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (clause_index));
4457 g_assert (finally_bb);
4459 LLVMBuildBr (ctx->builder, ctx->bblocks [finally_bb->block_num].call_handler_target_bb);
4462 ctx->builder = old_builder;
4464 return lpad_bb;
4468 static void
4469 emit_llvmonly_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBasicBlockRef cbb)
4471 int clause_index = MONO_REGION_CLAUSE_INDEX (bb->region);
4472 MonoExceptionClause *clause = &ctx->cfg->header->clauses [clause_index];
4474 // Make exception available to catch blocks
4475 if (!(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY || clause->flags & MONO_EXCEPTION_CLAUSE_FAULT)) {
4476 LLVMValueRef mono_exc = mono_llvm_emit_load_exception_call (ctx, ctx->builder);
4478 g_assert (ctx->ex_var);
4479 LLVMBuildStore (ctx->builder, LLVMBuildBitCast (ctx->builder, mono_exc, ObjRefType (), ""), ctx->ex_var);
4481 if (bb->in_scount == 1) {
4482 MonoInst *exvar = bb->in_stack [0];
4483 g_assert (!ctx->values [exvar->dreg]);
4484 g_assert (ctx->ex_var);
4485 ctx->values [exvar->dreg] = LLVMBuildLoad (ctx->builder, ctx->ex_var, "save_exception");
4486 emit_volatile_store (ctx, exvar->dreg);
4489 mono_llvm_emit_clear_exception_call (ctx, ctx->builder);
4492 LLVMBuilderRef handler_builder = create_builder (ctx);
4493 LLVMBasicBlockRef target_bb = ctx->bblocks [bb->block_num].call_handler_target_bb;
4494 LLVMPositionBuilderAtEnd (handler_builder, target_bb);
4496 // Make the handler code end with a jump to cbb
4497 LLVMBuildBr (handler_builder, cbb);
4500 static void
4501 emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder)
4503 MonoCompile *cfg = ctx->cfg;
4504 LLVMValueRef *values = ctx->values;
4505 LLVMModuleRef lmodule = ctx->lmodule;
4506 BBInfo *bblocks = ctx->bblocks;
4507 LLVMTypeRef i8ptr;
4508 LLVMValueRef personality;
4509 LLVMValueRef landing_pad;
4510 LLVMBasicBlockRef target_bb;
4511 MonoInst *exvar;
4512 static int ti_generator;
4513 char ti_name [128];
4514 LLVMValueRef type_info;
4515 int clause_index;
4516 GSList *l;
4518 // <resultval> = landingpad <somety> personality <type> <pers_fn> <clause>+
4520 if (cfg->compile_aot) {
4521 /* Use a dummy personality function */
4522 personality = LLVMGetNamedFunction (lmodule, "mono_personality");
4523 g_assert (personality);
4524 } else {
4525 #if LLVM_API_VERSION > 100
4526 /* Can't cache this as each method is in its own llvm module */
4527 LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
4528 personality = LLVMAddFunction (ctx->lmodule, "mono_personality", personality_type);
4529 mono_llvm_add_func_attr (personality, LLVM_ATTR_NO_UNWIND);
4530 LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlock (personality, "ENTRY");
4531 LLVMBuilderRef builder2 = LLVMCreateBuilder ();
4532 LLVMPositionBuilderAtEnd (builder2, entry_bb);
4533 LLVMBuildRet (builder2, LLVMConstInt (LLVMInt32Type (), 0, FALSE));
4534 LLVMDisposeBuilder (builder2);
4535 #else
4536 g_assert_not_reached ();
4537 #endif
4540 i8ptr = LLVMPointerType (LLVMInt8Type (), 0);
4542 clause_index = (mono_get_block_region_notry (cfg, bb->region) >> 8) - 1;
4545 * Create the type info
4547 sprintf (ti_name, "type_info_%d", ti_generator);
4548 ti_generator ++;
4550 if (cfg->compile_aot) {
4551 /* decode_eh_frame () in aot-runtime.c will decode this */
4552 type_info = LLVMAddGlobal (lmodule, LLVMInt32Type (), ti_name);
4553 LLVMSetInitializer (type_info, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE));
4556 * These symbols are not really used, the clause_index is embedded into the EH tables generated by DwarfMonoException in LLVM.
4558 LLVMSetLinkage (type_info, LLVMInternalLinkage);
4559 } else {
4560 #if LLVM_API_VERSION > 100
4561 type_info = LLVMAddGlobal (lmodule, LLVMInt32Type (), ti_name);
4562 LLVMSetInitializer (type_info, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE));
4563 #else
4564 g_assert_not_reached ();
4565 #endif
4569 LLVMTypeRef members [2], ret_type;
4571 members [0] = i8ptr;
4572 members [1] = LLVMInt32Type ();
4573 ret_type = LLVMStructType (members, 2, FALSE);
4575 landing_pad = LLVMBuildLandingPad (builder, ret_type, personality, 1, "");
4576 LLVMAddClause (landing_pad, type_info);
4578 /* Store the exception into the exvar */
4579 if (ctx->ex_var)
4580 LLVMBuildStore (builder, convert (ctx, LLVMBuildExtractValue (builder, landing_pad, 0, "ex_obj"), ObjRefType ()), ctx->ex_var);
4584 * LLVM throw sites are associated with a one landing pad, and LLVM generated
4585 * code expects control to be transferred to this landing pad even in the
4586 * presence of nested clauses. The landing pad needs to branch to the landing
4587 * pads belonging to nested clauses based on the selector value returned by
4588 * the landing pad instruction, which is passed to the landing pad in a
4589 * register by the EH code.
4591 target_bb = bblocks [bb->block_num].call_handler_target_bb;
4592 g_assert (target_bb);
4595 * Branch to the correct landing pad
4597 LLVMValueRef ex_selector = LLVMBuildExtractValue (builder, landing_pad, 1, "ex_selector");
4598 LLVMValueRef switch_ins = LLVMBuildSwitch (builder, ex_selector, target_bb, 0);
4600 for (l = ctx->nested_in [clause_index]; l; l = l->next) {
4601 int nesting_clause_index = GPOINTER_TO_INT (l->data);
4602 MonoBasicBlock *handler_bb;
4604 handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (nesting_clause_index));
4605 g_assert (handler_bb);
4607 g_assert (ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
4608 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), nesting_clause_index, FALSE), ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
4611 /* Start a new bblock which CALL_HANDLER can branch to */
4612 ctx->builder = builder = create_builder (ctx);
4613 LLVMPositionBuilderAtEnd (ctx->builder, target_bb);
4615 ctx->bblocks [bb->block_num].end_bblock = target_bb;
4617 /* Store the exception into the IL level exvar */
4618 if (bb->in_scount == 1) {
4619 g_assert (bb->in_scount == 1);
4620 exvar = bb->in_stack [0];
4622 // FIXME: This is shared with filter clauses ?
4623 g_assert (!values [exvar->dreg]);
4625 g_assert (ctx->ex_var);
4626 values [exvar->dreg] = LLVMBuildLoad (builder, ctx->ex_var, "");
4627 emit_volatile_store (ctx, exvar->dreg);
4630 /* Make normal branches to the start of the clause branch to the new bblock */
4631 bblocks [bb->block_num].bblock = target_bb;
4634 //Wasm requires us to canonicalize NaNs.
4635 static LLVMValueRef
4636 get_double_const (MonoCompile *cfg, double val)
4638 #ifdef TARGET_WASM
4639 if (mono_isnan (val))
4640 *(gint64 *)&val = 0x7FF8000000000000ll;
4641 #endif
4642 return LLVMConstReal (LLVMDoubleType (), val);
4645 static LLVMValueRef
4646 get_float_const (MonoCompile *cfg, float val)
4648 #ifdef TARGET_WASM
4649 if (mono_isnan (val))
4650 *(int *)&val = 0x7FC00000;
4651 #endif
4652 if (cfg->r4fp)
4653 return LLVMConstReal (LLVMFloatType (), val);
4654 else
4655 return LLVMConstFPExt (LLVMConstReal (LLVMFloatType (), val), LLVMDoubleType ());
4658 static void
4659 process_bb (EmitContext *ctx, MonoBasicBlock *bb)
4661 MonoCompile *cfg = ctx->cfg;
4662 MonoMethodSignature *sig = ctx->sig;
4663 LLVMValueRef method = ctx->lmethod;
4664 LLVMValueRef *values = ctx->values;
4665 LLVMValueRef *addresses = ctx->addresses;
4666 LLVMCallInfo *linfo = ctx->linfo;
4667 BBInfo *bblocks = ctx->bblocks;
4668 MonoInst *ins;
4669 LLVMBasicBlockRef cbb;
4670 LLVMBuilderRef builder, starting_builder;
4671 gboolean has_terminator;
4672 LLVMValueRef v;
4673 LLVMValueRef lhs, rhs;
4674 int nins = 0;
4676 cbb = get_end_bb (ctx, bb);
4678 builder = create_builder (ctx);
4679 ctx->builder = builder;
4680 LLVMPositionBuilderAtEnd (builder, cbb);
4682 if (!ctx_ok (ctx))
4683 return;
4685 if (bb->flags & BB_EXCEPTION_HANDLER) {
4686 if (!ctx->llvm_only && !bblocks [bb->block_num].invoke_target) {
4687 set_failure (ctx, "handler without invokes");
4688 return;
4691 if (ctx->llvm_only)
4692 emit_llvmonly_handler_start (ctx, bb, cbb);
4693 else
4694 emit_handler_start (ctx, bb, builder);
4695 if (!ctx_ok (ctx))
4696 return;
4697 builder = ctx->builder;
4700 has_terminator = FALSE;
4701 starting_builder = builder;
4702 for (ins = bb->code; ins; ins = ins->next) {
4703 const char *spec = LLVM_INS_INFO (ins->opcode);
4704 char *dname = NULL;
4705 char dname_buf [128];
4707 emit_dbg_loc (ctx, builder, ins->cil_code);
4709 nins ++;
4710 if (nins > 1000) {
4712 * Some steps in llc are non-linear in the size of basic blocks, see #5714.
4713 * Start a new bblock.
4714 * Prevent the bblocks to be merged by doing a volatile load + cond branch
4715 * from localloc-ed memory.
4717 if (!cfg->llvm_only)
4718 ;//set_failure (ctx, "basic block too long");
4720 if (!ctx->long_bb_break_var) {
4721 ctx->long_bb_break_var = build_alloca_llvm_type_name (ctx, LLVMInt32Type (), 0, "long_bb_break");
4722 mono_llvm_build_store (ctx->alloca_builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), ctx->long_bb_break_var, TRUE, LLVM_BARRIER_NONE);
4725 cbb = gen_bb (ctx, "CONT_LONG_BB");
4726 LLVMBasicBlockRef dummy_bb = gen_bb (ctx, "CONT_LONG_BB_DUMMY");
4728 LLVMValueRef load = mono_llvm_build_load (builder, ctx->long_bb_break_var, "", TRUE);
4730 * The long_bb_break_var is initialized to 0 in the prolog, so this branch will always go to 'cbb'
4731 * but llvm doesn't know that, so the branch is not going to be eliminated.
4733 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntEQ, load, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
4735 LLVMBuildCondBr (builder, cmp, cbb, dummy_bb);
4737 /* Emit a dummy false bblock which does nothing but contains a volatile store so it cannot be eliminated */
4738 ctx->builder = builder = create_builder (ctx);
4739 LLVMPositionBuilderAtEnd (builder, dummy_bb);
4740 mono_llvm_build_store (builder, LLVMConstInt (LLVMInt32Type (), 1, FALSE), ctx->long_bb_break_var, TRUE, LLVM_BARRIER_NONE);
4741 LLVMBuildBr (builder, cbb);
4743 ctx->builder = builder = create_builder (ctx);
4744 LLVMPositionBuilderAtEnd (builder, cbb);
4745 ctx->bblocks [bb->block_num].end_bblock = cbb;
4746 nins = 0;
4748 emit_dbg_loc (ctx, builder, ins->cil_code);
4751 if (has_terminator)
4752 /* There could be instructions after a terminator, skip them */
4753 break;
4755 if (spec [MONO_INST_DEST] != ' ' && !MONO_IS_STORE_MEMBASE (ins)) {
4756 sprintf (dname_buf, "t%d", ins->dreg);
4757 dname = dname_buf;
4760 if (spec [MONO_INST_SRC1] != ' ' && spec [MONO_INST_SRC1] != 'v') {
4761 MonoInst *var = get_vreg_to_inst (cfg, ins->sreg1);
4763 if (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) && var->opcode != OP_GSHAREDVT_ARG_REGOFFSET) {
4764 lhs = emit_volatile_load (ctx, ins->sreg1);
4765 } else {
4766 /* It is ok for SETRET to have an uninitialized argument */
4767 if (!values [ins->sreg1] && ins->opcode != OP_SETRET) {
4768 set_failure (ctx, "sreg1");
4769 return;
4771 lhs = values [ins->sreg1];
4773 } else {
4774 lhs = NULL;
4777 if (spec [MONO_INST_SRC2] != ' ' && spec [MONO_INST_SRC2] != ' ') {
4778 MonoInst *var = get_vreg_to_inst (cfg, ins->sreg2);
4779 if (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) {
4780 rhs = emit_volatile_load (ctx, ins->sreg2);
4781 } else {
4782 if (!values [ins->sreg2]) {
4783 set_failure (ctx, "sreg2");
4784 return;
4786 rhs = values [ins->sreg2];
4788 } else {
4789 rhs = NULL;
4792 //mono_print_ins (ins);
4793 switch (ins->opcode) {
4794 case OP_NOP:
4795 case OP_NOT_NULL:
4796 case OP_LIVERANGE_START:
4797 case OP_LIVERANGE_END:
4798 break;
4799 case OP_ICONST:
4800 values [ins->dreg] = LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE);
4801 break;
4802 case OP_I8CONST:
4803 #if TARGET_SIZEOF_VOID_P == 4
4804 values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins), FALSE);
4805 #else
4806 values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), (gint64)ins->inst_c0, FALSE);
4807 #endif
4808 break;
4809 case OP_R8CONST:
4810 values [ins->dreg] = get_double_const (cfg, *(double*)ins->inst_p0);
4811 break;
4812 case OP_R4CONST:
4813 values [ins->dreg] = get_float_const (cfg, *(float*)ins->inst_p0);
4814 break;
4815 case OP_DUMMY_ICONST:
4816 values [ins->dreg] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
4817 break;
4818 case OP_DUMMY_I8CONST:
4819 values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
4820 break;
4821 case OP_DUMMY_R8CONST:
4822 values [ins->dreg] = LLVMConstReal (LLVMDoubleType (), 0.0f);
4823 break;
4824 case OP_BR: {
4825 LLVMBasicBlockRef target_bb = get_bb (ctx, ins->inst_target_bb);
4826 LLVMBuildBr (builder, target_bb);
4827 has_terminator = TRUE;
4828 break;
4830 case OP_SWITCH: {
4831 int i;
4832 LLVMValueRef v;
4833 char bb_name [128];
4834 LLVMBasicBlockRef new_bb;
4835 LLVMBuilderRef new_builder;
4837 // The default branch is already handled
4838 // FIXME: Handle it here
4840 /* Start new bblock */
4841 sprintf (bb_name, "SWITCH_DEFAULT_BB%d", ctx->default_index ++);
4842 new_bb = LLVMAppendBasicBlock (ctx->lmethod, bb_name);
4844 lhs = convert (ctx, lhs, LLVMInt32Type ());
4845 v = LLVMBuildSwitch (builder, lhs, new_bb, GPOINTER_TO_UINT (ins->klass));
4846 for (i = 0; i < GPOINTER_TO_UINT (ins->klass); ++i) {
4847 MonoBasicBlock *target_bb = ins->inst_many_bb [i];
4849 LLVMAddCase (v, LLVMConstInt (LLVMInt32Type (), i, FALSE), get_bb (ctx, target_bb));
4852 new_builder = create_builder (ctx);
4853 LLVMPositionBuilderAtEnd (new_builder, new_bb);
4854 LLVMBuildUnreachable (new_builder);
4856 has_terminator = TRUE;
4857 g_assert (!ins->next);
4859 break;
4862 case OP_SETRET:
4863 switch (linfo->ret.storage) {
4864 case LLVMArgVtypeInReg: {
4865 LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
4866 LLVMValueRef val, addr, retval;
4867 int i;
4869 retval = LLVMGetUndef (ret_type);
4871 if (!addresses [ins->sreg1]) {
4873 * The return type is an LLVM vector type, have to convert between it and the
4874 * real return type which is a struct type.
4876 g_assert (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (sig->ret)));
4877 /* Convert to 2xi64 first */
4878 val = LLVMBuildBitCast (builder, values [ins->sreg1], LLVMVectorType (IntPtrType (), 2), "");
4880 for (i = 0; i < 2; ++i) {
4881 if (linfo->ret.pair_storage [i] == LLVMArgInIReg) {
4882 retval = LLVMBuildInsertValue (builder, retval, LLVMBuildExtractElement (builder, val, LLVMConstInt (LLVMInt32Type (), i, FALSE), ""), i, "");
4883 } else {
4884 g_assert (linfo->ret.pair_storage [i] == LLVMArgNone);
4887 } else {
4888 addr = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), "");
4889 for (i = 0; i < 2; ++i) {
4890 if (linfo->ret.pair_storage [i] == LLVMArgInIReg) {
4891 LLVMValueRef indexes [2], part_addr;
4893 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
4894 indexes [1] = LLVMConstInt (LLVMInt32Type (), i, FALSE);
4895 part_addr = LLVMBuildGEP (builder, addr, indexes, 2, "");
4897 retval = LLVMBuildInsertValue (builder, retval, LLVMBuildLoad (builder, part_addr, ""), i, "");
4898 } else {
4899 g_assert (linfo->ret.pair_storage [i] == LLVMArgNone);
4903 LLVMBuildRet (builder, retval);
4904 break;
4906 case LLVMArgVtypeAsScalar: {
4907 LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
4908 LLVMValueRef retval;
4910 g_assert (addresses [ins->sreg1]);
4912 retval = LLVMBuildLoad (builder, LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), ""), "");
4913 LLVMBuildRet (builder, retval);
4914 break;
4916 case LLVMArgVtypeByVal: {
4917 LLVMValueRef retval;
4919 g_assert (addresses [ins->sreg1]);
4920 retval = LLVMBuildLoad (builder, addresses [ins->sreg1], "");
4921 LLVMBuildRet (builder, retval);
4922 break;
4924 case LLVMArgVtypeByRef: {
4925 LLVMBuildRetVoid (builder);
4926 break;
4928 case LLVMArgGsharedvtFixed: {
4929 LLVMTypeRef ret_type = type_to_llvm_type (ctx, sig->ret);
4930 /* The return value is in lhs, need to store to the vret argument */
4931 /* sreg1 might not be set */
4932 if (lhs) {
4933 g_assert (cfg->vret_addr);
4934 g_assert (values [cfg->vret_addr->dreg]);
4935 LLVMBuildStore (builder, convert (ctx, lhs, ret_type), convert (ctx, values [cfg->vret_addr->dreg], LLVMPointerType (ret_type, 0)));
4937 LLVMBuildRetVoid (builder);
4938 break;
4940 case LLVMArgGsharedvtFixedVtype: {
4941 /* Already set */
4942 LLVMBuildRetVoid (builder);
4943 break;
4945 case LLVMArgGsharedvtVariable: {
4946 /* Already set */
4947 LLVMBuildRetVoid (builder);
4948 break;
4950 case LLVMArgVtypeRetAddr: {
4951 LLVMBuildRetVoid (builder);
4952 break;
4954 case LLVMArgAsIArgs:
4955 case LLVMArgFpStruct: {
4956 LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
4957 LLVMValueRef retval;
4959 g_assert (addresses [ins->sreg1]);
4960 retval = LLVMBuildLoad (builder, convert (ctx, addresses [ins->sreg1], LLVMPointerType (ret_type, 0)), "");
4961 LLVMBuildRet (builder, retval);
4962 break;
4964 case LLVMArgNone:
4965 case LLVMArgNormal: {
4966 if (!lhs || ctx->is_dead [ins->sreg1]) {
4968 * The method did not set its return value, probably because it
4969 * ends with a throw.
4971 if (cfg->vret_addr)
4972 LLVMBuildRetVoid (builder);
4973 else
4974 LLVMBuildRet (builder, LLVMConstNull (type_to_llvm_type (ctx, sig->ret)));
4975 } else {
4976 LLVMBuildRet (builder, convert (ctx, lhs, type_to_llvm_type (ctx, sig->ret)));
4978 has_terminator = TRUE;
4979 break;
4981 default:
4982 g_assert_not_reached ();
4983 break;
4985 break;
4986 case OP_ICOMPARE:
4987 case OP_FCOMPARE:
4988 case OP_RCOMPARE:
4989 case OP_LCOMPARE:
4990 case OP_COMPARE:
4991 case OP_ICOMPARE_IMM:
4992 case OP_LCOMPARE_IMM:
4993 case OP_COMPARE_IMM: {
4994 CompRelation rel;
4995 LLVMValueRef cmp, args [16];
4996 gboolean likely = (ins->flags & MONO_INST_LIKELY) != 0;
4997 gboolean unlikely = FALSE;
4999 if (MONO_IS_COND_BRANCH_OP (ins->next)) {
5000 if (ins->next->inst_false_bb->out_of_line)
5001 likely = TRUE;
5002 else if (ins->next->inst_true_bb->out_of_line)
5003 unlikely = TRUE;
5006 if (ins->next->opcode == OP_NOP)
5007 break;
5009 if (ins->next->opcode == OP_BR)
5010 /* The comparison result is not needed */
5011 continue;
5013 rel = mono_opcode_to_cond (ins->next->opcode);
5015 if (ins->opcode == OP_ICOMPARE_IMM) {
5016 lhs = convert (ctx, lhs, LLVMInt32Type ());
5017 rhs = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
5019 if (ins->opcode == OP_LCOMPARE_IMM) {
5020 lhs = convert (ctx, lhs, LLVMInt64Type ());
5021 rhs = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins), FALSE);
5023 if (ins->opcode == OP_LCOMPARE) {
5024 lhs = convert (ctx, lhs, LLVMInt64Type ());
5025 rhs = convert (ctx, rhs, LLVMInt64Type ());
5027 if (ins->opcode == OP_ICOMPARE) {
5028 lhs = convert (ctx, lhs, LLVMInt32Type ());
5029 rhs = convert (ctx, rhs, LLVMInt32Type ());
5032 if (lhs && rhs) {
5033 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind)
5034 rhs = convert (ctx, rhs, LLVMTypeOf (lhs));
5035 else if (LLVMGetTypeKind (LLVMTypeOf (rhs)) == LLVMPointerTypeKind)
5036 lhs = convert (ctx, lhs, LLVMTypeOf (rhs));
5039 /* We use COMPARE+SETcc/Bcc, llvm uses SETcc+br cond */
5040 if (ins->opcode == OP_FCOMPARE) {
5041 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMDoubleType ()), convert (ctx, rhs, LLVMDoubleType ()), "");
5042 } else if (ins->opcode == OP_RCOMPARE) {
5043 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMFloatType ()), convert (ctx, rhs, LLVMFloatType ()), "");
5044 } else if (ins->opcode == OP_COMPARE_IMM) {
5045 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind && ins->inst_imm == 0)
5046 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, LLVMConstNull (LLVMTypeOf (lhs)), "");
5047 else
5048 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), "");
5049 } else if (ins->opcode == OP_LCOMPARE_IMM) {
5050 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, rhs, "");
5052 else if (ins->opcode == OP_COMPARE) {
5053 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind && LLVMTypeOf (lhs) == LLVMTypeOf (rhs))
5054 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, rhs, "");
5055 else
5056 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, IntPtrType ()), convert (ctx, rhs, IntPtrType ()), "");
5057 } else
5058 cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, rhs, "");
5060 if (likely || unlikely) {
5061 args [0] = cmp;
5062 args [1] = LLVMConstInt (LLVMInt1Type (), likely ? 1 : 0, FALSE);
5063 cmp = LLVMBuildCall (ctx->builder, get_intrins (ctx, INTRINS_EXPECT_I1), args, 2, "");
5066 if (MONO_IS_COND_BRANCH_OP (ins->next)) {
5067 if (ins->next->inst_true_bb == ins->next->inst_false_bb) {
5069 * If the target bb contains PHI instructions, LLVM requires
5070 * two PHI entries for this bblock, while we only generate one.
5071 * So convert this to an unconditional bblock. (bxc #171).
5073 LLVMBuildBr (builder, get_bb (ctx, ins->next->inst_true_bb));
5074 } else {
5075 LLVMBuildCondBr (builder, cmp, get_bb (ctx, ins->next->inst_true_bb), get_bb (ctx, ins->next->inst_false_bb));
5077 has_terminator = TRUE;
5078 } else if (MONO_IS_SETCC (ins->next)) {
5079 sprintf (dname_buf, "t%d", ins->next->dreg);
5080 dname = dname_buf;
5081 values [ins->next->dreg] = LLVMBuildZExt (builder, cmp, LLVMInt32Type (), dname);
5083 /* Add stores for volatile variables */
5084 emit_volatile_store (ctx, ins->next->dreg);
5085 } else if (MONO_IS_COND_EXC (ins->next)) {
5086 emit_cond_system_exception (ctx, bb, (const char*)ins->next->inst_p1, cmp);
5087 if (!ctx_ok (ctx))
5088 break;
5089 builder = ctx->builder;
5090 } else {
5091 set_failure (ctx, "next");
5092 break;
5095 ins = ins->next;
5096 break;
5098 case OP_FCEQ:
5099 case OP_FCNEQ:
5100 case OP_FCLT:
5101 case OP_FCLT_UN:
5102 case OP_FCGT:
5103 case OP_FCGT_UN:
5104 case OP_FCGE:
5105 case OP_FCLE: {
5106 CompRelation rel;
5107 LLVMValueRef cmp;
5109 rel = mono_opcode_to_cond (ins->opcode);
5111 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMDoubleType ()), convert (ctx, rhs, LLVMDoubleType ()), "");
5112 values [ins->dreg] = LLVMBuildZExt (builder, cmp, LLVMInt32Type (), dname);
5113 break;
5115 case OP_RCEQ:
5116 case OP_RCNEQ:
5117 case OP_RCLT:
5118 case OP_RCLT_UN:
5119 case OP_RCGT:
5120 case OP_RCGT_UN: {
5121 CompRelation rel;
5122 LLVMValueRef cmp;
5124 rel = mono_opcode_to_cond (ins->opcode);
5126 cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMFloatType ()), convert (ctx, rhs, LLVMFloatType ()), "");
5127 values [ins->dreg] = LLVMBuildZExt (builder, cmp, LLVMInt32Type (), dname);
5128 break;
5130 case OP_PHI:
5131 case OP_FPHI:
5132 case OP_VPHI:
5133 case OP_XPHI: {
5134 int i;
5135 gboolean empty = TRUE;
5137 /* Check that all input bblocks really branch to us */
5138 for (i = 0; i < bb->in_count; ++i) {
5139 if (bb->in_bb [i]->last_ins && bb->in_bb [i]->last_ins->opcode == OP_NOT_REACHED)
5140 ins->inst_phi_args [i + 1] = -1;
5141 else
5142 empty = FALSE;
5145 if (empty) {
5146 /* LLVM doesn't like phi instructions with zero operands */
5147 ctx->is_dead [ins->dreg] = TRUE;
5148 break;
5151 /* Created earlier, insert it now */
5152 LLVMInsertIntoBuilder (builder, values [ins->dreg]);
5154 for (i = 0; i < ins->inst_phi_args [0]; i++) {
5155 int sreg1 = ins->inst_phi_args [i + 1];
5156 int count, j;
5159 * Count the number of times the incoming bblock branches to us,
5160 * since llvm requires a separate entry for each.
5162 if (bb->in_bb [i]->last_ins && bb->in_bb [i]->last_ins->opcode == OP_SWITCH) {
5163 MonoInst *switch_ins = bb->in_bb [i]->last_ins;
5165 count = 0;
5166 for (j = 0; j < GPOINTER_TO_UINT (switch_ins->klass); ++j) {
5167 if (switch_ins->inst_many_bb [j] == bb)
5168 count ++;
5170 } else {
5171 count = 1;
5174 /* Remember for later */
5175 for (j = 0; j < count; ++j) {
5176 PhiNode *node = (PhiNode*)mono_mempool_alloc0 (ctx->mempool, sizeof (PhiNode));
5177 node->bb = bb;
5178 node->phi = ins;
5179 node->in_bb = bb->in_bb [i];
5180 node->sreg = sreg1;
5181 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);
5184 break;
5186 case OP_MOVE:
5187 case OP_LMOVE:
5188 case OP_XMOVE:
5189 case OP_SETFRET:
5190 g_assert (lhs);
5191 values [ins->dreg] = lhs;
5192 break;
5193 case OP_FMOVE:
5194 case OP_RMOVE: {
5195 MonoInst *var = get_vreg_to_inst (cfg, ins->dreg);
5197 g_assert (lhs);
5198 values [ins->dreg] = lhs;
5200 if (var && m_class_get_byval_arg (var->klass)->type == MONO_TYPE_R4) {
5202 * This is added by the spilling pass in case of the JIT,
5203 * but we have to do it ourselves.
5205 values [ins->dreg] = convert (ctx, values [ins->dreg], LLVMFloatType ());
5207 break;
5209 case OP_MOVE_F_TO_I4: {
5210 values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildFPTrunc (builder, lhs, LLVMFloatType (), ""), LLVMInt32Type (), "");
5211 break;
5213 case OP_MOVE_I4_TO_F: {
5214 values [ins->dreg] = LLVMBuildFPExt (builder, LLVMBuildBitCast (builder, lhs, LLVMFloatType (), ""), LLVMDoubleType (), "");
5215 break;
5217 case OP_MOVE_F_TO_I8: {
5218 values [ins->dreg] = LLVMBuildBitCast (builder, lhs, LLVMInt64Type (), "");
5219 break;
5221 case OP_MOVE_I8_TO_F: {
5222 values [ins->dreg] = LLVMBuildBitCast (builder, lhs, LLVMDoubleType (), "");
5223 break;
5225 case OP_IADD:
5226 case OP_ISUB:
5227 case OP_IAND:
5228 case OP_IMUL:
5229 case OP_IDIV:
5230 case OP_IDIV_UN:
5231 case OP_IREM:
5232 case OP_IREM_UN:
5233 case OP_IOR:
5234 case OP_IXOR:
5235 case OP_ISHL:
5236 case OP_ISHR:
5237 case OP_ISHR_UN:
5238 case OP_FADD:
5239 case OP_FSUB:
5240 case OP_FMUL:
5241 case OP_FDIV:
5242 case OP_LADD:
5243 case OP_LSUB:
5244 case OP_LMUL:
5245 case OP_LDIV:
5246 case OP_LDIV_UN:
5247 case OP_LREM:
5248 case OP_LREM_UN:
5249 case OP_LAND:
5250 case OP_LOR:
5251 case OP_LXOR:
5252 case OP_LSHL:
5253 case OP_LSHR:
5254 case OP_LSHR_UN:
5255 lhs = convert (ctx, lhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
5256 rhs = convert (ctx, rhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
5258 emit_div_check (ctx, builder, bb, ins, lhs, rhs);
5259 if (!ctx_ok (ctx))
5260 break;
5261 builder = ctx->builder;
5263 switch (ins->opcode) {
5264 case OP_IADD:
5265 case OP_LADD:
5266 values [ins->dreg] = LLVMBuildAdd (builder, lhs, rhs, dname);
5267 break;
5268 case OP_ISUB:
5269 case OP_LSUB:
5270 values [ins->dreg] = LLVMBuildSub (builder, lhs, rhs, dname);
5271 break;
5272 case OP_IMUL:
5273 case OP_LMUL:
5274 values [ins->dreg] = LLVMBuildMul (builder, lhs, rhs, dname);
5275 break;
5276 case OP_IREM:
5277 case OP_LREM:
5278 values [ins->dreg] = LLVMBuildSRem (builder, lhs, rhs, dname);
5279 break;
5280 case OP_IREM_UN:
5281 case OP_LREM_UN:
5282 values [ins->dreg] = LLVMBuildURem (builder, lhs, rhs, dname);
5283 break;
5284 case OP_IDIV:
5285 case OP_LDIV:
5286 values [ins->dreg] = LLVMBuildSDiv (builder, lhs, rhs, dname);
5287 break;
5288 case OP_IDIV_UN:
5289 case OP_LDIV_UN:
5290 values [ins->dreg] = LLVMBuildUDiv (builder, lhs, rhs, dname);
5291 break;
5292 case OP_FDIV:
5293 case OP_RDIV:
5294 values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, dname);
5295 break;
5296 case OP_IAND:
5297 case OP_LAND:
5298 values [ins->dreg] = LLVMBuildAnd (builder, lhs, rhs, dname);
5299 break;
5300 case OP_IOR:
5301 case OP_LOR:
5302 values [ins->dreg] = LLVMBuildOr (builder, lhs, rhs, dname);
5303 break;
5304 case OP_IXOR:
5305 case OP_LXOR:
5306 values [ins->dreg] = LLVMBuildXor (builder, lhs, rhs, dname);
5307 break;
5308 case OP_ISHL:
5309 case OP_LSHL:
5310 values [ins->dreg] = LLVMBuildShl (builder, lhs, rhs, dname);
5311 break;
5312 case OP_ISHR:
5313 case OP_LSHR:
5314 values [ins->dreg] = LLVMBuildAShr (builder, lhs, rhs, dname);
5315 break;
5316 case OP_ISHR_UN:
5317 case OP_LSHR_UN:
5318 values [ins->dreg] = LLVMBuildLShr (builder, lhs, rhs, dname);
5319 break;
5321 case OP_FADD:
5322 values [ins->dreg] = LLVMBuildFAdd (builder, lhs, rhs, dname);
5323 break;
5324 case OP_FSUB:
5325 values [ins->dreg] = LLVMBuildFSub (builder, lhs, rhs, dname);
5326 break;
5327 case OP_FMUL:
5328 values [ins->dreg] = LLVMBuildFMul (builder, lhs, rhs, dname);
5329 break;
5331 default:
5332 g_assert_not_reached ();
5334 break;
5335 case OP_RADD:
5336 case OP_RSUB:
5337 case OP_RMUL:
5338 case OP_RDIV: {
5339 lhs = convert (ctx, lhs, LLVMFloatType ());
5340 rhs = convert (ctx, rhs, LLVMFloatType ());
5341 switch (ins->opcode) {
5342 case OP_RADD:
5343 values [ins->dreg] = LLVMBuildFAdd (builder, lhs, rhs, dname);
5344 break;
5345 case OP_RSUB:
5346 values [ins->dreg] = LLVMBuildFSub (builder, lhs, rhs, dname);
5347 break;
5348 case OP_RMUL:
5349 values [ins->dreg] = LLVMBuildFMul (builder, lhs, rhs, dname);
5350 break;
5351 case OP_RDIV:
5352 values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, dname);
5353 break;
5354 default:
5355 g_assert_not_reached ();
5356 break;
5358 break;
5360 case OP_IADD_IMM:
5361 case OP_ISUB_IMM:
5362 case OP_IMUL_IMM:
5363 case OP_IREM_IMM:
5364 case OP_IREM_UN_IMM:
5365 case OP_IDIV_IMM:
5366 case OP_IDIV_UN_IMM:
5367 case OP_IAND_IMM:
5368 case OP_IOR_IMM:
5369 case OP_IXOR_IMM:
5370 case OP_ISHL_IMM:
5371 case OP_ISHR_IMM:
5372 case OP_ISHR_UN_IMM:
5373 case OP_LADD_IMM:
5374 case OP_LSUB_IMM:
5375 case OP_LMUL_IMM:
5376 case OP_LREM_IMM:
5377 case OP_LAND_IMM:
5378 case OP_LOR_IMM:
5379 case OP_LXOR_IMM:
5380 case OP_LSHL_IMM:
5381 case OP_LSHR_IMM:
5382 case OP_LSHR_UN_IMM:
5383 case OP_ADD_IMM:
5384 case OP_AND_IMM:
5385 case OP_MUL_IMM:
5386 case OP_SHL_IMM:
5387 case OP_SHR_IMM:
5388 case OP_SHR_UN_IMM: {
5389 LLVMValueRef imm;
5391 if (spec [MONO_INST_SRC1] == 'l') {
5392 imm = LLVMConstInt (LLVMInt64Type (), GET_LONG_IMM (ins), FALSE);
5393 } else {
5394 imm = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
5397 emit_div_check (ctx, builder, bb, ins, lhs, imm);
5398 if (!ctx_ok (ctx))
5399 break;
5400 builder = ctx->builder;
5402 #if TARGET_SIZEOF_VOID_P == 4
5403 if (ins->opcode == OP_LSHL_IMM || ins->opcode == OP_LSHR_IMM || ins->opcode == OP_LSHR_UN_IMM)
5404 imm = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
5405 #endif
5407 if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind)
5408 lhs = convert (ctx, lhs, IntPtrType ());
5409 imm = convert (ctx, imm, LLVMTypeOf (lhs));
5410 switch (ins->opcode) {
5411 case OP_IADD_IMM:
5412 case OP_LADD_IMM:
5413 case OP_ADD_IMM:
5414 values [ins->dreg] = LLVMBuildAdd (builder, lhs, imm, dname);
5415 break;
5416 case OP_ISUB_IMM:
5417 case OP_LSUB_IMM:
5418 values [ins->dreg] = LLVMBuildSub (builder, lhs, imm, dname);
5419 break;
5420 case OP_IMUL_IMM:
5421 case OP_MUL_IMM:
5422 case OP_LMUL_IMM:
5423 values [ins->dreg] = LLVMBuildMul (builder, lhs, imm, dname);
5424 break;
5425 case OP_IDIV_IMM:
5426 case OP_LDIV_IMM:
5427 values [ins->dreg] = LLVMBuildSDiv (builder, lhs, imm, dname);
5428 break;
5429 case OP_IDIV_UN_IMM:
5430 case OP_LDIV_UN_IMM:
5431 values [ins->dreg] = LLVMBuildUDiv (builder, lhs, imm, dname);
5432 break;
5433 case OP_IREM_IMM:
5434 case OP_LREM_IMM:
5435 values [ins->dreg] = LLVMBuildSRem (builder, lhs, imm, dname);
5436 break;
5437 case OP_IREM_UN_IMM:
5438 values [ins->dreg] = LLVMBuildURem (builder, lhs, imm, dname);
5439 break;
5440 case OP_IAND_IMM:
5441 case OP_LAND_IMM:
5442 case OP_AND_IMM:
5443 values [ins->dreg] = LLVMBuildAnd (builder, lhs, imm, dname);
5444 break;
5445 case OP_IOR_IMM:
5446 case OP_LOR_IMM:
5447 values [ins->dreg] = LLVMBuildOr (builder, lhs, imm, dname);
5448 break;
5449 case OP_IXOR_IMM:
5450 case OP_LXOR_IMM:
5451 values [ins->dreg] = LLVMBuildXor (builder, lhs, imm, dname);
5452 break;
5453 case OP_ISHL_IMM:
5454 case OP_LSHL_IMM:
5455 values [ins->dreg] = LLVMBuildShl (builder, lhs, imm, dname);
5456 break;
5457 case OP_SHL_IMM:
5458 if (TARGET_SIZEOF_VOID_P == 8) {
5459 /* The IL is not regular */
5460 lhs = convert (ctx, lhs, LLVMInt64Type ());
5461 imm = convert (ctx, imm, LLVMInt64Type ());
5463 values [ins->dreg] = LLVMBuildShl (builder, lhs, imm, dname);
5464 break;
5465 case OP_ISHR_IMM:
5466 case OP_LSHR_IMM:
5467 case OP_SHR_IMM:
5468 values [ins->dreg] = LLVMBuildAShr (builder, lhs, imm, dname);
5469 break;
5470 case OP_ISHR_UN_IMM:
5471 /* This is used to implement conv.u4, so the lhs could be an i8 */
5472 lhs = convert (ctx, lhs, LLVMInt32Type ());
5473 imm = convert (ctx, imm, LLVMInt32Type ());
5474 values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
5475 break;
5476 case OP_LSHR_UN_IMM:
5477 case OP_SHR_UN_IMM:
5478 values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
5479 break;
5480 default:
5481 g_assert_not_reached ();
5483 break;
5485 case OP_INEG:
5486 values [ins->dreg] = LLVMBuildSub (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), convert (ctx, lhs, LLVMInt32Type ()), dname);
5487 break;
5488 case OP_LNEG:
5489 if (LLVMTypeOf (lhs) != LLVMInt64Type ())
5490 lhs = convert (ctx, lhs, LLVMInt64Type ());
5491 values [ins->dreg] = LLVMBuildSub (builder, LLVMConstInt (LLVMInt64Type (), 0, FALSE), lhs, dname);
5492 break;
5493 case OP_FNEG:
5494 lhs = convert (ctx, lhs, LLVMDoubleType ());
5495 values [ins->dreg] = LLVMBuildFSub (builder, LLVMConstReal (LLVMDoubleType (), 0.0), lhs, dname);
5496 break;
5497 case OP_RNEG:
5498 lhs = convert (ctx, lhs, LLVMFloatType ());
5499 values [ins->dreg] = LLVMBuildFSub (builder, LLVMConstReal (LLVMFloatType (), 0.0), lhs, dname);
5500 break;
5501 case OP_INOT: {
5502 guint32 v = 0xffffffff;
5503 values [ins->dreg] = LLVMBuildXor (builder, LLVMConstInt (LLVMInt32Type (), v, FALSE), convert (ctx, lhs, LLVMInt32Type ()), dname);
5504 break;
5506 case OP_LNOT: {
5507 if (LLVMTypeOf (lhs) != LLVMInt64Type ())
5508 lhs = convert (ctx, lhs, LLVMInt64Type ());
5509 guint64 v = 0xffffffffffffffffLL;
5510 values [ins->dreg] = LLVMBuildXor (builder, LLVMConstInt (LLVMInt64Type (), v, FALSE), lhs, dname);
5511 break;
5513 #if defined(TARGET_X86) || defined(TARGET_AMD64)
5514 case OP_X86_LEA: {
5515 LLVMValueRef v1, v2;
5517 rhs = LLVMBuildSExt (builder, convert (ctx, rhs, LLVMInt32Type ()), LLVMInt64Type (), "");
5519 v1 = LLVMBuildMul (builder, convert (ctx, rhs, IntPtrType ()), LLVMConstInt (IntPtrType (), ((unsigned long long)1 << ins->backend.shift_amount), FALSE), "");
5520 v2 = LLVMBuildAdd (builder, convert (ctx, lhs, IntPtrType ()), v1, "");
5521 values [ins->dreg] = LLVMBuildAdd (builder, v2, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), dname);
5522 break;
5524 #endif
5526 case OP_ICONV_TO_I1:
5527 case OP_ICONV_TO_I2:
5528 case OP_ICONV_TO_I4:
5529 case OP_ICONV_TO_U1:
5530 case OP_ICONV_TO_U2:
5531 case OP_ICONV_TO_U4:
5532 case OP_LCONV_TO_I1:
5533 case OP_LCONV_TO_I2:
5534 case OP_LCONV_TO_U1:
5535 case OP_LCONV_TO_U2:
5536 case OP_LCONV_TO_U4: {
5537 gboolean sign;
5539 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);
5541 /* Have to do two casts since our vregs have type int */
5542 v = LLVMBuildTrunc (builder, lhs, op_to_llvm_type (ins->opcode), "");
5543 if (sign)
5544 values [ins->dreg] = LLVMBuildSExt (builder, v, LLVMInt32Type (), dname);
5545 else
5546 values [ins->dreg] = LLVMBuildZExt (builder, v, LLVMInt32Type (), dname);
5547 break;
5549 case OP_ICONV_TO_I8:
5550 values [ins->dreg] = LLVMBuildSExt (builder, lhs, LLVMInt64Type (), dname);
5551 break;
5552 case OP_ICONV_TO_U8:
5553 values [ins->dreg] = LLVMBuildZExt (builder, lhs, LLVMInt64Type (), dname);
5554 break;
5555 case OP_FCONV_TO_I4:
5556 case OP_RCONV_TO_I4:
5557 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, LLVMInt32Type (), dname);
5558 break;
5559 case OP_FCONV_TO_I1:
5560 case OP_RCONV_TO_I1:
5561 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildFPToSI (builder, lhs, LLVMInt8Type (), dname), LLVMInt32Type (), "");
5562 break;
5563 case OP_FCONV_TO_U1:
5564 case OP_RCONV_TO_U1:
5565 values [ins->dreg] = LLVMBuildZExt (builder, LLVMBuildTrunc (builder, LLVMBuildFPToUI (builder, lhs, IntPtrType (), dname), LLVMInt8Type (), ""), LLVMInt32Type (), "");
5566 break;
5567 case OP_FCONV_TO_I2:
5568 case OP_RCONV_TO_I2:
5569 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildFPToSI (builder, lhs, LLVMInt16Type (), dname), LLVMInt32Type (), "");
5570 break;
5571 case OP_FCONV_TO_U2:
5572 case OP_RCONV_TO_U2:
5573 values [ins->dreg] = LLVMBuildZExt (builder, LLVMBuildFPToUI (builder, lhs, LLVMInt16Type (), dname), LLVMInt32Type (), "");
5574 break;
5575 case OP_RCONV_TO_U4:
5576 values [ins->dreg] = LLVMBuildFPToUI (builder, lhs, LLVMInt32Type (), dname);
5577 break;
5578 case OP_FCONV_TO_I8:
5579 case OP_RCONV_TO_I8:
5580 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, LLVMInt64Type (), dname);
5581 break;
5582 case OP_FCONV_TO_I:
5583 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, IntPtrType (), dname);
5584 break;
5585 case OP_ICONV_TO_R8:
5586 case OP_LCONV_TO_R8:
5587 values [ins->dreg] = LLVMBuildSIToFP (builder, lhs, LLVMDoubleType (), dname);
5588 break;
5589 case OP_ICONV_TO_R_UN:
5590 case OP_LCONV_TO_R_UN:
5591 values [ins->dreg] = LLVMBuildUIToFP (builder, lhs, LLVMDoubleType (), dname);
5592 break;
5593 #if TARGET_SIZEOF_VOID_P == 4
5594 case OP_LCONV_TO_U:
5595 #endif
5596 case OP_LCONV_TO_I4:
5597 values [ins->dreg] = LLVMBuildTrunc (builder, lhs, LLVMInt32Type (), dname);
5598 break;
5599 case OP_ICONV_TO_R4:
5600 case OP_LCONV_TO_R4:
5601 v = LLVMBuildSIToFP (builder, lhs, LLVMFloatType (), "");
5602 if (cfg->r4fp)
5603 values [ins->dreg] = v;
5604 else
5605 values [ins->dreg] = LLVMBuildFPExt (builder, v, LLVMDoubleType (), dname);
5606 break;
5607 case OP_FCONV_TO_R4:
5608 v = LLVMBuildFPTrunc (builder, lhs, LLVMFloatType (), "");
5609 if (cfg->r4fp)
5610 values [ins->dreg] = v;
5611 else
5612 values [ins->dreg] = LLVMBuildFPExt (builder, v, LLVMDoubleType (), dname);
5613 break;
5614 case OP_RCONV_TO_R8:
5615 values [ins->dreg] = LLVMBuildFPExt (builder, lhs, LLVMDoubleType (), dname);
5616 break;
5617 case OP_RCONV_TO_R4:
5618 values [ins->dreg] = lhs;
5619 break;
5620 case OP_SEXT_I4:
5621 values [ins->dreg] = LLVMBuildSExt (builder, convert (ctx, lhs, LLVMInt32Type ()), LLVMInt64Type (), dname);
5622 break;
5623 case OP_ZEXT_I4:
5624 values [ins->dreg] = LLVMBuildZExt (builder, convert (ctx, lhs, LLVMInt32Type ()), LLVMInt64Type (), dname);
5625 break;
5626 case OP_TRUNC_I4:
5627 values [ins->dreg] = LLVMBuildTrunc (builder, lhs, LLVMInt32Type (), dname);
5628 break;
5629 case OP_LOCALLOC_IMM: {
5630 LLVMValueRef v;
5632 guint32 size = ins->inst_imm;
5633 size = (size + (MONO_ARCH_FRAME_ALIGNMENT - 1)) & ~ (MONO_ARCH_FRAME_ALIGNMENT - 1);
5635 v = mono_llvm_build_alloca (builder, LLVMInt8Type (), LLVMConstInt (LLVMInt32Type (), size, FALSE), MONO_ARCH_FRAME_ALIGNMENT, "");
5637 if (ins->flags & MONO_INST_INIT) {
5638 LLVMValueRef args [5];
5640 args [0] = v;
5641 args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
5642 args [2] = LLVMConstInt (LLVMInt32Type (), size, FALSE);
5643 args [3] = LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT, FALSE);
5644 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5645 LLVMBuildCall (builder, get_intrins (ctx, INTRINS_MEMSET), args, 5, "");
5648 values [ins->dreg] = v;
5649 break;
5651 case OP_LOCALLOC: {
5652 LLVMValueRef v, size;
5654 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), "");
5656 v = mono_llvm_build_alloca (builder, LLVMInt8Type (), size, MONO_ARCH_FRAME_ALIGNMENT, "");
5658 if (ins->flags & MONO_INST_INIT) {
5659 LLVMValueRef args [5];
5661 args [0] = v;
5662 args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
5663 args [2] = size;
5664 args [3] = LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT, FALSE);
5665 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
5666 LLVMBuildCall (builder, get_intrins (ctx, INTRINS_MEMSET), args, 5, "");
5668 values [ins->dreg] = v;
5669 break;
5672 case OP_LOADI1_MEMBASE:
5673 case OP_LOADU1_MEMBASE:
5674 case OP_LOADI2_MEMBASE:
5675 case OP_LOADU2_MEMBASE:
5676 case OP_LOADI4_MEMBASE:
5677 case OP_LOADU4_MEMBASE:
5678 case OP_LOADI8_MEMBASE:
5679 case OP_LOADR4_MEMBASE:
5680 case OP_LOADR8_MEMBASE:
5681 case OP_LOAD_MEMBASE:
5682 case OP_LOADI8_MEM:
5683 case OP_LOADU1_MEM:
5684 case OP_LOADU2_MEM:
5685 case OP_LOADI4_MEM:
5686 case OP_LOADU4_MEM:
5687 case OP_LOAD_MEM: {
5688 int size = 8;
5689 LLVMValueRef base, index, addr;
5690 LLVMTypeRef t;
5691 gboolean sext = FALSE, zext = FALSE;
5692 gboolean is_volatile = (ins->flags & (MONO_INST_FAULT | MONO_INST_VOLATILE)) != 0;
5694 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5696 if (sext || zext)
5697 dname = (char*)"";
5699 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)) {
5700 addr = LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE);
5701 base = addr;
5702 } else {
5703 /* _MEMBASE */
5704 base = lhs;
5706 if (ins->inst_offset == 0) {
5707 addr = base;
5708 } else if (ins->inst_offset % size != 0) {
5709 /* Unaligned load */
5710 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
5711 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
5712 } else {
5713 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5714 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5718 addr = convert (ctx, addr, LLVMPointerType (t, 0));
5720 values [ins->dreg] = emit_load_general (ctx, bb, &builder, size, addr, base, dname, is_volatile, LLVM_BARRIER_NONE);
5722 if (!is_volatile && (ins->flags & MONO_INST_INVARIANT_LOAD)) {
5724 * These will signal LLVM that these loads do not alias any stores, and
5725 * they can't fail, allowing them to be hoisted out of loops.
5727 set_invariant_load_flag (values [ins->dreg]);
5728 #if LLVM_API_VERSION < 100
5729 set_metadata_flag (values [ins->dreg], "mono.nofail.load");
5730 #endif
5733 if (sext)
5734 values [ins->dreg] = LLVMBuildSExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5735 else if (zext)
5736 values [ins->dreg] = LLVMBuildZExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
5737 else if (!cfg->r4fp && ins->opcode == OP_LOADR4_MEMBASE)
5738 values [ins->dreg] = LLVMBuildFPExt (builder, values [ins->dreg], LLVMDoubleType (), dname);
5739 break;
5742 case OP_STOREI1_MEMBASE_REG:
5743 case OP_STOREI2_MEMBASE_REG:
5744 case OP_STOREI4_MEMBASE_REG:
5745 case OP_STOREI8_MEMBASE_REG:
5746 case OP_STORER4_MEMBASE_REG:
5747 case OP_STORER8_MEMBASE_REG:
5748 case OP_STORE_MEMBASE_REG: {
5749 int size = 8;
5750 LLVMValueRef index, addr, base;
5751 LLVMTypeRef t;
5752 gboolean sext = FALSE, zext = FALSE;
5753 gboolean is_volatile = (ins->flags & (MONO_INST_FAULT | MONO_INST_VOLATILE)) != 0;
5755 if (!values [ins->inst_destbasereg]) {
5756 set_failure (ctx, "inst_destbasereg");
5757 break;
5760 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5762 base = values [ins->inst_destbasereg];
5763 if (ins->inst_offset % size != 0) {
5764 /* Unaligned store */
5765 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
5766 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
5767 } else {
5768 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5769 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5771 emit_store (ctx, bb, &builder, size, convert (ctx, values [ins->sreg1], t), convert (ctx, addr, LLVMPointerType (t, 0)), base, is_volatile);
5772 break;
5775 case OP_STOREI1_MEMBASE_IMM:
5776 case OP_STOREI2_MEMBASE_IMM:
5777 case OP_STOREI4_MEMBASE_IMM:
5778 case OP_STOREI8_MEMBASE_IMM:
5779 case OP_STORE_MEMBASE_IMM: {
5780 int size = 8;
5781 LLVMValueRef index, addr, base;
5782 LLVMTypeRef t;
5783 gboolean sext = FALSE, zext = FALSE;
5784 gboolean is_volatile = (ins->flags & (MONO_INST_FAULT | MONO_INST_VOLATILE)) != 0;
5786 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
5788 base = values [ins->inst_destbasereg];
5789 if (ins->inst_offset % size != 0) {
5790 /* Unaligned store */
5791 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
5792 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
5793 } else {
5794 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
5795 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
5797 emit_store (ctx, bb, &builder, size, convert (ctx, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), t), convert (ctx, addr, LLVMPointerType (t, 0)), base, is_volatile);
5798 break;
5801 case OP_CHECK_THIS:
5802 emit_load_general (ctx, bb, &builder, TARGET_SIZEOF_VOID_P, convert (ctx, lhs, LLVMPointerType (IntPtrType (), 0)), lhs, "", TRUE, LLVM_BARRIER_NONE);
5803 break;
5804 case OP_OUTARG_VTRETADDR:
5805 break;
5806 case OP_VOIDCALL:
5807 case OP_CALL:
5808 case OP_LCALL:
5809 case OP_FCALL:
5810 case OP_RCALL:
5811 case OP_VCALL:
5812 case OP_VOIDCALL_MEMBASE:
5813 case OP_CALL_MEMBASE:
5814 case OP_LCALL_MEMBASE:
5815 case OP_FCALL_MEMBASE:
5816 case OP_RCALL_MEMBASE:
5817 case OP_VCALL_MEMBASE:
5818 case OP_VOIDCALL_REG:
5819 case OP_CALL_REG:
5820 case OP_LCALL_REG:
5821 case OP_FCALL_REG:
5822 case OP_RCALL_REG:
5823 case OP_VCALL_REG: {
5824 process_call (ctx, bb, &builder, ins);
5825 break;
5827 case OP_AOTCONST: {
5828 guint32 got_offset;
5829 LLVMValueRef indexes [2];
5830 MonoJumpInfo *tmp_ji, *ji;
5831 LLVMValueRef got_entry_addr;
5832 char *name;
5835 * FIXME: Can't allocate from the cfg mempool since that is freed if
5836 * the LLVM compile fails.
5838 tmp_ji = g_new0 (MonoJumpInfo, 1);
5839 tmp_ji->type = (MonoJumpInfoType)ins->inst_c1;
5840 tmp_ji->data.target = ins->inst_p0;
5842 ji = mono_aot_patch_info_dup (tmp_ji);
5843 g_free (tmp_ji);
5845 if (ji->type == MONO_PATCH_INFO_ICALL_ADDR) {
5846 char *symbol = mono_aot_get_direct_call_symbol (MONO_PATCH_INFO_ICALL_ADDR_CALL, ji->data.target);
5847 if (symbol) {
5849 * Avoid emitting a got entry for these since the method is directly called, and it might not be
5850 * resolvable at runtime using dlsym ().
5852 g_free (symbol);
5853 values [ins->dreg] = LLVMConstInt (IntPtrType (), 0, FALSE);
5854 break;
5858 ji->next = cfg->patch_info;
5859 cfg->patch_info = ji;
5861 //mono_add_patch_info (cfg, 0, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
5862 got_offset = compute_aot_got_offset (ctx->module, cfg->patch_info, NULL);
5864 ctx->module->max_got_offset = MAX (ctx->module->max_got_offset, got_offset);
5865 if (!mono_aot_is_shared_got_offset (got_offset)) {
5866 //mono_print_ji (ji);
5867 //printf ("\n");
5868 ctx->cfg->got_access_count ++;
5871 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
5872 indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
5873 got_entry_addr = LLVMBuildGEP (builder, ctx->module->got_var, indexes, 2, "");
5875 name = get_aotconst_name (ji->type, ji->data.target, got_offset);
5876 values [ins->dreg] = LLVMBuildLoad (builder, got_entry_addr, name);
5877 g_free (name);
5878 /* Can't use this in llvmonly mode since the got slots are initialized by the methods themselves */
5879 if (!cfg->llvm_only || mono_aot_is_shared_got_offset (got_offset))
5880 set_invariant_load_flag (values [ins->dreg]);
5881 break;
5883 case OP_NOT_REACHED:
5884 LLVMBuildUnreachable (builder);
5885 has_terminator = TRUE;
5886 g_assert (bb->block_num < cfg->max_block_num);
5887 ctx->unreachable [bb->block_num] = TRUE;
5888 /* Might have instructions after this */
5889 while (ins->next) {
5890 MonoInst *next = ins->next;
5892 * FIXME: If later code uses the regs defined by these instructions,
5893 * compilation will fail.
5895 MONO_DELETE_INS (bb, next);
5897 break;
5898 case OP_LDADDR: {
5899 MonoInst *var = ins->inst_i0;
5901 if (var->opcode == OP_VTARG_ADDR) {
5902 /* The variable contains the vtype address */
5903 values [ins->dreg] = values [var->dreg];
5904 } else if (var->opcode == OP_GSHAREDVT_LOCAL) {
5905 values [ins->dreg] = emit_gsharedvt_ldaddr (ctx, var->dreg);
5906 } else {
5907 values [ins->dreg] = addresses [var->dreg];
5909 break;
5911 case OP_SIN: {
5912 LLVMValueRef args [1];
5914 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5915 values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_SIN), args, 1, dname);
5916 break;
5918 case OP_SINF: {
5919 LLVMValueRef args [1];
5921 args [0] = convert (ctx, lhs, LLVMFloatType ());
5922 values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_SINF), args, 1, dname);
5923 break;
5925 case OP_COS: {
5926 LLVMValueRef args [1];
5928 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5929 values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_COS), args, 1, dname);
5930 break;
5932 case OP_COSF: {
5933 LLVMValueRef args [1];
5935 args [0] = convert (ctx, lhs, LLVMFloatType ());
5936 values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_COSF), args, 1, dname);
5937 break;
5939 case OP_SQRT: {
5940 LLVMValueRef args [1];
5942 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5943 values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_SQRT), args, 1, dname);
5944 break;
5946 case OP_SQRTF: {
5947 LLVMValueRef args [1];
5949 args [0] = convert (ctx, lhs, LLVMFloatType ());
5950 values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_SQRTF), args, 1, dname);
5951 break;
5953 case OP_ABS: {
5954 LLVMValueRef args [1];
5956 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5957 values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_FABS), args, 1, dname);
5958 break;
5960 case OP_ABSF: {
5961 LLVMValueRef args [1];
5963 #ifdef TARGET_AMD64
5964 args [0] = convert (ctx, lhs, LLVMFloatType ());
5965 values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_ABSF), args, 1, dname);
5966 #else
5967 /* llvm.fabs not supported on all platforms */
5968 args [0] = convert (ctx, lhs, LLVMDoubleType ());
5969 values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_FABS), args, 1, dname);
5970 values [ins->dreg] = convert (ctx, values [ins->dreg], LLVMFloatType ());
5971 #endif
5972 break;
5974 case OP_RPOW: {
5975 LLVMValueRef args [2];
5977 args [0] = convert (ctx, lhs, LLVMFloatType ());
5978 args [1] = convert (ctx, rhs, LLVMFloatType ());
5979 values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_POWF), args, 2, dname);
5980 break;
5983 case OP_IMIN:
5984 case OP_LMIN:
5985 case OP_IMAX:
5986 case OP_LMAX:
5987 case OP_IMIN_UN:
5988 case OP_LMIN_UN:
5989 case OP_IMAX_UN:
5990 case OP_LMAX_UN:
5991 case OP_RMAX: {
5992 LLVMValueRef v;
5994 lhs = convert (ctx, lhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
5995 rhs = convert (ctx, rhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
5997 switch (ins->opcode) {
5998 case OP_IMIN:
5999 case OP_LMIN:
6000 v = LLVMBuildICmp (builder, LLVMIntSLE, lhs, rhs, "");
6001 break;
6002 case OP_IMAX:
6003 case OP_LMAX:
6004 v = LLVMBuildICmp (builder, LLVMIntSGE, lhs, rhs, "");
6005 break;
6006 case OP_IMIN_UN:
6007 case OP_LMIN_UN:
6008 v = LLVMBuildICmp (builder, LLVMIntULE, lhs, rhs, "");
6009 break;
6010 case OP_IMAX_UN:
6011 case OP_LMAX_UN:
6012 v = LLVMBuildICmp (builder, LLVMIntUGE, lhs, rhs, "");
6013 break;
6014 case OP_RMAX:
6015 v = LLVMBuildFCmp (builder, LLVMRealUGE, lhs, rhs, "");
6016 break;
6017 default:
6018 g_assert_not_reached ();
6019 break;
6021 values [ins->dreg] = LLVMBuildSelect (builder, v, lhs, rhs, dname);
6022 break;
6026 * See the ARM64 comment in mono/utils/atomic.h for an explanation of why this
6027 * hack is necessary (for now).
6029 #ifdef TARGET_ARM64
6030 #define ARM64_ATOMIC_FENCE_FIX mono_llvm_build_fence (builder, LLVM_BARRIER_SEQ)
6031 #else
6032 #define ARM64_ATOMIC_FENCE_FIX
6033 #endif
6035 case OP_ATOMIC_EXCHANGE_I4:
6036 case OP_ATOMIC_EXCHANGE_I8: {
6037 LLVMValueRef args [2];
6038 LLVMTypeRef t;
6040 if (ins->opcode == OP_ATOMIC_EXCHANGE_I4)
6041 t = LLVMInt32Type ();
6042 else
6043 t = LLVMInt64Type ();
6045 g_assert (ins->inst_offset == 0);
6047 args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
6048 args [1] = convert (ctx, rhs, t);
6050 ARM64_ATOMIC_FENCE_FIX;
6051 values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
6052 ARM64_ATOMIC_FENCE_FIX;
6053 break;
6055 case OP_ATOMIC_ADD_I4:
6056 case OP_ATOMIC_ADD_I8: {
6057 LLVMValueRef args [2];
6058 LLVMTypeRef t;
6060 if (ins->opcode == OP_ATOMIC_ADD_I4)
6061 t = LLVMInt32Type ();
6062 else
6063 t = LLVMInt64Type ();
6065 g_assert (ins->inst_offset == 0);
6067 args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
6068 args [1] = convert (ctx, rhs, t);
6069 ARM64_ATOMIC_FENCE_FIX;
6070 values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname);
6071 ARM64_ATOMIC_FENCE_FIX;
6072 break;
6074 case OP_ATOMIC_CAS_I4:
6075 case OP_ATOMIC_CAS_I8: {
6076 LLVMValueRef args [3], val;
6077 LLVMTypeRef t;
6079 if (ins->opcode == OP_ATOMIC_CAS_I4)
6080 t = LLVMInt32Type ();
6081 else
6082 t = LLVMInt64Type ();
6084 args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
6085 /* comparand */
6086 args [1] = convert (ctx, values [ins->sreg3], t);
6087 /* new value */
6088 args [2] = convert (ctx, values [ins->sreg2], t);
6089 ARM64_ATOMIC_FENCE_FIX;
6090 val = mono_llvm_build_cmpxchg (builder, args [0], args [1], args [2]);
6091 ARM64_ATOMIC_FENCE_FIX;
6092 /* cmpxchg returns a pair */
6093 values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, "");
6094 break;
6096 case OP_MEMORY_BARRIER: {
6097 mono_llvm_build_fence (builder, (BarrierKind) ins->backend.memory_barrier_kind);
6098 break;
6100 case OP_ATOMIC_LOAD_I1:
6101 case OP_ATOMIC_LOAD_I2:
6102 case OP_ATOMIC_LOAD_I4:
6103 case OP_ATOMIC_LOAD_I8:
6104 case OP_ATOMIC_LOAD_U1:
6105 case OP_ATOMIC_LOAD_U2:
6106 case OP_ATOMIC_LOAD_U4:
6107 case OP_ATOMIC_LOAD_U8:
6108 case OP_ATOMIC_LOAD_R4:
6109 case OP_ATOMIC_LOAD_R8: {
6110 #if LLVM_API_VERSION > 100
6111 int size;
6112 gboolean sext, zext;
6113 LLVMTypeRef t;
6114 gboolean is_volatile = (ins->flags & (MONO_INST_FAULT | MONO_INST_VOLATILE)) != 0;
6115 BarrierKind barrier = (BarrierKind) ins->backend.memory_barrier_kind;
6116 LLVMValueRef index, addr;
6118 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
6120 if (sext || zext)
6121 dname = (char *)"";
6123 if (ins->inst_offset != 0) {
6124 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
6125 addr = LLVMBuildGEP (builder, convert (ctx, lhs, LLVMPointerType (t, 0)), &index, 1, "");
6126 } else {
6127 addr = lhs;
6130 addr = convert (ctx, addr, LLVMPointerType (t, 0));
6132 ARM64_ATOMIC_FENCE_FIX;
6133 values [ins->dreg] = emit_load_general (ctx, bb, &builder, size, addr, lhs, dname, is_volatile, barrier);
6134 ARM64_ATOMIC_FENCE_FIX;
6136 if (sext)
6137 values [ins->dreg] = LLVMBuildSExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
6138 else if (zext)
6139 values [ins->dreg] = LLVMBuildZExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
6140 break;
6141 #else
6142 set_failure (ctx, "atomic mono.load intrinsic");
6143 break;
6144 #endif
6146 case OP_ATOMIC_STORE_I1:
6147 case OP_ATOMIC_STORE_I2:
6148 case OP_ATOMIC_STORE_I4:
6149 case OP_ATOMIC_STORE_I8:
6150 case OP_ATOMIC_STORE_U1:
6151 case OP_ATOMIC_STORE_U2:
6152 case OP_ATOMIC_STORE_U4:
6153 case OP_ATOMIC_STORE_U8:
6154 case OP_ATOMIC_STORE_R4:
6155 case OP_ATOMIC_STORE_R8: {
6156 int size;
6157 gboolean sext, zext;
6158 LLVMTypeRef t;
6159 gboolean is_volatile = (ins->flags & (MONO_INST_FAULT | MONO_INST_VOLATILE)) != 0;
6160 BarrierKind barrier = (BarrierKind) ins->backend.memory_barrier_kind;
6161 LLVMValueRef index, addr, value, base;
6163 #if LLVM_API_VERSION < 100
6164 if (!cfg->llvm_only) {
6165 set_failure (ctx, "atomic mono.store intrinsic");
6166 break;
6168 #endif
6170 if (!values [ins->inst_destbasereg]) {
6171 set_failure (ctx, "inst_destbasereg");
6172 break;
6175 t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
6177 base = values [ins->inst_destbasereg];
6178 index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
6179 addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
6180 value = convert (ctx, values [ins->sreg1], t);
6182 ARM64_ATOMIC_FENCE_FIX;
6183 emit_store_general (ctx, bb, &builder, size, value, addr, base, is_volatile, barrier);
6184 ARM64_ATOMIC_FENCE_FIX;
6185 break;
6187 case OP_RELAXED_NOP: {
6188 #if defined(TARGET_AMD64) || defined(TARGET_X86)
6189 emit_call (ctx, bb, &builder, get_intrins_by_name (ctx, "llvm.x86.sse2.pause"), NULL, 0);
6190 break;
6191 #else
6192 break;
6193 #endif
6195 case OP_TLS_GET: {
6196 #if (defined(TARGET_AMD64) || defined(TARGET_X86)) && defined(__linux__)
6197 #ifdef TARGET_AMD64
6198 // 257 == FS segment register
6199 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 257);
6200 #else
6201 // 256 == GS segment register
6202 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
6203 #endif
6204 // FIXME: XEN
6205 values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), ins->inst_offset, TRUE), ptrtype, ""), "");
6206 #elif defined(TARGET_AMD64) && defined(TARGET_OSX)
6207 /* See mono_amd64_emit_tls_get () */
6208 int offset = mono_amd64_get_tls_gs_offset () + (ins->inst_offset * 8);
6210 // 256 == GS segment register
6211 LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
6212 values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), offset, TRUE), ptrtype, ""), "");
6213 #else
6214 set_failure (ctx, "opcode tls-get");
6215 break;
6216 #endif
6218 break;
6220 case OP_GC_SAFE_POINT: {
6221 LLVMValueRef val, cmp, callee;
6222 LLVMBasicBlockRef poll_bb, cont_bb;
6223 LLVMValueRef args [2];
6224 static LLVMTypeRef sig;
6225 const char *icall_name = "mono_threads_state_poll";
6227 if (!sig)
6228 sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
6231 * if (!*sreg1)
6232 * mono_threads_state_poll ();
6233 * FIXME: Use a preserveall wrapper
6235 val = mono_llvm_build_load (builder, convert (ctx, lhs, LLVMPointerType (IntPtrType (), 0)), "", TRUE);
6236 cmp = LLVMBuildICmp (builder, LLVMIntEQ, val, LLVMConstNull (LLVMTypeOf (val)), "");
6237 poll_bb = gen_bb (ctx, "POLL_BB");
6238 cont_bb = gen_bb (ctx, "CONT_BB");
6240 args [0] = cmp;
6241 args [1] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
6242 cmp = LLVMBuildCall (ctx->builder, get_intrins (ctx, INTRINS_EXPECT_I1), args, 2, "");
6244 LLVMBuildCondBr (builder, cmp, cont_bb, poll_bb);
6246 ctx->builder = builder = create_builder (ctx);
6247 LLVMPositionBuilderAtEnd (builder, poll_bb);
6249 if (ctx->cfg->compile_aot) {
6250 callee = get_callee (ctx, sig, MONO_PATCH_INFO_JIT_ICALL, icall_name);
6251 } else {
6252 gpointer target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_JIT_ICALL, icall_name);
6253 callee = emit_jit_callee (ctx, icall_name, sig, target);
6255 LLVMBuildCall (builder, callee, NULL, 0, "");
6256 LLVMBuildBr (builder, cont_bb);
6258 ctx->builder = builder = create_builder (ctx);
6259 LLVMPositionBuilderAtEnd (builder, cont_bb);
6260 ctx->bblocks [bb->block_num].end_bblock = cont_bb;
6261 break;
6265 * Overflow opcodes.
6267 case OP_IADD_OVF:
6268 case OP_IADD_OVF_UN:
6269 case OP_ISUB_OVF:
6270 case OP_ISUB_OVF_UN:
6271 case OP_IMUL_OVF:
6272 case OP_IMUL_OVF_UN:
6273 case OP_LADD_OVF:
6274 case OP_LADD_OVF_UN:
6275 case OP_LSUB_OVF:
6276 case OP_LSUB_OVF_UN:
6277 case OP_LMUL_OVF:
6278 case OP_LMUL_OVF_UN:
6280 LLVMValueRef args [2], val, ovf, func;
6282 args [0] = convert (ctx, lhs, op_to_llvm_type (ins->opcode));
6283 args [1] = convert (ctx, rhs, op_to_llvm_type (ins->opcode));
6284 func = get_intrins_by_name (ctx, ovf_op_to_intrins (ins->opcode));
6285 g_assert (func);
6286 val = LLVMBuildCall (builder, func, args, 2, "");
6287 values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, dname);
6288 ovf = LLVMBuildExtractValue (builder, val, 1, "");
6289 emit_cond_system_exception (ctx, bb, "OverflowException", ovf);
6290 if (!ctx_ok (ctx))
6291 break;
6292 builder = ctx->builder;
6293 break;
6297 * Valuetypes.
6298 * We currently model them using arrays. Promotion to local vregs is
6299 * disabled for them in mono_handle_global_vregs () in the LLVM case,
6300 * so we always have an entry in cfg->varinfo for them.
6301 * FIXME: Is this needed ?
6303 case OP_VZERO: {
6304 MonoClass *klass = ins->klass;
6305 LLVMValueRef args [5];
6307 if (!klass) {
6308 // FIXME:
6309 set_failure (ctx, "!klass");
6310 break;
6313 if (!addresses [ins->dreg])
6314 addresses [ins->dreg] = build_alloca (ctx, m_class_get_byval_arg (klass));
6315 args [0] = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
6316 args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
6317 args [2] = LLVMConstInt (LLVMInt32Type (), mono_class_value_size (klass, NULL), FALSE);
6318 // FIXME: Alignment
6319 args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6320 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
6321 LLVMBuildCall (builder, get_intrins (ctx, INTRINS_MEMSET), args, 5, "");
6322 break;
6324 case OP_DUMMY_VZERO:
6325 break;
6327 case OP_STOREV_MEMBASE:
6328 case OP_LOADV_MEMBASE:
6329 case OP_VMOVE: {
6330 MonoClass *klass = ins->klass;
6331 LLVMValueRef src = NULL, dst, args [5];
6332 gboolean done = FALSE;
6334 if (!klass) {
6335 // FIXME:
6336 set_failure (ctx, "!klass");
6337 break;
6340 if (mini_is_gsharedvt_klass (klass)) {
6341 // FIXME:
6342 set_failure (ctx, "gsharedvt");
6343 break;
6346 switch (ins->opcode) {
6347 case OP_STOREV_MEMBASE:
6348 if (cfg->gen_write_barriers && m_class_has_references (klass) && ins->inst_destbasereg != cfg->frame_reg &&
6349 LLVMGetInstructionOpcode (values [ins->inst_destbasereg]) != LLVMAlloca) {
6350 /* Decomposed earlier */
6351 g_assert_not_reached ();
6352 break;
6354 if (!addresses [ins->sreg1]) {
6355 /* SIMD */
6356 g_assert (values [ins->sreg1]);
6357 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));
6358 LLVMBuildStore (builder, values [ins->sreg1], dst);
6359 done = TRUE;
6360 } else {
6361 src = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (LLVMInt8Type (), 0), "");
6362 dst = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_destbasereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (LLVMInt8Type (), 0));
6364 break;
6365 case OP_LOADV_MEMBASE:
6366 if (!addresses [ins->dreg])
6367 addresses [ins->dreg] = build_alloca (ctx, m_class_get_byval_arg (klass));
6368 src = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_basereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (LLVMInt8Type (), 0));
6369 dst = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
6370 break;
6371 case OP_VMOVE:
6372 if (!addresses [ins->sreg1])
6373 addresses [ins->sreg1] = build_alloca (ctx, m_class_get_byval_arg (klass));
6374 if (!addresses [ins->dreg])
6375 addresses [ins->dreg] = build_alloca (ctx, m_class_get_byval_arg (klass));
6376 src = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (LLVMInt8Type (), 0), "");
6377 dst = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
6378 break;
6379 default:
6380 g_assert_not_reached ();
6382 if (!ctx_ok (ctx))
6383 break;
6385 if (done)
6386 break;
6388 args [0] = dst;
6389 args [1] = src;
6390 args [2] = LLVMConstInt (LLVMInt32Type (), mono_class_value_size (klass, NULL), FALSE);
6391 args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6392 // FIXME: Alignment
6393 args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6394 args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
6395 LLVMBuildCall (builder, get_intrins (ctx, INTRINS_MEMCPY), args, 5, "");
6396 break;
6398 case OP_LLVM_OUTARG_VT: {
6399 LLVMArgInfo *ainfo = (LLVMArgInfo*)ins->inst_p0;
6400 MonoType *t = mini_get_underlying_type (ins->inst_vtype);
6402 if (ainfo->storage == LLVMArgGsharedvtVariable) {
6403 MonoInst *var = get_vreg_to_inst (cfg, ins->sreg1);
6405 if (var && var->opcode == OP_GSHAREDVT_LOCAL) {
6406 addresses [ins->dreg] = convert (ctx, emit_gsharedvt_ldaddr (ctx, var->dreg), LLVMPointerType (IntPtrType (), 0));
6407 } else {
6408 g_assert (addresses [ins->sreg1]);
6409 addresses [ins->dreg] = addresses [ins->sreg1];
6411 } else if (ainfo->storage == LLVMArgGsharedvtFixed) {
6412 if (!addresses [ins->sreg1]) {
6413 addresses [ins->sreg1] = build_alloca (ctx, t);
6414 g_assert (values [ins->sreg1]);
6416 LLVMBuildStore (builder, convert (ctx, values [ins->sreg1], LLVMGetElementType (LLVMTypeOf (addresses [ins->sreg1]))), addresses [ins->sreg1]);
6417 addresses [ins->dreg] = addresses [ins->sreg1];
6418 } else {
6419 if (!addresses [ins->sreg1]) {
6420 addresses [ins->sreg1] = build_alloca (ctx, t);
6421 g_assert (values [ins->sreg1]);
6422 LLVMBuildStore (builder, convert (ctx, values [ins->sreg1], type_to_llvm_type (ctx, t)), addresses [ins->sreg1]);
6423 addresses [ins->dreg] = addresses [ins->sreg1];
6424 } else if (values [ins->sreg1] == addresses [ins->sreg1]) {
6425 /* LLVMArgVtypeByRef, have to make a copy */
6426 addresses [ins->dreg] = build_alloca (ctx, t);
6427 LLVMValueRef v = LLVMBuildLoad (builder, addresses [ins->sreg1], "");
6428 LLVMBuildStore (builder, convert (ctx, v, type_to_llvm_type (ctx, t)), addresses [ins->dreg]);
6429 } else {
6430 addresses [ins->dreg] = addresses [ins->sreg1];
6433 break;
6435 case OP_OBJC_GET_SELECTOR: {
6436 const char *name = (const char*)ins->inst_p0;
6437 LLVMValueRef var;
6439 if (!ctx->module->objc_selector_to_var) {
6440 ctx->module->objc_selector_to_var = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
6442 LLVMValueRef info_var = LLVMAddGlobal (ctx->lmodule, LLVMArrayType (LLVMInt8Type (), 8), "@OBJC_IMAGE_INFO");
6443 int32_t objc_imageinfo [] = { 0, 16 };
6444 LLVMSetInitializer (info_var, mono_llvm_create_constant_data_array ((uint8_t *) &objc_imageinfo, 8));
6445 LLVMSetLinkage (info_var, LLVMPrivateLinkage);
6446 LLVMSetExternallyInitialized (info_var, TRUE);
6447 LLVMSetSection (info_var, "__DATA, __objc_imageinfo,regular,no_dead_strip");
6448 LLVMSetAlignment (info_var, sizeof (target_mgreg_t));
6449 mark_as_used (ctx->module, info_var);
6452 var = (LLVMValueRef)g_hash_table_lookup (ctx->module->objc_selector_to_var, name);
6453 if (!var) {
6454 LLVMValueRef indexes [16];
6456 LLVMValueRef name_var = LLVMAddGlobal (ctx->lmodule, LLVMArrayType (LLVMInt8Type (), strlen (name) + 1), "@OBJC_METH_VAR_NAME_");
6457 LLVMSetInitializer (name_var, mono_llvm_create_constant_data_array ((const uint8_t*)name, strlen (name) + 1));
6458 LLVMSetLinkage (name_var, LLVMPrivateLinkage);
6459 LLVMSetSection (name_var, "__TEXT,__objc_methname,cstring_literals");
6460 mark_as_used (ctx->module, name_var);
6462 LLVMValueRef ref_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (LLVMInt8Type (), 0), "@OBJC_SELECTOR_REFERENCES_");
6464 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, 0);
6465 indexes [1] = LLVMConstInt (LLVMInt32Type (), 0, 0);
6466 LLVMSetInitializer (ref_var, LLVMConstGEP (name_var, indexes, 2));
6467 LLVMSetLinkage (ref_var, LLVMPrivateLinkage);
6468 LLVMSetExternallyInitialized (ref_var, TRUE);
6469 LLVMSetSection (ref_var, "__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
6470 LLVMSetAlignment (ref_var, sizeof (target_mgreg_t));
6471 mark_as_used (ctx->module, ref_var);
6473 g_hash_table_insert (ctx->module->objc_selector_to_var, g_strdup (name), ref_var);
6474 var = ref_var;
6477 values [ins->dreg] = LLVMBuildLoad (builder, var, "");
6478 break;
6482 * SIMD
6484 #if defined(TARGET_X86) || defined(TARGET_AMD64)
6485 case OP_XZERO: {
6486 values [ins->dreg] = LLVMConstNull (type_to_llvm_type (ctx, m_class_get_byval_arg (ins->klass)));
6487 break;
6489 case OP_LOADX_MEMBASE: {
6490 LLVMTypeRef t = type_to_llvm_type (ctx, m_class_get_byval_arg (ins->klass));
6491 LLVMValueRef src;
6493 src = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_basereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (t, 0));
6494 values [ins->dreg] = mono_llvm_build_aligned_load (builder, src, "", FALSE, 1);
6495 break;
6497 case OP_STOREX_MEMBASE: {
6498 LLVMTypeRef t = LLVMTypeOf (values [ins->sreg1]);
6499 LLVMValueRef dest;
6501 dest = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_destbasereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (t, 0));
6502 mono_llvm_build_aligned_store (builder, values [ins->sreg1], dest, FALSE, 1);
6503 break;
6505 case OP_PADDB:
6506 case OP_PADDW:
6507 case OP_PADDD:
6508 case OP_PADDQ:
6509 values [ins->dreg] = LLVMBuildAdd (builder, lhs, rhs, "");
6510 break;
6511 case OP_ADDPD:
6512 case OP_ADDPS:
6513 values [ins->dreg] = LLVMBuildFAdd (builder, lhs, rhs, "");
6514 break;
6515 case OP_PSUBB:
6516 case OP_PSUBW:
6517 case OP_PSUBD:
6518 case OP_PSUBQ:
6519 values [ins->dreg] = LLVMBuildSub (builder, lhs, rhs, "");
6520 break;
6521 case OP_SUBPD:
6522 case OP_SUBPS:
6523 values [ins->dreg] = LLVMBuildFSub (builder, lhs, rhs, "");
6524 break;
6525 case OP_MULPD:
6526 case OP_MULPS:
6527 values [ins->dreg] = LLVMBuildFMul (builder, lhs, rhs, "");
6528 break;
6529 case OP_DIVPD:
6530 case OP_DIVPS:
6531 values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, "");
6532 break;
6533 case OP_PAND:
6534 values [ins->dreg] = LLVMBuildAnd (builder, lhs, rhs, "");
6535 break;
6536 case OP_POR:
6537 values [ins->dreg] = LLVMBuildOr (builder, lhs, rhs, "");
6538 break;
6539 case OP_PXOR:
6540 values [ins->dreg] = LLVMBuildXor (builder, lhs, rhs, "");
6541 break;
6542 case OP_PMULW:
6543 case OP_PMULD:
6544 values [ins->dreg] = LLVMBuildMul (builder, lhs, rhs, "");
6545 break;
6546 case OP_ANDPS:
6547 case OP_ANDNPS:
6548 case OP_ORPS:
6549 case OP_XORPS:
6550 case OP_ANDPD:
6551 case OP_ANDNPD:
6552 case OP_ORPD:
6553 case OP_XORPD: {
6554 LLVMTypeRef t, rt;
6555 LLVMValueRef v = NULL;
6557 switch (ins->opcode) {
6558 case OP_ANDPS:
6559 case OP_ANDNPS:
6560 case OP_ORPS:
6561 case OP_XORPS:
6562 t = LLVMVectorType (LLVMInt32Type (), 4);
6563 rt = LLVMVectorType (LLVMFloatType (), 4);
6564 break;
6565 case OP_ANDPD:
6566 case OP_ANDNPD:
6567 case OP_ORPD:
6568 case OP_XORPD:
6569 t = LLVMVectorType (LLVMInt64Type (), 2);
6570 rt = LLVMVectorType (LLVMDoubleType (), 2);
6571 break;
6572 default:
6573 t = LLVMInt32Type ();
6574 rt = LLVMInt32Type ();
6575 g_assert_not_reached ();
6578 lhs = LLVMBuildBitCast (builder, lhs, t, "");
6579 rhs = LLVMBuildBitCast (builder, rhs, t, "");
6580 switch (ins->opcode) {
6581 case OP_ANDPS:
6582 case OP_ANDPD:
6583 v = LLVMBuildAnd (builder, lhs, rhs, "");
6584 break;
6585 case OP_ORPS:
6586 case OP_ORPD:
6587 v = LLVMBuildOr (builder, lhs, rhs, "");
6588 break;
6589 case OP_XORPS:
6590 case OP_XORPD:
6591 v = LLVMBuildXor (builder, lhs, rhs, "");
6592 break;
6593 case OP_ANDNPS:
6594 case OP_ANDNPD:
6595 v = LLVMBuildAnd (builder, rhs, LLVMBuildNot (builder, lhs, ""), "");
6596 break;
6598 values [ins->dreg] = LLVMBuildBitCast (builder, v, rt, "");
6599 break;
6601 case OP_PMIND_UN:
6602 case OP_PMINW_UN:
6603 case OP_PMINB_UN: {
6604 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntULT, lhs, rhs, "");
6605 values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
6606 break;
6608 case OP_PMAXD_UN:
6609 case OP_PMAXW_UN:
6610 case OP_PMAXB_UN: {
6611 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntUGT, lhs, rhs, "");
6612 values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
6613 break;
6615 case OP_PMINW: {
6616 LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntSLT, lhs, rhs, "");
6617 values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
6618 break;
6620 case OP_MINPD:
6621 case OP_MINPS:
6622 case OP_MAXPD:
6623 case OP_MAXPS:
6624 case OP_ADDSUBPD:
6625 case OP_ADDSUBPS:
6626 case OP_HADDPD:
6627 case OP_HADDPS:
6628 case OP_HSUBPD:
6629 case OP_HSUBPS:
6630 case OP_PADDB_SAT:
6631 case OP_PADDW_SAT:
6632 case OP_PSUBB_SAT:
6633 case OP_PSUBW_SAT:
6634 case OP_PADDB_SAT_UN:
6635 case OP_PADDW_SAT_UN:
6636 case OP_PSUBB_SAT_UN:
6637 case OP_PSUBW_SAT_UN:
6638 case OP_PACKW:
6639 case OP_PACKD:
6640 case OP_PACKW_UN:
6641 case OP_PACKD_UN:
6642 case OP_PMULW_HIGH:
6643 case OP_PMULW_HIGH_UN: {
6644 LLVMValueRef args [2];
6646 args [0] = lhs;
6647 args [1] = rhs;
6649 values [ins->dreg] = LLVMBuildCall (builder, get_intrins_by_name (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6650 break;
6652 case OP_PAVGB_UN:
6653 case OP_PAVGW_UN: {
6654 LLVMValueRef ones_vec;
6655 LLVMValueRef ones [32];
6656 int vector_size = LLVMGetVectorSize (LLVMTypeOf (lhs));
6657 LLVMTypeRef ext_elem_type = vector_size == 16 ? LLVMInt16Type () : LLVMInt32Type ();
6659 for (int i = 0; i < 32; ++i)
6660 ones [i] = LLVMConstInt (ext_elem_type, 1, FALSE);
6661 ones_vec = LLVMConstVector (ones, vector_size);
6663 #if LLVM_API_VERSION >= 500
6664 LLVMValueRef val;
6665 LLVMTypeRef ext_type = LLVMVectorType (ext_elem_type, vector_size);
6667 /* Have to increase the vector element size to prevent overflows */
6668 /* res = trunc ((zext (lhs) + zext (rhs) + 1) >> 1) */
6669 val = LLVMBuildAdd (builder, LLVMBuildZExt (builder, lhs, ext_type, ""), LLVMBuildZExt (builder, rhs, ext_type, ""), "");
6670 val = LLVMBuildAdd (builder, val, ones_vec, "");
6671 val = LLVMBuildLShr (builder, val, ones_vec, "");
6672 values [ins->dreg] = LLVMBuildTrunc (builder, val, LLVMTypeOf (lhs), "");
6673 #else
6674 LLVMValueRef args [2];
6676 args [0] = lhs;
6677 args [1] = rhs;
6679 values [ins->dreg] = LLVMBuildCall (builder, get_intrins_by_name (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6680 #endif
6681 break;
6683 case OP_PCMPEQB:
6684 case OP_PCMPEQW:
6685 case OP_PCMPEQD:
6686 case OP_PCMPEQQ: {
6687 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildICmp (builder, LLVMIntEQ, lhs, rhs, ""), LLVMTypeOf (lhs), "");
6688 break;
6690 case OP_PCMPGTB: {
6691 values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildICmp (builder, LLVMIntSGT, lhs, rhs, ""), LLVMTypeOf (lhs), "");
6692 break;
6694 case OP_EXTRACT_R8:
6695 case OP_EXTRACT_I8:
6696 case OP_EXTRACT_I4:
6697 case OP_EXTRACT_I2:
6698 case OP_EXTRACT_U2:
6699 case OP_EXTRACTX_U2:
6700 case OP_EXTRACT_I1:
6701 case OP_EXTRACT_U1: {
6702 LLVMTypeRef t;
6703 gboolean zext = FALSE;
6705 t = simd_op_to_llvm_type (ins->opcode);
6707 switch (ins->opcode) {
6708 case OP_EXTRACT_R8:
6709 case OP_EXTRACT_I8:
6710 case OP_EXTRACT_I4:
6711 case OP_EXTRACT_I2:
6712 case OP_EXTRACT_I1:
6713 break;
6714 case OP_EXTRACT_U2:
6715 case OP_EXTRACTX_U2:
6716 case OP_EXTRACT_U1:
6717 zext = TRUE;
6718 break;
6719 default:
6720 t = LLVMInt32Type ();
6721 g_assert_not_reached ();
6724 lhs = LLVMBuildBitCast (builder, lhs, t, "");
6725 values [ins->dreg] = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), "");
6726 if (zext)
6727 values [ins->dreg] = LLVMBuildZExt (builder, values [ins->dreg], LLVMInt32Type (), "");
6728 break;
6731 case OP_EXPAND_I1:
6732 case OP_EXPAND_I2:
6733 case OP_EXPAND_I4:
6734 case OP_EXPAND_I8:
6735 case OP_EXPAND_R4:
6736 case OP_EXPAND_R8: {
6737 LLVMTypeRef t = simd_op_to_llvm_type (ins->opcode);
6738 LLVMValueRef mask [16], v;
6739 int i;
6741 for (i = 0; i < 16; ++i)
6742 mask [i] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6744 v = convert (ctx, values [ins->sreg1], LLVMGetElementType (t));
6746 values [ins->dreg] = LLVMBuildInsertElement (builder, LLVMConstNull (t), v, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
6747 values [ins->dreg] = LLVMBuildShuffleVector (builder, values [ins->dreg], LLVMGetUndef (t), LLVMConstVector (mask, LLVMGetVectorSize (t)), "");
6748 break;
6751 case OP_INSERT_I1:
6752 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt8Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6753 break;
6754 case OP_INSERT_I2:
6755 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt16Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6756 break;
6757 case OP_INSERT_I4:
6758 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt32Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6759 break;
6760 case OP_INSERT_I8:
6761 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMInt64Type ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6762 break;
6763 case OP_INSERT_R4:
6764 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMFloatType ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6765 break;
6766 case OP_INSERT_R8:
6767 values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMDoubleType ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
6768 break;
6770 #if LLVM_API_VERSION > 100
6771 case OP_CVTDQ2PD: {
6772 LLVMValueRef indexes [16];
6774 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6775 indexes [1] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
6776 LLVMValueRef mask = LLVMConstVector (indexes, 2);
6777 LLVMValueRef shuffle = LLVMBuildShuffleVector (builder, lhs, LLVMConstNull (LLVMTypeOf (lhs)), mask, "");
6778 values [ins->dreg] = LLVMBuildSIToFP (builder, shuffle, LLVMVectorType (LLVMDoubleType (), 2), dname);
6779 break;
6781 case OP_CVTPS2PD: {
6782 LLVMValueRef indexes [16];
6784 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
6785 indexes [1] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
6786 LLVMValueRef mask = LLVMConstVector (indexes, 2);
6787 LLVMValueRef shuffle = LLVMBuildShuffleVector (builder, lhs, LLVMConstNull (LLVMTypeOf (lhs)), mask, "");
6788 values [ins->dreg] = LLVMBuildFPExt (builder, shuffle, LLVMVectorType (LLVMDoubleType (), 2), dname);
6789 break;
6791 case OP_CVTTPS2DQ:
6792 values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, LLVMVectorType (LLVMInt32Type (), 4), dname);
6793 break;
6794 #endif
6796 #if LLVM_API_VERSION <= 100
6797 case OP_CVTDQ2PD:
6798 case OP_CVTPS2PD:
6799 case OP_CVTTPS2DQ:
6800 #endif
6801 case OP_CVTDQ2PS:
6802 case OP_CVTPD2DQ:
6803 case OP_CVTPS2DQ:
6804 case OP_CVTPD2PS:
6805 case OP_CVTTPD2DQ:
6806 case OP_EXTRACT_MASK:
6807 case OP_SQRTPS:
6808 case OP_SQRTPD:
6809 case OP_RSQRTPS:
6810 case OP_RCPPS: {
6811 LLVMValueRef v;
6813 v = convert (ctx, values [ins->sreg1], simd_op_to_llvm_type (ins->opcode));
6815 values [ins->dreg] = LLVMBuildCall (builder, get_intrins_by_name (ctx, simd_op_to_intrins (ins->opcode)), &v, 1, dname);
6816 break;
6818 case OP_COMPPS:
6819 case OP_COMPPD: {
6820 LLVMRealPredicate op;
6822 switch (ins->inst_c0) {
6823 case SIMD_COMP_EQ:
6824 op = LLVMRealOEQ;
6825 break;
6826 case SIMD_COMP_LT:
6827 op = LLVMRealOLT;
6828 break;
6829 case SIMD_COMP_LE:
6830 op = LLVMRealOLE;
6831 break;
6832 case SIMD_COMP_UNORD:
6833 op = LLVMRealUNO;
6834 break;
6835 case SIMD_COMP_NEQ:
6836 op = LLVMRealUNE;
6837 break;
6838 case SIMD_COMP_NLT:
6839 op = LLVMRealUGE;
6840 break;
6841 case SIMD_COMP_NLE:
6842 op = LLVMRealUGT;
6843 break;
6844 case SIMD_COMP_ORD:
6845 op = LLVMRealORD;
6846 break;
6847 default:
6848 g_assert_not_reached ();
6851 LLVMValueRef cmp = LLVMBuildFCmp (builder, op, lhs, rhs, "");
6852 if (ins->opcode == OP_COMPPD)
6853 values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildSExt (builder, cmp, LLVMVectorType (LLVMInt64Type (), 2), ""), LLVMTypeOf (lhs), "");
6854 else
6855 values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildSExt (builder, cmp, LLVMVectorType (LLVMInt32Type (), 4), ""), LLVMTypeOf (lhs), "");
6856 break;
6858 case OP_ICONV_TO_X:
6859 /* This is only used for implementing shifts by non-immediate */
6860 values [ins->dreg] = lhs;
6861 break;
6863 case OP_PSHRW:
6864 case OP_PSHRD:
6865 case OP_PSHRQ:
6866 case OP_PSARW:
6867 case OP_PSARD:
6868 case OP_PSHLW:
6869 case OP_PSHLD:
6870 case OP_PSHLQ: {
6871 LLVMValueRef args [3];
6873 args [0] = lhs;
6874 args [1] = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
6876 values [ins->dreg] = LLVMBuildCall (builder, get_intrins_by_name (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6877 break;
6880 case OP_PSHRW_REG:
6881 case OP_PSHRD_REG:
6882 case OP_PSHRQ_REG:
6883 case OP_PSARW_REG:
6884 case OP_PSARD_REG:
6885 case OP_PSHLW_REG:
6886 case OP_PSHLD_REG:
6887 case OP_PSHLQ_REG: {
6888 LLVMValueRef args [3];
6890 args [0] = lhs;
6891 args [1] = values [ins->sreg2];
6893 values [ins->dreg] = LLVMBuildCall (builder, get_intrins_by_name (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
6894 break;
6897 case OP_SHUFPS:
6898 case OP_SHUFPD:
6899 case OP_PSHUFLED:
6900 case OP_PSHUFLEW_LOW:
6901 case OP_PSHUFLEW_HIGH: {
6902 int mask [16];
6903 LLVMValueRef v1 = NULL, v2 = NULL, mask_values [16];
6904 int i, mask_size = 0;
6905 int imask = ins->inst_c0;
6907 /* Convert the x86 shuffle mask to LLVM's */
6908 switch (ins->opcode) {
6909 case OP_SHUFPS:
6910 mask_size = 4;
6911 mask [0] = ((imask >> 0) & 3);
6912 mask [1] = ((imask >> 2) & 3);
6913 mask [2] = ((imask >> 4) & 3) + 4;
6914 mask [3] = ((imask >> 6) & 3) + 4;
6915 v1 = values [ins->sreg1];
6916 v2 = values [ins->sreg2];
6917 break;
6918 case OP_SHUFPD:
6919 mask_size = 2;
6920 mask [0] = ((imask >> 0) & 1);
6921 mask [1] = ((imask >> 1) & 1) + 2;
6922 v1 = values [ins->sreg1];
6923 v2 = values [ins->sreg2];
6924 break;
6925 case OP_PSHUFLEW_LOW:
6926 mask_size = 8;
6927 mask [0] = ((imask >> 0) & 3);
6928 mask [1] = ((imask >> 2) & 3);
6929 mask [2] = ((imask >> 4) & 3);
6930 mask [3] = ((imask >> 6) & 3);
6931 mask [4] = 4 + 0;
6932 mask [5] = 4 + 1;
6933 mask [6] = 4 + 2;
6934 mask [7] = 4 + 3;
6935 v1 = values [ins->sreg1];
6936 v2 = LLVMGetUndef (LLVMTypeOf (v1));
6937 break;
6938 case OP_PSHUFLEW_HIGH:
6939 mask_size = 8;
6940 mask [0] = 0;
6941 mask [1] = 1;
6942 mask [2] = 2;
6943 mask [3] = 3;
6944 mask [4] = 4 + ((imask >> 0) & 3);
6945 mask [5] = 4 + ((imask >> 2) & 3);
6946 mask [6] = 4 + ((imask >> 4) & 3);
6947 mask [7] = 4 + ((imask >> 6) & 3);
6948 v1 = values [ins->sreg1];
6949 v2 = LLVMGetUndef (LLVMTypeOf (v1));
6950 break;
6951 case OP_PSHUFLED:
6952 mask_size = 4;
6953 mask [0] = ((imask >> 0) & 3);
6954 mask [1] = ((imask >> 2) & 3);
6955 mask [2] = ((imask >> 4) & 3);
6956 mask [3] = ((imask >> 6) & 3);
6957 v1 = values [ins->sreg1];
6958 v2 = LLVMGetUndef (LLVMTypeOf (v1));
6959 break;
6960 default:
6961 g_assert_not_reached ();
6963 for (i = 0; i < mask_size; ++i)
6964 mask_values [i] = LLVMConstInt (LLVMInt32Type (), mask [i], FALSE);
6966 values [ins->dreg] =
6967 LLVMBuildShuffleVector (builder, v1, v2,
6968 LLVMConstVector (mask_values, mask_size), dname);
6969 break;
6972 case OP_UNPACK_LOWB:
6973 case OP_UNPACK_LOWW:
6974 case OP_UNPACK_LOWD:
6975 case OP_UNPACK_LOWQ:
6976 case OP_UNPACK_LOWPS:
6977 case OP_UNPACK_LOWPD:
6978 case OP_UNPACK_HIGHB:
6979 case OP_UNPACK_HIGHW:
6980 case OP_UNPACK_HIGHD:
6981 case OP_UNPACK_HIGHQ:
6982 case OP_UNPACK_HIGHPS:
6983 case OP_UNPACK_HIGHPD: {
6984 int mask [16];
6985 LLVMValueRef mask_values [16];
6986 int i, mask_size = 0;
6987 gboolean low = FALSE;
6989 switch (ins->opcode) {
6990 case OP_UNPACK_LOWB:
6991 mask_size = 16;
6992 low = TRUE;
6993 break;
6994 case OP_UNPACK_LOWW:
6995 mask_size = 8;
6996 low = TRUE;
6997 break;
6998 case OP_UNPACK_LOWD:
6999 case OP_UNPACK_LOWPS:
7000 mask_size = 4;
7001 low = TRUE;
7002 break;
7003 case OP_UNPACK_LOWQ:
7004 case OP_UNPACK_LOWPD:
7005 mask_size = 2;
7006 low = TRUE;
7007 break;
7008 case OP_UNPACK_HIGHB:
7009 mask_size = 16;
7010 break;
7011 case OP_UNPACK_HIGHW:
7012 mask_size = 8;
7013 break;
7014 case OP_UNPACK_HIGHD:
7015 case OP_UNPACK_HIGHPS:
7016 mask_size = 4;
7017 break;
7018 case OP_UNPACK_HIGHQ:
7019 case OP_UNPACK_HIGHPD:
7020 mask_size = 2;
7021 break;
7022 default:
7023 g_assert_not_reached ();
7026 if (low) {
7027 for (i = 0; i < (mask_size / 2); ++i) {
7028 mask [(i * 2)] = i;
7029 mask [(i * 2) + 1] = mask_size + i;
7031 } else {
7032 for (i = 0; i < (mask_size / 2); ++i) {
7033 mask [(i * 2)] = (mask_size / 2) + i;
7034 mask [(i * 2) + 1] = mask_size + (mask_size / 2) + i;
7038 for (i = 0; i < mask_size; ++i)
7039 mask_values [i] = LLVMConstInt (LLVMInt32Type (), mask [i], FALSE);
7041 values [ins->dreg] =
7042 LLVMBuildShuffleVector (builder, values [ins->sreg1], values [ins->sreg2],
7043 LLVMConstVector (mask_values, mask_size), dname);
7044 break;
7047 case OP_DUPPD: {
7048 LLVMTypeRef t = simd_op_to_llvm_type (ins->opcode);
7049 LLVMValueRef v, val;
7051 v = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
7052 val = LLVMConstNull (t);
7053 val = LLVMBuildInsertElement (builder, val, v, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
7054 val = LLVMBuildInsertElement (builder, val, v, LLVMConstInt (LLVMInt32Type (), 1, FALSE), dname);
7056 values [ins->dreg] = val;
7057 break;
7059 case OP_DUPPS_LOW:
7060 case OP_DUPPS_HIGH: {
7061 LLVMTypeRef t = simd_op_to_llvm_type (ins->opcode);
7062 LLVMValueRef v1, v2, val;
7065 if (ins->opcode == OP_DUPPS_LOW) {
7066 v1 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
7067 v2 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 2, FALSE), "");
7068 } else {
7069 v1 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 1, FALSE), "");
7070 v2 = LLVMBuildExtractElement (builder, lhs, LLVMConstInt (LLVMInt32Type (), 3, FALSE), "");
7072 val = LLVMConstNull (t);
7073 val = LLVMBuildInsertElement (builder, val, v1, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
7074 val = LLVMBuildInsertElement (builder, val, v1, LLVMConstInt (LLVMInt32Type (), 1, FALSE), "");
7075 val = LLVMBuildInsertElement (builder, val, v2, LLVMConstInt (LLVMInt32Type (), 2, FALSE), "");
7076 val = LLVMBuildInsertElement (builder, val, v2, LLVMConstInt (LLVMInt32Type (), 3, FALSE), "");
7078 values [ins->dreg] = val;
7079 break;
7082 case OP_DPPS: {
7083 LLVMValueRef args [3];
7085 args [0] = lhs;
7086 args [1] = rhs;
7087 /* 0xf1 == multiply all 4 elements, add them together, and store the result to the lowest element */
7088 #if LLVM_API_VERSION >= 500
7089 args [2] = LLVMConstInt (LLVMInt8Type (), 0xf1, FALSE);
7090 #else
7091 args [2] = LLVMConstInt (LLVMInt32Type (), 0xf1, FALSE);
7092 #endif
7094 values [ins->dreg] = LLVMBuildCall (builder, get_intrins_by_name (ctx, simd_op_to_intrins (ins->opcode)), args, 3, dname);
7095 break;
7098 case OP_FCONV_TO_R8_X: {
7099 values [ins->dreg] = LLVMBuildInsertElement (builder, LLVMConstNull (type_to_simd_type (MONO_TYPE_R8)), lhs, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
7100 break;
7103 case OP_SSE41_ROUNDPD: {
7104 LLVMValueRef args [3];
7106 args [0] = lhs;
7107 args [1] = LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE);
7109 values [ins->dreg] = LLVMBuildCall (builder, get_intrins_by_name (ctx, "llvm.x86.sse41.round.pd"), args, 2, dname);
7110 break;
7113 #endif /* SIMD */
7115 case OP_DUMMY_USE:
7116 break;
7119 * EXCEPTION HANDLING
7121 case OP_IMPLICIT_EXCEPTION:
7122 /* This marks a place where an implicit exception can happen */
7123 if (bb->region != -1)
7124 set_failure (ctx, "implicit-exception");
7125 break;
7126 case OP_THROW:
7127 case OP_RETHROW: {
7128 gboolean rethrow = (ins->opcode == OP_RETHROW);
7129 if (ctx->llvm_only) {
7130 emit_llvmonly_throw (ctx, bb, rethrow, lhs);
7131 has_terminator = TRUE;
7132 ctx->unreachable [bb->block_num] = TRUE;
7133 } else {
7134 emit_throw (ctx, bb, rethrow, lhs);
7135 builder = ctx->builder;
7137 break;
7139 case OP_CALL_HANDLER: {
7141 * We don't 'call' handlers, but instead simply branch to them.
7142 * The code generated by ENDFINALLY will branch back to us.
7144 LLVMBasicBlockRef noex_bb;
7145 GSList *bb_list;
7146 BBInfo *info = &bblocks [ins->inst_target_bb->block_num];
7148 bb_list = info->call_handler_return_bbs;
7151 * Set the indicator variable for the finally clause.
7153 lhs = info->finally_ind;
7154 g_assert (lhs);
7155 LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), g_slist_length (bb_list) + 1, FALSE), lhs);
7157 /* Branch to the finally clause */
7158 LLVMBuildBr (builder, info->call_handler_target_bb);
7160 noex_bb = gen_bb (ctx, "CALL_HANDLER_CONT_BB");
7161 info->call_handler_return_bbs = g_slist_append_mempool (cfg->mempool, info->call_handler_return_bbs, noex_bb);
7163 builder = ctx->builder = create_builder (ctx);
7164 LLVMPositionBuilderAtEnd (ctx->builder, noex_bb);
7166 bblocks [bb->block_num].end_bblock = noex_bb;
7167 break;
7169 case OP_START_HANDLER: {
7170 break;
7172 case OP_ENDFINALLY: {
7173 LLVMBasicBlockRef resume_bb;
7174 MonoBasicBlock *handler_bb;
7175 LLVMValueRef val, switch_ins, callee;
7176 GSList *bb_list;
7177 BBInfo *info;
7178 gboolean is_fault = MONO_REGION_FLAGS (bb->region) == MONO_EXCEPTION_CLAUSE_FAULT;
7181 * Fault clauses are like finally clauses, but they are only called if an exception is thrown.
7183 if (!is_fault) {
7184 handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)));
7185 g_assert (handler_bb);
7186 info = &bblocks [handler_bb->block_num];
7187 lhs = info->finally_ind;
7188 g_assert (lhs);
7190 bb_list = info->call_handler_return_bbs;
7192 resume_bb = gen_bb (ctx, "ENDFINALLY_RESUME_BB");
7194 /* Load the finally variable */
7195 val = LLVMBuildLoad (builder, lhs, "");
7197 /* Reset the variable */
7198 LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), lhs);
7200 /* Branch to either resume_bb, or to the bblocks in bb_list */
7201 switch_ins = LLVMBuildSwitch (builder, val, resume_bb, g_slist_length (bb_list));
7203 * The other targets are added at the end to handle OP_CALL_HANDLER
7204 * opcodes processed later.
7206 info->endfinally_switch_ins_list = g_slist_append_mempool (cfg->mempool, info->endfinally_switch_ins_list, switch_ins);
7208 builder = ctx->builder = create_builder (ctx);
7209 LLVMPositionBuilderAtEnd (ctx->builder, resume_bb);
7212 if (ctx->llvm_only) {
7213 emit_resume_eh (ctx, bb);
7214 } else {
7215 if (ctx->cfg->compile_aot) {
7216 callee = get_callee (ctx, LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE), MONO_PATCH_INFO_JIT_ICALL, "llvm_resume_unwind_trampoline");
7217 } else {
7218 #if LLVM_API_VERSION > 100
7219 MonoJitICallInfo *info;
7221 info = mono_find_jit_icall_by_name ("llvm_resume_unwind_trampoline");
7222 g_assert (info);
7223 gpointer target = (void*)info->func;
7224 LLVMTypeRef icall_sig = LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE);
7225 callee = emit_jit_callee (ctx, "llvm_resume_unwind_trampoline", icall_sig, target);
7226 #else
7227 g_assert_not_reached ();
7228 callee = NULL;
7229 #endif
7231 LLVMBuildCall (builder, callee, NULL, 0, "");
7232 LLVMBuildUnreachable (builder);
7235 has_terminator = TRUE;
7236 break;
7238 case OP_IL_SEQ_POINT:
7239 break;
7240 default: {
7241 char reason [128];
7243 sprintf (reason, "opcode %s", mono_inst_name (ins->opcode));
7244 set_failure (ctx, reason);
7245 break;
7249 if (!ctx_ok (ctx))
7250 break;
7252 /* Convert the value to the type required by phi nodes */
7253 if (spec [MONO_INST_DEST] != ' ' && !MONO_IS_STORE_MEMBASE (ins) && ctx->vreg_types [ins->dreg]) {
7254 if (ctx->is_vphi [ins->dreg])
7255 /* vtypes */
7256 values [ins->dreg] = addresses [ins->dreg];
7257 else
7258 values [ins->dreg] = convert (ctx, values [ins->dreg], ctx->vreg_types [ins->dreg]);
7261 /* Add stores for volatile variables */
7262 if (spec [MONO_INST_DEST] != ' ' && spec [MONO_INST_DEST] != 'v' && !MONO_IS_STORE_MEMBASE (ins))
7263 emit_volatile_store (ctx, ins->dreg);
7266 if (!ctx_ok (ctx))
7267 return;
7269 if (!has_terminator && bb->next_bb && (bb == cfg->bb_entry || bb->in_count > 0)) {
7270 LLVMBuildBr (builder, get_bb (ctx, bb->next_bb));
7273 if (bb == cfg->bb_exit && sig->ret->type == MONO_TYPE_VOID) {
7274 emit_dbg_loc (ctx, builder, cfg->header->code + cfg->header->code_size - 1);
7275 LLVMBuildRetVoid (builder);
7278 if (bb == cfg->bb_entry)
7279 ctx->last_alloca = LLVMGetLastInstruction (get_bb (ctx, cfg->bb_entry));
7283 * mono_llvm_check_method_supported:
7285 * Do some quick checks to decide whenever cfg->method can be compiled by LLVM, to avoid
7286 * compiling a method twice.
7288 void
7289 mono_llvm_check_method_supported (MonoCompile *cfg)
7291 int i, j;
7293 #ifdef TARGET_WASM
7294 if (mono_method_signature_internal (cfg->method)->call_convention == MONO_CALL_VARARG) {
7295 cfg->exception_message = g_strdup ("vararg callconv");
7296 cfg->disable_llvm = TRUE;
7297 return;
7299 #endif
7301 if (cfg->llvm_only)
7302 return;
7304 if (cfg->method->save_lmf) {
7305 cfg->exception_message = g_strdup ("lmf");
7306 cfg->disable_llvm = TRUE;
7308 if (cfg->disable_llvm)
7309 return;
7312 * Nested clauses where one of the clauses is a finally clause is
7313 * not supported, because LLVM can't figure out the control flow,
7314 * probably because we resume exception handling by calling our
7315 * own function instead of using the 'resume' llvm instruction.
7317 for (i = 0; i < cfg->header->num_clauses; ++i) {
7318 for (j = 0; j < cfg->header->num_clauses; ++j) {
7319 MonoExceptionClause *clause1 = &cfg->header->clauses [i];
7320 MonoExceptionClause *clause2 = &cfg->header->clauses [j];
7322 // FIXME: Nested try clauses fail in some cases too, i.e. #37273
7323 if (i != j && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
7324 //(clause1->flags == MONO_EXCEPTION_CLAUSE_FINALLY || clause2->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
7325 cfg->exception_message = g_strdup ("nested clauses");
7326 cfg->disable_llvm = TRUE;
7327 break;
7331 if (cfg->disable_llvm)
7332 return;
7334 /* FIXME: */
7335 if (cfg->method->dynamic) {
7336 cfg->exception_message = g_strdup ("dynamic.");
7337 cfg->disable_llvm = TRUE;
7339 if (cfg->disable_llvm)
7340 return;
7343 static LLVMCallInfo*
7344 get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
7346 LLVMCallInfo *linfo;
7347 int i;
7349 if (cfg->gsharedvt && cfg->llvm_only && mini_is_gsharedvt_variable_signature (sig)) {
7350 int i, n, pindex;
7353 * Gsharedvt methods have the following calling convention:
7354 * - all arguments are passed by ref, even non generic ones
7355 * - the return value is returned by ref too, using a vret
7356 * argument passed after 'this'.
7358 n = sig->param_count + sig->hasthis;
7359 linfo = (LLVMCallInfo*)mono_mempool_alloc0 (cfg->mempool, sizeof (LLVMCallInfo) + (sizeof (LLVMArgInfo) * n));
7361 pindex = 0;
7362 if (sig->hasthis)
7363 linfo->args [pindex ++].storage = LLVMArgNormal;
7365 if (sig->ret->type != MONO_TYPE_VOID) {
7366 if (mini_is_gsharedvt_variable_type (sig->ret))
7367 linfo->ret.storage = LLVMArgGsharedvtVariable;
7368 else if (mini_type_is_vtype (sig->ret))
7369 linfo->ret.storage = LLVMArgGsharedvtFixedVtype;
7370 else
7371 linfo->ret.storage = LLVMArgGsharedvtFixed;
7372 linfo->vret_arg_index = pindex;
7373 } else {
7374 linfo->ret.storage = LLVMArgNone;
7377 for (i = 0; i < sig->param_count; ++i) {
7378 if (sig->params [i]->byref)
7379 linfo->args [pindex].storage = LLVMArgNormal;
7380 else if (mini_is_gsharedvt_variable_type (sig->params [i]))
7381 linfo->args [pindex].storage = LLVMArgGsharedvtVariable;
7382 else if (mini_type_is_vtype (sig->params [i]))
7383 linfo->args [pindex].storage = LLVMArgGsharedvtFixedVtype;
7384 else
7385 linfo->args [pindex].storage = LLVMArgGsharedvtFixed;
7386 linfo->args [pindex].type = sig->params [i];
7387 pindex ++;
7389 return linfo;
7392 linfo = mono_arch_get_llvm_call_info (cfg, sig);
7393 linfo->dummy_arg_pindex = -1;
7394 for (i = 0; i < sig->param_count; ++i)
7395 linfo->args [i + sig->hasthis].type = sig->params [i];
7397 return linfo;
7400 static void
7401 emit_method_inner (EmitContext *ctx);
7403 static void
7404 free_ctx (EmitContext *ctx)
7406 GSList *l;
7408 g_free (ctx->values);
7409 g_free (ctx->addresses);
7410 g_free (ctx->vreg_types);
7411 g_free (ctx->is_vphi);
7412 g_free (ctx->vreg_cli_types);
7413 g_free (ctx->is_dead);
7414 g_free (ctx->unreachable);
7415 g_ptr_array_free (ctx->phi_values, TRUE);
7416 g_free (ctx->bblocks);
7417 g_hash_table_destroy (ctx->region_to_handler);
7418 g_hash_table_destroy (ctx->clause_to_handler);
7419 g_hash_table_destroy (ctx->jit_callees);
7421 g_ptr_array_free (ctx->callsite_list, TRUE);
7423 g_free (ctx->method_name);
7424 g_ptr_array_free (ctx->bblock_list, TRUE);
7426 for (l = ctx->builders; l; l = l->next) {
7427 LLVMBuilderRef builder = (LLVMBuilderRef)l->data;
7428 LLVMDisposeBuilder (builder);
7431 g_free (ctx);
7434 static gboolean
7435 is_externally_callable (EmitContext *ctx, MonoMethod *method)
7437 if (ctx->module->llvm_only && ctx->module->static_link && (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method_is_direct_callable (method)))
7438 return TRUE;
7439 return FALSE;
7443 * mono_llvm_emit_method:
7445 * Emit LLVM IL from the mono IL, and compile it to native code using LLVM.
7447 void
7448 mono_llvm_emit_method (MonoCompile *cfg)
7450 EmitContext *ctx;
7451 char *method_name;
7452 int i;
7454 if (cfg->skip)
7455 return;
7457 /* The code below might acquire the loader lock, so use it for global locking */
7458 mono_loader_lock ();
7460 /* Used to communicate with the callbacks */
7461 mono_native_tls_set_value (current_cfg_tls_id, cfg);
7463 ctx = g_new0 (EmitContext, 1);
7464 ctx->cfg = cfg;
7465 ctx->mempool = cfg->mempool;
7468 * This maps vregs to the LLVM instruction defining them
7470 ctx->values = g_new0 (LLVMValueRef, cfg->next_vreg);
7472 * This maps vregs for volatile variables to the LLVM instruction defining their
7473 * address.
7475 ctx->addresses = g_new0 (LLVMValueRef, cfg->next_vreg);
7476 ctx->vreg_types = g_new0 (LLVMTypeRef, cfg->next_vreg);
7477 ctx->is_vphi = g_new0 (gboolean, cfg->next_vreg);
7478 ctx->vreg_cli_types = g_new0 (MonoType*, cfg->next_vreg);
7479 ctx->phi_values = g_ptr_array_sized_new (256);
7481 * This signals whenever the vreg was defined by a phi node with no input vars
7482 * (i.e. all its input bblocks end with NOT_REACHABLE).
7484 ctx->is_dead = g_new0 (gboolean, cfg->next_vreg);
7485 /* Whenever the bblock is unreachable */
7486 ctx->unreachable = g_new0 (gboolean, cfg->max_block_num);
7487 ctx->bblock_list = g_ptr_array_sized_new (256);
7489 ctx->region_to_handler = g_hash_table_new (NULL, NULL);
7490 ctx->clause_to_handler = g_hash_table_new (NULL, NULL);
7491 ctx->callsite_list = g_ptr_array_new ();
7492 ctx->jit_callees = g_hash_table_new (NULL, NULL);
7493 if (cfg->compile_aot) {
7494 ctx->module = &aot_module;
7496 if (is_externally_callable (ctx, cfg->method))
7497 method_name = mono_aot_get_mangled_method_name (cfg->method);
7498 else
7499 method_name = mono_aot_get_method_name (cfg);
7500 cfg->llvm_method_name = g_strdup (method_name);
7501 } else {
7502 init_jit_module (cfg->domain);
7503 ctx->module = (MonoLLVMModule*)domain_jit_info (cfg->domain)->llvm_module;
7504 method_name = mono_method_full_name (cfg->method, TRUE);
7506 ctx->method_name = method_name;
7508 #if LLVM_API_VERSION > 100
7509 if (cfg->compile_aot)
7510 ctx->lmodule = ctx->module->lmodule;
7511 else
7512 ctx->lmodule = LLVMModuleCreateWithName (g_strdup_printf ("jit-module-%s", cfg->method->name));
7513 #else
7514 ctx->lmodule = ctx->module->lmodule;
7515 #endif
7516 ctx->llvm_only = ctx->module->llvm_only;
7517 #ifdef TARGET_WASM
7518 ctx->emit_dummy_arg = TRUE;
7519 #endif
7521 emit_method_inner (ctx);
7523 if (!ctx_ok (ctx)) {
7524 if (ctx->lmethod) {
7525 /* Need to add unused phi nodes as they can be referenced by other values */
7526 LLVMBasicBlockRef phi_bb = LLVMAppendBasicBlock (ctx->lmethod, "PHI_BB");
7527 LLVMBuilderRef builder;
7529 builder = create_builder (ctx);
7530 LLVMPositionBuilderAtEnd (builder, phi_bb);
7532 for (i = 0; i < ctx->phi_values->len; ++i) {
7533 LLVMValueRef v = (LLVMValueRef)g_ptr_array_index (ctx->phi_values, i);
7534 if (LLVMGetInstructionParent (v) == NULL)
7535 LLVMInsertIntoBuilder (builder, v);
7538 if (ctx->module->llvm_only && ctx->module->static_link) {
7539 // Keep a stub for the function since it might be called directly
7540 int nbbs = LLVMCountBasicBlocks (ctx->lmethod);
7541 LLVMBasicBlockRef *bblocks = g_new0 (LLVMBasicBlockRef, nbbs);
7542 LLVMGetBasicBlocks (ctx->lmethod, bblocks);
7543 for (int i = 0; i < nbbs; ++i)
7544 LLVMDeleteBasicBlock (bblocks [i]);
7546 LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlock (ctx->lmethod, "ENTRY");
7547 builder = create_builder (ctx);
7548 LLVMPositionBuilderAtEnd (builder, entry_bb);
7549 ctx->builder = builder;
7551 LLVMTypeRef sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
7552 LLVMValueRef callee = get_callee (ctx, sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mini_llvmonly_throw_nullref_exception");
7553 emit_call (ctx, cfg->bb_entry, &builder, callee, NULL, 0);
7554 LLVMBuildUnreachable (builder);
7555 } else {
7556 LLVMDeleteFunction (ctx->lmethod);
7561 free_ctx (ctx);
7563 mono_native_tls_set_value (current_cfg_tls_id, NULL);
7565 mono_loader_unlock ();
7568 static void
7569 emit_method_inner (EmitContext *ctx)
7571 MonoCompile *cfg = ctx->cfg;
7572 MonoMethodSignature *sig;
7573 MonoBasicBlock *bb;
7574 LLVMTypeRef method_type;
7575 LLVMValueRef method = NULL;
7576 LLVMValueRef *values = ctx->values;
7577 int i, max_block_num, bb_index;
7578 gboolean last = FALSE;
7579 LLVMCallInfo *linfo;
7580 LLVMModuleRef lmodule = ctx->lmodule;
7581 BBInfo *bblocks;
7582 GPtrArray *bblock_list = ctx->bblock_list;
7583 MonoMethodHeader *header;
7584 MonoExceptionClause *clause;
7585 char **names;
7586 LLVMBuilderRef entry_builder = NULL;
7587 LLVMBasicBlockRef entry_bb = NULL;
7589 if (cfg->gsharedvt && !cfg->llvm_only) {
7590 set_failure (ctx, "gsharedvt");
7591 return;
7594 #if 1
7596 static int count = 0;
7597 count ++;
7599 char *llvm_count_str = g_getenv ("LLVM_COUNT");
7600 if (llvm_count_str) {
7601 int lcount = atoi (llvm_count_str);
7602 g_free (llvm_count_str);
7603 if (count == lcount) {
7604 printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
7605 fflush (stdout);
7606 last = TRUE;
7608 if (count > lcount) {
7609 set_failure (ctx, "count");
7610 return;
7614 #endif
7616 // If we come upon one of the init_method wrappers, we need to find
7617 // the method that we have already emitted and tell LLVM that this
7618 // managed method info for the wrapper is associated with this method
7619 // we constructed ourselves from LLVM IR.
7621 // This is necessary to unwind through the init_method, in the case that
7622 // it has to run a static cctor that throws an exception
7623 if (cfg->method->wrapper_type == MONO_WRAPPER_OTHER) {
7624 WrapperInfo *info = mono_marshal_get_wrapper_info (cfg->method);
7625 if (info->subtype == WRAPPER_SUBTYPE_AOT_INIT) {
7626 method = get_init_icall_wrapper (ctx->module, info->d.aot_init.subtype);
7627 ctx->lmethod = method;
7628 ctx->module->max_method_idx = MAX (ctx->module->max_method_idx, cfg->method_index);
7630 const char *init_name = mono_marshal_get_aot_init_wrapper_name (info->d.aot_init.subtype);
7631 ctx->method_name = g_strdup_printf ("%s%s", ctx->module->global_prefix, init_name);
7632 ctx->cfg->asm_symbol = g_strdup (ctx->method_name);
7634 if (!cfg->llvm_only && ctx->module->external_symbols) {
7635 LLVMSetLinkage (method, LLVMExternalLinkage);
7636 LLVMSetVisibility (method, LLVMHiddenVisibility);
7639 goto after_codegen;
7643 sig = mono_method_signature_internal (cfg->method);
7644 ctx->sig = sig;
7646 linfo = get_llvm_call_info (cfg, sig);
7647 ctx->linfo = linfo;
7648 if (!ctx_ok (ctx))
7649 return;
7651 if (cfg->rgctx_var)
7652 linfo->rgctx_arg = TRUE;
7653 else if (needs_extra_arg (ctx, cfg->method))
7654 linfo->dummy_arg = TRUE;
7655 ctx->method_type = method_type = sig_to_llvm_sig_full (ctx, sig, linfo);
7656 if (!ctx_ok (ctx))
7657 return;
7659 method = LLVMAddFunction (lmodule, ctx->method_name, method_type);
7660 ctx->lmethod = method;
7662 if (!cfg->llvm_only)
7663 LLVMSetFunctionCallConv (method, LLVMMono1CallConv);
7665 /* if the method doesn't contain
7666 * (1) a call (so it's a leaf method)
7667 * (2) and no loops
7668 * we can skip the GC safepoint on method entry. */
7669 gboolean requires_safepoint = cfg->has_calls;
7670 if (!requires_safepoint) {
7671 for (bb = cfg->bb_entry->next_bb; bb; bb = bb->next_bb) {
7672 if (bb->loop_body_start || (bb->flags & BB_EXCEPTION_HANDLER)) {
7673 requires_safepoint = TRUE;
7678 if (!cfg->llvm_only && cfg->compile_aot && mono_threads_are_safepoints_enabled () && requires_safepoint)
7679 LLVMSetGC (method, "mono");
7680 LLVMSetLinkage (method, LLVMPrivateLinkage);
7682 mono_llvm_add_func_attr (method, LLVM_ATTR_UW_TABLE);
7684 if (cfg->compile_aot) {
7685 if (is_externally_callable (ctx, cfg->method)) {
7686 LLVMSetLinkage (method, LLVMExternalLinkage);
7687 } else {
7688 LLVMSetLinkage (method, LLVMInternalLinkage);
7689 //all methods have internal visibility when doing llvm_only
7690 if (!cfg->llvm_only && ctx->module->external_symbols) {
7691 LLVMSetLinkage (method, LLVMExternalLinkage);
7692 LLVMSetVisibility (method, LLVMHiddenVisibility);
7695 } else {
7696 LLVMSetLinkage (method, LLVMExternalLinkage);
7699 if (cfg->method->save_lmf && !cfg->llvm_only) {
7700 set_failure (ctx, "lmf");
7701 return;
7704 if (sig->pinvoke && cfg->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && !cfg->llvm_only) {
7705 set_failure (ctx, "pinvoke signature");
7706 return;
7709 header = cfg->header;
7710 for (i = 0; i < header->num_clauses; ++i) {
7711 clause = &header->clauses [i];
7712 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_FAULT && clause->flags != MONO_EXCEPTION_CLAUSE_NONE) {
7713 set_failure (ctx, "non-finally/catch/fault clause.");
7714 return;
7717 if (header->num_clauses || (cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING) || cfg->no_inline)
7718 /* We can't handle inlined methods with clauses */
7719 mono_llvm_add_func_attr (method, LLVM_ATTR_NO_INLINE);
7721 if (linfo->rgctx_arg) {
7722 ctx->rgctx_arg = LLVMGetParam (method, linfo->rgctx_arg_pindex);
7723 ctx->rgctx_arg_pindex = linfo->rgctx_arg_pindex;
7725 * We mark the rgctx parameter with the inreg attribute, which is mapped to
7726 * MONO_ARCH_RGCTX_REG in the Mono calling convention in llvm, i.e.
7727 * CC_X86_64_Mono in X86CallingConv.td.
7729 if (!ctx->llvm_only)
7730 mono_llvm_add_param_attr (ctx->rgctx_arg, LLVM_ATTR_IN_REG);
7731 LLVMSetValueName (ctx->rgctx_arg, "rgctx");
7732 } else {
7733 ctx->rgctx_arg_pindex = -1;
7735 if (cfg->vret_addr) {
7736 values [cfg->vret_addr->dreg] = LLVMGetParam (method, linfo->vret_arg_pindex);
7737 LLVMSetValueName (values [cfg->vret_addr->dreg], "vret");
7738 if (linfo->ret.storage == LLVMArgVtypeByRef) {
7739 mono_llvm_add_param_attr (LLVMGetParam (method, linfo->vret_arg_pindex), LLVM_ATTR_STRUCT_RET);
7740 mono_llvm_add_param_attr (LLVMGetParam (method, linfo->vret_arg_pindex), LLVM_ATTR_NO_ALIAS);
7744 if (sig->hasthis) {
7745 ctx->this_arg_pindex = linfo->this_arg_pindex;
7746 ctx->this_arg = LLVMGetParam (method, linfo->this_arg_pindex);
7747 values [cfg->args [0]->dreg] = ctx->this_arg;
7748 LLVMSetValueName (values [cfg->args [0]->dreg], "this");
7750 if (linfo->dummy_arg)
7751 LLVMSetValueName (LLVMGetParam (method, linfo->dummy_arg_pindex), "dummy_arg");
7753 names = g_new (char *, sig->param_count);
7754 mono_method_get_param_names (cfg->method, (const char **) names);
7756 /* Set parameter names/attributes */
7757 for (i = 0; i < sig->param_count; ++i) {
7758 LLVMArgInfo *ainfo = &linfo->args [i + sig->hasthis];
7759 char *name;
7760 int pindex = ainfo->pindex + ainfo->ndummy_fpargs;
7761 int j;
7763 for (j = 0; j < ainfo->ndummy_fpargs; ++j) {
7764 name = g_strdup_printf ("dummy_%d_%d", i, j);
7765 LLVMSetValueName (LLVMGetParam (method, ainfo->pindex + j), name);
7766 g_free (name);
7769 if (ainfo->storage == LLVMArgVtypeInReg && ainfo->pair_storage [0] == LLVMArgNone && ainfo->pair_storage [1] == LLVMArgNone)
7770 continue;
7772 values [cfg->args [i + sig->hasthis]->dreg] = LLVMGetParam (method, pindex);
7773 if (ainfo->storage == LLVMArgGsharedvtFixed || ainfo->storage == LLVMArgGsharedvtFixedVtype) {
7774 if (names [i] && names [i][0] != '\0')
7775 name = g_strdup_printf ("p_arg_%s", names [i]);
7776 else
7777 name = g_strdup_printf ("p_arg_%d", i);
7778 } else {
7779 if (names [i] && names [i][0] != '\0')
7780 name = g_strdup_printf ("arg_%s", names [i]);
7781 else
7782 name = g_strdup_printf ("arg_%d", i);
7784 LLVMSetValueName (LLVMGetParam (method, pindex), name);
7785 g_free (name);
7786 if (ainfo->storage == LLVMArgVtypeByVal)
7787 mono_llvm_add_param_attr (LLVMGetParam (method, pindex), LLVM_ATTR_BY_VAL);
7789 if (ainfo->storage == LLVMArgVtypeByRef) {
7790 /* For OP_LDADDR */
7791 cfg->args [i + sig->hasthis]->opcode = OP_VTARG_ADDR;
7794 g_free (names);
7796 if (ctx->module->emit_dwarf && cfg->compile_aot && mono_debug_enabled ()) {
7797 ctx->minfo = mono_debug_lookup_method (cfg->method);
7798 ctx->dbg_md = emit_dbg_subprogram (ctx, cfg, method, ctx->method_name);
7801 max_block_num = 0;
7802 for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
7803 max_block_num = MAX (max_block_num, bb->block_num);
7804 ctx->bblocks = bblocks = g_new0 (BBInfo, max_block_num + 1);
7806 /* Add branches between non-consecutive bblocks */
7807 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7808 if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins) &&
7809 bb->next_bb != bb->last_ins->inst_false_bb) {
7811 MonoInst *inst = (MonoInst*)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
7812 inst->opcode = OP_BR;
7813 inst->inst_target_bb = bb->last_ins->inst_false_bb;
7814 mono_bblock_add_inst (bb, inst);
7819 * Make a first pass over the code to precreate PHI nodes/set INDIRECT flags.
7821 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7822 MonoInst *ins;
7823 LLVMBuilderRef builder;
7824 char *dname;
7825 char dname_buf[128];
7827 builder = create_builder (ctx);
7829 for (ins = bb->code; ins; ins = ins->next) {
7830 switch (ins->opcode) {
7831 case OP_PHI:
7832 case OP_FPHI:
7833 case OP_VPHI:
7834 case OP_XPHI: {
7835 LLVMTypeRef phi_type = llvm_type_to_stack_type (cfg, type_to_llvm_type (ctx, m_class_get_byval_arg (ins->klass)));
7837 if (!ctx_ok (ctx))
7838 return;
7840 if (ins->opcode == OP_VPHI) {
7841 /* Treat valuetype PHI nodes as operating on the address itself */
7842 g_assert (ins->klass);
7843 phi_type = LLVMPointerType (type_to_llvm_type (ctx, m_class_get_byval_arg (ins->klass)), 0);
7847 * Have to precreate these, as they can be referenced by
7848 * earlier instructions.
7850 sprintf (dname_buf, "t%d", ins->dreg);
7851 dname = dname_buf;
7852 values [ins->dreg] = LLVMBuildPhi (builder, phi_type, dname);
7854 if (ins->opcode == OP_VPHI)
7855 ctx->addresses [ins->dreg] = values [ins->dreg];
7857 g_ptr_array_add (ctx->phi_values, values [ins->dreg]);
7860 * Set the expected type of the incoming arguments since these have
7861 * to have the same type.
7863 for (i = 0; i < ins->inst_phi_args [0]; i++) {
7864 int sreg1 = ins->inst_phi_args [i + 1];
7866 if (sreg1 != -1) {
7867 if (ins->opcode == OP_VPHI)
7868 ctx->is_vphi [sreg1] = TRUE;
7869 ctx->vreg_types [sreg1] = phi_type;
7872 break;
7874 case OP_LDADDR:
7875 ((MonoInst*)ins->inst_p0)->flags |= MONO_INST_INDIRECT;
7876 break;
7877 default:
7878 break;
7884 * Create an ordering for bblocks, use the depth first order first, then
7885 * put the exception handling bblocks last.
7887 for (bb_index = 0; bb_index < cfg->num_bblocks; ++bb_index) {
7888 bb = cfg->bblocks [bb_index];
7889 if (!(bb->region != -1 && !MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY))) {
7890 g_ptr_array_add (bblock_list, bb);
7891 bblocks [bb->block_num].added = TRUE;
7895 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7896 if (!bblocks [bb->block_num].added)
7897 g_ptr_array_add (bblock_list, bb);
7901 * Second pass: generate code.
7903 // Emit entry point
7904 entry_builder = create_builder (ctx);
7905 entry_bb = get_bb (ctx, cfg->bb_entry);
7906 LLVMPositionBuilderAtEnd (entry_builder, entry_bb);
7907 emit_entry_bb (ctx, entry_builder);
7909 // Make landing pads first
7910 ctx->exc_meta = g_hash_table_new_full (NULL, NULL, NULL, NULL);
7912 if (ctx->llvm_only) {
7913 size_t group_index = 0;
7914 while (group_index < cfg->header->num_clauses) {
7915 int count = 0;
7916 size_t cursor = group_index;
7917 while (cursor < cfg->header->num_clauses &&
7918 CLAUSE_START (&cfg->header->clauses [cursor]) == CLAUSE_START (&cfg->header->clauses [group_index]) &&
7919 CLAUSE_END (&cfg->header->clauses [cursor]) == CLAUSE_END (&cfg->header->clauses [group_index])) {
7920 count++;
7921 cursor++;
7924 LLVMBasicBlockRef lpad_bb = emit_landing_pad (ctx, group_index, count);
7925 intptr_t key = CLAUSE_END (&cfg->header->clauses [group_index]);
7926 g_hash_table_insert (ctx->exc_meta, (gpointer)key, lpad_bb);
7928 group_index = cursor;
7932 for (bb_index = 0; bb_index < bblock_list->len; ++bb_index) {
7933 bb = (MonoBasicBlock*)g_ptr_array_index (bblock_list, bb_index);
7935 // Prune unreachable mono BBs.
7936 if (!(bb == cfg->bb_entry || bb->in_count > 0))
7937 continue;
7939 process_bb (ctx, bb);
7940 if (!ctx_ok (ctx))
7941 return;
7943 g_hash_table_destroy (ctx->exc_meta);
7945 mono_memory_barrier ();
7947 /* Add incoming phi values */
7948 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7949 GSList *l, *ins_list;
7951 ins_list = bblocks [bb->block_num].phi_nodes;
7953 for (l = ins_list; l; l = l->next) {
7954 PhiNode *node = (PhiNode*)l->data;
7955 MonoInst *phi = node->phi;
7956 int sreg1 = node->sreg;
7957 LLVMBasicBlockRef in_bb;
7959 if (sreg1 == -1)
7960 continue;
7962 in_bb = get_end_bb (ctx, node->in_bb);
7964 if (ctx->unreachable [node->in_bb->block_num])
7965 continue;
7967 if (phi->opcode == OP_VPHI) {
7968 g_assert (LLVMTypeOf (ctx->addresses [sreg1]) == LLVMTypeOf (values [phi->dreg]));
7969 LLVMAddIncoming (values [phi->dreg], &ctx->addresses [sreg1], &in_bb, 1);
7970 } else {
7971 if (!values [sreg1]) {
7972 /* Can happen with values in EH clauses */
7973 set_failure (ctx, "incoming phi sreg1");
7974 return;
7976 if (LLVMTypeOf (values [sreg1]) != LLVMTypeOf (values [phi->dreg])) {
7977 set_failure (ctx, "incoming phi arg type mismatch");
7978 return;
7980 g_assert (LLVMTypeOf (values [sreg1]) == LLVMTypeOf (values [phi->dreg]));
7981 LLVMAddIncoming (values [phi->dreg], &values [sreg1], &in_bb, 1);
7986 /* Nullify empty phi instructions */
7987 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
7988 GSList *l, *ins_list;
7990 ins_list = bblocks [bb->block_num].phi_nodes;
7992 for (l = ins_list; l; l = l->next) {
7993 PhiNode *node = (PhiNode*)l->data;
7994 MonoInst *phi = node->phi;
7995 LLVMValueRef phi_ins = values [phi->dreg];
7997 if (!phi_ins)
7998 /* Already removed */
7999 continue;
8001 if (LLVMCountIncoming (phi_ins) == 0) {
8002 mono_llvm_replace_uses_of (phi_ins, LLVMConstNull (LLVMTypeOf (phi_ins)));
8003 LLVMInstructionEraseFromParent (phi_ins);
8004 values [phi->dreg] = NULL;
8009 /* Create the SWITCH statements for ENDFINALLY instructions */
8010 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
8011 BBInfo *info = &bblocks [bb->block_num];
8012 GSList *l;
8013 for (l = info->endfinally_switch_ins_list; l; l = l->next) {
8014 LLVMValueRef switch_ins = (LLVMValueRef)l->data;
8015 GSList *bb_list = info->call_handler_return_bbs;
8017 GSList *bb_list_iter;
8018 i = 0;
8019 for (bb_list_iter = bb_list; bb_list_iter; bb_list_iter = g_slist_next (bb_list_iter)) {
8020 LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i + 1, FALSE), (LLVMBasicBlockRef)bb_list_iter->data);
8021 i ++;
8026 /* Initialize the method if needed */
8027 if (cfg->compile_aot && !ctx->module->llvm_disable_self_init) {
8028 // FIXME: Add more shared got entries
8029 ctx->builder = create_builder (ctx);
8030 LLVMPositionBuilderAtEnd (ctx->builder, ctx->init_bb);
8032 ctx->module->max_method_idx = MAX (ctx->module->max_method_idx, cfg->method_index);
8034 // FIXME: beforefieldinit
8036 * NATIVE_TO_MANAGED methods might be called on a thread not attached to the runtime, so they are initialized when loaded
8037 * in load_method ().
8039 gboolean needs_init = ctx->cfg->got_access_count > 0;
8040 MonoMethod *cctor = NULL;
8041 if (!needs_init && (cctor = mono_class_get_cctor (cfg->method->klass))) {
8042 /* Needs init to run the cctor */
8043 if (cfg->method->flags & METHOD_ATTRIBUTE_STATIC)
8044 needs_init = TRUE;
8045 if (cctor == cfg->method)
8046 needs_init = FALSE;
8048 // If we are a constructor, we need to init so the static
8049 // constructor gets called.
8050 if (!strcmp (cfg->method->name, ".ctor"))
8051 needs_init = TRUE;
8053 if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED)
8054 needs_init = FALSE;
8055 if (needs_init)
8056 emit_init_method (ctx);
8057 else
8058 LLVMBuildBr (ctx->builder, ctx->inited_bb);
8060 // Was observing LLVM moving field accesses into the caller's method
8061 // body before the init call (the inlined one), leading to NULL derefs
8062 // after the init_method returns (GOT is filled out though)
8063 if (needs_init)
8064 mono_llvm_add_func_attr (method, LLVM_ATTR_NO_INLINE);
8067 after_codegen:
8068 if (cfg->compile_aot && !ctx->module->llvm_disable_self_init) {
8069 g_ptr_array_add (ctx->module->cfgs, cfg);
8072 * Add the contents of ctx->callsite_list to module->callsite_list.
8073 * We can't do this earlier, as it contains llvm instructions which can be
8074 * freed if compilation fails.
8075 * FIXME: Get rid of this when all methods can be llvm compiled.
8077 for (int i = 0; i < ctx->callsite_list->len; ++i)
8078 g_ptr_array_add (ctx->module->callsite_list, g_ptr_array_index (ctx->callsite_list, i));
8081 if (cfg->verbose_level > 1)
8082 mono_llvm_dump_value (method);
8084 if (cfg->compile_aot && !cfg->llvm_only)
8085 mark_as_used (ctx->module, method);
8087 if (!cfg->llvm_only) {
8088 LLVMValueRef md_args [16];
8089 LLVMValueRef md_node;
8090 int method_index;
8092 if (cfg->compile_aot)
8093 method_index = mono_aot_get_method_index (cfg->orig_method);
8094 else
8095 method_index = 1;
8096 md_args [0] = LLVMMDString (ctx->method_name, strlen (ctx->method_name));
8097 md_args [1] = LLVMConstInt (LLVMInt32Type (), method_index, FALSE);
8098 md_node = LLVMMDNode (md_args, 2);
8099 LLVMAddNamedMetadataOperand (lmodule, "mono.function_indexes", md_node);
8100 //LLVMSetMetadata (method, md_kind, LLVMMDNode (&md_arg, 1));
8103 if (cfg->compile_aot) {
8104 /* Don't generate native code, keep the LLVM IR */
8105 if (cfg->verbose_level) {
8106 char *name = mono_method_get_full_name (cfg->method);
8107 printf ("%s emitted as %s\n", name, ctx->method_name);
8108 g_free (name);
8111 //LLVMDumpValue (ctx->lmethod);
8112 #if LLVM_API_VERSION < 100
8113 /* VerifyFunction can't handle some of the debug info created by DIBuilder in llvm 3.9 */
8114 int err = LLVMVerifyFunction(ctx->lmethod, LLVMPrintMessageAction);
8115 g_assert (err == 0);
8116 #endif
8117 } else {
8118 //LLVMVerifyFunction (method, 0);
8119 llvm_jit_finalize_method (ctx);
8122 if (ctx->module->method_to_lmethod)
8123 g_hash_table_insert (ctx->module->method_to_lmethod, cfg->method, ctx->lmethod);
8124 if (ctx->module->idx_to_lmethod)
8125 g_hash_table_insert (ctx->module->idx_to_lmethod, GINT_TO_POINTER (cfg->method_index), ctx->lmethod);
8127 if (ctx->llvm_only && m_class_is_valuetype (cfg->orig_method->klass) && !(cfg->orig_method->flags & METHOD_ATTRIBUTE_STATIC))
8128 emit_unbox_tramp (ctx, ctx->method_name, ctx->method_type, ctx->lmethod, cfg->method_index);
8132 * mono_llvm_create_vars:
8134 * Same as mono_arch_create_vars () for LLVM.
8136 void
8137 mono_llvm_create_vars (MonoCompile *cfg)
8139 MonoMethodSignature *sig;
8141 sig = mono_method_signature_internal (cfg->method);
8142 if (cfg->gsharedvt && cfg->llvm_only) {
8143 gboolean vretaddr = FALSE;
8145 if (mini_is_gsharedvt_variable_signature (sig) && sig->ret->type != MONO_TYPE_VOID) {
8146 vretaddr = TRUE;
8147 } else {
8148 MonoMethodSignature *sig = mono_method_signature_internal (cfg->method);
8149 LLVMCallInfo *linfo;
8151 linfo = get_llvm_call_info (cfg, sig);
8152 vretaddr = (linfo->ret.storage == LLVMArgVtypeRetAddr || linfo->ret.storage == LLVMArgVtypeByRef || linfo->ret.storage == LLVMArgGsharedvtFixed || linfo->ret.storage == LLVMArgGsharedvtVariable || linfo->ret.storage == LLVMArgGsharedvtFixedVtype);
8154 if (vretaddr) {
8156 * Creating vret_addr forces CEE_SETRET to store the result into it,
8157 * so we don't have to generate any code in our OP_SETRET case.
8159 cfg->vret_addr = mono_compile_create_var (cfg, m_class_get_byval_arg (mono_get_intptr_class ()), OP_ARG);
8160 if (G_UNLIKELY (cfg->verbose_level > 1)) {
8161 printf ("vret_addr = ");
8162 mono_print_ins (cfg->vret_addr);
8165 } else {
8166 mono_arch_create_vars (cfg);
8171 * mono_llvm_emit_call:
8173 * Same as mono_arch_emit_call () for LLVM.
8175 void
8176 mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call)
8178 MonoInst *in;
8179 MonoMethodSignature *sig;
8180 int i, n, stack_size;
8181 LLVMArgInfo *ainfo;
8183 stack_size = 0;
8185 sig = call->signature;
8186 n = sig->param_count + sig->hasthis;
8188 call->cinfo = get_llvm_call_info (cfg, sig);
8190 if (cfg->disable_llvm)
8191 return;
8193 if (sig->call_convention == MONO_CALL_VARARG) {
8194 cfg->exception_message = g_strdup ("varargs");
8195 cfg->disable_llvm = TRUE;
8198 for (i = 0; i < n; ++i) {
8199 MonoInst *ins;
8201 ainfo = call->cinfo->args + i;
8203 in = call->args [i];
8205 /* Simply remember the arguments */
8206 switch (ainfo->storage) {
8207 case LLVMArgNormal: {
8208 MonoType *t = (sig->hasthis && i == 0) ? m_class_get_byval_arg (mono_get_intptr_class ()) : ainfo->type;
8209 int opcode;
8211 opcode = mono_type_to_regmove (cfg, t);
8212 if (opcode == OP_FMOVE) {
8213 MONO_INST_NEW (cfg, ins, OP_FMOVE);
8214 ins->dreg = mono_alloc_freg (cfg);
8215 } else if (opcode == OP_LMOVE) {
8216 MONO_INST_NEW (cfg, ins, OP_LMOVE);
8217 ins->dreg = mono_alloc_lreg (cfg);
8218 } else if (opcode == OP_RMOVE) {
8219 MONO_INST_NEW (cfg, ins, OP_RMOVE);
8220 ins->dreg = mono_alloc_freg (cfg);
8221 } else {
8222 MONO_INST_NEW (cfg, ins, OP_MOVE);
8223 ins->dreg = mono_alloc_ireg (cfg);
8225 ins->sreg1 = in->dreg;
8226 break;
8228 case LLVMArgVtypeByVal:
8229 case LLVMArgVtypeByRef:
8230 case LLVMArgVtypeInReg:
8231 case LLVMArgVtypeAsScalar:
8232 case LLVMArgAsIArgs:
8233 case LLVMArgAsFpArgs:
8234 case LLVMArgGsharedvtVariable:
8235 case LLVMArgGsharedvtFixed:
8236 case LLVMArgGsharedvtFixedVtype:
8237 MONO_INST_NEW (cfg, ins, OP_LLVM_OUTARG_VT);
8238 ins->dreg = mono_alloc_ireg (cfg);
8239 ins->sreg1 = in->dreg;
8240 ins->inst_p0 = mono_mempool_alloc0 (cfg->mempool, sizeof (LLVMArgInfo));
8241 memcpy (ins->inst_p0, ainfo, sizeof (LLVMArgInfo));
8242 ins->inst_vtype = ainfo->type;
8243 ins->klass = mono_class_from_mono_type_internal (ainfo->type);
8244 break;
8245 default:
8246 cfg->exception_message = g_strdup ("ainfo->storage");
8247 cfg->disable_llvm = TRUE;
8248 return;
8251 if (!cfg->disable_llvm) {
8252 MONO_ADD_INS (cfg->cbb, ins);
8253 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, 0, FALSE);
8258 static inline void
8259 AddFunc (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeRef *param_types, int nparams)
8261 LLVMAddFunction (module, name, LLVMFunctionType (ret_type, param_types, nparams, FALSE));
8264 static inline void
8265 AddFunc2 (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeRef param_type1, LLVMTypeRef param_type2)
8267 LLVMTypeRef param_types [4];
8269 param_types [0] = param_type1;
8270 param_types [1] = param_type2;
8272 AddFunc (module, name, ret_type, param_types, 2);
8275 typedef struct {
8276 IntrinsicId id;
8277 const char *name;
8278 } IntrinsicDesc;
8280 static IntrinsicDesc intrinsics[] = {
8281 {INTRINS_MEMSET, "llvm.memset.p0i8.i32"},
8282 {INTRINS_MEMCPY, "llvm.memcpy.p0i8.p0i8.i32"},
8283 {INTRINS_SADD_OVF_I32, "llvm.sadd.with.overflow.i32"},
8284 {INTRINS_UADD_OVF_I32, "llvm.uadd.with.overflow.i32"},
8285 {INTRINS_SSUB_OVF_I32, "llvm.ssub.with.overflow.i32"},
8286 {INTRINS_USUB_OVF_I32, "llvm.usub.with.overflow.i32"},
8287 {INTRINS_SMUL_OVF_I32, "llvm.smul.with.overflow.i32"},
8288 {INTRINS_UMUL_OVF_I32, "llvm.umul.with.overflow.i32"},
8289 {INTRINS_SADD_OVF_I64, "llvm.sadd.with.overflow.i64"},
8290 {INTRINS_UADD_OVF_I64, "llvm.uadd.with.overflow.i64"},
8291 {INTRINS_SSUB_OVF_I64, "llvm.ssub.with.overflow.i64"},
8292 {INTRINS_USUB_OVF_I64, "llvm.usub.with.overflow.i64"},
8293 {INTRINS_SMUL_OVF_I64, "llvm.smul.with.overflow.i64"},
8294 {INTRINS_UMUL_OVF_I64, "llvm.umul.with.overflow.i64"},
8295 {INTRINS_SIN, "llvm.sin.f64"},
8296 {INTRINS_COS, "llvm.cos.f64"},
8297 {INTRINS_SQRT, "llvm.sqrt.f64"},
8298 /* This isn't an intrinsic, instead llvm seems to special case it by name */
8299 {INTRINS_FABS, "fabs"},
8300 {INTRINS_ABSF, "llvm.fabs.f32"},
8301 {INTRINS_SINF, "llvm.sin.f32"},
8302 {INTRINS_COSF, "llvm.cos.f32"},
8303 {INTRINS_SQRTF, "llvm.sqrt.f32"},
8304 {INTRINS_POWF, "llvm.pow.f32"},
8305 {INTRINS_EXPECT_I8, "llvm.expect.i8"},
8306 {INTRINS_EXPECT_I1, "llvm.expect.i1"},
8307 #if defined(TARGET_AMD64) || defined(TARGET_X86)
8308 {INTRINS_SSE_PMOVMSKB, "llvm.x86.sse2.pmovmskb.128"},
8309 {INTRINS_SSE_PSRLI_W, "llvm.x86.sse2.psrli.w"},
8310 {INTRINS_SSE_PSRAI_W, "llvm.x86.sse2.psrai.w"},
8311 {INTRINS_SSE_PSLLI_W, "llvm.x86.sse2.pslli.w"},
8312 {INTRINS_SSE_PSRLI_D, "llvm.x86.sse2.psrli.d"},
8313 {INTRINS_SSE_PSRAI_D, "llvm.x86.sse2.psrai.d"},
8314 {INTRINS_SSE_PSLLI_D, "llvm.x86.sse2.pslli.d"},
8315 {INTRINS_SSE_PSRLI_Q, "llvm.x86.sse2.psrli.q"},
8316 {INTRINS_SSE_PSLLI_Q, "llvm.x86.sse2.pslli.q"},
8317 {INTRINS_SSE_SQRT_PD, "llvm.x86.sse2.sqrt.pd"},
8318 {INTRINS_SSE_SQRT_PS, "llvm.x86.sse.sqrt.ps"},
8319 {INTRINS_SSE_RSQRT_PS, "llvm.x86.sse.rsqrt.ps"},
8320 {INTRINS_SSE_RCP_PS, "llvm.x86.sse.rcp.ps"},
8321 {INTRINS_SSE_CVTTPD2DQ, "llvm.x86.sse2.cvttpd2dq"},
8322 {INTRINS_SSE_CVTTPS2DQ, "llvm.x86.sse2.cvttps2dq"},
8323 {INTRINS_SSE_CVTDQ2PD, "llvm.x86.sse2.cvtdq2pd"},
8324 {INTRINS_SSE_CVTDQ2PS, "llvm.x86.sse2.cvtdq2ps"},
8325 {INTRINS_SSE_CVTPD2DQ, "llvm.x86.sse2.cvtpd2dq"},
8326 {INTRINS_SSE_CVTPS2DQ, "llvm.x86.sse2.cvtps2dq"},
8327 {INTRINS_SSE_CVTPD2PS, "llvm.x86.sse2.cvtpd2ps"},
8328 {INTRINS_SSE_CVTPS2PD, "llvm.x86.sse2.cvtps2pd"},
8329 {INTRINS_SSE_CMPPD, "llvm.x86.sse2.cmp.pd"},
8330 {INTRINS_SSE_CMPPS, "llvm.x86.sse.cmp.ps"},
8331 {INTRINS_SSE_PACKSSWB, "llvm.x86.sse2.packsswb.128"},
8332 {INTRINS_SSE_PACKUSWB, "llvm.x86.sse2.packuswb.128"},
8333 {INTRINS_SSE_PACKSSDW, "llvm.x86.sse2.packssdw.128"},
8334 {INTRINS_SSE_PACKUSDW, "llvm.x86.sse41.packusdw"},
8335 {INTRINS_SSE_MINPS, "llvm.x86.sse.min.ps"},
8336 {INTRINS_SSE_MAXPS, "llvm.x86.sse.max.ps"},
8337 {INTRINS_SSE_HADDPS, "llvm.x86.sse3.hadd.ps"},
8338 {INTRINS_SSE_HSUBPS, "llvm.x86.sse3.hsub.ps"},
8339 {INTRINS_SSE_ADDSUBPS, "llvm.x86.sse3.addsub.ps"},
8340 {INTRINS_SSE_MINPD, "llvm.x86.sse2.min.pd"},
8341 {INTRINS_SSE_MAXPD, "llvm.x86.sse2.max.pd"},
8342 {INTRINS_SSE_HADDPD, "llvm.x86.sse3.hadd.pd"},
8343 {INTRINS_SSE_HSUBPD, "llvm.x86.sse3.hsub.pd"},
8344 {INTRINS_SSE_ADDSUBPD, "llvm.x86.sse3.addsub.pd"},
8345 {INTRINS_SSE_PADDSW, "llvm.x86.sse2.padds.w"},
8346 {INTRINS_SSE_PSUBSW, "llvm.x86.sse2.psubs.w"},
8347 {INTRINS_SSE_PADDUSW, "llvm.x86.sse2.paddus.w"},
8348 {INTRINS_SSE_PSUBUSW, "llvm.x86.sse2.psubus.w"},
8349 {INTRINS_SSE_PAVGW, "llvm.x86.sse2.pavg.w"},
8350 {INTRINS_SSE_PMULHW, "llvm.x86.sse2.pmulh.w"},
8351 {INTRINS_SSE_PMULHU, "llvm.x86.sse2.pmulhu.w"},
8352 {INTRINS_SE_PADDSB, "llvm.x86.sse2.padds.b"},
8353 {INTRINS_SSE_PSUBSB, "llvm.x86.sse2.psubs.b"},
8354 {INTRINS_SSE_PADDUSB, "llvm.x86.sse2.paddus.b"},
8355 {INTRINS_SSE_PSUBUSB, "llvm.x86.sse2.psubus.b"},
8356 {INTRINS_SSE_PAVGB, "llvm.x86.sse2.pavg.b"},
8357 {INTRINS_SSE_PAUSE, "llvm.x86.sse2.pause"},
8358 {INTRINS_SSE_DPPS, "llvm.x86.sse41.dpps"},
8359 {INTRINS_SSE_ROUNDPD, "llvm.x86.sse41.round.pd"}
8360 #endif
8363 static void
8364 add_sse_binary (LLVMModuleRef module, const char *name, int type)
8366 LLVMTypeRef ret_type = type_to_simd_type (type);
8367 AddFunc2 (module, name, ret_type, ret_type, ret_type);
8370 static void
8371 add_intrinsic (LLVMModuleRef module, int id)
8373 const char *name;
8374 #if defined(TARGET_AMD64) || defined(TARGET_X86)
8375 LLVMTypeRef ret_type, arg_types [16];
8376 #endif
8378 name = (const char*)g_hash_table_lookup (intrins_id_to_name, GINT_TO_POINTER (id));
8379 g_assert (name);
8381 switch (id) {
8382 case INTRINS_MEMSET: {
8383 LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMInt8Type (), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
8385 AddFunc (module, name, LLVMVoidType (), params, 5);
8386 break;
8388 case INTRINS_MEMCPY: {
8389 LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMPointerType (LLVMInt8Type (), 0), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
8391 AddFunc (module, name, LLVMVoidType (), params, 5);
8392 break;
8394 case INTRINS_SADD_OVF_I32:
8395 case INTRINS_UADD_OVF_I32:
8396 case INTRINS_SSUB_OVF_I32:
8397 case INTRINS_USUB_OVF_I32:
8398 case INTRINS_SMUL_OVF_I32:
8399 case INTRINS_UMUL_OVF_I32: {
8400 LLVMTypeRef ovf_res_i32 [] = { LLVMInt32Type (), LLVMInt1Type () };
8401 LLVMTypeRef params [] = { LLVMInt32Type (), LLVMInt32Type () };
8402 LLVMTypeRef ret_type = LLVMStructType (ovf_res_i32, 2, FALSE);
8404 AddFunc (module, name, ret_type, params, 2);
8405 break;
8407 case INTRINS_SADD_OVF_I64:
8408 case INTRINS_UADD_OVF_I64:
8409 case INTRINS_SSUB_OVF_I64:
8410 case INTRINS_USUB_OVF_I64:
8411 case INTRINS_SMUL_OVF_I64:
8412 case INTRINS_UMUL_OVF_I64: {
8413 LLVMTypeRef ovf_res_i64 [] = { LLVMInt64Type (), LLVMInt1Type () };
8414 LLVMTypeRef params [] = { LLVMInt64Type (), LLVMInt64Type () };
8415 LLVMTypeRef ret_type = LLVMStructType (ovf_res_i64, 2, FALSE);
8417 AddFunc (module, name, ret_type, params, 2);
8418 break;
8420 case INTRINS_SIN:
8421 case INTRINS_COS:
8422 case INTRINS_SQRT:
8423 case INTRINS_FABS: {
8424 LLVMTypeRef params [] = { LLVMDoubleType () };
8426 AddFunc (module, name, LLVMDoubleType (), params, 1);
8427 break;
8429 case INTRINS_SINF:
8430 case INTRINS_COSF:
8431 case INTRINS_SQRTF:
8432 case INTRINS_ABSF: {
8433 LLVMTypeRef params [] = { LLVMFloatType () };
8435 AddFunc (module, name, LLVMFloatType (), params, 1);
8436 break;
8438 case INTRINS_POWF: {
8439 LLVMTypeRef params [] = { LLVMFloatType (), LLVMFloatType () };
8441 AddFunc (module, name, LLVMFloatType (), params, 2);
8442 break;
8444 case INTRINS_EXPECT_I8:
8445 AddFunc2 (module, name, LLVMInt8Type (), LLVMInt8Type (), LLVMInt8Type ());
8446 break;
8447 case INTRINS_EXPECT_I1:
8448 AddFunc2 (module, name, LLVMInt1Type (), LLVMInt1Type (), LLVMInt1Type ());
8449 break;
8450 #if defined(TARGET_AMD64) || defined(TARGET_X86)
8451 case INTRINS_SSE_PMOVMSKB:
8452 /* pmovmskb */
8453 ret_type = LLVMInt32Type ();
8454 arg_types [0] = type_to_simd_type (MONO_TYPE_I1);
8455 AddFunc (module, name, ret_type, arg_types, 1);
8456 break;
8457 case INTRINS_SSE_PSRLI_W:
8458 case INTRINS_SSE_PSRAI_W:
8459 case INTRINS_SSE_PSLLI_W:
8460 /* shifts */
8461 ret_type = type_to_simd_type (MONO_TYPE_I2);
8462 arg_types [0] = ret_type;
8463 arg_types [1] = LLVMInt32Type ();
8464 AddFunc (module, name, ret_type, arg_types, 2);
8465 break;
8466 case INTRINS_SSE_PSRLI_D:
8467 case INTRINS_SSE_PSRAI_D:
8468 case INTRINS_SSE_PSLLI_D:
8469 ret_type = type_to_simd_type (MONO_TYPE_I4);
8470 arg_types [0] = ret_type;
8471 arg_types [1] = LLVMInt32Type ();
8472 AddFunc (module, name, ret_type, arg_types, 2);
8473 break;
8474 case INTRINS_SSE_PSRLI_Q:
8475 case INTRINS_SSE_PSLLI_Q:
8476 ret_type = type_to_simd_type (MONO_TYPE_I8);
8477 arg_types [0] = ret_type;
8478 arg_types [1] = LLVMInt32Type ();
8479 AddFunc (module, name, ret_type, arg_types, 2);
8480 break;
8481 case INTRINS_SSE_SQRT_PD:
8482 /* Unary ops */
8483 ret_type = type_to_simd_type (MONO_TYPE_R8);
8484 arg_types [0] = ret_type;
8485 AddFunc (module, name, ret_type, arg_types, 1);
8486 break;
8487 case INTRINS_SSE_SQRT_PS:
8488 ret_type = type_to_simd_type (MONO_TYPE_R4);
8489 arg_types [0] = ret_type;
8490 AddFunc (module, name, ret_type, arg_types, 1);
8491 break;
8492 case INTRINS_SSE_RSQRT_PS:
8493 ret_type = type_to_simd_type (MONO_TYPE_R4);
8494 arg_types [0] = ret_type;
8495 AddFunc (module, name, ret_type, arg_types, 1);
8496 break;
8497 case INTRINS_SSE_RCP_PS:
8498 ret_type = type_to_simd_type (MONO_TYPE_R4);
8499 arg_types [0] = ret_type;
8500 AddFunc (module, name, ret_type, arg_types, 1);
8501 break;
8502 case INTRINS_SSE_CVTTPD2DQ:
8503 ret_type = type_to_simd_type (MONO_TYPE_I4);
8504 arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
8505 AddFunc (module, name, ret_type, arg_types, 1);
8506 break;
8507 case INTRINS_SSE_CVTTPS2DQ:
8508 ret_type = type_to_simd_type (MONO_TYPE_I4);
8509 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8510 AddFunc (module, name, ret_type, arg_types, 1);
8511 break;
8512 case INTRINS_SSE_CVTDQ2PD:
8513 /* Conversion ops */
8514 ret_type = type_to_simd_type (MONO_TYPE_R8);
8515 arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
8516 AddFunc (module, name, ret_type, arg_types, 1);
8517 break;
8518 case INTRINS_SSE_CVTDQ2PS:
8519 ret_type = type_to_simd_type (MONO_TYPE_R4);
8520 arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
8521 AddFunc (module, name, ret_type, arg_types, 1);
8522 break;
8523 case INTRINS_SSE_CVTPD2DQ:
8524 ret_type = type_to_simd_type (MONO_TYPE_I4);
8525 arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
8526 AddFunc (module, name, ret_type, arg_types, 1);
8527 break;
8528 case INTRINS_SSE_CVTPS2DQ:
8529 ret_type = type_to_simd_type (MONO_TYPE_I4);
8530 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8531 AddFunc (module, name, ret_type, arg_types, 1);
8532 break;
8533 case INTRINS_SSE_CVTPD2PS:
8534 ret_type = type_to_simd_type (MONO_TYPE_R4);
8535 arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
8536 AddFunc (module, name, ret_type, arg_types, 1);
8537 break;
8538 case INTRINS_SSE_CVTPS2PD:
8539 ret_type = type_to_simd_type (MONO_TYPE_R8);
8540 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8541 AddFunc (module, name, ret_type, arg_types, 1);
8542 break;
8543 case INTRINS_SSE_CMPPD:
8544 /* cmp pd/ps */
8545 ret_type = type_to_simd_type (MONO_TYPE_R8);
8546 arg_types [0] = ret_type;
8547 arg_types [1] = ret_type;
8548 arg_types [2] = LLVMInt8Type ();
8549 AddFunc (module, name, ret_type, arg_types, 3);
8550 break;
8551 case INTRINS_SSE_CMPPS:
8552 ret_type = type_to_simd_type (MONO_TYPE_R4);
8553 arg_types [0] = ret_type;
8554 arg_types [1] = ret_type;
8555 arg_types [2] = LLVMInt8Type ();
8556 AddFunc (module, name, ret_type, arg_types, 3);
8557 break;
8558 case INTRINS_SSE_PACKSSWB:
8559 case INTRINS_SSE_PACKUSWB:
8560 case INTRINS_SSE_PACKSSDW:
8561 /* pack */
8562 ret_type = type_to_simd_type (MONO_TYPE_I1);
8563 arg_types [0] = type_to_simd_type (MONO_TYPE_I2);
8564 arg_types [1] = type_to_simd_type (MONO_TYPE_I2);
8565 AddFunc (module, name, ret_type, arg_types, 2);
8566 break;
8567 case INTRINS_SSE_PACKUSDW:
8568 ret_type = type_to_simd_type (MONO_TYPE_I2);
8569 arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
8570 arg_types [1] = type_to_simd_type (MONO_TYPE_I4);
8571 AddFunc (module, name, ret_type, arg_types, 2);
8572 break;
8573 /* SSE Binary ops */
8574 case INTRINS_SSE_PADDSW:
8575 case INTRINS_SSE_PSUBSW:
8576 case INTRINS_SSE_PADDUSW:
8577 case INTRINS_SSE_PSUBUSW:
8578 case INTRINS_SSE_PAVGW:
8579 case INTRINS_SSE_PMULHW:
8580 case INTRINS_SSE_PMULHU:
8581 add_sse_binary (module, name, MONO_TYPE_I2);
8582 break;
8583 case INTRINS_SSE_MINPS:
8584 case INTRINS_SSE_MAXPS:
8585 case INTRINS_SSE_HADDPS:
8586 case INTRINS_SSE_HSUBPS:
8587 case INTRINS_SSE_ADDSUBPS:
8588 add_sse_binary (module, name, MONO_TYPE_R4);
8589 break;
8590 case INTRINS_SSE_MINPD:
8591 case INTRINS_SSE_MAXPD:
8592 case INTRINS_SSE_HADDPD:
8593 case INTRINS_SSE_HSUBPD:
8594 case INTRINS_SSE_ADDSUBPD:
8595 add_sse_binary (module, name, MONO_TYPE_R8);
8596 break;
8597 case INTRINS_SE_PADDSB:
8598 case INTRINS_SSE_PSUBSB:
8599 case INTRINS_SSE_PADDUSB:
8600 case INTRINS_SSE_PSUBUSB:
8601 case INTRINS_SSE_PAVGB:
8602 add_sse_binary (module, name, MONO_TYPE_I1);
8603 break;
8604 case INTRINS_SSE_PAUSE:
8605 AddFunc (module, "llvm.x86.sse2.pause", LLVMVoidType (), NULL, 0);
8606 break;
8607 case INTRINS_SSE_DPPS:
8608 ret_type = type_to_simd_type (MONO_TYPE_R4);
8609 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8610 arg_types [1] = type_to_simd_type (MONO_TYPE_R4);
8611 #if LLVM_API_VERSION >= 500
8612 arg_types [2] = LLVMInt8Type ();
8613 #else
8614 arg_types [2] = LLVMInt32Type ();
8615 #endif
8616 AddFunc (module, name, ret_type, arg_types, 3);
8617 break;
8618 case INTRINS_SSE_ROUNDPD:
8619 ret_type = type_to_simd_type (MONO_TYPE_R8);
8620 arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
8621 arg_types [1] = LLVMInt32Type ();
8622 AddFunc (module, name, ret_type, arg_types, 2);
8623 break;
8624 #endif /* AMD64 || X86 */
8625 default:
8626 g_assert_not_reached ();
8627 break;
8631 static LLVMValueRef
8632 get_intrins (EmitContext *ctx, int id)
8634 const char *name = (const char*)g_hash_table_lookup (intrins_id_to_name, GINT_TO_POINTER (id));
8635 g_assert (name);
8637 #if LLVM_API_VERSION > 100
8638 LLVMValueRef res;
8641 * Every method is emitted into its own module so
8642 * we can add intrinsics on demand.
8644 res = ctx->module->intrins_by_id [id];
8645 if (!res) {
8646 res = LLVMGetNamedFunction (ctx->lmodule, name);
8647 if (!res) {
8648 add_intrinsic (ctx->lmodule, id);
8649 res = LLVMGetNamedFunction (ctx->lmodule, name);
8650 g_assert (res);
8652 ctx->module->intrins_by_id [id] = res;
8654 return res;
8655 #else
8656 LLVMValueRef res;
8658 res = LLVMGetNamedFunction (ctx->lmodule, name);
8659 g_assert (res);
8660 return res;
8661 #endif
8664 static LLVMValueRef
8665 get_intrins_by_name (EmitContext *ctx, const char *name)
8667 #if LLVM_API_VERSION > 100
8668 LLVMValueRef res;
8671 * Every method is emitted into its own module so
8672 * we can add intrinsics on demand.
8674 res = LLVMGetNamedFunction (ctx->lmodule, name);
8675 if (!res) {
8676 int id = -1;
8678 /* No locking needed */
8679 id = GPOINTER_TO_INT (g_hash_table_lookup (intrins_name_to_id, name));
8680 id --;
8681 if (id == -1)
8682 printf ("%s\n", name);
8683 g_assert (id != -1);
8684 add_intrinsic (ctx->lmodule, id);
8685 res = LLVMGetNamedFunction (ctx->lmodule, name);
8686 g_assert (res);
8689 return res;
8690 #else
8691 LLVMValueRef res;
8693 res = LLVMGetNamedFunction (ctx->lmodule, name);
8694 g_assert (res);
8695 return res;
8696 #endif
8699 static void
8700 add_intrinsics (LLVMModuleRef module)
8702 int i;
8704 /* Emit declarations of instrinsics */
8706 * It would be nicer to emit only the intrinsics actually used, but LLVM's Module
8707 * type doesn't seem to do any locking.
8709 for (i = 0; i < INTRINS_NUM; ++i)
8710 add_intrinsic (module, i);
8712 /* EH intrinsics */
8714 AddFunc (module, "mono_personality", LLVMVoidType (), NULL, 0);
8716 AddFunc (module, "llvm_resume_unwind_trampoline", LLVMVoidType (), NULL, 0);
8719 /* Load/Store intrinsics */
8721 LLVMTypeRef arg_types [5];
8722 int i;
8723 char name [128];
8725 for (i = 1; i <= 8; i *= 2) {
8726 arg_types [0] = LLVMPointerType (LLVMIntType (i * 8), 0);
8727 arg_types [1] = LLVMInt32Type ();
8728 arg_types [2] = LLVMInt1Type ();
8729 arg_types [3] = LLVMInt32Type ();
8730 sprintf (name, "llvm.mono.load.i%d.p0i%d", i * 8, i * 8);
8731 AddFunc (module, name, LLVMIntType (i * 8), arg_types, 4);
8733 arg_types [0] = LLVMIntType (i * 8);
8734 arg_types [1] = LLVMPointerType (LLVMIntType (i * 8), 0);
8735 arg_types [2] = LLVMInt32Type ();
8736 arg_types [3] = LLVMInt1Type ();
8737 arg_types [4] = LLVMInt32Type ();
8738 sprintf (name, "llvm.mono.store.i%d.p0i%d", i * 8, i * 8);
8739 AddFunc (module, name, LLVMVoidType (), arg_types, 5);
8744 static void
8745 add_types (MonoLLVMModule *module)
8747 module->ptr_type = LLVMPointerType (TARGET_SIZEOF_VOID_P == 8 ? LLVMInt64Type () : LLVMInt32Type (), 0);
8750 void
8751 mono_llvm_init (void)
8753 GHashTable *h;
8754 int i;
8756 mono_native_tls_alloc (&current_cfg_tls_id, NULL);
8758 h = g_hash_table_new (NULL, NULL);
8759 for (i = 0; i < INTRINS_NUM; ++i)
8760 g_hash_table_insert (h, GINT_TO_POINTER (intrinsics [i].id), (gpointer)intrinsics [i].name);
8761 intrins_id_to_name = h;
8763 h = g_hash_table_new (g_str_hash, g_str_equal);
8764 for (i = 0; i < INTRINS_NUM; ++i)
8765 g_hash_table_insert (h, (gpointer)intrinsics [i].name, GINT_TO_POINTER (intrinsics [i].id + 1));
8766 intrins_name_to_id = h;
8769 void
8770 mono_llvm_cleanup (void)
8772 MonoLLVMModule *module = &aot_module;
8774 if (module->lmodule)
8775 LLVMDisposeModule (module->lmodule);
8777 if (module->context)
8778 LLVMContextDispose (module->context);
8781 void
8782 mono_llvm_free_domain_info (MonoDomain *domain)
8784 MonoJitDomainInfo *info = domain_jit_info (domain);
8785 MonoLLVMModule *module = (MonoLLVMModule*)info->llvm_module;
8786 int i;
8788 if (!module)
8789 return;
8791 g_hash_table_destroy (module->llvm_types);
8793 mono_llvm_dispose_ee (module->mono_ee);
8795 if (module->bb_names) {
8796 for (i = 0; i < module->bb_names_len; ++i)
8797 g_free (module->bb_names [i]);
8798 g_free (module->bb_names);
8800 //LLVMDisposeModule (module->module);
8802 g_free (module);
8804 info->llvm_module = NULL;
8807 void
8808 mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, int initial_got_size, LLVMModuleFlags flags)
8810 MonoLLVMModule *module = &aot_module;
8811 gboolean emit_dwarf = (flags & LLVM_MODULE_FLAG_DWARF) ? 1 : 0;
8812 #ifdef TARGET_WIN32_MSVC
8813 gboolean emit_codeview = (flags & LLVM_MODULE_FLAG_CODEVIEW) ? 1 : 0;
8814 #endif
8815 gboolean static_link = (flags & LLVM_MODULE_FLAG_STATIC) ? 1 : 0;
8816 gboolean llvm_only = (flags & LLVM_MODULE_FLAG_LLVM_ONLY) ? 1 : 0;
8817 gboolean interp = (flags & LLVM_MODULE_FLAG_INTERP) ? 1 : 0;
8818 gboolean llvm_disable_self_init = mini_get_debug_options ()->llvm_disable_self_init;
8820 /* Delete previous module */
8821 g_hash_table_destroy (module->plt_entries);
8822 if (module->lmodule)
8823 LLVMDisposeModule (module->lmodule);
8825 memset (module, 0, sizeof (aot_module));
8827 module->lmodule = LLVMModuleCreateWithName ("aot");
8828 module->assembly = assembly;
8829 module->global_prefix = g_strdup (global_prefix);
8830 module->got_symbol = g_strdup_printf ("%s_llvm_got", global_prefix);
8831 module->eh_frame_symbol = g_strdup_printf ("%s_eh_frame", global_prefix);
8832 module->get_method_symbol = g_strdup_printf ("%s_get_method", global_prefix);
8833 module->get_unbox_tramp_symbol = g_strdup_printf ("%s_get_unbox_tramp", global_prefix);
8834 module->external_symbols = TRUE;
8835 module->emit_dwarf = emit_dwarf;
8836 module->static_link = static_link;
8837 module->llvm_only = llvm_only;
8838 module->llvm_disable_self_init = llvm_disable_self_init && !llvm_only; // llvm_only implies !llvm_disable_self_init
8839 module->interp = interp;
8840 /* The first few entries are reserved */
8841 module->max_got_offset = initial_got_size;
8842 module->context = LLVMGetGlobalContext ();
8843 module->cfgs = g_ptr_array_new ();
8844 module->intrins_by_id = g_new0 (LLVMValueRef, INTRINS_NUM);
8846 if (llvm_only)
8847 /* clang ignores our debug info because it has an invalid version */
8848 module->emit_dwarf = FALSE;
8850 add_intrinsics (module->lmodule);
8851 add_types (module);
8853 #ifdef MONO_ARCH_LLVM_TARGET_LAYOUT
8854 LLVMSetDataLayout (module->lmodule, MONO_ARCH_LLVM_TARGET_LAYOUT);
8855 #endif
8857 #ifdef MONO_ARCH_LLVM_TARGET_TRIPLE
8858 LLVMSetTarget (module->lmodule, MONO_ARCH_LLVM_TARGET_TRIPLE);
8859 #endif
8861 #if LLVM_API_VERSION > 100
8862 if (module->emit_dwarf) {
8863 char *dir, *build_info, *s, *cu_name;
8865 module->di_builder = mono_llvm_create_di_builder (module->lmodule);
8867 // FIXME:
8868 dir = g_strdup (".");
8869 build_info = mono_get_runtime_build_info ();
8870 s = g_strdup_printf ("Mono AOT Compiler %s (LLVM)", build_info);
8871 cu_name = g_path_get_basename (assembly->image->name);
8872 module->cu = mono_llvm_di_create_compile_unit (module->di_builder, cu_name, dir, s);
8873 g_free (dir);
8874 g_free (build_info);
8875 g_free (s);
8877 #endif
8879 #ifdef TARGET_WIN32_MSVC
8880 if (emit_codeview) {
8881 LLVMValueRef codeview_option_args[3];
8883 codeview_option_args[0] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
8884 codeview_option_args[1] = LLVMMDString ("CodeView", 8);
8885 codeview_option_args[2] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
8887 LLVMAddNamedMetadataOperand (module->lmodule, "llvm.module.flags", LLVMMDNode (codeview_option_args, G_N_ELEMENTS (codeview_option_args)));
8890 if (!static_link) {
8891 const char linker_options[] = "Linker Options";
8892 const char *default_dynamic_lib_names[] = { "/DEFAULTLIB:msvcrt",
8893 "/DEFAULTLIB:ucrt.lib",
8894 "/DEFAULTLIB:vcruntime.lib" };
8896 LLVMValueRef linker_option_args[3];
8897 LLVMValueRef default_lib_args[G_N_ELEMENTS (default_dynamic_lib_names)];
8898 LLVMValueRef default_lib_nodes[G_N_ELEMENTS(default_dynamic_lib_names)];
8900 const char *default_lib_name = NULL;
8901 for (int i = 0; i < G_N_ELEMENTS (default_dynamic_lib_names); ++i) {
8902 const char *default_lib_name = default_dynamic_lib_names[i];
8903 default_lib_args[i] = LLVMMDString (default_lib_name, strlen (default_lib_name));
8904 default_lib_nodes[i] = LLVMMDNode (default_lib_args + i, 1);
8907 #if LLVM_API_VERSION < 600
8908 linker_option_args[0] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
8909 linker_option_args[1] = LLVMMDString (linker_options, G_N_ELEMENTS (linker_options) - 1);
8910 linker_option_args[2] = LLVMMDNode (default_lib_nodes, G_N_ELEMENTS (default_lib_nodes));
8912 LLVMAddNamedMetadataOperand (module->lmodule, "llvm.module.flags", LLVMMDNode (linker_option_args, G_N_ELEMENTS (linker_option_args)));
8913 #else
8914 LLVMAddNamedMetadataOperand (module->lmodule, "llvm.linker.options", LLVMMDNode (default_lib_args, G_N_ELEMENTS (default_lib_args)));
8915 #endif
8917 #endif
8919 /* Add GOT */
8921 * We couldn't compute the type of the LLVM global representing the got because
8922 * its size is only known after all the methods have been emitted. So create
8923 * a dummy variable, and replace all uses it with the real got variable when
8924 * its size is known in mono_llvm_emit_aot_module ().
8927 LLVMTypeRef got_type = LLVMArrayType (module->ptr_type, 0);
8929 module->got_var = LLVMAddGlobal (module->lmodule, got_type, "mono_dummy_got");
8930 module->got_idx_to_type = g_hash_table_new (NULL, NULL);
8931 LLVMSetInitializer (module->got_var, LLVMConstNull (got_type));
8934 /* Add initialization array */
8935 if (!llvm_disable_self_init) {
8936 LLVMTypeRef inited_type = LLVMArrayType (LLVMInt8Type (), 0);
8938 module->inited_var = LLVMAddGlobal (aot_module.lmodule, inited_type, "mono_inited_tmp");
8939 LLVMSetInitializer (module->inited_var, LLVMConstNull (inited_type));
8943 emit_gc_safepoint_poll (module);
8945 emit_llvm_code_start (module);
8947 // Needs idx_to_lmethod
8948 if (!llvm_disable_self_init)
8949 emit_init_icall_wrappers (module);
8951 /* Add a dummy personality function */
8952 if (!use_debug_personality) {
8953 LLVMValueRef personality = LLVMAddFunction (module->lmodule, default_personality_name, LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE));
8954 LLVMSetLinkage (personality, LLVMExternalLinkage);
8956 //EMCC chockes if the personality function is referenced in the 'used' array
8957 #ifndef TARGET_WASM
8958 mark_as_used (module, personality);
8959 #endif
8962 /* Add a reference to the c++ exception we throw/catch */
8964 LLVMTypeRef exc = LLVMPointerType (LLVMInt8Type (), 0);
8965 module->sentinel_exception = LLVMAddGlobal (module->lmodule, exc, "_ZTIPi");
8966 LLVMSetLinkage (module->sentinel_exception, LLVMExternalLinkage);
8967 mono_llvm_set_is_constant (module->sentinel_exception);
8970 module->llvm_types = g_hash_table_new (NULL, NULL);
8971 module->plt_entries = g_hash_table_new (g_str_hash, g_str_equal);
8972 module->plt_entries_ji = g_hash_table_new (NULL, NULL);
8973 module->direct_callables = g_hash_table_new (g_str_hash, g_str_equal);
8974 module->method_to_lmethod = g_hash_table_new (NULL, NULL);
8975 module->idx_to_lmethod = g_hash_table_new (NULL, NULL);
8976 module->idx_to_unbox_tramp = g_hash_table_new (NULL, NULL);
8977 module->callsite_list = g_ptr_array_new ();
8980 void
8981 mono_llvm_fixup_aot_module (void)
8983 MonoLLVMModule *module = &aot_module;
8984 MonoMethod *method;
8986 if (module->llvm_disable_self_init)
8987 return;
8990 * Replace GOT entries for directly callable methods with the methods themselves.
8991 * It would be easier to implement this by predefining all methods before compiling
8992 * their bodies, but that couldn't handle the case when a method fails to compile
8993 * with llvm.
8996 GHashTable *patches_to_null = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
8997 for (int sindex = 0; sindex < module->callsite_list->len; ++sindex) {
8998 CallSite *site = (CallSite*)g_ptr_array_index (module->callsite_list, sindex);
8999 method = site->method;
9000 LLVMValueRef lmethod = (LLVMValueRef)g_hash_table_lookup (module->method_to_lmethod, method);
9002 LLVMValueRef placeholder = (LLVMValueRef)site->load;
9003 LLVMValueRef indexes [2], got_entry_addr, load;
9004 char *name;
9006 if (lmethod && !(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
9007 mono_llvm_replace_uses_of (placeholder, lmethod);
9008 g_hash_table_insert (patches_to_null, site->ji, site->ji);
9009 } else {
9010 int got_offset = compute_aot_got_offset (module, site->ji, site->type);
9012 module->max_got_offset = MAX (module->max_got_offset, got_offset);
9014 LLVMBuilderRef builder = LLVMCreateBuilder ();
9015 LLVMPositionBuilderBefore (builder, placeholder);
9016 indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9017 indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
9018 got_entry_addr = LLVMBuildGEP (builder, module->got_var, indexes, 2, "");
9020 name = get_aotconst_name (site->ji->type, site->ji->data.target, got_offset);
9021 load = LLVMBuildLoad (builder, got_entry_addr, "");
9022 load = LLVMBuildBitCast (builder, load, site->type, name ? name : "");
9023 LLVMReplaceAllUsesWith (placeholder, load);
9025 g_free (site);
9028 for (int i = 0; i < module->cfgs->len; ++i) {
9030 * Nullify the patches pointing to direct calls. This is needed to
9031 * avoid allocating extra got slots, which is a perf problem and it
9032 * makes module->max_got_offset invalid.
9033 * It would be better to just store the patch_info in CallSite, but
9034 * cfg->patch_info is copied in aot-compiler.c.
9036 MonoCompile *cfg = (MonoCompile *)g_ptr_array_index (module->cfgs, i);
9037 for (MonoJumpInfo *patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
9038 if (patch_info->type == MONO_PATCH_INFO_METHOD) {
9039 if (g_hash_table_lookup (patches_to_null, patch_info)) {
9040 patch_info->type = MONO_PATCH_INFO_NONE;
9041 /* Nullify the call to init_method () if possible */
9042 g_assert (cfg->got_access_count);
9043 cfg->got_access_count --;
9044 #if LLVM_API_VERSION >= 600
9045 if (cfg->got_access_count == 0) {
9046 LLVMValueRef br = (LLVMValueRef)cfg->llvmonly_init_cond;
9047 if (br)
9048 LLVMSetSuccessor (br, 0, LLVMGetSuccessor (br, 1));
9050 #endif
9056 g_hash_table_destroy (patches_to_null);
9059 static LLVMValueRef
9060 llvm_array_from_uints (LLVMTypeRef el_type, guint32 *values, int nvalues)
9062 int i;
9063 LLVMValueRef res, *vals;
9065 vals = g_new0 (LLVMValueRef, nvalues);
9066 for (i = 0; i < nvalues; ++i)
9067 vals [i] = LLVMConstInt (LLVMInt32Type (), values [i], FALSE);
9068 res = LLVMConstArray (LLVMInt32Type (), vals, nvalues);
9069 g_free (vals);
9070 return res;
9073 static LLVMValueRef
9074 llvm_array_from_bytes (guint8 *values, int nvalues)
9076 int i;
9077 LLVMValueRef res, *vals;
9079 vals = g_new0 (LLVMValueRef, nvalues);
9080 for (i = 0; i < nvalues; ++i)
9081 vals [i] = LLVMConstInt (LLVMInt8Type (), values [i], FALSE);
9082 res = LLVMConstArray (LLVMInt8Type (), vals, nvalues);
9083 g_free (vals);
9084 return res;
9087 * mono_llvm_emit_aot_file_info:
9089 * Emit the MonoAotFileInfo structure.
9090 * Same as emit_aot_file_info () in aot-compiler.c.
9092 void
9093 mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code)
9095 MonoLLVMModule *module = &aot_module;
9097 /* Save these for later */
9098 memcpy (&module->aot_info, info, sizeof (MonoAotFileInfo));
9099 module->has_jitted_code = has_jitted_code;
9103 * mono_llvm_emit_aot_data:
9105 * Emit the binary data DATA pointed to by symbol SYMBOL.
9107 void
9108 mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
9110 MonoLLVMModule *module = &aot_module;
9111 LLVMTypeRef type;
9112 LLVMValueRef d;
9114 type = LLVMArrayType (LLVMInt8Type (), data_len);
9115 d = LLVMAddGlobal (module->lmodule, type, symbol);
9116 LLVMSetVisibility (d, LLVMHiddenVisibility);
9117 LLVMSetLinkage (d, LLVMInternalLinkage);
9118 LLVMSetInitializer (d, mono_llvm_create_constant_data_array (data, data_len));
9119 LLVMSetAlignment (d, 8);
9120 mono_llvm_set_is_constant (d);
9123 /* Add a reference to a global defined in JITted code */
9124 static LLVMValueRef
9125 AddJitGlobal (MonoLLVMModule *module, LLVMTypeRef type, const char *name)
9127 char *s;
9128 LLVMValueRef v;
9130 s = g_strdup_printf ("%s%s", module->global_prefix, name);
9131 v = LLVMAddGlobal (module->lmodule, LLVMInt8Type (), s);
9132 LLVMSetVisibility (v, LLVMHiddenVisibility);
9133 g_free (s);
9134 return v;
9137 static void
9138 emit_aot_file_info (MonoLLVMModule *module)
9140 LLVMTypeRef file_info_type;
9141 LLVMTypeRef *eltypes, eltype;
9142 LLVMValueRef info_var;
9143 LLVMValueRef *fields;
9144 int i, nfields, tindex;
9145 MonoAotFileInfo *info;
9146 LLVMModuleRef lmodule = module->lmodule;
9148 info = &module->aot_info;
9150 /* Create an LLVM type to represent MonoAotFileInfo */
9151 nfields = 2 + MONO_AOT_FILE_INFO_NUM_SYMBOLS + 21 + 5;
9152 eltypes = g_new (LLVMTypeRef, nfields);
9153 tindex = 0;
9154 eltypes [tindex ++] = LLVMInt32Type ();
9155 eltypes [tindex ++] = LLVMInt32Type ();
9156 /* Symbols */
9157 for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i)
9158 eltypes [tindex ++] = LLVMPointerType (LLVMInt8Type (), 0);
9159 /* Scalars */
9160 for (i = 0; i < 20; ++i)
9161 eltypes [tindex ++] = LLVMInt32Type ();
9162 /* Arrays */
9163 eltypes [tindex ++] = LLVMArrayType (LLVMInt32Type (), MONO_AOT_TABLE_NUM);
9164 for (i = 0; i < 4; ++i)
9165 eltypes [tindex ++] = LLVMArrayType (LLVMInt32Type (), MONO_AOT_TRAMP_NUM);
9166 eltypes [tindex ++] = LLVMArrayType (LLVMInt8Type (), 16);
9167 g_assert (tindex == nfields);
9168 file_info_type = LLVMStructCreateNamed (module->context, "MonoAotFileInfo");
9169 LLVMStructSetBody (file_info_type, eltypes, nfields, FALSE);
9171 info_var = LLVMAddGlobal (lmodule, file_info_type, "mono_aot_file_info");
9172 if (module->static_link) {
9173 LLVMSetVisibility (info_var, LLVMHiddenVisibility);
9174 LLVMSetLinkage (info_var, LLVMInternalLinkage);
9177 #ifdef TARGET_WIN32
9178 if (!module->static_link) {
9179 LLVMSetDLLStorageClass (info_var, LLVMDLLExportStorageClass);
9181 #endif
9183 fields = g_new (LLVMValueRef, nfields);
9184 tindex = 0;
9185 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->version, FALSE);
9186 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->dummy, FALSE);
9188 /* Symbols */
9190 * We use LLVMGetNamedGlobal () for symbol which are defined in LLVM code, and LLVMAddGlobal ()
9191 * for symbols defined in the .s file emitted by the aot compiler.
9193 eltype = eltypes [tindex];
9194 if (module->llvm_only)
9195 fields [tindex ++] = LLVMConstNull (eltype);
9196 else
9197 fields [tindex ++] = AddJitGlobal (module, eltype, "jit_got");
9198 fields [tindex ++] = module->got_var;
9199 /* llc defines this directly */
9200 if (!module->llvm_only) {
9201 fields [tindex ++] = LLVMAddGlobal (lmodule, eltype, module->eh_frame_symbol);
9202 fields [tindex ++] = module->get_method;
9203 fields [tindex ++] = LLVMConstNull (eltype);
9204 } else {
9205 fields [tindex ++] = LLVMConstNull (eltype);
9206 fields [tindex ++] = module->get_method;
9207 fields [tindex ++] = module->get_unbox_tramp ? module->get_unbox_tramp : LLVMConstNull (eltype);
9209 if (module->has_jitted_code) {
9210 fields [tindex ++] = AddJitGlobal (module, eltype, "jit_code_start");
9211 fields [tindex ++] = AddJitGlobal (module, eltype, "jit_code_end");
9212 } else {
9213 fields [tindex ++] = LLVMConstNull (eltype);
9214 fields [tindex ++] = LLVMConstNull (eltype);
9216 if (!module->llvm_only)
9217 fields [tindex ++] = AddJitGlobal (module, eltype, "method_addresses");
9218 else
9219 fields [tindex ++] = LLVMConstNull (eltype);
9220 if (module->llvm_only && module->unbox_tramp_indexes) {
9221 fields [tindex ++] = module->unbox_tramp_indexes;
9222 fields [tindex ++] = module->unbox_trampolines;
9223 } else {
9224 fields [tindex ++] = LLVMConstNull (eltype);
9225 fields [tindex ++] = LLVMConstNull (eltype);
9227 if (info->flags & MONO_AOT_FILE_FLAG_SEPARATE_DATA) {
9228 for (i = 0; i < MONO_AOT_TABLE_NUM; ++i)
9229 fields [tindex ++] = LLVMConstNull (eltype);
9230 } else {
9231 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "blob");
9232 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "class_name_table");
9233 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "class_info_offsets");
9234 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "method_info_offsets");
9235 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "ex_info_offsets");
9236 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "extra_method_info_offsets");
9237 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "extra_method_table");
9238 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "got_info_offsets");
9239 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "llvm_got_info_offsets");
9240 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "image_table");
9241 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "weak_field_indexes");
9243 /* Not needed (mem_end) */
9244 fields [tindex ++] = LLVMConstNull (eltype);
9245 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "assembly_guid");
9246 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "runtime_version");
9247 if (info->trampoline_size [0]) {
9248 fields [tindex ++] = AddJitGlobal (module, eltype, "specific_trampolines");
9249 fields [tindex ++] = AddJitGlobal (module, eltype, "static_rgctx_trampolines");
9250 fields [tindex ++] = AddJitGlobal (module, eltype, "imt_trampolines");
9251 fields [tindex ++] = AddJitGlobal (module, eltype, "gsharedvt_arg_trampolines");
9252 fields [tindex ++] = AddJitGlobal (module, eltype, "ftnptr_arg_trampolines");
9253 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_arbitrary_trampolines");
9254 } else {
9255 fields [tindex ++] = LLVMConstNull (eltype);
9256 fields [tindex ++] = LLVMConstNull (eltype);
9257 fields [tindex ++] = LLVMConstNull (eltype);
9258 fields [tindex ++] = LLVMConstNull (eltype);
9259 fields [tindex ++] = LLVMConstNull (eltype);
9260 fields [tindex ++] = LLVMConstNull (eltype);
9262 if (module->static_link && !module->llvm_only)
9263 fields [tindex ++] = AddJitGlobal (module, eltype, "globals");
9264 else
9265 fields [tindex ++] = LLVMConstNull (eltype);
9266 fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "assembly_name");
9267 if (!module->llvm_only) {
9268 fields [tindex ++] = AddJitGlobal (module, eltype, "plt");
9269 fields [tindex ++] = AddJitGlobal (module, eltype, "plt_end");
9270 fields [tindex ++] = AddJitGlobal (module, eltype, "unwind_info");
9271 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_trampolines");
9272 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_trampolines_end");
9273 fields [tindex ++] = AddJitGlobal (module, eltype, "unbox_trampoline_addresses");
9274 } else {
9275 fields [tindex ++] = LLVMConstNull (eltype);
9276 fields [tindex ++] = LLVMConstNull (eltype);
9277 fields [tindex ++] = LLVMConstNull (eltype);
9278 fields [tindex ++] = LLVMConstNull (eltype);
9279 fields [tindex ++] = LLVMConstNull (eltype);
9280 fields [tindex ++] = LLVMConstNull (eltype);
9283 for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i) {
9284 g_assert (fields [2 + i]);
9285 fields [2 + i] = LLVMConstBitCast (fields [2 + i], eltype);
9288 /* Scalars */
9289 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->plt_got_offset_base, FALSE);
9290 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->got_size, FALSE);
9291 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->plt_size, FALSE);
9292 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nmethods, FALSE);
9293 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nextra_methods, FALSE);
9294 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->flags, FALSE);
9295 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->opts, FALSE);
9296 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->simd_opts, FALSE);
9297 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->gc_name_index, FALSE);
9298 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->num_rgctx_fetch_trampolines, FALSE);
9299 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->double_align, FALSE);
9300 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->long_align, FALSE);
9301 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->generic_tramp_num, FALSE);
9302 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->card_table_shift_bits, FALSE);
9303 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->card_table_mask, FALSE);
9304 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->tramp_page_size, FALSE);
9305 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nshared_got_entries, FALSE);
9306 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->datafile_size, FALSE);
9307 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), module->unbox_tramp_num, FALSE);
9308 fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), module->unbox_tramp_elemsize, FALSE);
9309 /* Arrays */
9310 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->table_offsets, MONO_AOT_TABLE_NUM);
9311 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->num_trampolines, MONO_AOT_TRAMP_NUM);
9312 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->trampoline_got_offset_base, MONO_AOT_TRAMP_NUM);
9313 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->trampoline_size, MONO_AOT_TRAMP_NUM);
9314 fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->tramp_page_code_offsets, MONO_AOT_TRAMP_NUM);
9316 fields [tindex ++] = llvm_array_from_bytes (info->aotid, 16);
9317 g_assert (tindex == nfields);
9319 LLVMSetInitializer (info_var, LLVMConstNamedStruct (file_info_type, fields, nfields));
9321 if (module->static_link) {
9322 char *s, *p;
9323 LLVMValueRef var;
9325 s = g_strdup_printf ("mono_aot_module_%s_info", module->assembly->aname.name);
9326 /* Get rid of characters which cannot occur in symbols */
9327 p = s;
9328 for (p = s; *p; ++p) {
9329 if (!(isalnum (*p) || *p == '_'))
9330 *p = '_';
9332 var = LLVMAddGlobal (module->lmodule, LLVMPointerType (LLVMInt8Type (), 0), s);
9333 g_free (s);
9334 LLVMSetInitializer (var, LLVMConstBitCast (LLVMGetNamedGlobal (module->lmodule, "mono_aot_file_info"), LLVMPointerType (LLVMInt8Type (), 0)));
9335 LLVMSetLinkage (var, LLVMExternalLinkage);
9340 * Emit the aot module into the LLVM bitcode file FILENAME.
9342 void
9343 mono_llvm_emit_aot_module (const char *filename, const char *cu_name)
9345 LLVMTypeRef got_type, inited_type;
9346 LLVMValueRef real_got, real_inited;
9347 MonoLLVMModule *module = &aot_module;
9349 emit_llvm_code_end (module);
9352 * Create the real got variable and replace all uses of the dummy variable with
9353 * the real one.
9355 int size = module->max_got_offset + 1;
9356 LLVMTypeRef *members = g_malloc0 (sizeof (LLVMValueRef) * size);
9357 for (int i = 0; i < size; i++) {
9358 LLVMTypeRef lookup_type = NULL;
9360 lookup_type = g_hash_table_lookup (module->got_idx_to_type, GINT_TO_POINTER (i));
9362 if (!lookup_type)
9363 lookup_type = module->ptr_type;
9365 members [i] = LLVMPointerType (lookup_type, 0);
9368 got_type = LLVMStructCreateNamed (module->context, g_strdup_printf ("MONO_GOT_%s", cu_name));
9369 LLVMStructSetBody (got_type, members, size, FALSE);
9370 real_got = LLVMAddGlobal (module->lmodule, got_type, module->got_symbol);
9372 LLVMSetInitializer (real_got, LLVMConstNull (got_type));
9373 if (module->external_symbols) {
9374 LLVMSetLinkage (real_got, LLVMExternalLinkage);
9375 LLVMSetVisibility (real_got, LLVMHiddenVisibility);
9376 } else {
9377 LLVMSetLinkage (real_got, LLVMInternalLinkage);
9379 mono_llvm_replace_uses_of (module->got_var, real_got);
9381 mark_as_used (&aot_module, real_got);
9383 /* Delete the dummy got so it doesn't become a global */
9384 LLVMDeleteGlobal (module->got_var);
9385 module->got_var = real_got;
9388 * Same for the init_var
9390 if (!module->llvm_disable_self_init) {
9391 inited_type = LLVMArrayType (LLVMInt8Type (), module->max_inited_idx + 1);
9392 real_inited = LLVMAddGlobal (module->lmodule, inited_type, "mono_inited");
9393 LLVMSetInitializer (real_inited, LLVMConstNull (inited_type));
9394 LLVMSetLinkage (real_inited, LLVMInternalLinkage);
9395 mono_llvm_replace_uses_of (module->inited_var, real_inited);
9396 LLVMDeleteGlobal (module->inited_var);
9398 emit_get_method (&aot_module);
9399 emit_get_unbox_tramp (&aot_module);
9402 emit_llvm_used (&aot_module);
9403 emit_dbg_info (&aot_module, filename, cu_name);
9404 emit_aot_file_info (&aot_module);
9406 /* Replace PLT entries for directly callable methods with the methods themselves */
9408 GHashTableIter iter;
9409 MonoJumpInfo *ji;
9410 LLVMValueRef callee;
9412 g_hash_table_iter_init (&iter, module->plt_entries_ji);
9413 while (g_hash_table_iter_next (&iter, (void**)&ji, (void**)&callee)) {
9414 if (mono_aot_is_direct_callable (ji)) {
9415 LLVMValueRef lmethod;
9417 lmethod = (LLVMValueRef)g_hash_table_lookup (module->method_to_lmethod, ji->data.method);
9418 /* The types might not match because the caller might pass an rgctx */
9419 if (lmethod && LLVMTypeOf (callee) == LLVMTypeOf (lmethod)) {
9420 mono_llvm_replace_uses_of (callee, lmethod);
9421 mono_aot_mark_unused_llvm_plt_entry (ji);
9427 /* Note: You can still dump an invalid bitcode file by running `llvm-dis`
9428 * in a debugger, set a breakpoint on `LLVMVerifyModule` and fake its
9429 * result to 0 (indicating success). */
9430 LLVMWriteBitcodeToFile (module->lmodule, filename);
9432 #if 1
9434 char *verifier_err;
9436 if (LLVMVerifyModule (module->lmodule, LLVMReturnStatusAction, &verifier_err)) {
9437 printf ("%s\n", verifier_err);
9438 g_assert_not_reached ();
9441 #endif
9445 static LLVMValueRef
9446 md_string (const char *s)
9448 return LLVMMDString (s, strlen (s));
9451 /* Debugging support */
9453 static void
9454 emit_dbg_info (MonoLLVMModule *module, const char *filename, const char *cu_name)
9456 LLVMModuleRef lmodule = module->lmodule;
9457 LLVMValueRef args [16], ver;
9460 * This can only be enabled when LLVM code is emitted into a separate object
9461 * file, since the AOT compiler also emits dwarf info,
9462 * and the abbrev indexes will not be correct since llvm has added its own
9463 * abbrevs.
9465 if (!module->emit_dwarf)
9466 return;
9468 #if LLVM_API_VERSION > 100
9469 mono_llvm_di_builder_finalize (module->di_builder);
9470 #else
9471 LLVMValueRef cu_args [16], cu;
9472 int n_cuargs;
9473 char *build_info, *s, *dir;
9476 * Emit dwarf info in the form of LLVM metadata. There is some
9477 * out-of-date documentation at:
9478 * http://llvm.org/docs/SourceLevelDebugging.html
9479 * but most of this was gathered from the llvm and
9480 * clang sources.
9483 n_cuargs = 0;
9484 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), DW_TAG_compile_unit, FALSE);
9485 /* CU name/compilation dir */
9486 dir = g_path_get_dirname (filename);
9487 args [0] = LLVMMDString (cu_name, strlen (cu_name));
9488 args [1] = LLVMMDString (dir, strlen (dir));
9489 cu_args [n_cuargs ++] = LLVMMDNode (args, 2);
9490 g_free (dir);
9491 /* Language */
9492 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), DW_LANG_C99, FALSE);
9493 /* Producer */
9494 build_info = mono_get_runtime_build_info ();
9495 s = g_strdup_printf ("Mono AOT Compiler %s (LLVM)", build_info);
9496 cu_args [n_cuargs ++] = LLVMMDString (s, strlen (s));
9497 g_free (build_info);
9498 /* Optimized */
9499 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9500 /* Flags */
9501 cu_args [n_cuargs ++] = LLVMMDString ("", strlen (""));
9502 /* Runtime version */
9503 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9504 /* Enums */
9505 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
9506 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
9507 /* Subprograms */
9508 if (module->subprogram_mds) {
9509 LLVMValueRef *mds;
9510 int i;
9512 mds = g_new0 (LLVMValueRef, module->subprogram_mds->len);
9513 for (i = 0; i < module->subprogram_mds->len; ++i)
9514 mds [i] = (LLVMValueRef)g_ptr_array_index (module->subprogram_mds, i);
9515 cu_args [n_cuargs ++] = LLVMMDNode (mds, module->subprogram_mds->len);
9516 } else {
9517 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
9519 /* GVs */
9520 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
9521 /* Imported modules */
9522 cu_args [n_cuargs ++] = LLVMMDNode (args, 0);
9523 /* SplitName */
9524 cu_args [n_cuargs ++] = LLVMMDString ("", strlen (""));
9525 /* DebugEmissionKind = FullDebug */
9526 cu_args [n_cuargs ++] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9527 cu = LLVMMDNode (cu_args, n_cuargs);
9528 LLVMAddNamedMetadataOperand (lmodule, "llvm.dbg.cu", cu);
9529 #endif
9531 #if LLVM_API_VERSION > 100
9532 args [0] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
9533 args [1] = LLVMMDString ("Dwarf Version", strlen ("Dwarf Version"));
9534 args [2] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
9535 ver = LLVMMDNode (args, 3);
9536 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
9538 args [0] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
9539 args [1] = LLVMMDString ("Debug Info Version", strlen ("Debug Info Version"));
9540 args [2] = LLVMConstInt (LLVMInt64Type (), 3, FALSE);
9541 ver = LLVMMDNode (args, 3);
9542 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
9543 #else
9544 args [0] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9545 args [1] = LLVMMDString ("Dwarf Version", strlen ("Dwarf Version"));
9546 args [2] = LLVMConstInt (LLVMInt32Type (), 2, FALSE);
9547 ver = LLVMMDNode (args, 3);
9548 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
9550 args [0] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9551 args [1] = LLVMMDString ("Debug Info Version", strlen ("Debug Info Version"));
9552 args [2] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9553 ver = LLVMMDNode (args, 3);
9554 LLVMAddNamedMetadataOperand (lmodule, "llvm.module.flags", ver);
9555 #endif
9558 static LLVMValueRef
9559 emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, const char *name)
9561 MonoLLVMModule *module = ctx->module;
9562 MonoDebugMethodInfo *minfo = ctx->minfo;
9563 char *source_file, *dir, *filename;
9564 LLVMValueRef md, args [16], ctx_args [16], md_args [64], type_args [16], ctx_md, type_md;
9565 MonoSymSeqPoint *sym_seq_points;
9566 int n_seq_points;
9568 if (!minfo)
9569 return NULL;
9571 mono_debug_get_seq_points (minfo, &source_file, NULL, NULL, &sym_seq_points, &n_seq_points);
9572 if (!source_file)
9573 source_file = g_strdup ("<unknown>");
9574 dir = g_path_get_dirname (source_file);
9575 filename = g_path_get_basename (source_file);
9577 #if LLVM_API_VERSION > 100
9578 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);
9579 #endif
9581 ctx_args [0] = LLVMConstInt (LLVMInt32Type (), 0x29, FALSE);
9582 args [0] = md_string (filename);
9583 args [1] = md_string (dir);
9584 ctx_args [1] = LLVMMDNode (args, 2);
9585 ctx_md = LLVMMDNode (ctx_args, 2);
9587 type_args [0] = LLVMConstInt (LLVMInt32Type (), DW_TAG_subroutine_type, FALSE);
9588 type_args [1] = NULL;
9589 type_args [2] = NULL;
9590 type_args [3] = LLVMMDString ("", 0);
9591 type_args [4] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9592 type_args [5] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
9593 type_args [6] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
9594 type_args [7] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
9595 type_args [8] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9596 type_args [9] = NULL;
9597 type_args [10] = NULL;
9598 type_args [11] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9599 type_args [12] = NULL;
9600 type_args [13] = NULL;
9601 type_args [14] = NULL;
9602 type_md = LLVMMDNode (type_args, 14);
9604 /* http://llvm.org/docs/SourceLevelDebugging.html#subprogram-descriptors */
9605 md_args [0] = LLVMConstInt (LLVMInt32Type (), DW_TAG_subprogram, FALSE);
9606 /* Source directory + file pair */
9607 args [0] = md_string (filename);
9608 args [1] = md_string (dir);
9609 md_args [1] = LLVMMDNode (args ,2);
9610 md_args [2] = ctx_md;
9611 md_args [3] = md_string (cfg->method->name);
9612 md_args [4] = md_string (name);
9613 md_args [5] = md_string (name);
9614 /* Line number */
9615 if (n_seq_points)
9616 md_args [6] = LLVMConstInt (LLVMInt32Type (), sym_seq_points [0].line, FALSE);
9617 else
9618 md_args [6] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9619 /* Type */
9620 md_args [7] = type_md;
9621 /* static */
9622 md_args [8] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
9623 /* not extern */
9624 md_args [9] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
9625 /* Virtuality */
9626 md_args [10] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
9627 /* Index into a virtual function */
9628 md_args [11] = NULL;
9629 md_args [12] = NULL;
9630 /* Flags */
9631 md_args [13] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
9632 /* isOptimized */
9633 md_args [14] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
9634 /* Pointer to LLVM function */
9635 md_args [15] = method;
9636 /* Function template parameter */
9637 md_args [16] = NULL;
9638 /* Function declaration descriptor */
9639 md_args [17] = NULL;
9640 /* List of function variables */
9641 md_args [18] = LLVMMDNode (args, 0);
9642 /* Line number */
9643 md_args [19] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
9644 md = LLVMMDNode (md_args, 20);
9646 if (!module->subprogram_mds)
9647 module->subprogram_mds = g_ptr_array_new ();
9648 g_ptr_array_add (module->subprogram_mds, md);
9650 g_free (dir);
9651 g_free (filename);
9652 g_free (source_file);
9653 g_free (sym_seq_points);
9655 return md;
9658 static void
9659 emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil_code)
9661 MonoCompile *cfg = ctx->cfg;
9663 if (ctx->minfo && cil_code && cil_code >= cfg->header->code && cil_code < cfg->header->code + cfg->header->code_size) {
9664 MonoDebugSourceLocation *loc;
9665 LLVMValueRef loc_md;
9667 loc = mono_debug_method_lookup_location (ctx->minfo, cil_code - cfg->header->code);
9669 if (loc) {
9670 #if LLVM_API_VERSION > 100
9671 loc_md = (LLVMValueRef)mono_llvm_di_create_location (ctx->module->di_builder, ctx->dbg_md, loc->row, loc->column);
9672 mono_llvm_di_set_location (builder, loc_md);
9673 #else
9674 LLVMValueRef md_args [16];
9675 int nmd_args;
9677 nmd_args = 0;
9678 md_args [nmd_args ++] = LLVMConstInt (LLVMInt32Type (), loc->row, FALSE);
9679 md_args [nmd_args ++] = LLVMConstInt (LLVMInt32Type (), loc->column, FALSE);
9680 md_args [nmd_args ++] = ctx->dbg_md;
9681 md_args [nmd_args ++] = NULL;
9682 loc_md = LLVMMDNode (md_args, nmd_args);
9683 LLVMSetCurrentDebugLocation (builder, loc_md);
9684 #endif
9685 mono_debug_free_source_location (loc);
9690 static void
9691 emit_default_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder)
9693 #if LLVM_API_VERSION > 100
9694 if (ctx->minfo) {
9695 LLVMValueRef loc_md;
9696 loc_md = (LLVMValueRef)mono_llvm_di_create_location (ctx->module->di_builder, ctx->dbg_md, 0, 0);
9697 mono_llvm_di_set_location (builder, loc_md);
9699 #else
9700 /* Older llvm versions don't require this */
9701 #endif
9704 void
9705 default_mono_llvm_unhandled_exception (void)
9707 MonoJitTlsData *jit_tls = mono_get_jit_tls ();
9708 MonoObject *target = mono_gchandle_get_target_internal (jit_tls->thrown_exc);
9710 mono_unhandled_exception_internal (target);
9711 mono_invoke_unhandled_exception_hook (target);
9712 g_assert_not_reached ();
9716 DESIGN:
9717 - Emit LLVM IR from the mono IR using the LLVM C API.
9718 - The original arch specific code remains, so we can fall back to it if we run
9719 into something we can't handle.
9723 A partial list of issues:
9724 - Handling of opcodes which can throw exceptions.
9726 In the mono JIT, these are implemented using code like this:
9727 method:
9728 <compare>
9729 throw_pos:
9730 b<cond> ex_label
9731 <rest of code>
9732 ex_label:
9733 push throw_pos - method
9734 call <exception trampoline>
9736 The problematic part is push throw_pos - method, which cannot be represented
9737 in the LLVM IR, since it does not support label values.
9738 -> this can be implemented in AOT mode using inline asm + labels, but cannot
9739 be implemented in JIT mode ?
9740 -> a possible but slower implementation would use the normal exception
9741 throwing code but it would need to control the placement of the throw code
9742 (it needs to be exactly after the compare+branch).
9743 -> perhaps add a PC offset intrinsics ?
9745 - efficient implementation of .ovf opcodes.
9747 These are currently implemented as:
9748 <ins which sets the condition codes>
9749 b<cond> ex_label
9751 Some overflow opcodes are now supported by LLVM SVN.
9753 - exception handling, unwinding.
9754 - SSA is disabled for methods with exception handlers
9755 - How to obtain unwind info for LLVM compiled methods ?
9756 -> this is now solved by converting the unwind info generated by LLVM
9757 into our format.
9758 - LLVM uses the c++ exception handling framework, while we use our home grown
9759 code, and couldn't use the c++ one:
9760 - its not supported under VC++, other exotic platforms.
9761 - it might be impossible to support filter clauses with it.
9763 - trampolines.
9765 The trampolines need a predictable call sequence, since they need to disasm
9766 the calling code to obtain register numbers / offsets.
9768 LLVM currently generates this code in non-JIT mode:
9769 mov -0x98(%rax),%eax
9770 callq *%rax
9771 Here, the vtable pointer is lost.
9772 -> solution: use one vtable trampoline per class.
9774 - passing/receiving the IMT pointer/RGCTX.
9775 -> solution: pass them as normal arguments ?
9777 - argument passing.
9779 LLVM does not allow the specification of argument registers etc. This means
9780 that all calls are made according to the platform ABI.
9782 - passing/receiving vtypes.
9784 Vtypes passed/received in registers are handled by the front end by using
9785 a signature with scalar arguments, and loading the parts of the vtype into those
9786 arguments.
9788 Vtypes passed on the stack are handled using the 'byval' attribute.
9790 - ldaddr.
9792 Supported though alloca, we need to emit the load/store code.
9794 - types.
9796 The mono JIT uses pointer sized iregs/double fregs, while LLVM uses precisely
9797 typed registers, so we have to keep track of the precise LLVM type of each vreg.
9798 This is made easier because the IR is already in SSA form.
9799 An additional problem is that our IR is not consistent with types, i.e. i32/i64
9800 types are frequently used incorrectly.
9804 AOT SUPPORT:
9805 Emit LLVM bytecode into a .bc file, compile it using llc into a .s file, then link
9806 it with the file containing the methods emitted by the JIT and the AOT data
9807 structures.
9810 /* FIXME: Normalize some aspects of the mono IR to allow easier translation, like:
9811 * - each bblock should end with a branch
9812 * - setting the return value, making cfg->ret non-volatile
9813 * - avoid some transformations in the JIT which make it harder for us to generate
9814 * code.
9815 * - use pointer types to help optimizations.
9818 #else /* DISABLE_JIT */
9820 void
9821 mono_llvm_cleanup (void)
9825 void
9826 mono_llvm_free_domain_info (MonoDomain *domain)
9830 void
9831 mono_llvm_init (void)
9835 void
9836 default_mono_llvm_unhandled_exception (void)
9840 #endif /* DISABLE_JIT */
9842 #if !defined(DISABLE_JIT) && !defined(MONO_CROSS_COMPILE)
9844 /* LLVM JIT support */
9846 static unsigned char*
9847 alloc_cb (LLVMValueRef function, int size)
9849 MonoCompile *cfg;
9851 cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
9853 if (cfg) {
9854 // FIXME: dynamic
9855 return (unsigned char*)mono_domain_code_reserve (cfg->domain, size);
9856 } else {
9857 return (unsigned char*)mono_domain_code_reserve (mono_domain_get (), size);
9861 static void
9862 emitted_cb (LLVMValueRef function, void *start, void *end)
9864 MonoCompile *cfg;
9866 cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
9867 g_assert (cfg);
9868 cfg->code_len = (guint8*)end - (guint8*)start;
9871 static void
9872 exception_cb (void *data)
9874 MonoCompile *cfg;
9875 MonoJitExceptionInfo *ei;
9876 guint32 ei_len, i, j, nested_len, nindex;
9877 gpointer *type_info;
9878 int this_reg, this_offset;
9880 cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
9881 g_assert (cfg);
9884 * data points to a DWARF FDE structure, convert it to our unwind format and
9885 * save it.
9886 * An alternative would be to save it directly, and modify our unwinder to work
9887 * with it.
9889 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);
9890 if (cfg->verbose_level > 1)
9891 mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
9893 /* Count nested clauses */
9894 nested_len = 0;
9895 for (i = 0; i < ei_len; ++i) {
9896 gint32 cindex1 = *(gint32*)type_info [i];
9897 MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];
9899 for (j = 0; j < cfg->header->num_clauses; ++j) {
9900 int cindex2 = j;
9901 MonoExceptionClause *clause2 = &cfg->header->clauses [cindex2];
9903 if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
9904 nested_len ++;
9909 cfg->llvm_ex_info = (MonoJitExceptionInfo*)mono_mempool_alloc0 (cfg->mempool, (ei_len + nested_len) * sizeof (MonoJitExceptionInfo));
9910 cfg->llvm_ex_info_len = ei_len + nested_len;
9911 memcpy (cfg->llvm_ex_info, ei, ei_len * sizeof (MonoJitExceptionInfo));
9912 /* Fill the rest of the information from the type info */
9913 for (i = 0; i < ei_len; ++i) {
9914 gint32 clause_index = *(gint32*)type_info [i];
9915 MonoExceptionClause *clause = &cfg->header->clauses [clause_index];
9917 cfg->llvm_ex_info [i].flags = clause->flags;
9918 cfg->llvm_ex_info [i].data.catch_class = clause->data.catch_class;
9919 cfg->llvm_ex_info [i].clause_index = clause_index;
9923 * For nested clauses, the LLVM produced exception info associates the try interval with
9924 * the innermost handler, while mono expects it to be associated with all nesting clauses.
9925 * So add new clauses which use the IL info (catch class etc.) from the nesting clause,
9926 * and everything else from the nested clause.
9928 nindex = ei_len;
9929 for (i = 0; i < ei_len; ++i) {
9930 gint32 cindex1 = *(gint32*)type_info [i];
9931 MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];
9933 for (j = 0; j < cfg->header->num_clauses; ++j) {
9934 int cindex2 = j;
9935 MonoExceptionClause *clause2 = &cfg->header->clauses [cindex2];
9936 MonoJitExceptionInfo *nesting_ei, *nested_ei;
9938 if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
9939 /* clause1 is the nested clause */
9940 nested_ei = &cfg->llvm_ex_info [i];
9941 nesting_ei = &cfg->llvm_ex_info [nindex];
9942 nindex ++;
9944 memcpy (nesting_ei, nested_ei, sizeof (MonoJitExceptionInfo));
9946 nesting_ei->flags = clause2->flags;
9947 nesting_ei->data.catch_class = clause2->data.catch_class;
9948 nesting_ei->clause_index = cindex2;
9952 g_assert (nindex == ei_len + nested_len);
9953 cfg->llvm_this_reg = this_reg;
9954 cfg->llvm_this_offset = this_offset;
9956 /* type_info [i] is cfg mempool allocated, no need to free it */
9958 g_free (ei);
9959 g_free (type_info);
9962 static char*
9963 dlsym_cb (const char *name, void **symbol)
9965 MonoDl *current;
9966 char *err;
9968 err = NULL;
9969 if (!strcmp (name, "__bzero")) {
9970 *symbol = (void*)bzero;
9971 } else {
9972 current = mono_dl_open (NULL, 0, NULL);
9973 g_assert (current);
9975 err = mono_dl_symbol (current, name, symbol);
9977 mono_dl_close (current);
9979 #ifdef MONO_ARCH_HAVE_CREATE_LLVM_NATIVE_THUNK
9980 *symbol = (char*)mono_arch_create_llvm_native_thunk (mono_domain_get (), (guint8*)(*symbol));
9981 #endif
9982 return err;
9986 * decode_llvm_eh_info:
9988 * Decode the EH table emitted by llvm in jit mode, and store
9989 * the result into cfg.
9991 static void
9992 decode_llvm_eh_info (EmitContext *ctx, gpointer eh_frame)
9994 MonoCompile *cfg = ctx->cfg;
9995 guint8 *cie, *fde;
9996 int fde_len;
9997 MonoLLVMFDEInfo info;
9998 MonoJitExceptionInfo *ei;
9999 guint8 *p = (guint8*)eh_frame;
10000 int version, fde_count, fde_offset;
10001 guint32 ei_len, i, nested_len;
10002 gpointer *type_info;
10003 gint32 *table;
10004 guint8 *unw_info;
10007 * Decode the one element EH table emitted by the MonoException class
10008 * in llvm.
10011 /* Similar to decode_llvm_mono_eh_frame () in aot-runtime.c */
10013 version = *p;
10014 g_assert (version == 3);
10015 p ++;
10016 p ++;
10017 p = (guint8 *)ALIGN_PTR_TO (p, 4);
10019 fde_count = *(guint32*)p;
10020 p += 4;
10021 table = (gint32*)p;
10023 g_assert (fde_count <= 2);
10025 /* The first entry is the real method */
10026 g_assert (table [0] == 1);
10027 fde_offset = table [1];
10028 table += fde_count * 2;
10029 /* Extra entry */
10030 cfg->code_len = table [0];
10031 fde_len = table [1] - fde_offset;
10032 table += 2;
10034 fde = (guint8*)eh_frame + fde_offset;
10035 cie = (guint8*)table;
10037 /* Compute lengths */
10038 mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info, NULL, NULL, NULL);
10040 ei = (MonoJitExceptionInfo *)g_malloc0 (info.ex_info_len * sizeof (MonoJitExceptionInfo));
10041 type_info = (gpointer *)g_malloc0 (info.ex_info_len * sizeof (gpointer));
10042 unw_info = (guint8*)g_malloc0 (info.unw_info_len);
10044 mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info, ei, type_info, unw_info);
10046 cfg->encoded_unwind_ops = unw_info;
10047 cfg->encoded_unwind_ops_len = info.unw_info_len;
10048 if (cfg->verbose_level > 1)
10049 mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
10050 if (info.this_reg != -1) {
10051 cfg->llvm_this_reg = info.this_reg;
10052 cfg->llvm_this_offset = info.this_offset;
10055 ei_len = info.ex_info_len;
10057 // Nested clauses are currently disabled
10058 nested_len = 0;
10060 cfg->llvm_ex_info = (MonoJitExceptionInfo*)mono_mempool_alloc0 (cfg->mempool, (ei_len + nested_len) * sizeof (MonoJitExceptionInfo));
10061 cfg->llvm_ex_info_len = ei_len + nested_len;
10062 memcpy (cfg->llvm_ex_info, ei, ei_len * sizeof (MonoJitExceptionInfo));
10063 /* Fill the rest of the information from the type info */
10064 for (i = 0; i < ei_len; ++i) {
10065 gint32 clause_index = *(gint32*)type_info [i];
10066 MonoExceptionClause *clause = &cfg->header->clauses [clause_index];
10068 cfg->llvm_ex_info [i].flags = clause->flags;
10069 cfg->llvm_ex_info [i].data.catch_class = clause->data.catch_class;
10070 cfg->llvm_ex_info [i].clause_index = clause_index;
10074 static void
10075 init_jit_module (MonoDomain *domain)
10077 MonoJitDomainInfo *dinfo;
10078 MonoLLVMModule *module;
10079 char *name;
10081 dinfo = domain_jit_info (domain);
10082 if (dinfo->llvm_module)
10083 return;
10085 mono_loader_lock ();
10087 if (dinfo->llvm_module) {
10088 mono_loader_unlock ();
10089 return;
10092 module = g_new0 (MonoLLVMModule, 1);
10094 name = g_strdup_printf ("mono-%s", domain->friendly_name);
10095 module->lmodule = LLVMModuleCreateWithName (name);
10096 module->context = LLVMGetGlobalContext ();
10097 module->intrins_by_id = g_new0 (LLVMValueRef, INTRINS_NUM);
10099 module->mono_ee = (MonoEERef*)mono_llvm_create_ee (LLVMCreateModuleProviderForExistingModule (module->lmodule), alloc_cb, emitted_cb, exception_cb, dlsym_cb, &module->ee);
10101 add_intrinsics (module->lmodule);
10102 add_types (module);
10104 module->llvm_types = g_hash_table_new (NULL, NULL);
10106 mono_memory_barrier ();
10108 dinfo->llvm_module = module;
10110 mono_loader_unlock ();
10113 static void
10114 llvm_jit_finalize_method (EmitContext *ctx)
10116 MonoCompile *cfg = ctx->cfg;
10118 #if LLVM_API_VERSION > 100
10119 MonoDomain *domain = mono_domain_get ();
10120 MonoJitDomainInfo *domain_info;
10121 int nvars = g_hash_table_size (ctx->jit_callees);
10122 LLVMValueRef *callee_vars = g_new0 (LLVMValueRef, nvars);
10123 gpointer *callee_addrs = g_new0 (gpointer, nvars);
10124 GHashTableIter iter;
10125 LLVMValueRef var;
10126 MonoMethod *callee;
10127 gpointer eh_frame;
10128 int i;
10131 * Compute the addresses of the LLVM globals pointing to the
10132 * methods called by the current method. Pass it to the trampoline
10133 * code so it can update them after their corresponding method was
10134 * compiled.
10136 g_hash_table_iter_init (&iter, ctx->jit_callees);
10137 i = 0;
10138 while (g_hash_table_iter_next (&iter, NULL, (void**)&var))
10139 callee_vars [i ++] = var;
10141 cfg->native_code = (guint8*)mono_llvm_compile_method (ctx->module->mono_ee, ctx->lmethod, nvars, callee_vars, callee_addrs, &eh_frame);
10143 decode_llvm_eh_info (ctx, eh_frame);
10145 mono_domain_lock (domain);
10146 domain_info = domain_jit_info (domain);
10147 if (!domain_info->llvm_jit_callees)
10148 domain_info->llvm_jit_callees = g_hash_table_new (NULL, NULL);
10149 g_hash_table_iter_init (&iter, ctx->jit_callees);
10150 i = 0;
10151 while (g_hash_table_iter_next (&iter, (void**)&callee, (void**)&var)) {
10152 GSList *addrs = (GSList*)g_hash_table_lookup (domain_info->llvm_jit_callees, callee);
10153 addrs = g_slist_prepend (addrs, callee_addrs [i]);
10154 g_hash_table_insert (domain_info->llvm_jit_callees, callee, addrs);
10155 i ++;
10157 mono_domain_unlock (domain);
10158 #else
10159 g_assert_not_reached ();
10160 #endif
10163 #else
10165 static void
10166 init_jit_module (MonoDomain *domain)
10168 g_assert_not_reached ();
10171 static void
10172 llvm_jit_finalize_method (EmitContext *ctx)
10174 g_assert_not_reached ();
10177 #endif