From 57f661bd7d20412f21ac6b7611c41a0f8b84fc01 Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Wed, 6 Jun 2018 09:40:06 +0000 Subject: [PATCH] [MC] Pass MCSubtargetInfo to fixupNeedsRelaxation and applyFixup On targets like Arm some relaxations may only be performed when certain architectural features are available. As functions can be compiled with differing levels of architectural support we must make a judgement on whether we can relax based on the MCSubtargetInfo for the function. This change passes through the MCSubtargetInfo for the function to fixupNeedsRelaxation so that the decision on whether to relax can be made per function. In this patch, only the ARM backend makes use of this information. We must also pass the MCSubtargetInfo to applyFixup because some fixups skip error checking on the assumption that relaxation has occurred, to prevent code-generation errors applyFixup must see the same MCSubtargetInfo as fixupNeedsRelaxation. Differential Revision: https://reviews.llvm.org/D44928 llvm-svn: 334078 --- llvm/include/llvm/MC/MCAsmBackend.h | 10 ++++- llvm/include/llvm/MC/MCFragment.h | 23 +++++++---- llvm/include/llvm/MC/MCObjectStreamer.h | 7 +++- llvm/include/llvm/MC/MCStreamer.h | 3 +- llvm/lib/MC/MCAsmStreamer.cpp | 6 ++- llvm/lib/MC/MCAssembler.cpp | 13 ++++-- llvm/lib/MC/MCELFStreamer.cpp | 30 ++++++++++---- llvm/lib/MC/MCMachOStreamer.cpp | 1 + llvm/lib/MC/MCObjectStreamer.cpp | 29 +++++++++---- llvm/lib/MC/MCParser/AsmParser.cpp | 4 +- llvm/lib/MC/MCWasmStreamer.cpp | 5 ++- llvm/lib/MC/MCWinCOFFStreamer.cpp | 2 +- .../MCTargetDesc/AArch64AsmBackend.cpp | 12 ++++-- .../AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp | 11 +++-- .../Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 41 +++++++++++-------- .../Target/ARM/MCTargetDesc/ARMAsmBackend.h | 16 ++++++-- .../Target/BPF/MCTargetDesc/BPFAsmBackend.cpp | 11 +++-- .../MCTargetDesc/HexagonAsmBackend.cpp | 12 +++--- .../Lanai/MCTargetDesc/LanaiAsmBackend.cpp | 9 ++-- .../Mips/MCTargetDesc/MipsAsmBackend.cpp | 3 +- .../Target/Mips/MCTargetDesc/MipsAsmBackend.h | 6 ++- .../PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 6 ++- .../Sparc/MCTargetDesc/SparcAsmBackend.cpp | 6 ++- .../MCTargetDesc/SystemZMCAsmBackend.cpp | 9 ++-- .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 9 ++-- .../CodeGen/ARM/relax-per-target-feature.ll | 34 +++++++++++++++ .../illegal-subtarget-change.s | 16 ++++++++ .../MC/ARM/AlignedBundling/subtarget-change.s | 33 +++++++++++++++ llvm/test/MC/ARM/fixup-per-fragment.s | 20 +++++++++ .../bundle-subtarget-change-error.s | 16 ++++++++ 30 files changed, 314 insertions(+), 89 deletions(-) create mode 100644 llvm/test/CodeGen/ARM/relax-per-target-feature.ll create mode 100644 llvm/test/MC/ARM/AlignedBundling/illegal-subtarget-change.s create mode 100644 llvm/test/MC/ARM/AlignedBundling/subtarget-change.s create mode 100644 llvm/test/MC/ARM/fixup-per-fragment.s create mode 100644 llvm/test/MC/X86/AlignedBundling/bundle-subtarget-change-error.s diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h index 1272829b1f6b..030d3c05aa5a 100644 --- a/llvm/include/llvm/MC/MCAsmBackend.h +++ b/llvm/include/llvm/MC/MCAsmBackend.h @@ -92,9 +92,12 @@ public: /// the offset specified by the fixup and following the fixup kind as /// appropriate. Errors (such as an out of range fixup value) should be /// reported via \p Ctx. + /// The \p STI is present only for fragments of type MCRelaxableFragment and + /// MCDataFragment with hasInstructions() == true. virtual void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved) const = 0; + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const = 0; /// Check whether the given target requires emitting differences of two /// symbols as a set of relocations. @@ -108,7 +111,10 @@ public: /// Check whether the given instruction may need relaxation. /// /// \param Inst - The instruction to test. - virtual bool mayNeedRelaxation(const MCInst &Inst) const = 0; + /// \param STI - The MCSubtargetInfo in effect when the instruction was + /// encoded. + virtual bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const = 0; /// Target specific predicate for whether a given fixup requires the /// associated instruction to be relaxed. diff --git a/llvm/include/llvm/MC/MCFragment.h b/llvm/include/llvm/MC/MCFragment.h index 95878f81c86c..16eb124d95e7 100644 --- a/llvm/include/llvm/MC/MCFragment.h +++ b/llvm/include/llvm/MC/MCFragment.h @@ -201,7 +201,16 @@ protected: : MCEncodedFragmentWithContents(FType, HasInstructions, Sec) {} + /// STI - The MCSubtargetInfo in effect when the instruction was encoded. + /// must be non-null for instructions. + const MCSubtargetInfo *STI = nullptr; + public: + + /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded. + /// Guaranteed to be non-null if hasInstructions() == true + const MCSubtargetInfo *getSubtargetInfo() const { return STI; } + using const_fixup_iterator = SmallVectorImpl::const_iterator; using fixup_iterator = SmallVectorImpl::iterator; @@ -228,7 +237,12 @@ public: MCDataFragment(MCSection *Sec = nullptr) : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {} - void setHasInstructions(bool V) { HasInstructions = V; } + /// Record that the fragment contains instructions with the MCSubtargetInfo in + /// effect when the instruction was encoded. + void setHasInstructions(const MCSubtargetInfo &STI) { + HasInstructions = true; + this->STI = &STI; + } static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Data; @@ -259,20 +273,15 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> { /// Inst - The instruction this is a fragment for. MCInst Inst; - /// STI - The MCSubtargetInfo in effect when the instruction was encoded. - const MCSubtargetInfo &STI; - public: MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI, MCSection *Sec = nullptr) : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec), - Inst(Inst), STI(STI) {} + Inst(Inst) { this->STI = &STI; } const MCInst &getInst() const { return Inst; } void setInst(const MCInst &Value) { Inst = Value; } - const MCSubtargetInfo &getSubtargetInfo() { return STI; } - static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Relaxable; } diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index 498a8af90112..8715a16e705d 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -73,7 +73,9 @@ public: /// Get a data fragment to write into, creating a new one if the current /// fragment is not a data fragment. - MCDataFragment *getOrCreateDataFragment(); + /// Optionally a \p STI can be passed in so that a new fragment is created + /// if the Subtarget differs from the current fragment. + MCDataFragment *getOrCreateDataFragment(const MCSubtargetInfo* STI = nullptr); MCPaddingFragment *getOrCreatePaddingFragment(); protected: @@ -158,7 +160,8 @@ public: void EmitGPRel32Value(const MCExpr *Value) override; void EmitGPRel64Value(const MCExpr *Value) override; bool EmitRelocDirective(const MCExpr &Offset, StringRef Name, - const MCExpr *Expr, SMLoc Loc) override; + const MCExpr *Expr, SMLoc Loc, + const MCSubtargetInfo &STI) override; using MCStreamer::emitFill; void emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc = SMLoc()) override; diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index db4f885a7d9c..43712de727ba 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -918,7 +918,8 @@ public: /// Returns true if the relocation could not be emitted because Name is not /// known. virtual bool EmitRelocDirective(const MCExpr &Offset, StringRef Name, - const MCExpr *Expr, SMLoc Loc) { + const MCExpr *Expr, SMLoc Loc, + const MCSubtargetInfo &STI) { return true; } diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 1b3d32d30339..d07f3cac4102 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -315,7 +315,8 @@ public: void EmitBundleUnlock() override; bool EmitRelocDirective(const MCExpr &Offset, StringRef Name, - const MCExpr *Expr, SMLoc Loc) override; + const MCExpr *Expr, SMLoc Loc, + const MCSubtargetInfo &STI) override; /// If this file is backed by an assembly streamer, this dumps the specified /// string in the output .s file. This capability is indicated by the @@ -1820,7 +1821,8 @@ void MCAsmStreamer::EmitBundleUnlock() { } bool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, - const MCExpr *Expr, SMLoc) { + const MCExpr *Expr, SMLoc, + const MCSubtargetInfo &STI) { OS << "\t.reloc "; Offset.print(OS, MAI); OS << ", " << Name; diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 0cf17a10d087..94857d94555d 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -805,12 +805,17 @@ void MCAssembler::layout(MCAsmLayout &Layout) { continue; ArrayRef Fixups; MutableArrayRef Contents; + const MCSubtargetInfo *STI = nullptr; if (auto *FragWithFixups = dyn_cast(&Frag)) { Fixups = FragWithFixups->getFixups(); Contents = FragWithFixups->getContents(); + STI = FragWithFixups->getSubtargetInfo(); + assert(!FragWithFixups->hasInstructions() || STI != nullptr); } else if (auto *FragWithFixups = dyn_cast(&Frag)) { Fixups = FragWithFixups->getFixups(); Contents = FragWithFixups->getContents(); + STI = FragWithFixups->getSubtargetInfo(); + assert(!FragWithFixups->hasInstructions() || STI != nullptr); } else if (auto *FragWithFixups = dyn_cast(&Frag)) { Fixups = FragWithFixups->getFixups(); Contents = FragWithFixups->getContents(); @@ -823,7 +828,7 @@ void MCAssembler::layout(MCAsmLayout &Layout) { std::tie(Target, FixedValue, IsResolved) = handleFixup(Layout, Frag, Fixup); getBackend().applyFixup(*this, Fixup, Target, Contents, FixedValue, - IsResolved); + IsResolved, STI); } } } @@ -860,7 +865,7 @@ bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F, // If this inst doesn't ever need relaxation, ignore it. This occurs when we // are intentionally pushing out inst fragments, or because we relaxed a // previous instruction to one that doesn't need relaxation. - if (!getBackend().mayNeedRelaxation(F->getInst())) + if (!getBackend().mayNeedRelaxation(F->getInst(), *F->getSubtargetInfo())) return false; for (const MCFixup &Fixup : F->getFixups()) @@ -885,7 +890,7 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout, // Relax the fragment. MCInst Relaxed; - getBackend().relaxInstruction(F.getInst(), F.getSubtargetInfo(), Relaxed); + getBackend().relaxInstruction(F.getInst(), *F.getSubtargetInfo(), Relaxed); // Encode the new instruction. // @@ -894,7 +899,7 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout, SmallVector Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); - getEmitter().encodeInstruction(Relaxed, VecOS, Fixups, F.getSubtargetInfo()); + getEmitter().encodeInstruction(Relaxed, VecOS, Fixups, *F.getSubtargetInfo()); // Update the fragment. F.setInst(Relaxed); diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index b112bd9639d8..df11495a9548 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -83,7 +83,8 @@ void MCELFStreamer::mergeFragment(MCDataFragment *DF, DF->getContents().size()); DF->getFixups().push_back(EF->getFixups()[i]); } - DF->setHasInstructions(true); + if (DF->getSubtargetInfo() == nullptr && EF->getSubtargetInfo()) + DF->setHasInstructions(*EF->getSubtargetInfo()); DF->getContents().append(EF->getContents().begin(), EF->getContents().end()); } @@ -493,6 +494,15 @@ void MCELFStreamer::EmitInstToFragment(const MCInst &Inst, fixSymbolsInTLSFixups(F.getFixups()[i].getValue()); } +// A fragment can only have one Subtarget, and when bundling is enabled we +// sometimes need to use the same fragment. We give an error if there +// are conflicting Subtargets. +static void CheckBundleSubtargets(const MCSubtargetInfo *OldSTI, + const MCSubtargetInfo *NewSTI) { + if (OldSTI && NewSTI && OldSTI != NewSTI) + report_fatal_error("A Bundle can only have one Subtarget."); +} + void MCELFStreamer::EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) { MCAssembler &Assembler = getAssembler(); @@ -508,7 +518,7 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst, // // If bundling is disabled, append the encoded instruction to the current data // fragment (or create a new such fragment if the current fragment is not a - // data fragment). + // data fragment, or the Subtarget has changed). // // If bundling is enabled: // - If we're not in a bundle-locked group, emit the instruction into a @@ -523,19 +533,23 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst, if (Assembler.isBundlingEnabled()) { MCSection &Sec = *getCurrentSectionOnly(); - if (Assembler.getRelaxAll() && isBundleLocked()) + if (Assembler.getRelaxAll() && isBundleLocked()) { // If the -mc-relax-all flag is used and we are bundle-locked, we re-use // the current bundle group. DF = BundleGroups.back(); + CheckBundleSubtargets(DF->getSubtargetInfo(), &STI); + } else if (Assembler.getRelaxAll() && !isBundleLocked()) // When not in a bundle-locked group and the -mc-relax-all flag is used, // we create a new temporary fragment which will be later merged into // the current fragment. DF = new MCDataFragment(); - else if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst()) + else if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst()) { // If we are bundle-locked, we re-use the current fragment. // The bundle-locking directive ensures this is a new data fragment. DF = cast(getCurrentFragment()); + CheckBundleSubtargets(DF->getSubtargetInfo(), &STI); + } else if (!isBundleLocked() && Fixups.size() == 0) { // Optimize memory usage by emitting the instruction to a // MCCompactEncodedInstFragment when not in a bundle-locked group and @@ -560,7 +574,7 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst, // to be turned off. Sec.setBundleGroupBeforeFirstInst(false); } else { - DF = getOrCreateDataFragment(); + DF = getOrCreateDataFragment(&STI); } // Add the fixups and data. @@ -568,12 +582,12 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst, Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); DF->getFixups().push_back(Fixups[i]); } - DF->setHasInstructions(true); + DF->setHasInstructions(STI); DF->getContents().append(Code.begin(), Code.end()); if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) { if (!isBundleLocked()) { - mergeFragment(getOrCreateDataFragment(), DF); + mergeFragment(getOrCreateDataFragment(&STI), DF); delete DF; } } @@ -633,7 +647,7 @@ void MCELFStreamer::EmitBundleUnlock() { // FIXME: Use more separate fragments for nested groups. if (!isBundleLocked()) { - mergeFragment(getOrCreateDataFragment(), DF); + mergeFragment(getOrCreateDataFragment(DF->getSubtargetInfo()), DF); BundleGroups.pop_back(); delete DF; } diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp index d4924a1edfe1..4b74c5695316 100644 --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/lib/MC/MCMachOStreamer.cpp @@ -450,6 +450,7 @@ void MCMachOStreamer::EmitInstToData(const MCInst &Inst, Fixup.setOffset(Fixup.getOffset() + DF->getContents().size()); DF->getFixups().push_back(Fixup); } + DF->setHasInstructions(STI); DF->getContents().append(Code.begin(), Code.end()); } diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 3ed9a6fbf6b3..5159cfee7a8c 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -146,12 +146,24 @@ MCFragment *MCObjectStreamer::getCurrentFragment() const { return nullptr; } -MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() { - MCDataFragment *F = dyn_cast_or_null(getCurrentFragment()); +static bool CanReuseDataFragment(const MCDataFragment &F, + const MCAssembler &Assembler, + const MCSubtargetInfo *STI) { + if (!F.hasInstructions()) + return true; // When bundling is enabled, we don't want to add data to a fragment that // already has instructions (see MCELFStreamer::EmitInstToData for details) - if (!F || (Assembler->isBundlingEnabled() && !Assembler->getRelaxAll() && - F->hasInstructions())) { + if (Assembler.isBundlingEnabled()) + return Assembler.getRelaxAll(); + // If the subtarget is changed mid fragment we start a new fragment to record + // the new STI. + return !STI || F.getSubtargetInfo() == STI; +} + +MCDataFragment * +MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) { + MCDataFragment *F = dyn_cast_or_null(getCurrentFragment()); + if (!F || !CanReuseDataFragment(*F, *Assembler, STI)) { F = new MCDataFragment(); insert(F); } @@ -327,7 +339,7 @@ void MCObjectStreamer::EmitInstructionImpl(const MCInst &Inst, // If this instruction doesn't need relaxation, just emit it as data. MCAssembler &Assembler = getAssembler(); - if (!Assembler.getBackend().mayNeedRelaxation(Inst)) { + if (!Assembler.getBackend().mayNeedRelaxation(Inst, STI)) { EmitInstToData(Inst, STI); return; } @@ -341,7 +353,7 @@ void MCObjectStreamer::EmitInstructionImpl(const MCInst &Inst, (Assembler.isBundlingEnabled() && Sec->isBundleLocked())) { MCInst Relaxed; getAssembler().getBackend().relaxInstruction(Inst, STI, Relaxed); - while (getAssembler().getBackend().mayNeedRelaxation(Relaxed)) + while (getAssembler().getBackend().mayNeedRelaxation(Relaxed, STI)) getAssembler().getBackend().relaxInstruction(Relaxed, STI, Relaxed); EmitInstToData(Relaxed, STI); return; @@ -606,7 +618,8 @@ void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) { } bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, - const MCExpr *Expr, SMLoc Loc) { + const MCExpr *Expr, SMLoc Loc, + const MCSubtargetInfo &STI) { int64_t OffsetValue; if (!Offset.evaluateAsAbsolute(OffsetValue)) llvm_unreachable("Offset is not absolute"); @@ -614,7 +627,7 @@ bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, if (OffsetValue < 0) llvm_unreachable("Offset is negative"); - MCDataFragment *DF = getOrCreateDataFragment(); + MCDataFragment *DF = getOrCreateDataFragment(&STI); flushPendingLabels(DF, DF->getContents().size()); Optional MaybeKind = Assembler->getBackend().getFixupKind(Name); diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index b43839db2d03..5c8946b286b4 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -2949,7 +2949,9 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) { "unexpected token in .reloc directive")) return true; - if (getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc)) + const MCTargetAsmParser &MCT = getTargetParser(); + const MCSubtargetInfo &STI = MCT.getSTI(); + if (getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc, STI)) return Error(NameLoc, "unknown relocation name"); return false; diff --git a/llvm/lib/MC/MCWasmStreamer.cpp b/llvm/lib/MC/MCWasmStreamer.cpp index a74d37529cc5..2c65371cf3ae 100644 --- a/llvm/lib/MC/MCWasmStreamer.cpp +++ b/llvm/lib/MC/MCWasmStreamer.cpp @@ -45,7 +45,8 @@ void MCWasmStreamer::mergeFragment(MCDataFragment *DF, MCDataFragment *EF) { DF->getContents().size()); DF->getFixups().push_back(EF->getFixups()[i]); } - DF->setHasInstructions(true); + if (DF->getSubtargetInfo() == nullptr && EF->getSubtargetInfo()) + DF->setHasInstructions(*EF->getSubtargetInfo()); DF->getContents().append(EF->getContents().begin(), EF->getContents().end()); } @@ -183,7 +184,7 @@ void MCWasmStreamer::EmitInstToData(const MCInst &Inst, Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); DF->getFixups().push_back(Fixups[i]); } - DF->setHasInstructions(true); + DF->setHasInstructions(STI); DF->getContents().append(Code.begin(), Code.end()); } diff --git a/llvm/lib/MC/MCWinCOFFStreamer.cpp b/llvm/lib/MC/MCWinCOFFStreamer.cpp index 9fc60ab1bf9f..32dc46c61d03 100644 --- a/llvm/lib/MC/MCWinCOFFStreamer.cpp +++ b/llvm/lib/MC/MCWinCOFFStreamer.cpp @@ -63,7 +63,7 @@ void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst, Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); DF->getFixups().push_back(Fixups[i]); } - + DF->setHasInstructions(STI); DF->getContents().append(Code.begin(), Code.end()); } diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp index c39111478f09..856946555198 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -73,9 +73,11 @@ public: void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved) const override; + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; - bool mayNeedRelaxation(const MCInst &Inst) const override; + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override; bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const override; @@ -285,7 +287,8 @@ unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) con void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, uint64_t Value, - bool IsResolved) const { + bool IsResolved, + const MCSubtargetInfo *STI) const { unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); if (!Value) return; // Doesn't change encoding. @@ -321,7 +324,8 @@ void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, } } -bool AArch64AsmBackend::mayNeedRelaxation(const MCInst &Inst) const { +bool AArch64AsmBackend::mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const { return false; } diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp index cf4964ebeea6..abc88c02adca 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp @@ -32,7 +32,8 @@ public: void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved) const override; + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const override { @@ -42,7 +43,10 @@ public: MCInst &Res) const override { llvm_unreachable("Not implemented"); } - bool mayNeedRelaxation(const MCInst &Inst) const override { return false; } + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override { + return false; + } unsigned getMinimumNopSize() const override; bool writeNopData(raw_ostream &OS, uint64_t Count) const override; @@ -102,7 +106,8 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, void AMDGPUAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, uint64_t Value, - bool IsResolved) const { + bool IsResolved, + const MCSubtargetInfo *STI) const { Value = adjustFixupValue(Fixup, Value, &Asm.getContext()); if (!Value) return; // Doesn't change encoding. diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 4a7bf8cc33cc..f524a0081301 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -173,7 +173,8 @@ void ARMAsmBackend::handleAssemblerFlag(MCAssemblerFlag Flag) { } } -unsigned ARMAsmBackend::getRelaxedOpcode(unsigned Op) const { +unsigned ARMAsmBackend::getRelaxedOpcode(unsigned Op, + const MCSubtargetInfo &STI) const { bool HasThumb2 = STI.getFeatureBits()[ARM::FeatureThumb2]; bool HasV8MBaselineOps = STI.getFeatureBits()[ARM::HasV8MBaselineOps]; @@ -195,8 +196,9 @@ unsigned ARMAsmBackend::getRelaxedOpcode(unsigned Op) const { } } -bool ARMAsmBackend::mayNeedRelaxation(const MCInst &Inst) const { - if (getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode()) +bool ARMAsmBackend::mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const { + if (getRelaxedOpcode(Inst.getOpcode(), STI) != Inst.getOpcode()) return true; return false; } @@ -263,7 +265,7 @@ bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, void ARMAsmBackend::relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, MCInst &Res) const { - unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode()); + unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode(), STI); // Sanity check w/ diagnostic if we get here w/ a bogus instruction. if (RelaxedOp == Inst.getOpcode()) { @@ -360,7 +362,8 @@ static uint32_t joinHalfWords(uint32_t FirstHalf, uint32_t SecondHalf, unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, uint64_t Value, - bool IsResolved, MCContext &Ctx) const { + bool IsResolved, MCContext &Ctx, + const MCSubtargetInfo* STI) const { unsigned Kind = Fixup.getKind(); // MachO tries to make .o files that look vaguely pre-linked, so for MOVW/MOVT @@ -389,7 +392,8 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm, case FK_SecRel_4: return Value; case ARM::fixup_arm_movt_hi16: - if (IsResolved || !STI.getTargetTriple().isOSBinFormatELF()) + assert(STI != nullptr); + if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF()) Value >>= 16; LLVM_FALLTHROUGH; case ARM::fixup_arm_movw_lo16: { @@ -401,7 +405,8 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm, return Value; } case ARM::fixup_t2_movt_hi16: - if (IsResolved || !STI.getTargetTriple().isOSBinFormatELF()) + assert(STI != nullptr); + if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF()) Value >>= 16; LLVM_FALLTHROUGH; case ARM::fixup_t2_movw_lo16: { @@ -529,9 +534,9 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm, } case ARM::fixup_arm_thumb_bl: { if (!isInt<25>(Value - 4) || - (!STI.getFeatureBits()[ARM::FeatureThumb2] && - !STI.getFeatureBits()[ARM::HasV8MBaselineOps] && - !STI.getFeatureBits()[ARM::HasV6MOps] && + (!STI->getFeatureBits()[ARM::FeatureThumb2] && + !STI->getFeatureBits()[ARM::HasV8MBaselineOps] && + !STI->getFeatureBits()[ARM::HasV6MOps] && !isInt<23>(Value - 4))) { Ctx.reportError(Fixup.getLoc(), "Relocation out of range"); return 0; @@ -603,7 +608,8 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm, case ARM::fixup_arm_thumb_cp: // On CPUs supporting Thumb2, this will be relaxed to an ldr.w, otherwise we // could have an error on our hands. - if (!STI.getFeatureBits()[ARM::FeatureThumb2] && IsResolved) { + assert(STI != nullptr); + if (!STI->getFeatureBits()[ARM::FeatureThumb2] && IsResolved) { const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); if (FixupDiagnostic) { Ctx.reportError(Fixup.getLoc(), FixupDiagnostic); @@ -627,8 +633,9 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm, } case ARM::fixup_arm_thumb_br: // Offset by 4 and don't encode the lower bit, which is always 0. - if (!STI.getFeatureBits()[ARM::FeatureThumb2] && - !STI.getFeatureBits()[ARM::HasV8MBaselineOps]) { + assert(STI != nullptr); + if (!STI->getFeatureBits()[ARM::FeatureThumb2] && + !STI->getFeatureBits()[ARM::HasV8MBaselineOps]) { const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); if (FixupDiagnostic) { Ctx.reportError(Fixup.getLoc(), FixupDiagnostic); @@ -638,7 +645,8 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm, return ((Value - 4) >> 1) & 0x7ff; case ARM::fixup_arm_thumb_bcc: // Offset by 4 and don't encode the lower bit, which is always 0. - if (!STI.getFeatureBits()[ARM::FeatureThumb2]) { + assert(STI != nullptr); + if (!STI->getFeatureBits()[ARM::FeatureThumb2]) { const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); if (FixupDiagnostic) { Ctx.reportError(Fixup.getLoc(), FixupDiagnostic); @@ -894,10 +902,11 @@ static unsigned getFixupKindContainerSizeBytes(unsigned Kind) { void ARMAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, uint64_t Value, - bool IsResolved) const { + bool IsResolved, + const MCSubtargetInfo* STI) const { unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); MCContext &Ctx = Asm.getContext(); - Value = adjustFixupValue(Asm, Fixup, Target, Value, IsResolved, Ctx); + Value = adjustFixupValue(Asm, Fixup, Target, Value, IsResolved, Ctx, STI); if (!Value) return; // Doesn't change encoding. diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h index b72f45d07174..88c476bf65f4 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h @@ -19,6 +19,9 @@ namespace llvm { class ARMAsmBackend : public MCAsmBackend { + // The STI from the target triple the MCAsmBackend was instantiated with + // note that MCFragments may have a different local STI that should be + // used in preference. const MCSubtargetInfo &STI; bool isThumbMode; // Currently emitting Thumb code. public: @@ -31,6 +34,8 @@ public: return ARM::NumTargetFixupKinds; } + // FIXME: this should be calculated per fragment as the STI may be + // different. bool hasNOP() const { return STI.getFeatureBits()[ARM::HasV6T2Ops]; } const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; @@ -40,15 +45,18 @@ public: unsigned adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, uint64_t Value, - bool IsResolved, MCContext &Ctx) const; + bool IsResolved, MCContext &Ctx, + const MCSubtargetInfo *STI) const; void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved) const override; + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; - unsigned getRelaxedOpcode(unsigned Op) const; + unsigned getRelaxedOpcode(unsigned Op, const MCSubtargetInfo &STI) const; - bool mayNeedRelaxation(const MCInst &Inst) const override; + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override; const char *reasonForFixupRelaxation(const MCFixup &Fixup, uint64_t Value) const; diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp index b36b01c7b733..6c255e9ef780 100644 --- a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp +++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp @@ -27,7 +27,8 @@ public: void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved) const override; + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; std::unique_ptr createObjectTargetWriter() const override; @@ -41,7 +42,10 @@ public: unsigned getNumFixupKinds() const override { return 1; } - bool mayNeedRelaxation(const MCInst &Inst) const override { return false; } + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override { + return false; + } void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, MCInst &Res) const override {} @@ -64,7 +68,8 @@ bool BPFAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { void BPFAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, uint64_t Value, - bool IsResolved) const { + bool IsResolved, + const MCSubtargetInfo *STI) const { if (Fixup.getKind() == FK_SecRel_4 || Fixup.getKind() == FK_SecRel_8) { assert(Value == 0); } else if (Fixup.getKind() == FK_Data_4) { diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp index 2bbdfb959700..af1e5429d0c2 100644 --- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp +++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp @@ -51,7 +51,7 @@ class HexagonAsmBackend : public MCAsmBackend { SmallVector Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); - E.encodeInstruction(HMB, VecOS, Fixups, RF.getSubtargetInfo()); + E.encodeInstruction(HMB, VecOS, Fixups, *RF.getSubtargetInfo()); // Update the fragment. RF.setInst(HMB); @@ -414,7 +414,8 @@ public: /// fixup kind as appropriate. void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, - uint64_t FixupValue, bool IsResolved) const override { + uint64_t FixupValue, bool IsResolved, + const MCSubtargetInfo *STI) const override { // When FixupValue is 0 the relocation is external and there // is nothing for us to do. @@ -561,7 +562,8 @@ public: /// relaxation. /// /// \param Inst - The instruction to test. - bool mayNeedRelaxation(MCInst const &Inst) const override { + bool mayNeedRelaxation(MCInst const &Inst, + const MCSubtargetInfo &STI) const override { return true; } @@ -736,7 +738,7 @@ public: Inst.addOperand(MCOperand::createInst(Nop)); Size -= 4; if (!HexagonMCChecker( - Context, *MCII, RF.getSubtargetInfo(), Inst, + Context, *MCII, *RF.getSubtargetInfo(), Inst, *Context.getRegisterInfo(), false) .check()) { Inst.erase(Inst.end() - 1); @@ -744,7 +746,7 @@ public: } } bool Error = HexagonMCShuffle(Context, true, *MCII, - RF.getSubtargetInfo(), Inst); + *RF.getSubtargetInfo(), Inst); //assert(!Error); (void)Error; ReplaceInstruction(Asm.getEmitter(), RF, Inst); diff --git a/llvm/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp b/llvm/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp index 0d01729d3939..85fffd9a7c7b 100644 --- a/llvm/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp +++ b/llvm/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp @@ -51,7 +51,8 @@ public: void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved) const override; + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; std::unique_ptr createObjectTargetWriter() const override; @@ -69,7 +70,8 @@ public: return Lanai::NumTargetFixupKinds; } - bool mayNeedRelaxation(const MCInst & /*Inst*/) const override { + bool mayNeedRelaxation(const MCInst & /*Inst*/, + const MCSubtargetInfo &STI) const override { return false; } @@ -93,7 +95,8 @@ bool LanaiAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { void LanaiAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, uint64_t Value, - bool /*IsResolved*/) const { + bool /*IsResolved*/, + const MCSubtargetInfo */*STI*/) const { MCFixupKind Kind = Fixup.getKind(); Value = adjustFixupValue(static_cast(Kind), Value); diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 1d01e521ece9..4397c971d080 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -243,7 +243,8 @@ static unsigned calculateMMLEIndex(unsigned i) { void MipsAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, uint64_t Value, - bool IsResolved) const { + bool IsResolved, + const MCSubtargetInfo *STI) const { MCFixupKind Kind = Fixup.getKind(); MCContext &Ctx = Asm.getContext(); Value = adjustFixupValue(Fixup, Value, Ctx); diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h index c66b7ffd27d1..3d5e16fcf9b4 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h @@ -42,7 +42,8 @@ public: void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved) const override; + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; Optional getFixupKind(StringRef Name) const override; const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; @@ -58,7 +59,8 @@ public: /// relaxation. /// /// \param Inst - The instruction to test. - bool mayNeedRelaxation(const MCInst &Inst) const override { + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override { return false; } diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp index 559365323dff..a405dd70c307 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -117,7 +117,8 @@ public: void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved) const override { + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override { Value = adjustFixupValue(Fixup.getKind(), Value); if (!Value) return; // Doesn't change encoding. @@ -157,7 +158,8 @@ public: } } - bool mayNeedRelaxation(const MCInst &Inst) const override { + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override { // FIXME. return false; } diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp index 2ef4655a8893..4b6c1de7d856 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -233,7 +233,8 @@ namespace { } } - bool mayNeedRelaxation(const MCInst &Inst) const override { + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override { // FIXME. return false; } @@ -275,7 +276,8 @@ namespace { void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved) const override { + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override { Value = adjustFixupValue(Fixup.getKind(), Value); if (!Value) return; // Doesn't change encoding. diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp index 96e38a6db9e2..2146832f7794 100644 --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp @@ -53,8 +53,10 @@ public: const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved) const override; - bool mayNeedRelaxation(const MCInst &Inst) const override { + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override { return false; } bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, @@ -96,7 +98,8 @@ void SystemZMCAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, uint64_t Value, - bool IsResolved) const { + bool IsResolved, + const MCSubtargetInfo *STI) const { MCFixupKind Kind = Fixup.getKind(); unsigned Offset = Fixup.getOffset(); unsigned BitSize = getFixupKindInfo(Kind).TargetSize; diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index b91b4508978a..0e4c4398e49d 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -101,7 +101,8 @@ public: void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved) const override { + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override { unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind()); assert(Fixup.getOffset() + Size <= Data.size() && "Invalid fixup offset!"); @@ -117,7 +118,8 @@ public: Data[Fixup.getOffset() + i] = uint8_t(Value >> (i * 8)); } - bool mayNeedRelaxation(const MCInst &Inst) const override; + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override; bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, @@ -264,7 +266,8 @@ static unsigned getRelaxedOpcode(const MCInst &Inst, bool is16BitMode) { return getRelaxedOpcodeBranch(Inst, is16BitMode); } -bool X86AsmBackend::mayNeedRelaxation(const MCInst &Inst) const { +bool X86AsmBackend::mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const { // Branches can always be relaxed in either mode. if (getRelaxedOpcodeBranch(Inst, false) != Inst.getOpcode()) return true; diff --git a/llvm/test/CodeGen/ARM/relax-per-target-feature.ll b/llvm/test/CodeGen/ARM/relax-per-target-feature.ll new file mode 100644 index 000000000000..769c82b51d63 --- /dev/null +++ b/llvm/test/CodeGen/ARM/relax-per-target-feature.ll @@ -0,0 +1,34 @@ +; RUN: llc -mtriple=thumbv4t-linux-gnueabi -o - %s | FileCheck %s + +; Functions may have more features than the base triple; code generation and +; instruction selection may be performed based on this information. This test +; makes sure that the MC layer performs instruction relaxation based on the +; target-features of the function. The relaxation for tail call is particularly +; important on Thumb2 as the 16-bit Thumb branch instruction has an extremely +; short range. + +declare dso_local void @g(...) local_unnamed_addr #2 + +define dso_local void @f() local_unnamed_addr #0 { +entry: + tail call void bitcast (void (...)* @g to void ()*)() #3 + ret void +} +; Function has thumb2 target-feature, tail call is allowed and must be widened. +; CHECK: f: +; CHECK: b g + +define dso_local void @h() local_unnamed_addr #2 { +entry: + tail call void bitcast (void (...)* @g to void ()*)() #3 + ret void +} +; Function does not have thumb2 target-feature, tail call should not be +; generated as it cannot be widened. +; CHECK: h: +; CHECK: bl g + +attributes #0 = { nounwind "disable-tail-calls"="false" "target-cpu"="cortex-a53" "target-features"="+crypto,+fp-armv8,+neon,+soft-float-abi,+strict-align,+thumb-mode,-crc,-dotprod,-dsp,-hwdiv,-hwdiv-arm,-ras" "use-soft-float"="true" } + +attributes #2 = { nounwind "disable-tail-calls"="false" "target-cpu"="arm7tdmi" "target-features"="+strict-align,+thumb-mode,-crc,-dotprod,-dsp,-hwdiv,-hwdiv-arm,-ras" "unsafe-fp-math"="false" "use-soft-float"="true" } +attributes #3 = { nounwind } diff --git a/llvm/test/MC/ARM/AlignedBundling/illegal-subtarget-change.s b/llvm/test/MC/ARM/AlignedBundling/illegal-subtarget-change.s new file mode 100644 index 000000000000..34d88918a349 --- /dev/null +++ b/llvm/test/MC/ARM/AlignedBundling/illegal-subtarget-change.s @@ -0,0 +1,16 @@ +# RUN: not llvm-mc -filetype=obj -triple armv7-linux-gnueabi %s -o - 2>&1 | FileCheck %s + + # We cannot switch subtargets mid-bundle + .syntax unified + .text + .bundle_align_mode 4 + .arch armv4t + bx lr + .bundle_lock + bx lr + .arch armv7a + movt r0, #0xffff + movw r0, #0xffff + .bundle_unlock + bx lr +# CHECK: LLVM ERROR: A Bundle can only have one Subtarget. diff --git a/llvm/test/MC/ARM/AlignedBundling/subtarget-change.s b/llvm/test/MC/ARM/AlignedBundling/subtarget-change.s new file mode 100644 index 000000000000..a06b83899c34 --- /dev/null +++ b/llvm/test/MC/ARM/AlignedBundling/subtarget-change.s @@ -0,0 +1,33 @@ +# RUN: llvm-mc -filetype=obj -triple armv7-linux-gnueabi %s -o - \ +# RUN: | llvm-objdump -no-show-raw-insn -triple armv7 -disassemble - | FileCheck %s + + # We can switch subtargets with .arch outside of a bundle + .syntax unified + .text + .bundle_align_mode 4 + .arch armv4t + bx lr + .bundle_lock + and r1, r1, r1 + and r1, r1, r1 + .bundle_unlock + bx lr + + # We can switch subtargets at the start of a bundle + bx lr + .bundle_lock align_to_end + .arch armv7a + movt r0, #0xffff + movw r0, #0xffff + .bundle_unlock + bx lr + +# CHECK: 0: bx lr +# CHECK-NEXT: 4: and r1, r1, r1 +# CHECK-NEXT: 8: and r1, r1, r1 +# CHECK-NEXT: c: bx lr +# CHECK-NEXT: 10: bx lr +# CHECK-NEXT: 14: nop +# CHECK-NEXT: 18: movt r0, #65535 +# CHECK-NEXT: 1c: movw r0, #65535 +# CHECK-NEXT: 20: bx lr diff --git a/llvm/test/MC/ARM/fixup-per-fragment.s b/llvm/test/MC/ARM/fixup-per-fragment.s new file mode 100644 index 000000000000..a127a396528f --- /dev/null +++ b/llvm/test/MC/ARM/fixup-per-fragment.s @@ -0,0 +1,20 @@ +@ RUN: not llvm-mc -triple armv7a-linux-gnueabihf %s -filetype=obj -o %s.o 2>&1 | FileCheck %s + +@ The relaxations should be applied using the subtarget from the fragment +@ containing the fixup and not the per module subtarget. + + .syntax unified + .thumb + @ Place a literal pool out of range of the 16-bit ldr but within + @ range of the 32-bit ldr.w + .text + @ Relaxation to ldr.w as target triple supports Thumb2 + ldr r0,=0x12345678 + .arch armv4t + @ No relaxation as v4t does not support Thumb + @ expect out of range error message + ldr r0,=0x87654321 + .space 1024 + +@ CHECK: error: out of range pc-relative fixup value +@ CHECK-NEXT: ldr r0,=0x87654321 diff --git a/llvm/test/MC/X86/AlignedBundling/bundle-subtarget-change-error.s b/llvm/test/MC/X86/AlignedBundling/bundle-subtarget-change-error.s new file mode 100644 index 000000000000..67ac55ed2f03 --- /dev/null +++ b/llvm/test/MC/X86/AlignedBundling/bundle-subtarget-change-error.s @@ -0,0 +1,16 @@ +# RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro %s -o - 2>&1 | FileCheck %s +# RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro -mc-relax-all %s -o - 2>&1 | FileCheck %s + +# Switching mode will change subtarget, which we can't do within a bundle + .text + .code64 + .bundle_align_mode 4 +foo: + pushq %rbp + .bundle_lock + addl %ebp, %eax + .code32 + movb $0x0, (%si) + .bundle_unlock + +CHECK: LLVM ERROR: A Bundle can only have one Subtarget.