diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h --- a/llvm/include/llvm/MC/MCAsmBackend.h +++ b/llvm/include/llvm/MC/MCAsmBackend.h @@ -55,7 +55,8 @@ /// Give the target a chance to manipulate state related to instruction /// alignment (e.g. padding for optimization), instruction relaxablility, etc. /// before and after actually emitting the instruction. - virtual void emitInstructionBegin(MCObjectStreamer &OS, const MCInst &Inst) {} + virtual void emitInstructionBegin(MCObjectStreamer &OS, const MCInst &Inst, + const MCSubtargetInfo &STI) {} virtual void emitInstructionEnd(MCObjectStreamer &OS, const MCInst &Inst) {} /// lifetime management @@ -185,13 +186,16 @@ /// Returns the maximum size of a nop in bytes on this target. /// - virtual unsigned getMaximumNopSize() const { return 0; } + virtual unsigned getMaximumNopSize(const MCSubtargetInfo &STI) const { + return 0; + } /// Write an (optimal) nop sequence of Count bytes to the given output. If the /// target cannot generate such a sequence, it should return an error. /// /// \return - True on success. - virtual bool writeNopData(raw_ostream &OS, uint64_t Count) const = 0; + virtual bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const = 0; /// Give backend an opportunity to finish layout after relaxation virtual void finishLayout(MCAssembler const &Asm, diff --git a/llvm/include/llvm/MC/MCFragment.h b/llvm/include/llvm/MC/MCFragment.h --- a/llvm/include/llvm/MC/MCFragment.h +++ b/llvm/include/llvm/MC/MCFragment.h @@ -377,17 +377,22 @@ /// Source location of the directive that this fragment was created for. SMLoc Loc; + /// When emitting Nops some subtargets have specific nop encodings. + const MCSubtargetInfo &STI; + public: MCNopsFragment(int64_t NumBytes, int64_t ControlledNopLength, SMLoc L, - MCSection *Sec = nullptr) + const MCSubtargetInfo &STI, MCSection *Sec = nullptr) : MCFragment(FT_Nops, false, Sec), Size(NumBytes), - ControlledNopLength(ControlledNopLength), Loc(L) {} + ControlledNopLength(ControlledNopLength), Loc(L), STI(STI) {} int64_t getNumBytes() const { return Size; } int64_t getControlledNopLength() const { return ControlledNopLength; } SMLoc getLoc() const { return Loc; } + const MCSubtargetInfo *getSubtargetInfo() const { return &STI; } + static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Nops; } @@ -580,10 +585,14 @@ /// is not meaningful before that. uint64_t Size = 0; + /// When emitting Nops some subtargets have specific nop encodings. + const MCSubtargetInfo &STI; + public: - MCBoundaryAlignFragment(Align AlignBoundary, MCSection *Sec = nullptr) - : MCFragment(FT_BoundaryAlign, false, Sec), AlignBoundary(AlignBoundary) { - } + MCBoundaryAlignFragment(Align AlignBoundary, const MCSubtargetInfo &STI, + MCSection *Sec = nullptr) + : MCFragment(FT_BoundaryAlign, false, Sec), AlignBoundary(AlignBoundary), + STI(STI) {} uint64_t getSize() const { return Size; } void setSize(uint64_t Value) { Size = Value; } @@ -597,6 +606,8 @@ LastFragment = F; } + const MCSubtargetInfo *getSubtargetInfo() const { return &STI; } + static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_BoundaryAlign; } diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -181,8 +181,8 @@ SMLoc Loc = SMLoc()) override; void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, SMLoc Loc = SMLoc()) override; - void emitNops(int64_t NumBytes, int64_t ControlledNopLength, - SMLoc Loc) override; + void emitNops(int64_t NumBytes, int64_t ControlledNopLength, SMLoc Loc, + const MCSubtargetInfo &STI) override; void emitFileDirective(StringRef Filename) override; void emitFileDirective(StringRef Filename, StringRef CompilerVerion, StringRef TimeStamp, StringRef Description) override; diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -799,7 +799,7 @@ SMLoc Loc = SMLoc()); virtual void emitNops(int64_t NumBytes, int64_t ControlledNopLength, - SMLoc Loc); + SMLoc Loc, const MCSubtargetInfo& STI); /// Emit NumBytes worth of zeros. /// This function properly handles data in virtual sections. diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -483,6 +483,7 @@ "Writing bundle padding for a fragment without instructions"); unsigned TotalLength = BundlePadding + static_cast(FSize); + const MCSubtargetInfo *STI = EF.getSubtargetInfo(); if (EF.alignToBundleEnd() && TotalLength > getBundleAlignSize()) { // If the padding itself crosses a bundle boundary, it must be emitted // in 2 pieces, since even nop instructions must not cross boundaries. @@ -493,12 +494,12 @@ // ---------------------------- // ^-------------------^ <- TotalLength unsigned DistanceToBoundary = TotalLength - getBundleAlignSize(); - if (!getBackend().writeNopData(OS, DistanceToBoundary)) + if (!getBackend().writeNopData(OS, DistanceToBoundary, STI)) report_fatal_error("unable to write NOP sequence of " + Twine(DistanceToBoundary) + " bytes"); BundlePadding -= DistanceToBoundary; } - if (!getBackend().writeNopData(OS, BundlePadding)) + if (!getBackend().writeNopData(OS, BundlePadding, STI)) report_fatal_error("unable to write NOP sequence of " + Twine(BundlePadding) + " bytes"); } @@ -544,7 +545,7 @@ // 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()) { - if (!Asm.getBackend().writeNopData(OS, Count)) + if (!Asm.getBackend().writeNopData(OS, Count, AF.getSubtargetInfo())) report_fatal_error("unable to write nop sequence of " + Twine(Count) + " bytes"); break; @@ -621,9 +622,11 @@ case MCFragment::FT_Nops: { ++stats::EmittedNopsFragments; const MCNopsFragment &NF = cast(F); + int64_t NumBytes = NF.getNumBytes(); int64_t ControlledNopLength = NF.getControlledNopLength(); - int64_t MaximumNopLength = Asm.getBackend().getMaximumNopSize(); + int64_t MaximumNopLength = + Asm.getBackend().getMaximumNopSize(*NF.getSubtargetInfo()); assert(NumBytes > 0 && "Expected positive NOPs fragment size"); assert(ControlledNopLength >= 0 && "Expected non-negative NOP size"); @@ -647,7 +650,8 @@ uint64_t NumBytesToEmit = (uint64_t)std::min(NumBytes, ControlledNopLength); assert(NumBytesToEmit && "try to emit empty NOP instruction"); - if (!Asm.getBackend().writeNopData(OS, NumBytesToEmit)) { + if (!Asm.getBackend().writeNopData(OS, NumBytesToEmit, + NF.getSubtargetInfo())) { report_fatal_error("unable to write nop sequence of the remaining " + Twine(NumBytesToEmit) + " bytes"); break; @@ -664,7 +668,8 @@ } case MCFragment::FT_BoundaryAlign: { - if (!Asm.getBackend().writeNopData(OS, FragmentSize)) + const MCBoundaryAlignFragment &BF = cast(F); + if (!Asm.getBackend().writeNopData(OS, FragmentSize, BF.getSubtargetInfo())) report_fatal_error("unable to write nop sequence of " + Twine(FragmentSize) + " bytes"); break; diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -368,7 +368,7 @@ "' cannot have instructions"); return; } - getAssembler().getBackend().emitInstructionBegin(*this, Inst); + getAssembler().getBackend().emitInstructionBegin(*this, Inst, STI); emitInstructionImpl(Inst, STI); getAssembler().getBackend().emitInstructionEnd(*this, Inst); } @@ -836,13 +836,14 @@ } void MCObjectStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLength, - SMLoc Loc) { + SMLoc Loc, const MCSubtargetInfo &STI) { // Emit an NOP fragment. MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); assert(getCurrentSectionOnly() && "need a section"); - insert(new MCNopsFragment(NumBytes, ControlledNopLength, Loc)); + + insert(new MCNopsFragment(NumBytes, ControlledNopLength, Loc, STI)); } void MCObjectStreamer::emitFileDirective(StringRef Filename) { diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -220,7 +220,7 @@ } void llvm::MCStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLen, - llvm::SMLoc) {} + llvm::SMLoc, const MCSubtargetInfo& STI) {} /// The implementation in this class just redirects to emitFill. void MCStreamer::emitZeros(uint64_t NumBytes) { emitFill(NumBytes, 0); } diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -92,7 +92,8 @@ const MCAsmLayout &Layout) const override; void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override; - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; unsigned getFixupKindContainereSizeInBytes(unsigned Kind) const; @@ -456,7 +457,8 @@ llvm_unreachable("AArch64AsmBackend::relaxInstruction() unimplemented"); } -bool AArch64AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +bool AArch64AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { // If the count is not 4-byte aligned, we must be writing data into the text // section (otherwise we have unaligned instructions, and thus have far // bigger problems), so just write zeros instead. diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp @@ -44,7 +44,8 @@ const MCSubtargetInfo &STI) const override; unsigned getMinimumNopSize() const override; - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; }; @@ -169,7 +170,8 @@ return 4; } -bool AMDGPUAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +bool AMDGPUAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { // If the count is not 4-byte aligned, we must be writing data into the text // section (otherwise we have unaligned instructions, and thus have far // bigger problems), so just write zeros instead. diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h @@ -18,24 +18,18 @@ 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: - ARMAsmBackend(const Target &T, const MCSubtargetInfo &STI, - support::endianness Endian) - : MCAsmBackend(Endian), STI(STI), - isThumbMode(STI.getTargetTriple().isThumb()) {} + ARMAsmBackend(const Target &T, bool isThumb, support::endianness Endian) + : MCAsmBackend(Endian), isThumbMode(isThumb) {} unsigned getNumFixupKinds() const override { return ARM::NumTargetFixupKinds; } - // FIXME: this should be calculated per fragment as the STI may be - // different. - bool hasNOP() const { return STI.getFeatureBits()[ARM::HasV6T2Ops]; } + bool hasNOP(const MCSubtargetInfo *STI) const { + return STI->getFeatureBits()[ARM::HasV6T2Ops]; + } Optional getFixupKind(StringRef Name) const override; @@ -69,7 +63,8 @@ void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override; - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; void handleAssemblerFlag(MCAssemblerFlag Flag) override; diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -48,9 +48,10 @@ } // end anonymous namespace Optional ARMAsmBackend::getFixupKind(StringRef Name) const { - if (!STI.getTargetTriple().isOSBinFormatELF()) - return None; + return None; +} +Optional ARMAsmBackendELF::getFixupKind(StringRef Name) const { unsigned Type = llvm::StringSwitch(Name) #define ELF_RELOC(X, Y) .Case(#X, Y) #include "llvm/BinaryFormat/ELFRelocs/ARM.def" @@ -357,14 +358,15 @@ Inst.setOpcode(RelaxedOp); } -bool ARMAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +bool ARMAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8 const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP const uint32_t ARMv4_NopEncoding = 0xe1a00000; // using MOV r0,r0 const uint32_t ARMv6T2_NopEncoding = 0xe320f000; // NOP if (isThumb()) { const uint16_t nopEncoding = - hasNOP() ? Thumb2_16bitNopEncoding : Thumb1_16bitNopEncoding; + hasNOP(STI) ? Thumb2_16bitNopEncoding : Thumb1_16bitNopEncoding; uint64_t NumNops = Count / 2; for (uint64_t i = 0; i != NumNops; ++i) support::endian::write(OS, nopEncoding, Endian); @@ -374,7 +376,7 @@ } // ARM mode const uint32_t nopEncoding = - hasNOP() ? ARMv6T2_NopEncoding : ARMv4_NopEncoding; + hasNOP(STI) ? ARMv6T2_NopEncoding : ARMv4_NopEncoding; uint64_t NumNops = Count / 4; for (uint64_t i = 0; i != NumNops; ++i) support::endian::write(OS, nopEncoding, Endian); @@ -1300,11 +1302,12 @@ return new ARMAsmBackendDarwin(T, STI, MRI); case Triple::COFF: assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported"); - return new ARMAsmBackendWinCOFF(T, STI); + return new ARMAsmBackendWinCOFF(T, STI.getTargetTriple().isThumb()); case Triple::ELF: assert(TheTriple.isOSBinFormatELF() && "using ELF for non-ELF target"); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); - return new ARMAsmBackendELF(T, STI, OSABI, Endian); + return new ARMAsmBackendELF(T, STI.getTargetTriple().isThumb(), OSABI, + Endian); } } diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h @@ -21,8 +21,8 @@ const MachO::CPUSubTypeARM Subtype; ARMAsmBackendDarwin(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI) - : ARMAsmBackend(T, STI, support::little), MRI(MRI), - TT(STI.getTargetTriple()), + : ARMAsmBackend(T, STI.getTargetTriple().isThumb(), support::little), + MRI(MRI), TT(STI.getTargetTriple()), Subtype((MachO::CPUSubTypeARM)cantFail( MachO::getCPUSubType(STI.getTargetTriple()))) {} diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendELF.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendELF.h --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendELF.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendELF.h @@ -19,14 +19,16 @@ class ARMAsmBackendELF : public ARMAsmBackend { public: uint8_t OSABI; - ARMAsmBackendELF(const Target &T, const MCSubtargetInfo &STI, uint8_t OSABI, + ARMAsmBackendELF(const Target &T, bool isThumb, uint8_t OSABI, support::endianness Endian) - : ARMAsmBackend(T, STI, Endian), OSABI(OSABI) {} + : ARMAsmBackend(T, isThumb, Endian), OSABI(OSABI) {} std::unique_ptr createObjectTargetWriter() const override { return createARMELFObjectWriter(OSABI); } + + Optional getFixupKind(StringRef Name) const override; }; } diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendWinCOFF.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendWinCOFF.h --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendWinCOFF.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendWinCOFF.h @@ -16,8 +16,8 @@ namespace { class ARMAsmBackendWinCOFF : public ARMAsmBackend { public: - ARMAsmBackendWinCOFF(const Target &T, const MCSubtargetInfo &STI) - : ARMAsmBackend(T, STI, support::little) {} + ARMAsmBackendWinCOFF(const Target &T, bool isThumb) + : ARMAsmBackend(T, isThumb, support::little) {} std::unique_ptr createObjectTargetWriter() const override { return createARMWinCOFFObjectWriter(); diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h @@ -55,7 +55,8 @@ return false; } - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target) override; diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp @@ -458,7 +458,8 @@ return Infos[Kind - FirstTargetFixupKind]; } -bool AVRAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +bool AVRAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { // If the count is not 2-byte aligned, we must be writing data into the text // section (otherwise we have unaligned instructions, and thus have far // bigger problems), so just write zeros instead. diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp --- a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp +++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp @@ -43,12 +43,14 @@ unsigned getNumFixupKinds() const override { return 1; } - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; }; } // end anonymous namespace -bool BPFAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +bool BPFAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { if ((Count % 8) != 0) return false; diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h @@ -39,7 +39,8 @@ void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override; - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; std::unique_ptr createObjectTargetWriter() const override; diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp @@ -145,7 +145,8 @@ llvm_unreachable("CSKYAsmBackend::relaxInstruction() unimplemented"); } -bool CSKYAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +bool CSKYAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { if (Count % 2) return false; diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp --- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp +++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp @@ -686,10 +686,11 @@ assert(Update && "Didn't find relaxation target"); } - bool writeNopData(raw_ostream &OS, uint64_t Count) const override { - static const uint32_t Nopcode = 0x7f000000, // Hard-coded NOP. - ParseIn = 0x00004000, // In packet parse-bits. - ParseEnd = 0x0000c000; // End of packet parse-bits. + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override { + static const uint32_t Nopcode = 0x7f000000, // Hard-coded NOP. + ParseIn = 0x00004000, // In packet parse-bits. + ParseEnd = 0x0000c000; // End of packet parse-bits. while (Count % HEXAGON_INSTR_SIZE) { LLVM_DEBUG(dbgs() << "Alignment not a multiple of the instruction size:" diff --git a/llvm/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp b/llvm/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp --- a/llvm/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp +++ b/llvm/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp @@ -69,10 +69,12 @@ return Lanai::NumTargetFixupKinds; } - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; }; -bool LanaiAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +bool LanaiAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { if ((Count % 4) != 0) return false; diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp --- a/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp +++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp @@ -82,7 +82,8 @@ /// Write a sequence of optimal nops to the output, covering \p Count bytes. /// \return - true on success, false on failure - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; }; } // end anonymous namespace @@ -200,7 +201,8 @@ Inst.setOpcode(RelaxedOp); } -bool M68kAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +bool M68kAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { // Cannot emit NOP with size being not multiple of 16 bits. if (Count % 2 != 0) return false; diff --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp --- a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp +++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp @@ -90,7 +90,8 @@ return Infos[Kind - FirstTargetFixupKind]; } - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; }; uint64_t MSP430AsmBackend::adjustFixupValue(const MCFixup &Fixup, @@ -147,7 +148,8 @@ } } -bool MSP430AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +bool MSP430AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { if ((Count % 2) != 0) return false; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h @@ -63,7 +63,8 @@ return false; } - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target) override; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -518,7 +518,8 @@ /// it should return an error. /// /// \return - True on success. -bool MipsAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +bool MipsAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { // Check for a less than instruction size number of bytes // FIXME: 16 bit instructions are not handled yet here. // We shouldn't be using a hard coded number for instruction size. diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -196,7 +196,8 @@ llvm_unreachable("relaxInstruction() unimplemented"); } - bool writeNopData(raw_ostream &OS, uint64_t Count) const override { + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override { uint64_t NumNops = Count / 4; for (uint64_t i = 0; i != NumNops; ++i) support::endian::write(OS, 0x60000000, Endian); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -99,7 +99,8 @@ bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, MCAsmLayout &Layout, bool &WasRelaxed) const override; - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; const MCTargetOptions &getTargetOptions() const { return TargetOptions; } RISCVABI::ABI getTargetABI() const { return TargetABI; } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -352,8 +352,9 @@ return getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode(); } -bool RISCVAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { - bool HasStdExtC = STI.getFeatureBits()[RISCV::FeatureStdExtC]; +bool RISCVAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { + bool HasStdExtC = STI->getFeatureBits()[RISCV::FeatureStdExtC]; unsigned MinNopLen = HasStdExtC ? 2 : 4; if ((Count % MinNopLen) != 0) diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -274,7 +274,8 @@ llvm_unreachable("relaxInstruction() unimplemented"); } - bool writeNopData(raw_ostream &OS, uint64_t Count) const override { + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override { // Cannot emit NOP with size not multiple of 32 bits. if (Count % 4 != 0) return false; diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp @@ -63,7 +63,8 @@ const MCAsmLayout &Layout) const override { return false; } - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; std::unique_ptr createObjectTargetWriter() const override { return createSystemZObjectWriter(OSABI); @@ -142,7 +143,8 @@ } } -bool SystemZMCAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +bool SystemZMCAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { for (uint64_t I = 0; I != Count; ++I) OS << '\x7'; return true; diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp --- a/llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp +++ b/llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp @@ -164,7 +164,8 @@ llvm_unreachable("relaxInstruction() should not be called"); } - bool writeNopData(raw_ostream &OS, uint64_t Count) const override { + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override { if ((Count % 8) != 0) return false; diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp @@ -59,7 +59,8 @@ return false; } - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; }; const MCFixupKindInfo & @@ -83,8 +84,8 @@ return Infos[Kind - FirstTargetFixupKind]; } -bool WebAssemblyAsmBackend::writeNopData(raw_ostream &OS, - uint64_t Count) const { +bool WebAssemblyAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { for (uint64_t I = 0; I < Count; ++I) OS << char(WebAssembly::Nop); diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -4855,7 +4855,7 @@ bool X86AsmParser::parseDirectiveNops(SMLoc L) { int64_t NumBytes = 0, Control = 0; SMLoc NumBytesLoc, ControlLoc; - const MCSubtargetInfo STI = getSTI(); + const MCSubtargetInfo& STI = getSTI(); NumBytesLoc = getTok().getLoc(); if (getParser().checkForValidSection() || getParser().parseAbsoluteExpression(NumBytes)) @@ -4881,7 +4881,7 @@ } /// Emit nops - getParser().getStreamer().emitNops(NumBytes, Control, L); + getParser().getStreamer().emitNops(NumBytes, Control, L, STI); return false; } diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -166,7 +166,8 @@ bool allowAutoPadding() const override; bool allowEnhancedRelaxation() const override; - void emitInstructionBegin(MCObjectStreamer &OS, const MCInst &Inst) override; + void emitInstructionBegin(MCObjectStreamer &OS, const MCInst &Inst, + const MCSubtargetInfo &STI) override; void emitInstructionEnd(MCObjectStreamer &OS, const MCInst &Inst) override; unsigned getNumFixupKinds() const override { @@ -207,9 +208,10 @@ void finishLayout(MCAssembler const &Asm, MCAsmLayout &Layout) const override; - unsigned getMaximumNopSize() const override; + unsigned getMaximumNopSize(const MCSubtargetInfo &STI) const override; - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; }; } // end anonymous namespace @@ -598,7 +600,7 @@ /// Insert BoundaryAlignFragment before instructions to align branches. void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS, - const MCInst &Inst) { + const MCInst &Inst, const MCSubtargetInfo &STI) { CanPadInst = canPadInst(Inst, OS); if (!canPadBranches(OS)) @@ -637,7 +639,7 @@ isFirstMacroFusibleInst(Inst, *MCII))) { // If we meet a unfused branch or the first instuction in a fusiable pair, // insert a BoundaryAlign fragment. - OS.insert(PendingBA = new MCBoundaryAlignFragment(AlignBoundary)); + OS.insert(PendingBA = new MCBoundaryAlignFragment(AlignBoundary, STI)); } } @@ -1081,7 +1083,7 @@ } } -unsigned X86AsmBackend::getMaximumNopSize() const { +unsigned X86AsmBackend::getMaximumNopSize(const MCSubtargetInfo &STI) const { if (STI.hasFeature(X86::Mode16Bit)) return 4; if (!STI.hasFeature(X86::FeatureNOPL) && !STI.hasFeature(X86::Mode64Bit)) @@ -1101,7 +1103,8 @@ /// Write a sequence of optimal nops to the output, covering \p Count /// bytes. /// \return - true on success, false on failure -bool X86AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +bool X86AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { static const char Nops32Bit[10][11] = { // nop "\x90", @@ -1138,9 +1141,9 @@ }; const char(*Nops)[11] = - STI.getFeatureBits()[X86::Mode16Bit] ? Nops16Bit : Nops32Bit; + STI->getFeatureBits()[X86::Mode16Bit] ? Nops16Bit : Nops32Bit; - uint64_t MaxNopLength = (uint64_t)getMaximumNopSize(); + uint64_t MaxNopLength = (uint64_t)getMaximumNopSize(*STI); // Emit as many MaxNopLength NOPs as needed, then emit a NOP of the remaining // length. diff --git a/llvm/test/CodeGen/ARM/subtarget-align.ll b/llvm/test/CodeGen/ARM/subtarget-align.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/subtarget-align.ll @@ -0,0 +1,39 @@ +; RUN: llc -mtriple=arm-linux-gnueabihf -filetype=obj <%s | llvm-objdump --triple=armv7 --no-show-raw-insn -d - | FileCheck %s + +;; Expect architectural nop to be used between func2 and func3 but not func1 +;; and func2 due to lack of subtarget support in func2. + +define i32 @func1() #0 align 16 { +entry: + ret i32 0 +} + +define i32 @func2() #1 align 16 { +entry: + ret i32 0 +} + +define i32 @func3() #0 align 16 { +entry: + ret i32 0 +} + +attributes #0 = { "target-cpu"="generic" "target-features"="+armv7-a,+dsp,+neon,+vfp3,-thumb-mode" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "target-cpu"="arm7tdmi" "target-features"="+armv4t" "use-soft-float"="true" } + + +; CHECK: 00000000 : +; CHECK-NEXT: 0: mov r0, #0 +; CHECK-NEXT: 4: bx lr +; CHECK-NEXT: 8: mov r0, r0 +; CHECK-NEXT: c: mov r0, r0 + +; CHECK: 00000010 : +; CHECK-NEXT: 10: mov r0, #0 +; CHECK-NEXT: 14: bx lr +; CHECK-NEXT: 18: nop +; CHECK-NEXT: 1c: nop + +; CHECK: 00000020 : +; CHECK-NEXT: 20: mov r0, #0 +; CHECK-NEXT: 24: bx lr diff --git a/llvm/test/MC/ARM/subtarget-nop.s b/llvm/test/MC/ARM/subtarget-nop.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ARM/subtarget-nop.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc %s --triple=arm-linux-gnueabihf -filetype=obj | llvm-objdump --no-show-raw-insn --triple=armv7 -d - | FileCheck %s + +// Check that the architectural nop is only produced for subtargets that +// support it. This includes nop padding for alignment. + .syntax unified + .arch armv6 +foo: + mov r1, r0 + nop + .p2align 4 + bx lr + + .arch armv7-a +bar: + mov r1, r0 + nop + .p2align 4 + bx lr + + .arch armv4t +baz: + mov r1, r0 + nop + .p2align 4 + bx lr + +// CHECK: 00000000 : +// CHECK-NEXT: 0: mov r1, r0 +// CHECK-NEXT: 4: mov r0, r0 +// CHECK-NEXT: 8: mov r0, r0 +// CHECK-NEXT: c: mov r0, r0 +// CHECK-NEXT: 10: bx lr + +// CHECK: 00000014 : +// CHECK-NEXT: 14: mov r1, r0 +// CHECK-NEXT: 18: nop +// CHECK-NEXT: 1c: nop +// CHECK-NEXT: 20: bx lr + +// CHECK: 00000024 : +// CHECK-NEXT: 24: mov r1, r0 +// CHECK-NEXT: 28: mov r0, r0 +// CHECK-NEXT: 2c: mov r0, r0 +// CHECK-NEXT: 30: bx lr diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp @@ -135,7 +135,7 @@ C.Streamer->emitCFIStartProc(true); auto Str = EncodeDefCfaExpr(ExprBytes); C.Streamer->emitCFIEscape(Str); - C.Streamer->emitNops(4, 1, SMLoc()); + C.Streamer->emitNops(4, 1, SMLoc(), *STI); C.Streamer->emitCFIEndProc(); C.Streamer->Finish(); return Storage;