1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*****************************************************************************/
6#ifndef _JIT_H_
7#define _JIT_H_
8/*****************************************************************************/
9
10//
11// clr.sln only defines _DEBUG
12// The jit uses DEBUG rather than _DEBUG
13// So we make sure that _DEBUG implies DEBUG
14//
15#ifdef _DEBUG
16#ifndef DEBUG
17#define DEBUG 1
18#endif
19#endif
20
21// Clang-format messes with the indentation of comments if they directly precede an
22// ifdef. This macro allows us to anchor the comments to the regular flow of code.
23#define CLANG_FORMAT_COMMENT_ANCHOR ;
24
25// Clang-tidy replaces 0 with nullptr in some templated functions, causing a build
26// break. Replacing those instances with ZERO avoids this change
27#define ZERO 0
28
29#ifdef _MSC_VER
30// These don't seem useful, so turning them off is no big deal
31#pragma warning(disable : 4065) // "switch statement contains 'default' but no 'case' labels" (happens due to #ifdefs)
32#pragma warning(disable : 4510) // can't generate default constructor
33#pragma warning(disable : 4511) // can't generate copy constructor
34#pragma warning(disable : 4512) // can't generate assignment constructor
35#pragma warning(disable : 4610) // user defined constructor required
36#pragma warning(disable : 4211) // nonstandard extension used (char name[0] in structs)
37#pragma warning(disable : 4127) // conditional expression constant
38#pragma warning(disable : 4201) // "nonstandard extension used : nameless struct/union"
39
40// Depending on the code base, you may want to not disable these
41#pragma warning(disable : 4245) // assigning signed / unsigned
42#pragma warning(disable : 4146) // unary minus applied to unsigned
43
44#pragma warning(disable : 4100) // unreferenced formal parameter
45#pragma warning(disable : 4291) // new operator without delete (only in emitX86.cpp)
46#endif
47
48#ifdef _MSC_VER
49#define CHECK_STRUCT_PADDING 0 // Set this to '1' to enable warning C4820 "'bytes' bytes padding added after
50 // construct 'member_name'" on interesting structs/classes
51#else
52#define CHECK_STRUCT_PADDING 0 // Never enable it for non-MSFT compilers
53#endif
54
55#if defined(_X86_)
56#if defined(_ARM_)
57#error Cannot define both _X86_ and _ARM_
58#endif
59#if defined(_AMD64_)
60#error Cannot define both _X86_ and _AMD64_
61#endif
62#if defined(_ARM64_)
63#error Cannot define both _X86_ and _ARM64_
64#endif
65#define _HOST_X86_
66#elif defined(_AMD64_)
67#if defined(_X86_)
68#error Cannot define both _AMD64_ and _X86_
69#endif
70#if defined(_ARM_)
71#error Cannot define both _AMD64_ and _ARM_
72#endif
73#if defined(_ARM64_)
74#error Cannot define both _AMD64_ and _ARM64_
75#endif
76#define _HOST_AMD64_
77#elif defined(_ARM_)
78#if defined(_X86_)
79#error Cannot define both _ARM_ and _X86_
80#endif
81#if defined(_AMD64_)
82#error Cannot define both _ARM_ and _AMD64_
83#endif
84#if defined(_ARM64_)
85#error Cannot define both _ARM_ and _ARM64_
86#endif
87#define _HOST_ARM_
88#elif defined(_ARM64_)
89#if defined(_X86_)
90#error Cannot define both _ARM64_ and _X86_
91#endif
92#if defined(_AMD64_)
93#error Cannot define both _ARM64_ and _AMD64_
94#endif
95#if defined(_ARM_)
96#error Cannot define both _ARM64_ and _ARM_
97#endif
98#define _HOST_ARM64_
99#else
100#error Unsupported or unset host architecture
101#endif
102
103#if defined(_HOST_AMD64_) || defined(_HOST_ARM64_)
104#define _HOST_64BIT_
105#endif
106
107#if defined(_TARGET_X86_)
108#if defined(_TARGET_ARM_)
109#error Cannot define both _TARGET_X86_ and _TARGET_ARM_
110#endif
111#if defined(_TARGET_AMD64_)
112#error Cannot define both _TARGET_X86_ and _TARGET_AMD64_
113#endif
114#if defined(_TARGET_ARM64_)
115#error Cannot define both _TARGET_X86_ and _TARGET_ARM64_
116#endif
117#if !defined(_HOST_X86_)
118#define _CROSS_COMPILER_
119#endif
120#elif defined(_TARGET_AMD64_)
121#if defined(_TARGET_X86_)
122#error Cannot define both _TARGET_AMD64_ and _TARGET_X86_
123#endif
124#if defined(_TARGET_ARM_)
125#error Cannot define both _TARGET_AMD64_ and _TARGET_ARM_
126#endif
127#if defined(_TARGET_ARM64_)
128#error Cannot define both _TARGET_AMD64_ and _TARGET_ARM64_
129#endif
130#if !defined(_HOST_AMD64_)
131#define _CROSS_COMPILER_
132#endif
133#elif defined(_TARGET_ARM_)
134#if defined(_TARGET_X86_)
135#error Cannot define both _TARGET_ARM_ and _TARGET_X86_
136#endif
137#if defined(_TARGET_AMD64_)
138#error Cannot define both _TARGET_ARM_ and _TARGET_AMD64_
139#endif
140#if defined(_TARGET_ARM64_)
141#error Cannot define both _TARGET_ARM_ and _TARGET_ARM64_
142#endif
143#if !defined(_HOST_ARM_)
144#define _CROSS_COMPILER_
145#endif
146#elif defined(_TARGET_ARM64_)
147#if defined(_TARGET_X86_)
148#error Cannot define both _TARGET_ARM64_ and _TARGET_X86_
149#endif
150#if defined(_TARGET_AMD64_)
151#error Cannot define both _TARGET_ARM64_ and _TARGET_AMD64_
152#endif
153#if defined(_TARGET_ARM_)
154#error Cannot define both _TARGET_ARM64_ and _TARGET_ARM_
155#endif
156#if !defined(_HOST_ARM64_)
157#define _CROSS_COMPILER_
158#endif
159#else
160#error Unsupported or unset target architecture
161#endif
162
163#if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
164#ifndef _TARGET_64BIT_
165#define _TARGET_64BIT_
166#endif // _TARGET_64BIT_
167#endif // defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
168
169#ifdef _TARGET_64BIT_
170#ifdef _TARGET_X86_
171#error Cannot define both _TARGET_X86_ and _TARGET_64BIT_
172#endif // _TARGET_X86_
173#ifdef _TARGET_ARM_
174#error Cannot define both _TARGET_ARM_ and _TARGET_64BIT_
175#endif // _TARGET_ARM_
176#endif // _TARGET_64BIT_
177
178#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
179#define _TARGET_XARCH_
180#endif
181
182#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
183#define _TARGET_ARMARCH_
184#endif
185
186// If the UNIX_AMD64_ABI is defined make sure that _TARGET_AMD64_ is also defined.
187#if defined(UNIX_AMD64_ABI)
188#if !defined(_TARGET_AMD64_)
189#error When UNIX_AMD64_ABI is defined you must define _TARGET_AMD64_ defined as well.
190#endif
191#endif
192
193// If the UNIX_X86_ABI is defined make sure that _TARGET_X86_ is also defined.
194#if defined(UNIX_X86_ABI)
195#if !defined(_TARGET_X86_)
196#error When UNIX_X86_ABI is defined you must define _TARGET_X86_ defined as well.
197#endif
198#endif
199
200#if defined(PLATFORM_UNIX)
201#define _HOST_UNIX_
202#endif
203
204// Are we generating code to target Unix? This is true if we will run on Unix (_HOST_UNIX_ is defined).
205// It's also true if we are building an altjit targetting Unix, which we determine by checking if either
206// UNIX_AMD64_ABI or UNIX_X86_ABI is defined.
207#if defined(_HOST_UNIX_) || ((defined(UNIX_AMD64_ABI) || defined(UNIX_X86_ABI)) && defined(ALT_JIT))
208#define _TARGET_UNIX_
209#endif
210
211#ifndef _TARGET_UNIX_
212#define _TARGET_WINDOWS_
213#endif // !_TARGET_UNIX_
214
215// --------------------------------------------------------------------------------
216// IMAGE_FILE_MACHINE_TARGET
217// --------------------------------------------------------------------------------
218
219#if defined(_TARGET_X86_)
220#define IMAGE_FILE_MACHINE_TARGET IMAGE_FILE_MACHINE_I386
221#elif defined(_TARGET_AMD64_)
222#define IMAGE_FILE_MACHINE_TARGET IMAGE_FILE_MACHINE_AMD64
223#elif defined(_TARGET_ARM_)
224#define IMAGE_FILE_MACHINE_TARGET IMAGE_FILE_MACHINE_ARMNT
225#elif defined(_TARGET_ARM64_)
226#define IMAGE_FILE_MACHINE_TARGET IMAGE_FILE_MACHINE_ARM64 // 0xAA64
227#else
228#error Unsupported or unset target architecture
229#endif
230
231// Include the AMD64 unwind codes when appropriate.
232#if defined(_TARGET_AMD64_)
233// We need to temporarily set PLATFORM_UNIX, if necessary, to get the Unix-specific unwind codes.
234#if defined(_TARGET_UNIX_) && !defined(_HOST_UNIX_)
235#define PLATFORM_UNIX
236#endif
237#include "win64unwind.h"
238#if defined(_TARGET_UNIX_) && !defined(_HOST_UNIX_)
239#undef PLATFORM_UNIX
240#endif
241#endif
242
243#include "corhdr.h"
244#include "corjit.h"
245#include "jitee.h"
246
247#define __OPERATOR_NEW_INLINE 1 // indicate that I will define these
248#define __PLACEMENT_NEW_INLINE // don't bring in the global placement new, it is easy to make a mistake
249 // with our new(compiler*) pattern.
250
251#include "utilcode.h" // this defines assert as _ASSERTE
252#include "host.h" // this redefines assert for the JIT to use assertAbort
253#include "utils.h"
254
255#ifdef DEBUG
256#define INDEBUG(x) x
257#define INDEBUG_COMMA(x) x,
258#define DEBUGARG(x) , x
259#else
260#define INDEBUG(x)
261#define INDEBUG_COMMA(x)
262#define DEBUGARG(x)
263#endif
264
265#if defined(DEBUG) || defined(LATE_DISASM)
266#define INDEBUG_LDISASM_COMMA(x) x,
267#else
268#define INDEBUG_LDISASM_COMMA(x)
269#endif
270
271#if defined(UNIX_AMD64_ABI)
272#define UNIX_AMD64_ABI_ONLY_ARG(x) , x
273#define UNIX_AMD64_ABI_ONLY(x) x
274#else // !defined(UNIX_AMD64_ABI)
275#define UNIX_AMD64_ABI_ONLY_ARG(x)
276#define UNIX_AMD64_ABI_ONLY(x)
277#endif // defined(UNIX_AMD64_ABI)
278
279#if defined(UNIX_AMD64_ABI) || !defined(_TARGET_64BIT_) || (defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_))
280#define FEATURE_PUT_STRUCT_ARG_STK 1
281#define PUT_STRUCT_ARG_STK_ONLY_ARG(x) , x
282#define PUT_STRUCT_ARG_STK_ONLY(x) x
283#else // !(defined(UNIX_AMD64_ABI) && defined(_TARGET_64BIT_) && !(defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_))
284#define PUT_STRUCT_ARG_STK_ONLY_ARG(x)
285#define PUT_STRUCT_ARG_STK_ONLY(x)
286#endif // !(defined(UNIX_AMD64_ABI) && defined(_TARGET_64BIT_) && !(defined(_TARGET_WINDOWS_) &&
287 // defined(_TARGET_ARM64_))
288
289#if defined(UNIX_AMD64_ABI)
290#define UNIX_AMD64_ABI_ONLY_ARG(x) , x
291#define UNIX_AMD64_ABI_ONLY(x) x
292#else // !defined(UNIX_AMD64_ABI)
293#define UNIX_AMD64_ABI_ONLY_ARG(x)
294#define UNIX_AMD64_ABI_ONLY(x)
295#endif // defined(UNIX_AMD64_ABI)
296
297#if defined(UNIX_AMD64_ABI) || defined(_TARGET_ARM64_)
298#define MULTIREG_HAS_SECOND_GC_RET 1
299#define MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(x) , x
300#define MULTIREG_HAS_SECOND_GC_RET_ONLY(x) x
301#else // !defined(UNIX_AMD64_ABI)
302#define MULTIREG_HAS_SECOND_GC_RET 0
303#define MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(x)
304#define MULTIREG_HAS_SECOND_GC_RET_ONLY(x)
305#endif // defined(UNIX_AMD64_ABI)
306
307// Arm64 Windows supports FEATURE_ARG_SPLIT, note this is different from
308// the official Arm64 ABI.
309// Case: splitting 16 byte struct between x7 and stack
310#if (defined(_TARGET_ARM_) || (defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_)))
311#define FEATURE_ARG_SPLIT 1
312#else
313#define FEATURE_ARG_SPLIT 0
314#endif // (defined(_TARGET_ARM_) || (defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_)))
315
316// To get rid of warning 4701 : local variable may be used without being initialized
317#define DUMMY_INIT(x) (x)
318
319#define REGEN_SHORTCUTS 0
320#define REGEN_CALLPAT 0
321
322/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
323XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
324XX XX
325XX jit.h XX
326XX XX
327XX Interface of the JIT with jit.cpp XX
328XX XX
329XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
330XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
331*/
332
333/*****************************************************************************/
334#if defined(DEBUG)
335#include "log.h"
336
337#define INFO6 LL_INFO10000 // Did Jit or Inline succeeded?
338#define INFO7 LL_INFO100000 // NYI stuff
339#define INFO8 LL_INFO1000000 // Weird failures
340#define INFO9 LL_EVERYTHING // Info about incoming settings
341#define INFO10 LL_EVERYTHING // Totally verbose
342
343#endif // DEBUG
344
345typedef class ICorJitInfo* COMP_HANDLE;
346
347const CORINFO_CLASS_HANDLE NO_CLASS_HANDLE = (CORINFO_CLASS_HANDLE) nullptr;
348
349/*****************************************************************************/
350
351inline bool False()
352{
353 return false;
354} // Use to disable code while keeping prefast happy
355
356// We define two IL offset types, as follows:
357//
358// IL_OFFSET: either a distinguished value, or an IL offset.
359// IL_OFFSETX: either a distinguished value, or the top two bits are a flags, and the remaining bottom
360// bits are a IL offset.
361//
362// In both cases, the set of legal distinguished values is:
363// BAD_IL_OFFSET -- A unique illegal IL offset number. Note that it must be different from
364// the ICorDebugInfo values, below, and must also not be a legal IL offset.
365// ICorDebugInfo::NO_MAPPING -- The IL offset corresponds to no source code (such as EH step blocks).
366// ICorDebugInfo::PROLOG -- The IL offset indicates a prolog
367// ICorDebugInfo::EPILOG -- The IL offset indicates an epilog
368//
369// The IL offset must be in the range [0 .. 0x3fffffff]. This is because we steal
370// the top two bits in IL_OFFSETX for flags, but we want the maximum range to be the same
371// for both types. The IL value can't be larger than the maximum IL offset of the function
372// being compiled.
373//
374// Blocks and statements never store one of the ICorDebugInfo values, even for IL_OFFSETX types. These are
375// only stored in the IPmappingDsc struct, ipmdILoffsx field.
376
377typedef unsigned IL_OFFSET;
378
379const IL_OFFSET BAD_IL_OFFSET = 0x80000000;
380const IL_OFFSET MAX_IL_OFFSET = 0x3fffffff;
381
382typedef unsigned IL_OFFSETX; // IL_OFFSET with stack-empty or call-instruction bit
383const IL_OFFSETX IL_OFFSETX_STKBIT = 0x80000000; // Note: this bit is set when the stack is NOT empty!
384const IL_OFFSETX IL_OFFSETX_CALLINSTRUCTIONBIT = 0x40000000; // Set when the IL offset is for a call instruction.
385const IL_OFFSETX IL_OFFSETX_BITS = IL_OFFSETX_STKBIT | IL_OFFSETX_CALLINSTRUCTIONBIT;
386
387IL_OFFSET jitGetILoffs(IL_OFFSETX offsx);
388IL_OFFSET jitGetILoffsAny(IL_OFFSETX offsx);
389bool jitIsStackEmpty(IL_OFFSETX offsx);
390bool jitIsCallInstruction(IL_OFFSETX offsx);
391
392const unsigned BAD_VAR_NUM = UINT_MAX;
393
394// Code can't be more than 2^31 in any direction. This is signed, so it should be used for anything that is
395// relative to something else.
396typedef int NATIVE_OFFSET;
397
398// This is the same as the above, but it's used in absolute contexts (i.e. offset from the start). Also,
399// this is used for native code sizes.
400typedef unsigned UNATIVE_OFFSET;
401
402typedef ptrdiff_t ssize_t;
403
404// For the following specially handled FIELD_HANDLES we need
405// values that are negative and have the low two bits zero
406// See eeFindJitDataOffs and eeGetJitDataOffs in Compiler.hpp
407#define FLD_GLOBAL_DS ((CORINFO_FIELD_HANDLE)-4)
408#define FLD_GLOBAL_FS ((CORINFO_FIELD_HANDLE)-8)
409
410/*****************************************************************************/
411
412#include "vartype.h"
413
414/*****************************************************************************/
415
416// Late disassembly is OFF by default. Can be turned ON by
417// adding /DLATE_DISASM=1 on the command line.
418// Always OFF in the non-debug version
419
420#if defined(LATE_DISASM) && (LATE_DISASM == 0)
421#undef LATE_DISASM
422#endif
423
424/*****************************************************************************/
425
426/*****************************************************************************/
427
428#define FEATURE_VALNUM_CSE 1 // enable the Value Number CSE optimization logic
429
430// true if Value Number CSE is enabled
431#define FEATURE_ANYCSE FEATURE_VALNUM_CSE
432
433#define CSE_INTO_HANDLERS 0
434
435#define LARGE_EXPSET 1 // Track 64 or 32 assertions/copies/consts/rangechecks
436#define ASSERTION_PROP 1 // Enable value/assertion propagation
437
438#define LOCAL_ASSERTION_PROP ASSERTION_PROP // Enable local assertion propagation
439
440//=============================================================================
441
442#define OPT_BOOL_OPS 1 // optimize boolean operations
443
444//=============================================================================
445
446#define REDUNDANT_LOAD 1 // track locals in regs, suppress loads
447#define STACK_PROBES 0 // Support for stack probes
448#define DUMP_FLOWGRAPHS DEBUG // Support for creating Xml Flowgraph reports in *.fgx files
449
450#define HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION 1 // if 1 we must have all handler entry points in the Hot code section
451
452/*****************************************************************************/
453
454#define VPTR_OFFS 0 // offset of vtable pointer from obj ptr
455
456/*****************************************************************************/
457
458#define DUMP_GC_TABLES DEBUG
459#define VERIFY_GC_TABLES 0
460#define REARRANGE_ADDS 1
461
462#define FUNC_INFO_LOGGING 1 // Support dumping function info to a file. In retail, only NYIs, with no function name,
463 // are dumped.
464
465/*****************************************************************************/
466/*****************************************************************************/
467/* Set these to 1 to collect and output various statistics about the JIT */
468
469#define CALL_ARG_STATS 0 // Collect stats about calls and call arguments.
470#define COUNT_BASIC_BLOCKS 0 // Create a histogram of basic block sizes, and a histogram of IL sizes in the simple
471 // case of single block methods.
472#define COUNT_LOOPS 0 // Collect stats about loops, such as the total number of natural loops, a histogram of
473 // the number of loop exits, etc.
474#define DATAFLOW_ITER 0 // Count iterations in lexical CSE and constant folding dataflow.
475#define DISPLAY_SIZES 0 // Display generated code, data, and GC information sizes.
476#define MEASURE_BLOCK_SIZE 0 // Collect stats about basic block and flowList node sizes and memory allocations.
477#define MEASURE_FATAL 0 // Count the number of calls to fatal(), including NYIs and noway_asserts.
478#define MEASURE_NODE_SIZE 0 // Collect stats about GenTree node allocations.
479#define MEASURE_PTRTAB_SIZE 0 // Collect stats about GC pointer table allocations.
480#define EMITTER_STATS 0 // Collect stats on the emitter.
481#define NODEBASH_STATS 0 // Collect stats on changed gtOper values in GenTree's.
482#define COUNT_AST_OPERS 0 // Display use counts for GenTree operators.
483
484#define VERBOSE_SIZES 0 // Always display GC info sizes. If set, DISPLAY_SIZES must also be set.
485#define VERBOSE_VERIFY 0 // Dump additional information when verifying code. Useful to debug verification bugs.
486
487#ifdef DEBUG
488#define MEASURE_MEM_ALLOC 1 // Collect memory allocation stats.
489#define LOOP_HOIST_STATS 1 // Collect loop hoisting stats.
490#define TRACK_LSRA_STATS 1 // Collect LSRA stats
491#else
492#define MEASURE_MEM_ALLOC 0 // You can set this to 1 to get memory stats in retail, as well
493#define LOOP_HOIST_STATS 0 // You can set this to 1 to get loop hoist stats in retail, as well
494#define TRACK_LSRA_STATS 0 // You can set this to 1 to get LSRA stats in retail, as well
495#endif
496
497// Timing calls to clr.dll is only available under certain conditions.
498#ifndef FEATURE_JIT_METHOD_PERF
499#define MEASURE_CLRAPI_CALLS 0 // Can't time these calls without METHOD_PERF.
500#endif
501#ifdef DEBUG
502#define MEASURE_CLRAPI_CALLS 0 // No point in measuring DEBUG code.
503#endif
504#if !defined(_HOST_X86_) && !defined(_HOST_AMD64_)
505#define MEASURE_CLRAPI_CALLS 0 // Cycle counters only hooked up on x86/x64.
506#endif
507#if !defined(_MSC_VER) && !defined(__clang__)
508#define MEASURE_CLRAPI_CALLS 0 // Only know how to do this with VC and Clang.
509#endif
510
511// If none of the above set the flag to 0, it's available.
512#ifndef MEASURE_CLRAPI_CALLS
513#define MEASURE_CLRAPI_CALLS 0 // Set to 1 to measure time in ICorJitInfo calls.
514#endif
515
516/*****************************************************************************/
517/* Portability Defines */
518/*****************************************************************************/
519#ifdef _TARGET_X86_
520#define JIT32_GCENCODER
521#endif
522
523/*****************************************************************************/
524#ifdef DEBUG
525/*****************************************************************************/
526
527#define DUMPER
528
529#else // !DEBUG
530
531#if DUMP_GC_TABLES
532#pragma message("NOTE: this non-debug build has GC ptr table dumping always enabled!")
533const bool dspGCtbls = true;
534#endif
535
536/*****************************************************************************/
537#endif // !DEBUG
538
539#ifdef DEBUG
540#define JITDUMP(...) \
541 { \
542 if (JitTls::GetCompiler()->verbose) \
543 logf(__VA_ARGS__); \
544 }
545#define JITLOG(x) \
546 { \
547 JitLogEE x; \
548 }
549#define JITLOG_THIS(t, x) \
550 { \
551 (t)->JitLogEE x; \
552 }
553#define DBEXEC(flg, expr) \
554 if (flg) \
555 { \
556 expr; \
557 }
558#define DISPNODE(t) \
559 if (JitTls::GetCompiler()->verbose) \
560 JitTls::GetCompiler()->gtDispTree(t, nullptr, nullptr, true);
561#define DISPTREE(t) \
562 if (JitTls::GetCompiler()->verbose) \
563 JitTls::GetCompiler()->gtDispTree(t);
564#define DISPRANGE(range) \
565 if (JitTls::GetCompiler()->verbose) \
566 JitTls::GetCompiler()->gtDispRange(range);
567#define DISPTREERANGE(range, t) \
568 if (JitTls::GetCompiler()->verbose) \
569 JitTls::GetCompiler()->gtDispTreeRange(range, t);
570#define VERBOSE JitTls::GetCompiler()->verbose
571#else // !DEBUG
572#define JITDUMP(...)
573#define JITLOG(x)
574#define JITLOG_THIS(t, x)
575#define DBEXEC(flg, expr)
576#define DISPNODE(t)
577#define DISPTREE(t)
578#define DISPRANGE(range)
579#define DISPTREERANGE(range, t)
580#define VERBOSE 0
581#endif // !DEBUG
582
583/*****************************************************************************
584 *
585 * Double alignment. This aligns ESP to 0 mod 8 in function prolog, then uses ESP
586 * to reference locals, EBP to reference parameters.
587 * It only makes sense if frameless method support is on.
588 * (frameless method support is now always on)
589 */
590
591#ifdef _TARGET_X86_
592#define DOUBLE_ALIGN 1 // permit the double alignment of ESP in prolog,
593 // and permit the double alignment of local offsets
594#else
595#define DOUBLE_ALIGN 0 // no special handling for double alignment
596#endif
597
598#ifdef DEBUG
599
600struct JitOptions
601{
602 const char* methodName; // Method to display output for
603 const char* className; // Class to display output for
604
605 double CGknob; // Tweakable knob for testing
606 unsigned testMask; // Tweakable mask for testing
607
608 JitOptions* lastDummyField; // Ensures instantiation uses right order of arguments
609};
610
611extern JitOptions jitOpts;
612
613// Forward declarations for UninitializedWord and IsUninitialized are needed by alloc.h
614template <typename T>
615inline T UninitializedWord(Compiler* comp);
616
617template <typename T>
618inline bool IsUninitialized(T data);
619
620#endif // DEBUG
621
622/*****************************************************************************/
623
624enum accessLevel
625{
626 ACL_NONE,
627 ACL_PRIVATE,
628 ACL_DEFAULT,
629 ACL_PROTECTED,
630 ACL_PUBLIC,
631};
632
633/*****************************************************************************/
634
635#define castto(var, typ) (*(typ*)&var)
636
637#define sizeto(typ, mem) (offsetof(typ, mem) + sizeof(((typ*)0)->mem))
638
639/*****************************************************************************/
640
641#ifdef NO_MISALIGNED_ACCESS
642
643#define MISALIGNED_RD_I2(src) (*castto(src, char*) | *castto(src + 1, char*) << 8)
644
645#define MISALIGNED_RD_U2(src) (*castto(src, char*) | *castto(src + 1, char*) << 8)
646
647#define MISALIGNED_WR_I2(dst, val) \
648 *castto(dst, char*) = val; \
649 *castto(dst + 1, char*) = val >> 8;
650
651#define MISALIGNED_WR_I4(dst, val) \
652 *castto(dst, char*) = val; \
653 *castto(dst + 1, char*) = val >> 8; \
654 *castto(dst + 2, char*) = val >> 16; \
655 *castto(dst + 3, char*) = val >> 24;
656
657#else
658
659#define MISALIGNED_RD_I2(src) (*castto(src, short*))
660#define MISALIGNED_RD_U2(src) (*castto(src, unsigned short*))
661
662#define MISALIGNED_WR_I2(dst, val) *castto(dst, short*) = val;
663#define MISALIGNED_WR_I4(dst, val) *castto(dst, int*) = val;
664
665#define MISALIGNED_WR_ST(dst, val) *castto(dst, ssize_t*) = val;
666
667#endif
668
669/*****************************************************************************/
670
671inline size_t roundUp(size_t size, size_t mult = sizeof(size_t))
672{
673 assert(mult && ((mult & (mult - 1)) == 0)); // power of two test
674
675 return (size + (mult - 1)) & ~(mult - 1);
676}
677
678inline size_t roundDn(size_t size, size_t mult = sizeof(size_t))
679{
680 assert(mult && ((mult & (mult - 1)) == 0)); // power of two test
681
682 return (size) & ~(mult - 1);
683}
684
685#ifdef _HOST_64BIT_
686inline unsigned int roundUp(unsigned size, unsigned mult)
687{
688 return (unsigned int)roundUp((size_t)size, (size_t)mult);
689}
690
691inline unsigned int roundDn(unsigned size, unsigned mult)
692{
693 return (unsigned int)roundDn((size_t)size, (size_t)mult);
694}
695#endif // _HOST_64BIT_
696
697inline unsigned int unsigned_abs(int x)
698{
699 return ((unsigned int)abs(x));
700}
701
702#ifdef _TARGET_64BIT_
703inline size_t unsigned_abs(ssize_t x)
704{
705 return ((size_t)abs(x));
706}
707#endif // _TARGET_64BIT_
708
709/*****************************************************************************/
710
711#if CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE || MEASURE_MEM_ALLOC
712
713#define HISTOGRAM_MAX_SIZE_COUNT 64
714
715class Histogram
716{
717public:
718 Histogram(const unsigned* const sizeTable);
719
720 void dump(FILE* output);
721 void record(unsigned size);
722
723private:
724 unsigned m_sizeCount;
725 const unsigned* const m_sizeTable;
726 unsigned m_counts[HISTOGRAM_MAX_SIZE_COUNT];
727};
728
729#endif // CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE
730
731/*****************************************************************************/
732#ifdef ICECAP
733#include "icapexp.h"
734#include "icapctrl.h"
735#endif
736
737/*****************************************************************************/
738
739#include "error.h"
740
741/*****************************************************************************/
742
743#if CHECK_STRUCT_PADDING
744#pragma warning(push)
745#pragma warning(default : 4820) // 'bytes' bytes padding added after construct 'member_name'
746#endif // CHECK_STRUCT_PADDING
747#include "alloc.h"
748#include "target.h"
749
750#if FEATURE_TAILCALL_OPT
751
752#ifdef FEATURE_CORECLR
753// CoreCLR - enable tail call opt for the following IL pattern
754//
755// call someFunc
756// jmp/jcc RetBlock
757// ...
758// RetBlock:
759// ret
760#define FEATURE_TAILCALL_OPT_SHARED_RETURN 1
761#else
762// Desktop: Keep this to zero as one of app-compat apps that is using GetCallingAssembly()
763// has an issue turning this ON.
764//
765// Refer to TF: Bug: 824625 and its associated regression TF Bug: 1113265
766#define FEATURE_TAILCALL_OPT_SHARED_RETURN 0
767#endif // FEATURE_CORECLR
768
769#else // !FEATURE_TAILCALL_OPT
770#define FEATURE_TAILCALL_OPT_SHARED_RETURN 0
771#endif // !FEATURE_TAILCALL_OPT
772
773#define CLFLG_CODESIZE 0x00001
774#define CLFLG_CODESPEED 0x00002
775#define CLFLG_CSE 0x00004
776#define CLFLG_REGVAR 0x00008
777#define CLFLG_RNGCHKOPT 0x00010
778#define CLFLG_DEADASGN 0x00020
779#define CLFLG_CODEMOTION 0x00040
780#define CLFLG_QMARK 0x00080
781#define CLFLG_TREETRANS 0x00100
782#define CLFLG_INLINING 0x00200
783#define CLFLG_CONSTANTFOLD 0x00800
784
785#if FEATURE_STRUCTPROMOTE
786#define CLFLG_STRUCTPROMOTE 0x00400
787#else
788#define CLFLG_STRUCTPROMOTE 0x00000
789#endif
790
791#define CLFLG_MAXOPT \
792 (CLFLG_CSE | CLFLG_REGVAR | CLFLG_RNGCHKOPT | CLFLG_DEADASGN | CLFLG_CODEMOTION | CLFLG_QMARK | CLFLG_TREETRANS | \
793 CLFLG_INLINING | CLFLG_STRUCTPROMOTE | CLFLG_CONSTANTFOLD)
794
795#define CLFLG_MINOPT (CLFLG_TREETRANS)
796
797#define JIT_RESERVED_STACK 64 // Reserved for arguments of calls and hidden
798 // pushes for finallys so that we don't
799 // probe on every call site. See comment in
800 // for CORINFO_STACKPROBE_DEPTH in corjit.h
801
802/*****************************************************************************/
803
804extern void dumpILBytes(const BYTE* const codeAddr, unsigned codeSize, unsigned alignSize);
805
806extern unsigned dumpSingleInstr(const BYTE* const codeAddr, IL_OFFSET offs, const char* prefix = nullptr);
807
808extern void dumpILRange(const BYTE* const codeAddr, unsigned codeSize); // in bytes
809
810/*****************************************************************************/
811
812extern int jitNativeCode(CORINFO_METHOD_HANDLE methodHnd,
813 CORINFO_MODULE_HANDLE classHnd,
814 COMP_HANDLE compHnd,
815 CORINFO_METHOD_INFO* methodInfo,
816 void** methodCodePtr,
817 ULONG* methodCodeSize,
818 JitFlags* compileFlags,
819 void* inlineInfoPtr);
820
821#ifdef _HOST_64BIT_
822const size_t INVALID_POINTER_VALUE = 0xFEEDFACEABADF00D;
823#else
824const size_t INVALID_POINTER_VALUE = 0xFEEDFACE;
825#endif
826
827// Constants for making sure size_t fit into smaller types.
828const size_t MAX_USHORT_SIZE_T = static_cast<size_t>(static_cast<unsigned short>(-1));
829const size_t MAX_UNSIGNED_SIZE_T = static_cast<size_t>(static_cast<unsigned>(-1));
830
831// These assume 2's complement...
832const int MAX_SHORT_AS_INT = 32767;
833const int MIN_SHORT_AS_INT = -32768;
834
835/*****************************************************************************/
836
837class Compiler;
838
839class JitTls
840{
841#ifdef DEBUG
842 Compiler* m_compiler;
843 LogEnv m_logEnv;
844 JitTls* m_next;
845#endif
846
847public:
848 JitTls(ICorJitInfo* jitInfo);
849 ~JitTls();
850
851#ifdef DEBUG
852 static LogEnv* GetLogEnv();
853#endif
854
855 static Compiler* GetCompiler();
856 static void SetCompiler(Compiler* compiler);
857};
858
859#if defined(DEBUG)
860// Include the definition of Compiler for use by these template functions
861//
862#include "compiler.h"
863
864//****************************************************************************
865//
866// Returns a word filled with the JITs allocator default fill value.
867//
868template <typename T>
869inline T UninitializedWord(Compiler* comp)
870{
871 unsigned char defaultFill = 0xdd;
872 if (comp == nullptr)
873 {
874 comp = JitTls::GetCompiler();
875 }
876 defaultFill = comp->compGetJitDefaultFill();
877 assert(defaultFill <= 0xff);
878 __int64 word = 0x0101010101010101LL * defaultFill;
879 return (T)word;
880}
881
882//****************************************************************************
883//
884// Tries to determine if this value is coming from uninitialized JIT memory
885// - Returns true if the value matches what we initialized the memory to.
886//
887// Notes:
888// - Asserts that use this are assuming that the UninitializedWord value
889// isn't a legal value for 'data'. Thus using a default fill value of
890// 0x00 will often trigger such asserts.
891//
892template <typename T>
893inline bool IsUninitialized(T data)
894{
895 return data == UninitializedWord<T>(JitTls::GetCompiler());
896}
897
898#pragma warning(push)
899#pragma warning(disable : 4312)
900//****************************************************************************
901//
902// Debug template definitions for dspPtr, dspOffset
903// - Used to format pointer/offset values for diffable Disasm
904//
905template <typename T>
906T dspPtr(T p)
907{
908 return (p == ZERO) ? ZERO : (JitTls::GetCompiler()->opts.dspDiffable ? T(0xD1FFAB1E) : p);
909}
910
911template <typename T>
912T dspOffset(T o)
913{
914 return (o == ZERO) ? ZERO : (JitTls::GetCompiler()->opts.dspDiffable ? T(0xD1FFAB1E) : o);
915}
916#pragma warning(pop)
917
918#else // !defined(DEBUG)
919
920//****************************************************************************
921//
922// Non-Debug template definitions for dspPtr, dspOffset
923// - This is a nop in non-Debug builds
924//
925template <typename T>
926T dspPtr(T p)
927{
928 return p;
929}
930
931template <typename T>
932T dspOffset(T o)
933{
934 return o;
935}
936
937#endif // !defined(DEBUG)
938
939/*****************************************************************************/
940#endif //_JIT_H_
941/*****************************************************************************/
942