summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/MC/MCAsmBackend.h10
-rw-r--r--llvm/include/llvm/MC/MCFragment.h23
-rw-r--r--llvm/include/llvm/MC/MCObjectStreamer.h7
-rw-r--r--llvm/include/llvm/MC/MCStreamer.h3
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp6
-rw-r--r--llvm/lib/MC/MCAssembler.cpp13
-rw-r--r--llvm/lib/MC/MCELFStreamer.cpp30
-rw-r--r--llvm/lib/MC/MCMachOStreamer.cpp1
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp29
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp4
-rw-r--r--llvm/lib/MC/MCWasmStreamer.cpp5
-rw-r--r--llvm/lib/MC/MCWinCOFFStreamer.cpp2
-rw-r--r--llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp12
-rw-r--r--llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp11
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp41
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h16
-rw-r--r--llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp11
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp12
-rw-r--r--llvm/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp9
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp3
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h6
-rw-r--r--llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp6
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp6
-rw-r--r--llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp9
-rw-r--r--llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp9
-rw-r--r--llvm/test/CodeGen/ARM/relax-per-target-feature.ll34
-rw-r--r--llvm/test/MC/ARM/AlignedBundling/illegal-subtarget-change.s16
-rw-r--r--llvm/test/MC/ARM/AlignedBundling/subtarget-change.s33
-rw-r--r--llvm/test/MC/ARM/fixup-per-fragment.s20
-rw-r--r--llvm/test/MC/X86/AlignedBundling/bundle-subtarget-change-error.s16
30 files changed, 314 insertions, 89 deletions
diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h
index 1272829b1f6..030d3c05aa5 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<char> 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 95878f81c86..16eb124d95e 100644
--- a/llvm/include/llvm/MC/MCFragment.h
+++ b/llvm/include/llvm/MC/MCFragment.h
@@ -201,7 +201,16 @@ protected:
: MCEncodedFragmentWithContents<ContentsSize>(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<MCFixup>::const_iterator;
using fixup_iterator = SmallVectorImpl<MCFixup>::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 498a8af9011..8715a16e705 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 db4f885a7d9..43712de727b 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 1b3d32d3033..d07f3cac410 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 0cf17a10d08..94857d94555 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -805,12 +805,17 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
continue;
ArrayRef<MCFixup> Fixups;
MutableArrayRef<char> Contents;
+ const MCSubtargetInfo *STI = nullptr;
if (auto *FragWithFixups = dyn_cast<MCDataFragment>(&Frag)) {
Fixups = FragWithFixups->getFixups();
Contents = FragWithFixups->getContents();
+ STI = FragWithFixups->getSubtargetInfo();
+ assert(!FragWithFixups->hasInstructions() || STI != nullptr);
} else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(&Frag)) {
Fixups = FragWithFixups->getFixups();
Contents = FragWithFixups->getContents();
+ STI = FragWithFixups->getSubtargetInfo();
+ assert(!FragWithFixups->hasInstructions() || STI != nullptr);
} else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&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<MCFixup, 4> 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 b112bd9639d..df11495a954 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<MCDataFragment>(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 d4924a1edfe..4b74c569531 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 3ed9a6fbf6b..5159cfee7a8 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<MCDataFragment>(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<MCDataFragment>(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<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name);
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index b43839db2d0..5c8946b286b 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 a74d37529cc..2c65371cf3a 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 9fc60ab1bf9..32dc46c61d0 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 c39111478f0..85694655519 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<char> 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<char> 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 cf4964ebeea..abc88c02adc 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<char> 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<char> 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 4a7bf8cc33c..f524a008130 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<char> 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 b72f45d0717..88c476bf65f 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<char> 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 b36b01c7b73..6c255e9ef78 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<char> Data,
- uint64_t Value, bool IsResolved) const override;
+ uint64_t Value, bool IsResolved,
+ const MCSubtargetInfo *STI) const override;
std::unique_ptr<MCObjectTargetWriter>
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<char> 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 2bbdfb95970..af1e5429d0c 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<MCFixup, 4> 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<char> 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 0d01729d393..85fffd9a7c7 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<char> Data,
- uint64_t Value, bool IsResolved) const override;
+ uint64_t Value, bool IsResolved,
+ const MCSubtargetInfo *STI) const override;
std::unique_ptr<MCObjectTargetWriter>
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<char> Data, uint64_t Value,
- bool /*IsResolved*/) const {
+ bool /*IsResolved*/,
+ const MCSubtargetInfo */*STI*/) const {
MCFixupKind Kind = Fixup.getKind();
Value = adjustFixupValue(static_cast<unsigned>(Kind), Value);
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
index 1d01e521ece..4397c971d08 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<char> 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 c66b7ffd27d..3d5e16fcf9b 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<char> Data,
- uint64_t Value, bool IsResolved) const override;
+ uint64_t Value, bool IsResolved,
+ const MCSubtargetInfo *STI) const override;
Optional<MCFixupKind> 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 559365323df..a405dd70c30 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<char> 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 2ef4655a889..4b6c1de7d85 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<char> 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 96e38a6db9e..2146832f779 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<char> 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<char> 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 b91b4508978..0e4c4398e49 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<char> 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 00000000000..769c82b51d6
--- /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 00000000000..34d88918a34
--- /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 00000000000..a06b83899c3
--- /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 00000000000..a127a396528
--- /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 00000000000..67ac55ed2f0
--- /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.
OpenPOWER on IntegriCloud