diff options
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r-- | llvm/lib/MC/MCAsmStreamer.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/MC/MCELFStreamer.cpp | 30 | ||||
-rw-r--r-- | llvm/lib/MC/MCMachOStreamer.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/MC/MCObjectStreamer.cpp | 29 | ||||
-rw-r--r-- | llvm/lib/MC/MCParser/AsmParser.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/MC/MCWasmStreamer.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/MC/MCWinCOFFStreamer.cpp | 2 |
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()); } |