summaryrefslogtreecommitdiff
path: root/llvm/lib/MC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-01-17 20:45:01 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-01-17 20:45:01 +0000
commit706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch)
tree4adf86a776049cbf7f69a1929c4babcbbef925eb /llvm/lib/MC
parent7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff)
Notes
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r--llvm/lib/MC/ELFObjectWriter.cpp26
-rw-r--r--llvm/lib/MC/MCAsmBackend.cpp26
-rw-r--r--llvm/lib/MC/MCAsmInfo.cpp2
-rw-r--r--llvm/lib/MC/MCAsmInfoELF.cpp2
-rw-r--r--llvm/lib/MC/MCAsmInfoXCOFF.cpp9
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp19
-rw-r--r--llvm/lib/MC/MCAssembler.cpp104
-rw-r--r--llvm/lib/MC/MCCodePadder.cpp370
-rw-r--r--llvm/lib/MC/MCContext.cpp7
-rw-r--r--llvm/lib/MC/MCDisassembler/Disassembler.cpp11
-rw-r--r--llvm/lib/MC/MCDisassembler/MCDisassembler.cpp15
-rw-r--r--llvm/lib/MC/MCDwarf.cpp3
-rw-r--r--llvm/lib/MC/MCELFStreamer.cpp9
-rw-r--r--llvm/lib/MC/MCExpr.cpp2
-rw-r--r--llvm/lib/MC/MCFragment.cpp56
-rw-r--r--llvm/lib/MC/MCInstPrinter.cpp90
-rw-r--r--llvm/lib/MC/MCObjectFileInfo.cpp38
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp130
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp90
-rw-r--r--llvm/lib/MC/MCParser/COFFAsmParser.cpp2
-rw-r--r--llvm/lib/MC/MCSection.cpp38
-rw-r--r--llvm/lib/MC/MCSectionXCOFF.cpp28
-rw-r--r--llvm/lib/MC/MCStreamer.cpp10
-rw-r--r--llvm/lib/MC/MCSymbolELF.cpp4
-rw-r--r--llvm/lib/MC/MCTargetOptions.cpp4
-rw-r--r--llvm/lib/MC/MCValue.cpp5
-rw-r--r--llvm/lib/MC/MCXCOFFStreamer.cpp11
-rw-r--r--llvm/lib/MC/WasmObjectWriter.cpp12
-rw-r--r--llvm/lib/MC/XCOFFObjectWriter.cpp368
29 files changed, 709 insertions, 782 deletions
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index 6f160e491cea5..6b4b45eb8effa 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -569,26 +569,6 @@ void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
IsReserved);
}
-// True if the assembler knows nothing about the final value of the symbol.
-// This doesn't cover the comdat issues, since in those cases the assembler
-// can at least know that all symbols in the section will move together.
-static bool isWeak(const MCSymbolELF &Sym) {
- if (Sym.getType() == ELF::STT_GNU_IFUNC)
- return true;
-
- switch (Sym.getBinding()) {
- default:
- llvm_unreachable("Unknown binding");
- case ELF::STB_LOCAL:
- return false;
- case ELF::STB_GLOBAL:
- return false;
- case ELF::STB_WEAK:
- case ELF::STB_GNU_UNIQUE:
- return true;
- }
-}
-
bool ELFWriter::isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol,
bool Used, bool Renamed) {
if (Symbol.isVariable()) {
@@ -615,9 +595,6 @@ bool ELFWriter::isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol,
return false;
}
- if (Symbol.isUndefined() && !Symbol.isBindingSet())
- return false;
-
if (Symbol.isTemporary())
return false;
@@ -1537,7 +1514,8 @@ bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
const auto &SymA = cast<MCSymbolELF>(SA);
if (IsPCRel) {
assert(!InSet);
- if (isWeak(SymA))
+ if (SymA.getBinding() != ELF::STB_LOCAL ||
+ SymA.getType() == ELF::STT_GNU_IFUNC)
return false;
}
return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
diff --git a/llvm/lib/MC/MCAsmBackend.cpp b/llvm/lib/MC/MCAsmBackend.cpp
index b800e9caee22a..cf110345df3de 100644
--- a/llvm/lib/MC/MCAsmBackend.cpp
+++ b/llvm/lib/MC/MCAsmBackend.cpp
@@ -9,7 +9,6 @@
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/MC/MCCodePadder.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCMachObjectWriter.h"
@@ -23,8 +22,7 @@
using namespace llvm;
-MCAsmBackend::MCAsmBackend(support::endianness Endian)
- : CodePadder(new MCCodePadder()), Endian(Endian) {}
+MCAsmBackend::MCAsmBackend(support::endianness Endian) : Endian(Endian) {}
MCAsmBackend::~MCAsmBackend() = default;
@@ -113,25 +111,3 @@ bool MCAsmBackend::fixupNeedsRelaxationAdvanced(
return true;
return fixupNeedsRelaxation(Fixup, Value, DF, Layout);
}
-
-void MCAsmBackend::handleCodePaddingBasicBlockStart(
- MCObjectStreamer *OS, const MCCodePaddingContext &Context) {
- CodePadder->handleBasicBlockStart(OS, Context);
-}
-
-void MCAsmBackend::handleCodePaddingBasicBlockEnd(
- const MCCodePaddingContext &Context) {
- CodePadder->handleBasicBlockEnd(Context);
-}
-
-void MCAsmBackend::handleCodePaddingInstructionBegin(const MCInst &Inst) {
- CodePadder->handleInstructionBegin(Inst);
-}
-
-void MCAsmBackend::handleCodePaddingInstructionEnd(const MCInst &Inst) {
- CodePadder->handleInstructionEnd(Inst);
-}
-
-bool MCAsmBackend::relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout) {
- return CodePadder->relaxFragment(PF, Layout);
-}
diff --git a/llvm/lib/MC/MCAsmInfo.cpp b/llvm/lib/MC/MCAsmInfo.cpp
index 71e51e320f8bd..420dbaa80ae90 100644
--- a/llvm/lib/MC/MCAsmInfo.cpp
+++ b/llvm/lib/MC/MCAsmInfo.cpp
@@ -100,7 +100,7 @@ MCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym,
return MCBinaryExpr::createSub(Res, PC, Context);
}
-static bool isAcceptableChar(char C) {
+bool MCAsmInfo::isAcceptableChar(char C) const {
return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') ||
(C >= '0' && C <= '9') || C == '_' || C == '$' || C == '.' || C == '@';
}
diff --git a/llvm/lib/MC/MCAsmInfoELF.cpp b/llvm/lib/MC/MCAsmInfoELF.cpp
index a5e8aff7f129d..9b8b8db794f0d 100644
--- a/llvm/lib/MC/MCAsmInfoELF.cpp
+++ b/llvm/lib/MC/MCAsmInfoELF.cpp
@@ -21,8 +21,6 @@ using namespace llvm;
void MCAsmInfoELF::anchor() {}
MCSection *MCAsmInfoELF::getNonexecutableStackSection(MCContext &Ctx) const {
- if (!UsesNonexecutableStackSection)
- return nullptr;
return Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0);
}
diff --git a/llvm/lib/MC/MCAsmInfoXCOFF.cpp b/llvm/lib/MC/MCAsmInfoXCOFF.cpp
index 65fe8848e20fb..c51cdff59fa0a 100644
--- a/llvm/lib/MC/MCAsmInfoXCOFF.cpp
+++ b/llvm/lib/MC/MCAsmInfoXCOFF.cpp
@@ -26,10 +26,11 @@ MCAsmInfoXCOFF::MCAsmInfoXCOFF() {
SupportsQuotedNames = false;
}
-bool MCAsmInfoXCOFF::isValidUnquotedName(StringRef Name) const {
- // FIXME: Remove this function when we stop using "TOC[TC0]" as a symbol name.
- if (Name.equals("TOC[TC0]"))
+bool MCAsmInfoXCOFF::isAcceptableChar(char C) const {
+ // QualName is allowed for a MCSymbolXCOFF, and
+ // QualName contains '[' and ']'.
+ if (C == '[' || C == ']')
return true;
- return MCAsmInfo::isValidUnquotedName(Name);
+ return MCAsmInfo::isAcceptableChar(C);
}
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 2d9c2cb21255b..5d369503995b3 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -77,6 +77,8 @@ public:
assert(InstPrinter);
if (IsVerboseAsm)
InstPrinter->setCommentStream(CommentStream);
+ if (Assembler->getBackendPtr())
+ setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
}
MCAssembler &getAssembler() { return *Assembler; }
@@ -164,7 +166,8 @@ public:
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
- void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ void EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
+ MCSymbol *CsectSym,
unsigned ByteAlign) override;
void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
@@ -765,16 +768,18 @@ void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
// We need an XCOFF-specific version of this directive as the AIX syntax
// requires a QualName argument identifying the csect name and storage mapping
// class to appear before the alignment if we are specifying it.
-void MCAsmStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+void MCAsmStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
+ uint64_t Size,
+ MCSymbol *CsectSym,
unsigned ByteAlignment) {
assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment &&
"We only support writing log base-2 alignment format with XCOFF.");
assert(isPowerOf2_32(ByteAlignment) && "Alignment must be a power of 2.");
OS << "\t.lcomm\t";
- Symbol->print(OS, MAI);
- OS << ',' << Size;
- OS << ',' << Symbol->getName();
+ LabelSym->print(OS, MAI);
+ OS << ',' << Size << ',';
+ CsectSym->print(OS, MAI);
OS << ',' << Log2_32(ByteAlignment);
EmitEOL();
@@ -1941,9 +1946,9 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst,
}
if(getTargetStreamer())
- getTargetStreamer()->prettyPrintAsm(*InstPrinter, OS, Inst, STI);
+ getTargetStreamer()->prettyPrintAsm(*InstPrinter, 0, Inst, STI, OS);
else
- InstPrinter->printInst(&Inst, OS, "", STI);
+ InstPrinter->printInst(&Inst, 0, "", STI, OS);
StringRef Comments = CommentToEmit;
if (Comments.size() && Comments.back() != '\n')
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index cf42fe85b8e5d..b30137aafb8d1 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -68,10 +68,6 @@ STATISTIC(FragmentLayouts, "Number of fragment layouts");
STATISTIC(ObjectBytes, "Number of emitted object file bytes");
STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps");
STATISTIC(RelaxedInstructions, "Number of relaxed instructions");
-STATISTIC(PaddingFragmentsRelaxations,
- "Number of Padding Fragments relaxations");
-STATISTIC(PaddingFragmentsBytes,
- "Total size of all padding from adding Fragments");
} // end namespace stats
} // end anonymous namespace
@@ -167,10 +163,6 @@ bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const {
if (!Symbol.isTemporary())
return true;
- // Absolute temporary labels are never visible.
- if (!Symbol.isInSection())
- return false;
-
if (Symbol.isUsedInReloc())
return true;
@@ -313,8 +305,8 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
case MCFragment::FT_LEB:
return cast<MCLEBFragment>(F).getContents().size();
- case MCFragment::FT_Padding:
- return cast<MCPaddingFragment>(F).getSize();
+ case MCFragment::FT_BoundaryAlign:
+ return cast<MCBoundaryAlignFragment>(F).getSize();
case MCFragment::FT_SymbolId:
return 4;
@@ -580,6 +572,7 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
unsigned VSize = FF.getValueSize();
const unsigned MaxChunkSize = 16;
char Data[MaxChunkSize];
+ assert(0 < VSize && VSize <= MaxChunkSize && "Illegal fragment fill size");
// Duplicate V into Data as byte vector to reduce number of
// writes done. As such, do endian conversion here.
for (unsigned I = 0; I != VSize; ++I) {
@@ -612,7 +605,7 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
break;
}
- case MCFragment::FT_Padding: {
+ case MCFragment::FT_BoundaryAlign: {
if (!Asm.getBackend().writeNopData(OS, FragmentSize))
report_fatal_error("unable to write nop sequence of " +
Twine(FragmentSize) + " bytes");
@@ -935,20 +928,6 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
return true;
}
-bool MCAssembler::relaxPaddingFragment(MCAsmLayout &Layout,
- MCPaddingFragment &PF) {
- assert(getBackendPtr() && "Expected assembler backend");
- uint64_t OldSize = PF.getSize();
- if (!getBackend().relaxFragment(&PF, Layout))
- return false;
- uint64_t NewSize = PF.getSize();
-
- ++stats::PaddingFragmentsRelaxations;
- stats::PaddingFragmentsBytes += NewSize;
- stats::PaddingFragmentsBytes -= OldSize;
- return true;
-}
-
bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) {
uint64_t OldSize = LF.getContents().size();
int64_t Value;
@@ -969,6 +948,72 @@ bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) {
return OldSize != LF.getContents().size();
}
+/// Check if the branch crosses the boundary.
+///
+/// \param StartAddr start address of the fused/unfused branch.
+/// \param Size size of the fused/unfused branch.
+/// \param BoundaryAlignment alignment requirement of the branch.
+/// \returns true if the branch cross the boundary.
+static bool mayCrossBoundary(uint64_t StartAddr, uint64_t Size,
+ Align BoundaryAlignment) {
+ uint64_t EndAddr = StartAddr + Size;
+ return (StartAddr >> Log2(BoundaryAlignment)) !=
+ ((EndAddr - 1) >> Log2(BoundaryAlignment));
+}
+
+/// Check if the branch is against the boundary.
+///
+/// \param StartAddr start address of the fused/unfused branch.
+/// \param Size size of the fused/unfused branch.
+/// \param BoundaryAlignment alignment requirement of the branch.
+/// \returns true if the branch is against the boundary.
+static bool isAgainstBoundary(uint64_t StartAddr, uint64_t Size,
+ Align BoundaryAlignment) {
+ uint64_t EndAddr = StartAddr + Size;
+ return (EndAddr & (BoundaryAlignment.value() - 1)) == 0;
+}
+
+/// Check if the branch needs padding.
+///
+/// \param StartAddr start address of the fused/unfused branch.
+/// \param Size size of the fused/unfused branch.
+/// \param BoundaryAlignment alignment requirement of the branch.
+/// \returns true if the branch needs padding.
+static bool needPadding(uint64_t StartAddr, uint64_t Size,
+ Align BoundaryAlignment) {
+ return mayCrossBoundary(StartAddr, Size, BoundaryAlignment) ||
+ isAgainstBoundary(StartAddr, Size, BoundaryAlignment);
+}
+
+bool MCAssembler::relaxBoundaryAlign(MCAsmLayout &Layout,
+ MCBoundaryAlignFragment &BF) {
+ // The MCBoundaryAlignFragment that doesn't emit NOP should not be relaxed.
+ if (!BF.canEmitNops())
+ return false;
+
+ uint64_t AlignedOffset = Layout.getFragmentOffset(BF.getNextNode());
+ uint64_t AlignedSize = 0;
+ const MCFragment *F = BF.getNextNode();
+ // If the branch is unfused, it is emitted into one fragment, otherwise it is
+ // emitted into two fragments at most, the next MCBoundaryAlignFragment(if
+ // exists) also marks the end of the branch.
+ for (auto i = 0, N = BF.isFused() ? 2 : 1;
+ i != N && !isa<MCBoundaryAlignFragment>(F); ++i, F = F->getNextNode()) {
+ AlignedSize += computeFragmentSize(Layout, *F);
+ }
+ uint64_t OldSize = BF.getSize();
+ AlignedOffset -= OldSize;
+ Align BoundaryAlignment = BF.getAlignment();
+ uint64_t NewSize = needPadding(AlignedOffset, AlignedSize, BoundaryAlignment)
+ ? offsetToAlignment(AlignedOffset, BoundaryAlignment)
+ : 0U;
+ if (NewSize == OldSize)
+ return false;
+ BF.setSize(NewSize);
+ Layout.invalidateFragmentsFrom(&BF);
+ return true;
+}
+
bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout,
MCDwarfLineAddrFragment &DF) {
MCContext &Context = Layout.getAssembler().getContext();
@@ -1085,8 +1130,9 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) {
case MCFragment::FT_LEB:
RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(I));
break;
- case MCFragment::FT_Padding:
- RelaxedFrag = relaxPaddingFragment(Layout, *cast<MCPaddingFragment>(I));
+ case MCFragment::FT_BoundaryAlign:
+ RelaxedFrag =
+ relaxBoundaryAlign(Layout, *cast<MCBoundaryAlignFragment>(I));
break;
case MCFragment::FT_CVInlineLines:
RelaxedFrag =
@@ -1124,8 +1170,8 @@ void MCAssembler::finishLayout(MCAsmLayout &Layout) {
// The layout is done. Mark every fragment as valid.
for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) {
MCSection &Section = *Layout.getSectionOrder()[i];
- Layout.getFragmentOffset(&*Section.rbegin());
- computeFragmentSize(Layout, *Section.rbegin());
+ Layout.getFragmentOffset(&*Section.getFragmentList().rbegin());
+ computeFragmentSize(Layout, *Section.getFragmentList().rbegin());
}
getBackend().finishLayout(*this, Layout);
}
diff --git a/llvm/lib/MC/MCCodePadder.cpp b/llvm/lib/MC/MCCodePadder.cpp
deleted file mode 100644
index 27a62f95a5294..0000000000000
--- a/llvm/lib/MC/MCCodePadder.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-//===- MCCodePadder.cpp - Target MC Code Padder ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCCodePadder.h"
-#include "llvm/MC/MCObjectStreamer.h"
-#include <algorithm>
-#include <limits>
-#include <numeric>
-
-using namespace llvm;
-
-//---------------------------------------------------------------------------
-// MCCodePadder
-//
-
-MCCodePadder::~MCCodePadder() {
- for (auto *Policy : CodePaddingPolicies)
- delete Policy;
-}
-
-bool MCCodePadder::addPolicy(MCCodePaddingPolicy *Policy) {
- assert(Policy && "Policy must be valid");
- return CodePaddingPolicies.insert(Policy).second;
-}
-
-void MCCodePadder::handleBasicBlockStart(MCObjectStreamer *OS,
- const MCCodePaddingContext &Context) {
- assert(OS != nullptr && "OS must be valid");
- assert(this->OS == nullptr && "Still handling another basic block");
- this->OS = OS;
-
- ArePoliciesActive = usePoliciesForBasicBlock(Context);
-
- bool InsertionPoint = basicBlockRequiresInsertionPoint(Context);
- assert((!InsertionPoint ||
- OS->getCurrentFragment()->getKind() != MCFragment::FT_Align) &&
- "Cannot insert padding nops right after an alignment fragment as it "
- "will ruin the alignment");
-
- uint64_t PoliciesMask = MCPaddingFragment::PFK_None;
- if (ArePoliciesActive) {
- PoliciesMask = std::accumulate(
- CodePaddingPolicies.begin(), CodePaddingPolicies.end(),
- MCPaddingFragment::PFK_None,
- [&Context](uint64_t Mask,
- const MCCodePaddingPolicy *Policy) -> uint64_t {
- return Policy->basicBlockRequiresPaddingFragment(Context)
- ? (Mask | Policy->getKindMask())
- : Mask;
- });
- }
-
- if (InsertionPoint || PoliciesMask != MCPaddingFragment::PFK_None) {
- MCPaddingFragment *PaddingFragment = OS->getOrCreatePaddingFragment();
- if (InsertionPoint)
- PaddingFragment->setAsInsertionPoint();
- PaddingFragment->setPaddingPoliciesMask(
- PaddingFragment->getPaddingPoliciesMask() | PoliciesMask);
- }
-}
-
-void MCCodePadder::handleBasicBlockEnd(const MCCodePaddingContext &Context) {
- assert(this->OS != nullptr && "Not handling a basic block");
- OS = nullptr;
-}
-
-void MCCodePadder::handleInstructionBegin(const MCInst &Inst) {
- if (!OS)
- return; // instruction was emitted outside a function
-
- assert(CurrHandledInstFragment == nullptr && "Can't start handling an "
- "instruction while still "
- "handling another instruction");
-
- bool InsertionPoint = instructionRequiresInsertionPoint(Inst);
- assert((!InsertionPoint ||
- OS->getCurrentFragment()->getKind() != MCFragment::FT_Align) &&
- "Cannot insert padding nops right after an alignment fragment as it "
- "will ruin the alignment");
-
- uint64_t PoliciesMask = MCPaddingFragment::PFK_None;
- if (ArePoliciesActive) {
- PoliciesMask = std::accumulate(
- CodePaddingPolicies.begin(), CodePaddingPolicies.end(),
- MCPaddingFragment::PFK_None,
- [&Inst](uint64_t Mask, const MCCodePaddingPolicy *Policy) -> uint64_t {
- return Policy->instructionRequiresPaddingFragment(Inst)
- ? (Mask | Policy->getKindMask())
- : Mask;
- });
- }
- MCFragment *CurrFragment = OS->getCurrentFragment();
- // CurrFragment can be a previously created MCPaddingFragment. If so, let's
- // update it with the information we have, such as the instruction that it
- // should point to.
- bool needToUpdateCurrFragment =
- CurrFragment != nullptr &&
- CurrFragment->getKind() == MCFragment::FT_Padding;
- if (InsertionPoint || PoliciesMask != MCPaddingFragment::PFK_None ||
- needToUpdateCurrFragment) {
- // temporarily holding the fragment as CurrHandledInstFragment, to be
- // updated after the instruction will be written
- CurrHandledInstFragment = OS->getOrCreatePaddingFragment();
- if (InsertionPoint)
- CurrHandledInstFragment->setAsInsertionPoint();
- CurrHandledInstFragment->setPaddingPoliciesMask(
- CurrHandledInstFragment->getPaddingPoliciesMask() | PoliciesMask);
- }
-}
-
-void MCCodePadder::handleInstructionEnd(const MCInst &Inst) {
- if (!OS)
- return; // instruction was emitted outside a function
- if (CurrHandledInstFragment == nullptr)
- return;
-
- MCFragment *InstFragment = OS->getCurrentFragment();
- if (MCDataFragment *InstDataFragment =
- dyn_cast_or_null<MCDataFragment>(InstFragment))
- // Inst is a fixed size instruction and was encoded into a MCDataFragment.
- // Let the fragment hold it and its size. Its size is the current size of
- // the data fragment, as the padding fragment was inserted right before it
- // and nothing was written yet except Inst
- CurrHandledInstFragment->setInstAndInstSize(
- Inst, InstDataFragment->getContents().size());
- else if (MCRelaxableFragment *InstRelaxableFragment =
- dyn_cast_or_null<MCRelaxableFragment>(InstFragment))
- // Inst may be relaxed and its size may vary.
- // Let the fragment hold the instruction and the MCRelaxableFragment
- // that's holding it.
- CurrHandledInstFragment->setInstAndInstFragment(Inst,
- InstRelaxableFragment);
- else
- llvm_unreachable("After encoding an instruction current fragment must be "
- "either a MCDataFragment or a MCRelaxableFragment");
-
- CurrHandledInstFragment = nullptr;
-}
-
-MCPFRange &MCCodePadder::getJurisdiction(MCPaddingFragment *Fragment,
- MCAsmLayout &Layout) {
- auto JurisdictionLocation = FragmentToJurisdiction.find(Fragment);
- if (JurisdictionLocation != FragmentToJurisdiction.end())
- return JurisdictionLocation->second;
-
- MCPFRange Jurisdiction;
-
- // Forward scanning the fragments in this section, starting from the given
- // fragments, and adding relevant MCPaddingFragments to the Jurisdiction
- for (MCFragment *CurrFragment = Fragment; CurrFragment != nullptr;
- CurrFragment = CurrFragment->getNextNode()) {
-
- MCPaddingFragment *CurrPaddingFragment =
- dyn_cast<MCPaddingFragment>(CurrFragment);
- if (CurrPaddingFragment == nullptr)
- continue;
-
- if (CurrPaddingFragment != Fragment &&
- CurrPaddingFragment->isInsertionPoint())
- // Found next insertion point Fragment. From now on it's its jurisdiction.
- break;
- for (const auto *Policy : CodePaddingPolicies) {
- if (CurrPaddingFragment->hasPaddingPolicy(Policy->getKindMask())) {
- Jurisdiction.push_back(CurrPaddingFragment);
- break;
- }
- }
- }
-
- auto InsertionResult =
- FragmentToJurisdiction.insert(std::make_pair(Fragment, Jurisdiction));
- assert(InsertionResult.second &&
- "Insertion to FragmentToJurisdiction failed");
- return InsertionResult.first->second;
-}
-
-uint64_t MCCodePadder::getMaxWindowSize(MCPaddingFragment *Fragment,
- MCAsmLayout &Layout) {
- auto MaxFragmentSizeLocation = FragmentToMaxWindowSize.find(Fragment);
- if (MaxFragmentSizeLocation != FragmentToMaxWindowSize.end())
- return MaxFragmentSizeLocation->second;
-
- MCPFRange &Jurisdiction = getJurisdiction(Fragment, Layout);
- uint64_t JurisdictionMask = MCPaddingFragment::PFK_None;
- for (const auto *Protege : Jurisdiction)
- JurisdictionMask |= Protege->getPaddingPoliciesMask();
-
- uint64_t MaxFragmentSize = UINT64_C(0);
- for (const auto *Policy : CodePaddingPolicies)
- if ((JurisdictionMask & Policy->getKindMask()) !=
- MCPaddingFragment::PFK_None)
- MaxFragmentSize = std::max(MaxFragmentSize, Policy->getWindowSize());
-
- auto InsertionResult =
- FragmentToMaxWindowSize.insert(std::make_pair(Fragment, MaxFragmentSize));
- assert(InsertionResult.second &&
- "Insertion to FragmentToMaxWindowSize failed");
- return InsertionResult.first->second;
-}
-
-bool MCCodePadder::relaxFragment(MCPaddingFragment *Fragment,
- MCAsmLayout &Layout) {
- if (!Fragment->isInsertionPoint())
- return false;
- uint64_t OldSize = Fragment->getSize();
-
- uint64_t MaxWindowSize = getMaxWindowSize(Fragment, Layout);
- if (MaxWindowSize == UINT64_C(0))
- return false;
- assert(isPowerOf2_64(MaxWindowSize) &&
- "MaxWindowSize must be an integer power of 2");
- uint64_t SectionAlignment = Fragment->getParent()->getAlignment();
- assert(isPowerOf2_64(SectionAlignment) &&
- "SectionAlignment must be an integer power of 2");
-
- MCPFRange &Jurisdiction = getJurisdiction(Fragment, Layout);
- uint64_t OptimalSize = UINT64_C(0);
- double OptimalWeight = std::numeric_limits<double>::max();
- uint64_t MaxFragmentSize = MaxWindowSize - UINT16_C(1);
- for (uint64_t Size = UINT64_C(0); Size <= MaxFragmentSize; ++Size) {
- Fragment->setSize(Size);
- Layout.invalidateFragmentsFrom(Fragment);
- double SizeWeight = 0.0;
- // The section is guaranteed to be aligned to SectionAlignment, but that
- // doesn't guarantee the exact section offset w.r.t. the policies window
- // size.
- // As a concrete example, the section could be aligned to 16B, but a
- // policy's window size can be 32B. That means that the section actual start
- // address can either be 0mod32 or 16mod32. The said policy will act
- // differently for each case, so we need to take both into consideration.
- for (uint64_t Offset = UINT64_C(0); Offset < MaxWindowSize;
- Offset += SectionAlignment) {
- double OffsetWeight = std::accumulate(
- CodePaddingPolicies.begin(), CodePaddingPolicies.end(), 0.0,
- [&Jurisdiction, &Offset, &Layout](
- double Weight, const MCCodePaddingPolicy *Policy) -> double {
- double PolicyWeight =
- Policy->computeRangePenaltyWeight(Jurisdiction, Offset, Layout);
- assert(PolicyWeight >= 0.0 && "A penalty weight must be positive");
- return Weight + PolicyWeight;
- });
- SizeWeight = std::max(SizeWeight, OffsetWeight);
- }
- if (SizeWeight < OptimalWeight) {
- OptimalWeight = SizeWeight;
- OptimalSize = Size;
- }
- if (OptimalWeight == 0.0)
- break;
- }
-
- Fragment->setSize(OptimalSize);
- Layout.invalidateFragmentsFrom(Fragment);
- return OldSize != OptimalSize;
-}
-
-//---------------------------------------------------------------------------
-// MCCodePaddingPolicy
-//
-
-uint64_t MCCodePaddingPolicy::getNextFragmentOffset(const MCFragment *Fragment,
- const MCAsmLayout &Layout) {
- assert(Fragment != nullptr && "Fragment cannot be null");
- MCFragment const *NextFragment = Fragment->getNextNode();
- return NextFragment == nullptr
- ? Layout.getSectionAddressSize(Fragment->getParent())
- : Layout.getFragmentOffset(NextFragment);
-}
-
-uint64_t
-MCCodePaddingPolicy::getFragmentInstByte(const MCPaddingFragment *Fragment,
- MCAsmLayout &Layout) const {
- uint64_t InstByte = getNextFragmentOffset(Fragment, Layout);
- if (InstByteIsLastByte)
- InstByte += Fragment->getInstSize() - UINT64_C(1);
- return InstByte;
-}
-
-uint64_t
-MCCodePaddingPolicy::computeWindowEndAddress(const MCPaddingFragment *Fragment,
- uint64_t Offset,
- MCAsmLayout &Layout) const {
- uint64_t InstByte = getFragmentInstByte(Fragment, Layout);
- return alignTo(InstByte + UINT64_C(1) + Offset, WindowSize) - Offset;
-}
-
-double MCCodePaddingPolicy::computeRangePenaltyWeight(
- const MCPFRange &Range, uint64_t Offset, MCAsmLayout &Layout) const {
-
- SmallVector<MCPFRange, 8> Windows;
- SmallVector<MCPFRange, 8>::iterator CurrWindowLocation = Windows.end();
- for (const MCPaddingFragment *Fragment : Range) {
- if (!Fragment->hasPaddingPolicy(getKindMask()))
- continue;
- uint64_t FragmentWindowEndAddress =
- computeWindowEndAddress(Fragment, Offset, Layout);
- if (CurrWindowLocation == Windows.end() ||
- FragmentWindowEndAddress !=
- computeWindowEndAddress(*CurrWindowLocation->begin(), Offset,
- Layout)) {
- // next window is starting
- Windows.push_back(MCPFRange());
- CurrWindowLocation = Windows.end() - 1;
- }
- CurrWindowLocation->push_back(Fragment);
- }
-
- if (Windows.empty())
- return 0.0;
-
- double RangeWeight = 0.0;
- SmallVector<MCPFRange, 8>::iterator I = Windows.begin();
- RangeWeight += computeFirstWindowPenaltyWeight(*I, Offset, Layout);
- ++I;
- RangeWeight += std::accumulate(
- I, Windows.end(), 0.0,
- [this, &Layout, &Offset](double Weight, MCPFRange &Window) -> double {
- return Weight += computeWindowPenaltyWeight(Window, Offset, Layout);
- });
- return RangeWeight;
-}
-
-double MCCodePaddingPolicy::computeFirstWindowPenaltyWeight(
- const MCPFRange &Window, uint64_t Offset, MCAsmLayout &Layout) const {
- if (Window.empty())
- return 0.0;
- uint64_t WindowEndAddress =
- computeWindowEndAddress(*Window.begin(), Offset, Layout);
-
- MCPFRange FullWindowFirstPart; // will hold all the fragments that are in the
- // same window as the fragments in the given
- // window but their penalty weight should not
- // be added
- for (const MCFragment *Fragment = (*Window.begin())->getPrevNode();
- Fragment != nullptr; Fragment = Fragment->getPrevNode()) {
- const MCPaddingFragment *PaddingNopFragment =
- dyn_cast<MCPaddingFragment>(Fragment);
- if (PaddingNopFragment == nullptr ||
- !PaddingNopFragment->hasPaddingPolicy(getKindMask()))
- continue;
- if (WindowEndAddress !=
- computeWindowEndAddress(PaddingNopFragment, Offset, Layout))
- break;
-
- FullWindowFirstPart.push_back(PaddingNopFragment);
- }
-
- std::reverse(FullWindowFirstPart.begin(), FullWindowFirstPart.end());
- double FullWindowFirstPartWeight =
- computeWindowPenaltyWeight(FullWindowFirstPart, Offset, Layout);
-
- MCPFRange FullWindow(
- FullWindowFirstPart); // will hold all the fragments that are in the
- // same window as the fragments in the given
- // window, whether their weight should be added
- // or not
- FullWindow.append(Window.begin(), Window.end());
- double FullWindowWeight =
- computeWindowPenaltyWeight(FullWindow, Offset, Layout);
-
- assert(FullWindowWeight >= FullWindowFirstPartWeight &&
- "More fragments necessarily means bigger weight");
- return FullWindowWeight - FullWindowFirstPartWeight;
-}
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index a69ee19e1a1ae..a6417113fd384 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeView.h"
#include "llvm/MC/MCDwarf.h"
@@ -550,13 +551,15 @@ MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section,
// Otherwise, return a new section.
StringRef CachedName = Entry.first.SectionName;
+ MCSymbol *QualName = getOrCreateSymbol(
+ CachedName + "[" + XCOFF::getMappingClassString(SMC) + "]");
MCSymbol *Begin = nullptr;
if (BeginSymName)
Begin = createTempSymbol(BeginSymName, false);
- MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate())
- MCSectionXCOFF(CachedName, SMC, Type, SC, Kind, Begin);
+ MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate()) MCSectionXCOFF(
+ CachedName, SMC, Type, SC, Kind, cast<MCSymbolXCOFF>(QualName), Begin);
Entry.second = Result;
auto *F = new MCDataFragment();
diff --git a/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/llvm/lib/MC/MCDisassembler/Disassembler.cpp
index 21bdc2eaea3e4..ff56695e8cc46 100644
--- a/llvm/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/llvm/lib/MC/MCDisassembler/Disassembler.cpp
@@ -24,6 +24,7 @@
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSchedule.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
@@ -56,8 +57,10 @@ LLVMCreateDisasmCPUFeatures(const char *TT, const char *CPU,
if (!MRI)
return nullptr;
+ MCTargetOptions MCOptions;
// Get the assembler info needed to setup the MCContext.
- std::unique_ptr<const MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT));
+ std::unique_ptr<const MCAsmInfo> MAI(
+ TheTarget->createMCAsmInfo(*MRI, TT, MCOptions));
if (!MAI)
return nullptr;
@@ -260,8 +263,7 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
MCDisassembler::DecodeStatus S;
SmallVector<char, 64> InsnStr;
raw_svector_ostream Annotations(InsnStr);
- S = DisAsm->getInstruction(Inst, Size, Data, PC,
- /*REMOVE*/ nulls(), Annotations);
+ S = DisAsm->getInstruction(Inst, Size, Data, PC, Annotations);
switch (S) {
case MCDisassembler::Fail:
case MCDisassembler::SoftFail:
@@ -274,7 +276,8 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
SmallVector<char, 64> InsnStr;
raw_svector_ostream OS(InsnStr);
formatted_raw_ostream FormattedOS(OS);
- IP->printInst(&Inst, FormattedOS, AnnotationsStr, *DC->getSubtargetInfo());
+ IP->printInst(&Inst, PC, AnnotationsStr, *DC->getSubtargetInfo(),
+ FormattedOS);
if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency)
emitLatency(DC, Inst);
diff --git a/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp b/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp
index 063f7e706024b..373916fbed785 100644
--- a/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp
+++ b/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp
@@ -16,9 +16,10 @@ using namespace llvm;
MCDisassembler::~MCDisassembler() = default;
-MCDisassembler::DecodeStatus MCDisassembler::onSymbolStart(
- StringRef Name, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address,
- raw_ostream &VStream, raw_ostream &CStream) const {
+MCDisassembler::DecodeStatus
+MCDisassembler::onSymbolStart(StringRef Name, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &CStream) const {
Size = 0;
return MCDisassembler::Success;
}
@@ -27,18 +28,16 @@ bool MCDisassembler::tryAddingSymbolicOperand(MCInst &Inst, int64_t Value,
uint64_t Address, bool IsBranch,
uint64_t Offset,
uint64_t InstSize) const {
- raw_ostream &cStream = CommentStream ? *CommentStream : nulls();
if (Symbolizer)
- return Symbolizer->tryAddingSymbolicOperand(Inst, cStream, Value, Address,
- IsBranch, Offset, InstSize);
+ return Symbolizer->tryAddingSymbolicOperand(
+ Inst, *CommentStream, Value, Address, IsBranch, Offset, InstSize);
return false;
}
void MCDisassembler::tryAddingPcLoadReferenceComment(int64_t Value,
uint64_t Address) const {
- raw_ostream &cStream = CommentStream ? *CommentStream : nulls();
if (Symbolizer)
- Symbolizer->tryAddingPcLoadReferenceComment(cStream, Value, Address);
+ Symbolizer->tryAddingPcLoadReferenceComment(*CommentStream, Value, Address);
}
void MCDisassembler::setSymbolizer(std::unique_ptr<MCSymbolizer> Symzer) {
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp
index bcc7c45afc01b..b4b3c9956cc2d 100644
--- a/llvm/lib/MC/MCDwarf.cpp
+++ b/llvm/lib/MC/MCDwarf.cpp
@@ -1701,7 +1701,8 @@ void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart,
MakeStartMinusEndExpr(Streamer, SectionStart, cieStart, 0);
emitAbsValue(Streamer, offset, 4);
} else {
- Streamer.EmitSymbolValue(&cieStart, 4);
+ Streamer.EmitSymbolValue(&cieStart, 4,
+ asmInfo->needsDwarfSectionOffsetDirective());
}
// PC Begin
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index fa2133078bfea..0a0c30df9c07f 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -106,9 +106,10 @@ void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) {
Symbol->setType(ELF::STT_TLS);
}
-void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc, MCFragment *F) {
+void MCELFStreamer::EmitLabelAtPos(MCSymbol *S, SMLoc Loc, MCFragment *F,
+ uint64_t Offset) {
auto *Symbol = cast<MCSymbolELF>(S);
- MCObjectStreamer::EmitLabel(Symbol, Loc, F);
+ MCObjectStreamer::EmitLabelAtPos(Symbol, Loc, F, Offset);
const MCSectionELF &Section =
static_cast<const MCSectionELF &>(*getCurrentSectionOnly());
@@ -307,10 +308,6 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
EmitLabel(Symbol);
EmitZeros(Size);
- // Update the maximum alignment of the section if necessary.
- if (ByteAlignment > Section.getAlignment())
- Section.setAlignment(Align(ByteAlignment));
-
SwitchSection(P.first, P.second);
} else {
if(Symbol->declareCommon(Size, ByteAlignment))
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 813c00f6f3bb3..7f25fd4e90a78 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -601,7 +601,7 @@ static bool canFold(const MCAssembler *Asm, const MCSymbolRefExpr *A,
/// and
/// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
///
-/// This routine attempts to aggresively fold the operands such that the result
+/// This routine attempts to aggressively fold the operands such that the result
/// is representable in an MCValue, but may not always succeed.
///
/// \returns True on success, false if the result is not representable in an
diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp
index ae5bd65507bc9..a96b8e86aed3c 100644
--- a/llvm/lib/MC/MCFragment.cpp
+++ b/llvm/lib/MC/MCFragment.cpp
@@ -232,13 +232,11 @@ uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler,
void ilist_alloc_traits<MCFragment>::deleteNode(MCFragment *V) { V->destroy(); }
-MCFragment::~MCFragment() = default;
-
MCFragment::MCFragment(FragmentType Kind, bool HasInstructions,
MCSection *Parent)
- : Kind(Kind), HasInstructions(HasInstructions), LayoutOrder(0),
- Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)) {
- if (Parent && !isDummy())
+ : Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)), LayoutOrder(0),
+ Kind(Kind), HasInstructions(HasInstructions) {
+ if (Parent && !isa<MCDummyFragment>(*this))
Parent->getFragmentList().push_back(this);
}
@@ -277,8 +275,8 @@ void MCFragment::destroy() {
case FT_LEB:
delete cast<MCLEBFragment>(this);
return;
- case FT_Padding:
- delete cast<MCPaddingFragment>(this);
+ case FT_BoundaryAlign:
+ delete cast<MCBoundaryAlignFragment>(this);
return;
case FT_SymbolId:
delete cast<MCSymbolIdFragment>(this);
@@ -324,7 +322,7 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
case MCFragment::FT_LEB: OS << "MCLEBFragment"; break;
- case MCFragment::FT_Padding: OS << "MCPaddingFragment"; break;
+ case MCFragment::FT_BoundaryAlign: OS<<"MCBoundaryAlignFragment"; break;
case MCFragment::FT_SymbolId: OS << "MCSymbolIdFragment"; break;
case MCFragment::FT_CVInlineLines: OS << "MCCVInlineLineTableFragment"; break;
case MCFragment::FT_CVDefRange: OS << "MCCVDefRangeTableFragment"; break;
@@ -333,13 +331,13 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
OS << "<MCFragment " << (const void *)this << " LayoutOrder:" << LayoutOrder
<< " Offset:" << Offset << " HasInstructions:" << hasInstructions();
- if (const MCEncodedFragment *EF = dyn_cast<MCEncodedFragment>(this))
+ if (const auto *EF = dyn_cast<MCEncodedFragment>(this))
OS << " BundlePadding:" << static_cast<unsigned>(EF->getBundlePadding());
OS << ">";
switch (getKind()) {
case MCFragment::FT_Align: {
- const MCAlignFragment *AF = cast<MCAlignFragment>(this);
+ const auto *AF = cast<MCAlignFragment>(this);
if (AF->hasEmitNops())
OS << " (emit nops)";
OS << "\n ";
@@ -349,7 +347,7 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
break;
}
case MCFragment::FT_Data: {
- const MCDataFragment *DF = cast<MCDataFragment>(this);
+ const auto *DF = cast<MCDataFragment>(this);
OS << "\n ";
OS << " Contents:[";
const SmallVectorImpl<char> &Contents = DF->getContents();
@@ -372,7 +370,7 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
break;
}
case MCFragment::FT_CompactEncodedInst: {
- const MCCompactEncodedInstFragment *CEIF =
+ const auto *CEIF =
cast<MCCompactEncodedInstFragment>(this);
OS << "\n ";
OS << " Contents:[";
@@ -385,60 +383,60 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
break;
}
case MCFragment::FT_Fill: {
- const MCFillFragment *FF = cast<MCFillFragment>(this);
+ const auto *FF = cast<MCFillFragment>(this);
OS << " Value:" << static_cast<unsigned>(FF->getValue())
<< " ValueSize:" << static_cast<unsigned>(FF->getValueSize())
<< " NumValues:" << FF->getNumValues();
break;
}
case MCFragment::FT_Relaxable: {
- const MCRelaxableFragment *F = cast<MCRelaxableFragment>(this);
+ const auto *F = cast<MCRelaxableFragment>(this);
OS << "\n ";
OS << " Inst:";
F->getInst().dump_pretty(OS);
break;
}
case MCFragment::FT_Org: {
- const MCOrgFragment *OF = cast<MCOrgFragment>(this);
+ const auto *OF = cast<MCOrgFragment>(this);
OS << "\n ";
OS << " Offset:" << OF->getOffset()
<< " Value:" << static_cast<unsigned>(OF->getValue());
break;
}
case MCFragment::FT_Dwarf: {
- const MCDwarfLineAddrFragment *OF = cast<MCDwarfLineAddrFragment>(this);
+ const auto *OF = cast<MCDwarfLineAddrFragment>(this);
OS << "\n ";
OS << " AddrDelta:" << OF->getAddrDelta()
<< " LineDelta:" << OF->getLineDelta();
break;
}
case MCFragment::FT_DwarfFrame: {
- const MCDwarfCallFrameFragment *CF = cast<MCDwarfCallFrameFragment>(this);
+ const auto *CF = cast<MCDwarfCallFrameFragment>(this);
OS << "\n ";
OS << " AddrDelta:" << CF->getAddrDelta();
break;
}
case MCFragment::FT_LEB: {
- const MCLEBFragment *LF = cast<MCLEBFragment>(this);
+ const auto *LF = cast<MCLEBFragment>(this);
OS << "\n ";
OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
break;
}
- case MCFragment::FT_Padding: {
- const MCPaddingFragment *F = cast<MCPaddingFragment>(this);
- OS << "\n ";
- OS << " PaddingPoliciesMask:" << F->getPaddingPoliciesMask()
- << " IsInsertionPoint:" << F->isInsertionPoint()
- << " Size:" << F->getSize();
- OS << "\n ";
- OS << " Inst:";
- F->getInst().dump_pretty(OS);
- OS << " InstSize:" << F->getInstSize();
+ case MCFragment::FT_BoundaryAlign: {
+ const auto *BF = cast<MCBoundaryAlignFragment>(this);
+ if (BF->canEmitNops())
+ OS << " (can emit nops to align";
+ if (BF->isFused())
+ OS << " fused branch)";
+ else
+ OS << " unfused branch)";
OS << "\n ";
+ OS << " BoundarySize:" << BF->getAlignment().value()
+ << " Size:" << BF->getSize();
break;
}
case MCFragment::FT_SymbolId: {
- const MCSymbolIdFragment *F = cast<MCSymbolIdFragment>(this);
+ const auto *F = cast<MCSymbolIdFragment>(this);
OS << "\n ";
OS << " Sym:" << F->getSymbol();
break;
diff --git a/llvm/lib/MC/MCInstPrinter.cpp b/llvm/lib/MC/MCInstPrinter.cpp
index c5c06f323e680..8bf699279ada4 100644
--- a/llvm/lib/MC/MCInstPrinter.cpp
+++ b/llvm/lib/MC/MCInstPrinter.cpp
@@ -10,7 +10,9 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -57,6 +59,94 @@ void MCInstPrinter::printAnnotation(raw_ostream &OS, StringRef Annot) {
}
}
+static bool matchAliasCondition(const MCInst &MI, const MCSubtargetInfo *STI,
+ const MCRegisterInfo &MRI, unsigned &OpIdx,
+ const AliasMatchingData &M,
+ const AliasPatternCond &C) {
+ // Feature tests are special, they don't consume operands.
+ if (C.Kind == AliasPatternCond::K_Feature)
+ return STI->getFeatureBits().test(C.Value);
+ if (C.Kind == AliasPatternCond::K_NegFeature)
+ return !STI->getFeatureBits().test(C.Value);
+
+ // Get and consume an operand.
+ const MCOperand &Opnd = MI.getOperand(OpIdx);
+ ++OpIdx;
+
+ // Check the specific condition for the operand.
+ switch (C.Kind) {
+ case AliasPatternCond::K_Imm:
+ // Operand must be a specific immediate.
+ return Opnd.isImm() && Opnd.getImm() == int32_t(C.Value);
+ case AliasPatternCond::K_Reg:
+ // Operand must be a specific register.
+ return Opnd.isReg() && Opnd.getReg() == C.Value;
+ case AliasPatternCond::K_TiedReg:
+ // Operand must match the register of another operand.
+ return Opnd.isReg() && Opnd.getReg() == MI.getOperand(C.Value).getReg();
+ case AliasPatternCond::K_RegClass:
+ // Operand must be a register in this class. Value is a register class id.
+ return Opnd.isReg() && MRI.getRegClass(C.Value).contains(Opnd.getReg());
+ case AliasPatternCond::K_Custom:
+ // Operand must match some custom criteria.
+ return M.ValidateMCOperand(Opnd, *STI, C.Value);
+ case AliasPatternCond::K_Ignore:
+ // Operand can be anything.
+ return true;
+ case AliasPatternCond::K_Feature:
+ case AliasPatternCond::K_NegFeature:
+ llvm_unreachable("handled earlier");
+ }
+ llvm_unreachable("invalid kind");
+}
+
+const char *MCInstPrinter::matchAliasPatterns(const MCInst *MI,
+ const MCSubtargetInfo *STI,
+ const AliasMatchingData &M) {
+ // Binary search by opcode. Return false if there are no aliases for this
+ // opcode.
+ auto It = lower_bound(M.OpToPatterns, MI->getOpcode(),
+ [](const PatternsForOpcode &L, unsigned Opcode) {
+ return L.Opcode < Opcode;
+ });
+ if (It == M.OpToPatterns.end() || It->Opcode != MI->getOpcode())
+ return nullptr;
+
+ // Try all patterns for this opcode.
+ uint32_t AsmStrOffset = ~0U;
+ ArrayRef<AliasPattern> Patterns =
+ M.Patterns.slice(It->PatternStart, It->NumPatterns);
+ for (const AliasPattern &P : Patterns) {
+ // Check operand count first.
+ if (MI->getNumOperands() != P.NumOperands)
+ return nullptr;
+
+ // Test all conditions for this pattern.
+ ArrayRef<AliasPatternCond> Conds =
+ M.PatternConds.slice(P.AliasCondStart, P.NumConds);
+ unsigned OpIdx = 0;
+ if (llvm::all_of(Conds, [&](const AliasPatternCond &C) {
+ return matchAliasCondition(*MI, STI, MRI, OpIdx, M, C);
+ })) {
+ // If all conditions matched, use this asm string.
+ AsmStrOffset = P.AsmStrOffset;
+ break;
+ }
+ }
+
+ // If no alias matched, don't print an alias.
+ if (AsmStrOffset == ~0U)
+ return nullptr;
+
+ // Go to offset AsmStrOffset and use the null terminated string there. The
+ // offset should point to the beginning of an alias string, so it should
+ // either be zero or be preceded by a null byte.
+ assert(AsmStrOffset < M.AsmStrings.size() &&
+ (AsmStrOffset == 0 || M.AsmStrings[AsmStrOffset - 1] == '\0') &&
+ "bad asm string offset");
+ return M.AsmStrings.data() + AsmStrOffset;
+}
+
/// Utility functions to make adding mark ups simpler.
StringRef MCInstPrinter::markup(StringRef s) const {
if (getUseMarkup())
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 70c0409ece7a9..d567cc14a8306 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -40,8 +40,7 @@ static bool useCompactUnwind(const Triple &T) {
return true;
// And the iOS simulator.
- if (T.isiOS() &&
- (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86))
+ if (T.isiOS() && T.isX86())
return true;
return false;
@@ -192,7 +191,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
Ctx->getMachOSection("__LD", "__compact_unwind", MachO::S_ATTR_DEBUG,
SectionKind::getReadOnly());
- if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86)
+ if (T.isX86())
CompactUnwindDwarfEHFrameOnly = 0x04000000; // UNWIND_X86_64_MODE_DWARF
else if (T.getArch() == Triple::aarch64 || T.getArch() == Triple::aarch64_32)
CompactUnwindDwarfEHFrameOnly = 0x03000000; // UNWIND_ARM64_MODE_DWARF
@@ -304,9 +303,14 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
case Triple::mipsel:
case Triple::mips64:
case Triple::mips64el:
- FDECFIEncoding = Ctx->getAsmInfo()->getCodePointerSize() == 4
- ? dwarf::DW_EH_PE_sdata4
- : dwarf::DW_EH_PE_sdata8;
+ // We cannot use DW_EH_PE_sdata8 for the large PositionIndependent case
+ // since there is no R_MIPS_PC64 relocation (only a 32-bit version).
+ if (PositionIndependent && !Large)
+ FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
+ else
+ FDECFIEncoding = Ctx->getAsmInfo()->getCodePointerSize() == 4
+ ? dwarf::DW_EH_PE_sdata4
+ : dwarf::DW_EH_PE_sdata8;
break;
case Triple::ppc64:
case Triple::ppc64le:
@@ -463,6 +467,11 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
DebugSecType, ELF::SHF_EXCLUDE);
DwarfRnglistsDWOSection =
Ctx->getELFSection(".debug_rnglists.dwo", DebugSecType, ELF::SHF_EXCLUDE);
+ DwarfMacinfoDWOSection =
+ Ctx->getELFSection(".debug_macinfo.dwo", DebugSecType, ELF::SHF_EXCLUDE);
+
+ DwarfLoclistsDWOSection =
+ Ctx->getELFSection(".debug_loclists.dwo", DebugSecType, ELF::SHF_EXCLUDE);
// DWP Sections
DwarfCUIndexSection =
@@ -480,9 +489,6 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
Ctx->getELFSection(".eh_frame", EHSectionType, EHSectionFlags);
StackSizesSection = Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, 0);
-
- RemarksSection =
- Ctx->getELFSection(".remarks", ELF::SHT_PROGBITS, ELF::SHF_EXCLUDE);
}
void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
@@ -619,6 +625,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ,
SectionKind::getMetadata(), "debug_macinfo");
+ DwarfMacinfoDWOSection = Ctx->getCOFFSection(
+ ".debug_macinfo.dwo",
+ COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getMetadata(), "debug_macinfo.dwo");
DwarfInfoDWOSection = Ctx->getCOFFSection(
".debug_info.dwo",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
@@ -715,6 +726,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
COFF::IMAGE_SCN_MEM_READ,
SectionKind::getMetadata());
+ GLJMPSection = Ctx->getCOFFSection(".gljmp$y",
+ COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getMetadata());
+
TLSDataSection = Ctx->getCOFFSection(
".tls$", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ |
COFF::IMAGE_SCN_MEM_WRITE,
@@ -775,6 +791,10 @@ void MCObjectFileInfo::initXCOFFMCObjectFileInfo(const Triple &T) {
DataSection = Ctx->getXCOFFSection(
".data", XCOFF::StorageMappingClass::XMC_RW, XCOFF::XTY_SD,
XCOFF::C_HIDEXT, SectionKind::getData());
+
+ ReadOnlySection = Ctx->getXCOFFSection(
+ ".rodata", XCOFF::StorageMappingClass::XMC_RO, XCOFF::XTY_SD,
+ XCOFF::C_HIDEXT, SectionKind::getReadOnly());
}
void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC,
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 83f6ab8fe332e..3d1358df475f1 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -29,7 +29,10 @@ MCObjectStreamer::MCObjectStreamer(MCContext &Context,
: MCStreamer(Context),
Assembler(std::make_unique<MCAssembler>(
Context, std::move(TAB), std::move(Emitter), std::move(OW))),
- EmitEHFrame(true), EmitDebugFrame(false) {}
+ EmitEHFrame(true), EmitDebugFrame(false) {
+ if (Assembler->getBackendPtr())
+ setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
+}
MCObjectStreamer::~MCObjectStreamer() {}
@@ -42,20 +45,64 @@ MCAssembler *MCObjectStreamer::getAssemblerPtr() {
return nullptr;
}
+void MCObjectStreamer::addPendingLabel(MCSymbol* S) {
+ MCSection *CurSection = getCurrentSectionOnly();
+ if (CurSection) {
+ // Register labels that have not yet been assigned to a Section.
+ if (!PendingLabels.empty()) {
+ for (MCSymbol* Sym : PendingLabels)
+ CurSection->addPendingLabel(Sym);
+ PendingLabels.clear();
+ }
+
+ // Add this label to the current Section / Subsection.
+ CurSection->addPendingLabel(S, CurSubsectionIdx);
+
+ // Add this Section to the list of PendingLabelSections.
+ auto SecIt = std::find(PendingLabelSections.begin(),
+ PendingLabelSections.end(), CurSection);
+ if (SecIt == PendingLabelSections.end())
+ PendingLabelSections.push_back(CurSection);
+ }
+ else
+ // There is no Section / Subsection for this label yet.
+ PendingLabels.push_back(S);
+}
+
void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
- if (PendingLabels.empty())
+ MCSection *CurSection = getCurrentSectionOnly();
+ if (!CurSection) {
+ assert(PendingLabels.empty());
return;
- if (!F) {
- F = new MCDataFragment();
- MCSection *CurSection = getCurrentSectionOnly();
- CurSection->getFragmentList().insert(CurInsertionPoint, F);
- F->setParent(CurSection);
}
- for (MCSymbol *Sym : PendingLabels) {
- Sym->setFragment(F);
- Sym->setOffset(FOffset);
+ // Register labels that have not yet been assigned to a Section.
+ if (!PendingLabels.empty()) {
+ for (MCSymbol* Sym : PendingLabels)
+ CurSection->addPendingLabel(Sym, CurSubsectionIdx);
+ PendingLabels.clear();
}
- PendingLabels.clear();
+
+ // Associate a fragment with this label, either the supplied fragment
+ // or an empty data fragment.
+ if (F)
+ CurSection->flushPendingLabels(F, FOffset, CurSubsectionIdx);
+ else
+ CurSection->flushPendingLabels(nullptr, 0, CurSubsectionIdx);
+}
+
+void MCObjectStreamer::flushPendingLabels() {
+ // Register labels that have not yet been assigned to a Section.
+ if (!PendingLabels.empty()) {
+ MCSection *CurSection = getCurrentSectionOnly();
+ assert(CurSection);
+ for (MCSymbol* Sym : PendingLabels)
+ CurSection->addPendingLabel(Sym, CurSubsectionIdx);
+ PendingLabels.clear();
+ }
+
+ // Assign an empty data fragment to all remaining pending labels.
+ for (MCSection* Section : PendingLabelSections)
+ Section->flushPendingLabels();
}
// When fixup's offset is a forward declared label, e.g.:
@@ -120,6 +167,7 @@ void MCObjectStreamer::reset() {
EmitEHFrame = true;
EmitDebugFrame = false;
PendingLabels.clear();
+ PendingLabelSections.clear();
MCStreamer::reset();
}
@@ -167,16 +215,6 @@ MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) {
return F;
}
-MCPaddingFragment *MCObjectStreamer::getOrCreatePaddingFragment() {
- MCPaddingFragment *F =
- dyn_cast_or_null<MCPaddingFragment>(getCurrentFragment());
- if (!F) {
- F = new MCPaddingFragment();
- insert(F);
- }
- return F;
-}
-
void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
Assembler->registerSymbol(Sym);
}
@@ -243,18 +281,32 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
Symbol->setFragment(F);
Symbol->setOffset(F->getContents().size());
} else {
- PendingLabels.push_back(Symbol);
+ // Assign all pending labels to offset 0 within the dummy "pending"
+ // fragment. (They will all be reassigned to a real fragment in
+ // flushPendingLabels())
+ Symbol->setOffset(0);
+ addPendingLabel(Symbol);
}
}
-void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) {
+// Emit a label at a previously emitted fragment/offset position. This must be
+// within the currently-active section.
+void MCObjectStreamer::EmitLabelAtPos(MCSymbol *Symbol, SMLoc Loc,
+ MCFragment *F, uint64_t Offset) {
+ assert(F->getParent() == getCurrentSectionOnly());
+
MCStreamer::EmitLabel(Symbol, Loc);
getAssembler().registerSymbol(*Symbol);
auto *DF = dyn_cast_or_null<MCDataFragment>(F);
- if (DF)
+ Symbol->setOffset(Offset);
+ if (DF) {
Symbol->setFragment(F);
- else
- PendingLabels.push_back(Symbol);
+ } else {
+ assert(isa<MCDummyFragment>(F) &&
+ "F must either be an MCDataFragment or the pending MCDummyFragment");
+ assert(Offset == 0);
+ addPendingLabel(Symbol);
+ }
}
void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) {
@@ -288,7 +340,6 @@ void MCObjectStreamer::ChangeSection(MCSection *Section,
bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
const MCExpr *Subsection) {
assert(Section && "Cannot switch to a null section!");
- flushPendingLabels(nullptr);
getContext().clearDwarfLocSeen();
bool Created = getAssembler().registerSection(*Section);
@@ -299,8 +350,9 @@ bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
report_fatal_error("Cannot evaluate subsection number");
if (IntSubsection < 0 || IntSubsection > 8192)
report_fatal_error("Subsection number out of range");
+ CurSubsectionIdx = unsigned(IntSubsection);
CurInsertionPoint =
- Section->getSubsectionInsertionPoint(unsigned(IntSubsection));
+ Section->getSubsectionInsertionPoint(CurSubsectionIdx);
return Created;
}
@@ -315,9 +367,9 @@ bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {
void MCObjectStreamer::EmitInstruction(const MCInst &Inst,
const MCSubtargetInfo &STI) {
- getAssembler().getBackend().handleCodePaddingInstructionBegin(Inst);
+ getAssembler().getBackend().alignBranchesBegin(*this, Inst);
EmitInstructionImpl(Inst, STI);
- getAssembler().getBackend().handleCodePaddingInstructionEnd(Inst);
+ getAssembler().getBackend().alignBranchesEnd(*this, Inst);
}
void MCObjectStreamer::EmitInstructionImpl(const MCInst &Inst,
@@ -520,12 +572,6 @@ void MCObjectStreamer::EmitBytes(StringRef Data) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
DF->getContents().append(Data.begin(), Data.end());
-
- // EmitBytes might not cover all possible ways we emit data (or could be used
- // to emit executable code in some cases), but is the best method we have
- // right now for checking this.
- MCSection *Sec = getCurrentSectionOnly();
- Sec->setHasData(true);
}
void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment,
@@ -554,16 +600,6 @@ void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
insert(new MCOrgFragment(*Offset, Value, Loc));
}
-void MCObjectStreamer::EmitCodePaddingBasicBlockStart(
- const MCCodePaddingContext &Context) {
- getAssembler().getBackend().handleCodePaddingBasicBlockStart(this, Context);
-}
-
-void MCObjectStreamer::EmitCodePaddingBasicBlockEnd(
- const MCCodePaddingContext &Context) {
- getAssembler().getBackend().handleCodePaddingBasicBlockEnd(Context);
-}
-
// Associate DTPRel32 fixup with data and resize data area
void MCObjectStreamer::EmitDTPRel32Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
@@ -725,7 +761,9 @@ void MCObjectStreamer::FinishImpl() {
// Dump out the dwarf file & directory tables and line tables.
MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams());
+ // Update any remaining pending labels with empty data fragments.
flushPendingLabels();
+
resolvePendingFixups();
getAssembler().Finish();
}
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index b59ac08ad6cc4..94a44c1f93b18 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -91,16 +91,13 @@ struct MacroInstantiation {
SMLoc InstantiationLoc;
/// The buffer where parsing should resume upon instantiation completion.
- int ExitBuffer;
+ unsigned ExitBuffer;
/// The location where parsing should resume upon instantiation completion.
SMLoc ExitLoc;
/// The depth of TheCondStack at the start of the instantiation.
size_t CondStackDepth;
-
-public:
- MacroInstantiation(SMLoc IL, int EB, SMLoc EL, size_t CondStackDepth);
};
struct ParseStatementInfo {
@@ -916,13 +913,12 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// While we have input, parse each statement.
while (Lexer.isNot(AsmToken::Eof)) {
ParseStatementInfo Info(&AsmStrRewrites);
- if (!parseStatement(Info, nullptr))
- continue;
+ bool Parsed = parseStatement(Info, nullptr);
// If we have a Lexer Error we are on an Error Token. Load in Lexer Error
// for printing ErrMsg via Lex() only if no (presumably better) parser error
// exists.
- if (!hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
+ if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
Lex();
}
@@ -930,7 +926,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
printPendingErrors();
// Skipping to the next line if needed.
- if (!getLexer().isAtStartOfStatement())
+ if (Parsed && !getLexer().isAtStartOfStatement())
eatToEndOfStatement();
}
@@ -2521,11 +2517,6 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
return false;
}
-MacroInstantiation::MacroInstantiation(SMLoc IL, int EB, SMLoc EL,
- size_t CondStackDepth)
- : InstantiationLoc(IL), ExitBuffer(EB), ExitLoc(EL),
- CondStackDepth(CondStackDepth) {}
-
static bool isOperator(AsmToken::TokenKind kind) {
switch (kind) {
default:
@@ -2800,8 +2791,8 @@ bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
// Create the macro instantiation object and add to the current macro
// instantiation stack.
- MacroInstantiation *MI = new MacroInstantiation(
- NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size());
+ MacroInstantiation *MI = new MacroInstantiation{
+ NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
ActiveMacros.push_back(MI);
++NumOfMacroInstantiations;
@@ -3139,8 +3130,9 @@ bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
Value = APFloat::getNaN(Semantics, false, ~0);
else
return TokError("invalid floating point literal");
- } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) ==
- APFloat::opInvalidOp)
+ } else if (errorToBool(
+ Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
+ .takeError()))
return TokError("invalid floating point literal");
if (IsNeg)
Value.changeSign();
@@ -5545,8 +5537,8 @@ void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
// Create the macro instantiation object and add to the current macro
// instantiation stack.
- MacroInstantiation *MI = new MacroInstantiation(
- DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size());
+ MacroInstantiation *MI = new MacroInstantiation{
+ DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
ActiveMacros.push_back(MI);
// Jump to the macro instantiation and prime the lexer.
@@ -5813,10 +5805,6 @@ bool AsmParser::parseMSInlineAsm(
for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
- // Immediate.
- if (Operand.isImm())
- continue;
-
// Register operand.
if (Operand.isReg() && !Operand.needAddressOf() &&
!getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
@@ -5836,19 +5824,31 @@ bool AsmParser::parseMSInlineAsm(
if (!OpDecl)
continue;
+ StringRef Constraint = Operand.getConstraint();
+ if (Operand.isImm()) {
+ // Offset as immediate
+ if (Operand.isOffsetOfLocal())
+ Constraint = "r";
+ else
+ Constraint = "i";
+ }
+
bool isOutput = (i == 1) && Desc.mayStore();
SMLoc Start = SMLoc::getFromPointer(SymName.data());
if (isOutput) {
++InputIdx;
OutputDecls.push_back(OpDecl);
OutputDeclsAddressOf.push_back(Operand.needAddressOf());
- OutputConstraints.push_back(("=" + Operand.getConstraint()).str());
+ OutputConstraints.push_back(("=" + Constraint).str());
AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
} else {
InputDecls.push_back(OpDecl);
InputDeclsAddressOf.push_back(Operand.needAddressOf());
- InputConstraints.push_back(Operand.getConstraint().str());
- AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
+ InputConstraints.push_back(Constraint.str());
+ if (Desc.OpInfo[i - 1].isBranchTarget())
+ AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
+ else
+ AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
}
}
@@ -5895,7 +5895,11 @@ bool AsmParser::parseMSInlineAsm(
const char *AsmStart = ASMString.begin();
const char *AsmEnd = ASMString.end();
array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
- for (const AsmRewrite &AR : AsmStrRewrites) {
+ for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) {
+ const AsmRewrite &AR = *it;
+ // Check if this has already been covered by another rewrite...
+ if (AR.Done)
+ continue;
AsmRewriteKind Kind = AR.Kind;
const char *Loc = AR.Loc.getPointer();
@@ -5926,9 +5930,32 @@ bool AsmParser::parseMSInlineAsm(
OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
<< AR.IntelExp.IndexReg;
if (AR.IntelExp.Scale > 1)
- OS << " * $$" << AR.IntelExp.Scale;
- if (AR.IntelExp.Imm || !AR.IntelExp.hasRegs())
- OS << (AR.IntelExp.hasRegs() ? " + $$" : "$$") << AR.IntelExp.Imm;
+ OS << " * $$" << AR.IntelExp.Scale;
+ if (AR.IntelExp.hasOffset()) {
+ if (AR.IntelExp.hasRegs())
+ OS << " + ";
+ // Fuse this rewrite with a rewrite of the offset name, if present.
+ StringRef OffsetName = AR.IntelExp.OffsetName;
+ SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
+ size_t OffsetLen = OffsetName.size();
+ auto rewrite_it = std::find_if(
+ it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
+ return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
+ (FusingAR.Kind == AOK_Input ||
+ FusingAR.Kind == AOK_CallInput);
+ });
+ if (rewrite_it == AsmStrRewrites.end()) {
+ OS << "offset " << OffsetName;
+ } else if (rewrite_it->Kind == AOK_CallInput) {
+ OS << "${" << InputIdx++ << ":P}";
+ rewrite_it->Done = true;
+ } else {
+ OS << '$' << InputIdx++;
+ rewrite_it->Done = true;
+ }
+ }
+ if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
+ OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
if (AR.IntelExp.NeedBracs)
OS << "]";
break;
@@ -5938,6 +5965,9 @@ bool AsmParser::parseMSInlineAsm(
case AOK_Input:
OS << '$' << InputIdx++;
break;
+ case AOK_CallInput:
+ OS << "${" << InputIdx++ << ":P}";
+ break;
case AOK_Output:
OS << '$' << OutputIdx++;
break;
diff --git a/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/llvm/lib/MC/MCParser/COFFAsmParser.cpp
index 06f8310ae0615..51bb1fe92b73d 100644
--- a/llvm/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/COFFAsmParser.cpp
@@ -144,7 +144,7 @@ public:
COFFAsmParser() = default;
};
-} // end annonomous namespace.
+} // end anonymous namespace.
static SectionKind computeSectionKind(unsigned Flags) {
if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp
index 2c892ab816081..074534bd73dbd 100644
--- a/llvm/lib/MC/MCSection.cpp
+++ b/llvm/lib/MC/MCSection.cpp
@@ -22,8 +22,7 @@ using namespace llvm;
MCSection::MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin)
: Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false),
- HasData(false), IsRegistered(false), DummyFragment(this), Variant(V),
- Kind(K) {}
+ IsRegistered(false), DummyFragment(this), Variant(V), Kind(K) {}
MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) {
if (!End)
@@ -86,6 +85,41 @@ MCSection::getSubsectionInsertionPoint(unsigned Subsection) {
return IP;
}
+void MCSection::addPendingLabel(MCSymbol* label, unsigned Subsection) {
+ PendingLabels.push_back(PendingLabel(label, Subsection));
+}
+
+void MCSection::flushPendingLabels(MCFragment *F, uint64_t FOffset,
+ unsigned Subsection) {
+ if (PendingLabels.empty())
+ return;
+
+ // Set the fragment and fragment offset for all pending symbols in the
+ // specified Subsection, and remove those symbols from the pending list.
+ for (auto It = PendingLabels.begin(); It != PendingLabels.end(); ++It) {
+ PendingLabel& Label = *It;
+ if (Label.Subsection == Subsection) {
+ Label.Sym->setFragment(F);
+ Label.Sym->setOffset(FOffset);
+ PendingLabels.erase(It--);
+ }
+ }
+}
+
+void MCSection::flushPendingLabels() {
+ // Make sure all remaining pending labels point to data fragments, by
+ // creating new empty data fragments for each Subsection with labels pending.
+ while (!PendingLabels.empty()) {
+ PendingLabel& Label = PendingLabels[0];
+ iterator CurInsertionPoint =
+ this->getSubsectionInsertionPoint(Label.Subsection);
+ MCFragment *F = new MCDataFragment();
+ getFragmentList().insert(CurInsertionPoint, F);
+ F->setParent(this);
+ flushPendingLabels(F, 0, Label.Subsection);
+ }
+}
+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MCSection::dump() const {
raw_ostream &OS = errs();
diff --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp
index d52959f15f928..8377e295532ae 100644
--- a/llvm/lib/MC/MCSectionXCOFF.cpp
+++ b/llvm/lib/MC/MCSectionXCOFF.cpp
@@ -15,18 +15,6 @@ using namespace llvm;
MCSectionXCOFF::~MCSectionXCOFF() = default;
-static StringRef getMappingClassString(XCOFF::StorageMappingClass SMC) {
- switch (SMC) {
- case XCOFF::XMC_DS:
- return "DS";
- case XCOFF::XMC_RW:
- return "RW";
- case XCOFF::XMC_PR:
- return "PR";
- default:
- report_fatal_error("Unhandled storage-mapping class.");
- }
-}
void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
raw_ostream &OS,
@@ -35,9 +23,14 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
if (getMappingClass() != XCOFF::XMC_PR)
report_fatal_error("Unhandled storage-mapping class for .text csect");
- OS << "\t.csect " << getSectionName() << "["
- << getMappingClassString(getMappingClass())
- << "]" << '\n';
+ OS << "\t.csect " << QualName->getName() << '\n';
+ return;
+ }
+
+ if (getKind().isReadOnly()) {
+ if (getMappingClass() != XCOFF::XMC_RO)
+ report_fatal_error("Unhandled storage-mapping class for .rodata csect.");
+ OS << "\t.csect " << QualName->getName() << '\n';
return;
}
@@ -45,8 +38,9 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
switch (getMappingClass()) {
case XCOFF::XMC_RW:
case XCOFF::XMC_DS:
- OS << "\t.csect " << getSectionName() << "["
- << getMappingClassString(getMappingClass()) << "]" << '\n';
+ OS << "\t.csect " << QualName->getName() << '\n';
+ break;
+ case XCOFF::XMC_TC:
break;
case XCOFF::XMC_TC0:
OS << "\t.toc\n";
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index b8278cb110799..0ab8835367798 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -977,9 +977,10 @@ void MCStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
}
void MCTargetStreamer::prettyPrintAsm(MCInstPrinter &InstPrinter,
- raw_ostream &OS, const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- InstPrinter.printInst(&Inst, OS, "", STI);
+ uint64_t Address, const MCInst &Inst,
+ const MCSubtargetInfo &STI,
+ raw_ostream &OS) {
+ InstPrinter.printInst(&Inst, Address, "", STI, OS);
}
void MCStreamer::visitUsedSymbol(const MCSymbol &Sym) {
@@ -1063,7 +1064,8 @@ void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
void MCStreamer::EmitCOFFSymbolType(int Type) {
llvm_unreachable("this directive only supported on COFF targets");
}
-void MCStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+void MCStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
+ MCSymbol *CsectSym,
unsigned ByteAlign) {
llvm_unreachable("this directive only supported on XCOFF targets");
}
diff --git a/llvm/lib/MC/MCSymbolELF.cpp b/llvm/lib/MC/MCSymbolELF.cpp
index a07c56c64f841..1830b87fd8567 100644
--- a/llvm/lib/MC/MCSymbolELF.cpp
+++ b/llvm/lib/MC/MCSymbolELF.cpp
@@ -40,8 +40,6 @@ enum {
void MCSymbolELF::setBinding(unsigned Binding) const {
setIsBindingSet();
- if (getType() == ELF::STT_SECTION && Binding != ELF::STB_LOCAL)
- setType(ELF::STT_NOTYPE);
unsigned Val;
switch (Binding) {
default:
@@ -93,8 +91,6 @@ unsigned MCSymbolELF::getBinding() const {
void MCSymbolELF::setType(unsigned Type) const {
unsigned Val;
- if (Type == ELF::STT_SECTION && getBinding() != ELF::STB_LOCAL)
- return;
switch (Type) {
default:
llvm_unreachable("Unsupported Binding");
diff --git a/llvm/lib/MC/MCTargetOptions.cpp b/llvm/lib/MC/MCTargetOptions.cpp
index 96bb094134fe8..5848e3ecadbe1 100644
--- a/llvm/lib/MC/MCTargetOptions.cpp
+++ b/llvm/lib/MC/MCTargetOptions.cpp
@@ -15,8 +15,8 @@ MCTargetOptions::MCTargetOptions()
: MCRelaxAll(false), MCNoExecStack(false), MCFatalWarnings(false),
MCNoWarn(false), MCNoDeprecatedWarn(false), MCSaveTempLabels(false),
MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false),
- MCPIECopyRelocations(false), ShowMCEncoding(false), ShowMCInst(false),
- AsmVerbose(false), PreserveAsmComments(true) {}
+ ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
+ PreserveAsmComments(true) {}
StringRef MCTargetOptions::getABIName() const {
return ABIName;
diff --git a/llvm/lib/MC/MCValue.cpp b/llvm/lib/MC/MCValue.cpp
index 81da47b2eced2..b6bcec9b2ca07 100644
--- a/llvm/lib/MC/MCValue.cpp
+++ b/llvm/lib/MC/MCValue.cpp
@@ -54,8 +54,5 @@ MCSymbolRefExpr::VariantKind MCValue::getAccessVariant() const {
if (!A)
return MCSymbolRefExpr::VK_None;
- MCSymbolRefExpr::VariantKind Kind = A->getKind();
- if (Kind == MCSymbolRefExpr::VK_WEAKREF)
- return MCSymbolRefExpr::VK_None;
- return Kind;
+ return A->getKind();
}
diff --git a/llvm/lib/MC/MCXCOFFStreamer.cpp b/llvm/lib/MC/MCXCOFFStreamer.cpp
index 50937d6adc0c8..6efa167ced42a 100644
--- a/llvm/lib/MC/MCXCOFFStreamer.cpp
+++ b/llvm/lib/MC/MCXCOFFStreamer.cpp
@@ -50,12 +50,6 @@ void MCXCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
XCOFF::C_HIDEXT);
Symbol->setCommon(Size, ByteAlignment);
- // Need to add this symbol to the current Fragment which will belong to the
- // containing CSECT.
- auto *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
- assert(F && "Expected a valid section with a fragment set.");
- Symbol->setFragment(F);
-
// Emit the alignment and storage for the variable to the section.
EmitValueToAlignment(ByteAlignment);
EmitZeros(Size);
@@ -94,8 +88,9 @@ MCStreamer *llvm::createXCOFFStreamer(MCContext &Context,
return S;
}
-void MCXCOFFStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol,
+void MCXCOFFStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
uint64_t Size,
+ MCSymbol *CsectSym,
unsigned ByteAlignment) {
- EmitCommonSymbol(Symbol, Size, ByteAlignment);
+ EmitCommonSymbol(CsectSym, Size, ByteAlignment);
}
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index c1ff3cc2480cd..321f93d76092b 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -1324,6 +1324,14 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
Comdats[C->getName()].emplace_back(
WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index});
}
+
+ if (WS.hasExportName()) {
+ wasm::WasmExport Export;
+ Export.Name = WS.getExportName();
+ Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
+ Export.Index = Index;
+ Exports.push_back(Export);
+ }
} else {
// An import; the index was assigned above.
Index = WasmIndices.find(&WS)->second;
@@ -1452,8 +1460,10 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
Flags |= wasm::WASM_SYMBOL_EXPORTED;
}
}
- if (WS.getName() != WS.getImportName())
+ if (WS.hasImportName())
Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME;
+ if (WS.hasExportName())
+ Flags |= wasm::WASM_SYMBOL_EXPORTED;
wasm::WasmSymbolInfo Info;
Info.Name = WS.getName();
diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp
index 353c21068735b..e584c6222a5a2 100644
--- a/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -44,6 +44,7 @@ using namespace llvm;
namespace {
constexpr unsigned DefaultSectionAlign = 4;
+constexpr int16_t MaxSectionIndex = INT16_MAX;
// Packs the csect's alignment and type into a byte.
uint8_t getEncodedType(const MCSectionXCOFF *);
@@ -73,6 +74,14 @@ struct ControlSection {
: MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
};
+// Type to be used for a container representing a set of csects with
+// (approximately) the same storage mapping class. For example all the csects
+// with a storage mapping class of `xmc_pr` will get placed into the same
+// container.
+using CsectGroup = std::deque<ControlSection>;
+
+using CsectGroups = std::deque<CsectGroup *>;
+
// Represents the data related to a section excluding the csects that make up
// the raw data of the section. The csects are stored separately as not all
// sections contain csects, and some sections contain csects which are better
@@ -94,49 +103,70 @@ struct Section {
// Virtual sections do not need storage allocated in the object file.
const bool IsVirtual;
+ // XCOFF has special section numbers for symbols:
+ // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
+ // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
+ // relocatable.
+ // 0 Specifies N_UNDEF, an undefined external symbol.
+ // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
+ // hasn't been initialized.
+ static constexpr int16_t UninitializedIndex =
+ XCOFF::ReservedSectionNum::N_DEBUG - 1;
+
+ CsectGroups Groups;
+
void reset() {
Address = 0;
Size = 0;
FileOffsetToData = 0;
FileOffsetToRelocations = 0;
RelocationCount = 0;
- Index = -1;
+ Index = UninitializedIndex;
+ // Clear any csects we have stored.
+ for (auto *Group : Groups)
+ Group->clear();
}
- Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual)
+ Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
+ CsectGroups Groups)
: Address(0), Size(0), FileOffsetToData(0), FileOffsetToRelocations(0),
- RelocationCount(0), Flags(Flags), Index(-1), IsVirtual(IsVirtual) {
+ RelocationCount(0), Flags(Flags), Index(UninitializedIndex),
+ IsVirtual(IsVirtual), Groups(Groups) {
strncpy(Name, N, XCOFF::NameSize);
}
};
class XCOFFObjectWriter : public MCObjectWriter {
- // Type to be used for a container representing a set of csects with
- // (approximately) the same storage mapping class. For example all the csects
- // with a storage mapping class of `xmc_pr` will get placed into the same
- // container.
- using CsectGroup = std::deque<ControlSection>;
+
+ uint32_t SymbolTableEntryCount = 0;
+ uint32_t SymbolTableOffset = 0;
+ uint16_t SectionCount = 0;
support::endian::Writer W;
std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
StringTableBuilder Strings;
- // The non-empty sections, in the order they will appear in the section header
- // table.
- std::vector<Section *> Sections;
-
- // The Predefined sections.
- Section Text;
- Section BSS;
-
// CsectGroups. These store the csects which make up different parts of
// the sections. Should have one for each set of csects that get mapped into
// the same section and get handled in a 'similar' way.
+ CsectGroup UndefinedCsects;
CsectGroup ProgramCodeCsects;
+ CsectGroup ReadOnlyCsects;
+ CsectGroup DataCsects;
+ CsectGroup FuncDSCsects;
+ CsectGroup TOCCsects;
CsectGroup BSSCsects;
- uint32_t SymbolTableEntryCount = 0;
- uint32_t SymbolTableOffset = 0;
+ // The Predefined sections.
+ Section Text;
+ Section Data;
+ Section BSS;
+
+ // All the XCOFF sections, in the order they will appear in the section header
+ // table.
+ std::array<Section *const, 3> Sections{{&Text, &Data, &BSS}};
+
+ CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
virtual void reset() override;
@@ -190,27 +220,72 @@ XCOFFObjectWriter::XCOFFObjectWriter(
std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
: W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
Strings(StringTableBuilder::XCOFF),
- Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false),
- BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true) {}
+ Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
+ CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
+ Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false,
+ CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
+ BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
+ CsectGroups{&BSSCsects}) {}
void XCOFFObjectWriter::reset() {
+ UndefinedCsects.clear();
+
// Reset any sections we have written to, and empty the section header table.
for (auto *Sec : Sections)
Sec->reset();
- Sections.clear();
-
- // Clear any csects we have stored.
- ProgramCodeCsects.clear();
- BSSCsects.clear();
// Reset the symbol table and string table.
SymbolTableEntryCount = 0;
SymbolTableOffset = 0;
+ SectionCount = 0;
Strings.clear();
MCObjectWriter::reset();
}
+CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
+ switch (MCSec->getMappingClass()) {
+ case XCOFF::XMC_PR:
+ assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
+ "Only an initialized csect can contain program code.");
+ return ProgramCodeCsects;
+ case XCOFF::XMC_RO:
+ assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
+ "Only an initialized csect can contain read only data.");
+ return ReadOnlyCsects;
+ case XCOFF::XMC_RW:
+ if (XCOFF::XTY_CM == MCSec->getCSectType())
+ return BSSCsects;
+
+ if (XCOFF::XTY_SD == MCSec->getCSectType())
+ return DataCsects;
+
+ report_fatal_error("Unhandled mapping of read-write csect to section.");
+ case XCOFF::XMC_DS:
+ return FuncDSCsects;
+ case XCOFF::XMC_BS:
+ assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
+ "Mapping invalid csect. CSECT with bss storage class must be "
+ "common type.");
+ return BSSCsects;
+ case XCOFF::XMC_TC0:
+ assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
+ "Only an initialized csect can contain TOC-base.");
+ assert(TOCCsects.empty() &&
+ "We should have only one TOC-base, and it should be the first csect "
+ "in this CsectGroup.");
+ return TOCCsects;
+ case XCOFF::XMC_TC:
+ assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
+ "Only an initialized csect can contain TC entry.");
+ assert(!TOCCsects.empty() &&
+ "We should at least have a TOC-base in this CsectGroup.");
+ return TOCCsects;
+ default:
+ report_fatal_error("Unhandled mapping of csect to section.");
+ }
+}
+
void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) {
if (TargetObjectWriter->is64Bit())
@@ -225,49 +300,38 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
const auto *MCSec = cast<const MCSectionXCOFF>(&S);
assert(WrapperMap.find(MCSec) == WrapperMap.end() &&
"Cannot add a csect twice.");
+ assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
+ "An undefined csect should not get registered.");
// If the name does not fit in the storage provided in the symbol table
// entry, add it to the string table.
if (nameShouldBeInStringTable(MCSec->getSectionName()))
Strings.add(MCSec->getSectionName());
- switch (MCSec->getMappingClass()) {
- case XCOFF::XMC_PR:
- assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
- "Only an initialized csect can contain program code.");
- ProgramCodeCsects.emplace_back(MCSec);
- WrapperMap[MCSec] = &ProgramCodeCsects.back();
- break;
- case XCOFF::XMC_RW:
- if (XCOFF::XTY_CM == MCSec->getCSectType()) {
- BSSCsects.emplace_back(MCSec);
- WrapperMap[MCSec] = &BSSCsects.back();
- break;
- }
- report_fatal_error("Unhandled mapping of read-write csect to section.");
- case XCOFF::XMC_TC0:
- // TODO FIXME Handle emiting the TOC base.
- break;
- case XCOFF::XMC_BS:
- assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
- "Mapping invalid csect. CSECT with bss storage class must be "
- "common type.");
- BSSCsects.emplace_back(MCSec);
- WrapperMap[MCSec] = &BSSCsects.back();
- break;
- default:
- report_fatal_error("Unhandled mapping of csect to section.");
- }
+ CsectGroup &Group = getCsectGroup(MCSec);
+ Group.emplace_back(MCSec);
+ WrapperMap[MCSec] = &Group.back();
}
for (const MCSymbol &S : Asm.symbols()) {
// Nothing to do for temporary symbols.
if (S.isTemporary())
continue;
- const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
- // Map the symbol into its containing csect.
+ const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
const MCSectionXCOFF *ContainingCsect = XSym->getContainingCsect();
+
+ // Handle undefined symbol.
+ if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
+ UndefinedCsects.emplace_back(ContainingCsect);
+ continue;
+ }
+
+ // If the symbol is the csect itself, we don't need to put the symbol
+ // into csect's Syms.
+ if (XSym == ContainingCsect->getQualNameSymbol())
+ continue;
+
assert(WrapperMap.find(ContainingCsect) != WrapperMap.end() &&
"Expected containing csect to exist in map");
@@ -287,27 +351,37 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &,
const MCFragment *, const MCFixup &,
MCValue, uint64_t &) {
- report_fatal_error("XCOFF relocations not supported.");
+ // TODO: recordRelocation is not yet implemented.
}
void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
const MCAsmLayout &Layout) {
- // Write the program code control sections one at a time.
- uint32_t CurrentAddressLocation = Text.Address;
- for (const auto &Csect : ProgramCodeCsects) {
- if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
- W.OS.write_zeros(PaddingSize);
- Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
- CurrentAddressLocation = Csect.Address + Csect.Size;
- }
+ uint32_t CurrentAddressLocation = 0;
+ for (const auto *Section : Sections) {
+ // Nothing to write for this Section.
+ if (Section->Index == Section::UninitializedIndex || Section->IsVirtual)
+ continue;
+
+ assert(CurrentAddressLocation == Section->Address &&
+ "Sections should be written consecutively.");
+ for (const auto *Group : Section->Groups) {
+ for (const auto &Csect : *Group) {
+ if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
+ W.OS.write_zeros(PaddingSize);
+ if (Csect.Size)
+ Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
+ CurrentAddressLocation = Csect.Address + Csect.Size;
+ }
+ }
- if (Text.Index != -1) {
// The size of the tail padding in a section is the end virtual address of
// the current section minus the the end virtual address of the last csect
// in that section.
if (uint32_t PaddingSize =
- Text.Address + Text.Size - CurrentAddressLocation)
+ Section->Address + Section->Size - CurrentAddressLocation) {
W.OS.write_zeros(PaddingSize);
+ CurrentAddressLocation += PaddingSize;
+ }
}
}
@@ -345,7 +419,7 @@ void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
W.write<int32_t>(0);
W.write<uint32_t>(Strings.getOffset(SymbolName));
} else {
- char Name[XCOFF::NameSize];
+ char Name[XCOFF::NameSize+1];
std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
ArrayRef<char> NameRef(Name, XCOFF::NameSize);
W.write(NameRef);
@@ -431,7 +505,7 @@ void XCOFFObjectWriter::writeFileHeader() {
// Magic.
W.write<uint16_t>(0x01df);
// Number of sections.
- W.write<uint16_t>(Sections.size());
+ W.write<uint16_t>(SectionCount);
// Timestamp field. For reproducible output we write a 0, which represents no
// timestamp.
W.write<int32_t>(0);
@@ -447,6 +521,10 @@ void XCOFFObjectWriter::writeFileHeader() {
void XCOFFObjectWriter::writeSectionHeaderTable() {
for (const auto *Sec : Sections) {
+ // Nothing to write for this Section.
+ if (Sec->Index == Section::UninitializedIndex)
+ continue;
+
// Write Name.
ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
W.write(NameRef);
@@ -472,104 +550,112 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
}
void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
- // Print out symbol table for the program code.
- for (const auto &Csect : ProgramCodeCsects) {
- // Write out the control section first and then each symbol in it.
- writeSymbolTableEntryForControlSection(Csect, Text.Index,
- Csect.MCCsect->getStorageClass());
- for (const auto &Sym : Csect.Syms)
- writeSymbolTableEntryForCsectMemberLabel(
- Sym, Csect, Text.Index, Layout.getSymbolOffset(*Sym.MCSym));
+ for (const auto &Csect : UndefinedCsects) {
+ writeSymbolTableEntryForControlSection(
+ Csect, XCOFF::ReservedSectionNum::N_UNDEF, Csect.MCCsect->getStorageClass());
}
- // The BSS Section is special in that the csects must contain a single symbol,
- // and the contained symbol cannot be represented in the symbol table as a
- // label definition.
- for (auto &Csect : BSSCsects) {
- assert(Csect.Syms.size() == 1 &&
- "Uninitialized csect cannot contain more then 1 symbol.");
- Symbol &Sym = Csect.Syms.back();
- writeSymbolTableEntryForControlSection(Csect, BSS.Index,
- Sym.getStorageClass());
+ for (const auto *Section : Sections) {
+ // Nothing to write for this Section.
+ if (Section->Index == Section::UninitializedIndex)
+ continue;
+
+ for (const auto *Group : Section->Groups) {
+ if (Group->empty())
+ continue;
+
+ const int16_t SectionIndex = Section->Index;
+ for (const auto &Csect : *Group) {
+ // Write out the control section first and then each symbol in it.
+ writeSymbolTableEntryForControlSection(
+ Csect, SectionIndex, Csect.MCCsect->getStorageClass());
+
+ for (const auto &Sym : Csect.Syms)
+ writeSymbolTableEntryForCsectMemberLabel(
+ Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
+ }
+ }
}
}
void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
+ // The first symbol table entry is for the file name. We are not emitting it
+ // yet, so start at index 0.
+ uint32_t SymbolTableIndex = 0;
+
+ // Calculate indices for undefined symbols.
+ for (auto &Csect : UndefinedCsects) {
+ Csect.Size = 0;
+ Csect.Address = 0;
+ Csect.SymbolTableIndex = SymbolTableIndex;
+ // 1 main and 1 auxiliary symbol table entry for each contained symbol.
+ SymbolTableIndex += 2;
+ }
+
// The address corrresponds to the address of sections and symbols in the
// object file. We place the shared address 0 immediately after the
// section header table.
uint32_t Address = 0;
// Section indices are 1-based in XCOFF.
- int16_t SectionIndex = 1;
- // The first symbol table entry is for the file name. We are not emitting it
- // yet, so start at index 0.
- uint32_t SymbolTableIndex = 0;
+ int32_t SectionIndex = 1;
- // Text section comes first.
- if (!ProgramCodeCsects.empty()) {
- Sections.push_back(&Text);
- Text.Index = SectionIndex++;
- for (auto &Csect : ProgramCodeCsects) {
- const MCSectionXCOFF *MCSec = Csect.MCCsect;
- Csect.Address = alignTo(Address, MCSec->getAlignment());
- Csect.Size = Layout.getSectionAddressSize(MCSec);
- Address = Csect.Address + Csect.Size;
- Csect.SymbolTableIndex = SymbolTableIndex;
- // 1 main and 1 auxiliary symbol table entry for the csect.
- SymbolTableIndex += 2;
- for (auto &Sym : Csect.Syms) {
- Sym.SymbolTableIndex = SymbolTableIndex;
- // 1 main and 1 auxiliary symbol table entry for each contained symbol
+ for (auto *Section : Sections) {
+ const bool IsEmpty =
+ llvm::all_of(Section->Groups,
+ [](const CsectGroup *Group) { return Group->empty(); });
+ if (IsEmpty)
+ continue;
+
+ if (SectionIndex > MaxSectionIndex)
+ report_fatal_error("Section index overflow!");
+ Section->Index = SectionIndex++;
+ SectionCount++;
+
+ bool SectionAddressSet = false;
+ for (auto *Group : Section->Groups) {
+ if (Group->empty())
+ continue;
+
+ for (auto &Csect : *Group) {
+ const MCSectionXCOFF *MCSec = Csect.MCCsect;
+ Csect.Address = alignTo(Address, MCSec->getAlignment());
+ Csect.Size = Layout.getSectionAddressSize(MCSec);
+ Address = Csect.Address + Csect.Size;
+ Csect.SymbolTableIndex = SymbolTableIndex;
+ // 1 main and 1 auxiliary symbol table entry for the csect.
SymbolTableIndex += 2;
+
+ for (auto &Sym : Csect.Syms) {
+ Sym.SymbolTableIndex = SymbolTableIndex;
+ // 1 main and 1 auxiliary symbol table entry for each contained
+ // symbol.
+ SymbolTableIndex += 2;
+ }
}
- }
- Address = alignTo(Address, DefaultSectionAlign);
- // The first csect of a section can be aligned by adjusting the virtual
- // address of its containing section instead of writing zeroes into the
- // object file.
- Text.Address = ProgramCodeCsects.front().Address;
-
- Text.Size = Address - Text.Address;
- }
-
- // Data section Second. TODO
-
- // BSS Section third.
- if (!BSSCsects.empty()) {
- Sections.push_back(&BSS);
- BSS.Index = SectionIndex++;
- for (auto &Csect : BSSCsects) {
- const MCSectionXCOFF *MCSec = Csect.MCCsect;
- Csect.Address = alignTo(Address, MCSec->getAlignment());
- Csect.Size = Layout.getSectionAddressSize(MCSec);
- Address = Csect.Address + Csect.Size;
- Csect.SymbolTableIndex = SymbolTableIndex;
- // 1 main and 1 auxiliary symbol table entry for the csect.
- SymbolTableIndex += 2;
-
- assert(Csect.Syms.size() == 1 &&
- "csect in the BSS can only contain a single symbol.");
- Csect.Syms[0].SymbolTableIndex = Csect.SymbolTableIndex;
+ if (!SectionAddressSet) {
+ Section->Address = Group->front().Address;
+ SectionAddressSet = true;
+ }
}
- // Pad out Address to the default alignment. This is to match how the system
- // assembler handles the .bss section. Its size is always a multiple of 4.
- Address = alignTo(Address, DefaultSectionAlign);
- BSS.Address = BSSCsects.front().Address;
- BSS.Size = Address - BSS.Address;
+ // Make sure the address of the next section aligned to
+ // DefaultSectionAlign.
+ Address = alignTo(Address, DefaultSectionAlign);
+ Section->Size = Address - Section->Address;
}
SymbolTableEntryCount = SymbolTableIndex;
// Calculate the RawPointer value for each section.
uint64_t RawPointer = sizeof(XCOFF::FileHeader32) + auxiliaryHeaderSize() +
- Sections.size() * sizeof(XCOFF::SectionHeader32);
+ SectionCount * sizeof(XCOFF::SectionHeader32);
for (auto *Sec : Sections) {
- if (!Sec->IsVirtual) {
- Sec->FileOffsetToData = RawPointer;
- RawPointer += Sec->Size;
- }
+ if (Sec->Index == Section::UninitializedIndex || Sec->IsVirtual)
+ continue;
+
+ Sec->FileOffsetToData = RawPointer;
+ RawPointer += Sec->Size;
}
// TODO Add in Relocation storage to the RawPointer Calculation.