aboutsummaryrefslogtreecommitdiff
path: root/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/ELFObjectWriter.cpp1
-rw-r--r--lib/MC/MCAsmInfo.cpp1
-rw-r--r--lib/MC/MCAsmStreamer.cpp28
-rw-r--r--lib/MC/MCAssembler.cpp321
-rw-r--r--lib/MC/MCDwarf.cpp2
-rw-r--r--lib/MC/MCELFStreamer.cpp27
-rw-r--r--lib/MC/MCNullStreamer.cpp7
-rw-r--r--lib/MC/MCObjectFileInfo.cpp7
-rw-r--r--lib/MC/MCObjectStreamer.cpp67
-rw-r--r--lib/MC/MCParser/AsmParser.cpp62
-rw-r--r--lib/MC/SubtargetFeature.cpp6
11 files changed, 517 insertions, 12 deletions
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index eda062376e..a94d51bb74 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -1568,4 +1568,5 @@ MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
raw_ostream &OS,
bool IsLittleEndian) {
return new ELFObjectWriter(MOTW, OS, IsLittleEndian);
+
}
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
index 7ea0f3b85a..e0a83453df 100644
--- a/lib/MC/MCAsmInfo.cpp
+++ b/lib/MC/MCAsmInfo.cpp
@@ -24,6 +24,7 @@ using namespace llvm;
MCAsmInfo::MCAsmInfo() {
PointerSize = 4;
+ StackSlotSize = 4; // @LOCALMOD
IsLittleEndian = true;
StackGrowsUp = false;
HasSubsectionsViaSymbols = false;
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index 17a6323d0e..16d1fff8a6 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -205,6 +205,13 @@ public:
virtual bool EmitValueToOffset(const MCExpr *Offset,
unsigned char Value = 0);
+ // @LOCALMOD-BEGIN
+ virtual void EmitBundleLock();
+ virtual void EmitBundleUnlock();
+ virtual void EmitBundleAlignStart();
+ virtual void EmitBundleAlignEnd();
+ // @LOCALMOD-END
+
virtual void EmitFileDirective(StringRef Filename);
virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
StringRef Filename);
@@ -783,6 +790,27 @@ bool MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset,
return false;
}
+// @LOCALMOD-BEGIN
+void MCAsmStreamer::EmitBundleLock() {
+ OS << "\t.bundle_lock";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitBundleUnlock() {
+ OS << "\t.bundle_unlock";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitBundleAlignStart() {
+ OS << "\t.bundle_align_start";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitBundleAlignEnd() {
+ OS << "\t.bundle_align_end";
+ EmitEOL();
+}
+// @LOCALMOD-END
void MCAsmStreamer::EmitFileDirective(StringRef Filename) {
assert(MAI.hasSingleParameterDotFile());
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 726ec5aba5..b6c3bb20b5 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -25,6 +25,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h" // @LOCALMOD
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/LEB128.h"
@@ -71,6 +72,26 @@ bool MCAsmLayout::isFragmentUpToDate(const MCFragment *F) const {
}
void MCAsmLayout::Invalidate(MCFragment *F) {
+ // @LOCALMOD-BEGIN
+ if (F->getParent()->isBundlingEnabled()) {
+ // If this fragment is part of a bundle locked group,
+ // we need to invalidate all the way to the first fragment
+ // in the group.
+ while (F && !F->isBundleGroupStart())
+ F = F->getPrevNode();
+ assert(F);
+ // With padding enabled, we need to invalidate back one
+ // fragment further in in order to force the recalculuation
+ // of the padding and offset.
+ if (F->getPrevNode()) {
+ F = F->getPrevNode();
+ } else {
+ LastValidFragment[F->getParent()] = NULL;
+ return;
+ }
+ }
+ // @LOCALMOD-END
+
// If this fragment wasn't already up-to-date, we don't need to do anything.
if (!isFragmentUpToDate(F))
return;
@@ -133,6 +154,15 @@ uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const {
assert(SD->getFragment() && "Invalid getOffset() on undefined symbol!");
return getFragmentOffset(SD->getFragment()) + SD->getOffset();
}
+
+// @LOCALMOD-BEGIN
+uint8_t MCAsmLayout::getFragmentPadding(const MCFragment *F) const {
+ EnsureValid(F);
+ assert(F->BundlePadding != (uint8_t)~UINT8_C(0) && "Padding not set!");
+ return F->BundlePadding;
+}
+// @LOCALMOD-END
+
uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const {
// The size is the last fragment's end offset.
@@ -158,10 +188,32 @@ MCFragment::~MCFragment() {
}
MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent)
- : Kind(_Kind), Parent(_Parent), Atom(0), Offset(~UINT64_C(0))
+ : Kind(_Kind),
+ // @LOCALMOD-BEGIN
+ BundleAlign(BundleAlignNone),
+ BundleGroupStart(false),
+ BundleGroupEnd(false),
+ BundlePadding(~UINT8_C(0)),
+ // @LOCALMOD-END
+ Parent(_Parent), Atom(0), Offset(~UINT64_C(0))
{
if (Parent)
Parent->getFragmentList().push_back(this);
+
+ // @LOCALMOD-BEGIN
+ if (Parent && Parent->isBundlingEnabled()) {
+ BundleAlign = Parent->getBundleAlignNext();
+ Parent->setBundleAlignNext(MCFragment::BundleAlignNone);
+ if (Parent->isBundleLocked()) {
+ BundleGroupStart = Parent->isBundleGroupFirstFrag();
+ BundleGroupEnd = false;
+ Parent->setBundleGroupFirstFrag(false);
+ } else {
+ BundleGroupStart = true;
+ BundleGroupEnd = true;
+ }
+ }
+ // @LOCALMOD-END
}
/* *** */
@@ -172,12 +224,91 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
: Section(&_Section),
Ordinal(~UINT32_C(0)),
Alignment(1),
- HasInstructions(false)
+ HasInstructions(false),
+// @LOCALMOD-BEGIN
+ BundlingEnabled(false),
+ BundleLocked(false),
+ BundleGroupFirstFrag(false),
+ BundleAlignNext(MCFragment::BundleAlignNone),
+ BundleOffsetKnown(false),
+ BundleOffset(0)
+// @LOCALMOD-END
{
if (A)
A->getSectionList().push_back(this);
+
+ // @LOCALMOD-BEGIN
+ BundleSize = A->getBackend().getBundleSize();
+ if (BundleSize && _Section.UseCodeAlign()) {
+ BundlingEnabled = true;
+ setAlignment(BundleSize);
+ }
+ // @LOCALMOD-END
+}
+
+// @LOCALMOD-BEGIN
+void MCSectionData::MarkBundleOffsetUnknown() {
+ BundleOffsetKnown = false;
+ BundleOffset = 0;
}
+// Only create a new fragment if:
+// 1) we are emitting the first instruction of a bundle locked sequence.
+// 2) we are not currently emitting a bundle locked sequence and we cannot
+// guarantee the instruction would not span a bundle boundary.
+// Otherwise, append to the current fragment to reduce the number of fragments.
+bool MCSectionData::ShouldCreateNewFragment(size_t Size) {
+ // The first instruction of a bundle locked region starts a new fragment.
+ if (isBundleLocked() && isBundleGroupFirstFrag())
+ return true;
+ // Unless we know the relative offset of the end of the current fragment,
+ // we need to create a new fragment.
+ if (!isBundleLocked() && !BundleOffsetKnown)
+ return true;
+ assert(BundleSize != 0 && "BundleSize needs to be non-zero");
+ assert(Size < BundleSize && "Instruction size must be less than BundleSize");
+ // If inserting the instruction would overlap a bundle boundary, start a
+ // new fragment.
+ // TODO(sehr): we could still explicitly insert a NOP and continue here.
+ if (BundleOffset + (unsigned) Size > BundleSize)
+ return true;
+ return false;
+}
+
+void MCSectionData::UpdateBundleOffset(size_t Size) {
+ // A bundle locked fragment could move if it spans a bundle boundary.
+ if (isBundleLocked()) {
+ BundleOffsetKnown = false;
+ return;
+ }
+ // If inserting the instruction would overlap a bundle boundary, starting a
+ // new fragment moves the known offset to the end of the instruction in the
+ // next bundle.
+ // TODO(sehr): we could insert a NOP and continue the fragment.
+ if (BundleOffset + (unsigned) Size > BundleSize)
+ BundleOffset = Size;
+ else
+ BundleOffset = BundleOffset + Size;
+}
+
+void MCSectionData::AlignBundleOffsetTo(size_t AlignBase) {
+ // If BundleOffset is already known, an alignment just moves bundleOffset.
+ if (BundleOffsetKnown) {
+ BundleOffset = RoundUpToAlignment(BundleOffset, AlignBase);
+ return;
+ }
+ // Otherwise, if AlignBase is at least as big as a bundle, then we know the
+ // offset relative to a bundle start.
+ if (AlignBase >= BundleSize) {
+ BundleOffsetKnown = true;
+ BundleOffset = 0;
+ } else {
+ BundleOffsetKnown = false;
+ BundleOffset = 0;
+ }
+}
+// @LOCALMOD-END
+
/* *** */
MCSymbolData::MCSymbolData() : Symbol(0) {}
@@ -319,7 +450,10 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
case MCFragment::FT_LEB:
return cast<MCLEBFragment>(F).getContents().size();
-
+// @LOCALMOD-BEGIN
+ case MCFragment::FT_Tiny:
+ return cast<MCTinyFragment>(F).getContents().size();
+// @LOCALMOD-END
case MCFragment::FT_Align: {
const MCAlignFragment &AF = cast<MCAlignFragment>(F);
unsigned Offset = Layout.getFragmentOffset(&AF);
@@ -375,15 +509,145 @@ void MCAsmLayout::LayoutFragment(MCFragment *F) {
uint64_t Offset = 0;
if (Prev)
Offset += Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev);
-
+ // @LOCALMOD-BEGIN
+ F->BundlePadding = getAssembler().ComputeBundlePadding(*this, F, Offset);
+ Offset += F->BundlePadding;
+ // @LOCALMOD-END
F->Offset = Offset;
LastValidFragment[F->getParent()] = F;
}
+// @LOCALMOD-BEGIN
+// Returns number of bytes of padding needed to align to bundle start.
+static uint64_t AddressToBundlePadding(uint64_t Address, uint64_t BundleMask) {
+ return (~Address + 1) & BundleMask;
+}
+
+uint64_t MCAssembler::getBundleSize() const {
+ return getBackend().getBundleSize();
+}
+
+uint64_t MCAssembler::getBundleMask() const {
+ uint64_t BundleSize = getBundleSize();
+ uint64_t BundleMask = BundleSize - 1;
+ assert(BundleSize != 0);
+ assert((BundleSize & BundleMask) == 0 &&
+ "Bundle size must be a power of 2!");
+ return BundleMask;
+}
+
+static unsigned ComputeGroupSize(MCFragment *F) {
+ if (!F->isBundleGroupStart()) {
+ return 0;
+ }
+
+ unsigned GroupSize = 0;
+ MCFragment *Cur = F;
+ while (Cur) {
+ switch (Cur->getKind()) {
+ default: llvm_unreachable("Unexpected fragment type in bundle!");
+ case MCFragment::FT_Align:
+ case MCFragment::FT_Org:
+ case MCFragment::FT_Fill:
+ if (Cur == F && Cur->isBundleGroupEnd()) {
+ return 0;
+ }
+ llvm_unreachable(".bundle_lock cannot contain .align, .org, or .fill");
+ case MCFragment::FT_Inst:
+ GroupSize += cast<MCInstFragment>(Cur)->getInstSize();
+ break;
+ case MCFragment::FT_Data:
+ GroupSize += cast<MCDataFragment>(Cur)->getContents().size();
+ break;
+ case MCFragment::FT_Tiny:
+ GroupSize += cast<MCTinyFragment>(Cur)->getContents().size();
+ break;
+ }
+ if (Cur->isBundleGroupEnd())
+ break;
+ Cur = Cur->getNextNode();
+ }
+ return GroupSize;
+}
+
+uint8_t MCAssembler::ComputeBundlePadding(const MCAsmLayout &Layout,
+ MCFragment *F,
+ uint64_t FragmentOffset) const {
+ if (!F->getParent()->isBundlingEnabled())
+ return 0;
+
+ uint64_t BundleSize = getBundleSize();
+ uint64_t BundleMask = getBundleMask();
+ unsigned GroupSize = ComputeGroupSize(F);
+
+ if (GroupSize > BundleSize) {
+ // EmitFill creates large groups consisting of repeated single bytes.
+ // These should be safe at any alignment, and in any case we cannot
+ // fix them up here.
+ return 0;
+ }
+
+ uint64_t Padding = 0;
+ uint64_t OffsetInBundle = FragmentOffset & BundleMask;
+
+ if (OffsetInBundle + GroupSize > BundleSize ||
+ F->getBundleAlign() == MCFragment::BundleAlignStart) {
+ // If this group would cross the bundle boundary, or this group must be
+ // aligned to the start of a bundle, then pad up to start of the next bundle
+ Padding += AddressToBundlePadding(OffsetInBundle, BundleMask);
+ OffsetInBundle = 0;
+ }
+ if (F->getBundleAlign() == MCFragment::BundleAlignEnd) {
+ // Push to the end of the bundle
+ Padding += AddressToBundlePadding(OffsetInBundle + GroupSize, BundleMask);
+ }
+ return Padding;
+}
+// @LOCALMOD-END
+
+
+
+
+// @LOCALMOD-BEGIN
+// Write out BundlePadding bytes in NOPs, being careful not to cross a bundle
+// boundary.
+static void WriteBundlePadding(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ uint64_t Offset, uint64_t TotalPadding,
+ MCObjectWriter *OW) {
+ uint64_t BundleSize = Asm.getBundleSize();
+ uint64_t BundleMask = Asm.getBundleMask();
+ uint64_t PaddingLeft = TotalPadding;
+ uint64_t StartPos = Offset;
+
+ bool FirstWrite = true;
+ while (PaddingLeft > 0) {
+ uint64_t NopsToWrite =
+ FirstWrite ? AddressToBundlePadding(StartPos, BundleMask) :
+ BundleSize;
+ if (NopsToWrite > PaddingLeft)
+ NopsToWrite = PaddingLeft;
+ if (!Asm.getBackend().writeNopData(NopsToWrite, OW))
+ report_fatal_error("unable to write nop sequence of " +
+ Twine(NopsToWrite) + " bytes");
+ PaddingLeft -= NopsToWrite;
+ FirstWrite = false;
+ }
+}
+// @LOCALMOD-END
+
/// WriteFragmentData - Write the \p F data to the output file.
static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment &F) {
MCObjectWriter *OW = &Asm.getWriter();
+ // @LOCALMOD-BEGIN
+ if (F.getParent()->isBundlingEnabled()) {
+ uint64_t BundlePadding = Layout.getFragmentPadding(&F);
+ uint64_t PaddingOffset = Layout.getFragmentOffset(&F) - BundlePadding;
+ WriteBundlePadding(Asm, Layout, PaddingOffset, BundlePadding, OW);
+ }
+ // @LOCALMOD-END
+
uint64_t Start = OW->getStream().tell();
(void) Start;
@@ -412,6 +676,16 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
// bytes left to fill use the Value and ValueSize to fill the rest.
// If we are aligning with nops, ask that target to emit the right data.
if (AF.hasEmitNops()) {
+ // @LOCALMOD-BEGIN
+ if (Asm.getBundleSize()) {
+ WriteBundlePadding(Asm, Layout,
+ Layout.getFragmentOffset(&F),
+ FragmentSize,
+ OW);
+ break;
+ }
+ // @LOCALMOD-END
+
if (!Asm.getBackend().writeNopData(Count, OW))
report_fatal_error("unable to write nop sequence of " +
Twine(Count) + " bytes");
@@ -438,6 +712,15 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
break;
}
+ // @LOCALMOD-BEGIN
+ case MCFragment::FT_Tiny: {
+ MCTinyFragment &TF = cast<MCTinyFragment>(F);
+ assert(FragmentSize == TF.getContents().size() && "Invalid size!");
+ OW->WriteBytes(TF.getContents().str());
+ break;
+ }
+ // @LOCALMOD-END
+
case MCFragment::FT_Fill: {
MCFillFragment &FF = cast<MCFillFragment>(F);
@@ -843,10 +1126,24 @@ void MCFragment::dump() {
case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
case MCFragment::FT_LEB: OS << "MCLEBFragment"; break;
+ // @LOCALMOD-BEGIN
+ case MCFragment::FT_Tiny: OS << "MCTinyFragment"; break;
+ // @LOCALMOD-END
}
OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
- << " Offset:" << Offset << ">";
+ << " Offset:" << Offset;
+ // @LOCALMOD-BEGIN
+ if (BundleGroupStart)
+ OS << " BundleGroupStart";
+ if (BundleGroupEnd)
+ OS << " BundleGroupEnd";
+ if (BundleAlign == BundleAlignStart)
+ OS << " BundleAlign: Start";
+ else if (BundleAlign == BundleAlignEnd)
+ OS << " BundleAlign: End";
+ OS << ">";
+ // @LOCALMOD-END
switch (getKind()) {
case MCFragment::FT_Align: {
@@ -895,6 +1192,20 @@ void MCFragment::dump() {
IF->getInst().dump_pretty(OS);
break;
}
+ // @LOCALMOD-BEGIN
+ case MCFragment::FT_Tiny: {
+ const MCTinyFragment *TF = cast<MCTinyFragment>(this);
+ OS << "\n ";
+ OS << " Contents:[";
+ const SmallVectorImpl<char> &Contents = TF->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;
+ }
+ // @LOCALMOD-END
case MCFragment::FT_Org: {
const MCOrgFragment *OF = cast<MCOrgFragment>(this);
OS << "\n ";
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index f71b266ad6..a1643b2da5 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -777,7 +777,7 @@ void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
static int getDataAlignmentFactor(MCStreamer &streamer) {
MCContext &context = streamer.getContext();
const MCAsmInfo &asmInfo = context.getAsmInfo();
- int size = asmInfo.getPointerSize();
+ int size = asmInfo.getStackSlotSize(); // @LOCALMOD
if (asmInfo.isStackGrowthDirectionUp())
return size;
else
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp
index 14fbc1ec83..b1bded288d 100644
--- a/lib/MC/MCELFStreamer.cpp
+++ b/lib/MC/MCELFStreamer.cpp
@@ -355,6 +355,7 @@ void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
unsigned AddrSpace) {
fixSymbolsInTLSFixups(Value);
MCObjectStreamer::EmitValueImpl(Value, Size, AddrSpace);
+ getCurrentSectionData()->MarkBundleOffsetUnknown(); // @LOCALMOD
}
@@ -423,10 +424,10 @@ void MCELFStreamer::EmitInstToFragment(const MCInst &Inst) {
for (unsigned i = 0, e = F.getFixups().size(); i != e; ++i)
fixSymbolsInTLSFixups(F.getFixups()[i].getValue());
+ getCurrentSectionData()->MarkBundleOffsetUnknown(); // @LOCALMOD
}
void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
- MCDataFragment *DF = getOrCreateDataFragment();
SmallVector<MCFixup, 4> Fixups;
SmallString<256> Code;
@@ -437,12 +438,26 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
fixSymbolsInTLSFixups(Fixups[i].getValue());
- // Add the fixups and data.
- for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
- Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
- DF->addFixup(Fixups[i]);
+ // @LOCALMOD-BEGIN
+ MCSectionData *SD = getCurrentSectionData();
+
+ if (Fixups.size() > 0 || !SD->isBundlingEnabled()) {
+ MCDataFragment *DF = getOrCreateDataFragment();
+
+ // Add the fixups and data.
+ for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
+ Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
+ DF->addFixup(Fixups[i]);
+ }
+ DF->getContents().append(Code.begin(), Code.end());
+ } else {
+ MCTinyFragment *TF = dyn_cast_or_null<MCTinyFragment>(getCurrentFragment());
+ if (!TF || SD->ShouldCreateNewFragment(Code.size()))
+ TF = new MCTinyFragment(SD);
+ TF->getContents().append(Code.begin(), Code.end());
}
- DF->getContents().append(Code.begin(), Code.end());
+ SD->UpdateBundleOffset(Code.size());
+ // @LOCALMOD-END
}
void MCELFStreamer::FinishImpl() {
diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp
index 4c17d91551..46579d7b1f 100644
--- a/lib/MC/MCNullStreamer.cpp
+++ b/lib/MC/MCNullStreamer.cpp
@@ -83,6 +83,13 @@ namespace {
virtual bool EmitValueToOffset(const MCExpr *Offset,
unsigned char Value = 0) { return false; }
+ // @LOCALMOD-BEGIN
+ virtual void EmitBundleLock() {}
+ virtual void EmitBundleUnlock() {}
+ virtual void EmitBundleAlignStart() {}
+ virtual void EmitBundleAlignEnd() {}
+ // @LOCALMOD-END
+
virtual void EmitFileDirective(StringRef Filename) {}
virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
StringRef Filename) {
diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp
index 2e1604d6b5..3338a17e5c 100644
--- a/lib/MC/MCObjectFileInfo.cpp
+++ b/lib/MC/MCObjectFileInfo.cpp
@@ -543,9 +543,16 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) {
SectionKind::getDataRel());
}
+// @LOCALMOD-START
+// TODO(petarj): HACK! Find a better way to set ELF::EF_MIPS_PIC flag.
+// See also file lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp.
+Reloc::Model RelocModelOption = Reloc::Default;
+// @LOCALMOD-END
+
void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm,
CodeModel::Model cm,
MCContext &ctx) {
+ RelocModelOption = relocm; // @LOCALMOD
RelocM = relocm;
CMModel = cm;
Ctx = &ctx;
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index 774632306d..37a445fae0 100644
--- a/lib/MC/MCObjectStreamer.cpp
+++ b/lib/MC/MCObjectStreamer.cpp
@@ -16,6 +16,7 @@
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSection.h" // @LOCALMOD
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
@@ -54,6 +55,11 @@ MCFragment *MCObjectStreamer::getCurrentFragment() const {
}
MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const {
+ // @LOCALMOD-BEGIN
+ if (getCurrentSectionData()->isBundlingEnabled()) {
+ return new MCDataFragment(getCurrentSectionData());
+ }
+ // @LOCALMOD-END
MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
if (!F)
F = new MCDataFragment(getCurrentSectionData());
@@ -153,6 +159,54 @@ void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias,
report_fatal_error("This file format doesn't support weak aliases.");
}
+// @LOCALMOD-BEGIN ========================================================
+
+void MCObjectStreamer::EmitBundleAlignStart() {
+ MCSectionData *SD = getCurrentSectionData();
+ assert(SD->isBundlingEnabled() &&
+ ".bundle_align_start called, but bundling disabled!");
+ assert(!SD->isBundleLocked() &&
+ ".bundle_align_start while bundle locked");
+ SD->setBundleAlignNext(MCFragment::BundleAlignStart);
+}
+
+void MCObjectStreamer::EmitBundleAlignEnd() {
+ MCSectionData *SD = getCurrentSectionData();
+ assert(SD->isBundlingEnabled() &&
+ ".bundle_align_end called, but bundling disabled!");
+ assert(!SD->isBundleLocked() &&
+ ".bundle_align_end while bundle locked");
+ SD->setBundleAlignNext(MCFragment::BundleAlignEnd);
+}
+
+void MCObjectStreamer::EmitBundleLock() {
+ MCSectionData *SD = getCurrentSectionData();
+ assert(SD->isBundlingEnabled() &&
+ ".bundle_lock called, but bundling disabled!");
+ assert(!SD->isBundleLocked() &&
+ ".bundle_lock issued when bundle already locked");
+ SD->setBundleLocked(true);
+ SD->setBundleGroupFirstFrag(true);
+}
+
+void MCObjectStreamer::EmitBundleUnlock() {
+ MCSectionData *SD = getCurrentSectionData();
+ assert(SD->isBundlingEnabled() &&
+ ".bundle_unlock called, but bundling disabled!");
+ assert(SD->isBundleLocked() &&
+ ".bundle_unlock called when bundle not locked");
+ // If there has been at least one fragment emitted inside
+ // this bundle lock, then we need to mark the last emitted
+ // fragment as the group end.
+ if (!SD->isBundleGroupFirstFrag()) {
+ assert(getCurrentFragment() != NULL);
+ getCurrentFragment()->setBundleGroupEnd(true);
+ }
+ SD->setBundleLocked(false);
+ SD->setBundleGroupFirstFrag(false);
+}
+// @LOCALMOD-END ==========================================================
+
void MCObjectStreamer::ChangeSection(const MCSection *Section) {
assert(Section && "Cannot switch to a null section!");
@@ -160,6 +214,13 @@ void MCObjectStreamer::ChangeSection(const MCSection *Section) {
}
void MCObjectStreamer::EmitInstruction(const MCInst &Inst) {
+
+ // @LOCALMOD-BEGIN
+ if (getAssembler().getBackend().CustomExpandInst(Inst, *this)) {
+ return;
+ }
+ // @LOCALMOD-END
+
// Scan for values.
for (unsigned i = Inst.getNumOperands(); i--; )
if (Inst.getOperand(i).isExpr())
@@ -235,6 +296,7 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
void MCObjectStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
assert(AddrSpace == 0 && "Address space must be 0!");
getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end());
+ getCurrentSectionData()->MarkBundleOffsetUnknown(); // @LOCALMOD
}
void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment,
@@ -246,6 +308,10 @@ void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment,
new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit,
getCurrentSectionData());
+ // @LOCALMOD-BEGIN
+ // Bump the bundle offset to account for alignment.
+ getCurrentSectionData()->AlignBundleOffsetTo(ByteAlignment);
+ // @LOCALMOD-END
// Update the maximum alignment on the current section if necessary.
if (ByteAlignment > getCurrentSectionData()->getAlignment())
getCurrentSectionData()->setAlignment(ByteAlignment);
@@ -301,6 +367,7 @@ void MCObjectStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue,
// FIXME: A MCFillFragment would be more memory efficient but MCExpr has
// problems evaluating expressions across multiple fragments.
getOrCreateDataFragment()->getContents().append(NumBytes, FillValue);
+ getCurrentSectionData()->MarkBundleOffsetUnknown();
}
void MCObjectStreamer::FinishImpl() {
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 6f2e85e553..cf86a44d1b 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -295,6 +295,13 @@ private:
// ".align{,32}", ".p2align{,w,l}"
bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize);
+ // @LOCALMOD-BEGIN
+ bool ParseDirectiveBundleLock();
+ bool ParseDirectiveBundleUnlock();
+ bool ParseDirectiveBundleAlignStart();
+ bool ParseDirectiveBundleAlignEnd();
+ // @LOCALMOD-END
+
/// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which
/// accepts a single symbol (which should be a label or an external).
bool ParseDirectiveSymbolAttribute(MCSymbolAttr Attr);
@@ -1283,6 +1290,17 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
if (IDVal == ".p2alignl")
return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
+ // @LOCALMOD-BEGIN
+ if (IDVal == ".bundle_lock")
+ return ParseDirectiveBundleLock();
+ if (IDVal == ".bundle_unlock")
+ return ParseDirectiveBundleUnlock();
+ if (IDVal == ".bundle_align_start")
+ return ParseDirectiveBundleAlignStart();
+ if (IDVal == ".bundle_align_end")
+ return ParseDirectiveBundleAlignEnd();
+ // @LOCALMOD-END
+
if (IDVal == ".org")
return ParseDirectiveOrg();
@@ -2404,6 +2422,50 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
return false;
}
+// @LOCALMOD-BEGIN
+bool AsmParser::ParseDirectiveBundleLock() {
+ CheckForValidSection();
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.bundle_lock' directive");
+ Lex();
+ getStreamer().EmitBundleLock();
+ return false;
+}
+
+bool AsmParser::ParseDirectiveBundleUnlock() {
+ CheckForValidSection();
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.bundle_unlock' directive");
+ Lex();
+ getStreamer().EmitBundleUnlock();
+ return false;
+}
+
+bool AsmParser::ParseDirectiveBundleAlignStart() {
+ CheckForValidSection();
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.bundle_align_start' directive");
+ Lex();
+ getStreamer().EmitBundleAlignStart();
+ return false;
+}
+
+bool AsmParser::ParseDirectiveBundleAlignEnd() {
+ CheckForValidSection();
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.bundle_align_end' directive");
+ Lex();
+ getStreamer().EmitBundleAlignEnd();
+ return false;
+}
+
+// @LOCALMOD-END
+
+
/// ParseDirectiveSymbolAttribute
/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
diff --git a/lib/MC/SubtargetFeature.cpp b/lib/MC/SubtargetFeature.cpp
index 7625abd465..7f902f1dd7 100644
--- a/lib/MC/SubtargetFeature.cpp
+++ b/lib/MC/SubtargetFeature.cpp
@@ -370,5 +370,11 @@ void SubtargetFeatures::getDefaultSubtargetFeatures(const Triple& Triple) {
AddFeature("64bit");
AddFeature("altivec");
}
+// @LOCALMOD-BEGIN
+ } else if (Triple.getArch() == Triple::arm &&
+ Triple.getOS() == Triple::NativeClient) {
+ AddFeature("-neon");
+ AddFeature("+vfp2");
+// @LOCALMOD-END
}
}