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 Unwind Info XX |
9 | XX XX |
10 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
11 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
12 | */ |
13 | |
14 | #ifdef _TARGET_ARMARCH_ |
15 | |
16 | // Windows no longer imposes a maximum prolog size. However, we still have an |
17 | // assert here just to inform us if we increase the size of the prolog |
18 | // accidentally, as there is still a slight performance advantage in the |
19 | // OS unwinder to having as few unwind codes as possible. |
20 | // You can increase this "max" number if necessary. |
21 | |
22 | #if defined(_TARGET_ARM_) |
23 | const unsigned MAX_PROLOG_SIZE_BYTES = 40; |
24 | const unsigned MAX_EPILOG_SIZE_BYTES = 40; |
25 | #define UWC_END 0xFF // "end" unwind code |
26 | #define UW_MAX_FRAGMENT_SIZE_BYTES (1U << 19) |
27 | #define UW_MAX_CODE_WORDS_COUNT 15 // Max number that can be encoded in the "Code Words" field of the .pdata record |
28 | #define UW_MAX_EPILOG_START_INDEX 0xFFU // Max number that can be encoded in the "Epilog Start Index" field |
29 | // of the .pdata record |
30 | #elif defined(_TARGET_ARM64_) |
31 | const unsigned MAX_PROLOG_SIZE_BYTES = 100; |
32 | const unsigned MAX_EPILOG_SIZE_BYTES = 100; |
33 | #define UWC_END 0xE4 // "end" unwind code |
34 | #define UWC_END_C 0xE5 // "end_c" unwind code |
35 | #define UW_MAX_FRAGMENT_SIZE_BYTES (1U << 20) |
36 | #define UW_MAX_CODE_WORDS_COUNT 31 |
37 | #define UW_MAX_EPILOG_START_INDEX 0x3FFU |
38 | #endif // _TARGET_ARM64_ |
39 | |
40 | #define UW_MAX_EPILOG_COUNT 31 // Max number that can be encoded in the "Epilog count" field |
41 | // of the .pdata record |
42 | #define UW_MAX_EXTENDED_CODE_WORDS_COUNT 0xFFU // Max number that can be encoded in the "Extended Code Words" |
43 | // field of the .pdata record |
44 | #define UW_MAX_EXTENDED_EPILOG_COUNT 0xFFFFU // Max number that can be encoded in the "Extended Epilog Count" |
45 | // field of the .pdata record |
46 | #define UW_MAX_EPILOG_START_OFFSET 0x3FFFFU // Max number that can be encoded in the "Epilog Start Offset" |
47 | // field of the .pdata record |
48 | |
49 | // |
50 | // Forward declaration of class defined in emit.h |
51 | // |
52 | |
53 | class emitLocation; |
54 | |
55 | // |
56 | // Forward declarations of classes defined in this file |
57 | // |
58 | |
59 | class UnwindCodesBase; |
60 | class UnwindPrologCodes; |
61 | class UnwindEpilogCodes; |
62 | class UnwindEpilogInfo; |
63 | class UnwindFragmentInfo; |
64 | class UnwindInfo; |
65 | |
66 | // UnwindBase: A base class shared by the the unwind classes that require |
67 | // a Compiler* for memory allocation. |
68 | |
69 | class UnwindBase |
70 | { |
71 | protected: |
72 | UnwindBase(Compiler* comp) : uwiComp(comp) |
73 | { |
74 | } |
75 | |
76 | UnwindBase() |
77 | { |
78 | } |
79 | ~UnwindBase() |
80 | { |
81 | } |
82 | |
83 | // TODO: How do we get the ability to access uwiComp without error on Clang? |
84 | #if defined(DEBUG) && !defined(__GNUC__) |
85 | |
86 | template <typename T> |
87 | T dspPtr(T p) |
88 | { |
89 | return uwiComp->dspPtr(p); |
90 | } |
91 | |
92 | template <typename T> |
93 | T dspOffset(T o) |
94 | { |
95 | return uwiComp->dspOffset(o); |
96 | } |
97 | |
98 | static const char* dspBool(bool b) |
99 | { |
100 | return (b) ? "true" : "false" ; |
101 | } |
102 | |
103 | #endif // DEBUG |
104 | |
105 | // |
106 | // Data |
107 | // |
108 | |
109 | Compiler* uwiComp; |
110 | }; |
111 | |
112 | // UnwindCodesBase: A base class shared by the the classes used to represent the prolog |
113 | // and epilog unwind codes. |
114 | |
115 | class UnwindCodesBase |
116 | { |
117 | public: |
118 | // Add a single unwind code. |
119 | |
120 | virtual void AddCode(BYTE b1) = 0; |
121 | virtual void AddCode(BYTE b1, BYTE b2) = 0; |
122 | virtual void AddCode(BYTE b1, BYTE b2, BYTE b3) = 0; |
123 | virtual void AddCode(BYTE b1, BYTE b2, BYTE b3, BYTE b4) = 0; |
124 | |
125 | // Get access to the unwind codes |
126 | |
127 | virtual BYTE* GetCodes() = 0; |
128 | |
129 | bool IsEndCode(BYTE b) |
130 | { |
131 | #if defined(_TARGET_ARM_) |
132 | return b >= 0xFD; |
133 | #elif defined(_TARGET_ARM64_) |
134 | return (b == UWC_END); // TODO-ARM64-Bug?: what about the "end_c" code? |
135 | #endif // _TARGET_ARM64_ |
136 | } |
137 | |
138 | #ifdef DEBUG |
139 | |
140 | unsigned GetCodeSizeFromUnwindCodes(bool isProlog); |
141 | |
142 | #endif // DEBUG |
143 | }; |
144 | |
145 | // UnwindPrologCodes: represents the unwind codes for a prolog sequence. |
146 | // Prolog unwind codes arrive in reverse order from how they will be emitted. |
147 | // Store them as a stack, storing from the end of an array towards the beginning. |
148 | // This class is also re-used as the final location of the consolidated unwind |
149 | // information for a function, including unwind info header, the prolog codes, |
150 | // and any epilog codes. |
151 | |
152 | class UnwindPrologCodes : public UnwindBase, public UnwindCodesBase |
153 | { |
154 | // UPC_LOCAL_COUNT is the amount of memory local to this class. For ARM mscorlib.dll, the maximum size is 34. |
155 | // Here is a histogram of other interesting sizes: |
156 | // <=16 79% |
157 | // <=24 96% |
158 | // <=32 99% |
159 | // From this data, we choose to use 24. |
160 | |
161 | static const int UPC_LOCAL_COUNT = 24; |
162 | |
163 | public: |
164 | UnwindPrologCodes(Compiler* comp) |
165 | : UnwindBase(comp) |
166 | , upcMem(upcMemLocal) |
167 | , upcMemSize(UPC_LOCAL_COUNT) |
168 | , upcCodeSlot(UPC_LOCAL_COUNT) |
169 | , upcHeaderSlot(-1) |
170 | , upcEpilogSlot(-1) |
171 | { |
172 | // Assume we've got a normal end code. |
173 | // Push four so we can generate an array that is a multiple of 4 bytes in size with the |
174 | // end codes (and padding) already in place. One is the end code for the prolog codes, |
175 | // three are end-of-array alignment padding. |
176 | PushByte(UWC_END); |
177 | PushByte(UWC_END); |
178 | PushByte(UWC_END); |
179 | PushByte(UWC_END); |
180 | } |
181 | |
182 | // |
183 | // Implementation of UnwindCodesBase |
184 | // |
185 | |
186 | virtual void AddCode(BYTE b1) |
187 | { |
188 | PushByte(b1); |
189 | } |
190 | |
191 | virtual void AddCode(BYTE b1, BYTE b2) |
192 | { |
193 | PushByte(b2); |
194 | PushByte(b1); |
195 | } |
196 | |
197 | virtual void AddCode(BYTE b1, BYTE b2, BYTE b3) |
198 | { |
199 | PushByte(b3); |
200 | PushByte(b2); |
201 | PushByte(b1); |
202 | } |
203 | |
204 | virtual void AddCode(BYTE b1, BYTE b2, BYTE b3, BYTE b4) |
205 | { |
206 | PushByte(b4); |
207 | PushByte(b3); |
208 | PushByte(b2); |
209 | PushByte(b1); |
210 | } |
211 | |
212 | // Return a pointer to the first unwind code byte |
213 | virtual BYTE* GetCodes() |
214 | { |
215 | assert(upcCodeSlot < upcMemSize); // There better be at least one code! |
216 | return &upcMem[upcCodeSlot]; |
217 | } |
218 | |
219 | /////////////////////////////////////////////////////////////////////////// |
220 | |
221 | BYTE GetByte(int index) |
222 | { |
223 | assert(upcCodeSlot <= index && index < upcMemSize); |
224 | return upcMem[index]; |
225 | } |
226 | |
227 | // Push a single byte on the unwind code stack |
228 | void PushByte(BYTE b) |
229 | { |
230 | if (upcCodeSlot == 0) |
231 | { |
232 | // We've run out of space! Reallocate, and copy everything to a new array. |
233 | EnsureSize(upcMemSize + 1); |
234 | } |
235 | |
236 | --upcCodeSlot; |
237 | noway_assert(0 <= upcCodeSlot && upcCodeSlot < upcMemSize); |
238 | |
239 | upcMem[upcCodeSlot] = b; |
240 | } |
241 | |
242 | // Return the size of the unwind codes, in bytes. The size is the exact size, not an aligned size. |
243 | // The size includes exactly one "end" code. |
244 | int Size() |
245 | { |
246 | // -3 because we put 4 "end" codes at the end in the constructor, and we shouldn't count that here |
247 | return upcMemSize - upcCodeSlot - 3; |
248 | } |
249 | |
250 | void SetFinalSize(int headerBytes, int epilogBytes); |
251 | |
252 | void AddHeaderWord(DWORD d); |
253 | |
254 | void GetFinalInfo(/* OUT */ BYTE** ppUnwindBlock, /* OUT */ ULONG* pUnwindBlockSize); |
255 | |
256 | // AppendEpilog: copy the epilog bytes to the next epilog bytes slot |
257 | void AppendEpilog(UnwindEpilogInfo* pEpi); |
258 | |
259 | // Match the prolog codes to a set of epilog codes |
260 | int Match(UnwindEpilogInfo* pEpi); |
261 | |
262 | // Copy the prolog codes from another prolog |
263 | void CopyFrom(UnwindPrologCodes* pCopyFrom); |
264 | |
265 | UnwindPrologCodes() |
266 | { |
267 | } |
268 | ~UnwindPrologCodes() |
269 | { |
270 | } |
271 | |
272 | #ifdef DEBUG |
273 | void Dump(int indent = 0); |
274 | #endif // DEBUG |
275 | |
276 | private: |
277 | void EnsureSize(int requiredSize); |
278 | |
279 | // No copy constructor or operator= |
280 | UnwindPrologCodes(const UnwindPrologCodes& info); |
281 | UnwindPrologCodes& operator=(const UnwindPrologCodes&); |
282 | |
283 | // |
284 | // Data |
285 | // |
286 | |
287 | // To store the unwind codes, we first use a local array that should satisfy almost all cases. |
288 | // If there are more unwind codes, we dynamically allocate memory. |
289 | BYTE upcMemLocal[UPC_LOCAL_COUNT]; |
290 | BYTE* upcMem; |
291 | |
292 | // upcMemSize is the number of bytes in upcMem. This is equal to UPC_LOCAL_COUNT unless |
293 | // we've dynamically allocated memory to store the codes. |
294 | int upcMemSize; |
295 | |
296 | // upcCodeSlot points to the last unwind code added to the array. The array is filled in from |
297 | // the end, so it starts pointing one beyond the array end. |
298 | int upcCodeSlot; |
299 | |
300 | // upcHeaderSlot points to the last header byte prepended to the array. Headers bytes are |
301 | // filled in from the beginning, and only after SetFinalSize() is called. |
302 | int upcHeaderSlot; |
303 | |
304 | // upcEpilogSlot points to the next epilog location to fill |
305 | int upcEpilogSlot; |
306 | |
307 | // upcUnwindBlockSlot is only set after SetFinalSize() is called. It is the index of the first |
308 | // byte of the final unwind data, namely the first byte of the header. |
309 | int upcUnwindBlockSlot; |
310 | }; |
311 | |
312 | // UnwindEpilogCodes: represents the unwind codes for a single epilog sequence. |
313 | // Epilog unwind codes arrive in the order they will be emitted. Store them as an array, |
314 | // adding new ones to the end of the array. |
315 | |
316 | class UnwindEpilogCodes : public UnwindBase, public UnwindCodesBase |
317 | { |
318 | // UEC_LOCAL_COUNT is the amount of memory local to this class. For ARM mscorlib.dll, the maximum size is 6, |
319 | // while 89% of epilogs fit in 4. So, set it to 4 to maintain array alignment and hit most cases. |
320 | static const int UEC_LOCAL_COUNT = 4; |
321 | |
322 | public: |
323 | UnwindEpilogCodes(Compiler* comp) |
324 | : UnwindBase(comp) |
325 | , uecMem(uecMemLocal) |
326 | , firstByteOfLastCode(0) |
327 | , uecMemSize(UEC_LOCAL_COUNT) |
328 | , uecCodeSlot(-1) |
329 | , uecFinalized(false) |
330 | { |
331 | } |
332 | |
333 | // |
334 | // Implementation of UnwindCodesBase |
335 | // |
336 | |
337 | virtual void AddCode(BYTE b1) |
338 | { |
339 | AppendByte(b1); |
340 | |
341 | firstByteOfLastCode = b1; |
342 | } |
343 | |
344 | virtual void AddCode(BYTE b1, BYTE b2) |
345 | { |
346 | AppendByte(b1); |
347 | AppendByte(b2); |
348 | |
349 | firstByteOfLastCode = b1; |
350 | } |
351 | |
352 | virtual void AddCode(BYTE b1, BYTE b2, BYTE b3) |
353 | { |
354 | AppendByte(b1); |
355 | AppendByte(b2); |
356 | AppendByte(b3); |
357 | |
358 | firstByteOfLastCode = b1; |
359 | } |
360 | |
361 | virtual void AddCode(BYTE b1, BYTE b2, BYTE b3, BYTE b4) |
362 | { |
363 | AppendByte(b1); |
364 | AppendByte(b2); |
365 | AppendByte(b3); |
366 | AppendByte(b4); |
367 | |
368 | firstByteOfLastCode = b1; |
369 | } |
370 | |
371 | // Return a pointer to the first unwind code byte |
372 | virtual BYTE* GetCodes() |
373 | { |
374 | assert(uecFinalized); |
375 | |
376 | // Codes start at the beginning |
377 | return uecMem; |
378 | } |
379 | |
380 | /////////////////////////////////////////////////////////////////////////// |
381 | |
382 | BYTE GetByte(int index) |
383 | { |
384 | assert(0 <= index && index <= uecCodeSlot); |
385 | return uecMem[index]; |
386 | } |
387 | |
388 | // Add a single byte on the unwind code array |
389 | void AppendByte(BYTE b) |
390 | { |
391 | if (uecCodeSlot == uecMemSize - 1) |
392 | { |
393 | // We've run out of space! Reallocate, and copy everything to a new array. |
394 | EnsureSize(uecMemSize + 1); |
395 | } |
396 | |
397 | ++uecCodeSlot; |
398 | noway_assert(0 <= uecCodeSlot && uecCodeSlot < uecMemSize); |
399 | |
400 | uecMem[uecCodeSlot] = b; |
401 | } |
402 | |
403 | // Return the size of the unwind codes, in bytes. The size is the exact size, not an aligned size. |
404 | int Size() |
405 | { |
406 | if (uecFinalized) |
407 | { |
408 | // Add one because uecCodeSlot is 0-based |
409 | return uecCodeSlot + 1; |
410 | } |
411 | else |
412 | { |
413 | // Add one because uecCodeSlot is 0-based, and one for an "end" code that isn't stored (yet). |
414 | return uecCodeSlot + 2; |
415 | } |
416 | } |
417 | |
418 | void FinalizeCodes() |
419 | { |
420 | assert(!uecFinalized); |
421 | noway_assert(0 <= uecCodeSlot && uecCodeSlot < uecMemSize); // There better be at least one code! |
422 | |
423 | if (!IsEndCode(firstByteOfLastCode)) // If the last code is an end code, we don't need to append one. |
424 | { |
425 | AppendByte(UWC_END); // Add a default "end" code to the end of the array of unwind codes |
426 | firstByteOfLastCode = UWC_END; // Update firstByteOfLastCode in case we use it later |
427 | } |
428 | |
429 | uecFinalized = true; // With the "end" code in place, now we're done |
430 | |
431 | #ifdef DEBUG |
432 | unsigned codeSize = GetCodeSizeFromUnwindCodes(false); |
433 | assert(codeSize <= MAX_EPILOG_SIZE_BYTES); |
434 | #endif // DEBUG |
435 | } |
436 | |
437 | UnwindEpilogCodes() |
438 | { |
439 | } |
440 | ~UnwindEpilogCodes() |
441 | { |
442 | } |
443 | |
444 | #ifdef DEBUG |
445 | void Dump(int indent = 0); |
446 | #endif // DEBUG |
447 | |
448 | private: |
449 | void EnsureSize(int requiredSize); |
450 | |
451 | // No destructor, copy constructor or operator= |
452 | UnwindEpilogCodes(const UnwindEpilogCodes& info); |
453 | UnwindEpilogCodes& operator=(const UnwindEpilogCodes&); |
454 | |
455 | // |
456 | // Data |
457 | // |
458 | |
459 | // To store the unwind codes, we first use a local array that should satisfy almost all cases. |
460 | // If there are more unwind codes, we dynamically allocate memory. |
461 | BYTE uecMemLocal[UEC_LOCAL_COUNT]; |
462 | BYTE* uecMem; |
463 | BYTE firstByteOfLastCode; |
464 | |
465 | // uecMemSize is the number of bytes/slots in uecMem. This is equal to UEC_LOCAL_COUNT unless |
466 | // we've dynamically allocated memory to store the codes. |
467 | int uecMemSize; |
468 | |
469 | // uecCodeSlot points to the last unwind code added to the array. The array is filled in from |
470 | // the beginning, so it starts at -1. |
471 | int uecCodeSlot; |
472 | |
473 | // Is the unwind information finalized? Finalized info has an end code appended. |
474 | bool uecFinalized; |
475 | }; |
476 | |
477 | // UnwindEpilogInfo: represents the unwind information for a single epilog sequence. Epilogs for a |
478 | // single function/funclet are in a linked list. |
479 | |
480 | class UnwindEpilogInfo : public UnwindBase |
481 | { |
482 | friend class UnwindFragmentInfo; |
483 | |
484 | static const unsigned EPI_ILLEGAL_OFFSET = 0xFFFFFFFF; |
485 | |
486 | public: |
487 | UnwindEpilogInfo(Compiler* comp) |
488 | : UnwindBase(comp) |
489 | , epiNext(NULL) |
490 | , epiEmitLocation(NULL) |
491 | , epiCodes(comp) |
492 | , epiStartOffset(EPI_ILLEGAL_OFFSET) |
493 | , epiMatches(false) |
494 | , epiStartIndex(-1) |
495 | { |
496 | } |
497 | |
498 | void CaptureEmitLocation(); |
499 | |
500 | void FinalizeOffset(); |
501 | |
502 | void FinalizeCodes() |
503 | { |
504 | epiCodes.FinalizeCodes(); |
505 | } |
506 | |
507 | UNATIVE_OFFSET GetStartOffset() |
508 | { |
509 | assert(epiStartOffset != EPI_ILLEGAL_OFFSET); |
510 | return epiStartOffset; |
511 | } |
512 | |
513 | int GetStartIndex() |
514 | { |
515 | assert(epiStartIndex != -1); |
516 | return epiStartIndex; // The final "Epilog Start Index" of this epilog's unwind codes |
517 | } |
518 | |
519 | void SetStartIndex(int index) |
520 | { |
521 | assert(epiStartIndex == -1); |
522 | epiStartIndex = (int)index; |
523 | } |
524 | |
525 | void SetMatches() |
526 | { |
527 | epiMatches = true; |
528 | } |
529 | |
530 | bool Matches() |
531 | { |
532 | return epiMatches; |
533 | } |
534 | |
535 | // Size of epilog unwind codes in bytes |
536 | int Size() |
537 | { |
538 | return epiCodes.Size(); |
539 | } |
540 | |
541 | // Return a pointer to the first unwind code byte |
542 | BYTE* GetCodes() |
543 | { |
544 | return epiCodes.GetCodes(); |
545 | } |
546 | |
547 | // Match the codes to a set of epilog codes |
548 | int Match(UnwindEpilogInfo* pEpi); |
549 | |
550 | UnwindEpilogInfo() |
551 | { |
552 | } |
553 | ~UnwindEpilogInfo() |
554 | { |
555 | } |
556 | |
557 | #ifdef DEBUG |
558 | void Dump(int indent = 0); |
559 | #endif // DEBUG |
560 | |
561 | private: |
562 | // No copy constructor or operator= |
563 | UnwindEpilogInfo(const UnwindEpilogInfo& info); |
564 | UnwindEpilogInfo& operator=(const UnwindEpilogInfo&); |
565 | |
566 | // |
567 | // Data |
568 | // |
569 | |
570 | UnwindEpilogInfo* epiNext; |
571 | emitLocation* epiEmitLocation; // The emitter location of the beginning of the epilog |
572 | UnwindEpilogCodes epiCodes; |
573 | UNATIVE_OFFSET epiStartOffset; // Actual offset of the epilog, in bytes, from the start of the function. Set in |
574 | // FinalizeOffset(). |
575 | bool epiMatches; // Do the epilog unwind codes match some other set of codes? If so, we don't copy these to the |
576 | // final set; we just point to another set. |
577 | int epiStartIndex; // The final "Epilog Start Index" of this epilog's unwind codes |
578 | }; |
579 | |
580 | // UnwindFragmentInfo: represents all the unwind information for a single fragment of a function or funclet. |
581 | // A fragment is a section with a code size less than the maximum unwind code size: either 512K bytes, or |
582 | // that specified by COMPlus_JitSplitFunctionSize. In most cases, there will be exactly one fragment. |
583 | |
584 | class UnwindFragmentInfo : public UnwindBase |
585 | { |
586 | friend class UnwindInfo; |
587 | |
588 | static const unsigned UFI_ILLEGAL_OFFSET = 0xFFFFFFFF; |
589 | |
590 | public: |
591 | UnwindFragmentInfo(Compiler* comp, emitLocation* emitLoc, bool hasPhantomProlog); |
592 | |
593 | void FinalizeOffset(); |
594 | |
595 | UNATIVE_OFFSET GetStartOffset() |
596 | { |
597 | assert(ufiStartOffset != UFI_ILLEGAL_OFFSET); |
598 | return ufiStartOffset; |
599 | } |
600 | |
601 | // Add an unwind code. It could be for a prolog, or for the current epilog. |
602 | // A single unwind code can be from 1 to 4 bytes. |
603 | |
604 | void AddCode(BYTE b1) |
605 | { |
606 | assert(ufiInitialized == UFI_INITIALIZED_PATTERN); |
607 | ufiCurCodes->AddCode(b1); |
608 | } |
609 | |
610 | void AddCode(BYTE b1, BYTE b2) |
611 | { |
612 | assert(ufiInitialized == UFI_INITIALIZED_PATTERN); |
613 | ufiCurCodes->AddCode(b1, b2); |
614 | } |
615 | |
616 | void AddCode(BYTE b1, BYTE b2, BYTE b3) |
617 | { |
618 | assert(ufiInitialized == UFI_INITIALIZED_PATTERN); |
619 | ufiCurCodes->AddCode(b1, b2, b3); |
620 | } |
621 | |
622 | void AddCode(BYTE b1, BYTE b2, BYTE b3, BYTE b4) |
623 | { |
624 | assert(ufiInitialized == UFI_INITIALIZED_PATTERN); |
625 | ufiCurCodes->AddCode(b1, b2, b3, b4); |
626 | } |
627 | |
628 | unsigned EpilogCount() |
629 | { |
630 | unsigned count = 0; |
631 | for (UnwindEpilogInfo* pEpi = ufiEpilogList; pEpi != NULL; pEpi = pEpi->epiNext) |
632 | { |
633 | ++count; |
634 | } |
635 | return count; |
636 | } |
637 | |
638 | void AddEpilog(); |
639 | |
640 | void MergeCodes(); |
641 | |
642 | void CopyPrologCodes(UnwindFragmentInfo* pCopyFrom); |
643 | |
644 | void SplitEpilogCodes(emitLocation* emitLoc, UnwindFragmentInfo* pSplitFrom); |
645 | |
646 | bool IsAtFragmentEnd(UnwindEpilogInfo* pEpi); |
647 | |
648 | // Return the full, final size of unwind block. This will be used to allocate memory for |
649 | // the unwind block. This is called before the code offsets are finalized. |
650 | // Size is in bytes. |
651 | ULONG Size() |
652 | { |
653 | assert(ufiSize != 0); |
654 | return ufiSize; |
655 | } |
656 | |
657 | void Finalize(UNATIVE_OFFSET functionLength); |
658 | |
659 | // GetFinalInfo: return a pointer to the final unwind info to hand to the VM, and the size of this info in bytes |
660 | void GetFinalInfo(/* OUT */ BYTE** ppUnwindBlock, /* OUT */ ULONG* pUnwindBlockSize) |
661 | { |
662 | ufiPrologCodes.GetFinalInfo(ppUnwindBlock, pUnwindBlockSize); |
663 | } |
664 | |
665 | void Reserve(BOOL isFunclet, bool isHotCode); |
666 | |
667 | void Allocate( |
668 | CorJitFuncKind funKind, void* pHotCode, void* pColdCode, UNATIVE_OFFSET funcEndOffset, bool isHotCode); |
669 | |
670 | UnwindFragmentInfo() |
671 | { |
672 | } |
673 | ~UnwindFragmentInfo() |
674 | { |
675 | } |
676 | |
677 | #ifdef DEBUG |
678 | void Dump(int indent = 0); |
679 | #endif // DEBUG |
680 | |
681 | private: |
682 | // No copy constructor or operator= |
683 | UnwindFragmentInfo(const UnwindFragmentInfo& info); |
684 | UnwindFragmentInfo& operator=(const UnwindFragmentInfo&); |
685 | |
686 | // |
687 | // Data |
688 | // |
689 | |
690 | UnwindFragmentInfo* ufiNext; // The next fragment |
691 | emitLocation* ufiEmitLoc; // Emitter location for start of fragment |
692 | bool ufiHasPhantomProlog; // Are the prolog codes for a phantom prolog, or a real prolog? |
693 | // (For a phantom prolog, this code fragment represents a fragment in |
694 | // the sense of the unwind info spec; something without a real prolog.) |
695 | UnwindPrologCodes ufiPrologCodes; // The unwind codes for the prolog |
696 | UnwindEpilogInfo ufiEpilogFirst; // In-line the first epilog to avoid separate memory allocation, since |
697 | // almost all functions will have at least one epilog. It is pointed |
698 | // to by ufiEpilogList when the first epilog is added. |
699 | UnwindEpilogInfo* ufiEpilogList; // The head of the epilog list |
700 | UnwindEpilogInfo* ufiEpilogLast; // The last entry in the epilog list (the last epilog added) |
701 | UnwindCodesBase* ufiCurCodes; // Pointer to current unwind codes, either prolog or epilog |
702 | |
703 | // Some data computed when merging the unwind codes, and used when finalizing the |
704 | // unwind block for emission. |
705 | unsigned ufiSize; // The size of the unwind data for this fragment, in bytes |
706 | bool ufiSetEBit; |
707 | bool ufiNeedExtendedCodeWordsEpilogCount; |
708 | unsigned ufiCodeWords; |
709 | unsigned ufiEpilogScopes; |
710 | UNATIVE_OFFSET ufiStartOffset; |
711 | |
712 | #ifdef DEBUG |
713 | |
714 | unsigned ufiNum; |
715 | |
716 | // Are we processing the prolog? The prolog must come first, followed by a (possibly empty) |
717 | // set of epilogs, for this function/funclet. |
718 | bool ufiInProlog; |
719 | |
720 | static const unsigned UFI_INITIALIZED_PATTERN = 0x0FACADE0; // Something unlikely to be the fill pattern for |
721 | // uninitialized memory |
722 | unsigned ufiInitialized; |
723 | |
724 | #endif // DEBUG |
725 | }; |
726 | |
727 | // UnwindInfo: represents all the unwind information for a single function or funclet |
728 | |
729 | class UnwindInfo : public UnwindBase |
730 | { |
731 | public: |
732 | void InitUnwindInfo(Compiler* comp, emitLocation* startLoc, emitLocation* endLoc); |
733 | |
734 | void HotColdSplitCodes(UnwindInfo* puwi); |
735 | |
736 | // The following act on all the fragments that make up the unwind info for this function or funclet. |
737 | |
738 | void Split(); |
739 | |
740 | static void EmitSplitCallback(void* context, emitLocation* emitLoc); |
741 | |
742 | void Reserve(BOOL isFunclet, bool isHotCode); |
743 | |
744 | void Allocate(CorJitFuncKind funKind, void* pHotCode, void* pColdCode, bool isHotCode); |
745 | |
746 | // The following act on the current fragment (the one pointed to by 'uwiFragmentLast'). |
747 | |
748 | // Add an unwind code. It could be for a prolog, or for the current epilog. |
749 | // A single unwind code can be from 1 to 4 bytes. |
750 | |
751 | void AddCode(BYTE b1) |
752 | { |
753 | assert(uwiInitialized == UWI_INITIALIZED_PATTERN); |
754 | assert(uwiFragmentLast != NULL); |
755 | INDEBUG(CheckOpsize(b1)); |
756 | |
757 | uwiFragmentLast->AddCode(b1); |
758 | CaptureLocation(); |
759 | } |
760 | |
761 | void AddCode(BYTE b1, BYTE b2) |
762 | { |
763 | assert(uwiInitialized == UWI_INITIALIZED_PATTERN); |
764 | assert(uwiFragmentLast != NULL); |
765 | INDEBUG(CheckOpsize(b1)); |
766 | |
767 | uwiFragmentLast->AddCode(b1, b2); |
768 | CaptureLocation(); |
769 | } |
770 | |
771 | void AddCode(BYTE b1, BYTE b2, BYTE b3) |
772 | { |
773 | assert(uwiInitialized == UWI_INITIALIZED_PATTERN); |
774 | assert(uwiFragmentLast != NULL); |
775 | INDEBUG(CheckOpsize(b1)); |
776 | |
777 | uwiFragmentLast->AddCode(b1, b2, b3); |
778 | CaptureLocation(); |
779 | } |
780 | |
781 | void AddCode(BYTE b1, BYTE b2, BYTE b3, BYTE b4) |
782 | { |
783 | assert(uwiInitialized == UWI_INITIALIZED_PATTERN); |
784 | assert(uwiFragmentLast != NULL); |
785 | INDEBUG(CheckOpsize(b1)); |
786 | |
787 | uwiFragmentLast->AddCode(b1, b2, b3, b4); |
788 | CaptureLocation(); |
789 | } |
790 | |
791 | void AddEpilog(); |
792 | |
793 | emitLocation* GetCurrentEmitterLocation() |
794 | { |
795 | return uwiCurLoc; |
796 | } |
797 | |
798 | #if defined(_TARGET_ARM_) |
799 | unsigned GetInstructionSize(); |
800 | #endif // defined(_TARGET_ARM_) |
801 | |
802 | void CaptureLocation(); |
803 | |
804 | UnwindInfo() |
805 | { |
806 | } |
807 | ~UnwindInfo() |
808 | { |
809 | } |
810 | |
811 | #ifdef DEBUG |
812 | |
813 | #if defined(_TARGET_ARM_) |
814 | // Given the first byte of the unwind code, check that its opsize matches |
815 | // the last instruction added in the emitter. |
816 | void CheckOpsize(BYTE b1); |
817 | #elif defined(_TARGET_ARM64_) |
818 | void CheckOpsize(BYTE b1) |
819 | { |
820 | } // nothing to do; all instructions are 4 bytes |
821 | #endif // defined(_TARGET_ARM64_) |
822 | |
823 | void Dump(bool isHotCode, int indent = 0); |
824 | |
825 | bool uwiAddingNOP; |
826 | |
827 | #endif // DEBUG |
828 | |
829 | private: |
830 | void AddFragment(emitLocation* emitLoc); |
831 | |
832 | // No copy constructor or operator= |
833 | UnwindInfo(const UnwindInfo& info); |
834 | UnwindInfo& operator=(const UnwindInfo&); |
835 | |
836 | // |
837 | // Data |
838 | // |
839 | |
840 | UnwindFragmentInfo uwiFragmentFirst; // The first fragment is directly here, so it doesn't need to be separately |
841 | // allocated. |
842 | UnwindFragmentInfo* uwiFragmentLast; // The last entry in the fragment list (the last fragment added) |
843 | emitLocation* uwiEndLoc; // End emitter location of this function/funclet (NULL == end of all code) |
844 | emitLocation* uwiCurLoc; // The current emitter location (updated after an unwind code is added), used for NOP |
845 | // padding, and asserts. |
846 | |
847 | #ifdef DEBUG |
848 | |
849 | static const unsigned UWI_INITIALIZED_PATTERN = 0x0FACADE1; // Something unlikely to be the fill pattern for |
850 | // uninitialized memory |
851 | unsigned uwiInitialized; |
852 | |
853 | #endif // DEBUG |
854 | }; |
855 | |
856 | #ifdef DEBUG |
857 | |
858 | // Forward declaration |
859 | void DumpUnwindInfo(Compiler* comp, |
860 | bool isHotCode, |
861 | UNATIVE_OFFSET startOffset, |
862 | UNATIVE_OFFSET endOffset, |
863 | const BYTE* const pHeader, |
864 | ULONG unwindBlockSize); |
865 | |
866 | #endif // DEBUG |
867 | |
868 | #endif // _TARGET_ARMARCH_ |
869 | |