Fix reading Time zone rules using Julian days (#17672)
[platform/upstream/coreclr.git] / src / jit / ssarenamestate.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 // ==++==
6 //
7
8 //
9
10 //
11 // ==--==
12
13 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
14 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
15 XX                                                                           XX
16 XX                                  SSA                                      XX
17 XX                                                                           XX
18 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
19 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
20 */
21
22 #pragma once
23
24 #include "jitstd.h"
25
26 // Fixed-size array that can hold elements with no default constructor;
27 // it will construct them all by forwarding whatever arguments are
28 // supplied to its constructor.
29 template <typename T, int N>
30 class ConstructedArray
31 {
32     union {
33         // Storage that gets used to hold the T objects.
34         unsigned char bytes[N * sizeof(T)];
35
36 #if defined(_MSC_VER) && (_MSC_VER < 1900)
37         // With MSVC pre-VS2015, the code in the #else branch would hit error C2621,
38         // so in that case just count on pointer alignment being sufficient
39         // (currently T is only ever instantiated as jitstd::list<SsaRenameStateForBlock>)
40
41         // Unused (except to impart alignment requirement)
42         void* pointer;
43 #else
44         // Unused (except to impart alignment requirement)
45         T alignedArray[N];
46 #endif // defined(_MSC_VER) && (_MSC_VER < 1900)
47     };
48
49 public:
50     T& operator[](size_t i)
51     {
52         return *(reinterpret_cast<T*>(bytes + i * sizeof(T)));
53     }
54
55     template <typename... Args>
56     ConstructedArray(Args&&... args)
57     {
58         for (int i = 0; i < N; ++i)
59         {
60             new (bytes + i * sizeof(T), jitstd::placement_t()) T(jitstd::forward<Args>(args)...);
61         }
62     }
63
64     ~ConstructedArray()
65     {
66         for (int i = 0; i < N; ++i)
67         {
68             operator[](i).~T();
69         }
70     }
71 };
72
73 struct SsaRenameStateForBlock
74 {
75     BasicBlock* m_bb;
76     unsigned    m_count;
77
78     SsaRenameStateForBlock(BasicBlock* bb, unsigned count) : m_bb(bb), m_count(count)
79     {
80     }
81     SsaRenameStateForBlock() : m_bb(nullptr), m_count(0)
82     {
83     }
84 };
85
86 // A record indicating that local "m_loc" was defined in block "m_bb".
87 struct SsaRenameStateLocDef
88 {
89     BasicBlock* m_bb;
90     unsigned    m_lclNum;
91
92     SsaRenameStateLocDef(BasicBlock* bb, unsigned lclNum) : m_bb(bb), m_lclNum(lclNum)
93     {
94     }
95 };
96
97 struct SsaRenameState
98 {
99     typedef jitstd::list<SsaRenameStateForBlock> Stack;
100     typedef Stack**                              Stacks;
101     typedef unsigned*                            Counts;
102     typedef jitstd::list<SsaRenameStateLocDef>   DefStack;
103
104     SsaRenameState(const jitstd::allocator<int>& allocator, unsigned lvaCount, bool byrefStatesMatchGcHeapStates);
105
106     void EnsureCounts();
107     void EnsureStacks();
108
109     // Requires "lclNum" to be a variable number for which a new count corresponding to a
110     // definition is desired. The method post increments the counter for the "lclNum."
111     unsigned CountForDef(unsigned lclNum);
112
113     // Requires "lclNum" to be a variable number for which an ssa number at the top of the
114     // stack is required i.e., for variable "uses."
115     unsigned CountForUse(unsigned lclNum);
116
117     // Requires "lclNum" to be a variable number, and requires "count" to represent
118     // an ssa number, that needs to be pushed on to the stack corresponding to the lclNum.
119     void Push(BasicBlock* bb, unsigned lclNum, unsigned count);
120
121     // Pop all stacks that have an entry for "bb" on top.
122     void PopBlockStacks(BasicBlock* bb);
123
124     // Similar functions for the special implicit memory variable.
125     unsigned CountForMemoryDef()
126     {
127         if (memoryCount == 0)
128         {
129             memoryCount = SsaConfig::FIRST_SSA_NUM;
130         }
131         unsigned res = memoryCount;
132         memoryCount++;
133         return res;
134     }
135     unsigned CountForMemoryUse(MemoryKind memoryKind)
136     {
137         if ((memoryKind == GcHeap) && byrefStatesMatchGcHeapStates)
138         {
139             // Share rename stacks in this configuration.
140             memoryKind = ByrefExposed;
141         }
142         return memoryStack[memoryKind].back().m_count;
143     }
144
145     void PushMemory(MemoryKind memoryKind, BasicBlock* bb, unsigned count)
146     {
147         if ((memoryKind == GcHeap) && byrefStatesMatchGcHeapStates)
148         {
149             // Share rename stacks in this configuration.
150             memoryKind = ByrefExposed;
151         }
152         memoryStack[memoryKind].push_back(SsaRenameStateForBlock(bb, count));
153     }
154
155     void PopBlockMemoryStack(MemoryKind memoryKind, BasicBlock* bb);
156
157     unsigned MemoryCount()
158     {
159         return memoryCount;
160     }
161
162 #ifdef DEBUG
163     // Debug interface
164     void DumpStacks();
165 #endif
166
167 private:
168     // Map of lclNum -> count.
169     Counts counts;
170
171     // Map of lclNum -> SsaRenameStateForBlock.
172     Stacks stacks;
173
174     // This list represents the set of locals defined in the current block.
175     DefStack definedLocs;
176
177     // Same state for the special implicit memory variables.
178     ConstructedArray<Stack, MemoryKindCount> memoryStack;
179     unsigned memoryCount;
180
181     // Number of stacks/counts to allocate.
182     unsigned lvaCount;
183
184     // Allocator to allocate stacks.
185     jitstd::allocator<void> m_alloc;
186
187     // Indicates whether GcHeap and ByrefExposed use the same state.
188     bool byrefStatesMatchGcHeapStates;
189 };