Fix reading Time zone rules using Julian days (#17672)
[platform/upstream/coreclr.git] / src / jit / utils.h
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 XX                                                                           XX
8 XX                                  Utils.h                                  XX
9 XX                                                                           XX
10 XX   Has miscellaneous utility functions                                     XX
11 XX                                                                           XX
12 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
13 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
14 */
15
16 #ifndef _UTILS_H_
17 #define _UTILS_H_
18
19 #include "iallocator.h"
20 #include "hostallocator.h"
21 #include "cycletimer.h"
22
23 // Needed for unreached()
24 #include "error.h"
25
26 #ifdef _TARGET_64BIT_
27 #define BitScanForwardPtr BitScanForward64
28 #else
29 #define BitScanForwardPtr BitScanForward
30 #endif
31
32 template <typename T, int size>
33 unsigned ArrLen(T (&)[size])
34 {
35     return size;
36 }
37
38 // return true if arg is a power of 2
39 template <typename T>
40 inline bool isPow2(T i)
41 {
42     return (i > 0 && ((i - 1) & i) == 0);
43 }
44
45 // Adapter for iterators to a type that is compatible with C++11
46 // range-based for loops.
47 template <typename TIterator>
48 class IteratorPair
49 {
50     TIterator m_begin;
51     TIterator m_end;
52
53 public:
54     IteratorPair(TIterator begin, TIterator end) : m_begin(begin), m_end(end)
55     {
56     }
57
58     inline TIterator begin()
59     {
60         return m_begin;
61     }
62
63     inline TIterator end()
64     {
65         return m_end;
66     }
67 };
68
69 template <typename TIterator>
70 inline IteratorPair<TIterator> MakeIteratorPair(TIterator begin, TIterator end)
71 {
72     return IteratorPair<TIterator>(begin, end);
73 }
74
75 // Recursive template definition to calculate the base-2 logarithm
76 // of a constant value.
77 template <unsigned val, unsigned acc = 0>
78 struct ConstLog2
79 {
80     enum
81     {
82         value = ConstLog2<val / 2, acc + 1>::value
83     };
84 };
85
86 template <unsigned acc>
87 struct ConstLog2<0, acc>
88 {
89     enum
90     {
91         value = acc
92     };
93 };
94
95 template <unsigned acc>
96 struct ConstLog2<1, acc>
97 {
98     enum
99     {
100         value = acc
101     };
102 };
103
104 inline const char* dspBool(bool b)
105 {
106     return (b) ? "true" : "false";
107 }
108
109 #ifdef FEATURE_CORECLR
110 #ifdef _CRT_ABS_DEFINED
111 // we don't have the full standard library
112 inline int64_t abs(int64_t t)
113 {
114     return t > 0 ? t : -t;
115 }
116 #endif
117 #endif // FEATURE_CORECLR
118
119 template <typename T>
120 int signum(T val)
121 {
122     if (val < T(0))
123     {
124         return -1;
125     }
126     else if (val > T(0))
127     {
128         return 1;
129     }
130     else
131     {
132         return 0;
133     }
134 }
135
136 #if defined(DEBUG) || defined(INLINE_DATA)
137
138 // ConfigMethodRange describes a set of methods, specified via their
139 // hash codes. This can be used for binary search and/or specifying an
140 // explicit method set.
141 //
142 // Note method hash codes are not necessarily unique. For instance
143 // many IL stubs may have the same hash.
144 //
145 // If range string is null or just whitespace, range includes all
146 // methods.
147 //
148 // Parses values as decimal numbers.
149 //
150 // Examples:
151 //
152 //  [string with just spaces] : all methods
153 //                   12345678 : a single method
154 //          12345678-23456789 : a range of methods
155 // 99998888 12345678-23456789 : a range of methods plus a single method
156
157 class ConfigMethodRange
158 {
159
160 public:
161     // Default capacity
162     enum
163     {
164         DEFAULT_CAPACITY = 50
165     };
166
167     // Does the range include this method's hash?
168     bool Contains(class ICorJitInfo* info, CORINFO_METHOD_HANDLE method);
169
170     // Ensure the range string has been parsed.
171     void EnsureInit(const wchar_t* rangeStr, unsigned capacity = DEFAULT_CAPACITY)
172     {
173         // Make sure that the memory was zero initialized
174         assert(m_inited == 0 || m_inited == 1);
175
176         if (!m_inited)
177         {
178             InitRanges(rangeStr, capacity);
179             assert(m_inited == 1);
180         }
181     }
182
183     // Error checks
184     bool Error() const
185     {
186         return m_badChar != 0;
187     }
188     size_t BadCharIndex() const
189     {
190         return m_badChar - 1;
191     }
192
193 private:
194     struct Range
195     {
196         unsigned m_low;
197         unsigned m_high;
198     };
199
200     void InitRanges(const wchar_t* rangeStr, unsigned capacity);
201
202     unsigned m_entries;   // number of entries in the range array
203     unsigned m_lastRange; // count of low-high pairs
204     unsigned m_inited;    // 1 if range string has been parsed
205     size_t   m_badChar;   // index + 1 of any bad character in range string
206     Range*   m_ranges;    // ranges of functions to include
207 };
208
209 #endif // defined(DEBUG) || defined(INLINE_DATA)
210
211 class Compiler;
212
213 /*****************************************************************************
214  * Fixed bit vector class
215  */
216 class FixedBitVect
217 {
218 private:
219     UINT bitVectSize;
220     UINT bitVect[];
221
222     // bitChunkSize() - Returns number of bits in a bitVect chunk
223     static UINT bitChunkSize();
224
225     // bitNumToBit() - Returns a bit mask of the given bit number
226     static UINT bitNumToBit(UINT bitNum);
227
228 public:
229     // bitVectInit() - Initializes a bit vector of a given size
230     static FixedBitVect* bitVectInit(UINT size, Compiler* comp);
231
232     // bitVectSet() - Sets the given bit
233     void bitVectSet(UINT bitNum);
234
235     // bitVectTest() - Tests the given bit
236     bool bitVectTest(UINT bitNum);
237
238     // bitVectOr() - Or in the given bit vector
239     void bitVectOr(FixedBitVect* bv);
240
241     // bitVectAnd() - And with passed in bit vector
242     void bitVectAnd(FixedBitVect& bv);
243
244     // bitVectGetFirst() - Find the first bit on and return the bit num.
245     //                    Return -1 if no bits found.
246     UINT bitVectGetFirst();
247
248     // bitVectGetNext() - Find the next bit on given previous bit and return bit num.
249     //                    Return -1 if no bits found.
250     UINT bitVectGetNext(UINT bitNumPrev);
251
252     // bitVectGetNextAndClear() - Find the first bit on, clear it and return it.
253     //                            Return -1 if no bits found.
254     UINT bitVectGetNextAndClear();
255 };
256
257 /******************************************************************************
258  * A specialized version of sprintf_s to simplify conversion to SecureCRT
259  *
260  * pWriteStart -> A pointer to the first byte to which data is written.
261  * pBufStart -> the start of the buffer into which the data is written.  If
262  *              composing a complex string with multiple calls to sprintf, this
263  *              should not change.
264  * cbBufSize -> The size of the overall buffer (i.e. the size of the buffer
265  *              pointed to by pBufStart).  For subsequent calls, this does not
266  *              change.
267  * fmt -> The format string
268  * ... -> Arguments.
269  *
270  * returns -> number of bytes successfully written, not including the null
271  *            terminator.  Calls NO_WAY on error.
272  */
273 int SimpleSprintf_s(__in_ecount(cbBufSize - (pWriteStart - pBufStart)) char* pWriteStart,
274                     __in_ecount(cbBufSize) char*                             pBufStart,
275                     size_t                                                   cbBufSize,
276                     __in_z const char*                                       fmt,
277                     ...);
278
279 #ifdef DEBUG
280 void hexDump(FILE* dmpf, const char* name, BYTE* addr, size_t size);
281 #endif // DEBUG
282
283 /******************************************************************************
284  * ScopedSetVariable: A simple class to set and restore a variable within a scope.
285  * For example, it can be used to set a 'bool' flag to 'true' at the beginning of a
286  * function and automatically back to 'false' either at the end the function, or at
287  * any other return location. The variable should not be changed during the scope:
288  * the destructor asserts that the value at destruction time is the same one we set.
289  * Usage: ScopedSetVariable<bool> _unused_name(&variable, true);
290  */
291 template <typename T>
292 class ScopedSetVariable
293 {
294 public:
295     ScopedSetVariable(T* pVariable, T value) : m_pVariable(pVariable)
296     {
297         m_oldValue   = *m_pVariable;
298         *m_pVariable = value;
299         INDEBUG(m_value = value;)
300     }
301
302     ~ScopedSetVariable()
303     {
304         assert(*m_pVariable == m_value); // Assert that the value didn't change between ctor and dtor
305         *m_pVariable = m_oldValue;
306     }
307
308 private:
309 #ifdef DEBUG
310     T m_value;      // The value we set the variable to (used for assert).
311 #endif              // DEBUG
312     T  m_oldValue;  // The old value, to restore the variable to.
313     T* m_pVariable; // Address of the variable to change
314 };
315
316 /******************************************************************************
317  * PhasedVar: A class to represent a variable that has phases, in particular,
318  * a write phase where the variable is computed, and a read phase where the
319  * variable is used. Once the variable has been read, it can no longer be changed.
320  * Reading the variable essentially commits everyone to using that value forever,
321  * and it is assumed that subsequent changes to the variable would invalidate
322  * whatever assumptions were made by the previous readers, leading to bad generated code.
323  * These assumptions are asserted in DEBUG builds.
324  * The phase ordering is clean for AMD64, but not for x86/ARM. So don't do the phase
325  * ordering asserts for those platforms.
326  */
327 template <typename T>
328 class PhasedVar
329 {
330 public:
331     PhasedVar()
332 #ifdef DEBUG
333         : m_initialized(false), m_writePhase(true)
334 #endif // DEBUG
335     {
336     }
337
338     PhasedVar(T value)
339         : m_value(value)
340 #ifdef DEBUG
341         , m_initialized(true)
342         , m_writePhase(true)
343 #endif // DEBUG
344     {
345     }
346
347     ~PhasedVar()
348     {
349 #ifdef DEBUG
350         m_initialized = false;
351         m_writePhase  = true;
352 #endif // DEBUG
353     }
354
355     // Read the value. Change to the read phase.
356     // Marked 'const' because we don't change the encapsulated value, even though
357     // we do change the write phase, which is only for debugging asserts.
358
359     operator T() const
360     {
361 #ifdef DEBUG
362         assert(m_initialized);
363         (const_cast<PhasedVar*>(this))->m_writePhase = false;
364 #endif // DEBUG
365         return m_value;
366     }
367
368     // Mark the value as read only; explicitly change the variable to the "read" phase.
369     void MarkAsReadOnly() const
370     {
371 #ifdef DEBUG
372         assert(m_initialized);
373         (const_cast<PhasedVar*>(this))->m_writePhase = false;
374 #endif // DEBUG
375     }
376
377     // Functions/operators to write the value. Must be in the write phase.
378
379     PhasedVar& operator=(const T& value)
380     {
381 #ifdef DEBUG
382 #ifndef LEGACY_BACKEND
383         assert(m_writePhase);
384 #endif // !LEGACY_BACKEND
385         m_initialized = true;
386 #endif // DEBUG
387         m_value = value;
388         return *this;
389     }
390
391     PhasedVar& operator&=(const T& value)
392     {
393 #ifdef DEBUG
394 #ifndef LEGACY_BACKEND
395         assert(m_writePhase);
396 #endif // !LEGACY_BACKEND
397         m_initialized = true;
398 #endif // DEBUG
399         m_value &= value;
400         return *this;
401     }
402
403     // Note: if you need more <op>= functions, you can define them here, like operator&=
404
405     // Assign a value, but don't assert if we're not in the write phase, and
406     // don't change the phase (if we're actually in the read phase, we'll stay
407     // in the read phase). This is a dangerous function, and overrides the main
408     // benefit of this class. Use it wisely!
409     void OverrideAssign(const T& value)
410     {
411 #ifdef DEBUG
412         m_initialized = true;
413 #endif // DEBUG
414         m_value = value;
415     }
416
417     // We've decided that this variable can go back to write phase, even if it has been
418     // written. This can be used, for example, for variables set and read during frame
419     // layout calculation, as long as it is before final layout, such that anything
420     // being calculated is just an estimate anyway. Obviously, it must be used carefully,
421     // since it overrides the main benefit of this class.
422     void ResetWritePhase()
423     {
424 #ifdef DEBUG
425         m_writePhase = true;
426 #endif // DEBUG
427     }
428
429 private:
430     // Don't allow a copy constructor. (This could be allowed, but only add it once it is actually needed.)
431
432     PhasedVar(const PhasedVar& o)
433     {
434         unreached();
435     }
436
437     T m_value;
438 #ifdef DEBUG
439     bool m_initialized; // true once the variable has been initialized, that is, written once.
440     bool m_writePhase;  // true if we are in the (initial) "write" phase. Once the value is read, this changes to false,
441                         // and can't be changed back.
442 #endif                  // DEBUG
443 };
444
445 class HelperCallProperties
446 {
447 private:
448     bool m_isPure[CORINFO_HELP_COUNT];
449     bool m_noThrow[CORINFO_HELP_COUNT];
450     bool m_nonNullReturn[CORINFO_HELP_COUNT];
451     bool m_isAllocator[CORINFO_HELP_COUNT];
452     bool m_mutatesHeap[CORINFO_HELP_COUNT];
453     bool m_mayRunCctor[CORINFO_HELP_COUNT];
454     bool m_mayFinalize[CORINFO_HELP_COUNT];
455
456     void init();
457
458 public:
459     HelperCallProperties()
460     {
461         init();
462     }
463
464     bool IsPure(CorInfoHelpFunc helperId)
465     {
466         assert(helperId > CORINFO_HELP_UNDEF);
467         assert(helperId < CORINFO_HELP_COUNT);
468         return m_isPure[helperId];
469     }
470
471     bool NoThrow(CorInfoHelpFunc helperId)
472     {
473         assert(helperId > CORINFO_HELP_UNDEF);
474         assert(helperId < CORINFO_HELP_COUNT);
475         return m_noThrow[helperId];
476     }
477
478     bool NonNullReturn(CorInfoHelpFunc helperId)
479     {
480         assert(helperId > CORINFO_HELP_UNDEF);
481         assert(helperId < CORINFO_HELP_COUNT);
482         return m_nonNullReturn[helperId];
483     }
484
485     bool IsAllocator(CorInfoHelpFunc helperId)
486     {
487         assert(helperId > CORINFO_HELP_UNDEF);
488         assert(helperId < CORINFO_HELP_COUNT);
489         return m_isAllocator[helperId];
490     }
491
492     bool MutatesHeap(CorInfoHelpFunc helperId)
493     {
494         assert(helperId > CORINFO_HELP_UNDEF);
495         assert(helperId < CORINFO_HELP_COUNT);
496         return m_mutatesHeap[helperId];
497     }
498
499     bool MayRunCctor(CorInfoHelpFunc helperId)
500     {
501         assert(helperId > CORINFO_HELP_UNDEF);
502         assert(helperId < CORINFO_HELP_COUNT);
503         return m_mayRunCctor[helperId];
504     }
505
506     bool MayFinalize(CorInfoHelpFunc helperId)
507     {
508         assert(helperId > CORINFO_HELP_UNDEF);
509         assert(helperId < CORINFO_HELP_COUNT);
510         return m_mayFinalize[helperId];
511     }
512 };
513
514 //*****************************************************************************
515 // AssemblyNamesList2: Parses and stores a list of Assembly names, and provides
516 // a function for determining whether a given assembly name is part of the list.
517 //
518 // This is a clone of the AssemblyNamesList class that exists in the VM's utilcode,
519 // modified to use the JIT's memory allocator and throw on out of memory behavior.
520 // It is named AssemblyNamesList2 to avoid a name conflict with the VM version.
521 // It might be preferable to adapt the VM's code to be more flexible (for example,
522 // by using an IAllocator), but the string handling code there is heavily macroized,
523 // and for the small usage we have of this class, investing in genericizing the VM
524 // implementation didn't seem worth it.
525 //*****************************************************************************
526
527 class AssemblyNamesList2
528 {
529     struct AssemblyName
530     {
531         char*         m_assemblyName;
532         AssemblyName* m_next;
533     };
534
535     AssemblyName*  m_pNames; // List of names
536     HostAllocator* m_alloc;  // HostAllocator to use in this class
537
538 public:
539     // Take a Unicode string list of assembly names, parse it, and store it.
540     AssemblyNamesList2(const wchar_t* list, __in HostAllocator* alloc);
541
542     ~AssemblyNamesList2();
543
544     // Return 'true' if 'assemblyName' (in UTF-8 format) is in the stored list of assembly names.
545     bool IsInList(const char* assemblyName);
546
547     // Return 'true' if the assembly name list is empty.
548     bool IsEmpty()
549     {
550         return m_pNames == nullptr;
551     }
552 };
553
554 #ifdef FEATURE_JIT_METHOD_PERF
555 // When Start() is called time is noted and when ElapsedTime
556 // is called we know how much time was spent in msecs.
557 //
558 class CycleCount
559 {
560 private:
561     double           cps;         // cycles per second
562     unsigned __int64 beginCycles; // cycles at stop watch construction
563 public:
564     CycleCount();
565
566     // Kick off the counter, and if re-entrant will use the latest cycles as starting point.
567     // If the method returns false, any other query yield unpredictable results.
568     bool Start();
569
570     // Return time elapsed in msecs, if Start returned true.
571     double ElapsedTime();
572
573 private:
574     // Return true if successful.
575     bool GetCycles(unsigned __int64* time);
576 };
577
578 // Uses win API QueryPerformanceCounter/QueryPerformanceFrequency.
579 class PerfCounter
580 {
581     LARGE_INTEGER beg;
582     double        freq;
583
584 public:
585     // If the method returns false, any other query yield unpredictable results.
586     bool Start();
587
588     // Return time elapsed from start in millis, if Start returned true.
589     double ElapsedTime();
590 };
591
592 #endif // FEATURE_JIT_METHOD_PERF
593
594 #ifdef DEBUG
595
596 /*****************************************************************************
597  * Return the number of digits in a number of the given base (default base 10).
598  * Used when outputting strings.
599  */
600 unsigned CountDigits(unsigned num, unsigned base = 10);
601
602 #endif // DEBUG
603
604 /*****************************************************************************
605 * Floating point utility class
606 */
607 class FloatingPointUtils
608 {
609 public:
610     static double convertUInt64ToDouble(unsigned __int64 u64);
611
612     static float convertUInt64ToFloat(unsigned __int64 u64);
613
614     static unsigned __int64 convertDoubleToUInt64(double d);
615
616     static double round(double x);
617
618     static float round(float x);
619 };
620
621 // The CLR requires that critical section locks be initialized via its ClrCreateCriticalSection API...but
622 // that can't be called until the CLR is initialized. If we have static data that we'd like to protect by a
623 // lock, and we have a statically allocated lock to protect that data, there's an issue in how to initialize
624 // that lock. We could insert an initialize call in the startup path, but one might prefer to keep the code
625 // more local. For such situations, CritSecObject solves the initialization problem, via a level of
626 // indirection. A pointer to the lock is initially null, and when we query for the lock pointer via "Val()".
627 // If the lock has not yet been allocated, this allocates one (here a leaf lock), and uses a
628 // CompareAndExchange-based lazy-initialization to update the field. If this fails, the allocated lock is
629 // destroyed. This will work as long as the first locking attempt occurs after enough CLR initialization has
630 // happened to make ClrCreateCriticalSection calls legal.
631
632 class CritSecObject
633 {
634 public:
635     CritSecObject()
636     {
637         m_pCs = nullptr;
638     }
639
640     CRITSEC_COOKIE Val()
641     {
642         if (m_pCs == nullptr)
643         {
644             // CompareExchange-based lazy init.
645             CRITSEC_COOKIE newCs    = ClrCreateCriticalSection(CrstLeafLock, CRST_DEFAULT);
646             CRITSEC_COOKIE observed = InterlockedCompareExchangeT(&m_pCs, newCs, NULL);
647             if (observed != nullptr)
648             {
649                 ClrDeleteCriticalSection(newCs);
650             }
651         }
652         return m_pCs;
653     }
654
655 private:
656     // CRITSEC_COOKIE is an opaque pointer type.
657     CRITSEC_COOKIE m_pCs;
658
659     // No copying or assignment allowed.
660     CritSecObject(const CritSecObject&) = delete;
661     CritSecObject& operator=(const CritSecObject&) = delete;
662 };
663
664 // Stack-based holder for a critial section lock.
665 // Ensures lock is released.
666
667 class CritSecHolder
668 {
669 public:
670     CritSecHolder(CritSecObject& critSec) : m_CritSec(critSec)
671     {
672         ClrEnterCriticalSection(m_CritSec.Val());
673     }
674
675     ~CritSecHolder()
676     {
677         ClrLeaveCriticalSection(m_CritSec.Val());
678     }
679
680 private:
681     CritSecObject& m_CritSec;
682
683     // No copying or assignment allowed.
684     CritSecHolder(const CritSecHolder&) = delete;
685     CritSecHolder& operator=(const CritSecHolder&) = delete;
686 };
687
688 namespace MagicDivide
689 {
690 uint32_t GetUnsigned32Magic(uint32_t d, bool* add /*out*/, int* shift /*out*/);
691 #ifdef _TARGET_64BIT_
692 uint64_t GetUnsigned64Magic(uint64_t d, bool* add /*out*/, int* shift /*out*/);
693 #endif
694 int32_t GetSigned32Magic(int32_t d, int* shift /*out*/);
695 #ifdef _TARGET_64BIT_
696 int64_t GetSigned64Magic(int64_t d, int* shift /*out*/);
697 #endif
698 }
699
700 #endif // _UTILS_H_