diff options
Diffstat (limited to 'lib/MC')
-rw-r--r-- | lib/MC/ELFObjectWriter.cpp | 1 | ||||
-rw-r--r-- | lib/MC/MCAsmInfo.cpp | 1 | ||||
-rw-r--r-- | lib/MC/MCAsmStreamer.cpp | 28 | ||||
-rw-r--r-- | lib/MC/MCAssembler.cpp | 321 | ||||
-rw-r--r-- | lib/MC/MCDwarf.cpp | 2 | ||||
-rw-r--r-- | lib/MC/MCELFStreamer.cpp | 27 | ||||
-rw-r--r-- | lib/MC/MCNullStreamer.cpp | 7 | ||||
-rw-r--r-- | lib/MC/MCObjectFileInfo.cpp | 7 | ||||
-rw-r--r-- | lib/MC/MCObjectStreamer.cpp | 67 | ||||
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 62 | ||||
-rw-r--r-- | lib/MC/SubtargetFeature.cpp | 6 |
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 } } |