1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
4 // ===================================================================================================
5 // Portions of the code implemented below are based on the 'Berkeley SoftFloat Release 3e' algorithms.
6 // ===================================================================================================
8 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
13 XX Has miscellaneous utility functions XX
15 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
16 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
26 /*****************************************************************************/
27 // Define the string platform name based on compilation #ifdefs. This is the
28 // same code for all platforms, hence it is here instead of in the targetXXX.cpp
32 // Should we distinguish Mac? Can we?
33 // Should we distinguish flavors of Unix? Can we?
34 const char* Target::g_tgtPlatformName = "Unix";
36 const char* Target::g_tgtPlatformName = "Windows";
37 #endif // !TARGET_UNIX
39 /*****************************************************************************/
45 const signed char opcodeSizes[] =
47 #define InlineNone_size 0
48 #define ShortInlineVar_size 1
49 #define InlineVar_size 2
50 #define ShortInlineI_size 1
51 #define InlineI_size 4
52 #define InlineI8_size 8
53 #define ShortInlineR_size 4
54 #define InlineR_size 8
55 #define ShortInlineBrTarget_size 1
56 #define InlineBrTarget_size 4
57 #define InlineMethod_size 4
58 #define InlineField_size 4
59 #define InlineType_size 4
60 #define InlineString_size 4
61 #define InlineSig_size 4
62 #define InlineRVA_size 4
63 #define InlineTok_size 4
64 #define InlineSwitch_size 0 // for now
65 #define InlinePhi_size 0 // for now
66 #define InlineVarTok_size 0 // remove
68 #define OPDEF(name,string,pop,push,oprType,opcType,l,s1,s2,ctrl) oprType ## _size ,
72 #undef InlineNone_size
73 #undef ShortInlineVar_size
75 #undef ShortInlineI_size
78 #undef ShortInlineR_size
80 #undef ShortInlineBrTarget_size
81 #undef InlineBrTarget_size
82 #undef InlineMethod_size
83 #undef InlineField_size
84 #undef InlineType_size
85 #undef InlineString_size
89 #undef InlineSwitch_size
94 const BYTE varTypeClassification[] = {
95 #define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) tf,
100 /*****************************************************************************/
101 /*****************************************************************************/
103 extern const char* const opcodeNames[] = {
104 #define OPDEF(name, string, pop, push, oprType, opcType, l, s1, s2, ctrl) string,
105 #include "opcode.def"
109 extern const BYTE opcodeArgKinds[] = {
110 #define OPDEF(name, string, pop, push, oprType, opcType, l, s1, s2, ctrl) (BYTE) oprType,
111 #include "opcode.def"
116 /*****************************************************************************/
118 const char* varTypeName(var_types vt)
120 static const char* const varTypeNames[] = {
121 #define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) nm,
122 #include "typelist.h"
126 assert((unsigned)vt < _countof(varTypeNames));
128 return varTypeNames[vt];
131 #if defined(DEBUG) || defined(LATE_DISASM) || DUMP_GC_TABLES
132 /*****************************************************************************
134 * Return the name of the given register.
137 const char* getRegName(regNumber reg, bool isFloat)
139 // Special-case REG_NA; it's not in the regNames array, but we might want to print it.
145 #if defined(TARGET_ARM64)
146 static const char* const regNames[] = {
147 #define REGDEF(name, rnum, mask, xname, wname) xname,
148 #include "register.h"
150 assert(reg < ArrLen(regNames));
151 return regNames[reg];
153 static const char* const regNames[] = {
154 #define REGDEF(name, rnum, mask, sname) sname,
155 #include "register.h"
157 assert(reg < ArrLen(regNames));
158 return regNames[reg];
162 const char* getRegName(unsigned reg,
163 bool isFloat) // this is for gcencode.cpp and disasm.cpp that dont use the regNumber type
165 return getRegName((regNumber)reg, isFloat);
167 #endif // defined(DEBUG) || defined(LATE_DISASM) || DUMP_GC_TABLES
171 const char* getRegNameFloat(regNumber reg, var_types type)
174 assert(genIsValidFloatReg(reg));
175 if (type == TYP_FLOAT)
176 return getRegName(reg);
184 assert(!"Bad double register");
239 #elif defined(TARGET_ARM64)
241 static const char* regNamesFloat[] = {
242 #define REGDEF(name, rnum, mask, xname, wname) xname,
243 #include "register.h"
245 assert((unsigned)reg < ArrLen(regNamesFloat));
247 return regNamesFloat[reg];
250 static const char* regNamesFloat[] = {
251 #define REGDEF(name, rnum, mask, sname) "x" sname,
252 #include "register.h"
255 static const char* regNamesYMM[] = {
256 #define REGDEF(name, rnum, mask, sname) "y" sname,
257 #include "register.h"
259 #endif // FEATURE_SIMD
260 assert((unsigned)reg < ArrLen(regNamesFloat));
263 if (type == TYP_SIMD32)
265 return regNamesYMM[reg];
267 #endif // FEATURE_SIMD
269 return regNamesFloat[reg];
273 /*****************************************************************************
275 * Displays a register set.
276 * TODO-ARM64-Cleanup: don't allow ip0, ip1 as part of a range.
279 void dspRegMask(regMaskTP regMask, size_t minSiz)
281 const char* sep = "";
285 bool inRegRange = false;
286 regNumber regPrev = REG_NA;
287 regNumber regHead = REG_NA; // When we start a range, remember the first register of the range, so we don't use
288 // range notation if the range contains just a single register.
289 for (regNumber regNum = REG_INT_FIRST; regNum <= REG_INT_LAST; regNum = REG_NEXT(regNum))
291 regMaskTP regBit = genRegMask(regNum);
293 if ((regMask & regBit) != 0)
295 // We have a register to display. It gets displayed now if:
296 // 1. This is the first register to display of a new range of registers (possibly because
297 // no register has ever been displayed).
298 // 2. This is the last register of an acceptable range (either the last integer register,
299 // or the last of a range that is displayed with range notation).
302 // It's the first register of a potential range.
303 const char* nam = getRegName(regNum);
304 printf("%s%s", sep, nam);
305 minSiz -= strlen(sep) + strlen(nam);
307 // By default, we're not starting a potential register range.
310 // What kind of separator should we use for this range (if it is indeed going to be a range)?
311 CLANG_FORMAT_COMMENT_ANCHOR;
313 #if defined(TARGET_AMD64)
314 // For AMD64, create ranges for int registers R8 through R15, but not the "old" registers.
315 if (regNum >= REG_R8)
321 #elif defined(TARGET_ARM64)
322 // R17 and R28 can't be the start of a range, since the range would include TEB or FP
323 if ((regNum < REG_R17) || ((REG_R19 <= regNum) && (regNum < REG_R28)))
329 #elif defined(TARGET_ARM)
330 if (regNum < REG_R12)
336 #elif defined(TARGET_X86)
337 // No register ranges
339 #error Unsupported or unset target architecture
343 #if defined(TARGET_ARM64)
344 // We've already printed a register. Is this the end of a range?
345 else if ((regNum == REG_INT_LAST) || (regNum == REG_R17) // last register before TEB
346 || (regNum == REG_R28)) // last register before FP
347 #else // TARGET_ARM64
348 // We've already printed a register. Is this the end of a range?
349 else if (regNum == REG_INT_LAST)
350 #endif // TARGET_ARM64
352 const char* nam = getRegName(regNum);
353 printf("%s%s", sep, nam);
354 minSiz -= strlen(sep) + strlen(nam);
355 inRegRange = false; // No longer in the middle of a register range
360 else // ((regMask & regBit) == 0)
364 assert(regHead != REG_NA);
365 if (regPrev != regHead)
367 // Close out the previous range, if it included more than one register.
368 const char* nam = getRegName(regPrev);
369 printf("%s%s", sep, nam);
370 minSiz -= strlen(sep) + strlen(nam);
378 if (regBit > regMask)
388 // We've already printed something.
394 for (regNumber regNum = REG_FP_FIRST; regNum <= REG_FP_LAST; regNum = REG_NEXT(regNum))
396 regMaskTP regBit = genRegMask(regNum);
398 if (regMask & regBit)
400 if (!inRegRange || (regNum == REG_FP_LAST))
402 const char* nam = getRegName(regNum);
403 printf("%s%s", sep, nam);
404 minSiz -= strlen(sep) + strlen(nam);
414 if (regPrev != regHead)
416 const char* nam = getRegName(regPrev);
417 printf("%s%s", sep, nam);
418 minSiz -= (strlen(sep) + strlen(nam));
425 if (regBit > regMask)
435 while ((int)minSiz > 0)
442 //------------------------------------------------------------------------
443 // dumpILBytes: Helper for dumpSingleInstr() to dump hex bytes of an IL stream,
444 // aligning up to a minimum alignment width.
447 // codeAddr - Pointer to IL byte stream to display.
448 // codeSize - Number of bytes of IL byte stream to display.
449 // alignSize - Pad out to this many characters, if fewer than this were written.
451 void dumpILBytes(const BYTE* const codeAddr,
453 unsigned alignSize) // number of characters to write, for alignment
455 for (IL_OFFSET offs = 0; offs < codeSize; ++offs)
457 printf(" %02x", *(codeAddr + offs));
460 unsigned charsWritten = 3 * codeSize;
461 for (unsigned i = charsWritten; i < alignSize; i++)
467 //------------------------------------------------------------------------
468 // dumpSingleInstr: Display a single IL instruction.
471 // codeAddr - Base pointer to a stream of IL instructions.
472 // offs - Offset from codeAddr of the IL instruction to display.
473 // prefix - Optional string to prefix the IL instruction with (if nullptr, no prefix is output).
476 // Size of the displayed IL instruction in the instruction stream, in bytes. (Add this to 'offs' to
477 // get to the next instruction.)
479 unsigned dumpSingleInstr(const BYTE* const codeAddr, IL_OFFSET offs, const char* prefix)
481 const BYTE* opcodePtr = codeAddr + offs;
482 const BYTE* startOpcodePtr = opcodePtr;
483 const unsigned ALIGN_WIDTH = 3 * 6; // assume 3 characters * (1 byte opcode + 4 bytes data + 1 prefix byte) for
486 if (prefix != nullptr)
488 printf("%s", prefix);
491 OPCODE opcode = (OPCODE)getU1LittleEndian(opcodePtr);
492 opcodePtr += sizeof(__int8);
496 if (opcode >= CEE_COUNT)
498 printf("\nIllegal opcode: %02X\n", (int)opcode);
499 return (IL_OFFSET)(opcodePtr - startOpcodePtr);
502 /* Get the size of additional parameters */
504 size_t sz = opcodeSizes[opcode];
505 unsigned argKind = opcodeArgKinds[opcode];
507 /* See what kind of an opcode we have, then */
512 opcode = OPCODE(getU1LittleEndian(opcodePtr) + 256);
513 opcodePtr += sizeof(__int8);
526 dumpILBytes(startOpcodePtr, (unsigned)(opcodePtr - startOpcodePtr), ALIGN_WIDTH);
527 printf(" %-12s", opcodeNames[opcode]);
531 iOp = getU1LittleEndian(opcodePtr);
534 iOp = getI1LittleEndian(opcodePtr);
537 iOp = getU2LittleEndian(opcodePtr);
546 iOp = getI4LittleEndian(opcodePtr);
549 iOp = getU4LittleEndian(opcodePtr);
550 iOp |= (__int64)getU4LittleEndian(opcodePtr + 4) << 32;
554 dumpILBytes(startOpcodePtr, (unsigned)((opcodePtr - startOpcodePtr) + sz), ALIGN_WIDTH);
555 printf(" %-12s 0x%X", opcodeNames[opcode], iOp);
559 dOp = getR4LittleEndian(opcodePtr);
562 dOp = getR8LittleEndian(opcodePtr);
566 dumpILBytes(startOpcodePtr, (unsigned)((opcodePtr - startOpcodePtr) + sz), ALIGN_WIDTH);
567 printf(" %-12s %f", opcodeNames[opcode], dOp);
570 case ShortInlineBrTarget:
571 jOp = getI1LittleEndian(opcodePtr);
574 jOp = getI4LittleEndian(opcodePtr);
578 dumpILBytes(startOpcodePtr, (unsigned)((opcodePtr - startOpcodePtr) + sz), ALIGN_WIDTH);
579 printf(" %-12s %d (IL_%04x)", opcodeNames[opcode], jOp, (int)(opcodePtr + sz - codeAddr) + jOp);
583 jOp2 = getU4LittleEndian(opcodePtr);
585 opcodePtr += jOp2 * 4; // Jump over the table
586 dumpILBytes(startOpcodePtr, (unsigned)(opcodePtr - startOpcodePtr), ALIGN_WIDTH);
587 printf(" %-12s", opcodeNames[opcode]);
591 jOp2 = getU1LittleEndian(opcodePtr);
593 opcodePtr += jOp2 * 2; // Jump over the table
594 dumpILBytes(startOpcodePtr, (unsigned)(opcodePtr - startOpcodePtr), ALIGN_WIDTH);
595 printf(" %-12s", opcodeNames[opcode]);
599 assert(!"Bad argKind");
608 return (IL_OFFSET)(opcodePtr - startOpcodePtr);
611 //------------------------------------------------------------------------
612 // dumpILRange: Display a range of IL instructions from an IL instruction stream.
615 // codeAddr - Pointer to IL byte stream to display.
616 // codeSize - Number of bytes of IL byte stream to display.
618 void dumpILRange(const BYTE* const codeAddr, unsigned codeSize) // in bytes
620 for (IL_OFFSET offs = 0; offs < codeSize;)
623 sprintf_s(prefix, _countof(prefix), "IL_%04x ", offs);
624 unsigned codeBytesDumped = dumpSingleInstr(codeAddr, offs, prefix);
625 offs += codeBytesDumped;
629 /*****************************************************************************
631 * Display a variable set.
633 const char* genES2str(BitVecTraits* traits, EXPSET_TP set)
635 const int bufSize = 65; // Supports a BitVec of up to 256 bits
636 static char num1[bufSize];
637 static char num2[bufSize];
638 static char* nump = num1;
640 assert(bufSize > roundUp(BitVecTraits::GetSize(traits), (unsigned)sizeof(char)) / 8);
643 nump = (nump == num1) ? num2 : num1;
644 sprintf_s(temp, bufSize, "%s", BitVecOps::ToString(traits, set));
649 const char* refCntWtd2str(BasicBlock::weight_t refCntWtd)
651 const int bufSize = 17;
652 static char num1[bufSize];
653 static char num2[bufSize];
654 static char* nump = num1;
658 nump = (nump == num1) ? num2 : num1;
660 if (refCntWtd == BB_MAX_WEIGHT)
662 sprintf_s(temp, bufSize, "MAX ");
666 float scaledWeight = refCntWtd / BB_UNITY_WEIGHT;
667 float intPart = (float)floor(scaledWeight);
668 bool isLarge = intPart > 1e9;
669 bool isSmall = (intPart < 1e-2) && (intPart != 0);
671 // Use g format for high dynamic range counts.
673 if (isLarge || isSmall)
675 sprintf_s(temp, bufSize, "%.2g", scaledWeight);
679 if (intPart == scaledWeight)
681 sprintf_s(temp, bufSize, "%lld ", (long long)intPart);
685 sprintf_s(temp, bufSize, "%.2f", scaledWeight);
694 #if defined(DEBUG) || defined(INLINE_DATA)
696 //------------------------------------------------------------------------
697 // Contains: check if the range includes a particular hash
700 // hash -- hash value to check
702 bool ConfigMethodRange::Contains(unsigned hash)
704 _ASSERT(m_inited == 1);
706 // No ranges specified means all methods included.
707 if (m_lastRange == 0)
712 for (unsigned i = 0; i < m_lastRange; i++)
714 if ((m_ranges[i].m_low <= hash) && (hash <= m_ranges[i].m_high))
723 //------------------------------------------------------------------------
724 // InitRanges: parse the range string and set up the range info
727 // rangeStr -- string to parse (may be nullptr)
728 // capacity -- number ranges to allocate in the range array
731 // Does some internal error checking; clients can use Error()
732 // to determine if the range string couldn't be fully parsed
733 // because of bad characters or too many entries, or had values
734 // that were too large to represent.
736 void ConfigMethodRange::InitRanges(const WCHAR* rangeStr, unsigned capacity)
738 // Make sure that the memory was zero initialized
739 assert(m_inited == 0 || m_inited == 1);
740 assert(m_entries == 0);
741 assert(m_ranges == nullptr);
742 assert(m_lastRange == 0);
744 // Flag any strange-looking requests
745 assert(capacity < 100000);
747 if (rangeStr == nullptr)
753 // Allocate some persistent memory
754 ICorJitHost* jitHost = g_jitHost;
755 m_ranges = (Range*)jitHost->allocateMemory(capacity * sizeof(Range));
756 m_entries = capacity;
758 const WCHAR* p = rangeStr;
759 unsigned lastRange = 0;
760 bool setHighPart = false;
762 while ((*p != 0) && (lastRange < m_entries))
764 while ((*p == L' ') || (*p == L','))
771 while (((L'0' <= *p) && (*p <= L'9')) || ((L'A' <= *p) && (*p <= L'F')) || ((L'a' <= *p) && (*p <= L'f')))
775 if ((L'0' <= *p) && (*p <= L'9'))
779 else if ((L'A' <= *p) && (*p <= L'F'))
781 n = (*p++) - L'A' + 10;
783 else if ((L'a' <= *p) && (*p <= L'f'))
785 n = (*p++) - L'a' + 10;
790 // Check for overflow
791 if ((m_badChar != 0) && (j <= i))
793 m_badChar = (p - rangeStr) + 1;
799 // Was this the high part of a low-high pair?
802 // Yep, set it and move to the next range
803 m_ranges[lastRange].m_high = i;
805 // Sanity check that range is proper
806 if ((m_badChar != 0) && (m_ranges[lastRange].m_high < m_ranges[lastRange].m_low))
808 m_badChar = (p - rangeStr) + 1;
816 // Must have been looking for the low part of a range
817 m_ranges[lastRange].m_low = i;
824 // Was that the low part of a low-high pair?
827 // Yep, skip the dash and set high part next time around.
833 // Else we have a point range, so set high = low
834 m_ranges[lastRange].m_high = i;
838 // If we didn't parse the full range string, note index of the the
840 if ((m_badChar != 0) && (*p != 0))
842 m_badChar = (p - rangeStr) + 1;
845 // Finish off any remaining open range
848 m_ranges[lastRange].m_high = UINT_MAX;
852 assert(lastRange <= m_entries);
853 m_lastRange = lastRange;
857 //------------------------------------------------------------------------
858 // Dump: dump hash ranges to stdout
860 void ConfigMethodRange::Dump()
864 printf("<uninitialized method range>\n");
868 if (m_lastRange == 0)
870 printf("<empty method range>\n");
874 printf("<method range with %d entries>\n", m_lastRange);
875 for (unsigned i = 0; i < m_lastRange; i++)
877 if (m_ranges[i].m_low == m_ranges[i].m_high)
879 printf("%i [0x%08x]\n", i, m_ranges[i].m_low);
883 printf("%i [0x%08x-0x%08x]\n", i, m_ranges[i].m_low, m_ranges[i].m_high);
888 #endif // defined(DEBUG) || defined(INLINE_DATA)
890 #if CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE || MEASURE_MEM_ALLOC
892 /*****************************************************************************
896 Histogram::Histogram(const unsigned* const sizeTable) : m_sizeTable(sizeTable)
898 unsigned sizeCount = 0;
902 } while ((sizeTable[sizeCount] != 0) && (sizeCount < 1000));
904 assert(sizeCount < HISTOGRAM_MAX_SIZE_COUNT - 1);
906 m_sizeCount = sizeCount;
908 memset(m_counts, 0, (m_sizeCount + 1) * sizeof(*m_counts));
911 void Histogram::dump(FILE* output)
914 for (unsigned i = 0; i < m_sizeCount; i++)
919 for (unsigned c = 0, i = 0; i <= m_sizeCount; i++)
921 if (i == m_sizeCount)
923 if (m_counts[i] == 0)
928 fprintf(output, " > %7u", m_sizeTable[i - 1]);
934 fprintf(output, " <= ");
938 fprintf(output, "%7u .. ", m_sizeTable[i - 1] + 1);
941 fprintf(output, "%7u", m_sizeTable[i]);
946 fprintf(output, " ===> %7u count (%3u%% of total)\n", m_counts[i], (int)(100.0 * c / t));
950 void Histogram::record(unsigned size)
953 for (i = 0; i < m_sizeCount; i++)
955 if (m_sizeTable[i] >= size)
964 #endif // CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE
966 /*****************************************************************************
967 * Fixed bit vector class
970 // bitChunkSize() - Returns number of bits in a bitVect chunk
971 inline UINT FixedBitVect::bitChunkSize()
973 return sizeof(UINT) * 8;
976 // bitNumToBit() - Returns a bit mask of the given bit number
977 inline UINT FixedBitVect::bitNumToBit(UINT bitNum)
979 assert(bitNum < bitChunkSize());
980 assert(bitChunkSize() <= sizeof(int) * 8);
985 // bitVectInit() - Initializes a bit vector of a given size
986 FixedBitVect* FixedBitVect::bitVectInit(UINT size, Compiler* comp)
988 UINT bitVectMemSize, numberOfChunks;
993 numberOfChunks = (size - 1) / bitChunkSize() + 1;
994 bitVectMemSize = numberOfChunks * (bitChunkSize() / 8); // size in bytes
996 assert(bitVectMemSize * bitChunkSize() >= size);
998 bv = (FixedBitVect*)comp->getAllocator(CMK_FixedBitVect).allocate<char>(sizeof(FixedBitVect) + bitVectMemSize);
999 memset(bv->bitVect, 0, bitVectMemSize);
1001 bv->bitVectSize = size;
1006 // bitVectSet() - Sets the given bit
1007 void FixedBitVect::bitVectSet(UINT bitNum)
1011 assert(bitNum <= bitVectSize);
1013 index = bitNum / bitChunkSize();
1014 bitNum -= index * bitChunkSize();
1016 bitVect[index] |= bitNumToBit(bitNum);
1019 // bitVectTest() - Tests the given bit
1020 bool FixedBitVect::bitVectTest(UINT bitNum)
1024 assert(bitNum <= bitVectSize);
1026 index = bitNum / bitChunkSize();
1027 bitNum -= index * bitChunkSize();
1029 return (bitVect[index] & bitNumToBit(bitNum)) != 0;
1032 // bitVectOr() - Or in the given bit vector
1033 void FixedBitVect::bitVectOr(FixedBitVect* bv)
1035 UINT bitChunkCnt = (bitVectSize - 1) / bitChunkSize() + 1;
1037 assert(bitVectSize == bv->bitVectSize);
1040 for (UINT i = 0; i < bitChunkCnt; i++)
1042 bitVect[i] |= bv->bitVect[i];
1046 // bitVectAnd() - And with passed in bit vector
1047 void FixedBitVect::bitVectAnd(FixedBitVect& bv)
1049 UINT bitChunkCnt = (bitVectSize - 1) / bitChunkSize() + 1;
1051 assert(bitVectSize == bv.bitVectSize);
1054 for (UINT i = 0; i < bitChunkCnt; i++)
1056 bitVect[i] &= bv.bitVect[i];
1060 // bitVectGetFirst() - Find the first bit on and return bit num,
1061 // Return -1 if no bits found.
1062 UINT FixedBitVect::bitVectGetFirst()
1064 return bitVectGetNext((UINT)-1);
1067 // bitVectGetNext() - Find the next bit on given previous position and return bit num.
1068 // Return -1 if no bits found.
1069 UINT FixedBitVect::bitVectGetNext(UINT bitNumPrev)
1071 UINT bitNum = (UINT)-1;
1074 UINT bitChunkCnt = (bitVectSize - 1) / bitChunkSize() + 1;
1077 if (bitNumPrev == (UINT)-1)
1086 index = bitNumPrev / bitChunkSize();
1087 bitNumPrev -= index * bitChunkSize();
1088 bit = bitNumToBit(bitNumPrev);
1089 bitMask = ~(bit | (bit - 1));
1093 for (i = index; i < bitChunkCnt; i++)
1095 UINT bitChunk = bitVect[i] & bitMask;
1099 BitScanForward((ULONG*)&bitNum, bitChunk);
1103 bitMask = 0xFFFFFFFF;
1106 // Empty bit vector?
1107 if (bitNum == (UINT)-1)
1112 bitNum += i * bitChunkSize();
1114 assert(bitNum <= bitVectSize);
1119 // bitVectGetNextAndClear() - Find the first bit on, clear it and return it.
1120 // Return -1 if no bits found.
1121 UINT FixedBitVect::bitVectGetNextAndClear()
1123 UINT bitNum = (UINT)-1;
1124 UINT bitChunkCnt = (bitVectSize - 1) / bitChunkSize() + 1;
1128 for (i = 0; i < bitChunkCnt; i++)
1130 if (bitVect[i] != 0)
1132 BitScanForward((ULONG*)&bitNum, bitVect[i]);
1137 // Empty bit vector?
1138 if (bitNum == (UINT)-1)
1143 // Clear the bit in the right chunk
1144 bitVect[i] &= ~bitNumToBit(bitNum);
1146 bitNum += i * bitChunkSize();
1148 assert(bitNum <= bitVectSize);
1153 int SimpleSprintf_s(__in_ecount(cbBufSize - (pWriteStart - pBufStart)) char* pWriteStart,
1154 __in_ecount(cbBufSize) char* pBufStart,
1156 __in_z const char* fmt,
1161 assert(pWriteStart);
1162 assert((size_t)pBufStart <= (size_t)pWriteStart);
1165 // compute the space left in the buffer.
1166 if ((pBufStart + cbBufSize) < pWriteStart)
1168 NO_WAY("pWriteStart is past end of buffer");
1170 size_t cbSpaceLeft = (size_t)((pBufStart + cbBufSize) - pWriteStart);
1172 va_start(args, fmt);
1173 ret = vsprintf_s(pWriteStart, cbSpaceLeft, const_cast<char*>(fmt), args);
1177 NO_WAY("vsprintf_s failed.");
1184 void hexDump(FILE* dmpf, const char* name, BYTE* addr, size_t size)
1193 fprintf(dmpf, "Hex dump of %s:\n", name);
1195 for (unsigned i = 0; i < size; i++)
1199 fprintf(dmpf, "\n %04X: ", i);
1202 fprintf(dmpf, "%02X ", *addr++);
1205 fprintf(dmpf, "\n\n");
1210 void HelperCallProperties::init()
1212 for (CorInfoHelpFunc helper = CORINFO_HELP_UNDEF; // initialize helper
1213 (helper < CORINFO_HELP_COUNT); // test helper for loop exit
1214 helper = CorInfoHelpFunc(int(helper) + 1)) // update helper to next
1216 // Generally you want initialize these to their most typical/safest result
1218 bool isPure = false; // true if the result only depends upon input args and not any global state
1219 bool noThrow = false; // true if the helper will never throw
1220 bool alwaysThrow = false; // true if the helper will always throw
1221 bool nonNullReturn = false; // true if the result will never be null or zero
1222 bool isAllocator = false; // true if the result is usually a newly created heap item, or may throw OutOfMemory
1223 bool mutatesHeap = false; // true if any previous heap objects [are|can be] modified
1224 bool mayRunCctor = false; // true if the helper call may cause a static constructor to be run.
1228 // Arithmetic helpers that cannot throw
1229 case CORINFO_HELP_LLSH:
1230 case CORINFO_HELP_LRSH:
1231 case CORINFO_HELP_LRSZ:
1232 case CORINFO_HELP_LMUL:
1233 case CORINFO_HELP_LNG2DBL:
1234 case CORINFO_HELP_ULNG2DBL:
1235 case CORINFO_HELP_DBL2INT:
1236 case CORINFO_HELP_DBL2LNG:
1237 case CORINFO_HELP_DBL2UINT:
1238 case CORINFO_HELP_DBL2ULNG:
1239 case CORINFO_HELP_FLTREM:
1240 case CORINFO_HELP_DBLREM:
1241 case CORINFO_HELP_FLTROUND:
1242 case CORINFO_HELP_DBLROUND:
1248 // Arithmetic helpers that *can* throw.
1250 // This (or these) are not pure, in that they have "VM side effects"...but they don't mutate the heap.
1251 case CORINFO_HELP_ENDCATCH:
1256 // Arithmetic helpers that may throw
1257 case CORINFO_HELP_LMOD: // Mods throw div-by zero, and signed mods have problems with the smallest integer
1259 case CORINFO_HELP_MOD: // which is not representable as a positive integer.
1260 case CORINFO_HELP_UMOD:
1261 case CORINFO_HELP_ULMOD:
1263 case CORINFO_HELP_UDIV: // Divs throw divide-by-zero.
1264 case CORINFO_HELP_DIV:
1265 case CORINFO_HELP_LDIV:
1266 case CORINFO_HELP_ULDIV:
1268 case CORINFO_HELP_LMUL_OVF:
1269 case CORINFO_HELP_ULMUL_OVF:
1270 case CORINFO_HELP_DBL2INT_OVF:
1271 case CORINFO_HELP_DBL2LNG_OVF:
1272 case CORINFO_HELP_DBL2UINT_OVF:
1273 case CORINFO_HELP_DBL2ULNG_OVF:
1278 // Heap Allocation helpers, these all never return null
1279 case CORINFO_HELP_NEWSFAST:
1280 case CORINFO_HELP_NEWSFAST_ALIGN8:
1281 case CORINFO_HELP_NEWSFAST_ALIGN8_VC:
1282 case CORINFO_HELP_NEWFAST:
1283 case CORINFO_HELP_NEWSFAST_FINALIZE:
1284 case CORINFO_HELP_NEWSFAST_ALIGN8_FINALIZE:
1285 case CORINFO_HELP_READYTORUN_NEW:
1286 case CORINFO_HELP_BOX:
1289 nonNullReturn = true;
1290 noThrow = true; // only can throw OutOfMemory
1293 // These allocation helpers do some checks on the size (and lower bound) inputs,
1294 // and can throw exceptions other than OOM.
1295 case CORINFO_HELP_NEWARR_1_VC:
1296 case CORINFO_HELP_NEWARR_1_ALIGN8:
1297 case CORINFO_HELP_NEW_MDARR:
1298 case CORINFO_HELP_NEWARR_1_DIRECT:
1299 case CORINFO_HELP_NEWARR_1_OBJ:
1300 case CORINFO_HELP_READYTORUN_NEWARR_1:
1303 nonNullReturn = true;
1306 // Heap Allocation helpers that are also pure
1307 case CORINFO_HELP_STRCNS:
1311 nonNullReturn = true;
1312 noThrow = true; // only can throw OutOfMemory
1315 case CORINFO_HELP_BOX_NULLABLE:
1316 // Box Nullable is not a 'pure' function
1317 // It has a Byref argument that it reads the contents of.
1319 // So two calls to Box Nullable that pass the same address (with the same Value Number)
1320 // will produce different results when the contents of the memory pointed to by the Byref changes
1323 noThrow = true; // only can throw OutOfMemory
1326 case CORINFO_HELP_RUNTIMEHANDLE_METHOD:
1327 case CORINFO_HELP_RUNTIMEHANDLE_CLASS:
1328 case CORINFO_HELP_RUNTIMEHANDLE_METHOD_LOG:
1329 case CORINFO_HELP_RUNTIMEHANDLE_CLASS_LOG:
1330 case CORINFO_HELP_READYTORUN_GENERIC_HANDLE:
1331 // logging helpers are not technically pure but can be optimized away
1334 nonNullReturn = true;
1337 // type casting helpers
1338 case CORINFO_HELP_ISINSTANCEOFINTERFACE:
1339 case CORINFO_HELP_ISINSTANCEOFARRAY:
1340 case CORINFO_HELP_ISINSTANCEOFCLASS:
1341 case CORINFO_HELP_ISINSTANCEOFANY:
1342 case CORINFO_HELP_READYTORUN_ISINSTANCEOF:
1343 case CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE:
1344 case CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE:
1347 noThrow = true; // These return null for a failing cast
1350 case CORINFO_HELP_ARE_TYPES_EQUIVALENT:
1351 case CORINFO_HELP_GETCURRENTMANAGEDTHREADID:
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_NOT_IMPLEMENTED:
1460 case CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED:
1461 case CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED:
1462 case CORINFO_HELP_FAIL_FAST:
1463 case CORINFO_HELP_METHOD_ACCESS_EXCEPTION:
1464 case CORINFO_HELP_FIELD_ACCESS_EXCEPTION:
1465 case CORINFO_HELP_CLASS_ACCESS_EXCEPTION:
1470 // These helper calls may throw an exception
1471 case CORINFO_HELP_MON_EXIT_STATIC:
1475 // This is a debugging aid; it simply returns a constant address.
1476 case CORINFO_HELP_LOOP_CLONE_CHOICE_ADDR:
1481 case CORINFO_HELP_DBG_IS_JUST_MY_CODE:
1482 case CORINFO_HELP_BBT_FCN_ENTER:
1483 case CORINFO_HELP_POLL_GC:
1484 case CORINFO_HELP_MON_ENTER:
1485 case CORINFO_HELP_MON_EXIT:
1486 case CORINFO_HELP_MON_ENTER_STATIC:
1487 case CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER:
1488 case CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT:
1489 case CORINFO_HELP_GETFIELDADDR:
1490 case CORINFO_HELP_INIT_PINVOKE_FRAME:
1491 case CORINFO_HELP_JIT_PINVOKE_BEGIN:
1492 case CORINFO_HELP_JIT_PINVOKE_END:
1497 // Not sure how to handle optimization involving the rest of these helpers
1500 // The most pessimistic results are returned for these helpers
1505 m_isPure[helper] = isPure;
1506 m_noThrow[helper] = noThrow;
1507 m_alwaysThrow[helper] = alwaysThrow;
1508 m_nonNullReturn[helper] = nonNullReturn;
1509 m_isAllocator[helper] = isAllocator;
1510 m_mutatesHeap[helper] = mutatesHeap;
1511 m_mayRunCctor[helper] = mayRunCctor;
1515 //=============================================================================
1516 // AssemblyNamesList2
1517 //=============================================================================
1518 // The string should be of the form
1520 // MyAssembly;mscorlib;System
1522 // You must use ';' as a separator; whitespace no longer works
1524 AssemblyNamesList2::AssemblyNamesList2(const WCHAR* list, HostAllocator alloc) : m_alloc(alloc)
1526 WCHAR prevChar = '?'; // dummy
1527 LPWSTR nameStart = nullptr; // start of the name currently being processed. nullptr if no current name
1528 AssemblyName** ppPrevLink = &m_pNames;
1530 for (LPWSTR listWalk = const_cast<LPWSTR>(list); prevChar != '\0'; prevChar = *listWalk, listWalk++)
1532 WCHAR curChar = *listWalk;
1534 if (curChar == W(';') || curChar == W('\0'))
1536 // Found separator or end of string
1539 // Found the end of the current name; add a new assembly name to the list.
1541 AssemblyName* newName = new (m_alloc) AssemblyName();
1543 // Null out the current character so we can do zero-terminated string work; we'll restore it later.
1544 *listWalk = W('\0');
1546 // How much space do we need?
1547 int convertedNameLenBytes =
1548 WszWideCharToMultiByte(CP_UTF8, 0, nameStart, -1, nullptr, 0, nullptr, nullptr);
1549 newName->m_assemblyName = new (m_alloc) char[convertedNameLenBytes]; // convertedNameLenBytes includes
1550 // the trailing null character
1551 if (WszWideCharToMultiByte(CP_UTF8, 0, nameStart, -1, newName->m_assemblyName, convertedNameLenBytes,
1552 nullptr, nullptr) != 0)
1554 *ppPrevLink = newName;
1555 ppPrevLink = &newName->m_next;
1559 // Failed to convert the string. Ignore this string (and leak the memory).
1562 nameStart = nullptr;
1564 // Restore the current character.
1565 *listWalk = curChar;
1568 else if (!nameStart)
1571 // Found the start of a new name
1574 nameStart = listWalk;
1578 assert(nameStart == nullptr); // cannot be in the middle of a name
1579 *ppPrevLink = nullptr; // Terminate the last element of the list.
1582 AssemblyNamesList2::~AssemblyNamesList2()
1584 for (AssemblyName* pName = m_pNames; pName != nullptr; /**/)
1586 AssemblyName* cur = pName;
1587 pName = pName->m_next;
1589 m_alloc.deallocate(cur->m_assemblyName);
1590 m_alloc.deallocate(cur);
1594 bool AssemblyNamesList2::IsInList(const char* assemblyName)
1596 for (AssemblyName* pName = m_pNames; pName != nullptr; pName = pName->m_next)
1598 if (_stricmp(pName->m_assemblyName, assemblyName) == 0)
1607 //=============================================================================
1609 //=============================================================================
1611 MethodSet::MethodSet(const WCHAR* filename, HostAllocator alloc) : m_pInfos(nullptr), m_alloc(alloc)
1613 FILE* methodSetFile = _wfopen(filename, W("r"));
1614 if (methodSetFile == nullptr)
1619 MethodInfo* lastInfo = m_pInfos;
1625 if (fgets(buffer, sizeof(buffer), methodSetFile) == nullptr)
1630 // Ignore lines starting with leading ";" "#" "//".
1631 if ((0 == _strnicmp(buffer, ";", 1)) || (0 == _strnicmp(buffer, "#", 1)) || (0 == _strnicmp(buffer, "//", 2)))
1636 // Remove trailing newline, if any.
1637 char* p = strpbrk(buffer, "\r\n");
1644 unsigned methodHash = 0;
1646 // Parse the line. Very simple. One of:
1649 // <method-name><whitespace>(MethodHash=<hash>)
1651 const char methodHashPattern[] = " (MethodHash=";
1652 p = strstr(buffer, methodHashPattern);
1655 // Just use it without the hash.
1656 methodName = _strdup(buffer);
1660 // There's a method hash; use that.
1662 // First, get the method name.
1666 // Null terminate method at first whitespace. (Don't have any leading whitespace!)
1667 p = strpbrk(buffer, " \t");
1672 methodName = _strdup(buffer);
1674 // Now get the method hash.
1675 p2 += strlen(methodHashPattern);
1676 char* p3 = strchr(p2, ')');
1679 // Malformed line: no trailing slash.
1680 JITDUMP("Couldn't parse: %s\n", p2);
1681 // We can still just use the method name.
1685 // Convert the slash to null.
1688 // Now parse it as hex.
1689 int count = sscanf_s(p2, "%x", &methodHash);
1692 JITDUMP("Couldn't parse: %s\n", p2);
1693 // Still, use the method name.
1698 MethodInfo* newInfo = new (m_alloc) MethodInfo(methodName, methodHash);
1699 if (m_pInfos == nullptr)
1701 m_pInfos = lastInfo = newInfo;
1705 lastInfo->m_next = newInfo;
1710 if (m_pInfos == nullptr)
1712 JITDUMP("No methods read from %ws\n", filename);
1716 JITDUMP("Methods read from %ws:\n", filename);
1718 int methodCount = 0;
1719 for (MethodInfo* pInfo = m_pInfos; pInfo != nullptr; pInfo = pInfo->m_next)
1721 JITDUMP(" %s (MethodHash: %x)\n", pInfo->m_MethodName, pInfo->m_MethodHash);
1725 if (methodCount > 100)
1727 JITDUMP("Warning: high method count (%d) for MethodSet with linear search lookups might be slow\n",
1733 MethodSet::~MethodSet()
1735 for (MethodInfo* pInfo = m_pInfos; pInfo != nullptr; /**/)
1737 MethodInfo* cur = pInfo;
1738 pInfo = pInfo->m_next;
1740 m_alloc.deallocate(cur->m_MethodName);
1741 m_alloc.deallocate(cur);
1745 // TODO: make this more like JitConfigValues::MethodSet::contains()?
1746 bool MethodSet::IsInSet(const char* methodName)
1748 for (MethodInfo* pInfo = m_pInfos; pInfo != nullptr; pInfo = pInfo->m_next)
1750 if (_stricmp(pInfo->m_MethodName, methodName) == 0)
1759 bool MethodSet::IsInSet(int methodHash)
1761 for (MethodInfo* pInfo = m_pInfos; pInfo != nullptr; pInfo = pInfo->m_next)
1763 if (pInfo->m_MethodHash == methodHash)
1772 bool MethodSet::IsActiveMethod(const char* methodName, int methodHash)
1774 if (methodHash != 0)
1776 // Use the method hash.
1777 if (IsInSet(methodHash))
1779 JITDUMP("Method active in MethodSet (hash match): %s Hash: %x\n", methodName, methodHash);
1784 // Else, fall back and use the method name.
1785 assert(methodName != nullptr);
1786 if (IsInSet(methodName))
1788 JITDUMP("Method active in MethodSet (name match): %s Hash: %x\n", methodName, methodHash);
1795 #ifdef FEATURE_JIT_METHOD_PERF
1796 CycleCount::CycleCount() : cps(CycleTimer::CyclesPerSecond())
1800 bool CycleCount::GetCycles(unsigned __int64* time)
1802 return CycleTimer::GetThreadCyclesS(time);
1805 bool CycleCount::Start()
1807 return GetCycles(&beginCycles);
1810 double CycleCount::ElapsedTime()
1812 unsigned __int64 nowCycles;
1813 (void)GetCycles(&nowCycles);
1814 return ((double)(nowCycles - beginCycles) / cps) * 1000.0;
1817 bool PerfCounter::Start()
1819 bool result = QueryPerformanceFrequency(&beg) != 0;
1824 freq = (double)beg.QuadPart / 1000.0;
1825 (void)QueryPerformanceCounter(&beg);
1829 // Return elapsed time from Start() in millis.
1830 double PerfCounter::ElapsedTime()
1833 (void)QueryPerformanceCounter(&li);
1834 return (double)(li.QuadPart - beg.QuadPart) / freq;
1841 /*****************************************************************************
1842 * Return the number of digits in a number of the given base (default base 10).
1843 * Used when outputting strings.
1845 unsigned CountDigits(unsigned num, unsigned base /* = 10 */)
1847 assert(2 <= base && base <= 16); // sanity check
1857 unsigned CountDigits(float num, unsigned base /* = 10 */)
1859 assert(2 <= base && base <= 16); // sanity check
1871 double FloatingPointUtils::convertUInt64ToDouble(unsigned __int64 uIntVal)
1873 __int64 s64 = uIntVal;
1877 #if defined(TARGET_XARCH)
1878 // RyuJIT codegen and clang (or gcc) may produce different results for casting uint64 to
1879 // double, and the clang result is more accurate. For example,
1880 // 1) (double)0x84595161401484A0UL --> 43e08b2a2c280290 (RyuJIT codegen or VC++)
1881 // 2) (double)0x84595161401484A0UL --> 43e08b2a2c280291 (clang or gcc)
1882 // If the folding optimization below is implemented by simple casting of (double)uint64_val
1883 // and it is compiled by clang, casting result can be inconsistent, depending on whether
1884 // the folding optimization is triggered or the codegen generates instructions for casting. //
1885 // The current solution is to force the same math as the codegen does, so that casting
1886 // result is always consistent.
1888 // d = (double)(int64_t)uint64 + 0x1p64
1889 uint64_t adjHex = 0x43F0000000000000UL;
1890 d = (double)s64 + *(double*)&adjHex;
1892 d = (double)uIntVal;
1897 d = (double)uIntVal;
1902 float FloatingPointUtils::convertUInt64ToFloat(unsigned __int64 u64)
1904 double d = convertUInt64ToDouble(u64);
1908 unsigned __int64 FloatingPointUtils::convertDoubleToUInt64(double d)
1910 unsigned __int64 u64;
1913 // Work around a C++ issue where it doesn't properly convert large positive doubles
1914 const double two63 = 2147483648.0 * 4294967296.0;
1921 // subtract 0x8000000000000000, do the convert then add it back again
1922 u64 = INT64(d - two63) + I64(0x8000000000000000);
1929 // While the Ecma spec does not specifically call this out,
1930 // the case of conversion from negative double to unsigned integer is
1931 // effectively an overflow and therefore the result is unspecified.
1932 // With MSVC for x86/x64, such a conversion results in the bit-equivalent
1933 // unsigned value of the conversion to integer. Other compilers convert
1934 // negative doubles to zero when the target is unsigned.
1935 // To make the behavior consistent across OS's on TARGET_XARCH,
1936 // this double cast is needed to conform MSVC behavior.
1938 u64 = UINT64(INT64(d));
1941 #endif // TARGET_XARCH
1946 // Rounds a double-precision floating-point value to the nearest integer,
1947 // and rounds midpoint values to the nearest even number.
1948 double FloatingPointUtils::round(double x)
1950 // ************************************************************************************
1951 // IMPORTANT: Do not change this implementation without also updating Math.Round(double),
1952 // MathF.Round(float), and FloatingPointUtils::round(float)
1953 // ************************************************************************************
1955 // This is based on the 'Berkeley SoftFloat Release 3e' algorithm
1957 uint64_t bits = *reinterpret_cast<uint64_t*>(&x);
1958 int32_t exponent = (int32_t)(bits >> 52) & 0x07FF;
1960 if (exponent <= 0x03FE)
1962 if ((bits << 1) == 0)
1964 // Exactly +/- zero should return the original value
1968 // Any value less than or equal to 0.5 will always round to exactly zero
1969 // and any value greater than 0.5 will always round to exactly one. However,
1970 // we need to preserve the original sign for IEEE compliance.
1972 double result = ((exponent == 0x03FE) && ((bits & UI64(0x000FFFFFFFFFFFFF)) != 0)) ? 1.0 : 0.0;
1973 return _copysign(result, x);
1976 if (exponent >= 0x0433)
1978 // Any value greater than or equal to 2^52 cannot have a fractional part,
1979 // So it will always round to exactly itself.
1984 // The absolute value should be greater than or equal to 1.0 and less than 2^52
1985 assert((0x03FF <= exponent) && (exponent <= 0x0432));
1987 // Determine the last bit that represents the integral portion of the value
1988 // and the bits representing the fractional portion
1990 uint64_t lastBitMask = UI64(1) << (0x0433 - exponent);
1991 uint64_t roundBitsMask = lastBitMask - 1;
1993 // Increment the first fractional bit, which represents the midpoint between
1994 // two integral values in the current window.
1996 bits += lastBitMask >> 1;
1998 if ((bits & roundBitsMask) == 0)
2000 // If that overflowed and the rest of the fractional bits are zero
2001 // then we were exactly x.5 and we want to round to the even result
2003 bits &= ~lastBitMask;
2007 // Otherwise, we just want to strip the fractional bits off, truncating
2008 // to the current integer value.
2010 bits &= ~roundBitsMask;
2013 return *reinterpret_cast<double*>(&bits);
2016 // Windows x86 and Windows ARM/ARM64 may not define _copysignf() but they do define _copysign().
2017 // We will redirect the macro to this other functions if the macro is not defined for the platform.
2018 // This has the side effect of a possible implicit upcasting for arguments passed in and an explicit
2019 // downcasting for the _copysign() call.
2020 #if (defined(TARGET_X86) || defined(TARGET_ARM) || defined(TARGET_ARM64)) && !defined(TARGET_UNIX)
2022 #if !defined(_copysignf)
2023 #define _copysignf (float)_copysign
2028 // Rounds a single-precision floating-point value to the nearest integer,
2029 // and rounds midpoint values to the nearest even number.
2030 float FloatingPointUtils::round(float x)
2032 // ************************************************************************************
2033 // IMPORTANT: Do not change this implementation without also updating MathF.Round(float),
2034 // Math.Round(double), and FloatingPointUtils::round(double)
2035 // ************************************************************************************
2037 // This is based on the 'Berkeley SoftFloat Release 3e' algorithm
2039 uint32_t bits = *reinterpret_cast<uint32_t*>(&x);
2040 int32_t exponent = (int32_t)(bits >> 23) & 0xFF;
2042 if (exponent <= 0x7E)
2044 if ((bits << 1) == 0)
2046 // Exactly +/- zero should return the original value
2050 // Any value less than or equal to 0.5 will always round to exactly zero
2051 // and any value greater than 0.5 will always round to exactly one. However,
2052 // we need to preserve the original sign for IEEE compliance.
2054 float result = ((exponent == 0x7E) && ((bits & 0x007FFFFF) != 0)) ? 1.0f : 0.0f;
2055 return _copysignf(result, x);
2058 if (exponent >= 0x96)
2060 // Any value greater than or equal to 2^52 cannot have a fractional part,
2061 // So it will always round to exactly itself.
2066 // The absolute value should be greater than or equal to 1.0 and less than 2^52
2067 assert((0x7F <= exponent) && (exponent <= 0x95));
2069 // Determine the last bit that represents the integral portion of the value
2070 // and the bits representing the fractional portion
2072 uint32_t lastBitMask = 1U << (0x96 - exponent);
2073 uint32_t roundBitsMask = lastBitMask - 1;
2075 // Increment the first fractional bit, which represents the midpoint between
2076 // two integral values in the current window.
2078 bits += lastBitMask >> 1;
2080 if ((bits & roundBitsMask) == 0)
2082 // If that overflowed and the rest of the fractional bits are zero
2083 // then we were exactly x.5 and we want to round to the even result
2085 bits &= ~lastBitMask;
2089 // Otherwise, we just want to strip the fractional bits off, truncating
2090 // to the current integer value.
2092 bits &= ~roundBitsMask;
2095 return *reinterpret_cast<float*>(&bits);
2098 bool FloatingPointUtils::isNormal(double x)
2100 int64_t bits = reinterpret_cast<int64_t&>(x);
2101 bits &= 0x7FFFFFFFFFFFFFFF;
2102 return (bits < 0x7FF0000000000000) && (bits != 0) && ((bits & 0x7FF0000000000000) != 0);
2105 bool FloatingPointUtils::isNormal(float x)
2107 int32_t bits = reinterpret_cast<int32_t&>(x);
2109 return (bits < 0x7F800000) && (bits != 0) && ((bits & 0x7F800000) != 0);
2112 //------------------------------------------------------------------------
2113 // infinite_float: return an infinite float value
2116 // Infinite float value.
2119 // This is the predefined constant HUGE_VALF on many platforms.
2121 float FloatingPointUtils::infinite_float()
2123 int32_t bits = 0x7F800000;
2124 return *reinterpret_cast<float*>(&bits);
2127 //------------------------------------------------------------------------
2128 // hasPreciseReciprocal: check double for precise reciprocal. E.g. 2.0 <--> 0.5
2131 // x - value to check for precise reciprocal
2134 // True if 'x' is a power of two value and is not denormal (denormals may not be well-defined
2135 // on some platforms such as if the user modified the floating-point environment via a P/Invoke)
2138 bool FloatingPointUtils::hasPreciseReciprocal(double x)
2145 uint64_t i = reinterpret_cast<uint64_t&>(x);
2146 uint64_t exponent = (i >> 52) & 0x7FFul; // 0x7FF mask drops the sign bit
2147 uint64_t mantissa = i & 0xFFFFFFFFFFFFFul; // 0xFFFFFFFFFFFFF mask drops the sign + exponent bits
2148 return mantissa == 0 && exponent != 0 && exponent != 1023;
2151 //------------------------------------------------------------------------
2152 // hasPreciseReciprocal: check float for precise reciprocal. E.g. 2.0f <--> 0.5f
2155 // x - value to check for precise reciprocal
2158 // True if 'x' is a power of two value and is not denormal (denormals may not be well-defined
2159 // on some platforms such as if the user modified the floating-point environment via a P/Invoke)
2162 bool FloatingPointUtils::hasPreciseReciprocal(float x)
2169 uint32_t i = reinterpret_cast<uint32_t&>(x);
2170 uint32_t exponent = (i >> 23) & 0xFFu; // 0xFF mask drops the sign bit
2171 uint32_t mantissa = i & 0x7FFFFFu; // 0x7FFFFF mask drops the sign + exponent bits
2172 return mantissa == 0 && exponent != 0 && exponent != 127;
2175 namespace MagicDivide
2177 template <int TableBase = 0, int TableSize, typename Magic>
2178 static const Magic* TryGetMagic(const Magic (&table)[TableSize], typename Magic::DivisorType index)
2180 if ((index < TableBase) || (TableBase + TableSize <= index))
2185 const Magic* p = &table[index - TableBase];
2195 template <typename T>
2196 struct UnsignedMagic
2198 typedef T DivisorType;
2205 template <typename T>
2206 const UnsignedMagic<T>* TryGetUnsignedMagic(T divisor)
2212 const UnsignedMagic<uint32_t>* TryGetUnsignedMagic(uint32_t divisor)
2214 static const UnsignedMagic<uint32_t> table[]{
2215 {0xaaaaaaab, false, 1}, // 3
2217 {0xcccccccd, false, 2}, // 5
2218 {0xaaaaaaab, false, 2}, // 6
2219 {0x24924925, true, 3}, // 7
2221 {0x38e38e39, false, 1}, // 9
2222 {0xcccccccd, false, 3}, // 10
2223 {0xba2e8ba3, false, 3}, // 11
2224 {0xaaaaaaab, false, 3}, // 12
2227 return TryGetMagic<3>(table, divisor);
2231 const UnsignedMagic<uint64_t>* TryGetUnsignedMagic(uint64_t divisor)
2233 static const UnsignedMagic<uint64_t> table[]{
2234 {0xaaaaaaaaaaaaaaab, false, 1}, // 3
2236 {0xcccccccccccccccd, false, 2}, // 5
2237 {0xaaaaaaaaaaaaaaab, false, 2}, // 6
2238 {0x2492492492492493, true, 3}, // 7
2240 {0xe38e38e38e38e38f, false, 3}, // 9
2241 {0xcccccccccccccccd, false, 3}, // 10
2242 {0x2e8ba2e8ba2e8ba3, false, 1}, // 11
2243 {0xaaaaaaaaaaaaaaab, false, 3}, // 12
2246 return TryGetMagic<3>(table, divisor);
2249 //------------------------------------------------------------------------
2250 // GetUnsignedMagic: Generates a magic number and shift amount for the magic
2251 // number unsigned division optimization.
2255 // add - Pointer to a flag indicating the kind of code to generate
2256 // shift - Pointer to the shift value to be returned
2259 // The magic number.
2262 // This code is adapted from _The_PowerPC_Compiler_Writer's_Guide_, pages 57-58.
2263 // The paper is based on "Division by invariant integers using multiplication"
2264 // by Torbjorn Granlund and Peter L. Montgomery in PLDI 94
2266 template <typename T>
2267 T GetUnsignedMagic(T d, bool* add /*out*/, int* shift /*out*/)
2269 assert((d >= 3) && !isPow2(d));
2271 const UnsignedMagic<T>* magic = TryGetUnsignedMagic(d);
2273 if (magic != nullptr)
2275 *shift = magic->shift;
2277 return magic->magic;
2280 typedef typename std::make_signed<T>::type ST;
2282 const unsigned bits = sizeof(T) * 8;
2283 const unsigned bitsMinus1 = bits - 1;
2284 const T twoNMinus1 = T(1) << bitsMinus1;
2287 const T nc = -ST(1) - -ST(d) % ST(d);
2288 unsigned p = bitsMinus1;
2289 T q1 = twoNMinus1 / nc;
2290 T r1 = twoNMinus1 - (q1 * nc);
2291 T q2 = (twoNMinus1 - 1) / d;
2292 T r2 = (twoNMinus1 - 1) - (q2 * d);
2299 if (r1 >= (nc - r1))
2310 if ((r2 + 1) >= (d - r2))
2312 if (q2 >= (twoNMinus1 - 1))
2318 r2 = 2 * r2 + 1 - d;
2322 if (q2 >= twoNMinus1)
2333 } while ((p < (bits * 2)) && ((q1 < delta) || ((q1 == delta) && (r1 == 0))));
2335 *shift = p - bits; // resulting shift
2336 return q2 + 1; // resulting magic number
2339 uint32_t GetUnsigned32Magic(uint32_t d, bool* add /*out*/, int* shift /*out*/)
2341 return GetUnsignedMagic<uint32_t>(d, add, shift);
2345 uint64_t GetUnsigned64Magic(uint64_t d, bool* add /*out*/, int* shift /*out*/)
2347 return GetUnsignedMagic<uint64_t>(d, add, shift);
2351 template <typename T>
2354 typedef T DivisorType;
2360 template <typename T>
2361 const SignedMagic<T>* TryGetSignedMagic(T divisor)
2367 const SignedMagic<int32_t>* TryGetSignedMagic(int32_t divisor)
2369 static const SignedMagic<int32_t> table[]{
2370 {0x55555556, 0}, // 3
2372 {0x66666667, 1}, // 5
2373 {0x2aaaaaab, 0}, // 6
2374 {(int32_t)0x92492493, 2}, // 7
2376 {0x38e38e39, 1}, // 9
2377 {0x66666667, 2}, // 10
2378 {0x2e8ba2e9, 1}, // 11
2379 {0x2aaaaaab, 1}, // 12
2382 return TryGetMagic<3>(table, divisor);
2386 const SignedMagic<int64_t>* TryGetSignedMagic(int64_t divisor)
2388 static const SignedMagic<int64_t> table[]{
2389 {0x5555555555555556, 0}, // 3
2391 {0x6666666666666667, 1}, // 5
2392 {0x2aaaaaaaaaaaaaab, 0}, // 6
2393 {0x4924924924924925, 1}, // 7
2395 {0x1c71c71c71c71c72, 0}, // 9
2396 {0x6666666666666667, 2}, // 10
2397 {0x2e8ba2e8ba2e8ba3, 1}, // 11
2398 {0x2aaaaaaaaaaaaaab, 1}, // 12
2401 return TryGetMagic<3>(table, divisor);
2404 //------------------------------------------------------------------------
2405 // GetSignedMagic: Generates a magic number and shift amount for
2406 // the magic number division optimization.
2409 // denom - The denominator
2410 // shift - Pointer to the shift value to be returned
2413 // The magic number.
2416 // This code is previously from UTC where it notes it was taken from
2417 // _The_PowerPC_Compiler_Writer's_Guide_, pages 57-58. The paper is based on
2418 // is "Division by invariant integers using multiplication" by Torbjorn Granlund
2419 // and Peter L. Montgomery in PLDI 94
2421 template <typename T>
2422 T GetSignedMagic(T denom, int* shift /*out*/)
2424 const SignedMagic<T>* magic = TryGetSignedMagic(denom);
2426 if (magic != nullptr)
2428 *shift = magic->shift;
2429 return magic->magic;
2432 const int bits = sizeof(T) * 8;
2433 const int bits_minus_1 = bits - 1;
2435 typedef typename std::make_unsigned<T>::type UT;
2437 const UT two_nminus1 = UT(1) << bits_minus_1;
2450 absDenom = abs(denom);
2451 t = two_nminus1 + (UT(denom) >> bits_minus_1);
2452 absNc = t - 1 - (t % absDenom); // absolute value of nc
2453 p = bits_minus_1; // initialize p
2454 q1 = two_nminus1 / absNc; // initialize q1 = 2^p / abs(nc)
2455 r1 = two_nminus1 - (q1 * absNc); // initialize r1 = rem(2^p, abs(nc))
2456 q2 = two_nminus1 / absDenom; // initialize q1 = 2^p / abs(denom)
2457 r2 = two_nminus1 - (q2 * absDenom); // initialize r1 = rem(2^p, abs(denom))
2462 q1 *= 2; // update q1 = 2^p / abs(nc)
2463 r1 *= 2; // update r1 = rem(2^p / abs(nc))
2466 { // must be unsigned comparison
2471 q2 *= 2; // update q2 = 2^p / abs(denom)
2472 r2 *= 2; // update r2 = rem(2^p / abs(denom))
2475 { // must be unsigned comparison
2480 delta = absDenom - r2;
2481 } while (q1 < delta || (q1 == delta && r1 == 0));
2483 result_magic = q2 + 1; // resulting magic number
2486 result_magic = -result_magic;
2488 *shift = p - bits; // resulting shift
2490 return result_magic;
2493 int32_t GetSigned32Magic(int32_t d, int* shift /*out*/)
2495 return GetSignedMagic<int32_t>(d, shift);
2499 int64_t GetSigned64Magic(int64_t d, int* shift /*out*/)
2501 return GetSignedMagic<int64_t>(d, shift);