[interp] Fix interp logging (#17636)
[mono-project.git] / mono / mini / mini.h
blob0a7a98b11a76fc1a3d61c5b042297044ada8d0fc
1 /**
2 * \file
3 * Copyright 2002-2003 Ximian Inc
4 * Copyright 2003-2011 Novell Inc
5 * Copyright 2011 Xamarin Inc
6 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
7 */
8 #ifndef __MONO_MINI_H__
9 #define __MONO_MINI_H__
11 #include "config.h"
12 #include <glib.h>
13 #include <signal.h>
14 #ifdef HAVE_SYS_TYPES_H
15 #include <sys/types.h>
16 #endif
17 #include <mono/utils/mono-forward-internal.h>
18 #include <mono/metadata/loader.h>
19 #include <mono/metadata/mempool.h>
20 #include <mono/utils/monobitset.h>
21 #include <mono/metadata/class.h>
22 #include <mono/metadata/object.h>
23 #include <mono/metadata/opcodes.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/domain-internals.h>
26 #include "mono/metadata/class-internals.h"
27 #include "mono/metadata/class-init.h"
28 #include "mono/metadata/object-internals.h"
29 #include <mono/metadata/profiler-private.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/abi-details.h>
32 #include <mono/utils/mono-compiler.h>
33 #include <mono/utils/mono-machine.h>
34 #include <mono/utils/mono-stack-unwinding.h>
35 #include <mono/utils/mono-threads.h>
36 #include <mono/utils/mono-threads-coop.h>
37 #include <mono/utils/mono-tls.h>
38 #include <mono/utils/atomic.h>
39 #include <mono/utils/mono-jemalloc.h>
40 #include <mono/utils/mono-conc-hashtable.h>
41 #include <mono/utils/mono-signal-handler.h>
42 #include <mono/metadata/icalls.h>
44 // Forward declare so that mini-*.h can have pointers to them.
45 // CallInfo is presently architecture specific.
46 typedef struct MonoInst MonoInst;
47 typedef struct CallInfo CallInfo;
48 typedef struct SeqPointInfo SeqPointInfo;
50 #include "mini-arch.h"
51 #include "regalloc.h"
52 #include "mini-unwind.h"
53 #include "jit.h"
54 #include "cfgdump.h"
55 #include "tiered.h"
57 #include "mono/metadata/tabledefs.h"
58 #include "mono/metadata/marshal.h"
59 #include "mono/metadata/security-manager.h"
60 #include "mono/metadata/exception.h"
61 #include "mono/metadata/callspec.h"
62 #include "mono/metadata/icall-signatures.h"
65 * The mini code should not have any compile time dependencies on the GC being used, so the same object file from mini/
66 * can be linked into both mono and mono-sgen.
68 #if !defined(MONO_DLL_EXPORT) || !defined(_MSC_VER)
69 #if defined(HAVE_BOEHM_GC) || defined(HAVE_SGEN_GC)
70 #error "The code in mini/ should not depend on these defines."
71 #endif
72 #endif
74 #ifndef __GNUC__
75 /*#define __alignof__(a) sizeof(a)*/
76 #define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
77 #endif
79 #if DISABLE_LOGGING
80 #define MINI_DEBUG(level,limit,code)
81 #else
82 #define MINI_DEBUG(level,limit,code) do {if (G_UNLIKELY ((level) >= (limit))) code} while (0)
83 #endif
85 #if !defined(DISABLE_TASKLETS) && defined(MONO_ARCH_SUPPORT_TASKLETS)
86 #if defined(__GNUC__)
87 #define MONO_SUPPORT_TASKLETS 1
88 #elif defined(HOST_WIN32)
89 #define MONO_SUPPORT_TASKLETS 1
90 // Replace some gnu intrinsics needed for tasklets with MSVC equivalents.
91 #define __builtin_extract_return_addr(x) x
92 #define __builtin_return_address(x) _ReturnAddress()
93 #define __builtin_frame_address(x) _AddressOfReturnAddress()
94 #endif
95 #endif
97 #if ENABLE_LLVM
98 #define COMPILE_LLVM(cfg) ((cfg)->compile_llvm)
99 #define LLVM_ENABLED TRUE
100 #else
101 #define COMPILE_LLVM(cfg) (0)
102 #define LLVM_ENABLED FALSE
103 #endif
105 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
106 #define COMPILE_SOFT_FLOAT(cfg) (!COMPILE_LLVM ((cfg)) && mono_arch_is_soft_float ())
107 #else
108 #define COMPILE_SOFT_FLOAT(cfg) (0)
109 #endif
111 #define NOT_IMPLEMENTED do { g_assert_not_reached (); } while (0)
113 /* for 32 bit systems */
114 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
115 #define MINI_LS_WORD_IDX 0
116 #define MINI_MS_WORD_IDX 1
117 #else
118 #define MINI_LS_WORD_IDX 1
119 #define MINI_MS_WORD_IDX 0
120 #endif
121 #define MINI_LS_WORD_OFFSET (MINI_LS_WORD_IDX * 4)
122 #define MINI_MS_WORD_OFFSET (MINI_MS_WORD_IDX * 4)
124 #define MONO_LVREG_LS(lvreg) ((lvreg) + 1)
125 #define MONO_LVREG_MS(lvreg) ((lvreg) + 2)
127 #ifndef DISABLE_AOT
128 #define MONO_USE_AOT_COMPILER
129 #endif
131 //TODO: This is x86/amd64 specific.
132 #define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6))
134 /* Remap printf to g_print (we use a mix of these in the mini code) */
135 #ifdef HOST_ANDROID
136 #define printf g_print
137 #endif
139 #define MONO_TYPE_IS_PRIMITIVE(t) ((!(t)->byref && ((((t)->type >= MONO_TYPE_BOOLEAN && (t)->type <= MONO_TYPE_R8) || ((t)->type >= MONO_TYPE_I && (t)->type <= MONO_TYPE_U)))))
140 //XXX this ignores if t is byref
141 #define MONO_TYPE_IS_PRIMITIVE_SCALAR(t) ((((((t)->type >= MONO_TYPE_BOOLEAN && (t)->type <= MONO_TYPE_U8) || ((t)->type >= MONO_TYPE_I && (t)->type <= MONO_TYPE_U)))))
143 typedef struct
145 MonoClass *klass;
146 MonoMethod *method;
147 } MonoClassMethodPair;
149 typedef struct
151 MonoClass *klass;
152 MonoMethod *method;
153 gboolean is_virtual;
154 } MonoDelegateClassMethodPair;
156 typedef struct {
157 MonoJitInfo *ji;
158 MonoCodeManager *code_mp;
159 } MonoJitDynamicMethodInfo;
161 /* An extension of MonoGenericParamFull used in generic sharing */
162 typedef struct {
163 MonoGenericParamFull param;
164 MonoGenericParam *parent;
165 } MonoGSharedGenericParam;
167 /* Contains a list of ips which needs to be patched when a method is compiled */
168 typedef struct {
169 GSList *list;
170 } MonoJumpList;
172 /* Arch-specific */
173 typedef struct {
174 int dummy;
175 } MonoDynCallInfo;
177 typedef struct {
178 guint32 index;
179 MonoExceptionClause *clause;
180 } MonoLeaveClause;
183 * Information about a stack frame.
184 * FIXME This typedef exists only to avoid tons of code rewriting
186 typedef MonoStackFrameInfo StackFrameInfo;
188 #if 0
189 #define mono_bitset_foreach_bit(set,b,n) \
190 for (b = 0; b < n; b++)\
191 if (mono_bitset_test_fast(set,b))
192 #else
193 #define mono_bitset_foreach_bit(set,b,n) \
194 for (b = mono_bitset_find_start (set); b < n && b >= 0; b = mono_bitset_find_first (set, b))
195 #endif
198 * Pull the list of opcodes
200 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
201 a = i,
203 enum {
204 #include "mono/cil/opcode.def"
205 CEE_LASTOP
207 #undef OPDEF
209 #define MONO_VARINFO(cfg,varnum) (&(cfg)->vars [varnum])
211 #define MONO_INST_NULLIFY_SREGS(dest) do { \
212 (dest)->sreg1 = (dest)->sreg2 = (dest)->sreg3 = -1; \
213 } while (0)
215 #define MONO_INST_NEW(cfg,dest,op) do { \
216 (dest) = (MonoInst *)mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
217 (dest)->opcode = (op); \
218 (dest)->dreg = -1; \
219 MONO_INST_NULLIFY_SREGS ((dest)); \
220 (dest)->cil_code = (cfg)->ip; \
221 } while (0)
223 #define MONO_INST_NEW_CALL(cfg,dest,op) do { \
224 (dest) = (MonoCallInst *)mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoCallInst)); \
225 (dest)->inst.opcode = (op); \
226 (dest)->inst.dreg = -1; \
227 MONO_INST_NULLIFY_SREGS (&(dest)->inst); \
228 (dest)->inst.cil_code = (cfg)->ip; \
229 } while (0)
231 #define MONO_ADD_INS(b,inst) do { \
232 if ((b)->last_ins) { \
233 (b)->last_ins->next = (inst); \
234 (inst)->prev = (b)->last_ins; \
235 (b)->last_ins = (inst); \
236 } else { \
237 (b)->code = (b)->last_ins = (inst); \
239 } while (0)
241 #define NULLIFY_INS(ins) do { \
242 (ins)->opcode = OP_NOP; \
243 (ins)->dreg = -1; \
244 MONO_INST_NULLIFY_SREGS ((ins)); \
245 } while (0)
247 /* Remove INS from BB */
248 #define MONO_REMOVE_INS(bb,ins) do { \
249 if ((ins)->prev) \
250 (ins)->prev->next = (ins)->next; \
251 if ((ins)->next) \
252 (ins)->next->prev = (ins)->prev; \
253 if ((bb)->code == (ins)) \
254 (bb)->code = (ins)->next; \
255 if ((bb)->last_ins == (ins)) \
256 (bb)->last_ins = (ins)->prev; \
257 } while (0)
259 /* Remove INS from BB and nullify it */
260 #define MONO_DELETE_INS(bb,ins) do { \
261 MONO_REMOVE_INS ((bb), (ins)); \
262 NULLIFY_INS ((ins)); \
263 } while (0)
266 * this is used to determine when some branch optimizations are possible: we exclude FP compares
267 * because they have weird semantics with NaNs.
269 #define MONO_IS_COND_BRANCH_OP(ins) (((ins)->opcode >= OP_LBEQ && (ins)->opcode <= OP_LBLT_UN) || ((ins)->opcode >= OP_FBEQ && (ins)->opcode <= OP_FBLT_UN) || ((ins)->opcode >= OP_IBEQ && (ins)->opcode <= OP_IBLT_UN))
270 #define MONO_IS_COND_BRANCH_NOFP(ins) (MONO_IS_COND_BRANCH_OP(ins) && !(((ins)->opcode >= OP_FBEQ) && ((ins)->opcode <= OP_FBLT_UN)))
272 #define MONO_IS_BRANCH_OP(ins) (MONO_IS_COND_BRANCH_OP(ins) || ((ins)->opcode == OP_BR) || ((ins)->opcode == OP_BR_REG) || ((ins)->opcode == OP_SWITCH))
274 #define MONO_IS_COND_EXC(ins) ((((ins)->opcode >= OP_COND_EXC_EQ) && ((ins)->opcode <= OP_COND_EXC_LT_UN)) || (((ins)->opcode >= OP_COND_EXC_IEQ) && ((ins)->opcode <= OP_COND_EXC_ILT_UN)))
276 #define MONO_IS_SETCC(ins) ((((ins)->opcode >= OP_CEQ) && ((ins)->opcode <= OP_CLT_UN)) || (((ins)->opcode >= OP_ICEQ) && ((ins)->opcode <= OP_ICLE_UN)) || (((ins)->opcode >= OP_LCEQ) && ((ins)->opcode <= OP_LCLT_UN)) || (((ins)->opcode >= OP_FCEQ) && ((ins)->opcode <= OP_FCLT_UN)))
278 #define MONO_HAS_CUSTOM_EMULATION(ins) (((ins)->opcode >= OP_FBEQ && (ins)->opcode <= OP_FBLT_UN) || ((ins)->opcode >= OP_FCEQ && (ins)->opcode <= OP_FCLT_UN))
280 #define MONO_IS_LOAD_MEMBASE(ins) (((ins)->opcode >= OP_LOAD_MEMBASE && (ins)->opcode <= OP_LOADV_MEMBASE) || ((ins)->opcode >= OP_ATOMIC_LOAD_I1 && (ins)->opcode <= OP_ATOMIC_LOAD_R8))
281 #define MONO_IS_STORE_MEMBASE(ins) (((ins)->opcode >= OP_STORE_MEMBASE_REG && (ins)->opcode <= OP_STOREV_MEMBASE) || ((ins)->opcode >= OP_ATOMIC_STORE_I1 && (ins)->opcode <= OP_ATOMIC_STORE_R8))
282 #define MONO_IS_STORE_MEMINDEX(ins) (((ins)->opcode >= OP_STORE_MEMINDEX) && ((ins)->opcode <= OP_STORER8_MEMINDEX))
284 // This is internal because it is easily confused with any enum or integer.
285 #define MONO_IS_TAILCALL_OPCODE_INTERNAL(opcode) ((opcode) == OP_TAILCALL || (opcode) == OP_TAILCALL_MEMBASE || (opcode) == OP_TAILCALL_REG)
287 #define MONO_IS_TAILCALL_OPCODE(call) (MONO_IS_TAILCALL_OPCODE_INTERNAL (call->inst.opcode))
289 // OP_DYN_CALL is not a MonoCallInst
290 #define MONO_IS_CALL(ins) (((ins)->opcode >= OP_VOIDCALL && (ins)->opcode <= OP_VCALL2_MEMBASE) || \
291 MONO_IS_TAILCALL_OPCODE_INTERNAL ((ins)->opcode))
293 #define MONO_IS_JUMP_TABLE(ins) (((ins)->opcode == OP_JUMP_TABLE) ? TRUE : ((((ins)->opcode == OP_AOTCONST) && (ins->inst_i1 == (gpointer)MONO_PATCH_INFO_SWITCH)) ? TRUE : ((ins)->opcode == OP_SWITCH) ? TRUE : ((((ins)->opcode == OP_GOT_ENTRY) && ((ins)->inst_right->inst_i1 == (gpointer)MONO_PATCH_INFO_SWITCH)) ? TRUE : FALSE)))
295 #define MONO_JUMP_TABLE_FROM_INS(ins) (((ins)->opcode == OP_JUMP_TABLE) ? (ins)->inst_p0 : (((ins)->opcode == OP_AOTCONST) && (ins->inst_i1 == (gpointer)MONO_PATCH_INFO_SWITCH) ? (ins)->inst_p0 : (((ins)->opcode == OP_SWITCH) ? (ins)->inst_p0 : ((((ins)->opcode == OP_GOT_ENTRY) && ((ins)->inst_right->inst_i1 == (gpointer)MONO_PATCH_INFO_SWITCH)) ? (ins)->inst_right->inst_p0 : NULL))))
297 /* FIXME: Add more instructions */
298 /* INEG sets the condition codes, and the OP_LNEG decomposition depends on this on x86 */
299 #define MONO_INS_HAS_NO_SIDE_EFFECT(ins) (MONO_IS_MOVE (ins) || (ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || MONO_IS_ZERO (ins) || (ins->opcode == OP_ADD_IMM) || (ins->opcode == OP_R8CONST) || (ins->opcode == OP_LADD_IMM) || (ins->opcode == OP_ISUB_IMM) || (ins->opcode == OP_IADD_IMM) || (ins->opcode == OP_LNEG) || (ins->opcode == OP_ISUB) || (ins->opcode == OP_CMOV_IGE) || (ins->opcode == OP_ISHL_IMM) || (ins->opcode == OP_ISHR_IMM) || (ins->opcode == OP_ISHR_UN_IMM) || (ins->opcode == OP_IAND_IMM) || (ins->opcode == OP_ICONV_TO_U1) || (ins->opcode == OP_ICONV_TO_I1) || (ins->opcode == OP_SEXT_I4) || (ins->opcode == OP_LCONV_TO_U1) || (ins->opcode == OP_ICONV_TO_U2) || (ins->opcode == OP_ICONV_TO_I2) || (ins->opcode == OP_LCONV_TO_I2) || (ins->opcode == OP_LDADDR) || (ins->opcode == OP_PHI) || (ins->opcode == OP_NOP) || (ins->opcode == OP_ZEXT_I4) || (ins->opcode == OP_NOT_NULL) || (ins->opcode == OP_IL_SEQ_POINT) || (ins->opcode == OP_XZERO))
301 #define MONO_INS_IS_PCONST_NULL(ins) ((ins)->opcode == OP_PCONST && (ins)->inst_p0 == 0)
303 #define MONO_METHOD_IS_FINAL(m) (((m)->flags & METHOD_ATTRIBUTE_FINAL) || ((m)->klass && (mono_class_get_flags ((m)->klass) & TYPE_ATTRIBUTE_SEALED)))
305 /* Determine whenever 'ins' represents a load of the 'this' argument */
306 #define MONO_CHECK_THIS(ins) (mono_method_signature_internal (cfg->method)->hasthis && ((ins)->opcode == OP_MOVE) && ((ins)->sreg1 == cfg->args [0]->dreg))
308 #ifdef MONO_ARCH_SIMD_INTRINSICS
310 #define MONO_IS_PHI(ins) (((ins)->opcode == OP_PHI) || ((ins)->opcode == OP_FPHI) || ((ins)->opcode == OP_VPHI) || ((ins)->opcode == OP_XPHI))
311 #define MONO_IS_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_FMOVE) || ((ins)->opcode == OP_VMOVE) || ((ins)->opcode == OP_XMOVE) || ((ins)->opcode == OP_RMOVE))
312 #define MONO_IS_NON_FP_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_VMOVE) || ((ins)->opcode == OP_XMOVE))
313 #define MONO_IS_REAL_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_FMOVE) || ((ins)->opcode == OP_XMOVE) || ((ins)->opcode == OP_RMOVE))
314 #define MONO_IS_ZERO(ins) (((ins)->opcode == OP_VZERO) || ((ins)->opcode == OP_XZERO))
316 #define MONO_CLASS_IS_SIMD(cfg, klass) (((cfg)->opt & MONO_OPT_SIMD) && m_class_is_simd_type (klass))
318 #else
320 #define MONO_IS_PHI(ins) (((ins)->opcode == OP_PHI) || ((ins)->opcode == OP_FPHI) || ((ins)->opcode == OP_VPHI))
321 #define MONO_IS_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_FMOVE) || ((ins)->opcode == OP_VMOVE) || ((ins)->opcode == OP_RMOVE))
322 #define MONO_IS_NON_FP_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_VMOVE))
323 /*A real MOVE is one that isn't decomposed such as a VMOVE or LMOVE*/
324 #define MONO_IS_REAL_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_FMOVE) || ((ins)->opcode == OP_RMOVE))
325 #define MONO_IS_ZERO(ins) ((ins)->opcode == OP_VZERO)
327 #define MONO_CLASS_IS_SIMD(cfg, klass) (0)
329 #endif
331 #if defined(TARGET_X86) || defined(TARGET_AMD64)
332 #define EMIT_NEW_X86_LEA(cfg,dest,sr1,sr2,shift,imm) do { \
333 MONO_INST_NEW (cfg, dest, OP_X86_LEA); \
334 (dest)->dreg = alloc_ireg_mp ((cfg)); \
335 (dest)->sreg1 = (sr1); \
336 (dest)->sreg2 = (sr2); \
337 (dest)->inst_imm = (imm); \
338 (dest)->backend.shift_amount = (shift); \
339 MONO_ADD_INS ((cfg)->cbb, (dest)); \
340 } while (0)
341 #endif
343 typedef struct MonoInstList MonoInstList;
344 typedef struct MonoCallInst MonoCallInst;
345 typedef struct MonoCallArgParm MonoCallArgParm;
346 typedef struct MonoMethodVar MonoMethodVar;
347 typedef struct MonoBasicBlock MonoBasicBlock;
348 typedef struct MonoSpillInfo MonoSpillInfo;
350 extern MonoCallSpec *mono_jit_trace_calls;
351 extern MonoMethodDesc *mono_inject_async_exc_method;
352 extern int mono_inject_async_exc_pos;
353 extern MonoMethodDesc *mono_break_at_bb_method;
354 extern int mono_break_at_bb_bb_num;
355 extern gboolean mono_do_x86_stack_align;
356 extern gboolean mono_using_xdebug;
357 extern int mini_verbose;
358 extern int valgrind_register;
360 #define INS_INFO(opcode) (&mini_ins_info [((opcode) - OP_START - 1) * 4])
362 /* instruction description for use in regalloc/scheduling */
364 enum {
365 MONO_INST_DEST = 0,
366 MONO_INST_SRC1 = 1, /* we depend on the SRCs to be consecutive */
367 MONO_INST_SRC2 = 2,
368 MONO_INST_SRC3 = 3,
369 MONO_INST_LEN = 4,
370 MONO_INST_CLOB = 5,
371 /* Unused, commented out to reduce the size of the mdesc tables
372 MONO_INST_FLAGS,
373 MONO_INST_COST,
374 MONO_INST_DELAY,
375 MONO_INST_RES,
377 MONO_INST_MAX = 6
380 typedef union MonoInstSpec { // instruction specification
381 struct {
382 char dest;
383 char src1;
384 char src2;
385 char src3;
386 unsigned char len;
387 char clob;
388 // char flags;
389 // char cost;
390 // char delay;
391 // char res;
393 struct {
394 char xdest;
395 char src [3];
396 unsigned char xlen;
397 char xclob;
399 char bytes[MONO_INST_MAX];
400 } MonoInstSpec;
402 MONO_LLVM_INTERNAL_EXTERN_C_BEGIN
403 extern const char mini_ins_info[] MONO_LLVM_INTERNAL_NO_EXTERN_C;
404 MONO_LLVM_INTERNAL_EXTERN_C_END
405 extern const gint8 mini_ins_sreg_counts [];
407 #ifndef DISABLE_JIT
408 #define mono_inst_get_num_src_registers(ins) (mini_ins_sreg_counts [(ins)->opcode - OP_START - 1])
409 #else
410 #define mono_inst_get_num_src_registers(ins) 0
411 #endif
413 #define mono_inst_get_src_registers(ins, regs) (((regs) [0] = (ins)->sreg1), ((regs) [1] = (ins)->sreg2), ((regs) [2] = (ins)->sreg3), mono_inst_get_num_src_registers ((ins)))
415 #define MONO_BB_FOR_EACH_INS(bb, ins) for ((ins) = (bb)->code; (ins); (ins) = (ins)->next)
417 #define MONO_BB_FOR_EACH_INS_SAFE(bb, n, ins) for ((ins) = (bb)->code, n = (ins) ? (ins)->next : NULL; (ins); (ins) = (n), (n) = (ins) ? (ins)->next : NULL)
419 #define MONO_BB_FOR_EACH_INS_REVERSE(bb, ins) for ((ins) = (bb)->last_ins; (ins); (ins) = (ins)->prev)
421 #define MONO_BB_FOR_EACH_INS_REVERSE_SAFE(bb, p, ins) for ((ins) = (bb)->last_ins, p = (ins) ? (ins)->prev : NULL; (ins); (ins) = (p), (p) = (ins) ? (ins)->prev : NULL)
423 #define mono_bb_first_ins(bb) (bb)->code
426 * Iterate through all used registers in the instruction.
427 * Relies on the existing order of the MONO_INST enum: MONO_INST_{DREG,SREG1,SREG2,SREG3,LEN}
428 * INS is the instruction, IDX is the register index, REG is the pointer to a register.
430 #define MONO_INS_FOR_EACH_REG(ins, idx, reg) for ((idx) = INS_INFO ((ins)->opcode)[MONO_INST_DEST] != ' ' ? MONO_INST_DEST : \
431 (mono_inst_get_num_src_registers (ins) ? MONO_INST_SRC1 : MONO_INST_LEN); \
432 (reg) = (idx) == MONO_INST_DEST ? &(ins)->dreg : \
433 ((idx) == MONO_INST_SRC1 ? &(ins)->sreg1 : \
434 ((idx) == MONO_INST_SRC2 ? &(ins)->sreg2 : \
435 ((idx) == MONO_INST_SRC3 ? &(ins)->sreg3 : NULL))), \
436 idx < MONO_INST_LEN; \
437 (idx) = (idx) > mono_inst_get_num_src_registers (ins) + (INS_INFO ((ins)->opcode)[MONO_INST_DEST] != ' ') ? MONO_INST_LEN : (idx) + 1)
439 struct MonoSpillInfo {
440 int offset;
444 * Information about a call site for the GC map creation code
446 typedef struct {
447 /* The next offset after the call instruction */
448 int pc_offset;
449 /* The basic block containing the call site */
450 MonoBasicBlock *bb;
452 * The set of variables live at the call site.
453 * Has length cfg->num_varinfo in bits.
455 guint8 *liveness;
457 * List of OP_GC_PARAM_SLOT_LIVENESS_DEF instructions defining the param slots
458 * used by this call.
460 GSList *param_slots;
461 } GCCallSite;
464 * The IR-level extended basic block.
466 * A basic block can have multiple exits just fine, as long as the point of
467 * 'departure' is the last instruction in the basic block. Extended basic
468 * blocks, on the other hand, may have instructions that leave the block
469 * midstream. The important thing is that they cannot be _entered_
470 * midstream, ie, execution of a basic block (or extened bb) always start
471 * at the beginning of the block, never in the middle.
473 struct MonoBasicBlock {
474 MonoInst *last_ins;
476 /* the next basic block in the order it appears in IL */
477 MonoBasicBlock *next_bb;
480 * Before instruction selection it is the first tree in the
481 * forest and the first item in the list of trees. After
482 * instruction selection it is the first instruction and the
483 * first item in the list of instructions.
485 MonoInst *code;
487 /* unique block number identification */
488 gint32 block_num;
490 gint32 dfn;
492 /* Basic blocks: incoming and outgoing counts and pointers */
493 /* Each bb should only appear once in each array */
494 gint16 out_count, in_count;
495 MonoBasicBlock **in_bb;
496 MonoBasicBlock **out_bb;
498 /* Points to the start of the CIL code that initiated this BB */
499 unsigned char* cil_code;
501 /* Length of the CIL block */
502 gint32 cil_length;
504 /* The offset of the generated code, used for fixups */
505 int native_offset;
506 /* The length of the generated code, doesn't include alignment padding */
507 int native_length;
508 /* The real native offset, which includes alignment padding too */
509 int real_native_offset;
510 int max_offset;
511 int max_length;
513 /* Visited and reachable flags */
514 guint32 flags;
517 * SSA and loop based flags
519 MonoBitSet *dominators;
520 MonoBitSet *dfrontier;
521 MonoBasicBlock *idom;
522 GSList *dominated;
523 /* fast dominator algorithm */
524 MonoBasicBlock *df_parent, *ancestor, *child, *label;
525 int size, sdom, idomn;
527 /* loop nesting and recognition */
528 GList *loop_blocks;
529 gint8 nesting;
530 gint8 loop_body_start;
533 * Whenever the bblock is rarely executed so it should be emitted after
534 * the function epilog.
536 guint out_of_line : 1;
537 /* Caches the result of uselessness calculation during optimize_branches */
538 guint not_useless : 1;
539 /* Whenever the decompose_array_access_opts () pass needs to process this bblock */
540 guint needs_decompose : 1;
541 /* Whenever this bblock is extended, ie. it has branches inside it */
542 guint extended : 1;
543 /* Whenever this bblock contains a OP_JUMP_TABLE instruction */
544 guint has_jump_table : 1;
545 /* Whenever this bblock contains an OP_CALL_HANDLER instruction */
546 guint has_call_handler : 1;
547 /* Whenever this bblock starts a try block */
548 guint try_start : 1;
550 #ifdef ENABLE_LLVM
551 /* The offset of the CIL instruction in this bblock which ends a try block */
552 intptr_t try_end;
553 #endif
556 * If this is set, extend the try range started by this bblock by an arch specific
557 * number of bytes to encompass the end of the previous bblock (e.g. a Monitor.Enter
558 * call).
560 guint extend_try_block : 1;
562 /* use for liveness analysis */
563 MonoBitSet *gen_set;
564 MonoBitSet *kill_set;
565 MonoBitSet *live_in_set;
566 MonoBitSet *live_out_set;
568 /* fields to deal with non-empty stack slots at bb boundary */
569 guint16 out_scount, in_scount;
570 MonoInst **out_stack;
571 MonoInst **in_stack;
573 /* we use that to prevent merging of bblocks covered by different clauses*/
574 guint real_offset;
576 GSList *seq_points;
578 // The MonoInst of the last sequence point for the current basic block.
579 MonoInst *last_seq_point;
581 // This will hold a list of last sequence points of incoming basic blocks
582 MonoInst **pred_seq_points;
583 guint num_pred_seq_points;
585 GSList *spill_slot_defs;
587 /* List of call sites in this bblock sorted by pc_offset */
588 GSList *gc_callsites;
591 * If this is not null, the basic block is a try hole for all the clauses
592 * in the list previous to this element (including the element).
594 GList *clause_holes;
597 * The region encodes whether the basic block is inside
598 * a finally, catch, filter or none of these.
600 * If the value is -1, then it is neither finally, catch nor filter
602 * Otherwise the format is:
604 * Bits: | 0-3 | 4-7 | 8-31
605 * | | |
606 * | clause-flags | MONO_REGION | clause-index
609 guint region;
611 /* The current symbolic register number, used in local register allocation. */
612 guint32 max_vreg;
615 /* BBlock flags */
616 enum {
617 BB_VISITED = 1 << 0,
618 BB_REACHABLE = 1 << 1,
619 BB_EXCEPTION_DEAD_OBJ = 1 << 2,
620 BB_EXCEPTION_UNSAFE = 1 << 3,
621 BB_EXCEPTION_HANDLER = 1 << 4,
622 /* for Native Client, mark the blocks that can be jumped to indirectly */
623 BB_INDIRECT_JUMP_TARGET = 1 << 5
626 typedef struct MonoMemcpyArgs {
627 int size, align;
628 } MonoMemcpyArgs;
630 typedef enum {
631 LLVMArgNone,
632 /* Scalar argument passed by value */
633 LLVMArgNormal,
634 /* Only in ainfo->pair_storage */
635 LLVMArgInIReg,
636 /* Only in ainfo->pair_storage */
637 LLVMArgInFPReg,
638 /* Valuetype passed in 1-2 consecutive register */
639 LLVMArgVtypeInReg,
640 LLVMArgVtypeByVal,
641 LLVMArgVtypeRetAddr, /* On on cinfo->ret */
642 LLVMArgGSharedVt,
643 /* Fixed size argument passed to/returned from gsharedvt method by ref */
644 LLVMArgGsharedvtFixed,
645 /* Fixed size vtype argument passed to/returned from gsharedvt method by ref */
646 LLVMArgGsharedvtFixedVtype,
647 /* Variable sized argument passed to/returned from gsharedvt method by ref */
648 LLVMArgGsharedvtVariable,
649 /* Vtype passed/returned as one int array argument */
650 LLVMArgAsIArgs,
651 /* Vtype passed as a set of fp arguments */
652 LLVMArgAsFpArgs,
654 * Only for returns, a structure which
655 * consists of floats/doubles.
657 LLVMArgFpStruct,
658 LLVMArgVtypeByRef,
659 /* Vtype returned as an int */
660 LLVMArgVtypeAsScalar,
661 /* Address to local vtype passed as argument (using register or stack). */
662 LLVMArgVtypeAddr
663 } LLVMArgStorage;
665 typedef struct {
666 LLVMArgStorage storage;
669 * Only if storage == ArgVtypeInReg/LLVMArgAsFpArgs.
670 * This contains how the parts of the vtype are passed.
672 LLVMArgStorage pair_storage [8];
674 * Only if storage == LLVMArgAsIArgs/LLVMArgAsFpArgs/LLVMArgFpStruct.
675 * If storage == LLVMArgAsFpArgs, this is the number of arguments
676 * used to pass the value.
677 * If storage == LLVMArgFpStruct, this is the number of fields
678 * in the structure.
680 int nslots;
681 /* Only if storage == LLVMArgAsIArgs/LLVMArgAsFpArgs/LLVMArgFpStruct (4/8) */
682 int esize;
683 /* Parameter index in the LLVM signature */
684 int pindex;
685 MonoType *type;
686 /* Only if storage == LLVMArgAsFpArgs. Dummy fp args to insert before this arg */
687 int ndummy_fpargs;
688 } LLVMArgInfo;
690 typedef struct {
691 LLVMArgInfo ret;
692 /* Whenever there is an rgctx argument */
693 gboolean rgctx_arg;
694 /* Whenever there is an IMT argument */
695 gboolean imt_arg;
696 /* Whenever there is a dummy extra argument */
697 gboolean dummy_arg;
699 * The position of the vret arg in the argument list.
700 * Only if ret->storage == ArgVtypeRetAddr.
701 * Should be 0 or 1.
703 int vret_arg_index;
704 /* The indexes of various special arguments in the LLVM signature */
705 int vret_arg_pindex, this_arg_pindex, rgctx_arg_pindex, imt_arg_pindex, dummy_arg_pindex;
707 /* Inline array of argument info */
708 /* args [0] is for the this argument if it exists */
709 LLVMArgInfo args [1];
710 } LLVMCallInfo;
712 #define MONO_MAX_SRC_REGS 3
714 struct MonoInst {
715 guint16 opcode;
716 guint8 type; /* stack type */
717 guint8 flags;
719 /* used by the register allocator */
720 gint32 dreg, sreg1, sreg2, sreg3;
722 MonoInst *next, *prev;
724 union {
725 union {
726 MonoInst *src;
727 MonoMethodVar *var;
728 target_mgreg_t const_val;
729 #if (SIZEOF_REGISTER > TARGET_SIZEOF_VOID_P) && (G_BYTE_ORDER == G_BIG_ENDIAN)
730 struct {
731 gpointer p[SIZEOF_REGISTER/TARGET_SIZEOF_VOID_P];
732 } pdata;
733 #else
734 gpointer p;
735 #endif
736 MonoMethod *method;
737 MonoMethodSignature *signature;
738 MonoBasicBlock **many_blocks;
739 MonoBasicBlock *target_block;
740 MonoInst **args;
741 MonoType *vtype;
742 MonoClass *klass;
743 int *phi_args;
744 MonoCallInst *call_inst;
745 GList *exception_clauses;
746 } op [2];
747 gint64 i8const;
748 double r8const;
749 } data;
751 const unsigned char* cil_code; /* for debugging and bblock splitting */
753 /* used mostly by the backend to store additional info it may need */
754 union {
755 gint32 reg3;
756 gint32 arg_info;
757 gint32 size;
758 MonoMemcpyArgs *memcpy_args; /* in OP_MEMSET and OP_MEMCPY */
759 gpointer data;
760 gint shift_amount;
761 gboolean is_pinvoke; /* for variables in the unmanaged marshal format */
762 gboolean record_cast_details; /* For CEE_CASTCLASS */
763 MonoInst *spill_var; /* for OP_MOVE_I4_TO_F/F_TO_I4 and OP_FCONV_TO_R8_X */
764 guint16 source_opcode; /*OP_XCONV_R8_TO_I4 needs to know which op was used to do proper widening*/
765 int pc_offset; /* OP_GC_LIVERANGE_START/END */
768 * memory_barrier: MONO_MEMORY_BARRIER_{ACQ,REL,SEQ}
769 * atomic_load_*: MONO_MEMORY_BARRIER_{ACQ,SEQ}
770 * atomic_store_*: MONO_MEMORY_BARRIER_{REL,SEQ}
772 int memory_barrier_kind;
773 } backend;
775 MonoClass *klass;
778 struct MonoCallInst {
779 MonoInst inst;
780 MonoMethodSignature *signature;
781 MonoMethod *method;
782 MonoInst **args;
783 MonoInst *out_args;
784 MonoInst *vret_var;
785 gconstpointer fptr;
786 guint stack_usage;
787 guint stack_align_amount;
788 guint is_virtual : 1;
789 // FIXME tailcall field is written after read; prefer MONO_IS_TAILCALL_OPCODE.
790 guint tailcall : 1;
791 /* If this is TRUE, 'fptr' points to a MonoJumpInfo instead of an address. */
792 guint fptr_is_patch : 1;
793 MonoJitICallId jit_icall_id;
795 * If this is true, then the call returns a vtype in a register using the same
796 * calling convention as OP_CALL.
798 guint vret_in_reg : 1;
799 /* Whenever vret_in_reg returns fp values */
800 guint vret_in_reg_fp : 1;
801 /* Whenever there is an IMT argument and it is dynamic */
802 guint dynamic_imt_arg : 1;
803 /* Whenever there is an RGCTX argument */
804 guint32 rgctx_reg : 1;
805 /* Whenever the call will need an unbox trampoline */
806 guint need_unbox_trampoline : 1;
807 regmask_t used_iregs;
808 regmask_t used_fregs;
809 GSList *out_ireg_args;
810 GSList *out_freg_args;
811 GSList *outarg_vts;
812 CallInfo *call_info;
813 #ifdef ENABLE_LLVM
814 LLVMCallInfo *cinfo;
815 int rgctx_arg_reg, imt_arg_reg;
816 #endif
817 #ifdef TARGET_ARM
818 /* See the comment in mini-arm.c!mono_arch_emit_call for RegTypeFP. */
819 GSList *float_args;
820 #endif
823 struct MonoCallArgParm {
824 MonoInst ins;
825 gint32 size;
826 gint32 offset;
827 gint32 offPrm;
831 * flags for MonoInst
832 * Note: some of the values overlap, because they can't appear
833 * in the same MonoInst.
835 enum {
836 MONO_INST_HAS_METHOD = 1,
837 MONO_INST_INIT = 1, /* in localloc */
838 MONO_INST_SINGLE_STEP_LOC = 1, /* in SEQ_POINT */
839 MONO_INST_IS_DEAD = 2,
840 MONO_INST_TAILCALL = 4,
841 MONO_INST_VOLATILE = 4,
842 MONO_INST_NOTYPECHECK = 4,
843 MONO_INST_NONEMPTY_STACK = 4, /* in SEQ_POINT */
844 MONO_INST_UNALIGNED = 8,
845 MONO_INST_NESTED_CALL = 8, /* in SEQ_POINT */
846 MONO_INST_CFOLD_TAKEN = 8, /* On branches */
847 MONO_INST_CFOLD_NOT_TAKEN = 16, /* On branches */
848 MONO_INST_DEFINITION_HAS_SIDE_EFFECTS = 8,
849 /* the address of the variable has been taken */
850 MONO_INST_INDIRECT = 16,
851 MONO_INST_NORANGECHECK = 16,
852 /* On loads, the source address can be null */
853 MONO_INST_FAULT = 32,
855 * On variables, identifies LMF variables. These variables have a dummy type (int), but
856 * require stack space for a MonoLMF struct.
858 MONO_INST_LMF = 32,
859 /* On loads, the source address points to a constant value */
860 MONO_INST_INVARIANT_LOAD = 64,
861 /* On variables, the variable needs GC tracking */
862 MONO_INST_GC_TRACK = 128,
864 * Set on instructions during code emission which make calls, i.e. OP_CALL, OP_THROW.
865 * backend.pc_offset will be set to the pc offset at the end of the native call instructions.
867 MONO_INST_GC_CALLSITE = 128,
868 /* On comparisons, mark the branch following the condition as likely to be taken */
869 MONO_INST_LIKELY = 128,
872 #define inst_c0 data.op[0].const_val
873 #define inst_c1 data.op[1].const_val
874 #define inst_i0 data.op[0].src
875 #define inst_i1 data.op[1].src
876 #if (SIZEOF_REGISTER > TARGET_SIZEOF_VOID_P) && (G_BYTE_ORDER == G_BIG_ENDIAN)
877 #define inst_p0 data.op[0].pdata.p[SIZEOF_REGISTER/TARGET_SIZEOF_VOID_P - 1]
878 #define inst_p1 data.op[1].pdata.p[SIZEOF_REGISTER/TARGET_SIZEOF_VOID_P - 1]
879 #else
880 #define inst_p0 data.op[0].p
881 #define inst_p1 data.op[1].p
882 #endif
883 #define inst_l data.i8const
884 #define inst_r data.r8const
885 #define inst_left data.op[0].src
886 #define inst_right data.op[1].src
888 #define inst_newa_len data.op[0].src
889 #define inst_newa_class data.op[1].klass
891 #define inst_var data.op[0].var
892 #define inst_vtype data.op[1].vtype
893 /* in branch instructions */
894 #define inst_many_bb data.op[1].many_blocks
895 #define inst_target_bb data.op[0].target_block
896 #define inst_true_bb data.op[1].many_blocks[0]
897 #define inst_false_bb data.op[1].many_blocks[1]
899 #define inst_basereg sreg1
900 #define inst_indexreg sreg2
901 #define inst_destbasereg dreg
902 #define inst_offset data.op[0].const_val
903 #define inst_imm data.op[1].const_val
904 #define inst_call data.op[1].call_inst
906 #define inst_phi_args data.op[1].phi_args
907 #define inst_eh_blocks data.op[1].exception_clauses
909 /* Return the lower 32 bits of the 64 bit immediate in INS */
910 static inline guint32
911 ins_get_l_low (MonoInst *ins)
913 return (guint32)(ins->data.i8const & 0xffffffff);
916 /* Return the higher 32 bits of the 64 bit immediate in INS */
917 static inline guint32
918 ins_get_l_high (MonoInst *ins)
920 return (guint32)((ins->data.i8const >> 32) & 0xffffffff);
923 static inline void
924 mono_inst_set_src_registers (MonoInst *ins, int *regs)
926 ins->sreg1 = regs [0];
927 ins->sreg2 = regs [1];
928 ins->sreg3 = regs [2];
931 typedef union {
932 struct {
933 guint16 tid; /* tree number */
934 guint16 bid; /* block number */
935 } pos ;
936 guint32 abs_pos;
937 } MonoPosition;
939 typedef struct {
940 MonoPosition first_use, last_use;
941 } MonoLiveRange;
943 typedef struct MonoLiveRange2 MonoLiveRange2;
945 struct MonoLiveRange2 {
946 int from, to;
947 MonoLiveRange2 *next;
950 typedef struct {
951 /* List of live ranges sorted by 'from' */
952 MonoLiveRange2 *range;
953 MonoLiveRange2 *last_range;
954 } MonoLiveInterval;
957 * Additional information about a variable
959 struct MonoMethodVar {
960 guint idx; /* inside cfg->varinfo, cfg->vars */
961 MonoLiveRange range; /* generated by liveness analysis */
962 MonoLiveInterval *interval; /* generated by liveness analysis */
963 int reg; /* != -1 if allocated into a register */
964 int spill_costs;
965 MonoBitSet *def_in; /* used by SSA */
966 MonoInst *def; /* used by SSA */
967 MonoBasicBlock *def_bb; /* used by SSA */
968 GList *uses; /* used by SSA */
969 char cpstate; /* used by SSA conditional constant propagation */
970 /* The native offsets corresponding to the live range of the variable */
971 gint32 live_range_start, live_range_end;
973 * cfg->varinfo [idx]->dreg could be replaced for OP_REGVAR, this contains the
974 * original vreg.
976 gint32 vreg;
979 /* Generic sharing */
982 * Flags for which contexts were used in inflating a generic.
984 enum {
985 MONO_GENERIC_CONTEXT_USED_CLASS = 1,
986 MONO_GENERIC_CONTEXT_USED_METHOD = 2
989 enum {
990 /* Cannot be 0 since this is stored in rgctx slots, and 0 means an unitialized rgctx slot */
991 MONO_GSHAREDVT_BOX_TYPE_VTYPE = 1,
992 MONO_GSHAREDVT_BOX_TYPE_REF = 2,
993 MONO_GSHAREDVT_BOX_TYPE_NULLABLE = 3
996 typedef enum {
997 MONO_RGCTX_INFO_STATIC_DATA = 0,
998 MONO_RGCTX_INFO_KLASS = 1,
999 MONO_RGCTX_INFO_ELEMENT_KLASS = 2,
1000 MONO_RGCTX_INFO_VTABLE = 3,
1001 MONO_RGCTX_INFO_TYPE = 4,
1002 MONO_RGCTX_INFO_REFLECTION_TYPE = 5,
1003 MONO_RGCTX_INFO_METHOD = 6,
1004 MONO_RGCTX_INFO_GENERIC_METHOD_CODE = 7,
1005 MONO_RGCTX_INFO_GSHAREDVT_OUT_WRAPPER = 8,
1006 MONO_RGCTX_INFO_CLASS_FIELD = 9,
1007 MONO_RGCTX_INFO_METHOD_RGCTX = 10,
1008 MONO_RGCTX_INFO_METHOD_CONTEXT = 11,
1009 MONO_RGCTX_INFO_REMOTING_INVOKE_WITH_CHECK = 12,
1010 MONO_RGCTX_INFO_METHOD_DELEGATE_CODE = 13,
1011 MONO_RGCTX_INFO_CAST_CACHE = 14,
1012 MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE = 15,
1013 MONO_RGCTX_INFO_VALUE_SIZE = 16,
1014 /* +1 to avoid zero values in rgctx slots */
1015 MONO_RGCTX_INFO_FIELD_OFFSET = 17,
1016 /* Either the code for a gsharedvt method, or the address for a gsharedvt-out trampoline for the method */
1017 /* In llvmonly mode, this is a function descriptor */
1018 MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE = 18,
1019 /* Same for virtual calls */
1020 /* In llvmonly mode, this is a function descriptor */
1021 MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT = 19,
1022 /* Same for calli, associated with a signature */
1023 MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI = 20,
1024 MONO_RGCTX_INFO_SIG_GSHAREDVT_IN_TRAMPOLINE_CALLI = 21,
1025 /* One of MONO_GSHAREDVT_BOX_TYPE */
1026 MONO_RGCTX_INFO_CLASS_BOX_TYPE = 22,
1027 /* Resolves to a MonoGSharedVtMethodRuntimeInfo */
1028 MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO = 23,
1029 MONO_RGCTX_INFO_LOCAL_OFFSET = 24,
1030 MONO_RGCTX_INFO_MEMCPY = 25,
1031 MONO_RGCTX_INFO_BZERO = 26,
1032 /* The address of Nullable<T>.Box () */
1033 /* In llvmonly mode, this is a function descriptor */
1034 MONO_RGCTX_INFO_NULLABLE_CLASS_BOX = 27,
1035 MONO_RGCTX_INFO_NULLABLE_CLASS_UNBOX = 28,
1036 /* MONO_PATCH_INFO_VCALL_METHOD */
1037 /* In llvmonly mode, this is a function descriptor */
1038 MONO_RGCTX_INFO_VIRT_METHOD_CODE = 29,
1040 * MONO_PATCH_INFO_VCALL_METHOD
1041 * Same as MONO_RGCTX_INFO_CLASS_BOX_TYPE, but for the class
1042 * which implements the method.
1044 MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE = 30,
1045 /* Resolve to 2 (TRUE) or 1 (FALSE) */
1046 MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS = 31,
1047 /* The MonoDelegateTrampInfo instance */
1048 MONO_RGCTX_INFO_DELEGATE_TRAMP_INFO = 32,
1049 /* Same as MONO_PATCH_INFO_METHOD_FTNDESC */
1050 MONO_RGCTX_INFO_METHOD_FTNDESC = 33,
1051 /* mono_type_size () for a class */
1052 MONO_RGCTX_INFO_CLASS_SIZEOF = 34
1053 } MonoRgctxInfoType;
1055 typedef struct _MonoRuntimeGenericContextInfoTemplate {
1056 MonoRgctxInfoType info_type;
1057 gpointer data;
1058 struct _MonoRuntimeGenericContextInfoTemplate *next;
1059 } MonoRuntimeGenericContextInfoTemplate;
1061 typedef struct {
1062 MonoClass *next_subclass;
1063 MonoRuntimeGenericContextInfoTemplate *infos;
1064 GSList *method_templates;
1065 } MonoRuntimeGenericContextTemplate;
1067 typedef struct {
1068 MonoVTable *class_vtable; /* must be the first element */
1069 MonoGenericInst *method_inst;
1070 gpointer infos [MONO_ZERO_LEN_ARRAY];
1071 } MonoMethodRuntimeGenericContext;
1073 #define MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT (MONO_ABI_SIZEOF (MonoMethodRuntimeGenericContext) - MONO_ZERO_LEN_ARRAY * TARGET_SIZEOF_VOID_P)
1075 #define MONO_RGCTX_SLOT_MAKE_RGCTX(i) (i)
1076 #define MONO_RGCTX_SLOT_MAKE_MRGCTX(i) ((i) | 0x80000000)
1077 #define MONO_RGCTX_SLOT_INDEX(s) ((s) & 0x7fffffff)
1078 #define MONO_RGCTX_SLOT_IS_MRGCTX(s) (((s) & 0x80000000) ? TRUE : FALSE)
1080 #define MONO_GSHAREDVT_DEL_INVOKE_VT_OFFSET -2
1082 typedef struct {
1083 MonoMethod *method;
1084 MonoRuntimeGenericContextInfoTemplate *entries;
1085 int num_entries, count_entries;
1086 } MonoGSharedVtMethodInfo;
1088 /* This is used by gsharedvt methods to allocate locals and compute local offsets */
1089 typedef struct {
1090 int locals_size;
1092 * The results of resolving the entries in MOonGSharedVtMethodInfo->entries.
1093 * We use this instead of rgctx slots since these can be loaded using a load instead
1094 * of a call to an rgctx fetch trampoline.
1096 gpointer entries [MONO_ZERO_LEN_ARRAY];
1097 } MonoGSharedVtMethodRuntimeInfo;
1099 typedef struct
1101 MonoMethod *invoke;
1102 MonoMethod *method;
1103 MonoMethodSignature *invoke_sig;
1104 MonoMethodSignature *sig;
1105 gpointer method_ptr;
1106 gpointer invoke_impl;
1107 gpointer impl_this;
1108 gpointer impl_nothis;
1109 gboolean need_rgctx_tramp;
1110 } MonoDelegateTrampInfo;
1113 * A function descriptor, which is a function address + argument pair.
1114 * In llvm-only mode, these are used instead of trampolines to pass
1115 * extra arguments to runtime functions/methods.
1117 typedef struct
1119 gpointer addr;
1120 gpointer arg;
1121 } MonoFtnDesc;
1123 typedef enum {
1124 #define PATCH_INFO(a,b) MONO_PATCH_INFO_ ## a,
1125 #include "patch-info.h"
1126 #undef PATCH_INFO
1127 MONO_PATCH_INFO_NUM
1128 } MonoJumpInfoType;
1130 typedef struct MonoJumpInfoRgctxEntry MonoJumpInfoRgctxEntry;
1131 typedef struct MonoJumpInfo MonoJumpInfo;
1132 typedef struct MonoJumpInfoGSharedVtCall MonoJumpInfoGSharedVtCall;
1134 // Subset of MonoJumpInfo.
1135 typedef struct MonoJumpInfoTarget {
1136 MonoJumpInfoType type;
1137 gconstpointer target;
1138 } MonoJumpInfoTarget;
1140 // This ordering is mimiced in MONO_JIT_ICALLS.
1141 typedef enum {
1142 MONO_TRAMPOLINE_JIT = 0,
1143 MONO_TRAMPOLINE_JUMP = 1,
1144 MONO_TRAMPOLINE_RGCTX_LAZY_FETCH = 2,
1145 MONO_TRAMPOLINE_AOT = 3,
1146 MONO_TRAMPOLINE_AOT_PLT = 4,
1147 MONO_TRAMPOLINE_DELEGATE = 5,
1148 MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING = 6,
1149 MONO_TRAMPOLINE_VCALL = 7,
1150 MONO_TRAMPOLINE_NUM = 8,
1151 } MonoTrampolineType;
1153 // Assuming MONO_TRAMPOLINE_JIT / MONO_JIT_ICALL_generic_trampoline_jit are first.
1154 #if __cplusplus
1155 g_static_assert (MONO_TRAMPOLINE_JIT == 0);
1156 #endif
1157 #define mono_trampoline_type_to_jit_icall_id(a) ((a) + MONO_JIT_ICALL_generic_trampoline_jit)
1158 #define mono_jit_icall_id_to_trampoline_type(a) ((MonoTrampolineType)((a) - MONO_JIT_ICALL_generic_trampoline_jit))
1160 /* These trampolines return normally to their caller */
1161 #define MONO_TRAMPOLINE_TYPE_MUST_RETURN(t) \
1162 ((t) == MONO_TRAMPOLINE_RGCTX_LAZY_FETCH)
1164 /* These trampolines receive an argument directly in a register */
1165 #define MONO_TRAMPOLINE_TYPE_HAS_ARG(t) \
1166 (FALSE)
1168 /* optimization flags */
1169 #define OPTFLAG(id,shift,name,descr) MONO_OPT_ ## id = 1 << shift,
1170 enum {
1171 #include "optflags-def.h"
1172 MONO_OPT_LAST
1176 * This structure represents a JIT backend.
1178 typedef struct {
1179 guint have_card_table_wb : 1;
1180 guint have_op_generic_class_init : 1;
1181 guint emulate_mul_div : 1;
1182 guint emulate_div : 1;
1183 guint emulate_long_shift_opts : 1;
1184 guint have_objc_get_selector : 1;
1185 guint have_generalized_imt_trampoline : 1;
1186 gboolean have_op_tailcall_membase : 1;
1187 gboolean have_op_tailcall_reg : 1;
1188 gboolean have_volatile_non_param_register : 1;
1189 guint gshared_supported : 1;
1190 guint use_fpstack : 1;
1191 guint ilp32 : 1;
1192 guint need_got_var : 1;
1193 guint need_div_check : 1;
1194 guint no_unaligned_access : 1;
1195 guint disable_div_with_mul : 1;
1196 guint explicit_null_checks : 1;
1197 guint optimized_div : 1;
1198 int monitor_enter_adjustment;
1199 int dyn_call_param_area;
1200 } MonoBackend;
1202 /* Flags for mini_method_compile () */
1203 typedef enum {
1204 /* Whenever to run cctors during JITting */
1205 JIT_FLAG_RUN_CCTORS = (1 << 0),
1206 /* Whenever this is an AOT compilation */
1207 JIT_FLAG_AOT = (1 << 1),
1208 /* Whenever this is a full AOT compilation */
1209 JIT_FLAG_FULL_AOT = (1 << 2),
1210 /* Whenever to compile with LLVM */
1211 JIT_FLAG_LLVM = (1 << 3),
1212 /* Whenever to disable direct calls to icall functions */
1213 JIT_FLAG_NO_DIRECT_ICALLS = (1 << 4),
1214 /* Emit explicit null checks */
1215 JIT_FLAG_EXPLICIT_NULL_CHECKS = (1 << 5),
1216 /* Whenever to compile in llvm-only mode */
1217 JIT_FLAG_LLVM_ONLY = (1 << 6),
1218 /* Whenever calls to pinvoke functions are made directly */
1219 JIT_FLAG_DIRECT_PINVOKE = (1 << 7),
1220 /* Whenever this is a compile-all run and the result should be discarded */
1221 JIT_FLAG_DISCARD_RESULTS = (1 << 8),
1222 /* Whenever to generate code which can work with the interpreter */
1223 JIT_FLAG_INTERP = (1 << 9),
1224 /* Allow AOT to use all current CPU instructions */
1225 JIT_FLAG_USE_CURRENT_CPU = (1 << 10),
1226 } JitFlags;
1228 /* Bit-fields in the MonoBasicBlock.region */
1229 #define MONO_REGION_TRY 0
1230 #define MONO_REGION_FINALLY 16
1231 #define MONO_REGION_CATCH 32
1232 #define MONO_REGION_FAULT 64
1233 #define MONO_REGION_FILTER 128
1235 #define MONO_BBLOCK_IS_IN_REGION(bblock, regtype) (((bblock)->region & (0xf << 4)) == (regtype))
1237 #define MONO_REGION_FLAGS(region) ((region) & 0x7)
1238 #define MONO_REGION_CLAUSE_INDEX(region) (((region) >> 8) - 1)
1240 #define get_vreg_to_inst(cfg, vreg) ((vreg) < (cfg)->vreg_to_inst_len ? (cfg)->vreg_to_inst [(vreg)] : NULL)
1242 #define vreg_is_volatile(cfg, vreg) (G_UNLIKELY (get_vreg_to_inst ((cfg), (vreg)) && (get_vreg_to_inst ((cfg), (vreg))->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT))))
1244 #define vreg_is_ref(cfg, vreg) ((vreg) < (cfg)->vreg_is_ref_len ? (cfg)->vreg_is_ref [(vreg)] : 0)
1245 #define vreg_is_mp(cfg, vreg) ((vreg) < (cfg)->vreg_is_mp_len ? (cfg)->vreg_is_mp [(vreg)] : 0)
1248 * Control Flow Graph and compilation unit information
1250 typedef struct {
1251 MonoMethod *method;
1252 MonoMethodHeader *header;
1253 MonoMemPool *mempool;
1254 MonoInst **varinfo;
1255 MonoMethodVar *vars;
1256 MonoInst *ret;
1257 MonoBasicBlock *bb_entry;
1258 MonoBasicBlock *bb_exit;
1259 MonoBasicBlock *bb_init;
1260 MonoBasicBlock **bblocks;
1261 MonoBasicBlock **cil_offset_to_bb;
1262 MonoMemPool *state_pool; /* used by instruction selection */
1263 MonoBasicBlock *cbb; /* used by instruction selection */
1264 MonoInst *prev_ins; /* in decompose */
1265 MonoJumpInfo *patch_info;
1266 MonoJitInfo *jit_info;
1267 MonoJitDynamicMethodInfo *dynamic_info;
1268 guint num_bblocks, max_block_num;
1269 guint locals_start;
1270 guint num_varinfo; /* used items in varinfo */
1271 guint varinfo_count; /* total storage in varinfo */
1272 gint stack_offset;
1273 gint max_ireg;
1274 gint cil_offset_to_bb_len;
1275 MonoRegState *rs;
1276 MonoSpillInfo *spill_info [16]; /* machine register spills */
1277 gint spill_count;
1278 gint spill_info_len [16];
1279 /* unsigned char *cil_code; */
1280 MonoInst *domainvar; /* a cache for the current domain */
1281 MonoInst *got_var; /* Global Offset Table variable */
1282 MonoInst **locals;
1283 MonoInst *rgctx_var; /* Runtime generic context variable (for static generic methods) */
1284 MonoInst **args;
1285 MonoType **arg_types;
1286 MonoMethod *current_method; /* The method currently processed by method_to_ir () */
1287 MonoMethod *method_to_register; /* The method to register in JIT info tables */
1288 MonoGenericContext *generic_context;
1289 MonoInst *this_arg;
1291 MonoBackend *backend;
1294 * This variable represents the hidden argument holding the vtype
1295 * return address. If the method returns something other than a vtype, or
1296 * the vtype is returned in registers this is NULL.
1298 MonoInst *vret_addr;
1301 * This is used to initialize the cil_code field of MonoInst's.
1303 const unsigned char *ip;
1305 struct MonoAliasingInformation *aliasing_info;
1307 /* A hashtable of region ID-> SP var mappings */
1308 /* An SP var is a place to store the stack pointer (used by handlers)*/
1310 * FIXME We can potentially get rid of this, since it was mainly used
1311 * for hijacking return address for handler.
1313 GHashTable *spvars;
1316 * A hashtable of region ID -> EX var mappings
1317 * An EX var stores the exception object passed to catch/filter blocks
1318 * For finally blocks, it is set to TRUE if we should throw an abort
1319 * once the execution of the finally block is over.
1321 GHashTable *exvars;
1323 GList *ldstr_list; /* used by AOT */
1325 MonoDomain *domain;
1327 guint real_offset;
1328 GHashTable *cbb_hash;
1330 /* The current virtual register number */
1331 guint32 next_vreg;
1333 MonoGenericSharingContext gsctx;
1334 MonoGenericContext *gsctx_context;
1336 MonoGSharedVtMethodInfo *gsharedvt_info;
1338 /* Points to the gsharedvt locals area at runtime */
1339 MonoInst *gsharedvt_locals_var;
1341 /* The localloc instruction used to initialize gsharedvt_locals_var */
1342 MonoInst *gsharedvt_locals_var_ins;
1344 /* Points to a MonoGSharedVtMethodRuntimeInfo at runtime */
1345 MonoInst *gsharedvt_info_var;
1347 /* For native-to-managed wrappers, CEE_MONO_JIT_(AT|DE)TACH opcodes */
1348 MonoInst *orig_domain_var;
1350 MonoInst *lmf_var;
1351 MonoInst *lmf_addr_var;
1353 MonoInst *stack_inbalance_var;
1355 unsigned char *cil_start;
1356 unsigned char *native_code;
1357 guint code_size;
1358 guint code_len;
1359 guint prolog_end;
1360 guint epilog_begin;
1361 guint epilog_end;
1362 regmask_t used_int_regs;
1363 guint32 opt;
1364 guint32 flags;
1365 guint32 comp_done;
1366 guint32 verbose_level;
1367 guint32 stack_usage;
1368 guint32 param_area;
1369 guint32 frame_reg;
1370 gint32 sig_cookie;
1371 guint disable_aot : 1;
1372 guint disable_ssa : 1;
1373 guint disable_llvm : 1;
1374 guint enable_extended_bblocks : 1;
1375 guint run_cctors : 1;
1376 guint need_lmf_area : 1;
1377 guint compile_aot : 1;
1378 guint full_aot : 1;
1379 guint compile_llvm : 1;
1380 guint got_var_allocated : 1;
1381 guint ret_var_is_local : 1;
1382 guint ret_var_set : 1;
1383 guint unverifiable : 1;
1384 guint skip_visibility : 1;
1385 guint disable_reuse_registers : 1;
1386 guint disable_reuse_stack_slots : 1;
1387 guint disable_reuse_ref_stack_slots : 1;
1388 guint disable_ref_noref_stack_slot_share : 1;
1389 guint disable_initlocals_opt : 1;
1390 guint disable_initlocals_opt_refs : 1;
1391 guint disable_omit_fp : 1;
1392 guint disable_vreg_to_lvreg : 1;
1393 guint disable_deadce_vars : 1;
1394 guint disable_out_of_line_bblocks : 1;
1395 guint disable_direct_icalls : 1;
1396 guint disable_gc_safe_points : 1;
1397 guint direct_pinvoke : 1;
1398 guint create_lmf_var : 1;
1400 * When this is set, the code to push/pop the LMF from the LMF stack is generated as IR
1401 * instead of being generated in emit_prolog ()/emit_epilog ().
1403 guint lmf_ir : 1;
1405 * Whenever to use the mono_lmf TLS variable instead of indirection through the
1406 * mono_lmf_addr TLS variable.
1408 guint gen_write_barriers : 1;
1409 guint init_ref_vars : 1;
1410 guint extend_live_ranges : 1;
1411 guint compute_precise_live_ranges : 1;
1412 guint has_got_slots : 1;
1413 guint uses_rgctx_reg : 1;
1414 guint uses_vtable_reg : 1;
1415 guint keep_cil_nops : 1;
1416 guint gen_seq_points : 1;
1417 /* Generate seq points for use by the debugger */
1418 guint gen_sdb_seq_points : 1;
1419 guint explicit_null_checks : 1;
1420 guint compute_gc_maps : 1;
1421 guint soft_breakpoints : 1;
1422 guint arch_eh_jit_info : 1;
1423 guint has_calls : 1;
1424 guint has_emulated_ops : 1;
1425 guint has_indirection : 1;
1426 guint has_atomic_add_i4 : 1;
1427 guint has_atomic_exchange_i4 : 1;
1428 guint has_atomic_cas_i4 : 1;
1429 guint check_pinvoke_callconv : 1;
1430 guint has_unwind_info_for_epilog : 1;
1431 guint disable_inline : 1;
1432 /* Disable inlining into caller */
1433 guint no_inline : 1;
1434 guint gshared : 1;
1435 guint gsharedvt : 1;
1436 guint r4fp : 1;
1437 guint llvm_only : 1;
1438 guint interp : 1;
1439 guint use_current_cpu : 1;
1440 guint domainvar_inited : 1;
1441 guint8 uses_simd_intrinsics;
1442 int r4_stack_type;
1443 gpointer debug_info;
1444 guint32 lmf_offset;
1445 guint16 *intvars;
1446 MonoProfilerCoverageInfo *coverage_info;
1447 GHashTable *token_info_hash;
1448 MonoCompileArch arch;
1449 guint32 inline_depth;
1450 /* Size of memory reserved for thunks */
1451 int thunk_area;
1452 /* Thunks */
1453 guint8 *thunks;
1454 /* Offset between the start of code and the thunks area */
1455 int thunks_offset;
1456 MonoExceptionType exception_type; /* MONO_EXCEPTION_* */
1457 guint32 exception_data;
1458 char* exception_message;
1459 gpointer exception_ptr;
1461 guint8 * encoded_unwind_ops;
1462 guint32 encoded_unwind_ops_len;
1463 GSList* unwind_ops;
1465 GList* dont_inline;
1467 /* Fields used by the local reg allocator */
1468 void* reginfo;
1469 int reginfo_len;
1471 /* Maps vregs to their associated MonoInst's */
1472 /* vregs with an associated MonoInst are 'global' while others are 'local' */
1473 MonoInst **vreg_to_inst;
1475 /* Size of above array */
1476 guint32 vreg_to_inst_len;
1478 /* Marks vregs which hold a GC ref */
1479 /* FIXME: Use a bitmap */
1480 gboolean *vreg_is_ref;
1482 /* Size of above array */
1483 guint32 vreg_is_ref_len;
1485 /* Marks vregs which hold a managed pointer */
1486 /* FIXME: Use a bitmap */
1487 gboolean *vreg_is_mp;
1489 /* Size of above array */
1490 guint32 vreg_is_mp_len;
1493 * The original method to compile, differs from 'method' when doing generic
1494 * sharing.
1496 MonoMethod *orig_method;
1498 /* Patches which describe absolute addresses embedded into the native code */
1499 GHashTable *abs_patches;
1501 /* Used to implement move_i4_to_f on archs that can't do raw
1502 copy between an ireg and a freg. This is an int32 var.*/
1503 MonoInst *iconv_raw_var;
1505 /* Used to implement fconv_to_r8_x. This is a double (8 bytes) var.*/
1506 MonoInst *fconv_to_r8_x_var;
1508 /*Use to implement simd constructors. This is a vector (16 bytes) var.*/
1509 MonoInst *simd_ctor_var;
1511 /* Used to implement dyn_call */
1512 MonoInst *dyn_call_var;
1514 MonoInst *last_seq_point;
1516 * List of sequence points represented as IL offset+native offset pairs.
1517 * Allocated using glib.
1518 * IL offset can be -1 or 0xffffff to refer to the sequence points
1519 * inside the prolog and epilog used to implement method entry/exit events.
1521 GPtrArray *seq_points;
1523 /* The encoded sequence point info */
1524 struct MonoSeqPointInfo *seq_point_info;
1526 /* Method headers which need to be freed after compilation */
1527 GSList *headers_to_free;
1529 /* Used by AOT */
1530 guint32 got_offset, ex_info_offset, method_info_offset, method_index;
1531 /* For llvm */
1532 guint32 got_access_count;
1533 gpointer llvmonly_init_cond;
1534 /* Symbol used to refer to this method in generated assembly */
1535 char *asm_symbol;
1536 char *asm_debug_symbol;
1537 char *llvm_method_name;
1538 int castclass_cache_index;
1540 MonoJitExceptionInfo *llvm_ex_info;
1541 guint32 llvm_ex_info_len;
1542 int llvm_this_reg, llvm_this_offset;
1544 GSList *try_block_holes;
1546 /* DWARF location list for 'this' */
1547 GSList *this_loclist;
1549 /* DWARF location list for 'rgctx_var' */
1550 GSList *rgctx_loclist;
1552 int *gsharedvt_vreg_to_idx;
1554 GSList *signatures;
1555 GSList *interp_in_signatures;
1557 /* GC Maps */
1559 /* The offsets of the locals area relative to the frame pointer */
1560 gint locals_min_stack_offset, locals_max_stack_offset;
1562 /* The current CFA rule */
1563 int cur_cfa_reg, cur_cfa_offset;
1565 /* The final CFA rule at the end of the prolog */
1566 int cfa_reg, cfa_offset;
1568 /* Points to a MonoCompileGC */
1569 gpointer gc_info;
1572 * The encoded GC map along with its size. This contains binary data so it can be saved in an AOT
1573 * image etc, but it requires a 4 byte alignment.
1575 guint8 *gc_map;
1576 guint32 gc_map_size;
1578 /* Error handling */
1579 MonoError* error;
1580 MonoErrorInternal error_value;
1582 /* pointer to context datastructure used for graph dumping */
1583 MonoGraphDumper *gdump_ctx;
1585 /* Stats */
1586 int stat_allocate_var;
1587 int stat_locals_stack_size;
1588 int stat_basic_blocks;
1589 int stat_cil_code_size;
1590 int stat_n_regvars;
1591 int stat_inlineable_methods;
1592 int stat_inlined_methods;
1593 int stat_code_reallocs;
1595 MonoProfilerCallInstrumentationFlags prof_flags;
1596 gboolean prof_coverage;
1598 /* For deduplication */
1599 gboolean skip;
1600 } MonoCompile;
1602 #define MONO_CFG_PROFILE(cfg, flag) \
1603 G_UNLIKELY ((cfg)->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_ ## flag)
1605 #define MONO_CFG_PROFILE_CALL_CONTEXT(cfg) \
1606 (MONO_CFG_PROFILE (cfg, ENTER_CONTEXT) || MONO_CFG_PROFILE (cfg, LEAVE_CONTEXT))
1608 typedef enum {
1609 MONO_CFG_HAS_ALLOCA = 1 << 0,
1610 MONO_CFG_HAS_CALLS = 1 << 1,
1611 MONO_CFG_HAS_LDELEMA = 1 << 2,
1612 MONO_CFG_HAS_VARARGS = 1 << 3,
1613 MONO_CFG_HAS_TAILCALL = 1 << 4,
1614 MONO_CFG_HAS_FPOUT = 1 << 5, /* there are fp values passed in int registers */
1615 MONO_CFG_HAS_SPILLUP = 1 << 6, /* spill var slots are allocated from bottom to top */
1616 MONO_CFG_HAS_CHECK_THIS = 1 << 7,
1617 MONO_CFG_NEEDS_DECOMPOSE = 1 << 8,
1618 MONO_CFG_HAS_TYPE_CHECK = 1 << 9
1619 } MonoCompileFlags;
1621 typedef enum {
1622 MONO_CFG_USES_SIMD_INTRINSICS = 1 << 0,
1623 MONO_CFG_USES_SIMD_INTRINSICS_SIMPLIFY_INDIRECTION = 1 << 1,
1624 MONO_CFG_USES_SIMD_INTRINSICS_DECOMPOSE_VTYPE = 1 << 2
1625 } MonoSimdIntrinsicsFlags;
1627 typedef struct {
1628 gint32 methods_compiled;
1629 gint32 methods_aot;
1630 gint32 methods_aot_llvm;
1631 gint32 methods_lookups;
1632 gint32 allocate_var;
1633 gint32 cil_code_size;
1634 gint32 native_code_size;
1635 gint32 code_reallocs;
1636 gint32 max_code_size_ratio;
1637 gint32 biggest_method_size;
1638 gint32 allocated_code_size;
1639 gint32 allocated_seq_points_size;
1640 gint32 inlineable_methods;
1641 gint32 inlined_methods;
1642 gint32 basic_blocks;
1643 gint32 max_basic_blocks;
1644 gint32 locals_stack_size;
1645 gint32 regvars;
1646 gint32 generic_virtual_invocations;
1647 gint32 alias_found;
1648 gint32 alias_removed;
1649 gint32 loads_eliminated;
1650 gint32 stores_eliminated;
1651 gint32 optimized_divisions;
1652 gint32 methods_with_llvm;
1653 gint32 methods_without_llvm;
1654 gint32 methods_with_interp;
1655 char *max_ratio_method;
1656 char *biggest_method;
1657 gint64 jit_method_to_ir;
1658 gint64 jit_liveness_handle_exception_clauses;
1659 gint64 jit_handle_out_of_line_bblock;
1660 gint64 jit_decompose_long_opts;
1661 gint64 jit_decompose_typechecks;
1662 gint64 jit_local_cprop;
1663 gint64 jit_local_emulate_ops;
1664 gint64 jit_optimize_branches;
1665 gint64 jit_handle_global_vregs;
1666 gint64 jit_local_deadce;
1667 gint64 jit_local_alias_analysis;
1668 gint64 jit_if_conversion;
1669 gint64 jit_bb_ordering;
1670 gint64 jit_compile_dominator_info;
1671 gint64 jit_compute_natural_loops;
1672 gint64 jit_insert_safepoints;
1673 gint64 jit_ssa_compute;
1674 gint64 jit_ssa_cprop;
1675 gint64 jit_ssa_deadce;
1676 gint64 jit_perform_abc_removal;
1677 gint64 jit_ssa_remove;
1678 gint64 jit_local_cprop2;
1679 gint64 jit_handle_global_vregs2;
1680 gint64 jit_local_deadce2;
1681 gint64 jit_optimize_branches2;
1682 gint64 jit_decompose_vtype_opts;
1683 gint64 jit_decompose_array_access_opts;
1684 gint64 jit_liveness_handle_exception_clauses2;
1685 gint64 jit_analyze_liveness;
1686 gint64 jit_linear_scan;
1687 gint64 jit_arch_allocate_vars;
1688 gint64 jit_spill_global_vars;
1689 gint64 jit_local_cprop3;
1690 gint64 jit_local_deadce3;
1691 gint64 jit_codegen;
1692 gint64 jit_create_jit_info;
1693 gint64 jit_gc_create_gc_map;
1694 gint64 jit_save_seq_point_info;
1695 gint64 jit_time;
1696 gboolean enabled;
1697 } MonoJitStats;
1699 extern MonoJitStats mono_jit_stats;
1701 /* opcodes: value assigned after all the CIL opcodes */
1702 #ifdef MINI_OP
1703 #undef MINI_OP
1704 #endif
1705 #ifdef MINI_OP3
1706 #undef MINI_OP3
1707 #endif
1708 #define MINI_OP(a,b,dest,src1,src2) a,
1709 #define MINI_OP3(a,b,dest,src1,src2,src3) a,
1710 enum {
1711 OP_START = MONO_CEE_LAST - 1,
1712 #include "mini-ops.h"
1713 OP_LAST
1715 #undef MINI_OP
1716 #undef MINI_OP3
1718 #if TARGET_SIZEOF_VOID_P == 8
1719 #define OP_PCONST OP_I8CONST
1720 #define OP_DUMMY_PCONST OP_DUMMY_I8CONST
1721 #define OP_PADD OP_LADD
1722 #define OP_PADD_IMM OP_LADD_IMM
1723 #define OP_PSUB_IMM OP_LSUB_IMM
1724 #define OP_PAND_IMM OP_LAND_IMM
1725 #define OP_PXOR_IMM OP_LXOR_IMM
1726 #define OP_PSUB OP_LSUB
1727 #define OP_PMUL OP_LMUL
1728 #define OP_PMUL_IMM OP_LMUL_IMM
1729 #define OP_PNEG OP_LNEG
1730 #define OP_PCONV_TO_I1 OP_LCONV_TO_I1
1731 #define OP_PCONV_TO_U1 OP_LCONV_TO_U1
1732 #define OP_PCONV_TO_I2 OP_LCONV_TO_I2
1733 #define OP_PCONV_TO_U2 OP_LCONV_TO_U2
1734 #define OP_PCONV_TO_OVF_I1_UN OP_LCONV_TO_OVF_I1_UN
1735 #define OP_PCONV_TO_OVF_I1 OP_LCONV_TO_OVF_I1
1736 #define OP_PBEQ OP_LBEQ
1737 #define OP_PCEQ OP_LCEQ
1738 #define OP_PCLT OP_LCLT
1739 #define OP_PCGT OP_LCGT
1740 #define OP_PCLT_UN OP_LCLT_UN
1741 #define OP_PCGT_UN OP_LCGT_UN
1742 #define OP_PBNE_UN OP_LBNE_UN
1743 #define OP_PBGE_UN OP_LBGE_UN
1744 #define OP_PBLT_UN OP_LBLT_UN
1745 #define OP_PBGE OP_LBGE
1746 #define OP_STOREP_MEMBASE_REG OP_STOREI8_MEMBASE_REG
1747 #define OP_STOREP_MEMBASE_IMM OP_STOREI8_MEMBASE_IMM
1748 #else
1749 #define OP_PCONST OP_ICONST
1750 #define OP_DUMMY_PCONST OP_DUMMY_ICONST
1751 #define OP_PADD OP_IADD
1752 #define OP_PADD_IMM OP_IADD_IMM
1753 #define OP_PSUB_IMM OP_ISUB_IMM
1754 #define OP_PAND_IMM OP_IAND_IMM
1755 #define OP_PXOR_IMM OP_IXOR_IMM
1756 #define OP_PSUB OP_ISUB
1757 #define OP_PMUL OP_IMUL
1758 #define OP_PMUL_IMM OP_IMUL_IMM
1759 #define OP_PNEG OP_INEG
1760 #define OP_PCONV_TO_I1 OP_ICONV_TO_I1
1761 #define OP_PCONV_TO_U1 OP_ICONV_TO_U1
1762 #define OP_PCONV_TO_I2 OP_ICONV_TO_I2
1763 #define OP_PCONV_TO_U2 OP_ICONV_TO_U2
1764 #define OP_PCONV_TO_OVF_I1_UN OP_ICONV_TO_OVF_I1_UN
1765 #define OP_PCONV_TO_OVF_I1 OP_ICONV_TO_OVF_I1
1766 #define OP_PBEQ OP_IBEQ
1767 #define OP_PCEQ OP_ICEQ
1768 #define OP_PCLT OP_ICLT
1769 #define OP_PCGT OP_ICGT
1770 #define OP_PCLT_UN OP_ICLT_UN
1771 #define OP_PCGT_UN OP_ICGT_UN
1772 #define OP_PBNE_UN OP_IBNE_UN
1773 #define OP_PBGE_UN OP_IBGE_UN
1774 #define OP_PBLT_UN OP_IBLT_UN
1775 #define OP_PBGE OP_IBGE
1776 #define OP_STOREP_MEMBASE_REG OP_STOREI4_MEMBASE_REG
1777 #define OP_STOREP_MEMBASE_IMM OP_STOREI4_MEMBASE_IMM
1778 #endif
1780 /* Opcodes to load/store regsize quantities */
1781 #if defined (MONO_ARCH_ILP32)
1782 #define OP_LOADR_MEMBASE OP_LOADI8_MEMBASE
1783 #define OP_STORER_MEMBASE_REG OP_STOREI8_MEMBASE_REG
1784 #else
1785 #define OP_LOADR_MEMBASE OP_LOAD_MEMBASE
1786 #define OP_STORER_MEMBASE_REG OP_STORE_MEMBASE_REG
1787 #endif
1789 typedef enum {
1790 STACK_INV,
1791 STACK_I4,
1792 STACK_I8,
1793 STACK_PTR,
1794 STACK_R8,
1795 STACK_MP,
1796 STACK_OBJ,
1797 STACK_VTYPE,
1798 STACK_R4,
1799 STACK_MAX
1800 } MonoStackType;
1802 typedef struct {
1803 union {
1804 double r8;
1805 gint32 i4;
1806 gint64 i8;
1807 gpointer p;
1808 MonoClass *klass;
1809 } data;
1810 int type;
1811 } StackSlot;
1813 extern const MonoInstSpec MONO_ARCH_CPU_SPEC [];
1814 #define MONO_ARCH_CPU_SPEC_IDX_COMBINE(a) a ## _idx
1815 #define MONO_ARCH_CPU_SPEC_IDX(a) MONO_ARCH_CPU_SPEC_IDX_COMBINE(a)
1816 extern const guint16 MONO_ARCH_CPU_SPEC_IDX(MONO_ARCH_CPU_SPEC) [];
1817 #define ins_get_spec(op) ((const char*)&MONO_ARCH_CPU_SPEC [MONO_ARCH_CPU_SPEC_IDX(MONO_ARCH_CPU_SPEC)[(op) - OP_LOAD]])
1819 #ifndef DISABLE_JIT
1821 static inline int
1822 ins_get_size (int opcode)
1824 return ((guint8 *)ins_get_spec (opcode))[MONO_INST_LEN];
1827 guint8*
1828 mini_realloc_code_slow (MonoCompile *cfg, int size);
1830 static inline guint8*
1831 realloc_code (MonoCompile *cfg, int size)
1833 const int EXTRA_CODE_SPACE = 16;
1834 const int code_len = cfg->code_len;
1836 if (G_UNLIKELY (code_len + size > (cfg->code_size - EXTRA_CODE_SPACE)))
1837 return mini_realloc_code_slow (cfg, size);
1838 return cfg->native_code + code_len;
1841 static inline void
1842 set_code_len (MonoCompile *cfg, int len)
1844 g_assert (len <= cfg->code_size);
1845 cfg->code_len = len;
1848 static inline void
1849 set_code_cursor (MonoCompile *cfg, void* void_code)
1851 guint8* code = (guint8*)void_code;
1852 g_assert (code <= (cfg->native_code + cfg->code_size));
1853 set_code_len (cfg, code - cfg->native_code);
1856 #endif
1858 enum {
1859 MONO_COMP_DOM = 1,
1860 MONO_COMP_IDOM = 2,
1861 MONO_COMP_DFRONTIER = 4,
1862 MONO_COMP_DOM_REV = 8,
1863 MONO_COMP_LIVENESS = 16,
1864 MONO_COMP_SSA = 32,
1865 MONO_COMP_SSA_DEF_USE = 64,
1866 MONO_COMP_REACHABILITY = 128,
1867 MONO_COMP_LOOPS = 256
1870 typedef enum {
1871 MONO_GRAPH_CFG = 1,
1872 MONO_GRAPH_DTREE = 2,
1873 MONO_GRAPH_CFG_CODE = 4,
1874 MONO_GRAPH_CFG_SSA = 8,
1875 MONO_GRAPH_CFG_OPTCODE = 16
1876 } MonoGraphOptions;
1878 typedef struct {
1879 guint16 size;
1880 guint16 offset;
1881 guint8 pad;
1882 } MonoJitArgumentInfo;
1884 enum {
1885 BRANCH_NOT_TAKEN,
1886 BRANCH_TAKEN,
1887 BRANCH_UNDEF
1890 typedef enum {
1891 CMP_EQ,
1892 CMP_NE,
1893 CMP_LE,
1894 CMP_GE,
1895 CMP_LT,
1896 CMP_GT,
1897 CMP_LE_UN,
1898 CMP_GE_UN,
1899 CMP_LT_UN,
1900 CMP_GT_UN
1901 } CompRelation;
1903 typedef enum {
1904 CMP_TYPE_L,
1905 CMP_TYPE_I,
1906 CMP_TYPE_F
1907 } CompType;
1909 /* Implicit exceptions */
1910 enum {
1911 MONO_EXC_INDEX_OUT_OF_RANGE,
1912 MONO_EXC_OVERFLOW,
1913 MONO_EXC_ARITHMETIC,
1914 MONO_EXC_DIVIDE_BY_ZERO,
1915 MONO_EXC_INVALID_CAST,
1916 MONO_EXC_NULL_REF,
1917 MONO_EXC_ARRAY_TYPE_MISMATCH,
1918 MONO_EXC_ARGUMENT,
1919 MONO_EXC_ARGUMENT_OUT_OF_RANGE,
1920 MONO_EXC_INTRINS_NUM
1924 * Information about a trampoline function.
1926 struct MonoTrampInfo
1929 * The native code of the trampoline. Not owned by this structure.
1931 guint8 *code;
1932 guint32 code_size;
1934 * The name of the trampoline which can be used in AOT/xdebug. Owned by this
1935 * structure.
1937 char *name;
1939 * Patches required by the trampoline when aot-ing. Owned by this structure.
1941 MonoJumpInfo *ji;
1943 * Unwind information. Owned by this structure.
1945 GSList *unwind_ops;
1947 MonoJitICallInfo *jit_icall_info;
1950 * Encoded unwind info loaded from AOT images
1952 guint8 *uw_info;
1953 guint32 uw_info_len;
1954 /* Whenever uw_info is owned by this structure */
1955 gboolean owns_uw_info;
1958 typedef void (*MonoInstFunc) (MonoInst *tree, gpointer data);
1960 enum {
1961 FILTER_IL_SEQ_POINT = 1 << 0,
1962 FILTER_NOP = 1 << 1,
1965 static inline gboolean
1966 mono_inst_filter (MonoInst *ins, int filter)
1968 if (!ins || !filter)
1969 return FALSE;
1971 if ((filter & FILTER_IL_SEQ_POINT) && ins->opcode == OP_IL_SEQ_POINT)
1972 return TRUE;
1974 if ((filter & FILTER_NOP) && ins->opcode == OP_NOP)
1975 return TRUE;
1977 return FALSE;
1980 static inline MonoInst*
1981 mono_inst_next (MonoInst *ins, int filter)
1983 do {
1984 ins = ins->next;
1985 } while (mono_inst_filter (ins, filter));
1987 return ins;
1990 static inline MonoInst*
1991 mono_inst_prev (MonoInst *ins, int filter)
1993 do {
1994 ins = ins->prev;
1995 } while (mono_inst_filter (ins, filter));
1997 return ins;
2000 static inline MonoInst*
2001 mono_bb_first_inst (MonoBasicBlock *bb, int filter)
2003 MonoInst *ins = bb->code;
2004 if (mono_inst_filter (ins, filter))
2005 ins = mono_inst_next (ins, filter);
2007 return ins;
2010 static inline MonoInst*
2011 mono_bb_last_inst (MonoBasicBlock *bb, int filter)
2013 MonoInst *ins = bb->last_ins;
2014 if (mono_inst_filter (ins, filter))
2015 ins = mono_inst_prev (ins, filter);
2017 return ins;
2020 /* profiler support */
2021 void mini_add_profiler_argument (const char *desc);
2022 void mini_profiler_emit_enter (MonoCompile *cfg);
2023 void mini_profiler_emit_leave (MonoCompile *cfg, MonoInst *ret);
2024 void mini_profiler_emit_tail_call (MonoCompile *cfg, MonoMethod *target);
2025 void mini_profiler_emit_call_finally (MonoCompile *cfg, MonoMethodHeader *header, unsigned char *ip, guint32 index, MonoExceptionClause *clause);
2026 void mini_profiler_context_enable (void);
2027 gpointer mini_profiler_context_get_this (MonoProfilerCallContext *ctx);
2028 gpointer mini_profiler_context_get_argument (MonoProfilerCallContext *ctx, guint32 pos);
2029 gpointer mini_profiler_context_get_local (MonoProfilerCallContext *ctx, guint32 pos);
2030 gpointer mini_profiler_context_get_result (MonoProfilerCallContext *ctx);
2031 void mini_profiler_context_free_buffer (gpointer buffer);
2033 /* graph dumping */
2034 void mono_cfg_dump_create_context (MonoCompile *cfg);
2035 void mono_cfg_dump_begin_group (MonoCompile *cfg);
2036 void mono_cfg_dump_close_group (MonoCompile *cfg);
2037 void mono_cfg_dump_ir (MonoCompile *cfg, const char *phase_name);
2039 /* helper methods */
2040 MonoInst* mono_find_spvar_for_region (MonoCompile *cfg, int region);
2041 MonoInst* mono_find_exvar_for_offset (MonoCompile *cfg, int offset);
2042 MONO_LLVM_INTERNAL int mono_get_block_region_notry (MonoCompile *cfg, int region);
2044 MONO_LLVM_INTERNAL void mono_bblock_add_inst (MonoBasicBlock *bb, MonoInst *inst);
2045 void mono_bblock_insert_after_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *ins_to_insert);
2046 void mono_bblock_insert_before_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *ins_to_insert);
2047 void mono_verify_bblock (MonoBasicBlock *bb);
2048 void mono_verify_cfg (MonoCompile *cfg);
2049 void mono_constant_fold (MonoCompile *cfg);
2050 MonoInst* mono_constant_fold_ins (MonoCompile *cfg, MonoInst *ins, MonoInst *arg1, MonoInst *arg2, gboolean overwrite);
2051 int mono_eval_cond_branch (MonoInst *branch);
2052 MONO_LLVM_INTERNAL int mono_is_power_of_two (guint32 val);
2053 void mono_cprop_local (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **acp, int acp_size);
2054 MONO_LLVM_INTERNAL MonoInst* mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode);
2055 MonoInst* mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, int vreg);
2056 void mono_compile_make_var_load (MonoCompile *cfg, MonoInst *dest, gssize var_index);
2057 MonoInst* mini_get_int_to_float_spill_area (MonoCompile *cfg);
2058 MonoType* mono_type_from_stack_type (MonoInst *ins);
2059 MONO_LLVM_INTERNAL guint32 mono_alloc_ireg (MonoCompile *cfg);
2060 MONO_LLVM_INTERNAL guint32 mono_alloc_lreg (MonoCompile *cfg);
2061 MONO_LLVM_INTERNAL guint32 mono_alloc_freg (MonoCompile *cfg);
2062 MONO_LLVM_INTERNAL guint32 mono_alloc_preg (MonoCompile *cfg);
2063 guint32 mono_alloc_dreg (MonoCompile *cfg, MonoStackType stack_type);
2064 MONO_LLVM_INTERNAL guint32 mono_alloc_ireg_ref (MonoCompile *cfg);
2065 MONO_LLVM_INTERNAL guint32 mono_alloc_ireg_mp (MonoCompile *cfg);
2066 MONO_LLVM_INTERNAL guint32 mono_alloc_ireg_copy (MonoCompile *cfg, guint32 vreg);
2067 void mono_mark_vreg_as_ref (MonoCompile *cfg, int vreg);
2068 void mono_mark_vreg_as_mp (MonoCompile *cfg, int vreg);
2070 void mono_link_bblock (MonoCompile *cfg, MonoBasicBlock *from, MonoBasicBlock* to);
2071 void mono_unlink_bblock (MonoCompile *cfg, MonoBasicBlock *from, MonoBasicBlock* to);
2072 gboolean mono_bblocks_linked (MonoBasicBlock *bb1, MonoBasicBlock *bb2);
2073 void mono_remove_bblock (MonoCompile *cfg, MonoBasicBlock *bb);
2074 void mono_nullify_basic_block (MonoBasicBlock *bb);
2075 void mono_merge_basic_blocks (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *bbn);
2076 void mono_optimize_branches (MonoCompile *cfg);
2078 void mono_blockset_print (MonoCompile *cfg, MonoBitSet *set, const char *name, guint idom);
2079 void mono_print_ins_index (int i, MonoInst *ins);
2080 GString *mono_print_ins_index_strbuf (int i, MonoInst *ins);
2081 MONO_LLVM_INTERNAL void mono_print_ins (MonoInst *ins);
2082 void mono_print_bb (MonoBasicBlock *bb, const char *msg);
2083 void mono_print_code (MonoCompile *cfg, const char *msg);
2084 MONO_LLVM_INTERNAL const char* mono_inst_name (int op);
2085 int mono_op_to_op_imm (int opcode);
2086 int mono_op_imm_to_op (int opcode);
2087 int mono_load_membase_to_load_mem (int opcode);
2088 guint mono_type_to_load_membase (MonoCompile *cfg, MonoType *type);
2089 guint mono_type_to_store_membase (MonoCompile *cfg, MonoType *type);
2090 guint32 mono_type_to_stloc_coerce (MonoType *type);
2091 guint mini_type_to_stind (MonoCompile* cfg, MonoType *type);
2092 MonoJitInfo* mini_lookup_method (MonoDomain *domain, MonoMethod *method, MonoMethod *shared);
2093 guint32 mono_reverse_branch_op (guint32 opcode);
2094 void mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id);
2095 MonoJumpInfoTarget mono_call_to_patch (MonoCallInst *call);
2096 void mono_call_add_patch_info (MonoCompile *cfg, MonoCallInst *call, int ip);
2097 MONO_LLVM_INTERNAL void mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target);
2098 MONO_LLVM_INTERNAL void mono_add_patch_info_rel (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target, int relocation);
2099 void mono_remove_patch_info (MonoCompile *cfg, int ip);
2100 gpointer mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoError *error);
2101 GList *mono_varlist_insert_sorted (MonoCompile *cfg, GList *list, MonoMethodVar *mv, int sort_type);
2102 GList *mono_varlist_sort (MonoCompile *cfg, GList *list, int sort_type);
2103 void mono_analyze_liveness (MonoCompile *cfg);
2104 void mono_analyze_liveness_gc (MonoCompile *cfg);
2105 void mono_linear_scan (MonoCompile *cfg, GList *vars, GList *regs, regmask_t *used_mask);
2106 void mono_global_regalloc (MonoCompile *cfg);
2107 void mono_create_jump_table (MonoCompile *cfg, MonoInst *label, MonoBasicBlock **bbs, int num_blocks);
2108 MonoCompile *mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts, int aot_method_index);
2109 void mono_destroy_compile (MonoCompile *cfg);
2110 void mono_empty_compile (MonoCompile *cfg);
2111 MonoJitICallInfo *mono_find_jit_opcode_emulation (int opcode);
2112 void mono_print_ins_index (int i, MonoInst *ins);
2113 void mono_print_ins (MonoInst *ins);
2114 gboolean mini_assembly_can_skip_verification (MonoDomain *domain, MonoMethod *method);
2115 gboolean mono_compile_is_broken (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile);
2116 MonoInst *mono_get_got_var (MonoCompile *cfg);
2117 void mono_add_seq_point (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, int native_offset);
2118 void mono_add_var_location (MonoCompile *cfg, MonoInst *var, gboolean is_reg, int reg, int offset, int from, int to);
2119 MonoInst* mono_emit_jit_icall_id (MonoCompile *cfg, MonoJitICallId jit_icall_id, MonoInst **args);
2120 #define mono_emit_jit_icall(cfg, name, args) (mono_emit_jit_icall_id ((cfg), MONO_JIT_ICALL_ ## name, (args)))
2122 MonoInst* mono_emit_jit_icall_by_info (MonoCompile *cfg, int il_offset, MonoJitICallInfo *info, MonoInst **args);
2123 MonoInst* mono_emit_method_call (MonoCompile *cfg, MonoMethod *method, MonoInst **args, MonoInst *this_ins);
2124 gboolean mini_should_insert_breakpoint (MonoMethod *method);
2125 int mono_target_pagesize (void);
2127 gboolean mini_class_is_system_array (MonoClass *klass);
2129 void mono_linterval_add_range (MonoCompile *cfg, MonoLiveInterval *interval, int from, int to);
2130 void mono_linterval_print (MonoLiveInterval *interval);
2131 void mono_linterval_print_nl (MonoLiveInterval *interval);
2132 gboolean mono_linterval_covers (MonoLiveInterval *interval, int pos);
2133 gint32 mono_linterval_get_intersect_pos (MonoLiveInterval *i1, MonoLiveInterval *i2);
2134 void mono_linterval_split (MonoCompile *cfg, MonoLiveInterval *interval, MonoLiveInterval **i1, MonoLiveInterval **i2, int pos);
2135 void mono_liveness_handle_exception_clauses (MonoCompile *cfg);
2137 gpointer mono_realloc_native_code (MonoCompile *cfg);
2139 void mono_xdebug_init (const char *xdebug_opts);
2140 void mono_save_xdebug_info (MonoCompile *cfg);
2141 void mono_save_trampoline_xdebug_info (MonoTrampInfo *info);
2142 /* This is an exported function */
2143 void mono_xdebug_flush (void);
2145 void mono_register_opcode_emulation (int opcode, const char* name, MonoMethodSignature *sig, gpointer func, gboolean no_throw);
2146 void mono_draw_graph (MonoCompile *cfg, MonoGraphOptions draw_options);
2147 void mono_add_ins_to_end (MonoBasicBlock *bb, MonoInst *inst);
2149 void mono_replace_ins (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, MonoInst **prev, MonoBasicBlock *first_bb, MonoBasicBlock *last_bb);
2151 void mini_register_opcode_emulation (int opcode, MonoJitICallInfo *jit_icall_info, const char *name, MonoMethodSignature *sig, gpointer func, const char *symbol, gboolean no_throw);
2153 #ifdef __cplusplus
2154 template <typename T>
2155 inline void
2156 mini_register_opcode_emulation (int opcode, MonoJitICallInfo *jit_icall_info, const char *name, MonoMethodSignature *sig, T func, const char *symbol, gboolean no_throw)
2158 mini_register_opcode_emulation (opcode, jit_icall_info, name, sig, (gpointer)func, symbol, no_throw);
2160 #endif // __cplusplus
2162 void mono_trampolines_init (void);
2163 void mono_trampolines_cleanup (void);
2164 guint8 * mono_get_trampoline_code (MonoTrampolineType tramp_type);
2165 gpointer mono_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len);
2166 gpointer mono_create_jump_trampoline (MonoDomain *domain,
2167 MonoMethod *method,
2168 gboolean add_sync_wrapper,
2169 MonoError *error);
2170 gpointer mono_create_class_init_trampoline (MonoVTable *vtable);
2171 MONO_LLVM_INTERNAL gpointer mono_create_jit_trampoline (MonoDomain *domain, MonoMethod *method, MonoError *error);
2172 gpointer mono_create_jit_trampoline_from_token (MonoImage *image, guint32 token);
2173 gpointer mono_create_delegate_trampoline (MonoDomain *domain, MonoClass *klass);
2174 MonoDelegateTrampInfo* mono_create_delegate_trampoline_info (MonoDomain *domain, MonoClass *klass, MonoMethod *method);
2175 gpointer mono_create_delegate_virtual_trampoline (MonoDomain *domain, MonoClass *klass, MonoMethod *method);
2176 gpointer mono_create_rgctx_lazy_fetch_trampoline (guint32 offset);
2177 gpointer mono_create_monitor_enter_trampoline (void);
2178 gpointer mono_create_monitor_enter_v4_trampoline (void);
2179 gpointer mono_create_monitor_exit_trampoline (void);
2180 gpointer mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr);
2181 gpointer mono_create_ftnptr_arg_trampoline (gpointer arg, gpointer addr);
2182 MonoVTable* mono_find_class_init_trampoline_by_addr (gconstpointer addr);
2183 guint32 mono_find_rgctx_lazy_fetch_trampoline_by_addr (gconstpointer addr);
2184 gpointer mono_magic_trampoline (host_mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp);
2185 #ifndef DISABLE_REMOTING
2186 gpointer mono_generic_virtual_remoting_trampoline (host_mgreg_t *regs, guint8 *code, MonoMethod *m, guint8 *tramp);
2187 #endif
2188 gpointer mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp);
2189 gpointer mono_aot_trampoline (host_mgreg_t *regs, guint8 *code, guint8 *token_info,
2190 guint8* tramp);
2191 gpointer mono_aot_plt_trampoline (host_mgreg_t *regs, guint8 *code, guint8 *token_info,
2192 guint8* tramp);
2193 void mono_class_init_trampoline (host_mgreg_t *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp);
2194 void mono_generic_class_init_trampoline (host_mgreg_t *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp);
2195 void mono_monitor_enter_trampoline (host_mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp);
2196 void mono_monitor_enter_v4_trampoline (host_mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp);
2197 void mono_monitor_exit_trampoline (host_mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp);
2198 gconstpointer mono_get_trampoline_func (MonoTrampolineType tramp_type);
2199 gpointer mini_get_vtable_trampoline (MonoVTable *vt, int slot_index);
2200 const char* mono_get_generic_trampoline_simple_name (MonoTrampolineType tramp_type);
2201 const char* mono_get_generic_trampoline_name (MonoTrampolineType tramp_type);
2202 char* mono_get_rgctx_fetch_trampoline_name (int slot);
2203 gpointer mini_get_nullified_class_init_trampoline (void);
2204 gpointer mini_get_single_step_trampoline (void);
2205 gpointer mini_get_breakpoint_trampoline (void);
2206 gpointer mini_add_method_trampoline (MonoMethod *m, gpointer compiled_method, gboolean add_static_rgctx_tramp, gboolean add_unbox_tramp);
2207 gboolean mini_jit_info_is_gsharedvt (MonoJitInfo *ji);
2208 gpointer* mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_method, MonoMethod **impl_method, gpointer *out_aot_addr,
2209 gboolean *out_need_rgctx_tramp, MonoMethod **variant_iface,
2210 MonoError *error);
2212 void* mono_global_codeman_reserve (int size);
2214 #define mono_global_codeman_reserve(size) (g_cast (mono_global_codeman_reserve ((size))))
2216 void mono_global_codeman_foreach (MonoCodeManagerFunc func, void *user_data);
2217 const char *mono_regname_full (int reg, int bank);
2218 gint32* mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align);
2219 void mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb);
2220 MonoInst *mono_branch_optimize_exception_target (MonoCompile *cfg, MonoBasicBlock *bb, const char * exname);
2221 void mono_remove_critical_edges (MonoCompile *cfg);
2222 gboolean mono_is_regsize_var (MonoType *t);
2223 MonoJumpInfo * mono_patch_info_new (MonoMemPool *mp, int ip, MonoJumpInfoType type, gconstpointer target);
2224 int mini_class_check_context_used (MonoCompile *cfg, MonoClass *klass);
2225 int mini_method_check_context_used (MonoCompile *cfg, MonoMethod *method);
2226 void mini_type_from_op (MonoCompile *cfg, MonoInst *ins, MonoInst *src1, MonoInst *src2);
2227 void mini_set_inline_failure (MonoCompile *cfg, const char *msg);
2228 void mini_test_tailcall (MonoCompile *cfg, gboolean tailcall);
2229 gboolean mini_should_check_stack_pointer (MonoCompile *cfg);
2230 MonoInst* mini_emit_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_used);
2231 void mini_emit_memcpy (MonoCompile *cfg, int destreg, int doffset, int srcreg, int soffset, int size, int align);
2232 void mini_emit_memset (MonoCompile *cfg, int destreg, int offset, int size, int val, int align);
2233 void mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native);
2234 void mini_emit_initobj (MonoCompile *cfg, MonoInst *dest, const guchar *ip, MonoClass *klass);
2235 int mini_emit_sext_index_reg (MonoCompile *cfg, MonoInst *index);
2236 MonoInst* mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, MonoInst *index, gboolean bcheck);
2237 MonoInst* mini_emit_get_gsharedvt_info_klass (MonoCompile *cfg, MonoClass *klass, MonoRgctxInfoType rgctx_type);
2238 MonoInst* mini_emit_get_rgctx_method (MonoCompile *cfg, int context_used,
2239 MonoMethod *cmethod, MonoRgctxInfoType rgctx_type);
2240 void mini_emit_tailcall_parameters (MonoCompile *cfg, MonoMethodSignature *sig);
2241 MonoCallInst * mini_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig,
2242 MonoInst **args, gboolean calli, gboolean virtual_, gboolean tailcall,
2243 gboolean rgctx, gboolean unbox_trampoline, MonoMethod *target);
2244 MonoInst* mini_emit_calli (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args, MonoInst *addr, MonoInst *imt_arg, MonoInst *rgctx_arg);
2245 MonoInst* mini_emit_calli_full (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args, MonoInst *addr,
2246 MonoInst *imt_arg, MonoInst *rgctx_arg, gboolean tailcall);
2247 MonoInst* mini_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSignature *sig, gboolean tailcall,
2248 MonoInst **args, MonoInst *this_ins, MonoInst *imt_arg, MonoInst *rgctx_arg);
2249 MonoInst* mini_emit_abs_call (MonoCompile *cfg, MonoJumpInfoType patch_type, gconstpointer data,
2250 MonoMethodSignature *sig, MonoInst **args);
2251 MonoInst* mini_emit_extra_arg_calli (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **orig_args, int arg_reg, MonoInst *call_target);
2252 MonoInst* mini_emit_llvmonly_calli (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **args, MonoInst *addr);
2253 MonoInst* mini_emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, int context_used, MonoInst **sp);
2254 MonoInst* mini_emit_memory_barrier (MonoCompile *cfg, int kind);
2255 MonoInst* mini_emit_storing_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value);
2256 void mini_emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value);
2257 MonoInst* mini_emit_memory_load (MonoCompile *cfg, MonoType *type, MonoInst *src, int offset, int ins_flag);
2258 void mini_emit_memory_store (MonoCompile *cfg, MonoType *type, MonoInst *dest, MonoInst *value, int ins_flag);
2259 void mini_emit_memory_copy_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoInst *size, int ins_flag);
2260 void mini_emit_memory_init_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *value, MonoInst *size, int ins_flag);
2261 void mini_emit_memory_copy (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native, int ins_flag);
2262 MonoInst* mini_emit_array_store (MonoCompile *cfg, MonoClass *klass, MonoInst **sp, gboolean safety_checks);
2263 MonoInst* mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
2264 MonoInst* mini_emit_inst_for_ctor (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
2265 #ifndef ENABLE_NETCORE
2266 MonoInst* mini_emit_inst_for_sharable_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
2267 #endif
2268 MonoInst* mini_emit_inst_for_field_load (MonoCompile *cfg, MonoClassField *field);
2269 MonoInst* mini_handle_enum_has_flag (MonoCompile *cfg, MonoClass *klass, MonoInst *enum_this, int enum_val_reg, MonoInst *enum_flag);
2271 MonoMethod* mini_get_memcpy_method (void);
2272 MonoMethod* mini_get_memset_method (void);
2273 int mini_class_check_context_used (MonoCompile *cfg, MonoClass *klass);
2275 MONO_LLVM_INTERNAL CompRelation mono_opcode_to_cond (int opcode);
2276 CompType mono_opcode_to_type (int opcode, int cmp_opcode);
2277 CompRelation mono_negate_cond (CompRelation cond);
2278 int mono_op_imm_to_op (int opcode);
2279 void mono_decompose_op_imm (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins);
2280 void mono_peephole_ins (MonoBasicBlock *bb, MonoInst *ins);
2281 MonoUnwindOp *mono_create_unwind_op (int when,
2282 int tag, int reg,
2283 int val);
2284 void mono_emit_unwind_op (MonoCompile *cfg, int when,
2285 int tag, int reg,
2286 int val);
2287 MonoTrampInfo* mono_tramp_info_create (const char *name, guint8 *code, guint32 code_size, MonoJumpInfo *ji, GSList *unwind_ops);
2288 void mono_tramp_info_free (MonoTrampInfo *info);
2289 void mono_aot_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain);
2290 void mono_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain);
2291 MONO_LLVM_INTERNAL int mini_exception_id_by_name (const char *name);
2292 MONO_LLVM_INTERNAL gboolean mini_type_is_hfa (MonoType *t, int *out_nfields, int *out_esize);
2294 int mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock,
2295 MonoInst *return_var, MonoInst **inline_args,
2296 guint inline_offset, gboolean is_virtual_call);
2298 //the following methods could just be renamed/moved from method-to-ir.c
2299 int mini_inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **sp, guchar *ip,
2300 guint real_offset, gboolean inline_always);
2302 MonoInst* mini_emit_get_rgctx_klass (MonoCompile *cfg, int context_used, MonoClass *klass, MonoRgctxInfoType rgctx_type);
2303 MonoInst* mini_emit_runtime_constant (MonoCompile *cfg, MonoJumpInfoType patch_type, gpointer data);
2304 void mini_save_cast_details (MonoCompile *cfg, MonoClass *klass, int obj_reg, gboolean null_check);
2305 void mini_reset_cast_details (MonoCompile *cfg);
2306 void mini_emit_class_check (MonoCompile *cfg, int klass_reg, MonoClass *klass);
2308 gboolean mini_class_has_reference_variant_generic_argument (MonoCompile *cfg, MonoClass *klass, int context_used);
2310 MonoInst *mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins);
2311 void mono_decompose_long_opts (MonoCompile *cfg);
2312 void mono_decompose_vtype_opts (MonoCompile *cfg);
2313 void mono_decompose_array_access_opts (MonoCompile *cfg);
2314 void mono_decompose_soft_float (MonoCompile *cfg);
2315 void mono_local_emulate_ops (MonoCompile *cfg);
2316 void mono_handle_global_vregs (MonoCompile *cfg);
2317 void mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts);
2318 void mono_allocate_gsharedvt_vars (MonoCompile *cfg);
2319 void mono_if_conversion (MonoCompile *cfg);
2321 /* Delegates */
2322 char* mono_get_delegate_virtual_invoke_impl_name (gboolean load_imt_reg, int offset);
2323 gpointer mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method);
2325 void mono_codegen (MonoCompile *cfg);
2326 MONO_LLVM_INTERNAL void mono_call_inst_add_outarg_reg (MonoCompile *cfg, MonoCallInst *call, int vreg, int hreg, int bank);
2327 void mono_call_inst_add_outarg_vt (MonoCompile *cfg, MonoCallInst *call, MonoInst *outarg_vt);
2329 /* methods that must be provided by the arch-specific port */
2330 void mono_arch_init (void);
2331 void mono_arch_finish_init (void);
2332 void mono_arch_cleanup (void);
2333 void mono_arch_cpu_init (void);
2334 guint32 mono_arch_cpu_optimizations (guint32 *exclude_mask);
2335 const char *mono_arch_regname (int reg);
2336 const char *mono_arch_fregname (int reg);
2337 void mono_arch_exceptions_init (void);
2338 guchar* mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot);
2339 gpointer mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot);
2340 gpointer mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboolean aot);
2341 gpointer mono_arch_get_nullified_class_init_trampoline (MonoTrampInfo **info);
2342 guint8* mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gboolean aot);
2343 gpointer mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot);
2344 gpointer mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot);
2345 MONO_LLVM_INTERNAL guint8 *mono_arch_create_llvm_native_thunk (MonoDomain *domain, guint8* addr);
2346 gpointer mono_arch_get_get_tls_tramp (void);
2347 GList *mono_arch_get_allocatable_int_vars (MonoCompile *cfg);
2348 GList *mono_arch_get_global_int_regs (MonoCompile *cfg);
2349 guint32 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv);
2350 void mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gboolean run_cctors, MonoError *error);
2351 void mono_arch_patch_code_new (MonoCompile *cfg, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gpointer target);
2352 void mono_arch_flush_icache (guint8 *code, gint size);
2353 guint8 *mono_arch_emit_prolog (MonoCompile *cfg);
2354 void mono_arch_emit_epilog (MonoCompile *cfg);
2355 void mono_arch_emit_exceptions (MonoCompile *cfg);
2356 void mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb);
2357 void mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb);
2358 void mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb);
2359 void mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb);
2360 void mono_arch_fill_argument_info (MonoCompile *cfg);
2361 void mono_arch_allocate_vars (MonoCompile *m);
2362 int mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info);
2363 void mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call);
2364 void mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src);
2365 void mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val);
2366 MonoDynCallInfo *mono_arch_dyn_call_prepare (MonoMethodSignature *sig);
2367 void mono_arch_dyn_call_free (MonoDynCallInfo *info);
2368 int mono_arch_dyn_call_get_buf_size (MonoDynCallInfo *info);
2369 void mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, guint8 *buf);
2370 void mono_arch_finish_dyn_call (MonoDynCallInfo *info, guint8 *buf);
2371 MonoInst *mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
2372 void mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins);
2373 void mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *ins);
2374 GSList* mono_arch_get_delegate_invoke_impls (void);
2375 MONO_LLVM_INTERNAL LLVMCallInfo* mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig);
2376 guint8* mono_arch_emit_load_got_addr (guint8 *start, guint8 *code, MonoCompile *cfg, MonoJumpInfo **ji);
2377 guint8* mono_arch_emit_load_aotconst (guint8 *start, guint8 *code, MonoJumpInfo **ji, MonoJumpInfoType tramp_type, gconstpointer target);
2378 GSList* mono_arch_get_cie_program (void);
2379 void mono_arch_set_target (char *mtriple);
2380 gboolean mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig);
2381 gpointer mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot);
2382 gpointer mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli);
2383 gboolean mono_arch_opcode_needs_emulation (MonoCompile *cfg, int opcode);
2384 gboolean mono_arch_tailcall_supported (MonoCompile *cfg, MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig, gboolean virtual_);
2385 int mono_arch_translate_tls_offset (int offset);
2386 gboolean mono_arch_opcode_supported (int opcode);
2387 void mono_arch_setup_resume_sighandler_ctx (MonoContext *ctx, gpointer func);
2388 gboolean mono_arch_have_fast_tls (void);
2390 #ifdef MONO_ARCH_HAS_REGISTER_ICALL
2391 void mono_arch_register_icall (void);
2392 #endif
2394 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
2395 gboolean mono_arch_is_soft_float (void);
2396 #else
2397 static inline MONO_ALWAYS_INLINE gboolean
2398 mono_arch_is_soft_float (void)
2400 return FALSE;
2402 #endif
2404 /* Soft Debug support */
2405 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
2406 void mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip);
2407 void mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip);
2408 void mono_arch_start_single_stepping (void);
2409 void mono_arch_stop_single_stepping (void);
2410 gboolean mono_arch_is_single_step_event (void *info, void *sigctx);
2411 gboolean mono_arch_is_breakpoint_event (void *info, void *sigctx);
2412 void mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji);
2413 void mono_arch_skip_single_step (MonoContext *ctx);
2414 SeqPointInfo *mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code);
2415 #endif
2417 gboolean
2418 mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
2419 MonoJitInfo *ji, MonoContext *ctx,
2420 MonoContext *new_ctx, MonoLMF **lmf,
2421 host_mgreg_t **save_locations,
2422 StackFrameInfo *frame_info);
2423 gpointer mono_arch_get_throw_exception_by_name (void);
2424 gpointer mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot);
2425 gpointer mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot);
2426 gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot);
2427 gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot);
2428 gpointer mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot);
2429 gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot);
2430 gpointer mono_arch_get_throw_pending_exception (MonoTrampInfo **info, gboolean aot);
2431 gboolean mono_arch_handle_exception (void *sigctx, gpointer obj);
2432 void mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, gpointer fault_addr, gboolean stack_ovf);
2433 gboolean mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, guint8* fault_addr);
2434 void mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, MonoContext *mctx, guint8* fault_addr);
2435 void mono_arch_undo_ip_adjustment (MonoContext *ctx);
2436 void mono_arch_do_ip_adjustment (MonoContext *ctx);
2437 gpointer mono_arch_ip_from_context (void *sigctx);
2438 host_mgreg_t mono_arch_context_get_int_reg (MonoContext *ctx, int reg);
2439 void mono_arch_context_set_int_reg (MonoContext *ctx, int reg, host_mgreg_t val);
2440 void mono_arch_flush_register_windows (void);
2441 gboolean mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm);
2442 gboolean mono_arch_is_int_overflow (void *sigctx, void *info);
2443 void mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg);
2444 guint32 mono_arch_get_patch_offset (guint8 *code);
2445 gpointer*mono_arch_get_delegate_method_ptr_addr (guint8* code, host_mgreg_t *regs);
2446 MONO_LLVM_INTERNAL void mono_arch_create_vars (MonoCompile *cfg);
2447 void mono_arch_save_unwind_info (MonoCompile *cfg);
2448 void mono_arch_register_lowlevel_calls (void);
2449 gpointer mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr);
2450 gpointer mono_arch_get_static_rgctx_trampoline (gpointer arg, gpointer addr);
2451 gpointer mono_arch_get_ftnptr_arg_trampoline (gpointer arg, gpointer addr);
2452 gpointer mono_arch_get_llvm_imt_trampoline (MonoDomain *domain, MonoMethod *method, int vt_offset);
2453 gpointer mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr);
2454 void mono_arch_patch_callsite (guint8 *method_start, guint8 *code, guint8 *addr);
2455 void mono_arch_patch_plt_entry (guint8 *code, gpointer *got, host_mgreg_t *regs, guint8 *addr);
2456 void mono_arch_nullify_class_init_trampoline(guint8 *code, host_mgreg_t *regs);
2457 int mono_arch_get_this_arg_reg (guint8 *code);
2458 gpointer mono_arch_get_this_arg_from_call (host_mgreg_t *regs, guint8 *code);
2459 gpointer mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target);
2460 gpointer mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg);
2461 gpointer mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len);
2462 MonoMethod* mono_arch_find_imt_method (host_mgreg_t *regs, guint8 *code);
2463 MonoVTable* mono_arch_find_static_call_vtable (host_mgreg_t *regs, guint8 *code);
2464 gpointer mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp);
2465 void mono_arch_notify_pending_exc (MonoThreadInfo *info);
2466 guint8* mono_arch_get_call_target (guint8 *code);
2467 guint32 mono_arch_get_plt_info_offset (guint8 *plt_entry, host_mgreg_t *regs, guint8 *code);
2468 GSList *mono_arch_get_trampolines (gboolean aot);
2469 gpointer mono_arch_get_interp_to_native_trampoline (MonoTrampInfo **info);
2470 gpointer mono_arch_get_native_to_interp_trampoline (MonoTrampInfo **info);
2472 #ifdef MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP
2473 void mono_arch_set_native_call_context_args (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig);
2474 void mono_arch_set_native_call_context_ret (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig);
2475 void mono_arch_get_native_call_context_args (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig);
2476 void mono_arch_get_native_call_context_ret (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig);
2477 #endif
2479 /*New interruption machinery */
2480 void
2481 mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data);
2483 void
2484 mono_arch_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data);
2486 gboolean
2487 mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info, /*optional*/ void *sigctx);
2490 /* Exception handling */
2491 typedef gboolean (*MonoJitStackWalk) (StackFrameInfo *frame, MonoContext *ctx, gpointer data);
2493 void mono_exceptions_init (void);
2494 gboolean mono_handle_exception (MonoContext *ctx, gpointer obj);
2495 void mono_handle_native_crash (const char *signal, MonoContext *mctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo);
2496 MONO_API void mono_print_thread_dump (void *sigctx);
2497 MONO_API void mono_print_thread_dump_from_ctx (MonoContext *ctx);
2498 void mono_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data);
2499 void mono_walk_stack_with_state (MonoJitStackWalk func, MonoThreadUnwindState *state, MonoUnwindOptions unwind_options, void *user_data);
2500 void mono_walk_stack (MonoJitStackWalk func, MonoUnwindOptions options, void *user_data);
2501 gboolean mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx);
2502 void mono_thread_state_init (MonoThreadUnwindState *ctx);
2503 gboolean mono_thread_state_init_from_current (MonoThreadUnwindState *ctx);
2504 gboolean mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx);
2506 void mono_setup_altstack (MonoJitTlsData *tls);
2507 void mono_free_altstack (MonoJitTlsData *tls);
2508 gpointer mono_altstack_restore_prot (host_mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp);
2509 MonoJitInfo* mini_jit_info_table_find (MonoDomain *domain, gpointer addr, MonoDomain **out_domain);
2510 MonoJitInfo* mini_jit_info_table_find_ext (MonoDomain *domain, gpointer addr, gboolean allow_trampolines, MonoDomain **out_domain);
2511 G_EXTERN_C void mono_resume_unwind (MonoContext *ctx) MONO_LLVM_INTERNAL_NO_EXTERN_C;
2513 MonoJitInfo * mono_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx, MonoContext *new_ctx, char **trace, MonoLMF **lmf, int *native_offset, gboolean *managed);
2515 typedef gboolean (*MonoExceptionFrameWalk) (MonoMethod *method, gpointer ip, size_t native_offset, gboolean managed, gpointer user_data);
2516 MONO_API gboolean mono_exception_walk_trace (MonoException *ex, MonoExceptionFrameWalk func, gpointer user_data);
2517 void mono_restore_context (MonoContext *ctx);
2518 guint8* mono_jinfo_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len);
2519 int mono_jinfo_get_epilog_size (MonoJitInfo *ji);
2520 G_EXTERN_C void mono_llvm_rethrow_exception (MonoObject *ex);
2521 G_EXTERN_C void mono_llvm_throw_exception (MonoObject *ex);
2522 G_EXTERN_C void mono_llvm_throw_corlib_exception (guint32 ex_token_index);
2523 G_EXTERN_C void mono_llvm_resume_exception (void);
2524 G_EXTERN_C void mono_llvm_clear_exception (void);
2525 G_EXTERN_C MonoObject *mono_llvm_load_exception (void);
2526 void mono_llvm_reset_exception (void);
2527 void mono_llvm_raise_exception (MonoException *e);
2528 void mono_llvm_reraise_exception (MonoException *e);
2529 G_EXTERN_C gint32 mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj);
2531 gboolean
2532 mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls,
2533 MonoJitInfo *prev_ji, MonoContext *ctx,
2534 MonoContext *new_ctx, char **trace, MonoLMF **lmf,
2535 host_mgreg_t **save_locations,
2536 StackFrameInfo *frame);
2538 gpointer mono_get_throw_exception (void);
2539 gpointer mono_get_rethrow_exception (void);
2540 gpointer mono_get_rethrow_preserve_exception (void);
2541 gpointer mono_get_call_filter (void);
2542 gpointer mono_get_restore_context (void);
2543 gpointer mono_get_throw_corlib_exception (void);
2544 gpointer mono_get_throw_exception_addr (void);
2545 gpointer mono_get_rethrow_preserve_exception_addr (void);
2546 ICALL_EXPORT
2547 MonoArray *ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info);
2549 ICALL_EXPORT
2550 MonoBoolean ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
2551 MonoReflectionMethod **method,
2552 gint32 *iloffset, gint32 *native_offset,
2553 MonoString **file, gint32 *line, gint32 *column);
2554 void mono_set_cast_details (MonoClass *from, MonoClass *to);
2556 void mono_decompose_typechecks (MonoCompile *cfg);
2557 /* Dominator/SSA methods */
2558 void mono_compile_dominator_info (MonoCompile *cfg, int dom_flags);
2559 void mono_compute_natural_loops (MonoCompile *cfg);
2560 MonoBitSet* mono_compile_iterated_dfrontier (MonoCompile *cfg, MonoBitSet *set);
2561 void mono_ssa_compute (MonoCompile *cfg);
2562 void mono_ssa_remove (MonoCompile *cfg);
2563 void mono_ssa_remove_gsharedvt (MonoCompile *cfg);
2564 void mono_ssa_cprop (MonoCompile *cfg);
2565 void mono_ssa_deadce (MonoCompile *cfg);
2566 void mono_ssa_strength_reduction (MonoCompile *cfg);
2567 void mono_free_loop_info (MonoCompile *cfg);
2568 void mono_ssa_loop_invariant_code_motion (MonoCompile *cfg);
2570 void mono_ssa_compute2 (MonoCompile *cfg);
2571 void mono_ssa_remove2 (MonoCompile *cfg);
2572 void mono_ssa_cprop2 (MonoCompile *cfg);
2573 void mono_ssa_deadce2 (MonoCompile *cfg);
2575 /* debugging support */
2576 void mono_debug_init_method (MonoCompile *cfg, MonoBasicBlock *start_block,
2577 guint32 breakpoint_id);
2578 void mono_debug_open_method (MonoCompile *cfg);
2579 void mono_debug_close_method (MonoCompile *cfg);
2580 void mono_debug_free_method (MonoCompile *cfg);
2581 void mono_debug_open_block (MonoCompile *cfg, MonoBasicBlock *bb, guint32 address);
2582 void mono_debug_record_line_number (MonoCompile *cfg, MonoInst *ins, guint32 address);
2583 void mono_debug_serialize_debug_info (MonoCompile *cfg, guint8 **out_buf, guint32 *buf_len);
2584 void mono_debug_add_aot_method (MonoDomain *domain,
2585 MonoMethod *method, guint8 *code_start,
2586 guint8 *debug_info, guint32 debug_info_len);
2587 MONO_API void mono_debug_print_vars (gpointer ip, gboolean only_arguments);
2588 MONO_API void mono_debugger_run_finally (MonoContext *start_ctx);
2590 MONO_API gboolean mono_breakpoint_clean_code (guint8 *method_start, guint8 *code, int offset, guint8 *buf, int size);
2592 /* Tracing */
2593 MonoCallSpec *mono_trace_set_options (const char *options);
2594 gboolean mono_trace_eval (MonoMethod *method);
2596 gboolean
2597 mono_tailcall_print_enabled (void);
2599 void
2600 mono_tailcall_print (const char *format, ...);
2602 gboolean
2603 mono_is_supported_tailcall_helper (gboolean value, const char *svalue);
2605 #define IS_SUPPORTED_TAILCALL(x) (mono_is_supported_tailcall_helper((x), #x))
2607 extern void
2608 mono_perform_abc_removal (MonoCompile *cfg);
2609 extern void
2610 mono_perform_abc_removal (MonoCompile *cfg);
2611 extern void
2612 mono_local_cprop (MonoCompile *cfg);
2613 extern void
2614 mono_local_cprop (MonoCompile *cfg);
2615 extern void
2616 mono_local_deadce (MonoCompile *cfg);
2617 void
2618 mono_local_alias_analysis (MonoCompile *cfg);
2620 /* Generic sharing */
2622 void
2623 mono_set_generic_sharing_supported (gboolean supported);
2625 void
2626 mono_set_generic_sharing_vt_supported (gboolean supported);
2628 void
2629 mono_set_partial_sharing_supported (gboolean supported);
2631 gboolean
2632 mono_class_generic_sharing_enabled (MonoClass *klass);
2634 gpointer
2635 mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot, MonoError *error);
2637 gpointer
2638 mono_method_fill_runtime_generic_context (MonoMethodRuntimeGenericContext *mrgctx, guint32 slot, MonoError *error);
2640 MONO_LLVM_INTERNAL const char*
2641 mono_rgctx_info_type_to_str (MonoRgctxInfoType type);
2643 MonoJumpInfoType
2644 mini_rgctx_info_type_to_patch_info_type (MonoRgctxInfoType info_type);
2646 gboolean
2647 mono_method_needs_static_rgctx_invoke (MonoMethod *method, gboolean allow_type_vars);
2650 mono_class_rgctx_get_array_size (int n, gboolean mrgctx);
2652 MonoGenericContext
2653 mono_method_construct_object_context (MonoMethod *method);
2655 MonoMethod*
2656 mono_method_get_declaring_generic_method (MonoMethod *method);
2659 mono_generic_context_check_used (MonoGenericContext *context);
2662 mono_class_check_context_used (MonoClass *klass);
2664 gboolean
2665 mono_generic_context_is_sharable (MonoGenericContext *context, gboolean allow_type_vars);
2667 gboolean
2668 mono_generic_context_is_sharable_full (MonoGenericContext *context, gboolean allow_type_vars, gboolean allow_partial);
2670 gboolean
2671 mono_method_is_generic_impl (MonoMethod *method);
2673 gboolean
2674 mono_method_is_generic_sharable (MonoMethod *method, gboolean allow_type_vars);
2676 gboolean
2677 mono_method_is_generic_sharable_full (MonoMethod *method, gboolean allow_type_vars, gboolean allow_partial, gboolean allow_gsharedvt);
2679 gboolean
2680 mini_class_is_generic_sharable (MonoClass *klass);
2682 gboolean
2683 mini_generic_inst_is_sharable (MonoGenericInst *inst, gboolean allow_type_vars, gboolean allow_partial);
2685 MonoMethod*
2686 mono_class_get_method_generic (MonoClass *klass, MonoMethod *method, MonoError *error);
2688 gboolean
2689 mono_is_partially_sharable_inst (MonoGenericInst *inst);
2691 gboolean
2692 mini_is_gsharedvt_gparam (MonoType *t);
2694 MonoGenericContext* mini_method_get_context (MonoMethod *method);
2696 int mono_method_check_context_used (MonoMethod *method);
2698 gboolean mono_generic_context_equal_deep (MonoGenericContext *context1, MonoGenericContext *context2);
2700 gpointer mono_helper_get_rgctx_other_ptr (MonoClass *caller_class, MonoVTable *vtable,
2701 guint32 token, guint32 token_source, guint32 rgctx_type,
2702 gint32 rgctx_index);
2704 void mono_generic_sharing_init (void);
2705 void mono_generic_sharing_cleanup (void);
2707 MonoClass* mini_class_get_container_class (MonoClass *klass);
2708 MonoGenericContext* mini_class_get_context (MonoClass *klass);
2710 typedef enum {
2711 SHARE_MODE_NONE = 0x0,
2712 SHARE_MODE_GSHAREDVT = 0x1,
2713 } GetSharedMethodFlags;
2715 MONO_LLVM_INTERNAL MonoType* mini_get_underlying_type (MonoType *type);
2716 MonoType* mini_type_get_underlying_type (MonoType *type);
2717 MonoClass* mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context);
2718 MonoMethod* mini_get_shared_method_to_register (MonoMethod *method);
2719 MonoMethod* mini_get_shared_method_full (MonoMethod *method, GetSharedMethodFlags flags, MonoError *error);
2720 MonoType* mini_get_shared_gparam (MonoType *t, MonoType *constraint);
2721 int mini_get_rgctx_entry_slot (MonoJumpInfoRgctxEntry *entry);
2723 int mini_type_stack_size (MonoType *t, int *align);
2724 int mini_type_stack_size_full (MonoType *t, guint32 *align, gboolean pinvoke);
2725 void mini_type_to_eval_stack_type (MonoCompile *cfg, MonoType *type, MonoInst *inst);
2726 MONO_LLVM_INTERNAL guint mono_type_to_regmove (MonoCompile *cfg, MonoType *type);
2728 void mono_cfg_add_try_hole (MonoCompile *cfg, MonoExceptionClause *clause, guint8 *start, MonoBasicBlock *bb);
2730 void mono_cfg_set_exception (MonoCompile *cfg, MonoExceptionType type);
2731 void mono_cfg_set_exception_invalid_program (MonoCompile *cfg, char *msg);
2733 #define MONO_TIME_TRACK(a, phase) \
2735 gint64 start = mono_time_track_start (); \
2736 (phase) ; \
2737 mono_time_track_end (&(a), start); \
2740 gint64 mono_time_track_start (void);
2741 void mono_time_track_end (gint64 *time, gint64 start);
2743 void mono_update_jit_stats (MonoCompile *cfg);
2745 gboolean mini_type_is_reference (MonoType *type);
2746 MONO_LLVM_INTERNAL gboolean mini_type_is_vtype (MonoType *t);
2747 MONO_LLVM_INTERNAL gboolean mini_type_var_is_vt (MonoType *type);
2748 gboolean mini_is_gsharedvt_type (MonoType *t);
2749 MONO_LLVM_INTERNAL gboolean mini_is_gsharedvt_klass (MonoClass *klass);
2750 gboolean mini_is_gsharedvt_signature (MonoMethodSignature *sig);
2751 MONO_LLVM_INTERNAL gboolean mini_is_gsharedvt_variable_type (MonoType *t);
2752 MONO_LLVM_INTERNAL gboolean mini_is_gsharedvt_variable_klass (MonoClass *klass);
2753 gboolean mini_is_gsharedvt_sharable_method (MonoMethod *method);
2754 MONO_LLVM_INTERNAL gboolean mini_is_gsharedvt_variable_signature (MonoMethodSignature *sig);
2755 gboolean mini_is_gsharedvt_sharable_inst (MonoGenericInst *inst);
2756 MONO_LLVM_INTERNAL gboolean mini_method_is_default_method (MonoMethod *m);
2757 gboolean mini_method_needs_mrgctx (MonoMethod *m);
2758 gpointer mini_method_get_rgctx (MonoMethod *m);
2759 void mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *context, MonoGenericSharingContext *gsctx);
2761 gpointer mini_get_gsharedvt_wrapper (gboolean gsharedvt_in, gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig,
2762 gint32 vcall_offset, gboolean calli);
2763 MonoMethod* mini_get_gsharedvt_in_sig_wrapper (MonoMethodSignature *sig);
2764 MonoMethod* mini_get_gsharedvt_out_sig_wrapper (MonoMethodSignature *sig);
2765 MonoMethodSignature* mini_get_gsharedvt_out_sig_wrapper_signature (gboolean has_this, gboolean has_ret, int param_count);
2766 gboolean mini_gsharedvt_runtime_invoke_supported (MonoMethodSignature *sig);
2767 G_EXTERN_C void mono_interp_entry_from_trampoline (gpointer ccontext, gpointer imethod);
2768 G_EXTERN_C void mono_interp_to_native_trampoline (gpointer addr, gpointer ccontext);
2769 MonoMethod* mini_get_interp_in_wrapper (MonoMethodSignature *sig);
2770 MonoMethod* mini_get_interp_lmf_wrapper (const char *name, gpointer target);
2771 char* mono_get_method_from_ip (void *ip);
2773 /* SIMD support */
2776 This enum MUST be kept in sync with its managed mirror Mono.Simd.AccelMode.
2778 enum {
2779 SIMD_VERSION_SSE1 = 1 << 0,
2780 SIMD_VERSION_SSE2 = 1 << 1,
2781 SIMD_VERSION_SSE3 = 1 << 2,
2782 SIMD_VERSION_SSSE3 = 1 << 3,
2783 SIMD_VERSION_SSE41 = 1 << 4,
2784 SIMD_VERSION_SSE42 = 1 << 5,
2785 SIMD_VERSION_SSE4a = 1 << 6,
2786 SIMD_VERSION_ALL = SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
2787 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
2788 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
2789 SIMD_VERSION_SSE4a,
2791 /* this value marks the end of the bit indexes used in
2792 * this emum.
2794 SIMD_VERSION_INDEX_END = 6
2797 typedef enum {
2798 /* Used for lazy initialization */
2799 MONO_CPU_INITED = 1 << 0,
2800 #if defined(TARGET_X86) || defined(TARGET_AMD64)
2801 MONO_CPU_X86_SSE = 1 << 1,
2802 MONO_CPU_X86_SSE2 = 1 << 2,
2803 MONO_CPU_X86_PCLMUL = 1 << 3,
2804 MONO_CPU_X86_AES = 1 << 4,
2805 MONO_CPU_X86_SSE3 = 1 << 5,
2806 MONO_CPU_X86_SSSE3 = 1 << 6,
2807 MONO_CPU_X86_SSE41 = 1 << 7,
2808 MONO_CPU_X86_SSE42 = 1 << 8,
2809 MONO_CPU_X86_POPCNT = 1 << 9,
2810 MONO_CPU_X86_AVX = 1 << 10,
2811 MONO_CPU_X86_AVX2 = 1 << 11,
2812 MONO_CPU_X86_FMA = 1 << 12,
2813 MONO_CPU_X86_LZCNT = 1 << 13,
2814 MONO_CPU_X86_BMI1 = 1 << 14,
2815 MONO_CPU_X86_BMI2 = 1 << 15,
2819 // Dependencies (based on System.Runtime.Intrinsics.X86 class hierarchy):
2821 // sse
2822 // sse2
2823 // pclmul
2824 // aes
2825 // sse3
2826 // ssse3
2827 // sse4.1
2828 // sse4.2
2829 // popcnt
2830 // avx
2831 // avx2
2832 // fma
2833 // lzcnt
2834 // bmi1
2835 // bmi2
2836 MONO_CPU_X86_SSE_COMBINED = MONO_CPU_X86_SSE,
2837 MONO_CPU_X86_SSE2_COMBINED = MONO_CPU_X86_SSE_COMBINED | MONO_CPU_X86_SSE2,
2838 MONO_CPU_X86_PCLMUL_COMBINED = MONO_CPU_X86_SSE2_COMBINED | MONO_CPU_X86_PCLMUL,
2839 MONO_CPU_X86_AES_COMBINED = MONO_CPU_X86_SSE2_COMBINED | MONO_CPU_X86_AES,
2840 MONO_CPU_X86_SSE3_COMBINED = MONO_CPU_X86_SSE2_COMBINED | MONO_CPU_X86_SSE3,
2841 MONO_CPU_X86_SSSE3_COMBINED = MONO_CPU_X86_SSE3_COMBINED | MONO_CPU_X86_PCLMUL | MONO_CPU_X86_AES | MONO_CPU_X86_SSSE3,
2842 MONO_CPU_X86_SSE41_COMBINED = MONO_CPU_X86_SSSE3_COMBINED | MONO_CPU_X86_SSE41,
2843 MONO_CPU_X86_SSE42_COMBINED = MONO_CPU_X86_SSE41_COMBINED | MONO_CPU_X86_SSE42,
2844 MONO_CPU_X86_POPCNT_COMBINED = MONO_CPU_X86_SSE42_COMBINED | MONO_CPU_X86_POPCNT,
2845 MONO_CPU_X86_AVX_COMBINED = MONO_CPU_X86_SSE42_COMBINED | MONO_CPU_X86_AVX,
2846 MONO_CPU_X86_AVX2_COMBINED = MONO_CPU_X86_AVX_COMBINED | MONO_CPU_X86_POPCNT | MONO_CPU_X86_AVX2,
2847 MONO_CPU_X86_FMA_COMBINED = MONO_CPU_X86_AVX_COMBINED | MONO_CPU_X86_POPCNT | MONO_CPU_X86_FMA,
2848 MONO_CPU_X86_FULL_SSEAVX_COMBINED = MONO_CPU_X86_FMA_COMBINED | MONO_CPU_X86_AVX2,
2849 #endif
2850 } MonoCPUFeatures;
2852 G_ENUM_FUNCTIONS (MonoCPUFeatures)
2854 MonoCPUFeatures mini_get_cpu_features (MonoCompile* cfg);
2856 enum {
2857 SIMD_COMP_EQ,
2858 SIMD_COMP_LT,
2859 SIMD_COMP_LE,
2860 SIMD_COMP_UNORD,
2861 SIMD_COMP_NEQ,
2862 SIMD_COMP_NLT,
2863 SIMD_COMP_NLE,
2864 SIMD_COMP_ORD
2867 enum {
2868 SIMD_PREFETCH_MODE_NTA,
2869 SIMD_PREFETCH_MODE_0,
2870 SIMD_PREFETCH_MODE_1,
2871 SIMD_PREFETCH_MODE_2,
2874 const char *mono_arch_xregname (int reg);
2875 guint32 mono_arch_cpu_enumerate_simd_versions (void);
2876 MonoCPUFeatures mono_arch_get_cpu_features (void);
2878 #ifdef MONO_ARCH_SIMD_INTRINSICS
2879 void mono_simd_simplify_indirection (MonoCompile *cfg);
2880 void mono_simd_decompose_intrinsic (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins);
2881 void mono_simd_decompose_intrinsics (MonoCompile *cfg);
2882 MonoInst* mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
2883 MonoInst* mono_emit_simd_field_load (MonoCompile *cfg, MonoClassField *field, MonoInst *addr);
2884 void mono_simd_intrinsics_init (void);
2885 #endif
2887 gboolean mono_class_is_magic_int (MonoClass *klass);
2888 gboolean mono_class_is_magic_float (MonoClass *klass);
2889 MonoInst* mono_emit_native_types_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
2890 gsize mini_magic_type_size (MonoCompile *cfg, MonoType *type);
2891 gboolean mini_magic_is_int_type (MonoType *t);
2892 gboolean mini_magic_is_float_type (MonoType *t);
2893 MONO_LLVM_INTERNAL MonoType* mini_native_type_replace_type (MonoType *type);
2895 MonoMethod*
2896 mini_method_to_shared (MonoMethod *method); // null if not shared
2898 static inline gboolean
2899 mini_safepoints_enabled (void)
2901 #if defined (TARGET_WASM)
2902 return FALSE;
2903 #else
2904 return TRUE;
2905 #endif
2908 gpointer
2909 mono_arch_load_function (MonoJitICallId jit_icall_id);
2911 #endif /* __MONO_MINI_H__ */