aboutsummaryrefslogtreecommitdiff
path: root/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/MCAssembler.cpp40
-rw-r--r--lib/MC/MCDwarf.cpp34
-rw-r--r--lib/MC/MCObjectStreamer.cpp49
3 files changed, 101 insertions, 22 deletions
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 030ff98739..5b291490f7 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -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,9 +752,14 @@ bool MCAssembler::LayoutSectionOnce(MCAsmLayout &Layout,
relaxedFrag = RelaxDwarfLineAddr(Layout,
*cast<MCDwarfLineAddrFragment>(it2));
break;
- case MCFragment::FT_LEB:
- relaxedFrag = RelaxLEB(Layout, *cast<MCLEBFragment>(it2));
- break;
+ case MCFragment::FT_DwarfFrame:
+ relaxedFrag =
+ RelaxDwarfCallFrameFragment(Layout,
+ *cast<MCDwarfCallFrameFragment>(it2));
+ break;
+ case MCFragment::FT_LEB:
+ relaxedFrag = RelaxLEB(Layout, *cast<MCLEBFragment>(it2));
+ break;
}
// Update the layout, and remember that we relaxed.
if (relaxedFrag && !FirstInvalidFragment)
@@ -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 ";
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index 6e59a58b04..08d327ae8b 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -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);
+ }
+}
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index af102ecf78..b428e8747b 100644
--- a/lib/MC/MCObjectStreamer.cpp
+++ b/lib/MC/MCObjectStreamer.cpp
@@ -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());