aboutsummaryrefslogtreecommitdiff
path: root/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC/MCAssembler.cpp')
-rw-r--r--lib/MC/MCAssembler.cpp58
1 files changed, 53 insertions, 5 deletions
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 5fdc57ad30..e5d4995e16 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -38,6 +38,8 @@ STATISTIC(EmittedRelaxableFragments,
"Number of emitted assembler fragments - relaxable");
STATISTIC(EmittedDataFragments,
"Number of emitted assembler fragments - data");
+STATISTIC(EmittedCompactEncodedInstFragments,
+ "Number of emitted assembler fragments - compact encoded inst");
STATISTIC(EmittedAlignFragments,
"Number of emitted assembler fragments - align");
STATISTIC(EmittedFillFragments,
@@ -222,6 +224,11 @@ MCEncodedFragment::~MCEncodedFragment() {
/* *** */
+MCEncodedFragmentWithFixups::~MCEncodedFragmentWithFixups() {
+}
+
+/* *** */
+
MCSectionData::MCSectionData() : Section(0) {}
MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
@@ -388,6 +395,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
switch (F.getKind()) {
case MCFragment::FT_Data:
case MCFragment::FT_Relaxable:
+ case MCFragment::FT_CompactEncodedInst:
return cast<MCEncodedFragment>(F).getContents().size();
case MCFragment::FT_Fill:
return cast<MCFillFragment>(F).getSize();
@@ -458,7 +466,7 @@ void MCAsmLayout::layoutFragment(MCFragment *F) {
//
//
// BundlePadding
- // |||
+ // |||
// -------------------------------------
// Prev |##########| F |
// -------------------------------------
@@ -497,6 +505,9 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment &F) {
MCObjectWriter *OW = &Asm.getWriter();
+ // FIXME: Embed in fragments instead?
+ uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F);
+
// Should NOP padding be written out before this fragment?
unsigned BundlePadding = F.getBundlePadding();
if (BundlePadding > 0) {
@@ -505,6 +516,22 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
assert(F.hasInstructions() &&
"Writing bundle padding for a fragment without instructions");
+ unsigned TotalLength = BundlePadding + static_cast<unsigned>(FragmentSize);
+ if (F.alignToBundleEnd() && TotalLength > Asm.getBundleAlignSize()) {
+ // If the padding itself crosses a bundle boundary, it must be emitted
+ // in 2 pieces, since even nop instructions must not cross boundaries.
+ // v--------------v <- BundleAlignSize
+ // v---------v <- BundlePadding
+ // ----------------------------
+ // | Prev |####|####| F |
+ // ----------------------------
+ // ^-------------------^ <- TotalLength
+ unsigned DistanceToBoundary = TotalLength - Asm.getBundleAlignSize();
+ if (!Asm.getBackend().writeNopData(DistanceToBoundary, OW))
+ report_fatal_error("unable to write NOP sequence of " +
+ Twine(DistanceToBoundary) + " bytes");
+ BundlePadding -= DistanceToBoundary;
+ }
if (!Asm.getBackend().writeNopData(BundlePadding, OW))
report_fatal_error("unable to write NOP sequence of " +
Twine(BundlePadding) + " bytes");
@@ -517,8 +544,6 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
++stats::EmittedFragments;
- // FIXME: Embed in fragments instead?
- uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F);
switch (F.getKind()) {
case MCFragment::FT_Align: {
++stats::EmittedAlignFragments;
@@ -570,6 +595,11 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
writeFragmentContents(F, OW);
break;
+ case MCFragment::FT_CompactEncodedInst:
+ ++stats::EmittedCompactEncodedInstFragments;
+ writeFragmentContents(F, OW);
+ break;
+
case MCFragment::FT_Fill: {
++stats::EmittedFillFragments;
MCFillFragment &FF = cast<MCFillFragment>(F);
@@ -742,9 +772,10 @@ void MCAssembler::Finish() {
for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) {
for (MCSectionData::iterator it2 = it->begin(),
ie2 = it->end(); it2 != ie2; ++it2) {
- MCEncodedFragment *F = dyn_cast<MCEncodedFragment>(it2);
+ MCEncodedFragmentWithFixups *F =
+ dyn_cast<MCEncodedFragmentWithFixups>(it2);
if (F) {
- for (MCEncodedFragment::fixup_iterator it3 = F->fixup_begin(),
+ for (MCEncodedFragmentWithFixups::fixup_iterator it3 = F->fixup_begin(),
ie3 = F->fixup_end(); it3 != ie3; ++it3) {
MCFixup &Fixup = *it3;
uint64_t FixedValue = handleFixup(Layout, *F, Fixup);
@@ -954,6 +985,8 @@ void MCFragment::dump() {
switch (getKind()) {
case MCFragment::FT_Align: OS << "MCAlignFragment"; break;
case MCFragment::FT_Data: OS << "MCDataFragment"; break;
+ case MCFragment::FT_CompactEncodedInst:
+ OS << "MCCompactEncodedInstFragment"; break;
case MCFragment::FT_Fill: OS << "MCFillFragment"; break;
case MCFragment::FT_Relaxable: OS << "MCRelaxableFragment"; break;
case MCFragment::FT_Org: OS << "MCOrgFragment"; break;
@@ -1001,6 +1034,19 @@ void MCFragment::dump() {
}
break;
}
+ case MCFragment::FT_CompactEncodedInst: {
+ const MCCompactEncodedInstFragment *CEIF =
+ cast<MCCompactEncodedInstFragment>(this);
+ OS << "\n ";
+ OS << " Contents:[";
+ const SmallVectorImpl<char> &Contents = CEIF->getContents();
+ for (unsigned i = 0, e = Contents.size(); i != e; ++i) {
+ if (i) OS << ",";
+ OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF);
+ }
+ OS << "] (" << Contents.size() << " bytes)";
+ break;
+ }
case MCFragment::FT_Fill: {
const MCFillFragment *FF = cast<MCFillFragment>(this);
OS << " Value:" << FF->getValue() << " ValueSize:" << FF->getValueSize()
@@ -1094,7 +1140,9 @@ void MCAssembler::dump() {
// anchors for MC*Fragment vtables
void MCEncodedFragment::anchor() { }
+void MCEncodedFragmentWithFixups::anchor() { }
void MCDataFragment::anchor() { }
+void MCCompactEncodedInstFragment::anchor() { }
void MCRelaxableFragment::anchor() { }
void MCAlignFragment::anchor() { }
void MCFillFragment::anchor() { }