summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC')
-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
8 files changed, 64 insertions, 26 deletions
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());
}
OpenPOWER on IntegriCloud