dafa816193cb777a503c4e16630801e88b89534a
[platform/upstream/dotnet/runtime.git] / src / coreclr / jit / utils.cpp
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
4 // ===================================================================================================
5 // Portions of the code implemented below are based on the 'Berkeley SoftFloat Release 3e' algorithms.
6 // ===================================================================================================
7
8 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10 XX                                                                           XX
11 XX                                  Utils.cpp                                XX
12 XX                                                                           XX
13 XX   Has miscellaneous utility functions                                     XX
14 XX                                                                           XX
15 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
16 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
17 */
18
19 #include "jitpch.h"
20 #ifdef _MSC_VER
21 #pragma hdrstop
22 #endif
23
24 #include "opcode.h"
25
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
29 // files.
30
31 #ifdef TARGET_UNIX
32 // Should we distinguish Mac? Can we?
33 // Should we distinguish flavors of Unix? Can we?
34 const char* Target::g_tgtPlatformName = "Unix";
35 #else  // !TARGET_UNIX
36 const char* Target::g_tgtPlatformName = "Windows";
37 #endif // !TARGET_UNIX
38
39 /*****************************************************************************/
40
41 #define DECLARE_DATA
42
43 // clang-format off
44 extern
45 const signed char       opcodeSizes[] =
46 {
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
67
68     #define OPDEF(name,string,pop,push,oprType,opcType,l,s1,s2,ctrl) oprType ## _size ,
69     #include "opcode.def"
70     #undef OPDEF
71
72     #undef InlineNone_size
73     #undef ShortInlineVar_size
74     #undef InlineVar_size
75     #undef ShortInlineI_size
76     #undef InlineI_size
77     #undef InlineI8_size
78     #undef ShortInlineR_size
79     #undef InlineR_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
86     #undef InlineSig_size
87     #undef InlineRVA_size
88     #undef InlineTok_size
89     #undef InlineSwitch_size
90     #undef InlinePhi_size
91 };
92 // clang-format on
93
94 const BYTE varTypeClassification[] = {
95 #define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) tf,
96 #include "typelist.h"
97 #undef DEF_TP
98 };
99
100 /*****************************************************************************/
101 /*****************************************************************************/
102 #ifdef DEBUG
103 extern const char* const opcodeNames[] = {
104 #define OPDEF(name, string, pop, push, oprType, opcType, l, s1, s2, ctrl) string,
105 #include "opcode.def"
106 #undef OPDEF
107 };
108
109 extern const BYTE opcodeArgKinds[] = {
110 #define OPDEF(name, string, pop, push, oprType, opcType, l, s1, s2, ctrl) (BYTE) oprType,
111 #include "opcode.def"
112 #undef OPDEF
113 };
114 #endif
115
116 /*****************************************************************************/
117
118 const char* varTypeName(var_types vt)
119 {
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"
123 #undef DEF_TP
124     };
125
126     assert((unsigned)vt < _countof(varTypeNames));
127
128     return varTypeNames[vt];
129 }
130
131 #if defined(DEBUG) || defined(LATE_DISASM) || DUMP_GC_TABLES
132 /*****************************************************************************
133  *
134  *  Return the name of the given register.
135  */
136
137 const char* getRegName(regNumber reg, bool isFloat)
138 {
139     // Special-case REG_NA; it's not in the regNames array, but we might want to print it.
140     if (reg == REG_NA)
141     {
142         return "NA";
143     }
144
145 #if defined(TARGET_ARM64)
146     static const char* const regNames[] = {
147 #define REGDEF(name, rnum, mask, xname, wname) xname,
148 #include "register.h"
149     };
150     assert(reg < ArrLen(regNames));
151     return regNames[reg];
152 #else
153     static const char* const regNames[] = {
154 #define REGDEF(name, rnum, mask, sname) sname,
155 #include "register.h"
156     };
157     assert(reg < ArrLen(regNames));
158     return regNames[reg];
159 #endif
160 }
161
162 const char* getRegName(unsigned reg,
163                        bool     isFloat) // this is for gcencode.cpp and disasm.cpp that dont use the regNumber type
164 {
165     return getRegName((regNumber)reg, isFloat);
166 }
167 #endif // defined(DEBUG) || defined(LATE_DISASM) || DUMP_GC_TABLES
168
169 #if defined(DEBUG)
170
171 const char* getRegNameFloat(regNumber reg, var_types type)
172 {
173 #ifdef TARGET_ARM
174     assert(genIsValidFloatReg(reg));
175     if (type == TYP_FLOAT)
176         return getRegName(reg);
177     else
178     {
179         const char* regName;
180
181         switch (reg)
182         {
183             default:
184                 assert(!"Bad double register");
185                 regName = "d??";
186                 break;
187             case REG_F0:
188                 regName = "d0";
189                 break;
190             case REG_F2:
191                 regName = "d2";
192                 break;
193             case REG_F4:
194                 regName = "d4";
195                 break;
196             case REG_F6:
197                 regName = "d6";
198                 break;
199             case REG_F8:
200                 regName = "d8";
201                 break;
202             case REG_F10:
203                 regName = "d10";
204                 break;
205             case REG_F12:
206                 regName = "d12";
207                 break;
208             case REG_F14:
209                 regName = "d14";
210                 break;
211             case REG_F16:
212                 regName = "d16";
213                 break;
214             case REG_F18:
215                 regName = "d18";
216                 break;
217             case REG_F20:
218                 regName = "d20";
219                 break;
220             case REG_F22:
221                 regName = "d22";
222                 break;
223             case REG_F24:
224                 regName = "d24";
225                 break;
226             case REG_F26:
227                 regName = "d26";
228                 break;
229             case REG_F28:
230                 regName = "d28";
231                 break;
232             case REG_F30:
233                 regName = "d30";
234                 break;
235         }
236         return regName;
237     }
238
239 #elif defined(TARGET_ARM64)
240
241     static const char* regNamesFloat[] = {
242 #define REGDEF(name, rnum, mask, xname, wname) xname,
243 #include "register.h"
244     };
245     assert((unsigned)reg < ArrLen(regNamesFloat));
246
247     return regNamesFloat[reg];
248
249 #else
250     static const char* regNamesFloat[] = {
251 #define REGDEF(name, rnum, mask, sname) "x" sname,
252 #include "register.h"
253     };
254 #ifdef FEATURE_SIMD
255     static const char* regNamesYMM[] = {
256 #define REGDEF(name, rnum, mask, sname) "y" sname,
257 #include "register.h"
258     };
259 #endif // FEATURE_SIMD
260     assert((unsigned)reg < ArrLen(regNamesFloat));
261
262 #ifdef FEATURE_SIMD
263     if (type == TYP_SIMD32)
264     {
265         return regNamesYMM[reg];
266     }
267 #endif // FEATURE_SIMD
268
269     return regNamesFloat[reg];
270 #endif
271 }
272
273 /*****************************************************************************
274  *
275  *  Displays a register set.
276  *  TODO-ARM64-Cleanup: don't allow ip0, ip1 as part of a range.
277  */
278
279 void dspRegMask(regMaskTP regMask, size_t minSiz)
280 {
281     const char* sep = "";
282
283     printf("[");
284
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))
290     {
291         regMaskTP regBit = genRegMask(regNum);
292
293         if ((regMask & regBit) != 0)
294         {
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).
300             if (!inRegRange)
301             {
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);
306
307                 // By default, we're not starting a potential register range.
308                 sep = " ";
309
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;
312
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)
316                 {
317                     regHead    = regNum;
318                     inRegRange = true;
319                     sep        = "-";
320                 }
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)))
324                 {
325                     regHead    = regNum;
326                     inRegRange = true;
327                     sep        = "-";
328                 }
329 #elif defined(TARGET_ARM)
330                 if (regNum < REG_R12)
331                 {
332                     regHead    = regNum;
333                     inRegRange = true;
334                     sep        = "-";
335                 }
336 #elif defined(TARGET_X86)
337 // No register ranges
338 #else // TARGET*
339 #error Unsupported or unset target architecture
340 #endif // TARGET*
341             }
342
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
351             {
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
356                 regHead    = REG_NA;
357                 sep        = " ";
358             }
359         }
360         else // ((regMask & regBit) == 0)
361         {
362             if (inRegRange)
363             {
364                 assert(regHead != REG_NA);
365                 if (regPrev != regHead)
366                 {
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);
371                 }
372                 sep        = " ";
373                 inRegRange = false;
374                 regHead    = REG_NA;
375             }
376         }
377
378         if (regBit > regMask)
379         {
380             break;
381         }
382
383         regPrev = regNum;
384     }
385
386     if (strlen(sep) > 0)
387     {
388         // We've already printed something.
389         sep = " ";
390     }
391     inRegRange = false;
392     regPrev    = REG_NA;
393     regHead    = REG_NA;
394     for (regNumber regNum = REG_FP_FIRST; regNum <= REG_FP_LAST; regNum = REG_NEXT(regNum))
395     {
396         regMaskTP regBit = genRegMask(regNum);
397
398         if (regMask & regBit)
399         {
400             if (!inRegRange || (regNum == REG_FP_LAST))
401             {
402                 const char* nam = getRegName(regNum);
403                 printf("%s%s", sep, nam);
404                 minSiz -= strlen(sep) + strlen(nam);
405                 sep     = "-";
406                 regHead = regNum;
407             }
408             inRegRange = true;
409         }
410         else
411         {
412             if (inRegRange)
413             {
414                 if (regPrev != regHead)
415                 {
416                     const char* nam = getRegName(regPrev);
417                     printf("%s%s", sep, nam);
418                     minSiz -= (strlen(sep) + strlen(nam));
419                 }
420                 sep = " ";
421             }
422             inRegRange = false;
423         }
424
425         if (regBit > regMask)
426         {
427             break;
428         }
429
430         regPrev = regNum;
431     }
432
433     printf("]");
434
435     while ((int)minSiz > 0)
436     {
437         printf(" ");
438         minSiz--;
439     }
440 }
441
442 //------------------------------------------------------------------------
443 // dumpILBytes: Helper for dumpSingleInstr() to dump hex bytes of an IL stream,
444 // aligning up to a minimum alignment width.
445 //
446 // Arguments:
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.
450 //
451 void dumpILBytes(const BYTE* const codeAddr,
452                  unsigned          codeSize,
453                  unsigned          alignSize) // number of characters to write, for alignment
454 {
455     for (IL_OFFSET offs = 0; offs < codeSize; ++offs)
456     {
457         printf(" %02x", *(codeAddr + offs));
458     }
459
460     unsigned charsWritten = 3 * codeSize;
461     for (unsigned i = charsWritten; i < alignSize; i++)
462     {
463         printf(" ");
464     }
465 }
466
467 //------------------------------------------------------------------------
468 // dumpSingleInstr: Display a single IL instruction.
469 //
470 // Arguments:
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).
474 //
475 // Return Value:
476 //    Size of the displayed IL instruction in the instruction stream, in bytes. (Add this to 'offs' to
477 //    get to the next instruction.)
478 //
479 unsigned dumpSingleInstr(const BYTE* const codeAddr, IL_OFFSET offs, const char* prefix)
480 {
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
484                                            // most things
485
486     if (prefix != nullptr)
487     {
488         printf("%s", prefix);
489     }
490
491     OPCODE opcode = (OPCODE)getU1LittleEndian(opcodePtr);
492     opcodePtr += sizeof(__int8);
493
494 DECODE_OPCODE:
495
496     if (opcode >= CEE_COUNT)
497     {
498         printf("\nIllegal opcode: %02X\n", (int)opcode);
499         return (IL_OFFSET)(opcodePtr - startOpcodePtr);
500     }
501
502     /* Get the size of additional parameters */
503
504     size_t   sz      = opcodeSizes[opcode];
505     unsigned argKind = opcodeArgKinds[opcode];
506
507     /* See what kind of an opcode we have, then */
508
509     switch (opcode)
510     {
511         case CEE_PREFIX1:
512             opcode = OPCODE(getU1LittleEndian(opcodePtr) + 256);
513             opcodePtr += sizeof(__int8);
514             goto DECODE_OPCODE;
515
516         default:
517         {
518             __int64 iOp;
519             double  dOp;
520             int     jOp;
521             DWORD   jOp2;
522
523             switch (argKind)
524             {
525                 case InlineNone:
526                     dumpILBytes(startOpcodePtr, (unsigned)(opcodePtr - startOpcodePtr), ALIGN_WIDTH);
527                     printf(" %-12s", opcodeNames[opcode]);
528                     break;
529
530                 case ShortInlineVar:
531                     iOp = getU1LittleEndian(opcodePtr);
532                     goto INT_OP;
533                 case ShortInlineI:
534                     iOp = getI1LittleEndian(opcodePtr);
535                     goto INT_OP;
536                 case InlineVar:
537                     iOp = getU2LittleEndian(opcodePtr);
538                     goto INT_OP;
539                 case InlineTok:
540                 case InlineMethod:
541                 case InlineField:
542                 case InlineType:
543                 case InlineString:
544                 case InlineSig:
545                 case InlineI:
546                     iOp = getI4LittleEndian(opcodePtr);
547                     goto INT_OP;
548                 case InlineI8:
549                     iOp = getU4LittleEndian(opcodePtr);
550                     iOp |= (__int64)getU4LittleEndian(opcodePtr + 4) << 32;
551                     goto INT_OP;
552
553                 INT_OP:
554                     dumpILBytes(startOpcodePtr, (unsigned)((opcodePtr - startOpcodePtr) + sz), ALIGN_WIDTH);
555                     printf(" %-12s 0x%X", opcodeNames[opcode], iOp);
556                     break;
557
558                 case ShortInlineR:
559                     dOp = getR4LittleEndian(opcodePtr);
560                     goto FLT_OP;
561                 case InlineR:
562                     dOp = getR8LittleEndian(opcodePtr);
563                     goto FLT_OP;
564
565                 FLT_OP:
566                     dumpILBytes(startOpcodePtr, (unsigned)((opcodePtr - startOpcodePtr) + sz), ALIGN_WIDTH);
567                     printf(" %-12s %f", opcodeNames[opcode], dOp);
568                     break;
569
570                 case ShortInlineBrTarget:
571                     jOp = getI1LittleEndian(opcodePtr);
572                     goto JMP_OP;
573                 case InlineBrTarget:
574                     jOp = getI4LittleEndian(opcodePtr);
575                     goto JMP_OP;
576
577                 JMP_OP:
578                     dumpILBytes(startOpcodePtr, (unsigned)((opcodePtr - startOpcodePtr) + sz), ALIGN_WIDTH);
579                     printf(" %-12s %d (IL_%04x)", opcodeNames[opcode], jOp, (int)(opcodePtr + sz - codeAddr) + jOp);
580                     break;
581
582                 case InlineSwitch:
583                     jOp2 = getU4LittleEndian(opcodePtr);
584                     opcodePtr += 4;
585                     opcodePtr += jOp2 * 4; // Jump over the table
586                     dumpILBytes(startOpcodePtr, (unsigned)(opcodePtr - startOpcodePtr), ALIGN_WIDTH);
587                     printf(" %-12s", opcodeNames[opcode]);
588                     break;
589
590                 case InlinePhi:
591                     jOp2 = getU1LittleEndian(opcodePtr);
592                     opcodePtr += 1;
593                     opcodePtr += jOp2 * 2; // Jump over the table
594                     dumpILBytes(startOpcodePtr, (unsigned)(opcodePtr - startOpcodePtr), ALIGN_WIDTH);
595                     printf(" %-12s", opcodeNames[opcode]);
596                     break;
597
598                 default:
599                     assert(!"Bad argKind");
600             }
601
602             opcodePtr += sz;
603             break;
604         }
605     }
606
607     printf("\n");
608     return (IL_OFFSET)(opcodePtr - startOpcodePtr);
609 }
610
611 //------------------------------------------------------------------------
612 // dumpILRange: Display a range of IL instructions from an IL instruction stream.
613 //
614 // Arguments:
615 //    codeAddr  - Pointer to IL byte stream to display.
616 //    codeSize  - Number of bytes of IL byte stream to display.
617 //
618 void dumpILRange(const BYTE* const codeAddr, unsigned codeSize) // in bytes
619 {
620     for (IL_OFFSET offs = 0; offs < codeSize;)
621     {
622         char prefix[100];
623         sprintf_s(prefix, _countof(prefix), "IL_%04x ", offs);
624         unsigned codeBytesDumped = dumpSingleInstr(codeAddr, offs, prefix);
625         offs += codeBytesDumped;
626     }
627 }
628
629 /*****************************************************************************
630  *
631  *  Display a variable set.
632  */
633 const char* genES2str(BitVecTraits* traits, EXPSET_TP set)
634 {
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;
639
640     assert(bufSize > roundUp(BitVecTraits::GetSize(traits), (unsigned)sizeof(char)) / 8);
641
642     char* temp = nump;
643     nump       = (nump == num1) ? num2 : num1;
644     sprintf_s(temp, bufSize, "%s", BitVecOps::ToString(traits, set));
645
646     return temp;
647 }
648
649 const char* refCntWtd2str(BasicBlock::weight_t refCntWtd)
650 {
651     const int    bufSize = 17;
652     static char  num1[bufSize];
653     static char  num2[bufSize];
654     static char* nump = num1;
655
656     char* temp = nump;
657
658     nump = (nump == num1) ? num2 : num1;
659
660     if (refCntWtd == BB_MAX_WEIGHT)
661     {
662         sprintf_s(temp, bufSize, "MAX   ");
663     }
664     else
665     {
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);
670
671         // Use g format for high dynamic range counts.
672         //
673         if (isLarge || isSmall)
674         {
675             sprintf_s(temp, bufSize, "%.2g", scaledWeight);
676         }
677         else
678         {
679             if (intPart == scaledWeight)
680             {
681                 sprintf_s(temp, bufSize, "%lld   ", (long long)intPart);
682             }
683             else
684             {
685                 sprintf_s(temp, bufSize, "%.2f", scaledWeight);
686             }
687         }
688     }
689     return temp;
690 }
691
692 #endif // DEBUG
693
694 #if defined(DEBUG) || defined(INLINE_DATA)
695
696 //------------------------------------------------------------------------
697 // Contains: check if the range includes a particular hash
698 //
699 // Arguments:
700 //    hash -- hash value to check
701
702 bool ConfigMethodRange::Contains(unsigned hash)
703 {
704     _ASSERT(m_inited == 1);
705
706     // No ranges specified means all methods included.
707     if (m_lastRange == 0)
708     {
709         return true;
710     }
711
712     for (unsigned i = 0; i < m_lastRange; i++)
713     {
714         if ((m_ranges[i].m_low <= hash) && (hash <= m_ranges[i].m_high))
715         {
716             return true;
717         }
718     }
719
720     return false;
721 }
722
723 //------------------------------------------------------------------------
724 // InitRanges: parse the range string and set up the range info
725 //
726 // Arguments:
727 //    rangeStr -- string to parse (may be nullptr)
728 //    capacity -- number ranges to allocate in the range array
729 //
730 // Notes:
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.
735
736 void ConfigMethodRange::InitRanges(const WCHAR* rangeStr, unsigned capacity)
737 {
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);
743
744     // Flag any strange-looking requests
745     assert(capacity < 100000);
746
747     if (rangeStr == nullptr)
748     {
749         m_inited = 1;
750         return;
751     }
752
753     // Allocate some persistent memory
754     ICorJitHost* jitHost = g_jitHost;
755     m_ranges             = (Range*)jitHost->allocateMemory(capacity * sizeof(Range));
756     m_entries            = capacity;
757
758     const WCHAR* p           = rangeStr;
759     unsigned     lastRange   = 0;
760     bool         setHighPart = false;
761
762     while ((*p != 0) && (lastRange < m_entries))
763     {
764         while ((*p == L' ') || (*p == L','))
765         {
766             p++;
767         }
768
769         int i = 0;
770
771         while (((L'0' <= *p) && (*p <= L'9')) || ((L'A' <= *p) && (*p <= L'F')) || ((L'a' <= *p) && (*p <= L'f')))
772         {
773             int n = 0;
774
775             if ((L'0' <= *p) && (*p <= L'9'))
776             {
777                 n = (*p++) - L'0';
778             }
779             else if ((L'A' <= *p) && (*p <= L'F'))
780             {
781                 n = (*p++) - L'A' + 10;
782             }
783             else if ((L'a' <= *p) && (*p <= L'f'))
784             {
785                 n = (*p++) - L'a' + 10;
786             }
787
788             int j = 16 * i + n;
789
790             // Check for overflow
791             if ((m_badChar != 0) && (j <= i))
792             {
793                 m_badChar = (p - rangeStr) + 1;
794             }
795
796             i = j;
797         }
798
799         // Was this the high part of a low-high pair?
800         if (setHighPart)
801         {
802             // Yep, set it and move to the next range
803             m_ranges[lastRange].m_high = i;
804
805             // Sanity check that range is proper
806             if ((m_badChar != 0) && (m_ranges[lastRange].m_high < m_ranges[lastRange].m_low))
807             {
808                 m_badChar = (p - rangeStr) + 1;
809             }
810
811             lastRange++;
812             setHighPart = false;
813             continue;
814         }
815
816         // Must have been looking for the low part of a range
817         m_ranges[lastRange].m_low = i;
818
819         while (*p == L' ')
820         {
821             p++;
822         }
823
824         // Was that the low part of a low-high pair?
825         if (*p == L'-')
826         {
827             // Yep, skip the dash and set high part next time around.
828             p++;
829             setHighPart = true;
830             continue;
831         }
832
833         // Else we have a point range, so set high = low
834         m_ranges[lastRange].m_high = i;
835         lastRange++;
836     }
837
838     // If we didn't parse the full range string, note index of the the
839     // first bad char.
840     if ((m_badChar != 0) && (*p != 0))
841     {
842         m_badChar = (p - rangeStr) + 1;
843     }
844
845     // Finish off any remaining open range
846     if (setHighPart)
847     {
848         m_ranges[lastRange].m_high = UINT_MAX;
849         lastRange++;
850     }
851
852     assert(lastRange <= m_entries);
853     m_lastRange = lastRange;
854     m_inited    = 1;
855 }
856
857 //------------------------------------------------------------------------
858 // Dump: dump hash ranges to stdout
859 //
860 void ConfigMethodRange::Dump()
861 {
862     if (m_inited != 1)
863     {
864         printf("<uninitialized method range>\n");
865         return;
866     }
867
868     if (m_lastRange == 0)
869     {
870         printf("<empty method range>\n");
871         return;
872     }
873
874     printf("<method range with %d entries>\n", m_lastRange);
875     for (unsigned i = 0; i < m_lastRange; i++)
876     {
877         if (m_ranges[i].m_low == m_ranges[i].m_high)
878         {
879             printf("%i [0x%08x]\n", i, m_ranges[i].m_low);
880         }
881         else
882         {
883             printf("%i [0x%08x-0x%08x]\n", i, m_ranges[i].m_low, m_ranges[i].m_high);
884         }
885     }
886 }
887
888 #endif // defined(DEBUG) || defined(INLINE_DATA)
889
890 #if CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE || MEASURE_MEM_ALLOC
891
892 /*****************************************************************************
893  *  Histogram class.
894  */
895
896 Histogram::Histogram(const unsigned* const sizeTable) : m_sizeTable(sizeTable)
897 {
898     unsigned sizeCount = 0;
899     do
900     {
901         sizeCount++;
902     } while ((sizeTable[sizeCount] != 0) && (sizeCount < 1000));
903
904     assert(sizeCount < HISTOGRAM_MAX_SIZE_COUNT - 1);
905
906     m_sizeCount = sizeCount;
907
908     memset(m_counts, 0, (m_sizeCount + 1) * sizeof(*m_counts));
909 }
910
911 void Histogram::dump(FILE* output)
912 {
913     unsigned t = 0;
914     for (unsigned i = 0; i < m_sizeCount; i++)
915     {
916         t += m_counts[i];
917     }
918
919     for (unsigned c = 0, i = 0; i <= m_sizeCount; i++)
920     {
921         if (i == m_sizeCount)
922         {
923             if (m_counts[i] == 0)
924             {
925                 break;
926             }
927
928             fprintf(output, "      >    %7u", m_sizeTable[i - 1]);
929         }
930         else
931         {
932             if (i == 0)
933             {
934                 fprintf(output, "     <=    ");
935             }
936             else
937             {
938                 fprintf(output, "%7u .. ", m_sizeTable[i - 1] + 1);
939             }
940
941             fprintf(output, "%7u", m_sizeTable[i]);
942         }
943
944         c += m_counts[i];
945
946         fprintf(output, " ===> %7u count (%3u%% of total)\n", m_counts[i], (int)(100.0 * c / t));
947     }
948 }
949
950 void Histogram::record(unsigned size)
951 {
952     unsigned i;
953     for (i = 0; i < m_sizeCount; i++)
954     {
955         if (m_sizeTable[i] >= size)
956         {
957             break;
958         }
959     }
960
961     m_counts[i]++;
962 }
963
964 #endif // CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE
965
966 /*****************************************************************************
967  * Fixed bit vector class
968  */
969
970 // bitChunkSize() - Returns number of bits in a bitVect chunk
971 inline UINT FixedBitVect::bitChunkSize()
972 {
973     return sizeof(UINT) * 8;
974 }
975
976 // bitNumToBit() - Returns a bit mask of the given bit number
977 inline UINT FixedBitVect::bitNumToBit(UINT bitNum)
978 {
979     assert(bitNum < bitChunkSize());
980     assert(bitChunkSize() <= sizeof(int) * 8);
981
982     return 1 << bitNum;
983 }
984
985 // bitVectInit() - Initializes a bit vector of a given size
986 FixedBitVect* FixedBitVect::bitVectInit(UINT size, Compiler* comp)
987 {
988     UINT          bitVectMemSize, numberOfChunks;
989     FixedBitVect* bv;
990
991     assert(size != 0);
992
993     numberOfChunks = (size - 1) / bitChunkSize() + 1;
994     bitVectMemSize = numberOfChunks * (bitChunkSize() / 8); // size in bytes
995
996     assert(bitVectMemSize * bitChunkSize() >= size);
997
998     bv = (FixedBitVect*)comp->getAllocator(CMK_FixedBitVect).allocate<char>(sizeof(FixedBitVect) + bitVectMemSize);
999     memset(bv->bitVect, 0, bitVectMemSize);
1000
1001     bv->bitVectSize = size;
1002
1003     return bv;
1004 }
1005
1006 // bitVectSet() - Sets the given bit
1007 void FixedBitVect::bitVectSet(UINT bitNum)
1008 {
1009     UINT index;
1010
1011     assert(bitNum <= bitVectSize);
1012
1013     index = bitNum / bitChunkSize();
1014     bitNum -= index * bitChunkSize();
1015
1016     bitVect[index] |= bitNumToBit(bitNum);
1017 }
1018
1019 // bitVectTest() - Tests the given bit
1020 bool FixedBitVect::bitVectTest(UINT bitNum)
1021 {
1022     UINT index;
1023
1024     assert(bitNum <= bitVectSize);
1025
1026     index = bitNum / bitChunkSize();
1027     bitNum -= index * bitChunkSize();
1028
1029     return (bitVect[index] & bitNumToBit(bitNum)) != 0;
1030 }
1031
1032 // bitVectOr() - Or in the given bit vector
1033 void FixedBitVect::bitVectOr(FixedBitVect* bv)
1034 {
1035     UINT bitChunkCnt = (bitVectSize - 1) / bitChunkSize() + 1;
1036
1037     assert(bitVectSize == bv->bitVectSize);
1038
1039     // Or each chunks
1040     for (UINT i = 0; i < bitChunkCnt; i++)
1041     {
1042         bitVect[i] |= bv->bitVect[i];
1043     }
1044 }
1045
1046 // bitVectAnd() - And with passed in bit vector
1047 void FixedBitVect::bitVectAnd(FixedBitVect& bv)
1048 {
1049     UINT bitChunkCnt = (bitVectSize - 1) / bitChunkSize() + 1;
1050
1051     assert(bitVectSize == bv.bitVectSize);
1052
1053     // And each chunks
1054     for (UINT i = 0; i < bitChunkCnt; i++)
1055     {
1056         bitVect[i] &= bv.bitVect[i];
1057     }
1058 }
1059
1060 // bitVectGetFirst() - Find the first bit on and return bit num,
1061 //                    Return -1 if no bits found.
1062 UINT FixedBitVect::bitVectGetFirst()
1063 {
1064     return bitVectGetNext((UINT)-1);
1065 }
1066
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)
1070 {
1071     UINT bitNum = (UINT)-1;
1072     UINT index;
1073     UINT bitMask;
1074     UINT bitChunkCnt = (bitVectSize - 1) / bitChunkSize() + 1;
1075     UINT i;
1076
1077     if (bitNumPrev == (UINT)-1)
1078     {
1079         index   = 0;
1080         bitMask = (UINT)-1;
1081     }
1082     else
1083     {
1084         UINT bit;
1085
1086         index = bitNumPrev / bitChunkSize();
1087         bitNumPrev -= index * bitChunkSize();
1088         bit     = bitNumToBit(bitNumPrev);
1089         bitMask = ~(bit | (bit - 1));
1090     }
1091
1092     // Find first bit
1093     for (i = index; i < bitChunkCnt; i++)
1094     {
1095         UINT bitChunk = bitVect[i] & bitMask;
1096
1097         if (bitChunk != 0)
1098         {
1099             BitScanForward((ULONG*)&bitNum, bitChunk);
1100             break;
1101         }
1102
1103         bitMask = 0xFFFFFFFF;
1104     }
1105
1106     // Empty bit vector?
1107     if (bitNum == (UINT)-1)
1108     {
1109         return (UINT)-1;
1110     }
1111
1112     bitNum += i * bitChunkSize();
1113
1114     assert(bitNum <= bitVectSize);
1115
1116     return bitNum;
1117 }
1118
1119 // bitVectGetNextAndClear() - Find the first bit on, clear it and return it.
1120 //                            Return -1 if no bits found.
1121 UINT FixedBitVect::bitVectGetNextAndClear()
1122 {
1123     UINT bitNum      = (UINT)-1;
1124     UINT bitChunkCnt = (bitVectSize - 1) / bitChunkSize() + 1;
1125     UINT i;
1126
1127     // Find first bit
1128     for (i = 0; i < bitChunkCnt; i++)
1129     {
1130         if (bitVect[i] != 0)
1131         {
1132             BitScanForward((ULONG*)&bitNum, bitVect[i]);
1133             break;
1134         }
1135     }
1136
1137     // Empty bit vector?
1138     if (bitNum == (UINT)-1)
1139     {
1140         return (UINT)-1;
1141     }
1142
1143     // Clear the bit in the right chunk
1144     bitVect[i] &= ~bitNumToBit(bitNum);
1145
1146     bitNum += i * bitChunkSize();
1147
1148     assert(bitNum <= bitVectSize);
1149
1150     return bitNum;
1151 }
1152
1153 int SimpleSprintf_s(__in_ecount(cbBufSize - (pWriteStart - pBufStart)) char* pWriteStart,
1154                     __in_ecount(cbBufSize) char*                             pBufStart,
1155                     size_t                                                   cbBufSize,
1156                     __in_z const char*                                       fmt,
1157                     ...)
1158 {
1159     assert(fmt);
1160     assert(pBufStart);
1161     assert(pWriteStart);
1162     assert((size_t)pBufStart <= (size_t)pWriteStart);
1163     int ret;
1164
1165     // compute the space left in the buffer.
1166     if ((pBufStart + cbBufSize) < pWriteStart)
1167     {
1168         NO_WAY("pWriteStart is past end of buffer");
1169     }
1170     size_t  cbSpaceLeft = (size_t)((pBufStart + cbBufSize) - pWriteStart);
1171     va_list args;
1172     va_start(args, fmt);
1173     ret = vsprintf_s(pWriteStart, cbSpaceLeft, const_cast<char*>(fmt), args);
1174     va_end(args);
1175     if (ret < 0)
1176     {
1177         NO_WAY("vsprintf_s failed.");
1178     }
1179     return ret;
1180 }
1181
1182 #ifdef DEBUG
1183
1184 void hexDump(FILE* dmpf, const char* name, BYTE* addr, size_t size)
1185 {
1186     if (!size)
1187     {
1188         return;
1189     }
1190
1191     assert(addr);
1192
1193     fprintf(dmpf, "Hex dump of %s:\n", name);
1194
1195     for (unsigned i = 0; i < size; i++)
1196     {
1197         if ((i % 16) == 0)
1198         {
1199             fprintf(dmpf, "\n    %04X: ", i);
1200         }
1201
1202         fprintf(dmpf, "%02X ", *addr++);
1203     }
1204
1205     fprintf(dmpf, "\n\n");
1206 }
1207
1208 #endif // DEBUG
1209
1210 void HelperCallProperties::init()
1211 {
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
1215     {
1216         // Generally you want initialize these to their most typical/safest result
1217         //
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.
1225
1226         switch (helper)
1227         {
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:
1243
1244                 isPure  = true;
1245                 noThrow = true;
1246                 break;
1247
1248             // Arithmetic helpers that *can* throw.
1249
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:
1252
1253                 noThrow = true;
1254                 break;
1255
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
1258                                     // mod -1,
1259             case CORINFO_HELP_MOD:  // which is not representable as a positive integer.
1260             case CORINFO_HELP_UMOD:
1261             case CORINFO_HELP_ULMOD:
1262
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:
1267
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:
1274
1275                 isPure = true;
1276                 break;
1277
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:
1287
1288                 isAllocator   = true;
1289                 nonNullReturn = true;
1290                 noThrow       = true; // only can throw OutOfMemory
1291                 break;
1292
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:
1301
1302                 isAllocator   = true;
1303                 nonNullReturn = true;
1304                 break;
1305
1306             // Heap Allocation helpers that are also pure
1307             case CORINFO_HELP_STRCNS:
1308
1309                 isPure        = true;
1310                 isAllocator   = true;
1311                 nonNullReturn = true;
1312                 noThrow       = true; // only can throw OutOfMemory
1313                 break;
1314
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.
1318                 //
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
1321                 //
1322                 isAllocator = true;
1323                 noThrow     = true; // only can throw OutOfMemory
1324                 break;
1325
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
1332                 isPure        = true;
1333                 noThrow       = true;
1334                 nonNullReturn = true;
1335                 break;
1336
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:
1345
1346                 isPure  = true;
1347                 noThrow = true; // These return null for a failing cast
1348                 break;
1349
1350             case CORINFO_HELP_ARE_TYPES_EQUIVALENT:
1351             case CORINFO_HELP_GETCURRENTMANAGEDTHREADID:
1352                 isPure  = true;
1353                 noThrow = true;
1354                 break;
1355
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:
1363
1364                 // These throw for a failing cast
1365                 // But if given a null input arg will return null
1366                 isPure = true;
1367                 break;
1368
1369             // helpers returning addresses, these can also throw
1370             case CORINFO_HELP_UNBOX:
1371             case CORINFO_HELP_GETREFANY:
1372             case CORINFO_HELP_LDELEMA_REF:
1373
1374                 isPure = true;
1375                 break;
1376
1377             // helpers that return internal handle
1378             case CORINFO_HELP_GETCLASSFROMMETHODPARAM:
1379             case CORINFO_HELP_GETSYNCFROMCLASSHANDLE:
1380
1381                 isPure  = true;
1382                 noThrow = true;
1383                 break;
1384
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:
1405
1406                 // These may invoke static class constructors
1407                 // These can throw InvalidProgram exception if the class can not be constructed
1408                 //
1409                 isPure        = true;
1410                 nonNullReturn = true;
1411                 mayRunCctor   = true;
1412                 break;
1413
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:
1418
1419                 // These do not invoke static class constructors
1420                 //
1421                 isPure        = true;
1422                 noThrow       = true;
1423                 nonNullReturn = true;
1424                 break;
1425
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:
1433
1434                 mutatesHeap = true;
1435                 break;
1436
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:
1445
1446                 mutatesHeap = true;
1447                 break;
1448
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:
1466
1467                 alwaysThrow = true;
1468                 break;
1469
1470             // These helper calls may throw an exception
1471             case CORINFO_HELP_MON_EXIT_STATIC:
1472
1473                 break;
1474
1475             // This is a debugging aid; it simply returns a constant address.
1476             case CORINFO_HELP_LOOP_CLONE_CHOICE_ADDR:
1477                 isPure  = true;
1478                 noThrow = true;
1479                 break;
1480
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:
1493
1494                 noThrow = true;
1495                 break;
1496
1497             // Not sure how to handle optimization involving the rest of these  helpers
1498             default:
1499
1500                 // The most pessimistic results are returned for these helpers
1501                 mutatesHeap = true;
1502                 break;
1503         }
1504
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;
1512     }
1513 }
1514
1515 //=============================================================================
1516 // AssemblyNamesList2
1517 //=============================================================================
1518 // The string should be of the form
1519 // MyAssembly
1520 // MyAssembly;mscorlib;System
1521 //
1522 // You must use ';' as a separator; whitespace no longer works
1523
1524 AssemblyNamesList2::AssemblyNamesList2(const WCHAR* list, HostAllocator alloc) : m_alloc(alloc)
1525 {
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;
1529
1530     for (LPWSTR listWalk = const_cast<LPWSTR>(list); prevChar != '\0'; prevChar = *listWalk, listWalk++)
1531     {
1532         WCHAR curChar = *listWalk;
1533
1534         if (curChar == W(';') || curChar == W('\0'))
1535         {
1536             // Found separator or end of string
1537             if (nameStart)
1538             {
1539                 // Found the end of the current name; add a new assembly name to the list.
1540
1541                 AssemblyName* newName = new (m_alloc) AssemblyName();
1542
1543                 // Null out the current character so we can do zero-terminated string work; we'll restore it later.
1544                 *listWalk = W('\0');
1545
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)
1553                 {
1554                     *ppPrevLink = newName;
1555                     ppPrevLink  = &newName->m_next;
1556                 }
1557                 else
1558                 {
1559                     // Failed to convert the string. Ignore this string (and leak the memory).
1560                 }
1561
1562                 nameStart = nullptr;
1563
1564                 // Restore the current character.
1565                 *listWalk = curChar;
1566             }
1567         }
1568         else if (!nameStart)
1569         {
1570             //
1571             // Found the start of a new name
1572             //
1573
1574             nameStart = listWalk;
1575         }
1576     }
1577
1578     assert(nameStart == nullptr); // cannot be in the middle of a name
1579     *ppPrevLink = nullptr;        // Terminate the last element of the list.
1580 }
1581
1582 AssemblyNamesList2::~AssemblyNamesList2()
1583 {
1584     for (AssemblyName* pName = m_pNames; pName != nullptr; /**/)
1585     {
1586         AssemblyName* cur = pName;
1587         pName             = pName->m_next;
1588
1589         m_alloc.deallocate(cur->m_assemblyName);
1590         m_alloc.deallocate(cur);
1591     }
1592 }
1593
1594 bool AssemblyNamesList2::IsInList(const char* assemblyName)
1595 {
1596     for (AssemblyName* pName = m_pNames; pName != nullptr; pName = pName->m_next)
1597     {
1598         if (_stricmp(pName->m_assemblyName, assemblyName) == 0)
1599         {
1600             return true;
1601         }
1602     }
1603
1604     return false;
1605 }
1606
1607 //=============================================================================
1608 // MethodSet
1609 //=============================================================================
1610
1611 MethodSet::MethodSet(const WCHAR* filename, HostAllocator alloc) : m_pInfos(nullptr), m_alloc(alloc)
1612 {
1613     FILE* methodSetFile = _wfopen(filename, W("r"));
1614     if (methodSetFile == nullptr)
1615     {
1616         return;
1617     }
1618
1619     MethodInfo* lastInfo = m_pInfos;
1620     char        buffer[1024];
1621
1622     while (true)
1623     {
1624         // Get next line
1625         if (fgets(buffer, sizeof(buffer), methodSetFile) == nullptr)
1626         {
1627             break;
1628         }
1629
1630         // Ignore lines starting with leading ";" "#" "//".
1631         if ((0 == _strnicmp(buffer, ";", 1)) || (0 == _strnicmp(buffer, "#", 1)) || (0 == _strnicmp(buffer, "//", 2)))
1632         {
1633             continue;
1634         }
1635
1636         // Remove trailing newline, if any.
1637         char* p = strpbrk(buffer, "\r\n");
1638         if (p != nullptr)
1639         {
1640             *p = '\0';
1641         }
1642
1643         char*    methodName;
1644         unsigned methodHash = 0;
1645
1646         // Parse the line. Very simple. One of:
1647         //
1648         //    <method-name>
1649         //    <method-name><whitespace>(MethodHash=<hash>)
1650
1651         const char methodHashPattern[] = " (MethodHash=";
1652         p                              = strstr(buffer, methodHashPattern);
1653         if (p == nullptr)
1654         {
1655             // Just use it without the hash.
1656             methodName = _strdup(buffer);
1657         }
1658         else
1659         {
1660             // There's a method hash; use that.
1661
1662             // First, get the method name.
1663             char* p2 = p;
1664             *p       = '\0';
1665
1666             // Null terminate method at first whitespace. (Don't have any leading whitespace!)
1667             p = strpbrk(buffer, " \t");
1668             if (p != nullptr)
1669             {
1670                 *p = '\0';
1671             }
1672             methodName = _strdup(buffer);
1673
1674             // Now get the method hash.
1675             p2 += strlen(methodHashPattern);
1676             char* p3 = strchr(p2, ')');
1677             if (p3 == nullptr)
1678             {
1679                 // Malformed line: no trailing slash.
1680                 JITDUMP("Couldn't parse: %s\n", p2);
1681                 // We can still just use the method name.
1682             }
1683             else
1684             {
1685                 // Convert the slash to null.
1686                 *p3 = '\0';
1687
1688                 // Now parse it as hex.
1689                 int count = sscanf_s(p2, "%x", &methodHash);
1690                 if (count != 1)
1691                 {
1692                     JITDUMP("Couldn't parse: %s\n", p2);
1693                     // Still, use the method name.
1694                 }
1695             }
1696         }
1697
1698         MethodInfo* newInfo = new (m_alloc) MethodInfo(methodName, methodHash);
1699         if (m_pInfos == nullptr)
1700         {
1701             m_pInfos = lastInfo = newInfo;
1702         }
1703         else
1704         {
1705             lastInfo->m_next = newInfo;
1706             lastInfo         = newInfo;
1707         }
1708     }
1709
1710     if (m_pInfos == nullptr)
1711     {
1712         JITDUMP("No methods read from %ws\n", filename);
1713     }
1714     else
1715     {
1716         JITDUMP("Methods read from %ws:\n", filename);
1717
1718         int methodCount = 0;
1719         for (MethodInfo* pInfo = m_pInfos; pInfo != nullptr; pInfo = pInfo->m_next)
1720         {
1721             JITDUMP("  %s (MethodHash: %x)\n", pInfo->m_MethodName, pInfo->m_MethodHash);
1722             ++methodCount;
1723         }
1724
1725         if (methodCount > 100)
1726         {
1727             JITDUMP("Warning: high method count (%d) for MethodSet with linear search lookups might be slow\n",
1728                     methodCount);
1729         }
1730     }
1731 }
1732
1733 MethodSet::~MethodSet()
1734 {
1735     for (MethodInfo* pInfo = m_pInfos; pInfo != nullptr; /**/)
1736     {
1737         MethodInfo* cur = pInfo;
1738         pInfo           = pInfo->m_next;
1739
1740         m_alloc.deallocate(cur->m_MethodName);
1741         m_alloc.deallocate(cur);
1742     }
1743 }
1744
1745 // TODO: make this more like JitConfigValues::MethodSet::contains()?
1746 bool MethodSet::IsInSet(const char* methodName)
1747 {
1748     for (MethodInfo* pInfo = m_pInfos; pInfo != nullptr; pInfo = pInfo->m_next)
1749     {
1750         if (_stricmp(pInfo->m_MethodName, methodName) == 0)
1751         {
1752             return true;
1753         }
1754     }
1755
1756     return false;
1757 }
1758
1759 bool MethodSet::IsInSet(int methodHash)
1760 {
1761     for (MethodInfo* pInfo = m_pInfos; pInfo != nullptr; pInfo = pInfo->m_next)
1762     {
1763         if (pInfo->m_MethodHash == methodHash)
1764         {
1765             return true;
1766         }
1767     }
1768
1769     return false;
1770 }
1771
1772 bool MethodSet::IsActiveMethod(const char* methodName, int methodHash)
1773 {
1774     if (methodHash != 0)
1775     {
1776         // Use the method hash.
1777         if (IsInSet(methodHash))
1778         {
1779             JITDUMP("Method active in MethodSet (hash match): %s Hash: %x\n", methodName, methodHash);
1780             return true;
1781         }
1782     }
1783
1784     // Else, fall back and use the method name.
1785     assert(methodName != nullptr);
1786     if (IsInSet(methodName))
1787     {
1788         JITDUMP("Method active in MethodSet (name match): %s Hash: %x\n", methodName, methodHash);
1789         return true;
1790     }
1791
1792     return false;
1793 }
1794
1795 #ifdef FEATURE_JIT_METHOD_PERF
1796 CycleCount::CycleCount() : cps(CycleTimer::CyclesPerSecond())
1797 {
1798 }
1799
1800 bool CycleCount::GetCycles(unsigned __int64* time)
1801 {
1802     return CycleTimer::GetThreadCyclesS(time);
1803 }
1804
1805 bool CycleCount::Start()
1806 {
1807     return GetCycles(&beginCycles);
1808 }
1809
1810 double CycleCount::ElapsedTime()
1811 {
1812     unsigned __int64 nowCycles;
1813     (void)GetCycles(&nowCycles);
1814     return ((double)(nowCycles - beginCycles) / cps) * 1000.0;
1815 }
1816
1817 bool PerfCounter::Start()
1818 {
1819     bool result = QueryPerformanceFrequency(&beg) != 0;
1820     if (!result)
1821     {
1822         return result;
1823     }
1824     freq = (double)beg.QuadPart / 1000.0;
1825     (void)QueryPerformanceCounter(&beg);
1826     return result;
1827 }
1828
1829 // Return elapsed time from Start() in millis.
1830 double PerfCounter::ElapsedTime()
1831 {
1832     LARGE_INTEGER li;
1833     (void)QueryPerformanceCounter(&li);
1834     return (double)(li.QuadPart - beg.QuadPart) / freq;
1835 }
1836
1837 #endif
1838
1839 #ifdef DEBUG
1840
1841 /*****************************************************************************
1842  * Return the number of digits in a number of the given base (default base 10).
1843  * Used when outputting strings.
1844  */
1845 unsigned CountDigits(unsigned num, unsigned base /* = 10 */)
1846 {
1847     assert(2 <= base && base <= 16); // sanity check
1848     unsigned count = 1;
1849     while (num >= base)
1850     {
1851         num /= base;
1852         ++count;
1853     }
1854     return count;
1855 }
1856
1857 unsigned CountDigits(float num, unsigned base /* = 10 */)
1858 {
1859     assert(2 <= base && base <= 16); // sanity check
1860     unsigned count = 1;
1861     while (num >= base)
1862     {
1863         num /= base;
1864         ++count;
1865     }
1866     return count;
1867 }
1868
1869 #endif // DEBUG
1870
1871 double FloatingPointUtils::convertUInt64ToDouble(unsigned __int64 uIntVal)
1872 {
1873     __int64 s64 = uIntVal;
1874     double  d;
1875     if (s64 < 0)
1876     {
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.
1887
1888         // d = (double)(int64_t)uint64 + 0x1p64
1889         uint64_t adjHex = 0x43F0000000000000UL;
1890         d               = (double)s64 + *(double*)&adjHex;
1891 #else
1892         d                             = (double)uIntVal;
1893 #endif
1894     }
1895     else
1896     {
1897         d = (double)uIntVal;
1898     }
1899     return d;
1900 }
1901
1902 float FloatingPointUtils::convertUInt64ToFloat(unsigned __int64 u64)
1903 {
1904     double d = convertUInt64ToDouble(u64);
1905     return (float)d;
1906 }
1907
1908 unsigned __int64 FloatingPointUtils::convertDoubleToUInt64(double d)
1909 {
1910     unsigned __int64 u64;
1911     if (d >= 0.0)
1912     {
1913         // Work around a C++ issue where it doesn't properly convert large positive doubles
1914         const double two63 = 2147483648.0 * 4294967296.0;
1915         if (d < two63)
1916         {
1917             u64 = UINT64(d);
1918         }
1919         else
1920         {
1921             // subtract 0x8000000000000000, do the convert then add it back again
1922             u64 = INT64(d - two63) + I64(0x8000000000000000);
1923         }
1924         return u64;
1925     }
1926
1927 #ifdef TARGET_XARCH
1928
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.
1937
1938     u64 = UINT64(INT64(d));
1939 #else
1940     u64                               = UINT64(d);
1941 #endif // TARGET_XARCH
1942
1943     return u64;
1944 }
1945
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)
1949 {
1950     // ************************************************************************************
1951     // IMPORTANT: Do not change this implementation without also updating Math.Round(double),
1952     //            MathF.Round(float), and FloatingPointUtils::round(float)
1953     // ************************************************************************************
1954
1955     // This is based on the 'Berkeley SoftFloat Release 3e' algorithm
1956
1957     uint64_t bits     = *reinterpret_cast<uint64_t*>(&x);
1958     int32_t  exponent = (int32_t)(bits >> 52) & 0x07FF;
1959
1960     if (exponent <= 0x03FE)
1961     {
1962         if ((bits << 1) == 0)
1963         {
1964             // Exactly +/- zero should return the original value
1965             return x;
1966         }
1967
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.
1971
1972         double result = ((exponent == 0x03FE) && ((bits & UI64(0x000FFFFFFFFFFFFF)) != 0)) ? 1.0 : 0.0;
1973         return _copysign(result, x);
1974     }
1975
1976     if (exponent >= 0x0433)
1977     {
1978         // Any value greater than or equal to 2^52 cannot have a fractional part,
1979         // So it will always round to exactly itself.
1980
1981         return x;
1982     }
1983
1984     // The absolute value should be greater than or equal to 1.0 and less than 2^52
1985     assert((0x03FF <= exponent) && (exponent <= 0x0432));
1986
1987     // Determine the last bit that represents the integral portion of the value
1988     // and the bits representing the fractional portion
1989
1990     uint64_t lastBitMask   = UI64(1) << (0x0433 - exponent);
1991     uint64_t roundBitsMask = lastBitMask - 1;
1992
1993     // Increment the first fractional bit, which represents the midpoint between
1994     // two integral values in the current window.
1995
1996     bits += lastBitMask >> 1;
1997
1998     if ((bits & roundBitsMask) == 0)
1999     {
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
2002
2003         bits &= ~lastBitMask;
2004     }
2005     else
2006     {
2007         // Otherwise, we just want to strip the fractional bits off, truncating
2008         // to the current integer value.
2009
2010         bits &= ~roundBitsMask;
2011     }
2012
2013     return *reinterpret_cast<double*>(&bits);
2014 }
2015
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)
2021
2022 #if !defined(_copysignf)
2023 #define _copysignf (float)_copysign
2024 #endif
2025
2026 #endif
2027
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)
2031 {
2032     // ************************************************************************************
2033     // IMPORTANT: Do not change this implementation without also updating MathF.Round(float),
2034     //            Math.Round(double), and FloatingPointUtils::round(double)
2035     // ************************************************************************************
2036
2037     // This is based on the 'Berkeley SoftFloat Release 3e' algorithm
2038
2039     uint32_t bits     = *reinterpret_cast<uint32_t*>(&x);
2040     int32_t  exponent = (int32_t)(bits >> 23) & 0xFF;
2041
2042     if (exponent <= 0x7E)
2043     {
2044         if ((bits << 1) == 0)
2045         {
2046             // Exactly +/- zero should return the original value
2047             return x;
2048         }
2049
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.
2053
2054         float result = ((exponent == 0x7E) && ((bits & 0x007FFFFF) != 0)) ? 1.0f : 0.0f;
2055         return _copysignf(result, x);
2056     }
2057
2058     if (exponent >= 0x96)
2059     {
2060         // Any value greater than or equal to 2^52 cannot have a fractional part,
2061         // So it will always round to exactly itself.
2062
2063         return x;
2064     }
2065
2066     // The absolute value should be greater than or equal to 1.0 and less than 2^52
2067     assert((0x7F <= exponent) && (exponent <= 0x95));
2068
2069     // Determine the last bit that represents the integral portion of the value
2070     // and the bits representing the fractional portion
2071
2072     uint32_t lastBitMask   = 1U << (0x96 - exponent);
2073     uint32_t roundBitsMask = lastBitMask - 1;
2074
2075     // Increment the first fractional bit, which represents the midpoint between
2076     // two integral values in the current window.
2077
2078     bits += lastBitMask >> 1;
2079
2080     if ((bits & roundBitsMask) == 0)
2081     {
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
2084
2085         bits &= ~lastBitMask;
2086     }
2087     else
2088     {
2089         // Otherwise, we just want to strip the fractional bits off, truncating
2090         // to the current integer value.
2091
2092         bits &= ~roundBitsMask;
2093     }
2094
2095     return *reinterpret_cast<float*>(&bits);
2096 }
2097
2098 bool FloatingPointUtils::isNormal(double x)
2099 {
2100     int64_t bits = reinterpret_cast<int64_t&>(x);
2101     bits &= 0x7FFFFFFFFFFFFFFF;
2102     return (bits < 0x7FF0000000000000) && (bits != 0) && ((bits & 0x7FF0000000000000) != 0);
2103 }
2104
2105 bool FloatingPointUtils::isNormal(float x)
2106 {
2107     int32_t bits = reinterpret_cast<int32_t&>(x);
2108     bits &= 0x7FFFFFFF;
2109     return (bits < 0x7F800000) && (bits != 0) && ((bits & 0x7F800000) != 0);
2110 }
2111
2112 //------------------------------------------------------------------------
2113 // infinite_float: return an infinite float value
2114 //
2115 // Returns:
2116 //    Infinite float value.
2117 //
2118 // Notes:
2119 //    This is the predefined constant HUGE_VALF on many platforms.
2120 //
2121 float FloatingPointUtils::infinite_float()
2122 {
2123     int32_t bits = 0x7F800000;
2124     return *reinterpret_cast<float*>(&bits);
2125 }
2126
2127 //------------------------------------------------------------------------
2128 // hasPreciseReciprocal: check double for precise reciprocal. E.g. 2.0 <--> 0.5
2129 //
2130 // Arguments:
2131 //    x - value to check for precise reciprocal
2132 //
2133 // Return Value:
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)
2136 //
2137
2138 bool FloatingPointUtils::hasPreciseReciprocal(double x)
2139 {
2140     if (!isNormal(x))
2141     {
2142         return false;
2143     }
2144
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;
2149 }
2150
2151 //------------------------------------------------------------------------
2152 // hasPreciseReciprocal: check float for precise reciprocal. E.g. 2.0f <--> 0.5f
2153 //
2154 // Arguments:
2155 //    x - value to check for precise reciprocal
2156 //
2157 // Return Value:
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)
2160 //
2161
2162 bool FloatingPointUtils::hasPreciseReciprocal(float x)
2163 {
2164     if (!isNormal(x))
2165     {
2166         return false;
2167     }
2168
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;
2173 }
2174
2175 namespace MagicDivide
2176 {
2177 template <int TableBase = 0, int TableSize, typename Magic>
2178 static const Magic* TryGetMagic(const Magic (&table)[TableSize], typename Magic::DivisorType index)
2179 {
2180     if ((index < TableBase) || (TableBase + TableSize <= index))
2181     {
2182         return nullptr;
2183     }
2184
2185     const Magic* p = &table[index - TableBase];
2186
2187     if (p->magic == 0)
2188     {
2189         return nullptr;
2190     }
2191
2192     return p;
2193 };
2194
2195 template <typename T>
2196 struct UnsignedMagic
2197 {
2198     typedef T DivisorType;
2199
2200     T    magic;
2201     bool add;
2202     int  shift;
2203 };
2204
2205 template <typename T>
2206 const UnsignedMagic<T>* TryGetUnsignedMagic(T divisor)
2207 {
2208     return nullptr;
2209 }
2210
2211 template <>
2212 const UnsignedMagic<uint32_t>* TryGetUnsignedMagic(uint32_t divisor)
2213 {
2214     static const UnsignedMagic<uint32_t> table[]{
2215         {0xaaaaaaab, false, 1}, // 3
2216         {},
2217         {0xcccccccd, false, 2}, // 5
2218         {0xaaaaaaab, false, 2}, // 6
2219         {0x24924925, true, 3},  // 7
2220         {},
2221         {0x38e38e39, false, 1}, // 9
2222         {0xcccccccd, false, 3}, // 10
2223         {0xba2e8ba3, false, 3}, // 11
2224         {0xaaaaaaab, false, 3}, // 12
2225     };
2226
2227     return TryGetMagic<3>(table, divisor);
2228 }
2229
2230 template <>
2231 const UnsignedMagic<uint64_t>* TryGetUnsignedMagic(uint64_t divisor)
2232 {
2233     static const UnsignedMagic<uint64_t> table[]{
2234         {0xaaaaaaaaaaaaaaab, false, 1}, // 3
2235         {},
2236         {0xcccccccccccccccd, false, 2}, // 5
2237         {0xaaaaaaaaaaaaaaab, false, 2}, // 6
2238         {0x2492492492492493, true, 3},  // 7
2239         {},
2240         {0xe38e38e38e38e38f, false, 3}, // 9
2241         {0xcccccccccccccccd, false, 3}, // 10
2242         {0x2e8ba2e8ba2e8ba3, false, 1}, // 11
2243         {0xaaaaaaaaaaaaaaab, false, 3}, // 12
2244     };
2245
2246     return TryGetMagic<3>(table, divisor);
2247 }
2248
2249 //------------------------------------------------------------------------
2250 // GetUnsignedMagic: Generates a magic number and shift amount for the magic
2251 // number unsigned division optimization.
2252 //
2253 // Arguments:
2254 //    d     - The divisor
2255 //    add   - Pointer to a flag indicating the kind of code to generate
2256 //    shift - Pointer to the shift value to be returned
2257 //
2258 // Returns:
2259 //    The magic number.
2260 //
2261 // Notes:
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
2265
2266 template <typename T>
2267 T GetUnsignedMagic(T d, bool* add /*out*/, int* shift /*out*/)
2268 {
2269     assert((d >= 3) && !isPow2(d));
2270
2271     const UnsignedMagic<T>* magic = TryGetUnsignedMagic(d);
2272
2273     if (magic != nullptr)
2274     {
2275         *shift = magic->shift;
2276         *add   = magic->add;
2277         return magic->magic;
2278     }
2279
2280     typedef typename std::make_signed<T>::type ST;
2281
2282     const unsigned bits       = sizeof(T) * 8;
2283     const unsigned bitsMinus1 = bits - 1;
2284     const T        twoNMinus1 = T(1) << bitsMinus1;
2285
2286     *add        = false;
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);
2293     T        delta;
2294
2295     do
2296     {
2297         p++;
2298
2299         if (r1 >= (nc - r1))
2300         {
2301             q1 = 2 * q1 + 1;
2302             r1 = 2 * r1 - nc;
2303         }
2304         else
2305         {
2306             q1 = 2 * q1;
2307             r1 = 2 * r1;
2308         }
2309
2310         if ((r2 + 1) >= (d - r2))
2311         {
2312             if (q2 >= (twoNMinus1 - 1))
2313             {
2314                 *add = true;
2315             }
2316
2317             q2 = 2 * q2 + 1;
2318             r2 = 2 * r2 + 1 - d;
2319         }
2320         else
2321         {
2322             if (q2 >= twoNMinus1)
2323             {
2324                 *add = true;
2325             }
2326
2327             q2 = 2 * q2;
2328             r2 = 2 * r2 + 1;
2329         }
2330
2331         delta = d - 1 - r2;
2332
2333     } while ((p < (bits * 2)) && ((q1 < delta) || ((q1 == delta) && (r1 == 0))));
2334
2335     *shift = p - bits; // resulting shift
2336     return q2 + 1;     // resulting magic number
2337 }
2338
2339 uint32_t GetUnsigned32Magic(uint32_t d, bool* add /*out*/, int* shift /*out*/)
2340 {
2341     return GetUnsignedMagic<uint32_t>(d, add, shift);
2342 }
2343
2344 #ifdef TARGET_64BIT
2345 uint64_t GetUnsigned64Magic(uint64_t d, bool* add /*out*/, int* shift /*out*/)
2346 {
2347     return GetUnsignedMagic<uint64_t>(d, add, shift);
2348 }
2349 #endif
2350
2351 template <typename T>
2352 struct SignedMagic
2353 {
2354     typedef T DivisorType;
2355
2356     T   magic;
2357     int shift;
2358 };
2359
2360 template <typename T>
2361 const SignedMagic<T>* TryGetSignedMagic(T divisor)
2362 {
2363     return nullptr;
2364 }
2365
2366 template <>
2367 const SignedMagic<int32_t>* TryGetSignedMagic(int32_t divisor)
2368 {
2369     static const SignedMagic<int32_t> table[]{
2370         {0x55555556, 0}, // 3
2371         {},
2372         {0x66666667, 1},          // 5
2373         {0x2aaaaaab, 0},          // 6
2374         {(int32_t)0x92492493, 2}, // 7
2375         {},
2376         {0x38e38e39, 1}, // 9
2377         {0x66666667, 2}, // 10
2378         {0x2e8ba2e9, 1}, // 11
2379         {0x2aaaaaab, 1}, // 12
2380     };
2381
2382     return TryGetMagic<3>(table, divisor);
2383 }
2384
2385 template <>
2386 const SignedMagic<int64_t>* TryGetSignedMagic(int64_t divisor)
2387 {
2388     static const SignedMagic<int64_t> table[]{
2389         {0x5555555555555556, 0}, // 3
2390         {},
2391         {0x6666666666666667, 1}, // 5
2392         {0x2aaaaaaaaaaaaaab, 0}, // 6
2393         {0x4924924924924925, 1}, // 7
2394         {},
2395         {0x1c71c71c71c71c72, 0}, // 9
2396         {0x6666666666666667, 2}, // 10
2397         {0x2e8ba2e8ba2e8ba3, 1}, // 11
2398         {0x2aaaaaaaaaaaaaab, 1}, // 12
2399     };
2400
2401     return TryGetMagic<3>(table, divisor);
2402 }
2403
2404 //------------------------------------------------------------------------
2405 // GetSignedMagic: Generates a magic number and shift amount for
2406 // the magic number division optimization.
2407 //
2408 // Arguments:
2409 //    denom - The denominator
2410 //    shift - Pointer to the shift value to be returned
2411 //
2412 // Returns:
2413 //    The magic number.
2414 //
2415 // Notes:
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
2420
2421 template <typename T>
2422 T GetSignedMagic(T denom, int* shift /*out*/)
2423 {
2424     const SignedMagic<T>* magic = TryGetSignedMagic(denom);
2425
2426     if (magic != nullptr)
2427     {
2428         *shift = magic->shift;
2429         return magic->magic;
2430     }
2431
2432     const int bits         = sizeof(T) * 8;
2433     const int bits_minus_1 = bits - 1;
2434
2435     typedef typename std::make_unsigned<T>::type UT;
2436
2437     const UT two_nminus1 = UT(1) << bits_minus_1;
2438
2439     int p;
2440     UT  absDenom;
2441     UT  absNc;
2442     UT  delta;
2443     UT  q1;
2444     UT  r1;
2445     UT  r2;
2446     UT  q2;
2447     UT  t;
2448     T   result_magic;
2449
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))
2458
2459     do
2460     {
2461         p++;
2462         q1 *= 2; // update q1 = 2^p / abs(nc)
2463         r1 *= 2; // update r1 = rem(2^p / abs(nc))
2464
2465         if (r1 >= absNc)
2466         { // must be unsigned comparison
2467             q1++;
2468             r1 -= absNc;
2469         }
2470
2471         q2 *= 2; // update q2 = 2^p / abs(denom)
2472         r2 *= 2; // update r2 = rem(2^p / abs(denom))
2473
2474         if (r2 >= absDenom)
2475         { // must be unsigned comparison
2476             q2++;
2477             r2 -= absDenom;
2478         }
2479
2480         delta = absDenom - r2;
2481     } while (q1 < delta || (q1 == delta && r1 == 0));
2482
2483     result_magic = q2 + 1; // resulting magic number
2484     if (denom < 0)
2485     {
2486         result_magic = -result_magic;
2487     }
2488     *shift = p - bits; // resulting shift
2489
2490     return result_magic;
2491 }
2492
2493 int32_t GetSigned32Magic(int32_t d, int* shift /*out*/)
2494 {
2495     return GetSignedMagic<int32_t>(d, shift);
2496 }
2497
2498 #ifdef TARGET_64BIT
2499 int64_t GetSigned64Magic(int64_t d, int* shift /*out*/)
2500 {
2501     return GetSignedMagic<int64_t>(d, shift);
2502 }
2503 #endif
2504 }