aboutsummaryrefslogtreecommitdiffstats
path: root/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@google.com>2013-01-31 17:00:03 +0000
committerDerek Schuff <dschuff@google.com>2013-01-31 17:00:03 +0000
commitb11917c1aa7348a67d80149fa9613f09a8d56f14 (patch)
treed4c8944fea705dc2a7631df663bd9ae2aa82f4b4 /lib/MC/MCAssembler.cpp
parent1711876988c796d69ba4d30e3aede4527237f79c (diff)
downloadexternal_llvm-b11917c1aa7348a67d80149fa9613f09a8d56f14.zip
external_llvm-b11917c1aa7348a67d80149fa9613f09a8d56f14.tar.gz
external_llvm-b11917c1aa7348a67d80149fa9613f09a8d56f14.tar.bz2
[MC] bundle alignment: prevent padding instructions from crossing bundle boundaries
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174067 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC/MCAssembler.cpp')
-rw-r--r--lib/MC/MCAssembler.cpp24
1 files changed, 20 insertions, 4 deletions
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 983de1a..498fbf7 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -467,7 +467,7 @@ void MCAsmLayout::layoutFragment(MCFragment *F) {
//
//
// BundlePadding
- // |||
+ // |||
// -------------------------------------
// Prev |##########| F |
// -------------------------------------
@@ -506,6 +506,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) {
@@ -514,6 +517,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");
@@ -526,8 +545,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;
@@ -1134,4 +1151,3 @@ void MCOrgFragment::anchor() { }
void MCLEBFragment::anchor() { }
void MCDwarfLineAddrFragment::anchor() { }
void MCDwarfCallFrameFragment::anchor() { }
-