Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer const reference to non-nullable pointer

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every single MCObjectStreamer::emit* that takes an MCSymbol takes it by pointer, as does every emit* function in the superclass MCStreamer. And all the other subclasses. I think I should leave this as is to match the surrounding code. Hopefully a broad cleanup will migrate everything.

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