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
6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7XX XX
8XX Unwind Info XX
9XX XX
10XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
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_)
23const unsigned MAX_PROLOG_SIZE_BYTES = 40;
24const 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_)
31const unsigned MAX_PROLOG_SIZE_BYTES = 100;
32const 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
53class emitLocation;
54
55//
56// Forward declarations of classes defined in this file
57//
58
59class UnwindCodesBase;
60class UnwindPrologCodes;
61class UnwindEpilogCodes;
62class UnwindEpilogInfo;
63class UnwindFragmentInfo;
64class UnwindInfo;
65
66// UnwindBase: A base class shared by the the unwind classes that require
67// a Compiler* for memory allocation.
68
69class UnwindBase
70{
71protected:
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
115class UnwindCodesBase
116{
117public:
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
152class 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
163public:
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
276private:
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
316class 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
322public:
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
448private:
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
480class UnwindEpilogInfo : public UnwindBase
481{
482 friend class UnwindFragmentInfo;
483
484 static const unsigned EPI_ILLEGAL_OFFSET = 0xFFFFFFFF;
485
486public:
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
561private:
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
584class UnwindFragmentInfo : public UnwindBase
585{
586 friend class UnwindInfo;
587
588 static const unsigned UFI_ILLEGAL_OFFSET = 0xFFFFFFFF;
589
590public:
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
681private:
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
729class UnwindInfo : public UnwindBase
730{
731public:
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
829private:
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
859void 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