aboutsummaryrefslogtreecommitdiff
path: root/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2010-11-02 17:22:24 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2010-11-02 17:22:24 +0000
commit3ff57094a7d176a759ddb1e1668489d89064f56c (patch)
tree27726bf327a50d838d365cc73ff14d45192d0661 /lib/MC/MCAssembler.cpp
parent8bc9ef77b7e9910fbeb40725dfa49d793158db51 (diff)
Add support for expressions in .sleb/.uleb directives.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118023 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC/MCAssembler.cpp')
-rw-r--r--lib/MC/MCAssembler.cpp133
1 files changed, 96 insertions, 37 deletions
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 9cd0a12c12..1b464ee98f 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -318,6 +318,9 @@ uint64_t MCAssembler::ComputeFragmentSize(MCAsmLayout &Layout,
case MCFragment::FT_Inst:
return cast<MCInstFragment>(F).getInstSize();
+ case MCFragment::FT_LEB:
+ return cast<MCLEBFragment>(F).getSize();
+
case MCFragment::FT_Align: {
const MCAlignFragment &AF = cast<MCAlignFragment>(F);
@@ -514,6 +517,23 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
llvm_unreachable("unexpected inst fragment after lowering");
break;
+ case MCFragment::FT_LEB: {
+ MCLEBFragment &LF = cast<MCLEBFragment>(F);
+
+ // FIXME: It is probably better if we don't call EvaluateAsAbsolute in
+ // here.
+ int64_t Value;
+ LF.getValue().EvaluateAsAbsolute(Value, &Layout);
+ SmallString<32> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ if (LF.isSigned())
+ MCObjectWriter::EncodeSLEB128(Value, OSE);
+ else
+ MCObjectWriter::EncodeULEB128(Value, OSE);
+ OW->WriteBytes(OSE.str());
+ break;
+ }
+
case MCFragment::FT_Org: {
MCOrgFragment &OF = cast<MCOrgFragment>(F);
@@ -781,6 +801,63 @@ bool MCAssembler::FragmentNeedsRelaxation(const MCObjectWriter &Writer,
return false;
}
+bool MCAssembler::RelaxInstruction(const MCObjectWriter &Writer,
+ MCAsmLayout &Layout,
+ MCInstFragment &IF) {
+ if (!FragmentNeedsRelaxation(Writer, &IF, Layout))
+ return false;
+
+ ++stats::RelaxedInstructions;
+
+ // FIXME-PERF: We could immediately lower out instructions if we can tell
+ // they are fully resolved, to avoid retesting on later passes.
+
+ // Relax the fragment.
+
+ MCInst Relaxed;
+ getBackend().RelaxInstruction(IF.getInst(), Relaxed);
+
+ // Encode the new instruction.
+ //
+ // FIXME-PERF: If it matters, we could let the target do this. It can
+ // probably do so more efficiently in many cases.
+ SmallVector<MCFixup, 4> Fixups;
+ SmallString<256> Code;
+ raw_svector_ostream VecOS(Code);
+ getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups);
+ VecOS.flush();
+
+ // Update the instruction fragment.
+ int SlideAmount = Code.size() - IF.getInstSize();
+ IF.setInst(Relaxed);
+ IF.getCode() = Code;
+ IF.getFixups().clear();
+ // FIXME: Eliminate copy.
+ for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
+ IF.getFixups().push_back(Fixups[i]);
+
+ // Update the layout, and remember that we relaxed.
+ Layout.UpdateForSlide(&IF, SlideAmount);
+ return true;
+}
+
+bool MCAssembler::RelaxLEB(const MCObjectWriter &Writer,
+ MCAsmLayout &Layout,
+ MCLEBFragment &LF) {
+ int64_t Value;
+ LF.getValue().EvaluateAsAbsolute(Value, &Layout);
+ SmallString<32> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ if (LF.isSigned())
+ MCObjectWriter::EncodeSLEB128(Value, OSE);
+ else
+ MCObjectWriter::EncodeULEB128(Value, OSE);
+ uint64_t OldSize = LF.getSize();
+ LF.setSize(OSE.GetNumBytesInBuffer());
+ return OldSize != LF.getSize();
+}
+
+
bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
MCAsmLayout &Layout) {
++stats::RelaxationSteps;
@@ -795,43 +872,18 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
for (MCSectionData::iterator it2 = SD.begin(),
ie2 = SD.end(); it2 != ie2; ++it2) {
- // Check if this is an instruction fragment that needs relaxation.
- MCInstFragment *IF = dyn_cast<MCInstFragment>(it2);
- if (!IF || !FragmentNeedsRelaxation(Writer, IF, Layout))
- continue;
-
- ++stats::RelaxedInstructions;
-
- // FIXME-PERF: We could immediately lower out instructions if we can tell
- // they are fully resolved, to avoid retesting on later passes.
-
- // Relax the fragment.
-
- MCInst Relaxed;
- getBackend().RelaxInstruction(IF->getInst(), Relaxed);
-
- // Encode the new instruction.
- //
- // FIXME-PERF: If it matters, we could let the target do this. It can
- // probably do so more efficiently in many cases.
- SmallVector<MCFixup, 4> Fixups;
- SmallString<256> Code;
- raw_svector_ostream VecOS(Code);
- getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups);
- VecOS.flush();
-
- // Update the instruction fragment.
- int SlideAmount = Code.size() - IF->getInstSize();
- IF->setInst(Relaxed);
- IF->getCode() = Code;
- IF->getFixups().clear();
- // FIXME: Eliminate copy.
- for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
- IF->getFixups().push_back(Fixups[i]);
-
- // Update the layout, and remember that we relaxed.
- Layout.UpdateForSlide(IF, SlideAmount);
- WasRelaxed = true;
+ // Check if this is an fragment that needs relaxation.
+ switch(it2->getKind()) {
+ default:
+ break;
+ case MCFragment::FT_Inst:
+ WasRelaxed |= RelaxInstruction(Writer, Layout,
+ *cast<MCInstFragment>(it2));
+ break;
+ case MCFragment::FT_LEB:
+ WasRelaxed |= RelaxLEB(Writer, Layout, *cast<MCLEBFragment>(it2));
+ break;
+ }
}
}
@@ -903,6 +955,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_LEB: OS << "MCLEBFragment"; break;
}
OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
@@ -970,6 +1023,12 @@ void MCFragment::dump() {
<< " LineDelta:" << OF->getLineDelta();
break;
}
+ case MCFragment::FT_LEB: {
+ const MCLEBFragment *LF = cast<MCLEBFragment>(this);
+ OS << "\n ";
+ OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
+ break;
+ }
}
OS << ">";
}