Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions llvm/include/llvm/BinaryFormat/SFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ template <endianness E> struct FDEInfo {
Info = ((PAuthKey & 1) << 5) | ((static_cast<uint8_t>(FDE) & 1) << 4) |
(static_cast<uint8_t>(FRE) & 0xf);
}
uint8_t getFuncInfo() const { return Info; }
};

template <endianness E> struct FuncDescEntry {
Expand Down Expand Up @@ -155,6 +156,7 @@ template <endianness E> struct FREInfo {
Info = ((RA & 1) << 7) | ((static_cast<uint8_t>(Sz) & 3) << 5) |
((N & 0xf) << 1) | (static_cast<uint8_t>(Reg) & 1);
}
uint8_t getFREInfo() const { return Info; }
};

template <typename T, endianness E> struct FrameRowEntry {
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/MC/MCAsmBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ class LLVM_ABI MCAsmBackend {
virtual bool relaxAlign(MCFragment &F, unsigned &Size) { return false; }
virtual bool relaxDwarfLineAddr(MCFragment &) const { return false; }
virtual bool relaxDwarfCFA(MCFragment &) const { return false; }
virtual bool relaxSFrameCFA(MCFragment &) const { return false; }

// Defined by linker relaxation targets to possibly emit LEB128 relocations
// and set Value at the relocated location.
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/MC/MCAssembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class MCAssembler {
void relaxBoundaryAlign(MCBoundaryAlignFragment &BF);
void relaxDwarfLineAddr(MCFragment &F);
void relaxDwarfCallFrameFragment(MCFragment &F);
void relaxSFrameFragment(MCFragment &DF);

public:
/// Construct a new assembler instance.
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/MC/MCObjectStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ class MCObjectStreamer : public MCStreamer {
MCSymbol *EndLabel = nullptr) override;
void emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
const MCSymbol *Label, SMLoc Loc);
void emitSFrameCalculateFuncOffset(const MCSymbol *FunCabsel,
const MCSymbol *FREBegin,
MCFragment *FDEFrag, SMLoc Loc);
void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
unsigned Column, bool PrologueEnd, bool IsStmt,
StringRef FileName, SMLoc Loc) override;
Expand Down
14 changes: 14 additions & 0 deletions llvm/include/llvm/MC/MCSFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,30 @@
#ifndef LLVM_MC_MCSFRAME_H
#define LLVM_MC_MCSFRAME_H

#include "llvm/ADT/SmallVector.h"
#include <cstdint>

namespace llvm {

class MCContext;
class MCObjectStreamer;
class MCFragment;

class MCSFrameEmitter {
public:
// Emit the sframe section.
//
// \param Streamer - Emit into this stream.
static void emit(MCObjectStreamer &Streamer);

// Encode the FRE's function offset.
//
// \param C - Context.
// \param Offset - Offset to encode.
// \param Out - Destination of the encoding.
// \param FDEFrag - Frag that specifies the encoding format.
static void encodeFuncOffset(MCContext &C, uint64_t Offset,
SmallVectorImpl<char> &Out, MCFragment *FDEFrag);
};

} // end namespace llvm
Expand Down
25 changes: 25 additions & 0 deletions llvm/include/llvm/MC/MCSection.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class MCFragment {
FT_Org,
FT_Dwarf,
FT_DwarfFrame,
FT_SFrame,
FT_BoundaryAlign,
FT_SymbolId,
FT_CVInlineLines,
Expand Down Expand Up @@ -143,6 +144,12 @@ class MCFragment {
// .loc dwarf directives.
int64_t LineDelta;
} dwarf;
struct {
// This FRE describes unwind info at AddrDelta from function start.
const MCExpr *AddrDelta;
// Fragment that records how many bytes of AddrDelta to emit.
MCFragment *FDEFragment;
} sframe;
} u{};

public:
Expand Down Expand Up @@ -296,6 +303,24 @@ class MCFragment {
assert(Kind == FT_Dwarf);
u.dwarf.LineDelta = LineDelta;
}

//== FT_SFrame functions
const MCExpr &getSFrameAddrDelta() const {
assert(Kind == FT_SFrame);
return *u.sframe.AddrDelta;
}
void setSFrameAddrDelta(const MCExpr *E) {
assert(Kind == FT_SFrame);
u.sframe.AddrDelta = E;
}
MCFragment *getSFrameFDE() const {
assert(Kind == FT_SFrame);
return u.sframe.FDEFragment;
}
void setSFrameFDE(MCFragment *F) {
assert(Kind == FT_SFrame);
u.sframe.FDEFragment = F;
}
};

