Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
Show First 20 Lines • Show All 1,283 Lines • ▼ Show 20 Lines | void ARMELFStreamer::emitPad(int64_t Offset) { | ||||
// Track the change of the $sp offset | // Track the change of the $sp offset | ||||
SPOffset -= Offset; | SPOffset -= Offset; | ||||
// To squash multiple .pad directives, we should delay the unwind opcode | // To squash multiple .pad directives, we should delay the unwind opcode | ||||
// until the .save, .vsave, .handlerdata, or .fnend directives. | // until the .save, .vsave, .handlerdata, or .fnend directives. | ||||
PendingOffset -= Offset; | PendingOffset -= Offset; | ||||
} | } | ||||
void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, | static std::pair<unsigned, unsigned> | ||||
bool IsVector) { | collectHWRegs(const MCRegisterInfo &MRI, unsigned Idx, | ||||
// Collect the registers in the register list | const SmallVectorImpl<unsigned> &RegList, bool IsVector, | ||||
unsigned Count = 0; | uint32_t &Mask_) { | ||||
uint32_t Mask = 0; | uint32_t Mask = 0; | ||||
const MCRegisterInfo *MRI = getContext().getRegisterInfo(); | unsigned Count = 0; | ||||
for (size_t i = 0; i < RegList.size(); ++i) { | while (Idx > 0) { | ||||
unsigned Reg = MRI->getEncodingValue(RegList[i]); | unsigned Reg = RegList[Idx - 1]; | ||||
if (Reg == ARM::RA_AUTH_CODE) | |||||
break; | |||||
Reg = MRI.getEncodingValue(Reg); | |||||
assert(Reg < (IsVector ? 32U : 16U) && "Register out of range"); | assert(Reg < (IsVector ? 32U : 16U) && "Register out of range"); | ||||
unsigned Bit = (1u << Reg); | unsigned Bit = (1u << Reg); | ||||
if ((Mask & Bit) == 0) { | if ((Mask & Bit) == 0) { | ||||
Mask |= Bit; | Mask |= Bit; | ||||
++Count; | ++Count; | ||||
} | } | ||||
--Idx; | |||||
} | } | ||||
Mask_ = Mask; | |||||
return {Idx, Count}; | |||||
} | |||||
void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, | |||||
bool IsVector) { | |||||
uint32_t Mask; | |||||
unsigned Idx, Count; | |||||
const MCRegisterInfo &MRI = *getContext().getRegisterInfo(); | |||||
// Collect the registers in the register list. Issue unwinding instructions in | |||||
// three parts: ordinary hardware registers, return address authentication | |||||
// code pseudo register, the rest of the registers. The RA PAC is kept in an | |||||
// architectural register (usually r12), but we treat it as a special case in | |||||
// order to distinguish between that register containing RA PAC or a general | |||||
// value. | |||||
Idx = RegList.size(); | |||||
while (Idx > 0) { | |||||
std::tie(Idx, Count) = collectHWRegs(MRI, Idx, RegList, IsVector, Mask); | |||||
if (Count) { | |||||
// Track the change the $sp offset: For the .save directive, the | // Track the change the $sp offset: For the .save directive, the | ||||
// corresponding push instruction will decrease the $sp by (4 * Count). | // corresponding push instruction will decrease the $sp by (4 * Count). | ||||
// For the .vsave directive, the corresponding vpush instruction will | // For the .vsave directive, the corresponding vpush instruction will | ||||
// decrease $sp by (8 * Count). | // decrease $sp by (8 * Count). | ||||
SPOffset -= Count * (IsVector ? 8 : 4); | SPOffset -= Count * (IsVector ? 8 : 4); | ||||
// Emit the opcode | // Emit the opcode | ||||
FlushPendingOffset(); | FlushPendingOffset(); | ||||
if (IsVector) | if (IsVector) | ||||
UnwindOpAsm.EmitVFPRegSave(Mask); | UnwindOpAsm.EmitVFPRegSave(Mask); | ||||
else | else | ||||
UnwindOpAsm.EmitRegSave(Mask); | UnwindOpAsm.EmitRegSave(Mask); | ||||
} else if (Idx > 0 && RegList[Idx - 1] == ARM::RA_AUTH_CODE) { | |||||
--Idx; | |||||
SPOffset -= 4; | |||||
FlushPendingOffset(); | |||||
UnwindOpAsm.EmitRegSave(0); | |||||
} | |||||
} | |||||
} | } | ||||
void ARMELFStreamer::emitUnwindRaw(int64_t Offset, | void ARMELFStreamer::emitUnwindRaw(int64_t Offset, | ||||
const SmallVectorImpl<uint8_t> &Opcodes) { | const SmallVectorImpl<uint8_t> &Opcodes) { | ||||
FlushPendingOffset(); | FlushPendingOffset(); | ||||
SPOffset = SPOffset - Offset; | SPOffset = SPOffset - Offset; | ||||
UnwindOpAsm.EmitRaw(Opcodes); | UnwindOpAsm.EmitRaw(Opcodes); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 42 Lines • Show Last 20 Lines |