37 FREInfo<endianness::native> Info;
38 bool CFARegSet =
false;
40 SFrameFRE(
const MCSymbol *Start) : Label(
Start) { Info.Info = 0; }
42 void emitOffset(MCObjectStreamer &S,
FREOffset OffsetSize,
size_t Offset) {
56 void emit(MCObjectStreamer &S,
const MCSymbol *FuncBegin,
57 MCFragment *FDEFrag) {
63 unsigned RegsTracked = 1;
68 Info.setOffsetCount(RegsTracked);
72 Info.setOffsetSize(FREOffset::B1);
74 Info.setOffsetSize(FREOffset::B2);
77 isInt<32>(RAOffset) &&
"Offset too big for sframe");
78 Info.setOffsetSize(FREOffset::B4);
82 Info.setReturnAddressSigned(
false);
88 [[maybe_unused]]
unsigned OffsetsEmitted = 1;
89 emitOffset(S, Info.getOffsetSize(), CFAOffset);
92 emitOffset(S, Info.getOffsetSize(), FPOffset);
96 emitOffset(S, Info.getOffsetSize(), RAOffset);
98 assert(OffsetsEmitted == RegsTracked &&
99 "Didn't emit the right number of offsets");
107 const MCDwarfFrameInfo &DFrame;
117 SFrameFDE(
const MCDwarfFrameInfo &
DF, MCSymbol *FRES)
118 : DFrame(
DF), FREStart(FRES), Frag(nullptr) {}
120 void emit(MCObjectStreamer &S,
const MCSymbol *FRESubSectionStart) {
124 const MCExpr *
V =
C.getAsmInfo()->getExprForFDESymbol(
125 &(*DFrame.Begin),
C.getObjectFileInfo()->getFDEEncoding(), S);
169class SFrameEmitterImpl {
170 MCObjectStreamer &Streamer;
181 int8_t FixedRAOffset;
186 bool setCFARegister(SFrameFRE &FRE,
const MCCFIInstruction &
I) {
187 if (
I.getRegister() == SPReg) {
188 FRE.CFARegSet =
true;
189 FRE.Info.setBaseRegister(BaseReg::SP);
192 if (
I.getRegister() == FPReg) {
193 FRE.CFARegSet =
true;
194 FRE.Info.setBaseRegister(BaseReg::FP);
197 Streamer.getContext().reportWarning(
198 I.getLoc(),
"canonical Frame Address not in stack- or frame-pointer. "
199 "Omitting SFrame unwind info for this function");
203 bool setCFAOffset(SFrameFRE &FRE, SMLoc Loc,
size_t Offset) {
204 if (!
FRE.CFARegSet) {
205 Streamer.getContext().reportWarning(
206 Loc,
"adjusting CFA offset without a base register. "
207 "Omitting SFrame unwind info for this function");
216 bool handleCFI(SFrameFDE &FDE, SFrameFRE &FRE,
const MCCFIInstruction &CFI) {
219 return setCFARegister(FRE, CFI);
222 if (!setCFARegister(FRE, CFI))
242 if (FDE.FREs.size() == 1) {
246 Streamer.getContext().reportWarning(
247 CFI.
getLoc(),
"skipping SFrame FDE; .cfi_remember_state without "
248 "prior SFrame FRE state");
251 FDE.SaveState.push_back(FRE);
256 FRE.FPOffset = FDE.FREs.front().FPOffset;
258 FRE.RAOffset = FDE.FREs.front().RAOffset;
263 assert(!FDE.SaveState.empty() &&
264 "cfi_restore_state without cfi_save_state");
265 FRE = FDE.SaveState.pop_back_val();
278 SFrameEmitterImpl(MCObjectStreamer &Streamer)
279 : Streamer(Streamer), TotalFREs(0) {
280 assert(Streamer.getContext()
284 FDEs.reserve(Streamer.getDwarfFrameInfos().size());
285 SFrameABI = *Streamer.getContext().getObjectFileInfo()->getSFrameABIArch();
287 case ABI::AArch64EndianBig:
288 case ABI::AArch64EndianLittle:
294 case ABI::AMD64EndianLittle:
298 RAReg =
static_cast<unsigned>(INT_MAX);
304 FDESubSectionStart = Streamer.getContext().createTempSymbol();
305 FRESubSectionStart = Streamer.getContext().createTempSymbol();
306 FRESubSectionEnd = Streamer.getContext().createTempSymbol();
309 bool atSameLocation(
const MCSymbol *
Left,
const MCSymbol *
Right) {
310 return Left !=
nullptr &&
Right !=
nullptr &&
311 Left->getFragment() ==
Right->getFragment() &&
315 bool equalIgnoringLocation(
const SFrameFRE &
Left,
const SFrameFRE &
Right) {
316 return Left.CFAOffset ==
Right.CFAOffset &&
318 Left.Info.getFREInfo() ==
Right.Info.getFREInfo() &&
322 void buildSFDE(
const MCDwarfFrameInfo &
DF) {
326 if (atSameLocation(
DF.Begin,
DF.End))
329 SFrameFDE FDE(
DF, Streamer.getContext().createTempSymbol());
336 if (
DF.RAReg != RAReg) {
337 Streamer.getContext().reportWarning(
338 SMLoc(),
"non-default RA register in .cfi_return_column " +
340 ". Omitting SFrame unwind info for this function");
344 SFrameFRE BaseFRE(LastLabel);
346 for (
const auto &CFI :
347 Streamer.getContext().getAsmInfo()->getInitialFrameState())
348 if (!handleCFI(FDE, BaseFRE, CFI))
351 FDE.FREs.push_back(BaseFRE);
353 for (
const auto &CFI :
DF.Instructions) {
361 if (L && !
L->isDefined())
364 SFrameFRE
FRE = FDE.FREs.back();
365 if (!handleCFI(FDE, FRE, CFI))
369 if (equalIgnoringLocation(FRE, FDE.FREs.back()))
374 if (atSameLocation(LastLabel, L))
375 FDE.FREs.back() =
FRE;
377 FDE.FREs.push_back(FRE);
378 FDE.FREs.back().Label =
L;
385 TotalFREs += FDE.FREs.size();
389 void emitPreamble() {
390 Streamer.emitInt16(
Magic);
391 Streamer.emitInt8(
static_cast<uint8_t
>(Version::V2));
392 Streamer.emitInt8(
static_cast<uint8_t
>(Flags::FDEFuncStartPCRel));
398 Streamer.emitInt8(
static_cast<uint8_t
>(SFrameABI));
400 Streamer.emitInt8(0);
402 Streamer.emitInt8(FixedRAOffset);
404 Streamer.emitInt8(0);
406 Streamer.emitInt32(FDEs.size());
408 Streamer.emitInt32(TotalFREs);
411 Streamer.emitAbsoluteSymbolDiff(FRESubSectionEnd, FRESubSectionStart,
414 Streamer.emitInt32(0);
416 Streamer.emitInt32(FDEs.size() *
417 sizeof(sframe::FuncDescEntry<endianness::native>));
421 Streamer.emitLabel(FDESubSectionStart);
422 for (
auto &FDE : FDEs) {
423 FDE.emit(Streamer, FRESubSectionStart);
428 Streamer.emitLabel(FRESubSectionStart);
429 for (
auto &FDE : FDEs) {
430 Streamer.emitLabel(FDE.FREStart);
431 for (
auto &FRE : FDE.FREs)
432 FRE.emit(Streamer, FDE.DFrame.
Begin, FDE.Frag);
434 Streamer.emitLabel(FRESubSectionEnd);
451 SFrameEmitterImpl
Emitter(Streamer);
456 for (
const auto &DFrame : FrameArray)
459 MCSection *Section = Context.getObjectFileInfo()->getSFrameSection();
461 Section->ensureMinAlignment(
Align(8));
463 MCSymbol *SectionStart = Context.createTempSymbol();
474 if (FDEFrag ==
nullptr) {
482 I.setFREType(FREType::Addr1);
484 I.setFREType(FREType::Addr2);
487 I.setFREType(FREType::Addr4);
489 I.setFDEType(FDEType::PCInc);
500 I.Info = FDEData.back();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
dxil DXContainer Global Emitter
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
This file contains data-structure definitions and constants to support unwinding based on ....
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
MCSymbol * getLabel() const
unsigned getRegister() const
OpType getOperation() const
int64_t getOffset() const
Context object for machine code objects.
const MCObjectFileInfo * getObjectFileInfo() const
static MCFixupKind getDataKindForSize(unsigned Size)
Return the generic fixup kind for a value with the given size.
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
MutableArrayRef< char > getVarContents()
std::optional< sframe::ABI > getSFrameABIArch() const
Streaming object file generation interface.
void emitSFrameCalculateFuncOffset(const MCSymbol *FunCabsel, const MCSymbol *FREBegin, MCFragment *FDEFrag, SMLoc Loc)
void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc()) override
Emit a label for Symbol into the current section.
void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) override
Emit the absolute difference between two symbols if possible.
static void emit(MCObjectStreamer &Streamer)
static void encodeFuncOffset(MCContext &C, uint64_t Offset, SmallVectorImpl< char > &Out, MCFragment *FDEFrag)
Instances of this class represent a uniqued identifier for a section in the current translation unit.
MCFragment * getCurrentFragment() const
MCContext & getContext() const
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
void emitInt16(uint64_t Value)
ArrayRef< MCDwarfFrameInfo > getDwarfFrameInfos() const
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
void emitInt32(uint64_t Value)
void emitInt8(uint64_t Value)
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
@ C
The default llvm calling convention, compatible with C.
@ FRE
Reciprocal estimate instructions (unary FP ops).
FREOffset
Size of stack offsets. Bits 6-7 of FREInfo.Info.
FREType
SFrame FRE Types. Bits 0-3 of FuncDescEntry.Info.
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
This is an optimization pass for GlobalISel generic memory operations.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
This struct is a compact representation of a valid (non-zero power of two) alignment.