mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-13 14:47:00 +00:00
Relax address updates in the eh_frame section.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122591 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5bba084253
commit
245a1e2041
@ -52,6 +52,7 @@ public:
|
||||
FT_Inst,
|
||||
FT_Org,
|
||||
FT_Dwarf,
|
||||
FT_DwarfFrame,
|
||||
FT_LEB
|
||||
};
|
||||
|
||||
@ -369,7 +370,7 @@ class MCDwarfLineAddrFragment : public MCFragment {
|
||||
|
||||
public:
|
||||
MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta,
|
||||
MCSectionData *SD = 0)
|
||||
MCSectionData *SD)
|
||||
: MCFragment(FT_Dwarf, SD),
|
||||
LineDelta(_LineDelta), AddrDelta(&_AddrDelta) { Contents.push_back(0); }
|
||||
|
||||
@ -391,6 +392,34 @@ public:
|
||||
static bool classof(const MCDwarfLineAddrFragment *) { return true; }
|
||||
};
|
||||
|
||||
class MCDwarfCallFrameFragment : public MCFragment {
|
||||
/// AddrDelta - The expression for the difference of the two symbols that
|
||||
/// make up the address delta between two .cfi_* dwarf directives.
|
||||
const MCExpr *AddrDelta;
|
||||
|
||||
SmallString<8> Contents;
|
||||
|
||||
public:
|
||||
MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, MCSectionData *SD)
|
||||
: MCFragment(FT_DwarfFrame, SD),
|
||||
AddrDelta(&_AddrDelta) { Contents.push_back(0); }
|
||||
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
const MCExpr &getAddrDelta() const { return *AddrDelta; }
|
||||
|
||||
SmallString<8> &getContents() { return Contents; }
|
||||
const SmallString<8> &getContents() const { return Contents; }
|
||||
|
||||
/// @}
|
||||
|
||||
static bool classof(const MCFragment *F) {
|
||||
return F->getKind() == MCFragment::FT_DwarfFrame;
|
||||
}
|
||||
static bool classof(const MCDwarfCallFrameFragment *) { return true; }
|
||||
};
|
||||
|
||||
// FIXME: Should this be a separate class, or just merged into MCSection? Since
|
||||
// we anticipate the fast path being through an MCAssembler, the only reason to
|
||||
// keep it out is for API abstraction.
|
||||
@ -705,6 +734,8 @@ private:
|
||||
bool RelaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF);
|
||||
|
||||
bool RelaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF);
|
||||
bool RelaxDwarfCallFrameFragment(MCAsmLayout &Layout,
|
||||
MCDwarfCallFrameFragment &DF);
|
||||
|
||||
/// FinishLayout - Finalize a layout, including fragment lowering.
|
||||
void FinishLayout(MCAsmLayout &Layout);
|
||||
|
@ -25,6 +25,7 @@
|
||||
namespace llvm {
|
||||
class MachineMove;
|
||||
class MCContext;
|
||||
class MCExpr;
|
||||
class MCSection;
|
||||
class MCSectionData;
|
||||
class MCStreamer;
|
||||
@ -245,6 +246,8 @@ namespace llvm {
|
||||
// This emits the frame info section.
|
||||
//
|
||||
static void Emit(MCStreamer &streamer);
|
||||
static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta);
|
||||
static void EncodeAdvanceLoc(uint64_t AddrDelta, raw_ostream &OS);
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
|
@ -71,6 +71,8 @@ public:
|
||||
virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta,
|
||||
const MCSymbol *LastLabel,
|
||||
const MCSymbol *Label);
|
||||
virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
|
||||
const MCSymbol *Label);
|
||||
virtual void Finish();
|
||||
|
||||
/// @}
|
||||
|
@ -386,6 +386,10 @@ namespace llvm {
|
||||
const MCSymbol *LastLabel,
|
||||
const MCSymbol *Label) = 0;
|
||||
|
||||
virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
|
||||
const MCSymbol *Label) {
|
||||
}
|
||||
|
||||
void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label,
|
||||
int PointerSize);
|
||||
|
||||
|
@ -323,6 +323,8 @@ uint64_t MCAssembler::ComputeFragmentSize(const MCAsmLayout &Layout,
|
||||
|
||||
case MCFragment::FT_Dwarf:
|
||||
return cast<MCDwarfLineAddrFragment>(F).getContents().size();
|
||||
case MCFragment::FT_DwarfFrame:
|
||||
return cast<MCDwarfCallFrameFragment>(F).getContents().size();
|
||||
}
|
||||
|
||||
assert(0 && "invalid fragment kind");
|
||||
@ -453,6 +455,11 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
OW->WriteBytes(OF.getContents().str());
|
||||
break;
|
||||
}
|
||||
case MCFragment::FT_DwarfFrame: {
|
||||
const MCDwarfCallFrameFragment &CF = cast<MCDwarfCallFrameFragment>(F);
|
||||
OW->WriteBytes(CF.getContents().str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(OW->getStream().tell() - Start == FragmentSize);
|
||||
@ -712,6 +719,21 @@ bool MCAssembler::RelaxDwarfLineAddr(MCAsmLayout &Layout,
|
||||
return OldSize != Data.size();
|
||||
}
|
||||
|
||||
bool MCAssembler::RelaxDwarfCallFrameFragment(MCAsmLayout &Layout,
|
||||
MCDwarfCallFrameFragment &DF) {
|
||||
int64_t AddrDelta = 0;
|
||||
uint64_t OldSize = DF.getContents().size();
|
||||
bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout);
|
||||
(void)IsAbs;
|
||||
assert(IsAbs);
|
||||
SmallString<8> &Data = DF.getContents();
|
||||
Data.clear();
|
||||
raw_svector_ostream OSE(Data);
|
||||
MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OSE);
|
||||
OSE.flush();
|
||||
return OldSize != Data.size();
|
||||
}
|
||||
|
||||
bool MCAssembler::LayoutSectionOnce(MCAsmLayout &Layout,
|
||||
MCSectionData &SD) {
|
||||
MCFragment *FirstInvalidFragment = NULL;
|
||||
@ -730,6 +752,11 @@ bool MCAssembler::LayoutSectionOnce(MCAsmLayout &Layout,
|
||||
relaxedFrag = RelaxDwarfLineAddr(Layout,
|
||||
*cast<MCDwarfLineAddrFragment>(it2));
|
||||
break;
|
||||
case MCFragment::FT_DwarfFrame:
|
||||
relaxedFrag =
|
||||
RelaxDwarfCallFrameFragment(Layout,
|
||||
*cast<MCDwarfCallFrameFragment>(it2));
|
||||
break;
|
||||
case MCFragment::FT_LEB:
|
||||
relaxedFrag = RelaxLEB(Layout, *cast<MCLEBFragment>(it2));
|
||||
break;
|
||||
@ -789,6 +816,7 @@ void MCFragment::dump() {
|
||||
case MCFragment::FT_Inst: OS << "MCInstFragment"; break;
|
||||
case MCFragment::FT_Org: OS << "MCOrgFragment"; break;
|
||||
case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
|
||||
case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
|
||||
case MCFragment::FT_LEB: OS << "MCLEBFragment"; break;
|
||||
}
|
||||
|
||||
@ -855,6 +883,12 @@ void MCFragment::dump() {
|
||||
<< " LineDelta:" << OF->getLineDelta();
|
||||
break;
|
||||
}
|
||||
case MCFragment::FT_DwarfFrame: {
|
||||
const MCDwarfCallFrameFragment *CF = cast<MCDwarfCallFrameFragment>(this);
|
||||
OS << "\n ";
|
||||
OS << " AddrDelta:" << CF->getAddrDelta();
|
||||
break;
|
||||
}
|
||||
case MCFragment::FT_LEB: {
|
||||
const MCLEBFragment *LF = cast<MCLEBFragment>(this);
|
||||
OS << "\n ";
|
||||
|
@ -460,12 +460,7 @@ static void EmitFrameMoves(MCStreamer &streamer,
|
||||
if (BaseLabel && Label) {
|
||||
MCSymbol *ThisSym = Label;
|
||||
if (ThisSym != BaseLabel) {
|
||||
// FIXME: We should relax this instead of using a DW_CFA_advance_loc4
|
||||
// for every address change!
|
||||
streamer.EmitIntValue(dwarf::DW_CFA_advance_loc4, 1);
|
||||
const MCExpr *Length = MakeStartMinusEndExpr(streamer, *BaseLabel,
|
||||
*ThisSym, 0);
|
||||
streamer.EmitValue(Length, 4);
|
||||
streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym);
|
||||
BaseLabel = ThisSym;
|
||||
}
|
||||
}
|
||||
@ -748,3 +743,30 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &streamer) {
|
||||
if (fdeEnd)
|
||||
streamer.EmitLabel(fdeEnd);
|
||||
}
|
||||
|
||||
void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer,
|
||||
uint64_t AddrDelta) {
|
||||
SmallString<256> Tmp;
|
||||
raw_svector_ostream OS(Tmp);
|
||||
MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS);
|
||||
Streamer.EmitBytes(OS.str(), /*AddrSpace=*/0);
|
||||
}
|
||||
|
||||
void MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta,
|
||||
raw_ostream &OS) {
|
||||
// FIXME: Assumes the code alignment factor is 1.
|
||||
if (isUIntN(6, AddrDelta)) {
|
||||
uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
|
||||
OS << Opcode;
|
||||
} else if (isUInt<8>(AddrDelta)) {
|
||||
OS << uint8_t(dwarf::DW_CFA_advance_loc1);
|
||||
OS << uint8_t(AddrDelta);
|
||||
} else if (isUInt<16>(AddrDelta)) {
|
||||
OS << uint8_t(dwarf::DW_CFA_advance_loc2);
|
||||
OS << uint16_t(AddrDelta);
|
||||
} else {
|
||||
assert(isUInt<32>(AddrDelta));
|
||||
OS << uint8_t(dwarf::DW_CFA_advance_loc4);
|
||||
OS << uint32_t(AddrDelta);
|
||||
}
|
||||
}
|
||||
|
@ -190,6 +190,28 @@ void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) {
|
||||
getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, IF->getFixups());
|
||||
}
|
||||
|
||||
static const MCExpr *BuildSymbolDiff(MCContext &Context,
|
||||
const MCSymbol *A, const MCSymbol *B) {
|
||||
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
|
||||
const MCExpr *ARef =
|
||||
MCSymbolRefExpr::Create(A, Variant, Context);
|
||||
const MCExpr *BRef =
|
||||
MCSymbolRefExpr::Create(B, Variant, Context);
|
||||
const MCExpr *AddrDelta =
|
||||
MCBinaryExpr::Create(MCBinaryExpr::Sub, ARef, BRef, Context);
|
||||
return AddrDelta;
|
||||
}
|
||||
|
||||
static const MCExpr *ForceExpAbs(MCObjectStreamer *Streamer,
|
||||
MCContext &Context, const MCExpr* Expr) {
|
||||
if (Context.getAsmInfo().hasAggressiveSymbolFolding())
|
||||
return Expr;
|
||||
|
||||
MCSymbol *ABS = Context.CreateTempSymbol();
|
||||
Streamer->EmitAssignment(ABS, Expr);
|
||||
return MCSymbolRefExpr::Create(ABS, Context);
|
||||
}
|
||||
|
||||
void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
|
||||
const MCSymbol *LastLabel,
|
||||
const MCSymbol *Label) {
|
||||
@ -198,27 +220,28 @@ void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
|
||||
EmitDwarfSetLineAddr(LineDelta, Label, PointerSize);
|
||||
return;
|
||||
}
|
||||
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
|
||||
const MCExpr *LabelRef =
|
||||
MCSymbolRefExpr::Create(Label, Variant, getContext());
|
||||
const MCExpr *LastLabelRef =
|
||||
MCSymbolRefExpr::Create(LastLabel, Variant, getContext());
|
||||
const MCExpr *AddrDelta =
|
||||
MCBinaryExpr::Create(MCBinaryExpr::Sub, LabelRef, LastLabelRef,
|
||||
getContext());
|
||||
const MCExpr *AddrDelta = BuildSymbolDiff(getContext(), Label, LastLabel);
|
||||
int64_t Res;
|
||||
if (AddrDelta->EvaluateAsAbsolute(Res, getAssembler())) {
|
||||
MCDwarfLineAddr::Emit(this, LineDelta, Res);
|
||||
return;
|
||||
}
|
||||
if (!getContext().getAsmInfo().hasAggressiveSymbolFolding()) {
|
||||
MCSymbol *ABS = getContext().CreateTempSymbol();
|
||||
EmitAssignment(ABS, AddrDelta);
|
||||
AddrDelta = MCSymbolRefExpr::Create(ABS, getContext());
|
||||
}
|
||||
AddrDelta = ForceExpAbs(this, getContext(), AddrDelta);
|
||||
new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, getCurrentSectionData());
|
||||
}
|
||||
|
||||
void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
|
||||
const MCSymbol *Label) {
|
||||
const MCExpr *AddrDelta = BuildSymbolDiff(getContext(), Label, LastLabel);
|
||||
int64_t Res;
|
||||
if (AddrDelta->EvaluateAsAbsolute(Res, getAssembler())) {
|
||||
MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res);
|
||||
return;
|
||||
}
|
||||
AddrDelta = ForceExpAbs(this, getContext(), AddrDelta);
|
||||
new MCDwarfCallFrameFragment(*AddrDelta, getCurrentSectionData());
|
||||
}
|
||||
|
||||
void MCObjectStreamer::EmitValueToOffset(const MCExpr *Offset,
|
||||
unsigned char Value) {
|
||||
new MCOrgFragment(*Offset, Value, getCurrentSectionData());
|
||||
|
@ -10,21 +10,18 @@ f:
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
// FIXME: This is a correct but really inefficient coding since
|
||||
// we use a CFA_advance_loc4 for every address change!
|
||||
|
||||
// CHECK: # Section 0x00000004
|
||||
// CHECK-NEXT: (('sh_name', 0x00000012) # '.eh_frame'
|
||||
// CHECK-NEXT: ('sh_type', 0x00000001)
|
||||
// CHECK-NEXT: ('sh_flags', 0x00000002)
|
||||
// CHECK-NEXT: ('sh_addr', 0x00000000)
|
||||
// CHECK-NEXT: ('sh_offset', 0x00000050)
|
||||
// CHECK-NEXT: ('sh_size', 0x00000038)
|
||||
// CHECK-NEXT: ('sh_size', 0x00000030)
|
||||
// CHECK-NEXT: ('sh_link', 0x00000000)
|
||||
// CHECK-NEXT: ('sh_info', 0x00000000)
|
||||
// CHECK-NEXT: ('sh_addralign', 0x00000008)
|
||||
// CHECK-NEXT: ('sh_entsize', 0x00000000)
|
||||
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 1c000000 1c000000 00000000 0a000000 00040400 00000e10 04050000 000e0800')
|
||||
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 0a000000 00440e10 450e0800')
|
||||
// CHECK-NEXT: ),
|
||||
|
||||
// CHECK: # Section 0x00000008
|
||||
@ -32,7 +29,7 @@ f:
|
||||
// CHECK-NEXT: ('sh_type', 0x00000004)
|
||||
// CHECK-NEXT: ('sh_flags', 0x00000000)
|
||||
// CHECK-NEXT: ('sh_addr', 0x00000000)
|
||||
// CHECK-NEXT: ('sh_offset', 0x00000168)
|
||||
// CHECK-NEXT: ('sh_offset', 0x00000160)
|
||||
// CHECK-NEXT: ('sh_size', 0x00000018)
|
||||
// CHECK-NEXT: ('sh_link', 0x00000006)
|
||||
// CHECK-NEXT: ('sh_info', 0x00000004)
|
||||
|
Loading…
Reference in New Issue
Block a user