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.
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10 XX Has miscellaneous utility functions XX
12 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
13 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
23 /*****************************************************************************/
24 // Define the string platform name based on compilation #ifdefs. This is the
25 // same code for all platforms, hence it is here instead of in the targetXXX.cpp
29 // Should we distinguish Mac? Can we?
30 // Should we distinguish flavors of Unix? Can we?
31 const char* Target::g_tgtPlatformName = "Unix";
32 #else // !_TARGET_UNIX_
33 const char* Target::g_tgtPlatformName = "Windows";
34 #endif // !_TARGET_UNIX_
36 /*****************************************************************************/
42 const signed char opcodeSizes[] =
44 #define InlineNone_size 0
45 #define ShortInlineVar_size 1
46 #define InlineVar_size 2
47 #define ShortInlineI_size 1
48 #define InlineI_size 4
49 #define InlineI8_size 8
50 #define ShortInlineR_size 4
51 #define InlineR_size 8
52 #define ShortInlineBrTarget_size 1
53 #define InlineBrTarget_size 4
54 #define InlineMethod_size 4
55 #define InlineField_size 4
56 #define InlineType_size 4
57 #define InlineString_size 4
58 #define InlineSig_size 4
59 #define InlineRVA_size 4
60 #define InlineTok_size 4
61 #define InlineSwitch_size 0 // for now
62 #define InlinePhi_size 0 // for now
63 #define InlineVarTok_size 0 // remove
65 #define OPDEF(name,string,pop,push,oprType,opcType,l,s1,s2,ctrl) oprType ## _size ,
69 #undef InlineNone_size
70 #undef ShortInlineVar_size
72 #undef ShortInlineI_size
75 #undef ShortInlineR_size
77 #undef ShortInlineBrTarget_size
78 #undef InlineBrTarget_size
79 #undef InlineMethod_size
80 #undef InlineField_size
81 #undef InlineType_size
82 #undef InlineString_size
86 #undef InlineSwitch_size
91 const BYTE varTypeClassification[] = {
92 #define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) tf,
97 /*****************************************************************************/
98 /*****************************************************************************/
100 extern const char* const opcodeNames[] = {
101 #define OPDEF(name, string, pop, push, oprType, opcType, l, s1, s2, ctrl) string,
102 #include "opcode.def"
106 extern const BYTE opcodeArgKinds[] = {
107 #define OPDEF(name, string, pop, push, oprType, opcType, l, s1, s2, ctrl) (BYTE) oprType,
108 #include "opcode.def"
113 /*****************************************************************************/
115 const char* varTypeName(var_types vt)
117 static const char* const varTypeNames[] = {
118 #define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) nm,
119 #include "typelist.h"
123 assert((unsigned)vt < _countof(varTypeNames));
125 return varTypeNames[vt];
128 #if defined(DEBUG) || defined(LATE_DISASM)
129 /*****************************************************************************
131 * Return the name of the given register.
134 const char* getRegName(regNumber reg, bool isFloat)
136 // Special-case REG_NA; it's not in the regNames array, but we might want to print it.
141 #if defined(_TARGET_X86_) && defined(LEGACY_BACKEND)
142 static const char* const regNames[] = {
143 #define REGDEF(name, rnum, mask, sname) sname,
144 #include "register.h"
147 static const char* const floatRegNames[] = {
148 #define REGDEF(name, rnum, mask, sname) sname,
149 #include "registerxmm.h"
153 assert(reg < ArrLen(floatRegNames));
154 return floatRegNames[reg];
158 assert(reg < ArrLen(regNames));
159 return regNames[reg];
161 #elif defined(_TARGET_ARM64_)
162 static const char* const regNames[] = {
163 #define REGDEF(name, rnum, mask, xname, wname) xname,
164 #include "register.h"
166 assert(reg < ArrLen(regNames));
167 return regNames[reg];
169 static const char* const regNames[] = {
170 #define REGDEF(name, rnum, mask, sname) sname,
171 #include "register.h"
173 assert(reg < ArrLen(regNames));
174 return regNames[reg];
178 const char* getRegName(unsigned reg,
179 bool isFloat) // this is for gcencode.cpp and disasm.cpp that dont use the regNumber type
181 return getRegName((regNumber)reg, isFloat);
183 #endif // defined(DEBUG) || defined(LATE_DISASM)
187 const char* getRegNameFloat(regNumber reg, var_types type)
190 assert(genIsValidFloatReg(reg));
191 if (type == TYP_FLOAT)
192 return getRegName(reg);
200 assert(!"Bad double register");
255 #elif defined(_TARGET_X86_) && defined(LEGACY_BACKEND)
257 static const char* regNamesFloat[] = {
258 #define REGDEF(name, rnum, mask, sname) sname,
259 #include "registerxmm.h"
261 assert((unsigned)reg < ArrLen(regNamesFloat));
263 return regNamesFloat[reg];
265 #elif defined(_TARGET_ARM64_)
267 static const char* regNamesFloat[] = {
268 #define REGDEF(name, rnum, mask, xname, wname) xname,
269 #include "register.h"
271 assert((unsigned)reg < ArrLen(regNamesFloat));
273 return regNamesFloat[reg];
276 static const char* regNamesFloat[] = {
277 #define REGDEF(name, rnum, mask, sname) "x" sname,
278 #include "register.h"
281 static const char* regNamesYMM[] = {
282 #define REGDEF(name, rnum, mask, sname) "y" sname,
283 #include "register.h"
285 #endif // FEATURE_SIMD
286 assert((unsigned)reg < ArrLen(regNamesFloat));
289 if (type == TYP_SIMD32)
291 return regNamesYMM[reg];
293 #endif // FEATURE_SIMD
295 return regNamesFloat[reg];
299 /*****************************************************************************
301 * Displays a register set.
302 * TODO-ARM64-Cleanup: don't allow ip0, ip1 as part of a range.
305 void dspRegMask(regMaskTP regMask, size_t minSiz)
307 const char* sep = "";
311 bool inRegRange = false;
312 regNumber regPrev = REG_NA;
313 regNumber regHead = REG_NA; // When we start a range, remember the first register of the range, so we don't use
314 // range notation if the range contains just a single register.
315 for (regNumber regNum = REG_INT_FIRST; regNum <= REG_INT_LAST; regNum = REG_NEXT(regNum))
317 regMaskTP regBit = genRegMask(regNum);
319 if ((regMask & regBit) != 0)
321 // We have a register to display. It gets displayed now if:
322 // 1. This is the first register to display of a new range of registers (possibly because
323 // no register has ever been displayed).
324 // 2. This is the last register of an acceptable range (either the last integer register,
325 // or the last of a range that is displayed with range notation).
328 // It's the first register of a potential range.
329 const char* nam = getRegName(regNum);
330 printf("%s%s", sep, nam);
331 minSiz -= strlen(sep) + strlen(nam);
333 // By default, we're not starting a potential register range.
336 // What kind of separator should we use for this range (if it is indeed going to be a range)?
337 CLANG_FORMAT_COMMENT_ANCHOR;
339 #if defined(_TARGET_AMD64_)
340 // For AMD64, create ranges for int registers R8 through R15, but not the "old" registers.
341 if (regNum >= REG_R8)
347 #elif defined(_TARGET_ARM64_)
348 // R17 and R28 can't be the start of a range, since the range would include TEB or FP
349 if ((regNum < REG_R17) || ((REG_R19 <= regNum) && (regNum < REG_R28)))
355 #elif defined(_TARGET_ARM_)
356 if (regNum < REG_R12)
362 #elif defined(_TARGET_X86_)
363 // No register ranges
365 #error Unsupported or unset target architecture
369 #if defined(_TARGET_ARM64_)
370 // We've already printed a register. Is this the end of a range?
371 else if ((regNum == REG_INT_LAST) || (regNum == REG_R17) // last register before TEB
372 || (regNum == REG_R28)) // last register before FP
373 #else // _TARGET_ARM64_
374 // We've already printed a register. Is this the end of a range?
375 else if (regNum == REG_INT_LAST)
376 #endif // _TARGET_ARM64_
378 const char* nam = getRegName(regNum);
379 printf("%s%s", sep, nam);
380 minSiz -= strlen(sep) + strlen(nam);
381 inRegRange = false; // No longer in the middle of a register range
386 else // ((regMask & regBit) == 0)
390 assert(regHead != REG_NA);
391 if (regPrev != regHead)
393 // Close out the previous range, if it included more than one register.
394 const char* nam = getRegName(regPrev);
395 printf("%s%s", sep, nam);
396 minSiz -= strlen(sep) + strlen(nam);
404 if (regBit > regMask)
412 #if CPU_HAS_BYTE_REGS
413 if (regMask & RBM_BYTE_REG_FLAG)
415 const char* nam = "BYTE";
416 printf("%s%s", sep, nam);
417 minSiz -= (strlen(sep) + strlen(nam));
421 #if !FEATURE_STACK_FP_X87
424 // We've already printed something.
430 for (regNumber regNum = REG_FP_FIRST; regNum <= REG_FP_LAST; regNum = REG_NEXT(regNum))
432 regMaskTP regBit = genRegMask(regNum);
434 if (regMask & regBit)
436 if (!inRegRange || (regNum == REG_FP_LAST))
438 const char* nam = getRegName(regNum);
439 printf("%s%s", sep, nam);
440 minSiz -= strlen(sep) + strlen(nam);
450 if (regPrev != regHead)
452 const char* nam = getRegName(regPrev);
453 printf("%s%s", sep, nam);
454 minSiz -= (strlen(sep) + strlen(nam));
461 if (regBit > regMask)
472 while ((int)minSiz > 0)
479 //------------------------------------------------------------------------
480 // dumpILBytes: Helper for dumpSingleInstr() to dump hex bytes of an IL stream,
481 // aligning up to a minimum alignment width.
484 // codeAddr - Pointer to IL byte stream to display.
485 // codeSize - Number of bytes of IL byte stream to display.
486 // alignSize - Pad out to this many characters, if fewer than this were written.
488 void dumpILBytes(const BYTE* const codeAddr,
490 unsigned alignSize) // number of characters to write, for alignment
492 for (IL_OFFSET offs = 0; offs < codeSize; ++offs)
494 printf(" %02x", *(codeAddr + offs));
497 unsigned charsWritten = 3 * codeSize;
498 for (unsigned i = charsWritten; i < alignSize; i++)
504 //------------------------------------------------------------------------
505 // dumpSingleInstr: Display a single IL instruction.
508 // codeAddr - Base pointer to a stream of IL instructions.
509 // offs - Offset from codeAddr of the IL instruction to display.
510 // prefix - Optional string to prefix the IL instruction with (if nullptr, no prefix is output).
513 // Size of the displayed IL instruction in the instruction stream, in bytes. (Add this to 'offs' to
514 // get to the next instruction.)
516 unsigned dumpSingleInstr(const BYTE* const codeAddr, IL_OFFSET offs, const char* prefix)
518 const BYTE* opcodePtr = codeAddr + offs;
519 const BYTE* startOpcodePtr = opcodePtr;
520 const unsigned ALIGN_WIDTH = 3 * 6; // assume 3 characters * (1 byte opcode + 4 bytes data + 1 prefix byte) for
523 if (prefix != nullptr)
525 printf("%s", prefix);
528 OPCODE opcode = (OPCODE)getU1LittleEndian(opcodePtr);
529 opcodePtr += sizeof(__int8);
533 if (opcode >= CEE_COUNT)
535 printf("\nIllegal opcode: %02X\n", (int)opcode);
536 return (IL_OFFSET)(opcodePtr - startOpcodePtr);
539 /* Get the size of additional parameters */
541 size_t sz = opcodeSizes[opcode];
542 unsigned argKind = opcodeArgKinds[opcode];
544 /* See what kind of an opcode we have, then */
549 opcode = OPCODE(getU1LittleEndian(opcodePtr) + 256);
550 opcodePtr += sizeof(__int8);
563 dumpILBytes(startOpcodePtr, (unsigned)(opcodePtr - startOpcodePtr), ALIGN_WIDTH);
564 printf(" %-12s", opcodeNames[opcode]);
568 iOp = getU1LittleEndian(opcodePtr);
571 iOp = getI1LittleEndian(opcodePtr);
574 iOp = getU2LittleEndian(opcodePtr);
583 iOp = getI4LittleEndian(opcodePtr);
586 iOp = getU4LittleEndian(opcodePtr);
587 iOp |= (__int64)getU4LittleEndian(opcodePtr + 4) << 32;
591 dumpILBytes(startOpcodePtr, (unsigned)((opcodePtr - startOpcodePtr) + sz), ALIGN_WIDTH);
592 printf(" %-12s 0x%X", opcodeNames[opcode], iOp);
596 dOp = getR4LittleEndian(opcodePtr);
599 dOp = getR8LittleEndian(opcodePtr);
603 dumpILBytes(startOpcodePtr, (unsigned)((opcodePtr - startOpcodePtr) + sz), ALIGN_WIDTH);
604 printf(" %-12s %f", opcodeNames[opcode], dOp);
607 case ShortInlineBrTarget:
608 jOp = getI1LittleEndian(opcodePtr);
611 jOp = getI4LittleEndian(opcodePtr);
615 dumpILBytes(startOpcodePtr, (unsigned)((opcodePtr - startOpcodePtr) + sz), ALIGN_WIDTH);
616 printf(" %-12s %d (IL_%04x)", opcodeNames[opcode], jOp, (int)(opcodePtr + sz - codeAddr) + jOp);
620 jOp2 = getU4LittleEndian(opcodePtr);
622 opcodePtr += jOp2 * 4; // Jump over the table
623 dumpILBytes(startOpcodePtr, (unsigned)(opcodePtr - startOpcodePtr), ALIGN_WIDTH);
624 printf(" %-12s", opcodeNames[opcode]);
628 jOp2 = getU1LittleEndian(opcodePtr);
630 opcodePtr += jOp2 * 2; // Jump over the table
631 dumpILBytes(startOpcodePtr, (unsigned)(opcodePtr - startOpcodePtr), ALIGN_WIDTH);
632 printf(" %-12s", opcodeNames[opcode]);
636 assert(!"Bad argKind");
645 return (IL_OFFSET)(opcodePtr - startOpcodePtr);
648 //------------------------------------------------------------------------
649 // dumpILRange: Display a range of IL instructions from an IL instruction stream.
652 // codeAddr - Pointer to IL byte stream to display.
653 // codeSize - Number of bytes of IL byte stream to display.
655 void dumpILRange(const BYTE* const codeAddr, unsigned codeSize) // in bytes
657 for (IL_OFFSET offs = 0; offs < codeSize;)
660 sprintf_s(prefix, _countof(prefix), "IL_%04x ", offs);
661 unsigned codeBytesDumped = dumpSingleInstr(codeAddr, offs, prefix);
662 offs += codeBytesDumped;
666 /*****************************************************************************
668 * Display a variable set.
670 const char* genES2str(BitVecTraits* traits, EXPSET_TP set)
672 const int bufSize = 17;
673 static char num1[bufSize];
675 static char num2[bufSize];
677 static char* nump = num1;
681 nump = (nump == num1) ? num2 : num1;
683 sprintf_s(temp, bufSize, "%s", BitVecOps::ToString(traits, set));
688 const char* refCntWtd2str(unsigned refCntWtd)
690 const int bufSize = 17;
691 static char num1[bufSize];
693 static char num2[bufSize];
695 static char* nump = num1;
699 nump = (nump == num1) ? num2 : num1;
701 if (refCntWtd == BB_MAX_WEIGHT)
703 sprintf_s(temp, bufSize, "MAX ");
707 unsigned valueInt = refCntWtd / BB_UNITY_WEIGHT;
708 unsigned valueFrac = refCntWtd % BB_UNITY_WEIGHT;
712 sprintf_s(temp, bufSize, "%u ", valueInt);
716 sprintf_s(temp, bufSize, "%u.%02u", valueInt, (valueFrac * 100 / BB_UNITY_WEIGHT));
724 #if defined(DEBUG) || defined(INLINE_DATA)
726 //------------------------------------------------------------------------
727 // Contains: check if the range includes a particular method
730 // info -- jit interface pointer
731 // method -- method handle for the method of interest
733 bool ConfigMethodRange::Contains(ICorJitInfo* info, CORINFO_METHOD_HANDLE method)
735 _ASSERT(m_inited == 1);
737 // No ranges specified means all methods included.
738 if (m_lastRange == 0)
743 // Check the hash. Note we can't use the cached hash here since
744 // we may not be asking about the method currently being jitted.
745 const unsigned hash = info->getMethodHash(method);
747 for (unsigned i = 0; i < m_lastRange; i++)
749 if ((m_ranges[i].m_low <= hash) && (hash <= m_ranges[i].m_high))
758 //------------------------------------------------------------------------
759 // InitRanges: parse the range string and set up the range info
762 // rangeStr -- string to parse (may be nullptr)
763 // capacity -- number ranges to allocate in the range array
766 // Does some internal error checking; clients can use Error()
767 // to determine if the range string couldn't be fully parsed
768 // because of bad characters or too many entries, or had values
769 // that were too large to represent.
771 void ConfigMethodRange::InitRanges(const wchar_t* rangeStr, unsigned capacity)
773 // Make sure that the memory was zero initialized
774 assert(m_inited == 0 || m_inited == 1);
775 assert(m_entries == 0);
776 assert(m_ranges == nullptr);
777 assert(m_lastRange == 0);
779 // Flag any crazy-looking requests
780 assert(capacity < 100000);
782 if (rangeStr == nullptr)
788 // Allocate some persistent memory
789 ICorJitHost* jitHost = g_jitHost;
790 m_ranges = (Range*)jitHost->allocateMemory(capacity * sizeof(Range));
791 m_entries = capacity;
793 const wchar_t* p = rangeStr;
794 unsigned lastRange = 0;
795 bool setHighPart = false;
797 while ((*p != 0) && (lastRange < m_entries))
806 while (L'0' <= *p && *p <= L'9')
808 int j = 10 * i + ((*p++) - L'0');
810 // Check for overflow
811 if ((m_badChar != 0) && (j <= i))
813 m_badChar = (p - rangeStr) + 1;
819 // Was this the high part of a low-high pair?
822 // Yep, set it and move to the next range
823 m_ranges[lastRange].m_high = i;
825 // Sanity check that range is proper
826 if ((m_badChar != 0) && (m_ranges[lastRange].m_high < m_ranges[lastRange].m_low))
828 m_badChar = (p - rangeStr) + 1;
836 // Must have been looking for the low part of a range
837 m_ranges[lastRange].m_low = i;
844 // Was that the low part of a low-high pair?
847 // Yep, skip the dash and set high part next time around.
853 // Else we have a point range, so set high = low
854 m_ranges[lastRange].m_high = i;
858 // If we didn't parse the full range string, note index of the the
860 if ((m_badChar != 0) && (*p != 0))
862 m_badChar = (p - rangeStr) + 1;
865 // Finish off any remaining open range
868 m_ranges[lastRange].m_high = UINT_MAX;
872 assert(lastRange <= m_entries);
873 m_lastRange = lastRange;
877 #endif // defined(DEBUG) || defined(INLINE_DATA)
879 #if CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE || MEASURE_MEM_ALLOC
881 /*****************************************************************************
885 Histogram::Histogram(const unsigned* const sizeTable) : m_sizeTable(sizeTable)
887 unsigned sizeCount = 0;
891 } while ((sizeTable[sizeCount] != 0) && (sizeCount < 1000));
893 assert(sizeCount < HISTOGRAM_MAX_SIZE_COUNT - 1);
895 m_sizeCount = sizeCount;
897 memset(m_counts, 0, (m_sizeCount + 1) * sizeof(*m_counts));
900 void Histogram::dump(FILE* output)
903 for (unsigned i = 0; i < m_sizeCount; i++)
908 for (unsigned c = 0, i = 0; i <= m_sizeCount; i++)
910 if (i == m_sizeCount)
912 if (m_counts[i] == 0)
917 fprintf(output, " > %7u", m_sizeTable[i - 1]);
923 fprintf(output, " <= ");
927 fprintf(output, "%7u .. ", m_sizeTable[i - 1] + 1);
930 fprintf(output, "%7u", m_sizeTable[i]);
935 fprintf(output, " ===> %7u count (%3u%% of total)\n", m_counts[i], (int)(100.0 * c / t));
939 void Histogram::record(unsigned size)
942 for (i = 0; i < m_sizeCount; i++)
944 if (m_sizeTable[i] >= size)
953 #endif // CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE
955 /*****************************************************************************
956 * Fixed bit vector class
959 // bitChunkSize() - Returns number of bits in a bitVect chunk
960 inline UINT FixedBitVect::bitChunkSize()
962 return sizeof(UINT) * 8;
965 // bitNumToBit() - Returns a bit mask of the given bit number
966 inline UINT FixedBitVect::bitNumToBit(UINT bitNum)
968 assert(bitNum < bitChunkSize());
969 assert(bitChunkSize() <= sizeof(int) * 8);
974 // bitVectInit() - Initializes a bit vector of a given size
975 FixedBitVect* FixedBitVect::bitVectInit(UINT size, Compiler* comp)
977 UINT bitVectMemSize, numberOfChunks;
982 numberOfChunks = (size - 1) / bitChunkSize() + 1;
983 bitVectMemSize = numberOfChunks * (bitChunkSize() / 8); // size in bytes
985 assert(bitVectMemSize * bitChunkSize() >= size);
987 bv = (FixedBitVect*)comp->compGetMem(sizeof(FixedBitVect) + bitVectMemSize, CMK_FixedBitVect);
988 memset(bv->bitVect, 0, bitVectMemSize);
990 bv->bitVectSize = size;
995 // bitVectSet() - Sets the given bit
996 void FixedBitVect::bitVectSet(UINT bitNum)
1000 assert(bitNum <= bitVectSize);
1002 index = bitNum / bitChunkSize();
1003 bitNum -= index * bitChunkSize();
1005 bitVect[index] |= bitNumToBit(bitNum);
1008 // bitVectTest() - Tests the given bit
1009 bool FixedBitVect::bitVectTest(UINT bitNum)
1013 assert(bitNum <= bitVectSize);
1015 index = bitNum / bitChunkSize();
1016 bitNum -= index * bitChunkSize();
1018 return (bitVect[index] & bitNumToBit(bitNum)) != 0;
1021 // bitVectOr() - Or in the given bit vector
1022 void FixedBitVect::bitVectOr(FixedBitVect* bv)
1024 UINT bitChunkCnt = (bitVectSize - 1) / bitChunkSize() + 1;
1026 assert(bitVectSize == bv->bitVectSize);
1029 for (UINT i = 0; i < bitChunkCnt; i++)
1031 bitVect[i] |= bv->bitVect[i];
1035 // bitVectAnd() - And with passed in bit vector
1036 void FixedBitVect::bitVectAnd(FixedBitVect& bv)
1038 UINT bitChunkCnt = (bitVectSize - 1) / bitChunkSize() + 1;
1040 assert(bitVectSize == bv.bitVectSize);
1043 for (UINT i = 0; i < bitChunkCnt; i++)
1045 bitVect[i] &= bv.bitVect[i];
1049 // bitVectGetFirst() - Find the first bit on and return bit num,
1050 // Return -1 if no bits found.
1051 UINT FixedBitVect::bitVectGetFirst()
1053 return bitVectGetNext((UINT)-1);
1056 // bitVectGetNext() - Find the next bit on given previous position and return bit num.
1057 // Return -1 if no bits found.
1058 UINT FixedBitVect::bitVectGetNext(UINT bitNumPrev)
1060 UINT bitNum = (UINT)-1;
1063 UINT bitChunkCnt = (bitVectSize - 1) / bitChunkSize() + 1;
1066 if (bitNumPrev == (UINT)-1)
1075 index = bitNumPrev / bitChunkSize();
1076 bitNumPrev -= index * bitChunkSize();
1077 bit = bitNumToBit(bitNumPrev);
1078 bitMask = ~(bit | (bit - 1));
1082 for (i = index; i < bitChunkCnt; i++)
1084 UINT bitChunk = bitVect[i] & bitMask;
1088 BitScanForward((ULONG*)&bitNum, bitChunk);
1092 bitMask = 0xFFFFFFFF;
1095 // Empty bit vector?
1096 if (bitNum == (UINT)-1)
1101 bitNum += i * bitChunkSize();
1103 assert(bitNum <= bitVectSize);
1108 // bitVectGetNextAndClear() - Find the first bit on, clear it and return it.
1109 // Return -1 if no bits found.
1110 UINT FixedBitVect::bitVectGetNextAndClear()
1112 UINT bitNum = (UINT)-1;
1113 UINT bitChunkCnt = (bitVectSize - 1) / bitChunkSize() + 1;
1117 for (i = 0; i < bitChunkCnt; i++)
1119 if (bitVect[i] != 0)
1121 BitScanForward((ULONG*)&bitNum, bitVect[i]);
1126 // Empty bit vector?
1127 if (bitNum == (UINT)-1)
1132 // Clear the bit in the right chunk
1133 bitVect[i] &= ~bitNumToBit(bitNum);
1135 bitNum += i * bitChunkSize();
1137 assert(bitNum <= bitVectSize);
1142 int SimpleSprintf_s(__in_ecount(cbBufSize - (pWriteStart - pBufStart)) char* pWriteStart,
1143 __in_ecount(cbBufSize) char* pBufStart,
1145 __in_z const char* fmt,
1150 assert(pWriteStart);
1151 assert((size_t)pBufStart <= (size_t)pWriteStart);
1154 // compute the space left in the buffer.
1155 if ((pBufStart + cbBufSize) < pWriteStart)
1157 NO_WAY("pWriteStart is past end of buffer");
1159 size_t cbSpaceLeft = (size_t)((pBufStart + cbBufSize) - pWriteStart);
1161 va_start(args, fmt);
1162 ret = vsprintf_s(pWriteStart, cbSpaceLeft, const_cast<char*>(fmt), args);
1166 NO_WAY("vsprintf_s failed.");
1173 void hexDump(FILE* dmpf, const char* name, BYTE* addr, size_t size)
1182 fprintf(dmpf, "Hex dump of %s:\n", name);
1184 for (unsigned i = 0; i < size; i++)
1188 fprintf(dmpf, "\n %04X: ", i);
1191 fprintf(dmpf, "%02X ", *addr++);
1194 fprintf(dmpf, "\n\n");
1199 void HelperCallProperties::init()
1201 for (CorInfoHelpFunc helper = CORINFO_HELP_UNDEF; // initialize helper
1202 (helper < CORINFO_HELP_COUNT); // test helper for loop exit
1203 helper = CorInfoHelpFunc(int(helper) + 1)) // update helper to next
1205 // Generally you want initialize these to their most typical/safest result
1207 bool isPure = false; // true if the result only depends upon input args and not any global state
1208 bool noThrow = false; // true if the helper will never throw
1209 bool nonNullReturn = false; // true if the result will never be null or zero
1210 bool isAllocator = false; // true if the result is usually a newly created heap item, or may throw OutOfMemory
1211 bool mutatesHeap = false; // true if any previous heap objects [are|can be] modified
1212 bool mayRunCctor = false; // true if the helper call may cause a static constructor to be run.
1213 bool mayFinalize = false; // true if the helper call allocates an object that may need to run a finalizer
1217 // Arithmetic helpers that cannot throw
1218 case CORINFO_HELP_LLSH:
1219 case CORINFO_HELP_LRSH:
1220 case CORINFO_HELP_LRSZ:
1221 case CORINFO_HELP_LMUL:
1222 case CORINFO_HELP_LNG2DBL:
1223 case CORINFO_HELP_ULNG2DBL:
1224 case CORINFO_HELP_DBL2INT:
1225 case CORINFO_HELP_DBL2LNG:
1226 case CORINFO_HELP_DBL2UINT:
1227 case CORINFO_HELP_DBL2ULNG:
1228 case CORINFO_HELP_FLTREM:
1229 case CORINFO_HELP_DBLREM:
1230 case CORINFO_HELP_FLTROUND:
1231 case CORINFO_HELP_DBLROUND:
1237 // Arithmetic helpers that *can* throw.
1239 // This (or these) are not pure, in that they have "VM side effects"...but they don't mutate the heap.
1240 case CORINFO_HELP_ENDCATCH:
1245 // Arithmetic helpers that may throw
1246 case CORINFO_HELP_LMOD: // Mods throw div-by zero, and signed mods have problems with the smallest integer
1248 case CORINFO_HELP_MOD: // which is not representable as a positive integer.
1249 case CORINFO_HELP_UMOD:
1250 case CORINFO_HELP_ULMOD:
1252 case CORINFO_HELP_UDIV: // Divs throw divide-by-zero.
1253 case CORINFO_HELP_DIV:
1254 case CORINFO_HELP_LDIV:
1255 case CORINFO_HELP_ULDIV:
1257 case CORINFO_HELP_LMUL_OVF:
1258 case CORINFO_HELP_ULMUL_OVF:
1259 case CORINFO_HELP_DBL2INT_OVF:
1260 case CORINFO_HELP_DBL2LNG_OVF:
1261 case CORINFO_HELP_DBL2UINT_OVF:
1262 case CORINFO_HELP_DBL2ULNG_OVF:
1267 // Heap Allocation helpers, these all never return null
1268 case CORINFO_HELP_NEWSFAST:
1269 case CORINFO_HELP_NEWSFAST_ALIGN8:
1272 nonNullReturn = true;
1273 noThrow = true; // only can throw OutOfMemory
1276 case CORINFO_HELP_NEW_CROSSCONTEXT:
1277 case CORINFO_HELP_NEWFAST:
1278 case CORINFO_HELP_READYTORUN_NEW:
1280 mayFinalize = true; // These may run a finalizer
1282 nonNullReturn = true;
1283 noThrow = true; // only can throw OutOfMemory
1286 // These allocation helpers do some checks on the size (and lower bound) inputs,
1287 // and can throw exceptions other than OOM.
1288 case CORINFO_HELP_NEWARR_1_VC:
1289 case CORINFO_HELP_NEWARR_1_ALIGN8:
1292 nonNullReturn = true;
1295 // These allocation helpers do some checks on the size (and lower bound) inputs,
1296 // and can throw exceptions other than OOM.
1297 case CORINFO_HELP_NEW_MDARR:
1298 case CORINFO_HELP_NEWARR_1_DIRECT:
1299 case CORINFO_HELP_NEWARR_1_OBJ:
1300 case CORINFO_HELP_NEWARR_1_R2R_DIRECT:
1301 case CORINFO_HELP_READYTORUN_NEWARR_1:
1303 mayFinalize = true; // These may run a finalizer
1305 nonNullReturn = true;
1308 // Heap Allocation helpers that are also pure
1309 case CORINFO_HELP_STRCNS:
1313 nonNullReturn = true;
1314 noThrow = true; // only can throw OutOfMemory
1317 case CORINFO_HELP_BOX:
1318 nonNullReturn = true;
1320 noThrow = true; // only can throw OutOfMemory
1323 case CORINFO_HELP_BOX_NULLABLE:
1324 // Box Nullable is not a 'pure' function
1325 // It has a Byref argument that it reads the contents of.
1327 // So two calls to Box Nullable that pass the same address (with the same Value Number)
1328 // will produce different results when the contents of the memory pointed to by the Byref changes
1331 noThrow = true; // only can throw OutOfMemory
1334 case CORINFO_HELP_RUNTIMEHANDLE_METHOD:
1335 case CORINFO_HELP_RUNTIMEHANDLE_CLASS:
1336 case CORINFO_HELP_RUNTIMEHANDLE_METHOD_LOG:
1337 case CORINFO_HELP_RUNTIMEHANDLE_CLASS_LOG:
1338 // logging helpers are not technically pure but can be optimized away
1341 nonNullReturn = true;
1344 // type casting helpers
1345 case CORINFO_HELP_ISINSTANCEOFINTERFACE:
1346 case CORINFO_HELP_ISINSTANCEOFARRAY:
1347 case CORINFO_HELP_ISINSTANCEOFCLASS:
1348 case CORINFO_HELP_ISINSTANCEOFANY:
1349 case CORINFO_HELP_READYTORUN_ISINSTANCEOF:
1350 case CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE:
1353 noThrow = true; // These return null for a failing cast
1356 // type casting helpers that throw
1357 case CORINFO_HELP_CHKCASTINTERFACE:
1358 case CORINFO_HELP_CHKCASTARRAY:
1359 case CORINFO_HELP_CHKCASTCLASS:
1360 case CORINFO_HELP_CHKCASTANY:
1361 case CORINFO_HELP_CHKCASTCLASS_SPECIAL:
1362 case CORINFO_HELP_READYTORUN_CHKCAST:
1364 // These throw for a failing cast
1365 // But if given a null input arg will return null
1369 // helpers returning addresses, these can also throw
1370 case CORINFO_HELP_UNBOX:
1371 case CORINFO_HELP_GETREFANY:
1372 case CORINFO_HELP_LDELEMA_REF:
1377 // helpers that return internal handle
1378 case CORINFO_HELP_GETCLASSFROMMETHODPARAM:
1379 case CORINFO_HELP_GETSYNCFROMCLASSHANDLE:
1385 // Helpers that load the base address for static variables.
1386 // We divide these between those that may and may not invoke
1387 // static class constructors.
1388 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
1389 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
1390 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
1391 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
1392 case CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE:
1393 case CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE:
1394 case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
1395 case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE:
1396 case CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS:
1397 case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
1398 case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS:
1399 case CORINFO_HELP_GETSTATICFIELDADDR_CONTEXT:
1400 case CORINFO_HELP_GETSTATICFIELDADDR_TLS:
1401 case CORINFO_HELP_GETGENERICS_GCSTATIC_BASE:
1402 case CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE:
1403 case CORINFO_HELP_READYTORUN_STATIC_BASE:
1404 case CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE:
1406 // These may invoke static class constructors
1407 // These can throw InvalidProgram exception if the class can not be constructed
1410 nonNullReturn = true;
1414 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
1415 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
1416 case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
1417 case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR:
1419 // These do not invoke static class constructors
1423 nonNullReturn = true;
1426 // GC Write barrier support
1427 // TODO-ARM64-Bug?: Can these throw or not?
1428 case CORINFO_HELP_ASSIGN_REF:
1429 case CORINFO_HELP_CHECKED_ASSIGN_REF:
1430 case CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP:
1431 case CORINFO_HELP_ASSIGN_BYREF:
1432 case CORINFO_HELP_ASSIGN_STRUCT:
1437 // Accessing fields (write)
1438 case CORINFO_HELP_SETFIELD32:
1439 case CORINFO_HELP_SETFIELD64:
1440 case CORINFO_HELP_SETFIELDOBJ:
1441 case CORINFO_HELP_SETFIELDSTRUCT:
1442 case CORINFO_HELP_SETFIELDFLOAT:
1443 case CORINFO_HELP_SETFIELDDOUBLE:
1444 case CORINFO_HELP_ARRADDR_ST:
1449 // These helper calls always throw an exception
1450 case CORINFO_HELP_OVERFLOW:
1451 case CORINFO_HELP_VERIFICATION:
1452 case CORINFO_HELP_RNGCHKFAIL:
1453 case CORINFO_HELP_THROWDIVZERO:
1454 case CORINFO_HELP_THROWNULLREF:
1455 case CORINFO_HELP_THROW:
1456 case CORINFO_HELP_RETHROW:
1457 case CORINFO_HELP_THROW_ARGUMENTEXCEPTION:
1458 case CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION:
1459 case CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED:
1460 case CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED:
1464 // These helper calls may throw an exception
1465 case CORINFO_HELP_METHOD_ACCESS_CHECK:
1466 case CORINFO_HELP_FIELD_ACCESS_CHECK:
1467 case CORINFO_HELP_CLASS_ACCESS_CHECK:
1468 case CORINFO_HELP_DELEGATE_SECURITY_CHECK:
1469 case CORINFO_HELP_MON_EXIT_STATIC:
1473 // This is a debugging aid; it simply returns a constant address.
1474 case CORINFO_HELP_LOOP_CLONE_CHOICE_ADDR:
1479 case CORINFO_HELP_DBG_IS_JUST_MY_CODE:
1480 case CORINFO_HELP_BBT_FCN_ENTER:
1481 case CORINFO_HELP_POLL_GC:
1482 case CORINFO_HELP_MON_ENTER:
1483 case CORINFO_HELP_MON_EXIT:
1484 case CORINFO_HELP_MON_ENTER_STATIC:
1485 case CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER:
1486 case CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT:
1487 case CORINFO_HELP_SECURITY_PROLOG:
1488 case CORINFO_HELP_SECURITY_PROLOG_FRAMED:
1489 case CORINFO_HELP_VERIFICATION_RUNTIME_CHECK:
1490 case CORINFO_HELP_GETFIELDADDR:
1491 case CORINFO_HELP_INIT_PINVOKE_FRAME:
1492 case CORINFO_HELP_JIT_PINVOKE_BEGIN:
1493 case CORINFO_HELP_JIT_PINVOKE_END:
1494 case CORINFO_HELP_GETCURRENTMANAGEDTHREADID:
1499 // Not sure how to handle optimization involving the rest of these helpers
1502 // The most pessimistic results are returned for these helpers
1507 m_isPure[helper] = isPure;
1508 m_noThrow[helper] = noThrow;
1509 m_nonNullReturn[helper] = nonNullReturn;
1510 m_isAllocator[helper] = isAllocator;
1511 m_mutatesHeap[helper] = mutatesHeap;
1512 m_mayRunCctor[helper] = mayRunCctor;
1513 m_mayFinalize[helper] = mayFinalize;
1517 //=============================================================================
1518 // AssemblyNamesList2
1519 //=============================================================================
1520 // The string should be of the form
1522 // MyAssembly;mscorlib;System
1523 // MyAssembly;mscorlib System
1525 AssemblyNamesList2::AssemblyNamesList2(const wchar_t* list, HostAllocator* alloc) : m_alloc(alloc)
1527 assert(m_alloc != nullptr);
1529 WCHAR prevChar = '?'; // dummy
1530 LPWSTR nameStart = nullptr; // start of the name currently being processed. nullptr if no current name
1531 AssemblyName** ppPrevLink = &m_pNames;
1533 for (LPWSTR listWalk = const_cast<LPWSTR>(list); prevChar != '\0'; prevChar = *listWalk, listWalk++)
1535 WCHAR curChar = *listWalk;
1537 if (iswspace(curChar) || curChar == W(';') || curChar == W('\0'))
1540 // Found white-space
1545 // Found the end of the current name; add a new assembly name to the list.
1547 AssemblyName* newName = new (m_alloc) AssemblyName();
1549 // Null out the current character so we can do zero-terminated string work; we'll restore it later.
1550 *listWalk = W('\0');
1552 // How much space do we need?
1553 int convertedNameLenBytes =
1554 WszWideCharToMultiByte(CP_UTF8, 0, nameStart, -1, nullptr, 0, nullptr, nullptr);
1555 newName->m_assemblyName = new (m_alloc) char[convertedNameLenBytes]; // convertedNameLenBytes includes
1556 // the trailing null character
1557 if (WszWideCharToMultiByte(CP_UTF8, 0, nameStart, -1, newName->m_assemblyName, convertedNameLenBytes,
1558 nullptr, nullptr) != 0)
1560 *ppPrevLink = newName;
1561 ppPrevLink = &newName->m_next;
1565 // Failed to convert the string. Ignore this string (and leak the memory).
1568 nameStart = nullptr;
1570 // Restore the current character.
1571 *listWalk = curChar;
1574 else if (!nameStart)
1577 // Found the start of a new name
1580 nameStart = listWalk;
1584 assert(nameStart == nullptr); // cannot be in the middle of a name
1585 *ppPrevLink = nullptr; // Terminate the last element of the list.
1588 AssemblyNamesList2::~AssemblyNamesList2()
1590 for (AssemblyName* pName = m_pNames; pName != nullptr; /**/)
1592 AssemblyName* cur = pName;
1593 pName = pName->m_next;
1595 m_alloc->Free(cur->m_assemblyName);
1600 bool AssemblyNamesList2::IsInList(const char* assemblyName)
1602 for (AssemblyName* pName = m_pNames; pName != nullptr; pName = pName->m_next)
1604 if (_stricmp(pName->m_assemblyName, assemblyName) == 0)
1613 #ifdef FEATURE_JIT_METHOD_PERF
1614 CycleCount::CycleCount() : cps(CycleTimer::CyclesPerSecond())
1618 bool CycleCount::GetCycles(unsigned __int64* time)
1620 return CycleTimer::GetThreadCyclesS(time);
1623 bool CycleCount::Start()
1625 return GetCycles(&beginCycles);
1628 double CycleCount::ElapsedTime()
1630 unsigned __int64 nowCycles;
1631 (void)GetCycles(&nowCycles);
1632 return ((double)(nowCycles - beginCycles) / cps) * 1000.0;
1635 bool PerfCounter::Start()
1637 bool result = QueryPerformanceFrequency(&beg) != 0;
1642 freq = (double)beg.QuadPart / 1000.0;
1643 (void)QueryPerformanceCounter(&beg);
1647 // Return elapsed time from Start() in millis.
1648 double PerfCounter::ElapsedTime()
1651 (void)QueryPerformanceCounter(&li);
1652 return (double)(li.QuadPart - beg.QuadPart) / freq;
1659 /*****************************************************************************
1660 * Return the number of digits in a number of the given base (default base 10).
1661 * Used when outputting strings.
1663 unsigned CountDigits(unsigned num, unsigned base /* = 10 */)
1665 assert(2 <= base && base <= 16); // sanity check
1677 double FloatingPointUtils::convertUInt64ToDouble(unsigned __int64 uIntVal)
1679 __int64 s64 = uIntVal;
1683 #if defined(_TARGET_XARCH_)
1684 // RyuJIT codegen and clang (or gcc) may produce different results for casting uint64 to
1685 // double, and the clang result is more accurate. For example,
1686 // 1) (double)0x84595161401484A0UL --> 43e08b2a2c280290 (RyuJIT codegen or VC++)
1687 // 2) (double)0x84595161401484A0UL --> 43e08b2a2c280291 (clang or gcc)
1688 // If the folding optimization below is implemented by simple casting of (double)uint64_val
1689 // and it is compiled by clang, casting result can be inconsistent, depending on whether
1690 // the folding optimization is triggered or the codegen generates instructions for casting. //
1691 // The current solution is to force the same math as the codegen does, so that casting
1692 // result is always consistent.
1694 // d = (double)(int64_t)uint64 + 0x1p64
1695 uint64_t adjHex = 0x43F0000000000000UL;
1696 d = (double)s64 + *(double*)&adjHex;
1698 d = (double)uIntVal;
1703 d = (double)uIntVal;
1708 float FloatingPointUtils::convertUInt64ToFloat(unsigned __int64 u64)
1710 double d = convertUInt64ToDouble(u64);
1714 unsigned __int64 FloatingPointUtils::convertDoubleToUInt64(double d)
1716 unsigned __int64 u64;
1719 // Work around a C++ issue where it doesn't properly convert large positive doubles
1720 const double two63 = 2147483648.0 * 4294967296.0;
1727 // subtract 0x8000000000000000, do the convert then add it back again
1728 u64 = INT64(d - two63) + I64(0x8000000000000000);
1733 #ifdef _TARGET_XARCH_
1735 // While the Ecma spec does not specifically call this out,
1736 // the case of conversion from negative double to unsigned integer is
1737 // effectively an overflow and therefore the result is unspecified.
1738 // With MSVC for x86/x64, such a conversion results in the bit-equivalent
1739 // unsigned value of the conversion to integer. Other compilers convert
1740 // negative doubles to zero when the target is unsigned.
1741 // To make the behavior consistent across OS's on TARGET_XARCH,
1742 // this double cast is needed to conform MSVC behavior.
1744 u64 = UINT64(INT64(d));
1747 #endif // _TARGET_XARCH_
1752 // Rounds a double-precision floating-point value to the nearest integer,
1753 // and rounds midpoint values to the nearest even number.
1754 double FloatingPointUtils::round(double x)
1756 // ************************************************************************************
1757 // IMPORTANT: Do not change this implementation without also updating Math.Round(double),
1758 // MathF.Round(float), and FloatingPointUtils::round(float)
1759 // ************************************************************************************
1761 // If the number has no fractional part do nothing
1762 // This shortcut is necessary to workaround precision loss in borderline cases on some platforms
1764 if (x == (double)((INT64)x))
1769 // We had a number that was equally close to 2 integers.
1770 // We need to return the even one.
1772 double flrTempVal = floor(x + 0.5);
1774 if ((x == (floor(x) + 0.5)) && (fmod(flrTempVal, 2.0) != 0))
1779 return _copysign(flrTempVal, x);
1782 // Windows x86 and Windows ARM/ARM64 may not define _copysignf() but they do define _copysign().
1783 // We will redirect the macro to this other functions if the macro is not defined for the platform.
1784 // This has the side effect of a possible implicit upcasting for arguments passed in and an explicit
1785 // downcasting for the _copysign() call.
1786 #if (defined(_TARGET_X86_) || defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)) && !defined(FEATURE_PAL)
1788 #if !defined(_copysignf)
1789 #define _copysignf (float)_copysign
1794 // Rounds a single-precision floating-point value to the nearest integer,
1795 // and rounds midpoint values to the nearest even number.
1796 float FloatingPointUtils::round(float x)
1798 // ************************************************************************************
1799 // IMPORTANT: Do not change this implementation without also updating MathF.Round(float),
1800 // Math.Round(double), and FloatingPointUtils::round(double)
1801 // ************************************************************************************
1803 // If the number has no fractional part do nothing
1804 // This shortcut is necessary to workaround precision loss in borderline cases on some platforms
1806 if (x == (float)((INT32)x))
1811 // We had a number that was equally close to 2 integers.
1812 // We need to return the even one.
1814 float flrTempVal = floorf(x + 0.5f);
1816 if ((x == (floorf(x) + 0.5f)) && (fmodf(flrTempVal, 2.0f) != 0))
1821 return _copysignf(flrTempVal, x);
1824 namespace MagicDivide
1826 template <int TableBase = 0, int TableSize, typename Magic>
1827 static const Magic* TryGetMagic(const Magic (&table)[TableSize], typename Magic::DivisorType index)
1829 if ((index < TableBase) || (TableBase + TableSize <= index))
1834 const Magic* p = &table[index - TableBase];
1844 template <typename T>
1845 struct UnsignedMagic
1847 typedef T DivisorType;
1854 template <typename T>
1855 const UnsignedMagic<T>* TryGetUnsignedMagic(T divisor)
1861 const UnsignedMagic<uint32_t>* TryGetUnsignedMagic(uint32_t divisor)
1863 static const UnsignedMagic<uint32_t> table[]{
1864 {0xaaaaaaab, false, 1}, // 3
1866 {0xcccccccd, false, 2}, // 5
1867 {0xaaaaaaab, false, 2}, // 6
1868 {0x24924925, true, 3}, // 7
1870 {0x38e38e39, false, 1}, // 9
1871 {0xcccccccd, false, 3}, // 10
1872 {0xba2e8ba3, false, 3}, // 11
1873 {0xaaaaaaab, false, 3}, // 12
1876 return TryGetMagic<3>(table, divisor);
1880 const UnsignedMagic<uint64_t>* TryGetUnsignedMagic(uint64_t divisor)
1882 static const UnsignedMagic<uint64_t> table[]{
1883 {0xaaaaaaaaaaaaaaab, false, 1}, // 3
1885 {0xcccccccccccccccd, false, 2}, // 5
1886 {0xaaaaaaaaaaaaaaab, false, 2}, // 6
1887 {0x2492492492492493, true, 3}, // 7
1889 {0xe38e38e38e38e38f, false, 3}, // 9
1890 {0xcccccccccccccccd, false, 3}, // 10
1891 {0x2e8ba2e8ba2e8ba3, false, 1}, // 11
1892 {0xaaaaaaaaaaaaaaab, false, 3}, // 12
1895 return TryGetMagic<3>(table, divisor);
1898 //------------------------------------------------------------------------
1899 // GetUnsignedMagic: Generates a magic number and shift amount for the magic
1900 // number unsigned division optimization.
1904 // add - Pointer to a flag indicating the kind of code to generate
1905 // shift - Pointer to the shift value to be returned
1908 // The magic number.
1911 // This code is adapted from _The_PowerPC_Compiler_Writer's_Guide_, pages 57-58.
1912 // The paper is based on "Division by invariant integers using multiplication"
1913 // by Torbjorn Granlund and Peter L. Montgomery in PLDI 94
1915 template <typename T>
1916 T GetUnsignedMagic(T d, bool* add /*out*/, int* shift /*out*/)
1918 assert((d >= 3) && !isPow2(d));
1920 const UnsignedMagic<T>* magic = TryGetUnsignedMagic(d);
1922 if (magic != nullptr)
1924 *shift = magic->shift;
1926 return magic->magic;
1929 typedef typename jitstd::make_signed<T>::type ST;
1931 const unsigned bits = sizeof(T) * 8;
1932 const unsigned bitsMinus1 = bits - 1;
1933 const T twoNMinus1 = T(1) << bitsMinus1;
1936 const T nc = -ST(1) - -ST(d) % ST(d);
1937 unsigned p = bitsMinus1;
1938 T q1 = twoNMinus1 / nc;
1939 T r1 = twoNMinus1 - (q1 * nc);
1940 T q2 = (twoNMinus1 - 1) / d;
1941 T r2 = (twoNMinus1 - 1) - (q2 * d);
1948 if (r1 >= (nc - r1))
1959 if ((r2 + 1) >= (d - r2))
1961 if (q2 >= (twoNMinus1 - 1))
1967 r2 = 2 * r2 + 1 - d;
1971 if (q2 >= twoNMinus1)
1982 } while ((p < (bits * 2)) && ((q1 < delta) || ((q1 == delta) && (r1 == 0))));
1984 *shift = p - bits; // resulting shift
1985 return q2 + 1; // resulting magic number
1988 uint32_t GetUnsigned32Magic(uint32_t d, bool* add /*out*/, int* shift /*out*/)
1990 return GetUnsignedMagic<uint32_t>(d, add, shift);
1993 #ifdef _TARGET_64BIT_
1994 uint64_t GetUnsigned64Magic(uint64_t d, bool* add /*out*/, int* shift /*out*/)
1996 return GetUnsignedMagic<uint64_t>(d, add, shift);
2000 template <typename T>
2003 typedef T DivisorType;
2009 template <typename T>
2010 const SignedMagic<T>* TryGetSignedMagic(T divisor)
2016 const SignedMagic<int32_t>* TryGetSignedMagic(int32_t divisor)
2018 static const SignedMagic<int32_t> table[]{
2019 {0x55555556, 0}, // 3
2021 {0x66666667, 1}, // 5
2022 {0x2aaaaaab, 0}, // 6
2023 {0x92492493, 2}, // 7
2025 {0x38e38e39, 1}, // 9
2026 {0x66666667, 2}, // 10
2027 {0x2e8ba2e9, 1}, // 11
2028 {0x2aaaaaab, 1}, // 12
2031 return TryGetMagic<3>(table, divisor);
2035 const SignedMagic<int64_t>* TryGetSignedMagic(int64_t divisor)
2037 static const SignedMagic<int64_t> table[]{
2038 {0x5555555555555556, 0}, // 3
2040 {0x6666666666666667, 1}, // 5
2041 {0x2aaaaaaaaaaaaaab, 0}, // 6
2042 {0x4924924924924925, 1}, // 7
2044 {0x1c71c71c71c71c72, 0}, // 9
2045 {0x6666666666666667, 2}, // 10
2046 {0x2e8ba2e8ba2e8ba3, 1}, // 11
2047 {0x2aaaaaaaaaaaaaab, 1}, // 12
2050 return TryGetMagic<3>(table, divisor);
2053 //------------------------------------------------------------------------
2054 // GetSignedMagic: Generates a magic number and shift amount for
2055 // the magic number division optimization.
2058 // denom - The denominator
2059 // shift - Pointer to the shift value to be returned
2062 // The magic number.
2065 // This code is previously from UTC where it notes it was taken from
2066 // _The_PowerPC_Compiler_Writer's_Guide_, pages 57-58. The paper is is based on
2067 // is "Division by invariant integers using multiplication" by Torbjorn Granlund
2068 // and Peter L. Montgomery in PLDI 94
2070 template <typename T>
2071 T GetSignedMagic(T denom, int* shift /*out*/)
2073 const SignedMagic<T>* magic = TryGetSignedMagic(denom);
2075 if (magic != nullptr)
2077 *shift = magic->shift;
2078 return magic->magic;
2081 const int bits = sizeof(T) * 8;
2082 const int bits_minus_1 = bits - 1;
2084 typedef typename jitstd::make_unsigned<T>::type UT;
2086 const UT two_nminus1 = UT(1) << bits_minus_1;
2100 absDenom = abs(denom);
2101 t = two_nminus1 + ((unsigned int)denom >> 31);
2102 absNc = t - 1 - (t % absDenom); // absolute value of nc
2103 p = bits_minus_1; // initialize p
2104 q1 = two_nminus1 / absNc; // initialize q1 = 2^p / abs(nc)
2105 r1 = two_nminus1 - (q1 * absNc); // initialize r1 = rem(2^p, abs(nc))
2106 q2 = two_nminus1 / absDenom; // initialize q1 = 2^p / abs(denom)
2107 r2 = two_nminus1 - (q2 * absDenom); // initialize r1 = rem(2^p, abs(denom))
2113 q1 *= 2; // update q1 = 2^p / abs(nc)
2114 r1 *= 2; // update r1 = rem(2^p / abs(nc))
2117 { // must be unsigned comparison
2122 q2 *= 2; // update q2 = 2^p / abs(denom)
2123 r2 *= 2; // update r2 = rem(2^p / abs(denom))
2126 { // must be unsigned comparison
2131 delta = absDenom - r2;
2132 } while (q1 < delta || (q1 == delta && r1 == 0));
2134 result_magic = q2 + 1; // resulting magic number
2137 result_magic = -result_magic;
2139 *shift = p - bits; // resulting shift
2141 return result_magic;
2144 int32_t GetSigned32Magic(int32_t d, int* shift /*out*/)
2146 return GetSignedMagic<int32_t>(d, shift);
2149 #ifdef _TARGET_64BIT_
2150 int64_t GetSigned64Magic(int64_t d, int* shift /*out*/)
2152 return GetSignedMagic<int64_t>(d, shift);