28 class UnwindOpcodeStreamer {
37 void EmitByte(uint8_t elem) {
39 Pos = (((Pos ^ 0x3u) + 1) ^ 0x3u);
43 void EmitSize(
size_t Size) {
44 size_t SizeInWords = (
Size + 3) / 4;
45 assert(SizeInWords <= 0x100u &&
46 "Only 256 additional words are allowed for unwind opcodes");
47 EmitByte(
static_cast<uint8_t
>(SizeInWords - 1));
51 void EmitPersonalityIndex(
unsigned PI) {
53 "Invalid personality prefix");
58 void FillFinishOpcode() {
59 while (Pos < Vec.
size())
74 if (RegSave & (1u << 4)) {
82 Mask &= ~(0xffffffe0u <<
Range);
85 uint32_t UnmaskedReg = RegSave & 0xfff0u & (~Mask);
86 if (UnmaskedReg == 0u) {
90 }
else if (UnmaskedReg == (1u << 14)) {
98 if ((RegSave & 0xfff0u) != 0)
102 if ((RegSave & 0x000fu) != 0)
110 for (
uint32_t Regs : {VFPRegSave & 0xffff0000u, VFPRegSave & 0x0000ffffu}) {
115 auto RangeLSB = RangeMSB - RangeLen;
117 int Opcode = RangeLSB >= 16
121 EmitInt16(Opcode | ((RangeLSB % 16) << 4) | (RangeLen - 1));
124 Regs &= ~(-1u << RangeLSB);
140 emitBytes(Buff, ULEBSize + 1);
147 static_cast<uint8_t
>((
Offset - 4) >> 2));
154 static_cast<uint8_t
>(((-
Offset) - 4) >> 2));
160 UnwindOpcodeStreamer OpStreamer(Result);
162 if (HasPersonality) {
165 size_t TotalSize = Ops.
size() + 1;
166 size_t RoundUpSize = (TotalSize + 3) / 4 * 4;
167 Result.resize(RoundUpSize);
168 OpStreamer.EmitSize(RoundUpSize);
176 assert(Ops.
size() <= 3 &&
"too many opcodes for __aeabi_unwind_cpp_pr0");
178 OpStreamer.EmitPersonalityIndex(PersonalityIndex);
181 size_t TotalSize = Ops.
size() + 2;
182 size_t RoundUpSize = (TotalSize + 3) / 4 * 4;
183 Result.resize(RoundUpSize);
184 OpStreamer.EmitPersonalityIndex(PersonalityIndex);
185 OpStreamer.EmitSize(RoundUpSize);
190 for (
size_t i = OpBegins.
size() - 1; i > 0; --i)
191 for (
size_t j = OpBegins[i - 1], end = OpBegins[i]; j < end; ++j)
192 OpStreamer.EmitByte(Ops[j]);
195 OpStreamer.FillFinishOpcode();
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the C++20 <bit> header.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void EmitSetSP(uint16_t Reg)
Emit unwind opcodes to copy address from source register to $sp.
void EmitVFPRegSave(uint32_t VFPRegSave)
Emit unwind opcodes for .vsave directives.
void EmitRegSave(uint32_t RegSave)
Emit unwind opcodes for .save directives.
void EmitSPOffset(int64_t Offset)
Emit unwind opcodes to add $sp with an offset.
void Reset()
Reset the unwind opcode assembler.
void Finalize(unsigned &PersonalityIndex, SmallVectorImpl< uint8_t > &Result)
Finalize the unwind opcode sequence for emitBytes()
@ UNWIND_OPCODE_POP_REG_RANGE_R4
@ UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D16
@ UNWIND_OPCODE_POP_REG_MASK
@ UNWIND_OPCODE_INC_VSP_ULEB128
@ UNWIND_OPCODE_POP_REG_RANGE_R4_R14
@ UNWIND_OPCODE_POP_RA_AUTH_CODE
@ UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD
@ UNWIND_OPCODE_POP_REG_MASK_R4
This is an optimization pass for GlobalISel generic memory operations.
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
int countl_one(T Value)
Count the number of ones from the most significant bit to the first zero bit.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.