// MCFragment subclasses do not use the fixed-size part or variable-size tail of
Expand Down
24 changes: 24 additions & 0 deletions llvm/lib/MC/MCAssembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSFrame.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
Expand Down Expand Up @@ -199,6 +200,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const {
case MCFragment::FT_LEB:
case MCFragment::FT_Dwarf:
case MCFragment::FT_DwarfFrame:
case MCFragment::FT_SFrame:
case MCFragment::FT_CVInlineLines:
case MCFragment::FT_CVDefRange:
return F.getSize();
Expand Down Expand Up @@ -399,6 +401,7 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
case MCFragment::FT_LEB:
case MCFragment::FT_Dwarf:
case MCFragment::FT_DwarfFrame:
case MCFragment::FT_SFrame:
case MCFragment::FT_CVInlineLines:
case MCFragment::FT_CVDefRange: {
if (F.getKind() == MCFragment::FT_Data)
Expand Down Expand Up @@ -914,6 +917,24 @@ void MCAssembler::relaxDwarfCallFrameFragment(MCFragment &F) {
F.clearVarFixups();
}

void MCAssembler::relaxSFrameFragment(MCFragment &F) {
assert(F.getKind() == MCFragment::FT_SFrame);
MCContext &C = getContext();
int64_t Value;
bool Abs = F.getSFrameAddrDelta().evaluateAsAbsolute(Value, *this);
if (!Abs) {
C.reportError(F.getSFrameAddrDelta().getLoc(),
"invalid CFI advance_loc expression in sframe");
F.setSFrameAddrDelta(MCConstantExpr::create(0, C));
return;
}

SmallVector<char, 4> Data;
MCSFrameEmitter::encodeFuncOffset(Context, Value, Data, F.getSFrameFDE());
F.setVarContents(Data);
F.clearVarFixups();
}

bool MCAssembler::relaxFragment(MCFragment &F) {
auto Size = computeFragmentSize(F);
switch (F.getKind()) {
Expand All @@ -932,6 +953,9 @@ bool MCAssembler::relaxFragment(MCFragment &F) {
case MCFragment::FT_DwarfFrame:
relaxDwarfCallFrameFragment(F);
break;
case MCFragment::FT_SFrame:
relaxSFrameFragment(F);
break;
case MCFragment::FT_BoundaryAlign:
relaxBoundaryAlign(static_cast<MCBoundaryAlignFragment &>(F));
break;
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/MC/MCFragment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
case MCFragment::FT_Org: OS << "Org"; break;
case MCFragment::FT_Dwarf: OS << "Dwarf"; break;
case MCFragment::FT_DwarfFrame: OS << "DwarfCallFrame"; break;
case MCFragment::FT_SFrame: OS << "SFrame"; break;
case MCFragment::FT_LEB: OS << "LEB"; break;
case MCFragment::FT_BoundaryAlign: OS<<"BoundaryAlign"; break;
case MCFragment::FT_SymbolId: OS << "SymbolId"; break;
Expand All @@ -79,7 +80,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
case MCFragment::FT_Align:
case MCFragment::FT_LEB:
case MCFragment::FT_Dwarf:
case MCFragment::FT_DwarfFrame: {
case MCFragment::FT_DwarfFrame:
case MCFragment::FT_SFrame: {
if (isLinkerRelaxable())
OS << " LinkerRelaxable";
auto Fixed = getContents();
Expand Down Expand Up @@ -129,6 +131,7 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
OS << " LineDelta:" << getDwarfLineDelta();
break;
case MCFragment::FT_DwarfFrame:
case MCFragment::FT_SFrame:
OS << " AddrDelta:";
getDwarfAddrDelta().print(OS, nullptr);
break;
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/MC/MCObjectStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,19 @@ void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
newFragment();
}

void MCObjectStreamer::emitSFrameCalculateFuncOffset(const MCSymbol *FuncBase,
const MCSymbol *FREBegin,
MCFragment *FDEFrag,
SMLoc Loc) {
assert(FuncBase && "No function base address");
assert(FREBegin && "FRE doesn't describe a location");
auto *F = getCurrentFragment();
F->Kind = MCFragment::FT_SFrame;
F->setSFrameAddrDelta(buildSymbolDiff(*this, FREBegin, FuncBase, Loc));
F->setSFrameFDE(FDEFrag);
newFragment();
}

void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
unsigned Line, unsigned Column,
bool PrologueEnd, bool IsStmt,
Expand Down
Loading
Loading