Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:27

0001 //===-- llvm/Support/ARMWinEH.h - Windows on ARM EH Constants ---*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_SUPPORT_ARMWINEH_H
0010 #define LLVM_SUPPORT_ARMWINEH_H
0011 
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/Support/Endian.h"
0014 
0015 namespace llvm {
0016 namespace ARM {
0017 namespace WinEH {
0018 enum class RuntimeFunctionFlag {
0019   RFF_Unpacked,       /// unpacked entry
0020   RFF_Packed,         /// packed entry
0021   RFF_PackedFragment, /// packed entry representing a fragment
0022   RFF_Reserved,       /// reserved
0023 };
0024 
0025 enum class ReturnType {
0026   RT_POP,             /// return via pop {pc} (L flag must be set)
0027   RT_B,               /// 16-bit branch
0028   RT_BW,              /// 32-bit branch
0029   RT_NoEpilogue,      /// no epilogue (fragment)
0030 };
0031 
0032 /// RuntimeFunction - An entry in the table of procedure data (.pdata)
0033 ///
0034 /// This is ARM specific, but the Function Start RVA, Flag and
0035 /// ExceptionInformationRVA fields work identically for ARM64.
0036 ///
0037 ///  3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0038 ///  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
0039 /// +---------------------------------------------------------------+
0040 /// |                     Function Start RVA                        |
0041 /// +-------------------+-+-+-+-----+-+---+---------------------+---+
0042 /// |    Stack Adjust   |C|L|R| Reg |H|Ret|   Function Length   |Flg|
0043 /// +-------------------+-+-+-+-----+-+---+---------------------+---+
0044 ///
0045 /// Flag : 2-bit field with the following meanings:
0046 ///   - 00 = packed unwind data not used; reamining bits point to .xdata record
0047 ///   - 01 = packed unwind data
0048 ///   - 10 = packed unwind data, function assumed to have no prologue; useful
0049 ///          for function fragments that are discontiguous with the start of the
0050 ///          function
0051 ///   - 11 = reserved
0052 /// Function Length : 11-bit field providing the length of the entire function
0053 ///                   in bytes, divided by 2; if the function is greater than
0054 ///                   4KB, a full .xdata record must be used instead
0055 /// Ret : 2-bit field indicating how the function returns
0056 ///   - 00 = return via pop {pc} (the L bit must be set)
0057 ///   - 01 = return via 16-bit branch
0058 ///   - 10 = return via 32-bit branch
0059 ///   - 11 = no epilogue; useful for function fragments that may only contain a
0060 ///          prologue but the epilogue is elsewhere
0061 /// H : 1-bit flag indicating whether the function "homes" the integer parameter
0062 ///     registers (r0-r3), allocating 16-bytes on the stack
0063 /// Reg : 3-bit field indicating the index of the last saved non-volatile
0064 ///       register.  If the R bit is set to 0, then only integer registers are
0065 ///       saved (r4-rN, where N is 4 + Reg).  If the R bit is set to 1, then
0066 ///       only floating-point registers are being saved (d8-dN, where N is
0067 ///       8 + Reg).  The special case of the R bit being set to 1 and Reg equal
0068 ///       to 7 indicates that no registers are saved.
0069 /// R : 1-bit flag indicating whether the non-volatile registers are integer or
0070 ///     floating-point.  0 indicates integer, 1 indicates floating-point.  The
0071 ///     special case of the R-flag being set and Reg being set to 7 indicates
0072 ///     that no non-volatile registers are saved.
0073 /// L : 1-bit flag indicating whether the function saves/restores the link
0074 ///     register (LR)
0075 /// C : 1-bit flag indicating whether the function includes extra instructions
0076 ///     to setup a frame chain for fast walking.  If this flag is set, r11 is
0077 ///     implicitly added to the list of saved non-volatile integer registers.
0078 /// Stack Adjust : 10-bit field indicating the number of bytes of stack that are
0079 ///                allocated for this function.  Only values between 0x000 and
0080 ///                0x3f3 can be directly encoded.  If the value is 0x3f4 or
0081 ///                greater, then the low 4 bits have special meaning as follows:
0082 ///                - Bit 0-1
0083 ///                  indicate the number of words' of adjustment (1-4), minus 1
0084 ///                - Bit 2
0085 ///                  indicates if the prologue combined adjustment into push
0086 ///                - Bit 3
0087 ///                  indicates if the epilogue combined adjustment into pop
0088 ///
0089 /// RESTRICTIONS:
0090 ///   - IF C is SET:
0091 ///     + L flag must be set since frame chaining requires r11 and lr
0092 ///     + r11 must NOT be included in the set of registers described by Reg
0093 ///   - IF Ret is 0:
0094 ///     + L flag must be set
0095 
0096 // NOTE: RuntimeFunction is meant to be a simple class that provides raw access
0097 // to all fields in the structure.  The accessor methods reflect the names of
0098 // the bitfields that they correspond to.  Although some obvious simplifications
0099 // are possible via merging of methods, it would prevent the use of this class
0100 // to fully inspect the contents of the data structure which is particularly
0101 // useful for scenarios such as llvm-readobj to aid in testing.
0102 
0103 class RuntimeFunction {
0104 public:
0105   const support::ulittle32_t BeginAddress;
0106   const support::ulittle32_t UnwindData;
0107 
0108   RuntimeFunction(const support::ulittle32_t *Data)
0109     : BeginAddress(Data[0]), UnwindData(Data[1]) {}
0110 
0111   RuntimeFunction(const support::ulittle32_t BeginAddress,
0112                   const support::ulittle32_t UnwindData)
0113     : BeginAddress(BeginAddress), UnwindData(UnwindData) {}
0114 
0115   RuntimeFunctionFlag Flag() const {
0116     return RuntimeFunctionFlag(UnwindData & 0x3);
0117   }
0118 
0119   uint32_t ExceptionInformationRVA() const {
0120     assert(Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
0121            "unpacked form required for this operation");
0122     return (UnwindData & ~0x3);
0123   }
0124 
0125   uint32_t PackedUnwindData() const {
0126     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0127             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0128            "packed form required for this operation");
0129     return (UnwindData & ~0x3);
0130   }
0131   uint32_t FunctionLength() const {
0132     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0133             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0134            "packed form required for this operation");
0135     return (((UnwindData & 0x00001ffc) >> 2) << 1);
0136   }
0137   ReturnType Ret() const {
0138     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0139             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0140            "packed form required for this operation");
0141     assert(((UnwindData & 0x00006000) || L()) && "L must be set to 1");
0142     return ReturnType((UnwindData & 0x00006000) >> 13);
0143   }
0144   bool H() const {
0145     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0146             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0147            "packed form required for this operation");
0148     return ((UnwindData & 0x00008000) >> 15);
0149   }
0150   uint8_t Reg() const {
0151     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0152             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0153            "packed form required for this operation");
0154     return ((UnwindData & 0x00070000) >> 16);
0155   }
0156   bool R() const {
0157     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0158             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0159            "packed form required for this operation");
0160     return ((UnwindData & 0x00080000) >> 19);
0161   }
0162   bool L() const {
0163     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0164             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0165            "packed form required for this operation");
0166     return ((UnwindData & 0x00100000) >> 20);
0167   }
0168   bool C() const {
0169     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0170             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0171            "packed form required for this operation");
0172     assert(((~UnwindData & 0x00200000) || L()) &&
0173            "L flag must be set, chaining requires r11 and LR");
0174     assert(((~UnwindData & 0x00200000) || (Reg() < 7) || R()) &&
0175            "r11 must not be included in Reg; C implies r11");
0176     return ((UnwindData & 0x00200000) >> 21);
0177   }
0178   uint16_t StackAdjust() const {
0179     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0180             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0181            "packed form required for this operation");
0182     return ((UnwindData & 0xffc00000) >> 22);
0183   }
0184 };
0185 
0186 /// PrologueFolding - pseudo-flag derived from Stack Adjust indicating that the
0187 /// prologue has stack adjustment combined into the push
0188 inline bool PrologueFolding(const RuntimeFunction &RF) {
0189   return RF.StackAdjust() >= 0x3f4 && (RF.StackAdjust() & 0x4);
0190 }
0191 /// Epilogue - pseudo-flag derived from Stack Adjust indicating that the
0192 /// epilogue has stack adjustment combined into the pop
0193 inline bool EpilogueFolding(const RuntimeFunction &RF) {
0194   return RF.StackAdjust() >= 0x3f4 && (RF.StackAdjust() & 0x8);
0195 }
0196 /// StackAdjustment - calculated stack adjustment in words.  The stack
0197 /// adjustment should be determined via this function to account for the special
0198 /// handling the special encoding when the value is >= 0x3f4.
0199 inline uint16_t StackAdjustment(const RuntimeFunction &RF) {
0200   uint16_t Adjustment = RF.StackAdjust();
0201   if (Adjustment >= 0x3f4)
0202     return (Adjustment & 0x3) + 1;
0203   return Adjustment;
0204 }
0205 
0206 /// SavedRegisterMask - Utility function to calculate the set of saved general
0207 /// purpose (r0-r15) and VFP (d0-d31) registers.
0208 std::pair<uint16_t, uint32_t> SavedRegisterMask(const RuntimeFunction &RF,
0209                                                 bool Prologue = true);
0210 
0211 /// RuntimeFunctionARM64 - An entry in the table of procedure data (.pdata)
0212 ///
0213 ///  3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0214 ///  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
0215 /// +---------------------------------------------------------------+
0216 /// |                     Function Start RVA                        |
0217 /// +-----------------+---+-+-------+-----+---------------------+---+
0218 /// |    Frame Size   |CR |H| RegI  |RegF |   Function Length   |Flg|
0219 /// +-----------------+---+-+-------+-----+---------------------+---+
0220 ///
0221 /// See https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
0222 /// for the full reference for this struct.
0223 
0224 class RuntimeFunctionARM64 {
0225 public:
0226   const support::ulittle32_t BeginAddress;
0227   const support::ulittle32_t UnwindData;
0228 
0229   RuntimeFunctionARM64(const support::ulittle32_t *Data)
0230       : BeginAddress(Data[0]), UnwindData(Data[1]) {}
0231 
0232   RuntimeFunctionARM64(const support::ulittle32_t BeginAddress,
0233                        const support::ulittle32_t UnwindData)
0234       : BeginAddress(BeginAddress), UnwindData(UnwindData) {}
0235 
0236   RuntimeFunctionFlag Flag() const {
0237     return RuntimeFunctionFlag(UnwindData & 0x3);
0238   }
0239 
0240   uint32_t ExceptionInformationRVA() const {
0241     assert(Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
0242            "unpacked form required for this operation");
0243     return (UnwindData & ~0x3);
0244   }
0245 
0246   uint32_t PackedUnwindData() const {
0247     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0248             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0249            "packed form required for this operation");
0250     return (UnwindData & ~0x3);
0251   }
0252   uint32_t FunctionLength() const {
0253     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0254             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0255            "packed form required for this operation");
0256     return (((UnwindData & 0x00001ffc) >> 2) << 2);
0257   }
0258   uint8_t RegF() const {
0259     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0260             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0261            "packed form required for this operation");
0262     return ((UnwindData & 0x0000e000) >> 13);
0263   }
0264   uint8_t RegI() const {
0265     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0266             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0267            "packed form required for this operation");
0268     return ((UnwindData & 0x000f0000) >> 16);
0269   }
0270   bool H() const {
0271     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0272             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0273            "packed form required for this operation");
0274     return ((UnwindData & 0x00100000) >> 20);
0275   }
0276   uint8_t CR() const {
0277     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0278             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0279            "packed form required for this operation");
0280     return ((UnwindData & 0x600000) >> 21);
0281   }
0282   uint16_t FrameSize() const {
0283     assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
0284             Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
0285            "packed form required for this operation");
0286     return ((UnwindData & 0xff800000) >> 23);
0287   }
0288 };
0289 
0290 /// ExceptionDataRecord - An entry in the table of exception data (.xdata)
0291 ///
0292 /// The format on ARM is:
0293 ///
0294 ///  3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0295 ///  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
0296 /// +-------+---------+-+-+-+---+-----------------------------------+
0297 /// | C Wrd | Epi Cnt |F|E|X|Ver|         Function Length           |
0298 /// +-------+--------+'-'-'-'---'---+-------------------------------+
0299 /// |    Reserved    |Ex. Code Words|   (Extended Epilogue Count)   |
0300 /// +-------+--------+--------------+-------------------------------+
0301 ///
0302 /// The format on ARM64 is:
0303 ///
0304 ///  3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0305 ///  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
0306 /// +---------+---------+-+-+---+-----------------------------------+
0307 /// |  C Wrd  | Epi Cnt |E|X|Ver|         Function Length           |
0308 /// +---------+------+--'-'-'---'---+-------------------------------+
0309 /// |    Reserved    |Ex. Code Words|   (Extended Epilogue Count)   |
0310 /// +-------+--------+--------------+-------------------------------+
0311 ///
0312 /// Function Length : 18-bit field indicating the total length of the function
0313 ///                   in bytes divided by 2.  If a function is larger than
0314 ///                   512KB, then multiple pdata and xdata records must be used.
0315 /// Vers : 2-bit field describing the version of the remaining structure.  Only
0316 ///        version 0 is currently defined (values 1-3 are not permitted).
0317 /// X : 1-bit field indicating the presence of exception data
0318 /// E : 1-bit field indicating that the single epilogue is packed into the
0319 ///     header
0320 /// F : 1-bit field indicating that the record describes a function fragment
0321 ///     (implies that no prologue is present, and prologue processing should be
0322 ///     skipped) (ARM only)
0323 /// Epilogue Count : 5-bit field that differs in meaning based on the E field.
0324 ///
0325 ///                  If E is set, then this field specifies the index of the
0326 ///                  first unwind code describing the (only) epilogue.
0327 ///
0328 ///                  Otherwise, this field indicates the number of exception
0329 ///                  scopes.  If more than 31 scopes exist, then this field and
0330 ///                  the Code Words field must both be set to 0 to indicate that
0331 ///                  an extension word is required.
0332 /// Code Words : 4-bit (5-bit on ARM64) field that specifies the number of
0333 ///              32-bit words needed to contain all the unwind codes.  If more
0334 ///              than 15 words (31 words on ARM64) are required, then this field
0335 ///              and the Epilogue Count field must both be set to 0 to indicate
0336 ///              that an extension word is required.
0337 /// Extended Epilogue Count, Extended Code Words :
0338 ///                          Valid only if Epilog Count and Code Words are both
0339 ///                          set to 0.  Provides an 8-bit extended code word
0340 ///                          count and 16-bits for epilogue count
0341 ///
0342 /// The epilogue scope format on ARM is:
0343 ///
0344 ///  3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0345 ///  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
0346 /// +----------------+------+---+---+-------------------------------+
0347 /// |  Ep Start Idx  | Cond |Res|       Epilogue Start Offset       |
0348 /// +----------------+------+---+-----------------------------------+
0349 ///
0350 /// The epilogue scope format on ARM64 is:
0351 ///
0352 ///  3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0353 ///  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
0354 /// +-------------------+-------+---+-------------------------------+
0355 /// |  Ep Start Idx     |  Res  |   Epilogue Start Offset           |
0356 /// +-------------------+-------+-----------------------------------+
0357 ///
0358 /// If the E bit is unset in the header, the header is followed by a series of
0359 /// epilogue scopes, which are sorted by their offset.
0360 ///
0361 /// Epilogue Start Offset: 18-bit field encoding the offset of epilogue relative
0362 ///                        to the start of the function in bytes divided by two
0363 /// Res : 2-bit field reserved for future expansion (must be set to 0)
0364 /// Condition : (ARM only) 4-bit field providing the condition under which the
0365 ///             epilogue is executed.  Unconditional epilogues should set this
0366 ///             field to 0xe. Epilogues must be entirely conditional or
0367 ///             unconditional, and in Thumb-2 mode.  The epilogue begins with
0368 ///             the first instruction after the IT opcode.
0369 /// Epilogue Start Index : 8-bit field indicating the byte index of the first
0370 ///                        unwind code describing the epilogue
0371 ///
0372 ///  3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0373 ///  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
0374 /// +---------------+---------------+---------------+---------------+
0375 /// | Unwind Code 3 | Unwind Code 2 | Unwind Code 1 | Unwind Code 0 |
0376 /// +---------------+---------------+---------------+---------------+
0377 ///
0378 /// Following the epilogue scopes, the byte code describing the unwinding
0379 /// follows.  This is padded to align up to word alignment.  Bytes are stored in
0380 /// little endian.
0381 ///
0382 ///  3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0383 ///  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
0384 /// +---------------------------------------------------------------+
0385 /// |           Exception Handler RVA (requires X = 1)              |
0386 /// +---------------------------------------------------------------+
0387 /// |  (possibly followed by data required for exception handler)   |
0388 /// +---------------------------------------------------------------+
0389 ///
0390 /// If the X bit is set in the header, the unwind byte code is followed by the
0391 /// exception handler information.  This constants of one Exception Handler RVA
0392 /// which is the address to the exception handler, followed immediately by the
0393 /// variable length data associated with the exception handler.
0394 ///
0395 
0396 struct EpilogueScope {
0397   const support::ulittle32_t ES;
0398 
0399   EpilogueScope(const support::ulittle32_t Data) : ES(Data) {}
0400   // Same for both ARM and AArch64.
0401   uint32_t EpilogueStartOffset() const {
0402     return (ES & 0x0003ffff);
0403   }
0404 
0405   // Different implementations for ARM and AArch64.
0406   uint8_t ResARM() const {
0407     return ((ES & 0x000c0000) >> 18);
0408   }
0409 
0410   uint8_t ResAArch64() const {
0411     return ((ES & 0x000f0000) >> 18);
0412   }
0413 
0414   // Condition is only applicable to ARM.
0415   uint8_t Condition() const {
0416     return ((ES & 0x00f00000) >> 20);
0417   }
0418 
0419   // Different implementations for ARM and AArch64.
0420   uint8_t EpilogueStartIndexARM() const {
0421     return ((ES & 0xff000000) >> 24);
0422   }
0423 
0424   uint16_t EpilogueStartIndexAArch64() const {
0425     return ((ES & 0xffc00000) >> 22);
0426   }
0427 };
0428 
0429 struct ExceptionDataRecord;
0430 inline size_t HeaderWords(const ExceptionDataRecord &XR);
0431 
0432 struct ExceptionDataRecord {
0433   const support::ulittle32_t *Data;
0434   bool isAArch64;
0435 
0436   ExceptionDataRecord(const support::ulittle32_t *Data, bool isAArch64) :
0437     Data(Data), isAArch64(isAArch64) {}
0438 
0439   uint32_t FunctionLength() const {
0440     return (Data[0] & 0x0003ffff);
0441   }
0442 
0443   uint32_t FunctionLengthInBytesARM() const {
0444     return FunctionLength() << 1;
0445   }
0446 
0447   uint32_t FunctionLengthInBytesAArch64() const {
0448     return FunctionLength() << 2;
0449   }
0450 
0451   uint8_t Vers() const {
0452     return (Data[0] & 0x000C0000) >> 18;
0453   }
0454 
0455   bool X() const {
0456     return ((Data[0] & 0x00100000) >> 20);
0457   }
0458 
0459   bool E() const {
0460     return ((Data[0] & 0x00200000) >> 21);
0461   }
0462 
0463   bool F() const {
0464     assert(!isAArch64 && "Fragments are only supported on ARMv7 WinEH");
0465     return ((Data[0] & 0x00400000) >> 22);
0466   }
0467 
0468   uint16_t EpilogueCount() const {
0469     if (HeaderWords(*this) == 1) {
0470       if (isAArch64)
0471         return (Data[0] & 0x07C00000) >> 22;
0472       return (Data[0] & 0x0f800000) >> 23;
0473     }
0474     return Data[1] & 0x0000ffff;
0475   }
0476 
0477   uint8_t CodeWords() const {
0478     if (HeaderWords(*this) == 1) {
0479       if (isAArch64)
0480         return (Data[0] & 0xf8000000) >> 27;
0481       return (Data[0] & 0xf0000000) >> 28;
0482     }
0483     return (Data[1] & 0x00ff0000) >> 16;
0484   }
0485 
0486   ArrayRef<support::ulittle32_t> EpilogueScopes() const {
0487     assert(E() == 0 && "epilogue scopes are only present when the E bit is 0");
0488     size_t Offset = HeaderWords(*this);
0489     return ArrayRef(&Data[Offset], EpilogueCount());
0490   }
0491 
0492   ArrayRef<uint8_t> UnwindByteCode() const {
0493     const size_t Offset = HeaderWords(*this)
0494                         + (E() ? 0 :  EpilogueCount());
0495     const uint8_t *ByteCode =
0496       reinterpret_cast<const uint8_t *>(&Data[Offset]);
0497     return ArrayRef(ByteCode, CodeWords() * sizeof(uint32_t));
0498   }
0499 
0500   uint32_t ExceptionHandlerRVA() const {
0501     assert(X() && "Exception Handler RVA is only valid if the X bit is set");
0502     return Data[HeaderWords(*this) + (E() ? 0 : EpilogueCount()) + CodeWords()];
0503   }
0504 
0505   uint32_t ExceptionHandlerParameter() const {
0506     assert(X() && "Exception Handler RVA is only valid if the X bit is set");
0507     return Data[HeaderWords(*this) + (E() ? 0 : EpilogueCount()) + CodeWords() +
0508                 1];
0509   }
0510 };
0511 
0512 inline size_t HeaderWords(const ExceptionDataRecord &XR) {
0513   if (XR.isAArch64)
0514     return (XR.Data[0] & 0xffc00000) ? 1 : 2;
0515   return (XR.Data[0] & 0xff800000) ? 1 : 2;
0516 }
0517 }
0518 }
0519 }
0520 
0521 #endif