Fix reading Time zone rules using Julian days (#17672)
[platform/upstream/coreclr.git] / src / jit / unwindx86.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 // See the LICENSE file in the project root for more information.
4
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 XX                                                                           XX
8 XX                              UnwindInfo                                   XX
9 XX                                                                           XX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13
14 #include "jitpch.h"
15 #ifdef _MSC_VER
16 #pragma hdrstop
17 #endif
18
19 #ifndef _TARGET_X86_
20 #error "This should be included only for x86"
21 #endif // _TARGET_X86_
22
23 #if defined(_TARGET_UNIX_)
24 int Compiler::mapRegNumToDwarfReg(regNumber reg)
25 {
26     int dwarfReg = DWARF_REG_ILLEGAL;
27
28     NYI("CFI codes");
29
30     return dwarfReg;
31 }
32 #endif // _TARGET_UNIX_
33
34 void Compiler::unwindBegProlog()
35 {
36 }
37
38 void Compiler::unwindEndProlog()
39 {
40 }
41
42 void Compiler::unwindBegEpilog()
43 {
44 }
45
46 void Compiler::unwindEndEpilog()
47 {
48 }
49
50 void Compiler::unwindPush(regNumber reg)
51 {
52 }
53
54 void Compiler::unwindAllocStack(unsigned size)
55 {
56 }
57
58 void Compiler::unwindSetFrameReg(regNumber reg, unsigned offset)
59 {
60 }
61
62 void Compiler::unwindSaveReg(regNumber reg, unsigned offset)
63 {
64 }
65
66 //------------------------------------------------------------------------
67 // Compiler::unwindReserve: Ask the VM to reserve space for the unwind information
68 // for the function and all its funclets. Called once, just before asking the VM
69 // for memory and emitting the generated code. Calls unwindReserveFunc() to handle
70 // the main function and each of the funclets, in turn.
71 //
72 void Compiler::unwindReserve()
73 {
74 #if FEATURE_EH_FUNCLETS
75     assert(!compGeneratingProlog);
76     assert(!compGeneratingEpilog);
77
78     assert(compFuncInfoCount > 0);
79     for (unsigned funcIdx = 0; funcIdx < compFuncInfoCount; funcIdx++)
80     {
81         unwindReserveFunc(funGetFunc(funcIdx));
82     }
83 #endif
84 }
85
86 //------------------------------------------------------------------------
87 // Compiler::unwindEmit: Report all the unwind information to the VM.
88 //
89 // Arguments:
90 //    pHotCode  - Pointer to the beginning of the memory with the function and funclet hot  code.
91 //    pColdCode - Pointer to the beginning of the memory with the function and funclet cold code.
92 //
93 void Compiler::unwindEmit(void* pHotCode, void* pColdCode)
94 {
95 #if FEATURE_EH_FUNCLETS
96     assert(!compGeneratingProlog);
97     assert(!compGeneratingEpilog);
98
99     assert(compFuncInfoCount > 0);
100     for (unsigned funcIdx = 0; funcIdx < compFuncInfoCount; funcIdx++)
101     {
102         unwindEmitFunc(funGetFunc(funcIdx), pHotCode, pColdCode);
103     }
104 #endif // FEATURE_EH_FUNCLETS
105 }
106
107 #if FEATURE_EH_FUNCLETS
108 //------------------------------------------------------------------------
109 // Compiler::unwindReserveFunc: Reserve the unwind information from the VM for a
110 // given main function or funclet.
111 //
112 // Arguments:
113 //    func - The main function or funclet to reserve unwind info for.
114 //
115 void Compiler::unwindReserveFunc(FuncInfoDsc* func)
116 {
117     unwindReserveFuncHelper(func, true);
118
119     if (fgFirstColdBlock != nullptr)
120     {
121         unwindReserveFuncHelper(func, false);
122     }
123 }
124
125 //------------------------------------------------------------------------
126 // Compiler::unwindReserveFuncHelper: Reserve the unwind information from the VM for a
127 // given main function or funclet, for either the hot or the cold section.
128 //
129 // Arguments:
130 //    func      - The main function or funclet to reserve unwind info for.
131 //    isHotCode - 'true' to reserve the hot section, 'false' to reserve the cold section.
132 //
133 void Compiler::unwindReserveFuncHelper(FuncInfoDsc* func, bool isHotCode)
134 {
135     BOOL isFunclet  = (func->funKind != FUNC_ROOT);
136     BOOL isColdCode = isHotCode ? FALSE : TRUE;
137
138     eeReserveUnwindInfo(isFunclet, isColdCode, sizeof(UNWIND_INFO));
139 }
140
141 //------------------------------------------------------------------------
142 // Compiler::unwindEmitFunc: Report the unwind information to the VM for a
143 // given main function or funclet. Reports the hot section, then the cold
144 // section if necessary.
145 //
146 // Arguments:
147 //    func      - The main function or funclet to reserve unwind info for.
148 //    pHotCode  - Pointer to the beginning of the memory with the function and funclet hot  code.
149 //    pColdCode - Pointer to the beginning of the memory with the function and funclet cold code.
150 //
151 void Compiler::unwindEmitFunc(FuncInfoDsc* func, void* pHotCode, void* pColdCode)
152 {
153     // Verify that the JIT enum is in sync with the JIT-EE interface enum
154     static_assert_no_msg(FUNC_ROOT == (FuncKind)CORJIT_FUNC_ROOT);
155     static_assert_no_msg(FUNC_HANDLER == (FuncKind)CORJIT_FUNC_HANDLER);
156     static_assert_no_msg(FUNC_FILTER == (FuncKind)CORJIT_FUNC_FILTER);
157
158     unwindEmitFuncHelper(func, pHotCode, pColdCode, true);
159
160     if (pColdCode != nullptr)
161     {
162         unwindEmitFuncHelper(func, pHotCode, pColdCode, false);
163     }
164 }
165
166 //------------------------------------------------------------------------
167 // Compiler::unwindEmitFuncHelper: Report the unwind information to the VM for a
168 // given main function or funclet, for either the hot or cold section.
169 //
170 // Arguments:
171 //    func      - The main function or funclet to reserve unwind info for.
172 //    pHotCode  - Pointer to the beginning of the memory with the function and funclet hot  code.
173 //    pColdCode - Pointer to the beginning of the memory with the function and funclet cold code.
174 //                Ignored if 'isHotCode' is true.
175 //    isHotCode - 'true' to report the hot section, 'false' to report the cold section.
176 //
177 void Compiler::unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pColdCode, bool isHotCode)
178 {
179     UNATIVE_OFFSET startOffset;
180     UNATIVE_OFFSET endOffset;
181
182     if (isHotCode)
183     {
184         emitLocation* startLoc;
185         emitLocation* endLoc;
186
187         unwindGetFuncLocations(func, true, &startLoc, &endLoc);
188
189         if (startLoc == nullptr)
190         {
191             startOffset = 0;
192         }
193         else
194         {
195             startOffset = startLoc->CodeOffset(genEmitter);
196         }
197
198         if (endLoc == nullptr)
199         {
200             endOffset = info.compNativeCodeSize;
201         }
202         else
203         {
204             endOffset = endLoc->CodeOffset(genEmitter);
205         }
206     }
207     else
208     {
209         emitLocation* coldStartLoc;
210         emitLocation* coldEndLoc;
211
212         assert(fgFirstColdBlock != nullptr);
213         assert(func->funKind == FUNC_ROOT); // No splitting of funclets.
214
215         unwindGetFuncLocations(func, false, &coldStartLoc, &coldEndLoc);
216
217         if (coldStartLoc == nullptr)
218         {
219             startOffset = 0;
220         }
221         else
222         {
223             startOffset = coldStartLoc->CodeOffset(genEmitter);
224         }
225
226         if (coldEndLoc == nullptr)
227         {
228             endOffset = info.compNativeCodeSize;
229         }
230         else
231         {
232             endOffset = coldEndLoc->CodeOffset(genEmitter);
233         }
234     }
235
236     // Adjust for cold or hot code:
237     // 1. The VM doesn't want the cold code pointer unless this is cold code.
238     // 2. The startOffset and endOffset need to be from the base of the hot section for hot code
239     //    and from the base of the cold section for cold code
240
241     if (isHotCode)
242     {
243         assert(endOffset <= info.compTotalHotCodeSize);
244         pColdCode = nullptr;
245     }
246     else
247     {
248         assert(startOffset >= info.compTotalHotCodeSize);
249         startOffset -= info.compTotalHotCodeSize;
250         endOffset -= info.compTotalHotCodeSize;
251     }
252
253     UNWIND_INFO unwindInfo;
254
255     unwindInfo.FunctionLength = (ULONG)(endOffset - startOffset);
256
257     eeAllocUnwindInfo((BYTE*)pHotCode, (BYTE*)pColdCode, startOffset, endOffset, sizeof(UNWIND_INFO),
258                       (BYTE*)&unwindInfo, (CorJitFuncKind)func->funKind);
259 }
260 #endif // FEATURE_EH_FUNCLETS