aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/MC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-30 16:33:32 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-30 16:33:32 +0000
commit51315c45ff5643a27f9c84b816db54ee870ba29b (patch)
tree1d87443fa0e53d3e6b315ce25787e64be0906bf7 /contrib/llvm/lib/MC
parent6dfd050075216be8538ae375a22d30db72916f7e (diff)
parenteb11fae6d08f479c0799db45860a98af528fa6e7 (diff)
Merge llvm trunk r338150, and resolve conflicts.
Notes
Notes: svn path=/projects/clang700-import/; revision=336916
Diffstat (limited to 'contrib/llvm/lib/MC')
-rw-r--r--contrib/llvm/lib/MC/ELFObjectWriter.cpp1014
-rw-r--r--contrib/llvm/lib/MC/MCAsmBackend.cpp57
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfo.cpp11
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp19
-rw-r--r--contrib/llvm/lib/MC/MCAsmMacro.cpp42
-rw-r--r--contrib/llvm/lib/MC/MCAsmStreamer.cpp329
-rw-r--r--contrib/llvm/lib/MC/MCAssembler.cpp270
-rw-r--r--contrib/llvm/lib/MC/MCCodeView.cpp17
-rw-r--r--contrib/llvm/lib/MC/MCContext.cpp69
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp10
-rw-r--r--contrib/llvm/lib/MC/MCDwarf.cpp265
-rw-r--r--contrib/llvm/lib/MC/MCELFStreamer.cpp105
-rw-r--r--contrib/llvm/lib/MC/MCExpr.cpp65
-rw-r--r--contrib/llvm/lib/MC/MCFragment.cpp44
-rw-r--r--contrib/llvm/lib/MC/MCInst.cpp19
-rw-r--r--contrib/llvm/lib/MC/MCInstrAnalysis.cpp9
-rw-r--r--contrib/llvm/lib/MC/MCLabel.cpp1
-rw-r--r--contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp2
-rw-r--r--contrib/llvm/lib/MC/MCMachOStreamer.cpp30
-rw-r--r--contrib/llvm/lib/MC/MCNullStreamer.cpp3
-rw-r--r--contrib/llvm/lib/MC/MCObjectFileInfo.cpp91
-rw-r--r--contrib/llvm/lib/MC/MCObjectStreamer.cpp133
-rw-r--r--contrib/llvm/lib/MC/MCParser/AsmParser.cpp367
-rw-r--r--contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp52
-rw-r--r--contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp12
-rw-r--r--contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp100
-rw-r--r--contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp93
-rw-r--r--contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp2
-rw-r--r--contrib/llvm/lib/MC/MCSchedule.cpp118
-rw-r--r--contrib/llvm/lib/MC/MCSection.cpp1
-rw-r--r--contrib/llvm/lib/MC/MCSectionCOFF.cpp25
-rw-r--r--contrib/llvm/lib/MC/MCSectionELF.cpp4
-rw-r--r--contrib/llvm/lib/MC/MCStreamer.cpp93
-rw-r--r--contrib/llvm/lib/MC/MCSubtargetInfo.cpp5
-rw-r--r--contrib/llvm/lib/MC/MCSymbol.cpp1
-rw-r--r--contrib/llvm/lib/MC/MCValue.cpp1
-rw-r--r--contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp3
-rw-r--r--contrib/llvm/lib/MC/MCWasmStreamer.cpp36
-rw-r--r--contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp40
-rw-r--r--contrib/llvm/lib/MC/MachObjectWriter.cpp275
-rw-r--r--contrib/llvm/lib/MC/StringTableBuilder.cpp2
-rw-r--r--contrib/llvm/lib/MC/SubtargetFeature.cpp1
-rw-r--r--contrib/llvm/lib/MC/WasmObjectWriter.cpp1201
-rw-r--r--contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp195
44 files changed, 3389 insertions, 1843 deletions
diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp
index 989d4bb4eb9c..db531f75c87c 100644
--- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp
@@ -43,6 +43,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/StringSaver.h"
@@ -68,9 +69,14 @@ namespace {
using SectionIndexMapTy = DenseMap<const MCSectionELF *, uint32_t>;
class ELFObjectWriter;
+struct ELFWriter;
+
+bool isDwoSection(const MCSectionELF &Sec) {
+ return Sec.getSectionName().endswith(".dwo");
+}
class SymbolTableWriter {
- ELFObjectWriter &EWriter;
+ ELFWriter &EWriter;
bool Is64Bit;
// indexes we are going to write to .symtab_shndx.
@@ -84,7 +90,7 @@ class SymbolTableWriter {
template <typename T> void write(T Value);
public:
- SymbolTableWriter(ELFObjectWriter &EWriter, bool Is64Bit);
+ SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit);
void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size,
uint8_t other, uint32_t shndx, bool Reserved);
@@ -92,7 +98,16 @@ public:
ArrayRef<uint32_t> getShndxIndexes() const { return ShndxIndexes; }
};
-class ELFObjectWriter : public MCObjectWriter {
+struct ELFWriter {
+ ELFObjectWriter &OWriter;
+ support::endian::Writer W;
+
+ enum DwoMode {
+ AllSections,
+ NonDwoOnly,
+ DwoOnly,
+ } Mode;
+
static uint64_t SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout);
static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol,
bool Used, bool Renamed);
@@ -117,13 +132,6 @@ class ELFObjectWriter : public MCObjectWriter {
}
};
- /// The target specific ELF writer instance.
- std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter;
-
- DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames;
-
- DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> Relocations;
-
/// @}
/// @name Symbol Table Data
/// @{
@@ -144,14 +152,8 @@ class ELFObjectWriter : public MCObjectWriter {
unsigned addToSectionTable(const MCSectionELF *Sec);
// TargetObjectWriter wrappers.
- bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
- bool hasRelocationAddend() const {
- return TargetObjectWriter->hasRelocationAddend();
- }
- unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
- const MCFixup &Fixup, bool IsPCRel) const {
- return TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel);
- }
+ bool is64Bit() const;
+ bool hasRelocationAddend() const;
void align(unsigned Alignment);
@@ -160,33 +162,20 @@ class ELFObjectWriter : public MCObjectWriter {
bool ZLibStyle, unsigned Alignment);
public:
- ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
- raw_pwrite_stream &OS, bool IsLittleEndian)
- : MCObjectWriter(OS, IsLittleEndian),
- TargetObjectWriter(std::move(MOTW)) {}
-
- ~ELFObjectWriter() override = default;
+ ELFWriter(ELFObjectWriter &OWriter, raw_pwrite_stream &OS,
+ bool IsLittleEndian, DwoMode Mode)
+ : OWriter(OWriter),
+ W(OS, IsLittleEndian ? support::little : support::big), Mode(Mode) {}
- void reset() override {
- Renames.clear();
- Relocations.clear();
- StrTabBuilder.clear();
- SectionTable.clear();
- MCObjectWriter::reset();
- }
-
- void WriteWord(uint64_t W) {
+ void WriteWord(uint64_t Word) {
if (is64Bit())
- write64(W);
+ W.write<uint64_t>(Word);
else
- write32(W);
+ W.write<uint32_t>(Word);
}
template <typename T> void write(T Val) {
- if (IsLittleEndian)
- support::endian::Writer<support::little>(getStream()).write(Val);
- else
- support::endian::Writer<support::big>(getStream()).write(Val);
+ W.write(Val);
}
void writeHeader(const MCAssembler &Asm);
@@ -198,15 +187,6 @@ public:
using SectionOffsetsTy =
std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>>;
- bool shouldRelocateWithSymbol(const MCAssembler &Asm,
- const MCSymbolRefExpr *RefA,
- const MCSymbol *Sym, uint64_t C,
- unsigned Type) const;
-
- void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCFragment *Fragment, const MCFixup &Fixup,
- MCValue Target, uint64_t &FixedValue) override;
-
// Map from a signature symbol to the group section index
using RevGroupMapTy = DenseMap<const MCSymbol *, unsigned>;
@@ -220,14 +200,13 @@ public:
const RevGroupMapTy &RevGroupMap,
SectionOffsetsTy &SectionOffsets);
+ void writeAddrsigSection();
+
MCSectionELF *createRelocationSection(MCContext &Ctx,
const MCSectionELF &Sec);
const MCSectionELF *createStringTable(MCContext &Ctx);
- void executePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout) override;
-
void writeSectionHeader(const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap,
const SectionOffsetsTy &SectionOffsets);
@@ -242,26 +221,126 @@ public:
void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec);
- using MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl;
+ uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout);
+ void writeSection(const SectionIndexMapTy &SectionIndexMap,
+ uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size,
+ const MCSectionELF &Section);
+};
+
+class ELFObjectWriter : public MCObjectWriter {
+ /// The target specific ELF writer instance.
+ std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter;
+
+ DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> Relocations;
+
+ DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames;
+
+ bool EmitAddrsigSection = false;
+ std::vector<const MCSymbol *> AddrsigSyms;
+
+ bool hasRelocationAddend() const;
+
+ bool shouldRelocateWithSymbol(const MCAssembler &Asm,
+ const MCSymbolRefExpr *RefA,
+ const MCSymbolELF *Sym, uint64_t C,
+ unsigned Type) const;
+
+public:
+ ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW)
+ : TargetObjectWriter(std::move(MOTW)) {}
+
+ void reset() override {
+ Relocations.clear();
+ Renames.clear();
+ MCObjectWriter::reset();
+ }
+
bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
const MCSymbol &SymA,
const MCFragment &FB, bool InSet,
bool IsPCRel) const override;
- void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
- void writeSection(const SectionIndexMapTy &SectionIndexMap,
- uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size,
- const MCSectionELF &Section);
+ virtual bool checkRelocation(MCContext &Ctx, SMLoc Loc,
+ const MCSectionELF *From,
+ const MCSectionELF *To) {
+ return true;
+ }
+
+ void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
+ const MCFragment *Fragment, const MCFixup &Fixup,
+ MCValue Target, uint64_t &FixedValue) override;
+
+ void executePostLayoutBinding(MCAssembler &Asm,
+ const MCAsmLayout &Layout) override;
+
+ void emitAddrsigSection() override { EmitAddrsigSection = true; }
+ void addAddrsigSymbol(const MCSymbol *Sym) override {
+ AddrsigSyms.push_back(Sym);
+ }
+
+ friend struct ELFWriter;
+};
+
+class ELFSingleObjectWriter : public ELFObjectWriter {
+ raw_pwrite_stream &OS;
+ bool IsLittleEndian;
+
+public:
+ ELFSingleObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS, bool IsLittleEndian)
+ : ELFObjectWriter(std::move(MOTW)), OS(OS),
+ IsLittleEndian(IsLittleEndian) {}
+
+ uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override {
+ return ELFWriter(*this, OS, IsLittleEndian, ELFWriter::AllSections)
+ .writeObject(Asm, Layout);
+ }
+
+ friend struct ELFWriter;
+};
+
+class ELFDwoObjectWriter : public ELFObjectWriter {
+ raw_pwrite_stream &OS, &DwoOS;
+ bool IsLittleEndian;
+
+public:
+ ELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS,
+ bool IsLittleEndian)
+ : ELFObjectWriter(std::move(MOTW)), OS(OS), DwoOS(DwoOS),
+ IsLittleEndian(IsLittleEndian) {}
+
+ virtual bool checkRelocation(MCContext &Ctx, SMLoc Loc,
+ const MCSectionELF *From,
+ const MCSectionELF *To) override {
+ if (isDwoSection(*From)) {
+ Ctx.reportError(Loc, "A dwo section may not contain relocations");
+ return false;
+ }
+ if (To && isDwoSection(*To)) {
+ Ctx.reportError(Loc, "A relocation may not refer to a dwo section");
+ return false;
+ }
+ return true;
+ }
+
+ uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override {
+ uint64_t Size = ELFWriter(*this, OS, IsLittleEndian, ELFWriter::NonDwoOnly)
+ .writeObject(Asm, Layout);
+ Size += ELFWriter(*this, DwoOS, IsLittleEndian, ELFWriter::DwoOnly)
+ .writeObject(Asm, Layout);
+ return Size;
+ }
};
} // end anonymous namespace
-void ELFObjectWriter::align(unsigned Alignment) {
- uint64_t Padding = OffsetToAlignment(getStream().tell(), Alignment);
- WriteZeros(Padding);
+void ELFWriter::align(unsigned Alignment) {
+ uint64_t Padding = OffsetToAlignment(W.OS.tell(), Alignment);
+ W.OS.write_zeros(Padding);
}
-unsigned ELFObjectWriter::addToSectionTable(const MCSectionELF *Sec) {
+unsigned ELFWriter::addToSectionTable(const MCSectionELF *Sec) {
SectionTable.push_back(Sec);
StrTabBuilder.add(Sec->getSectionName());
return SectionTable.size();
@@ -278,7 +357,7 @@ template <typename T> void SymbolTableWriter::write(T Value) {
EWriter.write(Value);
}
-SymbolTableWriter::SymbolTableWriter(ELFObjectWriter &EWriter, bool Is64Bit)
+SymbolTableWriter::SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit)
: EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {}
void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
@@ -317,8 +396,16 @@ void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
++NumWritten;
}
+bool ELFWriter::is64Bit() const {
+ return OWriter.TargetObjectWriter->is64Bit();
+}
+
+bool ELFWriter::hasRelocationAddend() const {
+ return OWriter.hasRelocationAddend();
+}
+
// Emit the ELF header.
-void ELFObjectWriter::writeHeader(const MCAssembler &Asm) {
+void ELFWriter::writeHeader(const MCAssembler &Asm) {
// ELF Header
// ----------
//
@@ -327,51 +414,54 @@ void ELFObjectWriter::writeHeader(const MCAssembler &Asm) {
// emitWord method behaves differently for ELF32 and ELF64, writing
// 4 bytes in the former and 8 in the latter.
- writeBytes(ELF::ElfMagic); // e_ident[EI_MAG0] to e_ident[EI_MAG3]
+ W.OS << ELF::ElfMagic; // e_ident[EI_MAG0] to e_ident[EI_MAG3]
- write8(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
+ W.OS << char(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
// e_ident[EI_DATA]
- write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
+ W.OS << char(W.Endian == support::little ? ELF::ELFDATA2LSB
+ : ELF::ELFDATA2MSB);
- write8(ELF::EV_CURRENT); // e_ident[EI_VERSION]
+ W.OS << char(ELF::EV_CURRENT); // e_ident[EI_VERSION]
// e_ident[EI_OSABI]
- write8(TargetObjectWriter->getOSABI());
- write8(0); // e_ident[EI_ABIVERSION]
+ W.OS << char(OWriter.TargetObjectWriter->getOSABI());
+ W.OS << char(0); // e_ident[EI_ABIVERSION]
- WriteZeros(ELF::EI_NIDENT - ELF::EI_PAD);
+ W.OS.write_zeros(ELF::EI_NIDENT - ELF::EI_PAD);
- write16(ELF::ET_REL); // e_type
+ W.write<uint16_t>(ELF::ET_REL); // e_type
- write16(TargetObjectWriter->getEMachine()); // e_machine = target
+ W.write<uint16_t>(OWriter.TargetObjectWriter->getEMachine()); // e_machine = target
- write32(ELF::EV_CURRENT); // e_version
+ W.write<uint32_t>(ELF::EV_CURRENT); // e_version
WriteWord(0); // e_entry, no entry point in .o file
WriteWord(0); // e_phoff, no program header for .o
WriteWord(0); // e_shoff = sec hdr table off in bytes
// e_flags = whatever the target wants
- write32(Asm.getELFHeaderEFlags());
+ W.write<uint32_t>(Asm.getELFHeaderEFlags());
// e_ehsize = ELF header size
- write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr));
+ W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Ehdr)
+ : sizeof(ELF::Elf32_Ehdr));
- write16(0); // e_phentsize = prog header entry size
- write16(0); // e_phnum = # prog header entries = 0
+ W.write<uint16_t>(0); // e_phentsize = prog header entry size
+ W.write<uint16_t>(0); // e_phnum = # prog header entries = 0
// e_shentsize = Section header entry size
- write16(is64Bit() ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr));
+ W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Shdr)
+ : sizeof(ELF::Elf32_Shdr));
// e_shnum = # of section header ents
- write16(0);
+ W.write<uint16_t>(0);
// e_shstrndx = Section # of '.shstrtab'
assert(StringTableIndex < ELF::SHN_LORESERVE);
- write16(StringTableIndex);
+ W.write<uint16_t>(StringTableIndex);
}
-uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym,
- const MCAsmLayout &Layout) {
+uint64_t ELFWriter::SymbolValue(const MCSymbol &Sym,
+ const MCAsmLayout &Layout) {
if (Sym.isCommon() && Sym.isExternal())
return Sym.getCommonAlignment();
@@ -385,45 +475,6 @@ uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym,
return Res;
}
-void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- // The presence of symbol versions causes undefined symbols and
- // versions declared with @@@ to be renamed.
- for (const std::pair<StringRef, const MCSymbol *> &P : Asm.Symvers) {
- StringRef AliasName = P.first;
- const auto &Symbol = cast<MCSymbolELF>(*P.second);
- size_t Pos = AliasName.find('@');
- assert(Pos != StringRef::npos);
-
- StringRef Prefix = AliasName.substr(0, Pos);
- StringRef Rest = AliasName.substr(Pos);
- StringRef Tail = Rest;
- if (Rest.startswith("@@@"))
- Tail = Rest.substr(Symbol.isUndefined() ? 2 : 1);
-
- auto *Alias =
- cast<MCSymbolELF>(Asm.getContext().getOrCreateSymbol(Prefix + Tail));
- Asm.registerSymbol(*Alias);
- const MCExpr *Value = MCSymbolRefExpr::create(&Symbol, Asm.getContext());
- Alias->setVariableValue(Value);
-
- // Aliases defined with .symvar copy the binding from the symbol they alias.
- // This is the first place we are able to copy this information.
- Alias->setExternal(Symbol.isExternal());
- Alias->setBinding(Symbol.getBinding());
-
- if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
- continue;
-
- // FIXME: produce a better error message.
- if (Symbol.isUndefined() && Rest.startswith("@@") &&
- !Rest.startswith("@@@"))
- report_fatal_error("A @@ version cannot be undefined");
-
- Renames.insert(std::make_pair(&Symbol, Alias));
- }
-}
-
static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) {
uint8_t Type = newType;
@@ -459,9 +510,8 @@ static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) {
return Type;
}
-void ELFObjectWriter::writeSymbol(SymbolTableWriter &Writer,
- uint32_t StringIndex, ELFSymbolData &MSD,
- const MCAsmLayout &Layout) {
+void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
+ ELFSymbolData &MSD, const MCAsmLayout &Layout) {
const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol);
const MCSymbolELF *Base =
cast_or_null<MCSymbolELF>(Layout.getBaseSymbol(Symbol));
@@ -502,108 +552,6 @@ void ELFObjectWriter::writeSymbol(SymbolTableWriter &Writer,
IsReserved);
}
-// It is always valid to create a relocation with a symbol. It is preferable
-// to use a relocation with a section if that is possible. Using the section
-// allows us to omit some local symbols from the symbol table.
-bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
- const MCSymbolRefExpr *RefA,
- const MCSymbol *S, uint64_t C,
- unsigned Type) const {
- const auto *Sym = cast_or_null<MCSymbolELF>(S);
- // A PCRel relocation to an absolute value has no symbol (or section). We
- // represent that with a relocation to a null section.
- if (!RefA)
- return false;
-
- MCSymbolRefExpr::VariantKind Kind = RefA->getKind();
- switch (Kind) {
- default:
- break;
- // The .odp creation emits a relocation against the symbol ".TOC." which
- // create a R_PPC64_TOC relocation. However the relocation symbol name
- // in final object creation should be NULL, since the symbol does not
- // really exist, it is just the reference to TOC base for the current
- // object file. Since the symbol is undefined, returning false results
- // in a relocation with a null section which is the desired result.
- case MCSymbolRefExpr::VK_PPC_TOCBASE:
- return false;
-
- // These VariantKind cause the relocation to refer to something other than
- // the symbol itself, like a linker generated table. Since the address of
- // symbol is not relevant, we cannot replace the symbol with the
- // section and patch the difference in the addend.
- case MCSymbolRefExpr::VK_GOT:
- case MCSymbolRefExpr::VK_PLT:
- case MCSymbolRefExpr::VK_GOTPCREL:
- case MCSymbolRefExpr::VK_PPC_GOT_LO:
- case MCSymbolRefExpr::VK_PPC_GOT_HI:
- case MCSymbolRefExpr::VK_PPC_GOT_HA:
- return true;
- }
-
- // An undefined symbol is not in any section, so the relocation has to point
- // to the symbol itself.
- assert(Sym && "Expected a symbol");
- if (Sym->isUndefined())
- return true;
-
- unsigned Binding = Sym->getBinding();
- switch(Binding) {
- default:
- llvm_unreachable("Invalid Binding");
- case ELF::STB_LOCAL:
- break;
- case ELF::STB_WEAK:
- // If the symbol is weak, it might be overridden by a symbol in another
- // file. The relocation has to point to the symbol so that the linker
- // can update it.
- return true;
- case ELF::STB_GLOBAL:
- // Global ELF symbols can be preempted by the dynamic linker. The relocation
- // has to point to the symbol for a reason analogous to the STB_WEAK case.
- return true;
- }
-
- // If a relocation points to a mergeable section, we have to be careful.
- // If the offset is zero, a relocation with the section will encode the
- // same information. With a non-zero offset, the situation is different.
- // For example, a relocation can point 42 bytes past the end of a string.
- // If we change such a relocation to use the section, the linker would think
- // that it pointed to another string and subtracting 42 at runtime will
- // produce the wrong value.
- if (Sym->isInSection()) {
- auto &Sec = cast<MCSectionELF>(Sym->getSection());
- unsigned Flags = Sec.getFlags();
- if (Flags & ELF::SHF_MERGE) {
- if (C != 0)
- return true;
-
- // It looks like gold has a bug (http://sourceware.org/PR16794) and can
- // only handle section relocations to mergeable sections if using RELA.
- if (!hasRelocationAddend())
- return true;
- }
-
- // Most TLS relocations use a got, so they need the symbol. Even those that
- // are just an offset (@tpoff), require a symbol in gold versions before
- // 5efeedf61e4fe720fd3e9a08e6c91c10abb66d42 (2014-09-26) which fixed
- // http://sourceware.org/PR16773.
- if (Flags & ELF::SHF_TLS)
- return true;
- }
-
- // If the symbol is a thumb function the final relocation must set the lowest
- // bit. With a symbol that is done by just having the symbol have that bit
- // set, so we would lose the bit if we relocated with the section.
- // FIXME: We could use the section but add the bit to the relocation value.
- if (Asm.isThumbFunc(Sym))
- return true;
-
- if (TargetObjectWriter->needsRelocateWithSymbol(*Sym, Type))
- return true;
- return false;
-}
-
// 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.
@@ -624,118 +572,8 @@ static bool isWeak(const MCSymbolELF &Sym) {
}
}
-void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup, MCValue Target,
- uint64_t &FixedValue) {
- MCAsmBackend &Backend = Asm.getBackend();
- bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
- MCFixupKindInfo::FKF_IsPCRel;
- const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent());
- uint64_t C = Target.getConstant();
- uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
- MCContext &Ctx = Asm.getContext();
-
- if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
- // Let A, B and C being the components of Target and R be the location of
- // the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
- // If it is pcrel, we want to compute (A - B + C - R).
-
- // In general, ELF has no relocations for -B. It can only represent (A + C)
- // or (A + C - R). If B = R + K and the relocation is not pcrel, we can
- // replace B to implement it: (A - R - K + C)
- if (IsPCRel) {
- Ctx.reportError(
- Fixup.getLoc(),
- "No relocation available to represent this relative expression");
- return;
- }
-
- const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol());
-
- if (SymB.isUndefined()) {
- Ctx.reportError(Fixup.getLoc(),
- Twine("symbol '") + SymB.getName() +
- "' can not be undefined in a subtraction expression");
- return;
- }
-
- assert(!SymB.isAbsolute() && "Should have been folded");
- const MCSection &SecB = SymB.getSection();
- if (&SecB != &FixupSection) {
- Ctx.reportError(Fixup.getLoc(),
- "Cannot represent a difference across sections");
- return;
- }
-
- uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
- uint64_t K = SymBOffset - FixupOffset;
- IsPCRel = true;
- C -= K;
- }
-
- // We either rejected the fixup or folded B into C at this point.
- const MCSymbolRefExpr *RefA = Target.getSymA();
- const auto *SymA = RefA ? cast<MCSymbolELF>(&RefA->getSymbol()) : nullptr;
-
- bool ViaWeakRef = false;
- if (SymA && SymA->isVariable()) {
- const MCExpr *Expr = SymA->getVariableValue();
- if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
- if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) {
- SymA = cast<MCSymbolELF>(&Inner->getSymbol());
- ViaWeakRef = true;
- }
- }
- }
-
- unsigned Type = getRelocType(Ctx, Target, Fixup, IsPCRel);
- uint64_t OriginalC = C;
- bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type);
- if (!RelocateWithSymbol && SymA && !SymA->isUndefined())
- C += Layout.getSymbolOffset(*SymA);
-
- uint64_t Addend = 0;
- if (hasRelocationAddend()) {
- Addend = C;
- C = 0;
- }
-
- FixedValue = C;
-
- if (!RelocateWithSymbol) {
- const MCSection *SecA =
- (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr;
- auto *ELFSec = cast_or_null<MCSectionELF>(SecA);
- const auto *SectionSymbol =
- ELFSec ? cast<MCSymbolELF>(ELFSec->getBeginSymbol()) : nullptr;
- if (SectionSymbol)
- SectionSymbol->setUsedInReloc();
- ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend, SymA,
- OriginalC);
- Relocations[&FixupSection].push_back(Rec);
- return;
- }
-
- const auto *RenamedSymA = SymA;
- if (SymA) {
- if (const MCSymbolELF *R = Renames.lookup(SymA))
- RenamedSymA = R;
-
- if (ViaWeakRef)
- RenamedSymA->setIsWeakrefUsedInReloc();
- else
- RenamedSymA->setUsedInReloc();
- }
- ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend, SymA,
- OriginalC);
- Relocations[&FixupSection].push_back(Rec);
-}
-
-bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout,
- const MCSymbolELF &Symbol, bool Used,
- bool Renamed) {
+bool ELFWriter::isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol,
+ bool Used, bool Renamed) {
if (Symbol.isVariable()) {
const MCExpr *Expr = Symbol.getVariableValue();
if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) {
@@ -768,7 +606,7 @@ bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout,
return true;
}
-void ELFObjectWriter::computeSymbolTable(
+void ELFWriter::computeSymbolTable(
MCAssembler &Asm, const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap,
SectionOffsetsTy &SectionOffsets) {
@@ -783,7 +621,7 @@ void ELFObjectWriter::computeSymbolTable(
SymbolTableIndex = addToSectionTable(SymtabSection);
align(SymtabSection->getAlignment());
- uint64_t SecStart = getStream().tell();
+ uint64_t SecStart = W.OS.tell();
// The first entry is the undefined symbol entry.
Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
@@ -800,7 +638,7 @@ void ELFObjectWriter::computeSymbolTable(
bool isSignature = Symbol.isSignature();
if (!isInSymtab(Layout, Symbol, Used || WeakrefUsed || isSignature,
- Renames.count(&Symbol)))
+ OWriter.Renames.count(&Symbol)))
continue;
if (Symbol.isTemporary() && Symbol.isUndefined()) {
@@ -830,6 +668,8 @@ void ELFObjectWriter::computeSymbolTable(
} else {
const MCSectionELF &Section =
static_cast<const MCSectionELF &>(Symbol.getSection());
+ if (Mode == NonDwoOnly && isDwoSection(Section))
+ continue;
MSD.SectionIndex = SectionIndexMap.lookup(&Section);
assert(MSD.SectionIndex && "Invalid section index!");
if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
@@ -899,7 +739,7 @@ void ELFObjectWriter::computeSymbolTable(
assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL);
}
- uint64_t SecEnd = getStream().tell();
+ uint64_t SecEnd = W.OS.tell();
SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd);
ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
@@ -909,19 +749,23 @@ void ELFObjectWriter::computeSymbolTable(
}
assert(SymtabShndxSectionIndex != 0);
- SecStart = getStream().tell();
+ SecStart = W.OS.tell();
const MCSectionELF *SymtabShndxSection =
SectionTable[SymtabShndxSectionIndex - 1];
for (uint32_t Index : ShndxIndexes)
write(Index);
- SecEnd = getStream().tell();
+ SecEnd = W.OS.tell();
SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd);
}
-MCSectionELF *
-ELFObjectWriter::createRelocationSection(MCContext &Ctx,
- const MCSectionELF &Sec) {
- if (Relocations[&Sec].empty())
+void ELFWriter::writeAddrsigSection() {
+ for (const MCSymbol *Sym : OWriter.AddrsigSyms)
+ encodeULEB128(Sym->getIndex(), W.OS);
+}
+
+MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx,
+ const MCSectionELF &Sec) {
+ if (OWriter.Relocations[&Sec].empty())
return nullptr;
const StringRef SectionName = Sec.getSectionName();
@@ -946,7 +790,7 @@ ELFObjectWriter::createRelocationSection(MCContext &Ctx,
}
// Include the debug info compression header.
-bool ELFObjectWriter::maybeWriteCompression(
+bool ELFWriter::maybeWriteCompression(
uint64_t Size, SmallVectorImpl<char> &CompressedContents, bool ZLibStyle,
unsigned Alignment) {
if (ZLibStyle) {
@@ -975,13 +819,13 @@ bool ELFObjectWriter::maybeWriteCompression(
const StringRef Magic = "ZLIB";
if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size())
return false;
- write(ArrayRef<char>(Magic.begin(), Magic.size()));
- writeBE64(Size);
+ W.OS << Magic;
+ support::endian::write(W.OS, Size, support::big);
return true;
}
-void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
- const MCAsmLayout &Layout) {
+void ELFWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
+ const MCAsmLayout &Layout) {
MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
StringRef SectionName = Section.getSectionName();
@@ -995,7 +839,7 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
MAI->compressDebugSections() != DebugCompressionType::None;
if (!CompressionEnabled || !SectionName.startswith(".debug_") ||
SectionName == ".debug_frame") {
- Asm.writeSectionData(&Section, Layout);
+ Asm.writeSectionData(W.OS, &Section, Layout);
return;
}
@@ -1005,24 +849,21 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
SmallVector<char, 128> UncompressedData;
raw_svector_ostream VecOS(UncompressedData);
- raw_pwrite_stream &OldStream = getStream();
- setStream(VecOS);
- Asm.writeSectionData(&Section, Layout);
- setStream(OldStream);
+ Asm.writeSectionData(VecOS, &Section, Layout);
SmallVector<char, 128> CompressedContents;
if (Error E = zlib::compress(
StringRef(UncompressedData.data(), UncompressedData.size()),
CompressedContents)) {
consumeError(std::move(E));
- getStream() << UncompressedData;
+ W.OS << UncompressedData;
return;
}
bool ZlibStyle = MAI->compressDebugSections() == DebugCompressionType::Z;
if (!maybeWriteCompression(UncompressedData.size(), CompressedContents,
ZlibStyle, Sec.getAlignment())) {
- getStream() << UncompressedData;
+ W.OS << UncompressedData;
return;
}
@@ -1032,30 +873,28 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
else
// Add "z" prefix to section name. This is zlib-gnu style.
MC.renameELFSection(&Section, (".z" + SectionName.drop_front(1)).str());
- getStream() << CompressedContents;
+ W.OS << CompressedContents;
}
-void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type,
- uint64_t Flags, uint64_t Address,
- uint64_t Offset, uint64_t Size,
- uint32_t Link, uint32_t Info,
- uint64_t Alignment,
- uint64_t EntrySize) {
- write32(Name); // sh_name: index into string table
- write32(Type); // sh_type
+void ELFWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
+ uint64_t Address, uint64_t Offset,
+ uint64_t Size, uint32_t Link, uint32_t Info,
+ uint64_t Alignment, uint64_t EntrySize) {
+ W.write<uint32_t>(Name); // sh_name: index into string table
+ W.write<uint32_t>(Type); // sh_type
WriteWord(Flags); // sh_flags
WriteWord(Address); // sh_addr
WriteWord(Offset); // sh_offset
WriteWord(Size); // sh_size
- write32(Link); // sh_link
- write32(Info); // sh_info
+ W.write<uint32_t>(Link); // sh_link
+ W.write<uint32_t>(Info); // sh_info
WriteWord(Alignment); // sh_addralign
WriteWord(EntrySize); // sh_entsize
}
-void ELFObjectWriter::writeRelocations(const MCAssembler &Asm,
+void ELFWriter::writeRelocations(const MCAssembler &Asm,
const MCSectionELF &Sec) {
- std::vector<ELFRelocationEntry> &Relocs = Relocations[&Sec];
+ std::vector<ELFRelocationEntry> &Relocs = OWriter.Relocations[&Sec];
// We record relocations by pushing to the end of a vector. Reverse the vector
// to get the relocations in the order they were created.
@@ -1064,7 +903,7 @@ void ELFObjectWriter::writeRelocations(const MCAssembler &Asm,
std::reverse(Relocs.begin(), Relocs.end());
// Sort the relocation entries. MIPS needs this.
- TargetObjectWriter->sortRelocs(Asm, Relocs);
+ OWriter.TargetObjectWriter->sortRelocs(Asm, Relocs);
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
const ELFRelocationEntry &Entry = Relocs[e - i - 1];
@@ -1072,13 +911,13 @@ void ELFObjectWriter::writeRelocations(const MCAssembler &Asm,
if (is64Bit()) {
write(Entry.Offset);
- if (TargetObjectWriter->getEMachine() == ELF::EM_MIPS) {
+ if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) {
write(uint32_t(Index));
- write(TargetObjectWriter->getRSsym(Entry.Type));
- write(TargetObjectWriter->getRType3(Entry.Type));
- write(TargetObjectWriter->getRType2(Entry.Type));
- write(TargetObjectWriter->getRType(Entry.Type));
+ write(OWriter.TargetObjectWriter->getRSsym(Entry.Type));
+ write(OWriter.TargetObjectWriter->getRType3(Entry.Type));
+ write(OWriter.TargetObjectWriter->getRType2(Entry.Type));
+ write(OWriter.TargetObjectWriter->getRType(Entry.Type));
} else {
struct ELF::Elf64_Rela ERE64;
ERE64.setSymbolAndType(Index, Entry.Type);
@@ -1096,15 +935,17 @@ void ELFObjectWriter::writeRelocations(const MCAssembler &Asm,
if (hasRelocationAddend())
write(uint32_t(Entry.Addend));
- if (TargetObjectWriter->getEMachine() == ELF::EM_MIPS) {
- if (uint32_t RType = TargetObjectWriter->getRType2(Entry.Type)) {
+ if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) {
+ if (uint32_t RType =
+ OWriter.TargetObjectWriter->getRType2(Entry.Type)) {
write(uint32_t(Entry.Offset));
ERE32.setSymbolAndType(0, RType);
write(ERE32.r_info);
write(uint32_t(0));
}
- if (uint32_t RType = TargetObjectWriter->getRType3(Entry.Type)) {
+ if (uint32_t RType =
+ OWriter.TargetObjectWriter->getRType3(Entry.Type)) {
write(uint32_t(Entry.Offset));
ERE32.setSymbolAndType(0, RType);
@@ -1116,15 +957,15 @@ void ELFObjectWriter::writeRelocations(const MCAssembler &Asm,
}
}
-const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) {
+const MCSectionELF *ELFWriter::createStringTable(MCContext &Ctx) {
const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1];
- StrTabBuilder.write(getStream());
+ StrTabBuilder.write(W.OS);
return StrtabSection;
}
-void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
- uint32_t GroupSymbolIndex, uint64_t Offset,
- uint64_t Size, const MCSectionELF &Section) {
+void ELFWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
+ uint32_t GroupSymbolIndex, uint64_t Offset,
+ uint64_t Size, const MCSectionELF &Section) {
uint64_t sh_link = 0;
uint64_t sh_info = 0;
@@ -1146,12 +987,13 @@ void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
}
case ELF::SHT_SYMTAB:
- case ELF::SHT_DYNSYM:
sh_link = StringTableIndex;
sh_info = LastLocalSymbolIndex;
break;
case ELF::SHT_SYMTAB_SHNDX:
+ case ELF::SHT_LLVM_CALL_GRAPH_PROFILE:
+ case ELF::SHT_LLVM_ADDRSIG:
sh_link = SymbolTableIndex;
break;
@@ -1173,7 +1015,7 @@ void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
Section.getEntrySize());
}
-void ELFObjectWriter::writeSectionHeader(
+void ELFWriter::writeSectionHeader(
const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap,
const SectionOffsetsTy &SectionOffsets) {
const unsigned NumSections = SectionTable.size();
@@ -1204,8 +1046,9 @@ void ELFObjectWriter::writeSectionHeader(
}
}
-void ELFObjectWriter::writeObject(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
+uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
+ uint64_t StartOffset = W.OS.tell();
+
MCContext &Ctx = Asm.getContext();
MCSectionELF *StrtabSection =
Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
@@ -1225,16 +1068,20 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
std::vector<MCSectionELF *> Relocations;
for (MCSection &Sec : Asm) {
MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
+ if (Mode == NonDwoOnly && isDwoSection(Section))
+ continue;
+ if (Mode == DwoOnly && !isDwoSection(Section))
+ continue;
align(Section.getAlignment());
// Remember the offset into the file for this section.
- uint64_t SecStart = getStream().tell();
+ uint64_t SecStart = W.OS.tell();
const MCSymbolELF *SignatureSymbol = Section.getGroup();
writeSectionData(Asm, Section, Layout);
- uint64_t SecEnd = getStream().tell();
+ uint64_t SecEnd = W.OS.tell();
SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd);
MCSectionELF *RelSection = createRelocationSection(Ctx, Section);
@@ -1262,11 +1109,19 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
}
}
+ MCSectionELF *CGProfileSection = nullptr;
+ if (!Asm.CGProfile.empty()) {
+ CGProfileSection = Ctx.getELFSection(".llvm.call-graph-profile",
+ ELF::SHT_LLVM_CALL_GRAPH_PROFILE,
+ ELF::SHF_EXCLUDE, 16, "");
+ SectionIndexMap[CGProfileSection] = addToSectionTable(CGProfileSection);
+ }
+
for (MCSectionELF *Group : Groups) {
align(Group->getAlignment());
// Remember the offset into the file for this section.
- uint64_t SecStart = getStream().tell();
+ uint64_t SecStart = W.OS.tell();
const MCSymbol *SignatureSymbol = Group->getGroup();
assert(SignatureSymbol);
@@ -1276,65 +1131,364 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
write(SecIndex);
}
- uint64_t SecEnd = getStream().tell();
+ uint64_t SecEnd = W.OS.tell();
SectionOffsets[Group] = std::make_pair(SecStart, SecEnd);
}
- // Compute symbol table information.
- computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, SectionOffsets);
+ if (Mode == DwoOnly) {
+ // dwo files don't have symbol tables or relocations, but they do have
+ // string tables.
+ StrTabBuilder.finalize();
+ } else {
+ MCSectionELF *AddrsigSection;
+ if (OWriter.EmitAddrsigSection) {
+ AddrsigSection = Ctx.getELFSection(".llvm_addrsig", ELF::SHT_LLVM_ADDRSIG,
+ ELF::SHF_EXCLUDE);
+ addToSectionTable(AddrsigSection);
+ }
+
+ // Compute symbol table information.
+ computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap,
+ SectionOffsets);
- for (MCSectionELF *RelSection : Relocations) {
- align(RelSection->getAlignment());
+ for (MCSectionELF *RelSection : Relocations) {
+ align(RelSection->getAlignment());
- // Remember the offset into the file for this section.
- uint64_t SecStart = getStream().tell();
+ // Remember the offset into the file for this section.
+ uint64_t SecStart = W.OS.tell();
- writeRelocations(Asm,
- cast<MCSectionELF>(*RelSection->getAssociatedSection()));
+ writeRelocations(Asm,
+ cast<MCSectionELF>(*RelSection->getAssociatedSection()));
- uint64_t SecEnd = getStream().tell();
- SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
+ uint64_t SecEnd = W.OS.tell();
+ SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
+ }
+
+ if (OWriter.EmitAddrsigSection) {
+ uint64_t SecStart = W.OS.tell();
+ writeAddrsigSection();
+ uint64_t SecEnd = W.OS.tell();
+ SectionOffsets[AddrsigSection] = std::make_pair(SecStart, SecEnd);
+ }
+ }
+
+ if (CGProfileSection) {
+ uint64_t SecStart = W.OS.tell();
+ for (const MCAssembler::CGProfileEntry &CGPE : Asm.CGProfile) {
+ W.write<uint32_t>(CGPE.From->getSymbol().getIndex());
+ W.write<uint32_t>(CGPE.To->getSymbol().getIndex());
+ W.write<uint64_t>(CGPE.Count);
+ }
+ uint64_t SecEnd = W.OS.tell();
+ SectionOffsets[CGProfileSection] = std::make_pair(SecStart, SecEnd);
}
{
- uint64_t SecStart = getStream().tell();
+ uint64_t SecStart = W.OS.tell();
const MCSectionELF *Sec = createStringTable(Ctx);
- uint64_t SecEnd = getStream().tell();
+ uint64_t SecEnd = W.OS.tell();
SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd);
}
uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
align(NaturalAlignment);
- const uint64_t SectionHeaderOffset = getStream().tell();
+ const uint64_t SectionHeaderOffset = W.OS.tell();
// ... then the section header table ...
writeSectionHeader(Layout, SectionIndexMap, SectionOffsets);
- uint16_t NumSections = (SectionTable.size() + 1 >= ELF::SHN_LORESERVE)
- ? (uint16_t)ELF::SHN_UNDEF
- : SectionTable.size() + 1;
- if (sys::IsLittleEndianHost != IsLittleEndian)
- sys::swapByteOrder(NumSections);
+ uint16_t NumSections = support::endian::byte_swap<uint16_t>(
+ (SectionTable.size() + 1 >= ELF::SHN_LORESERVE) ? (uint16_t)ELF::SHN_UNDEF
+ : SectionTable.size() + 1,
+ W.Endian);
unsigned NumSectionsOffset;
+ auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);
if (is64Bit()) {
- uint64_t Val = SectionHeaderOffset;
- if (sys::IsLittleEndianHost != IsLittleEndian)
- sys::swapByteOrder(Val);
- getStream().pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
- offsetof(ELF::Elf64_Ehdr, e_shoff));
+ uint64_t Val =
+ support::endian::byte_swap<uint64_t>(SectionHeaderOffset, W.Endian);
+ Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
+ offsetof(ELF::Elf64_Ehdr, e_shoff));
NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum);
} else {
- uint32_t Val = SectionHeaderOffset;
- if (sys::IsLittleEndianHost != IsLittleEndian)
- sys::swapByteOrder(Val);
- getStream().pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
- offsetof(ELF::Elf32_Ehdr, e_shoff));
+ uint32_t Val =
+ support::endian::byte_swap<uint32_t>(SectionHeaderOffset, W.Endian);
+ Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
+ offsetof(ELF::Elf32_Ehdr, e_shoff));
NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum);
}
- getStream().pwrite(reinterpret_cast<char *>(&NumSections),
- sizeof(NumSections), NumSectionsOffset);
+ Stream.pwrite(reinterpret_cast<char *>(&NumSections), sizeof(NumSections),
+ NumSectionsOffset);
+
+ return W.OS.tell() - StartOffset;
+}
+
+bool ELFObjectWriter::hasRelocationAddend() const {
+ return TargetObjectWriter->hasRelocationAddend();
+}
+
+void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ // The presence of symbol versions causes undefined symbols and
+ // versions declared with @@@ to be renamed.
+ for (const std::pair<StringRef, const MCSymbol *> &P : Asm.Symvers) {
+ StringRef AliasName = P.first;
+ const auto &Symbol = cast<MCSymbolELF>(*P.second);
+ size_t Pos = AliasName.find('@');
+ assert(Pos != StringRef::npos);
+
+ StringRef Prefix = AliasName.substr(0, Pos);
+ StringRef Rest = AliasName.substr(Pos);
+ StringRef Tail = Rest;
+ if (Rest.startswith("@@@"))
+ Tail = Rest.substr(Symbol.isUndefined() ? 2 : 1);
+
+ auto *Alias =
+ cast<MCSymbolELF>(Asm.getContext().getOrCreateSymbol(Prefix + Tail));
+ Asm.registerSymbol(*Alias);
+ const MCExpr *Value = MCSymbolRefExpr::create(&Symbol, Asm.getContext());
+ Alias->setVariableValue(Value);
+
+ // Aliases defined with .symvar copy the binding from the symbol they alias.
+ // This is the first place we are able to copy this information.
+ Alias->setExternal(Symbol.isExternal());
+ Alias->setBinding(Symbol.getBinding());
+
+ if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
+ continue;
+
+ // FIXME: produce a better error message.
+ if (Symbol.isUndefined() && Rest.startswith("@@") &&
+ !Rest.startswith("@@@"))
+ report_fatal_error("A @@ version cannot be undefined");
+
+ if (Renames.count(&Symbol) && Renames[&Symbol] != Alias)
+ report_fatal_error(llvm::Twine("Multiple symbol versions defined for ") +
+ Symbol.getName());
+
+ Renames.insert(std::make_pair(&Symbol, Alias));
+ }
+
+ for (const MCSymbol *&Sym : AddrsigSyms) {
+ if (const MCSymbol *R = Renames.lookup(cast<MCSymbolELF>(Sym)))
+ Sym = R;
+ Sym->setUsedInReloc();
+ }
+}
+
+// It is always valid to create a relocation with a symbol. It is preferable
+// to use a relocation with a section if that is possible. Using the section
+// allows us to omit some local symbols from the symbol table.
+bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
+ const MCSymbolRefExpr *RefA,
+ const MCSymbolELF *Sym,
+ uint64_t C,
+ unsigned Type) const {
+ // A PCRel relocation to an absolute value has no symbol (or section). We
+ // represent that with a relocation to a null section.
+ if (!RefA)
+ return false;
+
+ MCSymbolRefExpr::VariantKind Kind = RefA->getKind();
+ switch (Kind) {
+ default:
+ break;
+ // The .odp creation emits a relocation against the symbol ".TOC." which
+ // create a R_PPC64_TOC relocation. However the relocation symbol name
+ // in final object creation should be NULL, since the symbol does not
+ // really exist, it is just the reference to TOC base for the current
+ // object file. Since the symbol is undefined, returning false results
+ // in a relocation with a null section which is the desired result.
+ case MCSymbolRefExpr::VK_PPC_TOCBASE:
+ return false;
+
+ // These VariantKind cause the relocation to refer to something other than
+ // the symbol itself, like a linker generated table. Since the address of
+ // symbol is not relevant, we cannot replace the symbol with the
+ // section and patch the difference in the addend.
+ case MCSymbolRefExpr::VK_GOT:
+ case MCSymbolRefExpr::VK_PLT:
+ case MCSymbolRefExpr::VK_GOTPCREL:
+ case MCSymbolRefExpr::VK_PPC_GOT_LO:
+ case MCSymbolRefExpr::VK_PPC_GOT_HI:
+ case MCSymbolRefExpr::VK_PPC_GOT_HA:
+ return true;
+ }
+
+ // An undefined symbol is not in any section, so the relocation has to point
+ // to the symbol itself.
+ assert(Sym && "Expected a symbol");
+ if (Sym->isUndefined())
+ return true;
+
+ unsigned Binding = Sym->getBinding();
+ switch(Binding) {
+ default:
+ llvm_unreachable("Invalid Binding");
+ case ELF::STB_LOCAL:
+ break;
+ case ELF::STB_WEAK:
+ // If the symbol is weak, it might be overridden by a symbol in another
+ // file. The relocation has to point to the symbol so that the linker
+ // can update it.
+ return true;
+ case ELF::STB_GLOBAL:
+ // Global ELF symbols can be preempted by the dynamic linker. The relocation
+ // has to point to the symbol for a reason analogous to the STB_WEAK case.
+ return true;
+ }
+
+ // If a relocation points to a mergeable section, we have to be careful.
+ // If the offset is zero, a relocation with the section will encode the
+ // same information. With a non-zero offset, the situation is different.
+ // For example, a relocation can point 42 bytes past the end of a string.
+ // If we change such a relocation to use the section, the linker would think
+ // that it pointed to another string and subtracting 42 at runtime will
+ // produce the wrong value.
+ if (Sym->isInSection()) {
+ auto &Sec = cast<MCSectionELF>(Sym->getSection());
+ unsigned Flags = Sec.getFlags();
+ if (Flags & ELF::SHF_MERGE) {
+ if (C != 0)
+ return true;
+
+ // It looks like gold has a bug (http://sourceware.org/PR16794) and can
+ // only handle section relocations to mergeable sections if using RELA.
+ if (!hasRelocationAddend())
+ return true;
+ }
+
+ // Most TLS relocations use a got, so they need the symbol. Even those that
+ // are just an offset (@tpoff), require a symbol in gold versions before
+ // 5efeedf61e4fe720fd3e9a08e6c91c10abb66d42 (2014-09-26) which fixed
+ // http://sourceware.org/PR16773.
+ if (Flags & ELF::SHF_TLS)
+ return true;
+ }
+
+ // If the symbol is a thumb function the final relocation must set the lowest
+ // bit. With a symbol that is done by just having the symbol have that bit
+ // set, so we would lose the bit if we relocated with the section.
+ // FIXME: We could use the section but add the bit to the relocation value.
+ if (Asm.isThumbFunc(Sym))
+ return true;
+
+ if (TargetObjectWriter->needsRelocateWithSymbol(*Sym, Type))
+ return true;
+ return false;
+}
+
+void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup, MCValue Target,
+ uint64_t &FixedValue) {
+ MCAsmBackend &Backend = Asm.getBackend();
+ bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
+ MCFixupKindInfo::FKF_IsPCRel;
+ const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent());
+ uint64_t C = Target.getConstant();
+ uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
+ MCContext &Ctx = Asm.getContext();
+
+ if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
+ // Let A, B and C being the components of Target and R be the location of
+ // the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
+ // If it is pcrel, we want to compute (A - B + C - R).
+
+ // In general, ELF has no relocations for -B. It can only represent (A + C)
+ // or (A + C - R). If B = R + K and the relocation is not pcrel, we can
+ // replace B to implement it: (A - R - K + C)
+ if (IsPCRel) {
+ Ctx.reportError(
+ Fixup.getLoc(),
+ "No relocation available to represent this relative expression");
+ return;
+ }
+
+ const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol());
+
+ if (SymB.isUndefined()) {
+ Ctx.reportError(Fixup.getLoc(),
+ Twine("symbol '") + SymB.getName() +
+ "' can not be undefined in a subtraction expression");
+ return;
+ }
+
+ assert(!SymB.isAbsolute() && "Should have been folded");
+ const MCSection &SecB = SymB.getSection();
+ if (&SecB != &FixupSection) {
+ Ctx.reportError(Fixup.getLoc(),
+ "Cannot represent a difference across sections");
+ return;
+ }
+
+ uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
+ uint64_t K = SymBOffset - FixupOffset;
+ IsPCRel = true;
+ C -= K;
+ }
+
+ // We either rejected the fixup or folded B into C at this point.
+ const MCSymbolRefExpr *RefA = Target.getSymA();
+ const auto *SymA = RefA ? cast<MCSymbolELF>(&RefA->getSymbol()) : nullptr;
+
+ bool ViaWeakRef = false;
+ if (SymA && SymA->isVariable()) {
+ const MCExpr *Expr = SymA->getVariableValue();
+ if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
+ if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) {
+ SymA = cast<MCSymbolELF>(&Inner->getSymbol());
+ ViaWeakRef = true;
+ }
+ }
+ }
+
+ unsigned Type = TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel);
+ uint64_t OriginalC = C;
+ bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type);
+ if (!RelocateWithSymbol && SymA && !SymA->isUndefined())
+ C += Layout.getSymbolOffset(*SymA);
+
+ uint64_t Addend = 0;
+ if (hasRelocationAddend()) {
+ Addend = C;
+ C = 0;
+ }
+
+ FixedValue = C;
+
+ const MCSectionELF *SecA = (SymA && SymA->isInSection())
+ ? cast<MCSectionELF>(&SymA->getSection())
+ : nullptr;
+ if (!checkRelocation(Ctx, Fixup.getLoc(), &FixupSection, SecA))
+ return;
+
+ if (!RelocateWithSymbol) {
+ const auto *SectionSymbol =
+ SecA ? cast<MCSymbolELF>(SecA->getBeginSymbol()) : nullptr;
+ if (SectionSymbol)
+ SectionSymbol->setUsedInReloc();
+ ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend, SymA,
+ OriginalC);
+ Relocations[&FixupSection].push_back(Rec);
+ return;
+ }
+
+ const auto *RenamedSymA = SymA;
+ if (SymA) {
+ if (const MCSymbolELF *R = Renames.lookup(SymA))
+ RenamedSymA = R;
+
+ if (ViaWeakRef)
+ RenamedSymA->setIsWeakrefUsedInReloc();
+ else
+ RenamedSymA->setUsedInReloc();
+ }
+ ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend, SymA,
+ OriginalC);
+ Relocations[&FixupSection].push_back(Rec);
}
bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
@@ -1353,6 +1507,14 @@ bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
std::unique_ptr<MCObjectWriter>
llvm::createELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS, bool IsLittleEndian) {
- return llvm::make_unique<ELFObjectWriter>(std::move(MOTW), OS,
- IsLittleEndian);
+ return llvm::make_unique<ELFSingleObjectWriter>(std::move(MOTW), OS,
+ IsLittleEndian);
+}
+
+std::unique_ptr<MCObjectWriter>
+llvm::createELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS,
+ bool IsLittleEndian) {
+ return llvm::make_unique<ELFDwoObjectWriter>(std::move(MOTW), OS, DwoOS,
+ IsLittleEndian);
}
diff --git a/contrib/llvm/lib/MC/MCAsmBackend.cpp b/contrib/llvm/lib/MC/MCAsmBackend.cpp
index b4a4d0a89966..92d3a8a2645f 100644
--- a/contrib/llvm/lib/MC/MCAsmBackend.cpp
+++ b/contrib/llvm/lib/MC/MCAsmBackend.cpp
@@ -11,20 +11,54 @@
#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"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCWasmObjectWriter.h"
+#include "llvm/MC/MCWinCOFFObjectWriter.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
using namespace llvm;
-MCAsmBackend::MCAsmBackend() : CodePadder(new MCCodePadder()) {}
-
-MCAsmBackend::MCAsmBackend(std::unique_ptr<MCCodePadder> TargetCodePadder)
- : CodePadder(std::move(TargetCodePadder)) {}
+MCAsmBackend::MCAsmBackend(support::endianness Endian)
+ : CodePadder(new MCCodePadder()), Endian(Endian) {}
MCAsmBackend::~MCAsmBackend() = default;
+std::unique_ptr<MCObjectWriter>
+MCAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
+ auto TW = createObjectTargetWriter();
+ switch (TW->getFormat()) {
+ case Triple::ELF:
+ return createELFObjectWriter(cast<MCELFObjectTargetWriter>(std::move(TW)), OS,
+ Endian == support::little);
+ case Triple::MachO:
+ return createMachObjectWriter(cast<MCMachObjectTargetWriter>(std::move(TW)),
+ OS, Endian == support::little);
+ case Triple::COFF:
+ return createWinCOFFObjectWriter(
+ cast<MCWinCOFFObjectTargetWriter>(std::move(TW)), OS);
+ case Triple::Wasm:
+ return createWasmObjectWriter(cast<MCWasmObjectTargetWriter>(std::move(TW)),
+ OS);
+ default:
+ llvm_unreachable("unexpected object format");
+ }
+}
+
+std::unique_ptr<MCObjectWriter>
+MCAsmBackend::createDwoObjectWriter(raw_pwrite_stream &OS,
+ raw_pwrite_stream &DwoOS) const {
+ auto TW = createObjectTargetWriter();
+ if (TW->getFormat() != Triple::ELF)
+ report_fatal_error("dwo only supported with ELF");
+ return createELFDwoObjectWriter(cast<MCELFObjectTargetWriter>(std::move(TW)),
+ OS, DwoOS, Endian == support::little);
+}
+
Optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const {
return None;
}
@@ -50,7 +84,15 @@ const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"FK_SecRel_1", 0, 8, 0},
{"FK_SecRel_2", 0, 16, 0},
{"FK_SecRel_4", 0, 32, 0},
- {"FK_SecRel_8", 0, 64, 0}};
+ {"FK_SecRel_8", 0, 64, 0},
+ {"FK_Data_Add_1", 0, 8, 0},
+ {"FK_Data_Add_2", 0, 16, 0},
+ {"FK_Data_Add_4", 0, 32, 0},
+ {"FK_Data_Add_8", 0, 64, 0},
+ {"FK_Data_Sub_1", 0, 8, 0},
+ {"FK_Data_Sub_2", 0, 16, 0},
+ {"FK_Data_Sub_4", 0, 32, 0},
+ {"FK_Data_Sub_8", 0, 64, 0}};
assert((size_t)Kind <= array_lengthof(Builtins) && "Unknown fixup kind");
return Builtins[Kind];
@@ -58,7 +100,8 @@ const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
bool MCAsmBackend::fixupNeedsRelaxationAdvanced(
const MCFixup &Fixup, bool Resolved, uint64_t Value,
- const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const {
+ const MCRelaxableFragment *DF, const MCAsmLayout &Layout,
+ const bool WasForced) const {
if (!Resolved)
return true;
return fixupNeedsRelaxation(Fixup, Value, DF, Layout);
@@ -84,4 +127,4 @@ void MCAsmBackend::handleCodePaddingInstructionEnd(const MCInst &Inst) {
bool MCAsmBackend::relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout) {
return CodePadder->relaxFragment(PF, Layout);
-} \ No newline at end of file
+}
diff --git a/contrib/llvm/lib/MC/MCAsmInfo.cpp b/contrib/llvm/lib/MC/MCAsmInfo.cpp
index f05904048e0b..30f22d2d68f4 100644
--- a/contrib/llvm/lib/MC/MCAsmInfo.cpp
+++ b/contrib/llvm/lib/MC/MCAsmInfo.cpp
@@ -17,9 +17,18 @@
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/CommandLine.h"
using namespace llvm;
+enum DefaultOnOff { Default, Enable, Disable };
+static cl::opt<DefaultOnOff> DwarfExtendedLoc(
+ "dwarf-extended-loc", cl::Hidden,
+ cl::desc("Disable emission of the extended flags in .loc directives."),
+ cl::values(clEnumVal(Default, "Default for platform"),
+ clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")),
+ cl::init(Default));
+
MCAsmInfo::MCAsmInfo() {
SeparatorString = ";";
CommentString = "#";
@@ -41,6 +50,8 @@ MCAsmInfo::MCAsmInfo() {
Data64bitsDirective = "\t.quad\t";
GlobalDirective = "\t.globl\t";
WeakDirective = "\t.weak\t";
+ if (DwarfExtendedLoc != Default)
+ SupportsExtendedDwarfLocDirective = DwarfExtendedLoc == Enable;
// FIXME: Clang's logic should be synced with the logic used to initialize
// this member and the two implementations should be merged.
diff --git a/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp b/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp
index 85104484fd40..d8fb875b67c6 100644
--- a/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp
+++ b/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp
@@ -41,6 +41,15 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() {
// At least MSVC inline-asm does AShr.
UseLogicalShr = false;
+
+ // If this is a COFF target, assume that it supports associative comdats. It's
+ // part of the spec.
+ HasCOFFAssociativeComdats = true;
+
+ // We can generate constants in comdat sections that can be shared,
+ // but in order not to create null typed symbols, we actually need to
+ // make them global symbols as well.
+ HasCOFFComdatConstants = true;
}
void MCAsmInfoMicrosoft::anchor() {}
@@ -49,4 +58,12 @@ MCAsmInfoMicrosoft::MCAsmInfoMicrosoft() = default;
void MCAsmInfoGNUCOFF::anchor() {}
-MCAsmInfoGNUCOFF::MCAsmInfoGNUCOFF() = default;
+MCAsmInfoGNUCOFF::MCAsmInfoGNUCOFF() {
+ // If this is a GNU environment (mingw or cygwin), don't use associative
+ // comdats for jump tables, unwind information, and other data associated with
+ // a function.
+ HasCOFFAssociativeComdats = false;
+
+ // We don't create constants in comdat sections for MinGW.
+ HasCOFFComdatConstants = false;
+}
diff --git a/contrib/llvm/lib/MC/MCAsmMacro.cpp b/contrib/llvm/lib/MC/MCAsmMacro.cpp
new file mode 100644
index 000000000000..7e89c03c6c6b
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCAsmMacro.cpp
@@ -0,0 +1,42 @@
+//===- MCAsmMacro.h - Assembly Macros ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmMacro.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void MCAsmMacroParameter::dump(raw_ostream &OS) const {
+ OS << "\"" << Name << "\"";
+ if (Required)
+ OS << ":req";
+ if (Vararg)
+ OS << ":vararg";
+ if (!Value.empty()) {
+ OS << " = ";
+ bool first = true;
+ for (const AsmToken &T : Value) {
+ if (!first)
+ OS << ", ";
+ first = false;
+ OS << T.getString();
+ }
+ }
+ OS << "\n";
+}
+
+void MCAsmMacro::dump(raw_ostream &OS) const {
+ OS << "Macro " << Name << ":\n";
+ OS << " Parameters:\n";
+ for (const MCAsmMacroParameter &P : Parameters) {
+ OS << " ";
+ P.dump();
+ }
+ OS << " (BEGIN BODY)" << Body << "(END BODY)\n";
+}
diff --git a/contrib/llvm/lib/MC/MCAsmStreamer.cpp b/contrib/llvm/lib/MC/MCAsmStreamer.cpp
index 6f045a4b10ba..92f615180561 100644
--- a/contrib/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/contrib/llvm/lib/MC/MCAsmStreamer.cpp
@@ -7,12 +7,14 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCCodeView.h"
#include "llvm/MC/MCContext.h"
@@ -21,6 +23,7 @@
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
@@ -30,6 +33,7 @@
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/TargetRegistry.h"
#include <cctype>
using namespace llvm;
@@ -41,12 +45,12 @@ class MCAsmStreamer final : public MCStreamer {
formatted_raw_ostream &OS;
const MCAsmInfo *MAI;
std::unique_ptr<MCInstPrinter> InstPrinter;
- std::unique_ptr<MCCodeEmitter> Emitter;
- std::unique_ptr<MCAsmBackend> AsmBackend;
+ std::unique_ptr<MCAssembler> Assembler;
SmallString<128> ExplicitCommentToEmit;
SmallString<128> CommentToEmit;
raw_svector_ostream CommentStream;
+ raw_null_ostream NullStream;
unsigned IsVerboseAsm : 1;
unsigned ShowInst : 1;
@@ -59,18 +63,24 @@ class MCAsmStreamer final : public MCStreamer {
public:
MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
bool isVerboseAsm, bool useDwarfDirectory,
- MCInstPrinter *printer, MCCodeEmitter *emitter,
- MCAsmBackend *asmbackend, bool showInst)
+ MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter,
+ std::unique_ptr<MCAsmBackend> asmbackend, bool showInst)
: MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
- MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter),
- AsmBackend(asmbackend), CommentStream(CommentToEmit),
- IsVerboseAsm(isVerboseAsm), ShowInst(showInst),
- UseDwarfDirectory(useDwarfDirectory) {
+ MAI(Context.getAsmInfo()), InstPrinter(printer),
+ Assembler(llvm::make_unique<MCAssembler>(
+ Context, std::move(asmbackend), std::move(emitter),
+ (asmbackend) ? asmbackend->createObjectWriter(NullStream)
+ : nullptr)),
+ CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
+ ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) {
assert(InstPrinter);
if (IsVerboseAsm)
InstPrinter->setCommentStream(CommentStream);
}
+ MCAssembler &getAssembler() { return *Assembler; }
+ MCAssembler *getAssemblerPtr() override { return nullptr; }
+
inline void EmitEOL() {
// Dump Explicit Comments here.
emitExplicitComments();
@@ -86,26 +96,24 @@ public:
void EmitCommentsAndEOL();
- /// isVerboseAsm - Return true if this streamer supports verbose assembly at
- /// all.
+ /// Return true if this streamer supports verbose assembly at all.
bool isVerboseAsm() const override { return IsVerboseAsm; }
- /// hasRawTextSupport - We support EmitRawText.
+ /// Do we support EmitRawText?
bool hasRawTextSupport() const override { return true; }
- /// AddComment - Add a comment that can be emitted to the generated .s
- /// file if applicable as a QoI issue to make the output of the compiler
- /// more readable. This only affects the MCAsmStreamer, and only when
- /// verbose assembly output is enabled.
+ /// Add a comment that can be emitted to the generated .s file to make the
+ /// output of the compiler more readable. This only affects the MCAsmStreamer
+ /// and only when verbose assembly output is enabled.
void AddComment(const Twine &T, bool EOL = true) override;
- /// AddEncodingComment - Add a comment showing the encoding of an instruction.
- /// If PrintSchedInfo - is true then the comment sched:[x:y] should
- // be added to output if it's being supported by target
+ /// Add a comment showing the encoding of an instruction.
+ /// If PrintSchedInfo is true, then the comment sched:[x:y] will be added to
+ /// the output if supported by the target.
void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &,
bool PrintSchedInfo);
- /// GetCommentOS - Return a raw_ostream that comments can be written to.
+ /// Return a raw_ostream that comments can be written to.
/// Unlike AddComment, you are required to terminate comments with \n if you
/// use this method.
raw_ostream &GetCommentOS() override {
@@ -119,7 +127,7 @@ public:
void addExplicitComment(const Twine &T) override;
void emitExplicitComments() override;
- /// AddBlankLine - Emit a blank line to a .s file to pretty it up.
+ /// Emit a blank line to a .s file to pretty it up.
void AddBlankLine() override {
EmitEOL();
}
@@ -154,13 +162,15 @@ public:
void EmitCOFFSymbolType(int Type) override;
void EndCOFFSymbolDef() override;
void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
+ void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override;
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 emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
- /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
+ /// Emit a local common (.lcomm) symbol.
///
/// @param Symbol - The common symbol to emit.
/// @param Size - The size of the common symbol.
@@ -169,7 +179,8 @@ public:
unsigned ByteAlignment) override;
void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
- uint64_t Size = 0, unsigned ByteAlignment = 0) override;
+ uint64_t Size = 0, unsigned ByteAlignment = 0,
+ SMLoc Loc = SMLoc()) override;
void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment = 0) override;
@@ -198,8 +209,6 @@ public:
void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
SMLoc Loc = SMLoc()) override;
- void emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) override;
-
void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
SMLoc Loc = SMLoc()) override;
@@ -215,9 +224,16 @@ public:
SMLoc Loc) override;
void EmitFileDirective(StringRef Filename) override;
- unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
- StringRef Filename,
- unsigned CUID = 0) override;
+ Expected<unsigned> tryEmitDwarfFileDirective(unsigned FileNo,
+ StringRef Directory,
+ StringRef Filename,
+ MD5::MD5Result *Checksum = 0,
+ Optional<StringRef> Source = None,
+ unsigned CUID = 0) override;
+ void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> Source,
+ unsigned CUID = 0) override;
void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags,
unsigned Isa, unsigned Discriminator,
@@ -290,6 +306,9 @@ public:
SMLoc Loc) override;
void EmitWinEHHandlerData(SMLoc Loc) override;
+ void emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To, uint64_t Count) override;
+
void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
bool PrintSchedInfo) override;
@@ -298,11 +317,15 @@ 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;
+
+ void EmitAddrsig() override;
+ void EmitAddrsigSym(const MCSymbol *Sym) override;
- /// EmitRawText - 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 hasRawTextSupport() predicate.
+ /// 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
+ /// hasRawTextSupport() predicate.
void EmitRawTextImpl(StringRef String) override;
void FinishImpl() override;
@@ -310,11 +333,6 @@ public:
} // end anonymous namespace.
-/// AddComment - Add a comment that can be emitted to the generated .s
-/// file if applicable as a QoI issue to make the output of the compiler
-/// more readable. This only affects the MCAsmStreamer, and only when
-/// verbose assembly output is enabled.
-/// By deafult EOL is set to true so that each comment goes on its own line.
void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
if (!IsVerboseAsm) return;
@@ -536,11 +554,19 @@ void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) {
}
void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
- Symbol->print(OS, MAI);
- OS << " = ";
- Value->print(OS, MAI);
+ // Do not emit a .set on inlined target assignments.
+ bool EmitSet = true;
+ if (auto *E = dyn_cast<MCTargetExpr>(Value))
+ if (E->inlineAssignedExpr())
+ EmitSet = false;
+ if (EmitSet) {
+ OS << ".set ";
+ Symbol->print(OS, MAI);
+ OS << ", ";
+ Value->print(OS, MAI);
- EmitEOL();
+ EmitEOL();
+ }
MCStreamer::EmitAssignment(Symbol, Value);
}
@@ -576,7 +602,7 @@ bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
case MCSA_ELF_TypeObject: OS << "object"; break;
case MCSA_ELF_TypeTLS: OS << "tls_object"; break;
case MCSA_ELF_TypeCommon: OS << "common"; break;
- case MCSA_ELF_TypeNoType: OS << "no_type"; break;
+ case MCSA_ELF_TypeNoType: OS << "notype"; break;
case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
}
EmitEOL();
@@ -661,6 +687,12 @@ void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
EmitEOL();
}
+void MCAsmStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
+ OS << "\t.symidx\t";
+ Symbol->print(OS, MAI);
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
OS << "\t.secidx\t";
Symbol->print(OS, MAI);
@@ -675,6 +707,16 @@ void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
EmitEOL();
}
+void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
+ OS << "\t.rva\t";
+ Symbol->print(OS, MAI);
+ if (Offset > 0)
+ OS << '+' << Offset;
+ else if (Offset < 0)
+ OS << '-' << -Offset;
+ EmitEOL();
+}
+
void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
assert(MAI->hasDotTypeDotSizeDirective());
OS << "\t.size\t";
@@ -699,10 +741,6 @@ void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
EmitEOL();
}
-/// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
-///
-/// @param Symbol - The common symbol to emit.
-/// @param Size - The size of the common symbol.
void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlign) {
OS << "\t.lcomm\t";
@@ -726,14 +764,18 @@ void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
}
void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment) {
+ uint64_t Size, unsigned ByteAlignment,
+ SMLoc Loc) {
if (Symbol)
AssignFragment(Symbol, &Section->getDummyFragment());
// Note: a .zerofill directive does not switch sections.
OS << ".zerofill ";
+ assert(Section->getVariant() == MCSection::SV_MachO &&
+ ".zerofill is a Mach-O specific directive");
// This is a mach-o specific directive.
+
const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
OS << MOSection->getSegmentName() << "," << MOSection->getSectionName();
@@ -756,7 +798,11 @@ void MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
assert(Symbol && "Symbol shouldn't be NULL!");
// Instead of using the Section we'll just use the shortcut.
+
+ assert(Section->getVariant() == MCSection::SV_MachO &&
+ ".zerofill is a Mach-O specific directive");
// This is a mach-o specific directive and section.
+
OS << ".tbss ";
Symbol->print(OS, MAI);
OS << ", " << Size;
@@ -780,7 +826,7 @@ static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
continue;
}
- if (isprint((unsigned char)C)) {
+ if (isPrint((unsigned char)C)) {
OS << (char)C;
continue;
}
@@ -915,7 +961,7 @@ void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) {
EmitULEB128IntValue(IntValue);
return;
}
- OS << ".uleb128 ";
+ OS << "\t.uleb128 ";
Value->print(OS, MAI);
EmitEOL();
}
@@ -926,7 +972,7 @@ void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) {
EmitSLEB128IntValue(IntValue);
return;
}
- OS << ".sleb128 ";
+ OS << "\t.sleb128 ";
Value->print(OS, MAI);
EmitEOL();
}
@@ -992,14 +1038,6 @@ void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
MCStreamer::emitFill(NumBytes, FillValue);
}
-void MCAsmStreamer::emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) {
- if (NumValues == 0)
- return;
-
- const MCExpr *E = MCConstantExpr::create(NumValues, getContext());
- emitFill(*E, Size, Expr);
-}
-
void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
int64_t Expr, SMLoc Loc) {
// FIXME: Emit location directives
@@ -1086,20 +1124,12 @@ void MCAsmStreamer::EmitFileDirective(StringRef Filename) {
EmitEOL();
}
-unsigned MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo,
- StringRef Directory,
- StringRef Filename,
- unsigned CUID) {
- assert(CUID == 0);
-
- MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
- unsigned NumFiles = Table.getMCDwarfFiles().size();
- FileNo = Table.getFile(Directory, Filename, FileNo);
- if (FileNo == 0)
- return 0;
- if (NumFiles == Table.getMCDwarfFiles().size())
- return FileNo;
-
+static void printDwarfFileDirective(unsigned FileNo, StringRef Directory,
+ StringRef Filename,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> Source,
+ bool UseDwarfDirectory,
+ raw_svector_ostream &OS) {
SmallString<128> FullPathName;
if (!UseDwarfDirectory && !Directory.empty()) {
@@ -1113,51 +1143,102 @@ unsigned MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo,
}
}
- SmallString<128> Str;
- raw_svector_ostream OS1(Str);
- OS1 << "\t.file\t" << FileNo << ' ';
+ OS << "\t.file\t" << FileNo << ' ';
if (!Directory.empty()) {
- PrintQuotedString(Directory, OS1);
- OS1 << ' ';
+ PrintQuotedString(Directory, OS);
+ OS << ' ';
}
- PrintQuotedString(Filename, OS1);
- if (MCTargetStreamer *TS = getTargetStreamer()) {
+ PrintQuotedString(Filename, OS);
+ if (Checksum)
+ OS << " md5 0x" << Checksum->digest();
+ if (Source) {
+ OS << " source ";
+ PrintQuotedString(*Source, OS);
+ }
+}
+
+Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
+ unsigned FileNo, StringRef Directory, StringRef Filename,
+ MD5::MD5Result *Checksum, Optional<StringRef> Source, unsigned CUID) {
+ assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer");
+
+ MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
+ unsigned NumFiles = Table.getMCDwarfFiles().size();
+ Expected<unsigned> FileNoOrErr =
+ Table.tryGetFile(Directory, Filename, Checksum, Source, FileNo);
+ if (!FileNoOrErr)
+ return FileNoOrErr.takeError();
+ FileNo = FileNoOrErr.get();
+ if (NumFiles == Table.getMCDwarfFiles().size())
+ return FileNo;
+
+ SmallString<128> Str;
+ raw_svector_ostream OS1(Str);
+ printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source,
+ UseDwarfDirectory, OS1);
+
+ if (MCTargetStreamer *TS = getTargetStreamer())
TS->emitDwarfFileDirective(OS1.str());
- } else {
+ else
EmitRawText(OS1.str());
- }
return FileNo;
}
+void MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory,
+ StringRef Filename,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> Source,
+ unsigned CUID) {
+ assert(CUID == 0);
+ // .file 0 is new for DWARF v5.
+ if (getContext().getDwarfVersion() < 5)
+ return;
+ // Inform MCDwarf about the root file.
+ getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
+ Source);
+
+ SmallString<128> Str;
+ raw_svector_ostream OS1(Str);
+ printDwarfFileDirective(0, Directory, Filename, Checksum, Source,
+ UseDwarfDirectory, OS1);
+
+ if (MCTargetStreamer *TS = getTargetStreamer())
+ TS->emitDwarfFileDirective(OS1.str());
+ else
+ EmitRawText(OS1.str());
+}
+
void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags,
unsigned Isa,
unsigned Discriminator,
StringRef FileName) {
OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
- if (Flags & DWARF2_FLAG_BASIC_BLOCK)
- OS << " basic_block";
- if (Flags & DWARF2_FLAG_PROLOGUE_END)
- OS << " prologue_end";
- if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
- OS << " epilogue_begin";
-
- unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
- if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
- OS << " is_stmt ";
+ if (MAI->supportsExtendedDwarfLocDirective()) {
+ if (Flags & DWARF2_FLAG_BASIC_BLOCK)
+ OS << " basic_block";
+ if (Flags & DWARF2_FLAG_PROLOGUE_END)
+ OS << " prologue_end";
+ if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
+ OS << " epilogue_begin";
+
+ unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
+ if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
+ OS << " is_stmt ";
+
+ if (Flags & DWARF2_FLAG_IS_STMT)
+ OS << "1";
+ else
+ OS << "0";
+ }
- if (Flags & DWARF2_FLAG_IS_STMT)
- OS << "1";
- else
- OS << "0";
+ if (Isa)
+ OS << " isa " << Isa;
+ if (Discriminator)
+ OS << " discriminator " << Discriminator;
}
- if (Isa)
- OS << " isa " << Isa;
- if (Discriminator)
- OS << " discriminator " << Discriminator;
-
if (IsVerboseAsm) {
OS.PadToColumn(MAI->getCommentColumn());
OS << MAI->getCommentString() << ' ' << FileName << ':'
@@ -1606,6 +1687,17 @@ void MCAsmStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
EmitEOL();
}
+void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To,
+ uint64_t Count) {
+ OS << "\t.cg_profile ";
+ From->getSymbol().print(OS, MAI);
+ OS << ", ";
+ To->getSymbol().print(OS, MAI);
+ OS << ", " << Count;
+ EmitEOL();
+}
+
void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
const MCSubtargetInfo &STI,
bool PrintSchedInfo) {
@@ -1613,7 +1705,12 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
SmallString<256> Code;
SmallVector<MCFixup, 4> Fixups;
raw_svector_ostream VecOS(Code);
- Emitter->encodeInstruction(Inst, VecOS, Fixups, STI);
+
+ // If we have no code emitter, don't emit code.
+ if (!getAssembler().getEmitterPtr())
+ return;
+
+ getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
// If we are showing fixups, create symbolic markers in the encoded
// representation. We do this by making a per-bit map to the fixup item index,
@@ -1625,7 +1722,8 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
MCFixup &F = Fixups[i];
- const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind());
+ const MCFixupKindInfo &Info =
+ getAssembler().getBackend().getFixupKindInfo(F.getKind());
for (unsigned j = 0; j != Info.TargetSize; ++j) {
unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
@@ -1689,7 +1787,8 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
MCFixup &F = Fixups[i];
- const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind());
+ const MCFixupKindInfo &Info =
+ getAssembler().getBackend().getFixupKindInfo(F.getKind());
OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
<< ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
}
@@ -1702,8 +1801,7 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst,
"Cannot emit contents before setting section!");
// Show the encoding in a comment if we have a code emitter.
- if (Emitter)
- AddEncodingComment(Inst, STI, PrintSchedInfo);
+ AddEncodingComment(Inst, STI, PrintSchedInfo);
// Show the MCInst if enabled.
if (ShowInst) {
@@ -1749,7 +1847,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;
@@ -1761,6 +1860,17 @@ bool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
return false;
}
+void MCAsmStreamer::EmitAddrsig() {
+ OS << "\t.addrsig";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitAddrsigSym(const MCSymbol *Sym) {
+ OS << "\t.addrsig_sym ";
+ Sym->print(OS, MAI);
+ EmitEOL();
+}
+
/// EmitRawText - 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 hasRawTextSupport() predicate.
@@ -1792,8 +1902,11 @@ void MCAsmStreamer::FinishImpl() {
MCStreamer *llvm::createAsmStreamer(MCContext &Context,
std::unique_ptr<formatted_raw_ostream> OS,
bool isVerboseAsm, bool useDwarfDirectory,
- MCInstPrinter *IP, MCCodeEmitter *CE,
- MCAsmBackend *MAB, bool ShowInst) {
+ MCInstPrinter *IP,
+ std::unique_ptr<MCCodeEmitter> &&CE,
+ std::unique_ptr<MCAsmBackend> &&MAB,
+ bool ShowInst) {
return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm,
- useDwarfDirectory, IP, CE, MAB, ShowInst);
+ useDwarfDirectory, IP, std::move(CE), std::move(MAB),
+ ShowInst);
}
diff --git a/contrib/llvm/lib/MC/MCAssembler.cpp b/contrib/llvm/lib/MC/MCAssembler.cpp
index bd881b4d6e85..1470e026d985 100644
--- a/contrib/llvm/lib/MC/MCAssembler.cpp
+++ b/contrib/llvm/lib/MC/MCAssembler.cpp
@@ -83,9 +83,12 @@ STATISTIC(PaddingFragmentsBytes,
/* *** */
-MCAssembler::MCAssembler(MCContext &Context, MCAsmBackend &Backend,
- MCCodeEmitter &Emitter, MCObjectWriter &Writer)
- : Context(Context), Backend(Backend), Emitter(Emitter), Writer(Writer),
+MCAssembler::MCAssembler(MCContext &Context,
+ std::unique_ptr<MCAsmBackend> Backend,
+ std::unique_ptr<MCCodeEmitter> Emitter,
+ std::unique_ptr<MCObjectWriter> Writer)
+ : Context(Context), Backend(std::move(Backend)),
+ Emitter(std::move(Emitter)), Writer(std::move(Writer)),
BundleAlignSize(0), RelaxAll(false), SubsectionsViaSymbols(false),
IncrementalLinkerCompatible(false), ELFHeaderEFlags(0) {
VersionInfo.Major = 0; // Major version == 0 for "none specified"
@@ -110,9 +113,12 @@ void MCAssembler::reset() {
VersionInfo.Major = 0;
// reset objects owned by us
- getBackend().reset();
- getEmitter().reset();
- getWriter().reset();
+ if (getBackendPtr())
+ getBackendPtr()->reset();
+ if (getEmitterPtr())
+ getEmitterPtr()->reset();
+ if (getWriterPtr())
+ getWriterPtr()->reset();
getLOHContainer().reset();
}
@@ -191,7 +197,8 @@ const MCSymbol *MCAssembler::getAtom(const MCSymbol &S) const {
bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
const MCFixup &Fixup, const MCFragment *DF,
- MCValue &Target, uint64_t &Value) const {
+ MCValue &Target, uint64_t &Value,
+ bool &WasForced) const {
++stats::evaluateFixup;
// FIXME: This code has some duplication with recordRelocation. We should
@@ -203,6 +210,7 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
const MCExpr *Expr = Fixup.getValue();
MCContext &Ctx = getContext();
Value = 0;
+ WasForced = false;
if (!Expr->evaluateAsRelocatable(Target, &Layout, &Fixup)) {
Ctx.reportError(Fixup.getLoc(), "expected relocatable expression");
return true;
@@ -215,10 +223,11 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
}
}
- bool IsPCRel = Backend.getFixupKindInfo(
- Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
+ assert(getBackendPtr() && "Expected assembler backend");
+ bool IsPCRel = getBackendPtr()->getFixupKindInfo(Fixup.getKind()).Flags &
+ MCFixupKindInfo::FKF_IsPCRel;
- bool IsResolved;
+ bool IsResolved = false;
if (IsPCRel) {
if (Target.getSymB()) {
IsResolved = false;
@@ -229,8 +238,8 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
const MCSymbol &SA = A->getSymbol();
if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined()) {
IsResolved = false;
- } else {
- IsResolved = getWriter().isSymbolRefDifferenceFullyResolvedImpl(
+ } else if (auto *Writer = getWriterPtr()) {
+ IsResolved = Writer->isSymbolRefDifferenceFullyResolvedImpl(
*this, SA, *DF, false, true);
}
}
@@ -251,8 +260,8 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
Value -= Layout.getSymbolOffset(Sym);
}
- bool ShouldAlignPC = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
- MCFixupKindInfo::FKF_IsAlignedDownTo32Bits;
+ bool ShouldAlignPC = getBackend().getFixupKindInfo(Fixup.getKind()).Flags &
+ MCFixupKindInfo::FKF_IsAlignedDownTo32Bits;
assert((ShouldAlignPC ? IsPCRel : true) &&
"FKF_IsAlignedDownTo32Bits is only allowed on PC-relative fixups!");
@@ -266,14 +275,17 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
}
// Let the backend force a relocation if needed.
- if (IsResolved && Backend.shouldForceRelocation(*this, Fixup, Target))
+ if (IsResolved && getBackend().shouldForceRelocation(*this, Fixup, Target)) {
IsResolved = false;
+ WasForced = true;
+ }
return IsResolved;
}
uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
const MCFragment &F) const {
+ assert(getBackendPtr() && "Requires assembler backend");
switch (F.getKind()) {
case MCFragment::FT_Data:
return cast<MCDataFragment>(F).getContents().size();
@@ -283,10 +295,13 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
return cast<MCCompactEncodedInstFragment>(F).getContents().size();
case MCFragment::FT_Fill: {
auto &FF = cast<MCFillFragment>(F);
- int64_t Size = 0;
- if (!FF.getSize().evaluateAsAbsolute(Size, Layout))
+ int64_t NumValues = 0;
+ if (!FF.getNumValues().evaluateAsAbsolute(NumValues, Layout)) {
getContext().reportError(FF.getLoc(),
"expected assembly-time absolute expression");
+ return 0;
+ }
+ int64_t Size = NumValues * FF.getValueSize();
if (Size < 0) {
getContext().reportError(FF.getLoc(), "invalid number of bytes");
return 0;
@@ -411,17 +426,18 @@ void MCAsmLayout::layoutFragment(MCFragment *F) {
if (Assembler.isBundlingEnabled() && F->hasInstructions()) {
assert(isa<MCEncodedFragment>(F) &&
"Only MCEncodedFragment implementations have instructions");
- uint64_t FSize = Assembler.computeFragmentSize(*this, *F);
+ MCEncodedFragment *EF = cast<MCEncodedFragment>(F);
+ uint64_t FSize = Assembler.computeFragmentSize(*this, *EF);
if (!Assembler.getRelaxAll() && FSize > Assembler.getBundleAlignSize())
report_fatal_error("Fragment can't be larger than a bundle size");
- uint64_t RequiredBundlePadding = computeBundlePadding(Assembler, F,
- F->Offset, FSize);
+ uint64_t RequiredBundlePadding =
+ computeBundlePadding(Assembler, EF, EF->Offset, FSize);
if (RequiredBundlePadding > UINT8_MAX)
report_fatal_error("Padding cannot exceed 255 bytes");
- F->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
- F->Offset += RequiredBundlePadding;
+ EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
+ EF->Offset += RequiredBundlePadding;
}
}
@@ -435,18 +451,20 @@ void MCAssembler::registerSymbol(const MCSymbol &Symbol, bool *Created) {
}
}
-void MCAssembler::writeFragmentPadding(const MCFragment &F, uint64_t FSize,
- MCObjectWriter *OW) const {
+void MCAssembler::writeFragmentPadding(raw_ostream &OS,
+ const MCEncodedFragment &EF,
+ uint64_t FSize) const {
+ assert(getBackendPtr() && "Expected assembler backend");
// Should NOP padding be written out before this fragment?
- unsigned BundlePadding = F.getBundlePadding();
+ unsigned BundlePadding = EF.getBundlePadding();
if (BundlePadding > 0) {
assert(isBundlingEnabled() &&
"Writing bundle padding with disabled bundling");
- assert(F.hasInstructions() &&
+ assert(EF.hasInstructions() &&
"Writing bundle padding for a fragment without instructions");
unsigned TotalLength = BundlePadding + static_cast<unsigned>(FSize);
- if (F.alignToBundleEnd() && TotalLength > getBundleAlignSize()) {
+ if (EF.alignToBundleEnd() && TotalLength > getBundleAlignSize()) {
// If the padding itself crosses a bundle boundary, it must be emitted
// in 2 pieces, since even nop instructions must not cross boundaries.
// v--------------v <- BundleAlignSize
@@ -456,30 +474,31 @@ void MCAssembler::writeFragmentPadding(const MCFragment &F, uint64_t FSize,
// ----------------------------
// ^-------------------^ <- TotalLength
unsigned DistanceToBoundary = TotalLength - getBundleAlignSize();
- if (!getBackend().writeNopData(DistanceToBoundary, OW))
- report_fatal_error("unable to write NOP sequence of " +
- Twine(DistanceToBoundary) + " bytes");
+ if (!getBackend().writeNopData(OS, DistanceToBoundary))
+ report_fatal_error("unable to write NOP sequence of " +
+ Twine(DistanceToBoundary) + " bytes");
BundlePadding -= DistanceToBoundary;
}
- if (!getBackend().writeNopData(BundlePadding, OW))
+ if (!getBackend().writeNopData(OS, BundlePadding))
report_fatal_error("unable to write NOP sequence of " +
Twine(BundlePadding) + " bytes");
}
}
-/// \brief Write the fragment \p F to the output file.
-static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCFragment &F) {
- MCObjectWriter *OW = &Asm.getWriter();
-
+/// Write the fragment \p F to the output file.
+static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
+ const MCAsmLayout &Layout, const MCFragment &F) {
// FIXME: Embed in fragments instead?
uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F);
- Asm.writeFragmentPadding(F, FragmentSize, OW);
+ support::endianness Endian = Asm.getBackend().Endian;
+
+ if (const MCEncodedFragment *EF = dyn_cast<MCEncodedFragment>(&F))
+ Asm.writeFragmentPadding(OS, *EF, FragmentSize);
// This variable (and its dummy usage) is to participate in the assert at
// the end of the function.
- uint64_t Start = OW->getStream().tell();
+ uint64_t Start = OS.tell();
(void) Start;
++stats::EmittedFragments;
@@ -506,7 +525,7 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
// bytes left to fill use the Value and ValueSize to fill the rest.
// If we are aligning with nops, ask that target to emit the right data.
if (AF.hasEmitNops()) {
- if (!Asm.getBackend().writeNopData(Count, OW))
+ if (!Asm.getBackend().writeNopData(OS, Count))
report_fatal_error("unable to write nop sequence of " +
Twine(Count) + " bytes");
break;
@@ -516,10 +535,16 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
for (uint64_t i = 0; i != Count; ++i) {
switch (AF.getValueSize()) {
default: llvm_unreachable("Invalid size!");
- case 1: OW->write8 (uint8_t (AF.getValue())); break;
- case 2: OW->write16(uint16_t(AF.getValue())); break;
- case 4: OW->write32(uint32_t(AF.getValue())); break;
- case 8: OW->write64(uint64_t(AF.getValue())); break;
+ case 1: OS << char(AF.getValue()); break;
+ case 2:
+ support::endian::write<uint16_t>(OS, AF.getValue(), Endian);
+ break;
+ case 4:
+ support::endian::write<uint32_t>(OS, AF.getValue(), Endian);
+ break;
+ case 8:
+ support::endian::write<uint64_t>(OS, AF.getValue(), Endian);
+ break;
}
}
break;
@@ -527,47 +552,60 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
case MCFragment::FT_Data:
++stats::EmittedDataFragments;
- OW->writeBytes(cast<MCDataFragment>(F).getContents());
+ OS << cast<MCDataFragment>(F).getContents();
break;
case MCFragment::FT_Relaxable:
++stats::EmittedRelaxableFragments;
- OW->writeBytes(cast<MCRelaxableFragment>(F).getContents());
+ OS << cast<MCRelaxableFragment>(F).getContents();
break;
case MCFragment::FT_CompactEncodedInst:
++stats::EmittedCompactEncodedInstFragments;
- OW->writeBytes(cast<MCCompactEncodedInstFragment>(F).getContents());
+ OS << cast<MCCompactEncodedInstFragment>(F).getContents();
break;
case MCFragment::FT_Fill: {
++stats::EmittedFillFragments;
const MCFillFragment &FF = cast<MCFillFragment>(F);
- uint8_t V = FF.getValue();
+ uint64_t V = FF.getValue();
+ unsigned VSize = FF.getValueSize();
const unsigned MaxChunkSize = 16;
char Data[MaxChunkSize];
- memcpy(Data, &V, 1);
- for (unsigned I = 1; I < MaxChunkSize; ++I)
- Data[I] = Data[0];
-
- uint64_t Size = FragmentSize;
- for (unsigned ChunkSize = MaxChunkSize; ChunkSize; ChunkSize /= 2) {
- StringRef Ref(Data, ChunkSize);
- for (uint64_t I = 0, E = Size / ChunkSize; I != E; ++I)
- OW->writeBytes(Ref);
- Size = Size % ChunkSize;
+ // 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) {
+ unsigned index = Endian == support::little ? I : (VSize - I - 1);
+ Data[I] = uint8_t(V >> (index * 8));
}
+ for (unsigned I = VSize; I < MaxChunkSize; ++I)
+ Data[I] = Data[I - VSize];
+
+ // Set to largest multiple of VSize in Data.
+ const unsigned NumPerChunk = MaxChunkSize / VSize;
+ // Set ChunkSize to largest multiple of VSize in Data
+ const unsigned ChunkSize = VSize * NumPerChunk;
+
+ // Do copies by chunk.
+ StringRef Ref(Data, ChunkSize);
+ for (uint64_t I = 0, E = FragmentSize / ChunkSize; I != E; ++I)
+ OS << Ref;
+
+ // do remainder if needed.
+ unsigned TrailingCount = FragmentSize % ChunkSize;
+ if (TrailingCount)
+ OS.write(Data, TrailingCount);
break;
}
case MCFragment::FT_LEB: {
const MCLEBFragment &LF = cast<MCLEBFragment>(F);
- OW->writeBytes(LF.getContents());
+ OS << LF.getContents();
break;
}
case MCFragment::FT_Padding: {
- if (!Asm.getBackend().writeNopData(FragmentSize, OW))
+ if (!Asm.getBackend().writeNopData(OS, FragmentSize))
report_fatal_error("unable to write nop sequence of " +
Twine(FragmentSize) + " bytes");
break;
@@ -575,7 +613,7 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
case MCFragment::FT_SymbolId: {
const MCSymbolIdFragment &SF = cast<MCSymbolIdFragment>(F);
- OW->write32(SF.getSymbol()->getIndex());
+ support::endian::write<uint32_t>(OS, SF.getSymbol()->getIndex(), Endian);
break;
}
@@ -584,41 +622,43 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCOrgFragment &OF = cast<MCOrgFragment>(F);
for (uint64_t i = 0, e = FragmentSize; i != e; ++i)
- OW->write8(uint8_t(OF.getValue()));
+ OS << char(OF.getValue());
break;
}
case MCFragment::FT_Dwarf: {
const MCDwarfLineAddrFragment &OF = cast<MCDwarfLineAddrFragment>(F);
- OW->writeBytes(OF.getContents());
+ OS << OF.getContents();
break;
}
case MCFragment::FT_DwarfFrame: {
const MCDwarfCallFrameFragment &CF = cast<MCDwarfCallFrameFragment>(F);
- OW->writeBytes(CF.getContents());
+ OS << CF.getContents();
break;
}
case MCFragment::FT_CVInlineLines: {
const auto &OF = cast<MCCVInlineLineTableFragment>(F);
- OW->writeBytes(OF.getContents());
+ OS << OF.getContents();
break;
}
case MCFragment::FT_CVDefRange: {
const auto &DRF = cast<MCCVDefRangeFragment>(F);
- OW->writeBytes(DRF.getContents());
+ OS << DRF.getContents();
break;
}
case MCFragment::FT_Dummy:
llvm_unreachable("Should not have been added");
}
- assert(OW->getStream().tell() - Start == FragmentSize &&
+ assert(OS.tell() - Start == FragmentSize &&
"The stream should advance by fragment size");
}
-void MCAssembler::writeSectionData(const MCSection *Sec,
+void MCAssembler::writeSectionData(raw_ostream &OS, const MCSection *Sec,
const MCAsmLayout &Layout) const {
+ assert(getBackendPtr() && "Expected assembler backend");
+
// Ignore virtual sections.
if (Sec->isVirtualSection()) {
assert(Layout.getSectionFileSize(Sec) == 0 && "Invalid size for section!");
@@ -661,14 +701,13 @@ void MCAssembler::writeSectionData(const MCSection *Sec,
return;
}
- uint64_t Start = getWriter().getStream().tell();
+ uint64_t Start = OS.tell();
(void)Start;
for (const MCFragment &F : *Sec)
- writeFragment(*this, Layout, F);
+ writeFragment(OS, *this, Layout, F);
- assert(getWriter().getStream().tell() - Start ==
- Layout.getSectionAddressSize(Sec));
+ assert(OS.tell() - Start == Layout.getSectionAddressSize(Sec));
}
std::tuple<MCValue, uint64_t, bool>
@@ -677,17 +716,39 @@ MCAssembler::handleFixup(const MCAsmLayout &Layout, MCFragment &F,
// Evaluate the fixup.
MCValue Target;
uint64_t FixedValue;
- bool IsResolved = evaluateFixup(Layout, Fixup, &F, Target, FixedValue);
+ bool WasForced;
+ bool IsResolved = evaluateFixup(Layout, Fixup, &F, Target, FixedValue,
+ WasForced);
if (!IsResolved) {
// The fixup was unresolved, we need a relocation. Inform the object
// writer of the relocation, and give it an opportunity to adjust the
// fixup value if need be.
- getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, FixedValue);
+ if (Target.getSymA() && Target.getSymB() &&
+ getBackend().requiresDiffExpressionRelocations()) {
+ // The fixup represents the difference between two symbols, which the
+ // backend has indicated must be resolved at link time. Split up the fixup
+ // into two relocations, one for the add, and one for the sub, and emit
+ // both of these. The constant will be associated with the add half of the
+ // expression.
+ MCFixup FixupAdd = MCFixup::createAddFor(Fixup);
+ MCValue TargetAdd =
+ MCValue::get(Target.getSymA(), nullptr, Target.getConstant());
+ getWriter().recordRelocation(*this, Layout, &F, FixupAdd, TargetAdd,
+ FixedValue);
+ MCFixup FixupSub = MCFixup::createSubFor(Fixup);
+ MCValue TargetSub = MCValue::get(Target.getSymB());
+ getWriter().recordRelocation(*this, Layout, &F, FixupSub, TargetSub,
+ FixedValue);
+ } else {
+ getWriter().recordRelocation(*this, Layout, &F, Fixup, Target,
+ FixedValue);
+ }
}
return std::make_tuple(Target, FixedValue, IsResolved);
}
void MCAssembler::layout(MCAsmLayout &Layout) {
+ assert(getBackendPtr() && "Expected assembler backend");
DEBUG_WITH_TYPE("mc-dump", {
errs() << "assembler backend - pre-layout\n--\n";
dump(); });
@@ -747,12 +808,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();
@@ -765,7 +831,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);
}
}
}
@@ -776,35 +842,33 @@ void MCAssembler::Finish() {
MCAsmLayout Layout(*this);
layout(Layout);
- raw_ostream &OS = getWriter().getStream();
- uint64_t StartOffset = OS.tell();
-
// Write the object file.
- getWriter().writeObject(*this, Layout);
-
- stats::ObjectBytes += OS.tell() - StartOffset;
+ stats::ObjectBytes += getWriter().writeObject(*this, Layout);
}
bool MCAssembler::fixupNeedsRelaxation(const MCFixup &Fixup,
const MCRelaxableFragment *DF,
const MCAsmLayout &Layout) const {
+ assert(getBackendPtr() && "Expected assembler backend");
MCValue Target;
uint64_t Value;
- bool Resolved = evaluateFixup(Layout, Fixup, DF, Target, Value);
+ bool WasForced;
+ bool Resolved = evaluateFixup(Layout, Fixup, DF, Target, Value, WasForced);
if (Target.getSymA() &&
Target.getSymA()->getKind() == MCSymbolRefExpr::VK_X86_ABS8 &&
Fixup.getKind() == FK_Data_1)
return false;
return getBackend().fixupNeedsRelaxationAdvanced(Fixup, Resolved, Value, DF,
- Layout);
+ Layout, WasForced);
}
bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F,
const MCAsmLayout &Layout) const {
+ assert(getBackendPtr() && "Expected assembler backend");
// 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())
@@ -816,6 +880,8 @@ bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F,
bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
MCRelaxableFragment &F) {
+ assert(getEmitterPtr() &&
+ "Expected CodeEmitter defined for relaxInstruction");
if (!fragmentNeedsRelaxation(&F, Layout))
return false;
@@ -827,7 +893,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.
//
@@ -836,7 +902,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);
@@ -848,6 +914,7 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
bool MCAssembler::relaxPaddingFragment(MCAsmLayout &Layout,
MCPaddingFragment &PF) {
+ assert(getBackendPtr() && "Expected assembler backend");
uint64_t OldSize = PF.getSize();
if (!getBackend().relaxFragment(&PF, Layout))
return false;
@@ -868,10 +935,14 @@ bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) {
SmallString<8> &Data = LF.getContents();
Data.clear();
raw_svector_ostream OSE(Data);
+ // The compiler can generate EH table assembly that is impossible to assemble
+ // without either adding padding to an LEB fragment or adding extra padding
+ // to a later alignment fragment. To accommodate such tables, relaxation can
+ // only increase an LEB fragment size here, not decrease it. See PR35809.
if (LF.isSigned())
- encodeSLEB128(Value, OSE);
+ encodeSLEB128(Value, OSE, OldSize);
else
- encodeULEB128(Value, OSE);
+ encodeULEB128(Value, OSE, OldSize);
return OldSize != LF.getContents().size();
}
@@ -988,6 +1059,7 @@ bool MCAssembler::layoutOnce(MCAsmLayout &Layout) {
}
void MCAssembler::finishLayout(MCAsmLayout &Layout) {
+ assert(getBackendPtr() && "Expected assembler backend");
// 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];
@@ -996,3 +1068,27 @@ void MCAssembler::finishLayout(MCAsmLayout &Layout) {
}
getBackend().finishLayout(*this, Layout);
}
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void MCAssembler::dump() const{
+ raw_ostream &OS = errs();
+
+ OS << "<MCAssembler\n";
+ OS << " Sections:[\n ";
+ for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+ if (it != begin()) OS << ",\n ";
+ it->dump();
+ }
+ OS << "],\n";
+ OS << " Symbols:[";
+
+ for (const_symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) {
+ if (it != symbol_begin()) OS << ",\n ";
+ OS << "(";
+ it->dump();
+ OS << ", Index:" << it->getIndex() << ", ";
+ OS << ")";
+ }
+ OS << "]>\n";
+}
+#endif
diff --git a/contrib/llvm/lib/MC/MCCodeView.cpp b/contrib/llvm/lib/MC/MCCodeView.cpp
index 5fd5bde9f1eb..155fd7eeb576 100644
--- a/contrib/llvm/lib/MC/MCCodeView.cpp
+++ b/contrib/llvm/lib/MC/MCCodeView.cpp
@@ -472,6 +472,19 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
if (Locs.empty())
return;
+ // Check that the locations are all in the same section.
+#ifndef NDEBUG
+ const MCSection *FirstSec = &Locs.front().getLabel()->getSection();
+ for (const MCCVLineEntry &Loc : Locs) {
+ if (&Loc.getLabel()->getSection() != FirstSec) {
+ errs() << ".cv_loc " << Loc.getFunctionId() << ' ' << Loc.getFileNum()
+ << ' ' << Loc.getLine() << ' ' << Loc.getColumn()
+ << " is in the wrong section\n";
+ llvm_unreachable(".cv_loc crosses sections");
+ }
+ }
+#endif
+
// Make an artificial start location using the function start and the inlinee
// lines start location information. All deltas start relative to this
// location.
@@ -576,7 +589,7 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
if (!LocAfter.empty()) {
// Only try to compute this difference if we're in the same section.
const MCCVLineEntry &Loc = LocAfter[0];
- if (&Loc.getLabel()->getSection(false) == &LastLabel->getSection(false))
+ if (&Loc.getLabel()->getSection() == &LastLabel->getSection())
LocAfterLength = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
}
@@ -619,7 +632,7 @@ void CodeViewContext::encodeDefRange(MCAsmLayout &Layout,
}
unsigned NumGaps = J - I - 1;
- support::endian::Writer<support::little> LEWriter(OS);
+ support::endian::Writer LEWriter(OS, support::little);
unsigned Bias = 0;
// We must split the range into chunks of MaxDefRange, this is a fundamental
diff --git a/contrib/llvm/lib/MC/MCContext.cpp b/contrib/llvm/lib/MC/MCContext.cpp
index 5c25e902bbe7..606da2526890 100644
--- a/contrib/llvm/lib/MC/MCContext.cpp
+++ b/contrib/llvm/lib/MC/MCContext.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCContext.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
@@ -104,6 +105,7 @@ void MCContext::reset() {
MachOUniquingMap.clear();
ELFUniquingMap.clear();
COFFUniquingMap.clear();
+ WasmUniquingMap.clear();
NextID.clear();
AllowTemporaryLabels = true;
@@ -490,8 +492,10 @@ MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind K,
const Twine &Group, unsigned UniqueID,
const char *BeginSymName) {
MCSymbolWasm *GroupSym = nullptr;
- if (!Group.isTriviallyEmpty() && !Group.str().empty())
+ if (!Group.isTriviallyEmpty() && !Group.str().empty()) {
GroupSym = cast<MCSymbolWasm>(getOrCreateSymbol(Group));
+ GroupSym->setComdat(true);
+ }
return getWasmSection(Section, K, GroupSym, UniqueID, BeginSymName);
}
@@ -512,13 +516,18 @@ MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind Kind,
StringRef CachedName = Entry.first.SectionName;
- MCSymbol *Begin = nullptr;
- if (BeginSymName)
- Begin = createTempSymbol(BeginSymName, false);
+ MCSymbol *Begin = createSymbol(CachedName, false, false);
+ cast<MCSymbolWasm>(Begin)->setType(wasm::WASM_SYMBOL_TYPE_SECTION);
MCSectionWasm *Result = new (WasmAllocator.Allocate())
MCSectionWasm(CachedName, Kind, GroupSym, UniqueID, Begin);
Entry.second = Result;
+
+ auto *F = new MCDataFragment();
+ Result->getFragmentList().insert(Result->begin(), F);
+ F->setParent(Result);
+ Begin->setFragment(F);
+
return Result;
}
@@ -526,28 +535,61 @@ MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) {
return *new (MCSubtargetAllocator.Allocate()) MCSubtargetInfo(STI);
}
+void MCContext::addDebugPrefixMapEntry(const std::string &From,
+ const std::string &To) {
+ DebugPrefixMap.insert(std::make_pair(From, To));
+}
+
+void MCContext::RemapDebugPaths() {
+ const auto &DebugPrefixMap = this->DebugPrefixMap;
+ const auto RemapDebugPath = [&DebugPrefixMap](std::string &Path) {
+ for (const auto &Entry : DebugPrefixMap)
+ if (StringRef(Path).startswith(Entry.first)) {
+ std::string RemappedPath =
+ (Twine(Entry.second) + Path.substr(Entry.first.size())).str();
+ Path.swap(RemappedPath);
+ }
+ };
+
+ // Remap compilation directory.
+ std::string CompDir = CompilationDir.str();
+ RemapDebugPath(CompDir);
+ CompilationDir = CompDir;
+
+ // Remap MCDwarfDirs in all compilation units.
+ for (auto &CUIDTablePair : MCDwarfLineTablesCUMap)
+ for (auto &Dir : CUIDTablePair.second.getMCDwarfDirs())
+ RemapDebugPath(Dir);
+}
+
//===----------------------------------------------------------------------===//
// Dwarf Management
//===----------------------------------------------------------------------===//
-/// getDwarfFile - takes a file name an number to place in the dwarf file and
+/// getDwarfFile - takes a file name and number to place in the dwarf file and
/// directory tables. If the file number has already been allocated it is an
/// error and zero is returned and the client reports the error, else the
/// allocated file number is returned. The file numbers may be in any order.
-unsigned MCContext::getDwarfFile(StringRef Directory, StringRef FileName,
- unsigned FileNumber, unsigned CUID) {
+Expected<unsigned> MCContext::getDwarfFile(StringRef Directory,
+ StringRef FileName,
+ unsigned FileNumber,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> Source,
+ unsigned CUID) {
MCDwarfLineTable &Table = MCDwarfLineTablesCUMap[CUID];
- return Table.getFile(Directory, FileName, FileNumber);
+ return Table.tryGetFile(Directory, FileName, Checksum, Source, FileNumber);
}
/// isValidDwarfFileNumber - takes a dwarf file number and returns true if it
/// currently is assigned and false otherwise.
bool MCContext::isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID) {
- const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles = getMCDwarfFiles(CUID);
- if (FileNumber == 0 || FileNumber >= MCDwarfFiles.size())
+ const MCDwarfLineTable &LineTable = getMCDwarfLineTable(CUID);
+ if (FileNumber == 0)
+ return getDwarfVersion() >= 5 && LineTable.hasRootFile();
+ if (FileNumber >= LineTable.getMCDwarfFiles().size())
return false;
- return !MCDwarfFiles[FileNumber].Name.empty();
+ return !LineTable.getMCDwarfFiles()[FileNumber].Name.empty();
}
/// Remove empty sections from SectionStartEndSyms, to avoid generating
@@ -563,6 +605,11 @@ CodeViewContext &MCContext::getCVContext() {
return *CVContext.get();
}
+void MCContext::clearCVLocSeen() {
+ if (CVContext)
+ CVContext->clearCVLocSeen();
+}
+
//===----------------------------------------------------------------------===//
// Error Reporting
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp
index ef1d8335e1bd..30e0bb562644 100644
--- a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp
@@ -130,7 +130,7 @@ void LLVMDisasmDispose(LLVMDisasmContextRef DCR){
delete DC;
}
-/// \brief Emits the comments that are stored in \p DC comment stream.
+/// Emits the comments that are stored in \p DC comment stream.
/// Each comment in the comment stream must end with a newline.
static void emitComments(LLVMDisasmContext *DC,
formatted_raw_ostream &FormattedOS) {
@@ -158,7 +158,7 @@ static void emitComments(LLVMDisasmContext *DC,
DC->CommentsToEmit.clear();
}
-/// \brief Gets latency information for \p Inst from the itinerary
+/// Gets latency information for \p Inst from the itinerary
/// scheduling model, based on \p DC information.
/// \return The maximum expected latency over all the operands or -1
/// if no information is available.
@@ -184,7 +184,7 @@ static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
return Latency;
}
-/// \brief Gets latency information for \p Inst, based on \p DC information.
+/// Gets latency information for \p Inst, based on \p DC information.
/// \return The maximum expected latency over all the definitions or -1
/// if no information is available.
static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
@@ -209,7 +209,7 @@ static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
return NoInformationAvailable;
// Compute output latency.
- int Latency = 0;
+ int16_t Latency = 0;
for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
DefIdx != DefEnd; ++DefIdx) {
// Lookup the definition's write latency in SubtargetInfo.
@@ -221,7 +221,7 @@ static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
return Latency;
}
-/// \brief Emits latency information in DC->CommentStream for \p Inst, based
+/// Emits latency information in DC->CommentStream for \p Inst, based
/// on the information available in \p DC.
static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
int Latency = getLatency(DC, Inst);
diff --git a/contrib/llvm/lib/MC/MCDwarf.cpp b/contrib/llvm/lib/MC/MCDwarf.cpp
index 9e5d9ff73c76..6131fcd658b2 100644
--- a/contrib/llvm/lib/MC/MCDwarf.cpp
+++ b/contrib/llvm/lib/MC/MCDwarf.cpp
@@ -11,7 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -28,6 +28,7 @@
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
@@ -45,6 +46,29 @@
using namespace llvm;
+/// Manage the .debug_line_str section contents, if we use it.
+class llvm::MCDwarfLineStr {
+ MCSymbol *LineStrLabel = nullptr;
+ StringTableBuilder LineStrings{StringTableBuilder::DWARF};
+ bool UseRelocs = false;
+
+public:
+ /// Construct an instance that can emit .debug_line_str (for use in a normal
+ /// v5 line table).
+ explicit MCDwarfLineStr(MCContext &Ctx) {
+ UseRelocs = Ctx.getAsmInfo()->doesDwarfUseRelocationsAcrossSections();
+ if (UseRelocs)
+ LineStrLabel =
+ Ctx.getObjectFileInfo()->getDwarfLineStrSection()->getBeginSymbol();
+ }
+
+ /// Emit a reference to the string.
+ void emitRef(MCStreamer *MCOS, StringRef Path);
+
+ /// Emit the .debug_line_str section if appropriate.
+ void emitSection(MCStreamer *MCOS);
+};
+
static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) {
unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment();
if (MinInsnLength == 1)
@@ -108,6 +132,18 @@ static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS,
}
//
+// This helper routine returns an expression of Start + IntVal .
+//
+static inline const MCExpr *
+makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) {
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+ const MCExpr *LHS = MCSymbolRefExpr::create(&Start, Variant, Ctx);
+ const MCExpr *RHS = MCConstantExpr::create(IntVal, Ctx);
+ const MCExpr *Res = MCBinaryExpr::create(MCBinaryExpr::Add, LHS, RHS, Ctx);
+ return Res;
+}
+
+//
// This emits the Dwarf line table for the specified section from the entries
// in the LineSection.
//
@@ -205,22 +241,35 @@ void MCDwarfLineTable::Emit(MCObjectStreamer *MCOS,
if (LineTables.empty())
return;
+ // In a v5 non-split line table, put the strings in a separate section.
+ Optional<MCDwarfLineStr> LineStr;
+ if (context.getDwarfVersion() >= 5)
+ LineStr = MCDwarfLineStr(context);
+
// Switch to the section where the table will be emitted into.
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());
// Handle the rest of the Compile Units.
- for (const auto &CUIDTablePair : LineTables)
- CUIDTablePair.second.EmitCU(MCOS, Params);
+ for (const auto &CUIDTablePair : LineTables) {
+ CUIDTablePair.second.EmitCU(MCOS, Params, LineStr);
+ }
+
+ if (LineStr)
+ LineStr->emitSection(MCOS);
}
-void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS,
- MCDwarfLineTableParams Params) const {
- MCOS.EmitLabel(Header.Emit(&MCOS, Params, None).second);
+void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
+ MCSection *Section) const {
+ if (Header.MCDwarfFiles.empty())
+ return;
+ Optional<MCDwarfLineStr> NoLineStr(None);
+ MCOS.SwitchSection(Section);
+ MCOS.EmitLabel(Header.Emit(&MCOS, Params, None, NoLineStr).second);
}
std::pair<MCSymbol *, MCSymbol *>
-MCDwarfLineTableHeader::Emit(MCStreamer *MCOS,
- MCDwarfLineTableParams Params) const {
+MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
+ Optional<MCDwarfLineStr> &LineStr) const {
static const char StandardOpcodeLengths[] = {
0, // length of DW_LNS_copy
1, // length of DW_LNS_advance_pc
@@ -237,8 +286,10 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS,
};
assert(array_lengthof(StandardOpcodeLengths) >=
(Params.DWARF2LineOpcodeBase - 1U));
- return Emit(MCOS, Params, makeArrayRef(StandardOpcodeLengths,
- Params.DWARF2LineOpcodeBase - 1));
+ return Emit(
+ MCOS, Params,
+ makeArrayRef(StandardOpcodeLengths, Params.DWARF2LineOpcodeBase - 1),
+ LineStr);
}
static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) {
@@ -257,12 +308,31 @@ static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) {
OS.EmitValue(ABS, Size);
}
-static void
-emitV2FileDirTables(MCStreamer *MCOS,
- const SmallVectorImpl<std::string> &MCDwarfDirs,
- const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles) {
+void MCDwarfLineStr::emitSection(MCStreamer *MCOS) {
+ // Switch to the .debug_line_str section.
+ MCOS->SwitchSection(
+ MCOS->getContext().getObjectFileInfo()->getDwarfLineStrSection());
+ // Emit the strings without perturbing the offsets we used.
+ LineStrings.finalizeInOrder();
+ SmallString<0> Data;
+ Data.resize(LineStrings.getSize());
+ LineStrings.write((uint8_t *)Data.data());
+ MCOS->EmitBinaryData(Data.str());
+}
+
+void MCDwarfLineStr::emitRef(MCStreamer *MCOS, StringRef Path) {
+ int RefSize = 4; // FIXME: Support DWARF-64
+ size_t Offset = LineStrings.add(Path);
+ if (UseRelocs) {
+ MCContext &Ctx = MCOS->getContext();
+ MCOS->EmitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset), RefSize);
+ } else
+ MCOS->EmitIntValue(Offset, RefSize);
+}
+
+void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const {
// First the directory table.
- for (auto Dir : MCDwarfDirs) {
+ for (auto &Dir : MCDwarfDirs) {
MCOS->EmitBytes(Dir); // The DirectoryName, and...
MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
}
@@ -280,46 +350,101 @@ emitV2FileDirTables(MCStreamer *MCOS,
MCOS->EmitIntValue(0, 1); // Terminate the file list.
}
-static void
-emitV5FileDirTables(MCStreamer *MCOS,
- const SmallVectorImpl<std::string> &MCDwarfDirs,
- const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles,
- StringRef CompilationDir) {
- // The directory format, which is just inline null-terminated strings.
+static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
+ bool EmitMD5, bool HasSource,
+ Optional<MCDwarfLineStr> &LineStr) {
+ assert(!DwarfFile.Name.empty());
+ if (LineStr)
+ LineStr->emitRef(MCOS, DwarfFile.Name);
+ else {
+ MCOS->EmitBytes(DwarfFile.Name); // FileName and...
+ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ }
+ MCOS->EmitULEB128IntValue(DwarfFile.DirIndex); // Directory number.
+ if (EmitMD5) {
+ MD5::MD5Result *Cksum = DwarfFile.Checksum;
+ MCOS->EmitBinaryData(
+ StringRef(reinterpret_cast<const char *>(Cksum->Bytes.data()),
+ Cksum->Bytes.size()));
+ }
+ if (HasSource) {
+ if (LineStr)
+ LineStr->emitRef(MCOS, DwarfFile.Source.getValueOr(StringRef()));
+ else {
+ MCOS->EmitBytes(
+ DwarfFile.Source.getValueOr(StringRef())); // Source and...
+ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ }
+ }
+}
+
+void MCDwarfLineTableHeader::emitV5FileDirTables(
+ MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr,
+ StringRef CtxCompilationDir) const {
+ // The directory format, which is just a list of the directory paths. In a
+ // non-split object, these are references to .debug_line_str; in a split
+ // object, they are inline strings.
MCOS->EmitIntValue(1, 1);
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
- MCOS->EmitULEB128IntValue(dwarf::DW_FORM_string);
- // Then the list of directory paths. CompilationDir comes first.
+ MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
+ : dwarf::DW_FORM_string);
MCOS->EmitULEB128IntValue(MCDwarfDirs.size() + 1);
- MCOS->EmitBytes(CompilationDir);
- MCOS->EmitBytes(StringRef("\0", 1));
- for (auto Dir : MCDwarfDirs) {
- MCOS->EmitBytes(Dir); // The DirectoryName, and...
- MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ // Try not to emit an empty compilation directory.
+ const StringRef CompDir =
+ CompilationDir.empty() ? CtxCompilationDir : StringRef(CompilationDir);
+ if (LineStr) {
+ // Record path strings, emit references here.
+ LineStr->emitRef(MCOS, CompDir);
+ for (const auto &Dir : MCDwarfDirs)
+ LineStr->emitRef(MCOS, Dir);
+ } else {
+ // The list of directory paths. Compilation directory comes first.
+ MCOS->EmitBytes(CompDir);
+ MCOS->EmitBytes(StringRef("\0", 1));
+ for (const auto &Dir : MCDwarfDirs) {
+ MCOS->EmitBytes(Dir); // The DirectoryName, and...
+ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ }
}
// The file format, which is the inline null-terminated filename and a
// directory index. We don't track file size/timestamp so don't emit them
- // in the v5 table.
- // FIXME: Arrange to emit MD5 signatures for the source files.
- MCOS->EmitIntValue(2, 1);
+ // in the v5 table. Emit MD5 checksums and source if we have them.
+ uint64_t Entries = 2;
+ if (HasAllMD5)
+ Entries += 1;
+ if (HasSource)
+ Entries += 1;
+ MCOS->EmitIntValue(Entries, 1);
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
- MCOS->EmitULEB128IntValue(dwarf::DW_FORM_string);
+ MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
+ : dwarf::DW_FORM_string);
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_directory_index);
MCOS->EmitULEB128IntValue(dwarf::DW_FORM_udata);
- // Then the list of file names. These start at 1 for some reason.
- MCOS->EmitULEB128IntValue(MCDwarfFiles.size() - 1);
- for (unsigned i = 1; i < MCDwarfFiles.size(); ++i) {
- assert(!MCDwarfFiles[i].Name.empty());
- MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName and...
- MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
- MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.
+ if (HasAllMD5) {
+ MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_MD5);
+ MCOS->EmitULEB128IntValue(dwarf::DW_FORM_data16);
+ }
+ if (HasSource) {
+ MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
+ MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
+ : dwarf::DW_FORM_string);
}
+ // Then the counted list of files. The root file is file #0, then emit the
+ // files as provide by .file directives. To accommodate assembler source
+ // written for DWARF v4 but trying to emit v5, if we didn't see a root file
+ // explicitly, replicate file #1.
+ MCOS->EmitULEB128IntValue(MCDwarfFiles.size());
+ emitOneV5FileEntry(MCOS, RootFile.Name.empty() ? MCDwarfFiles[1] : RootFile,
+ HasAllMD5, HasSource, LineStr);
+ for (unsigned i = 1; i < MCDwarfFiles.size(); ++i)
+ emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasSource, LineStr);
}
std::pair<MCSymbol *, MCSymbol *>
MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
- ArrayRef<char> StandardOpcodeLengths) const {
+ ArrayRef<char> StandardOpcodeLengths,
+ Optional<MCDwarfLineStr> &LineStr) const {
MCContext &context = MCOS->getContext();
// Create a symbol at the beginning of the line table.
@@ -384,9 +509,9 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
// Put out the directory and file tables. The formats vary depending on
// the version.
if (LineTableVersion >= 5)
- emitV5FileDirTables(MCOS, MCDwarfDirs, MCDwarfFiles, CompilationDir);
+ emitV5FileDirTables(MCOS, LineStr, context.getCompilationDir());
else
- emitV2FileDirTables(MCOS, MCDwarfDirs, MCDwarfFiles);
+ emitV2FileDirTables(MCOS);
// This is the end of the prologue, so set the value of the symbol at the
// end of the prologue (that was used in a previous expression).
@@ -396,8 +521,9 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
}
void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS,
- MCDwarfLineTableParams Params) const {
- MCSymbol *LineEndSym = Header.Emit(MCOS, Params).second;
+ MCDwarfLineTableParams Params,
+ Optional<MCDwarfLineStr> &LineStr) const {
+ MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
// Put out the line tables.
for (const auto &LineSec : MCLineSections.getMCLineEntries())
@@ -408,14 +534,20 @@ void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS,
MCOS->EmitLabel(LineEndSym);
}
-unsigned MCDwarfLineTable::getFile(StringRef &Directory, StringRef &FileName,
- unsigned FileNumber) {
- return Header.getFile(Directory, FileName, FileNumber);
+Expected<unsigned> MCDwarfLineTable::tryGetFile(StringRef &Directory,
+ StringRef &FileName,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> Source,
+ unsigned FileNumber) {
+ return Header.tryGetFile(Directory, FileName, Checksum, Source, FileNumber);
}
-unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory,
- StringRef &FileName,
- unsigned FileNumber) {
+Expected<unsigned>
+MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
+ StringRef &FileName,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> &Source,
+ unsigned FileNumber) {
if (Directory == CompilationDir)
Directory = "";
if (FileName.empty()) {
@@ -423,6 +555,12 @@ unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory,
Directory = "";
}
assert(!FileName.empty());
+ // Keep track of whether any or all files have an MD5 checksum.
+ // If any files have embedded source, they all must.
+ if (MCDwarfFiles.empty()) {
+ trackMD5Usage(Checksum);
+ HasSource = (Source != None);
+ }
if (FileNumber == 0) {
// File numbers start with 1 and/or after any file numbers
// allocated by inline-assembler .file directives.
@@ -441,9 +579,15 @@ unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory,
// Get the new MCDwarfFile slot for this FileNumber.
MCDwarfFile &File = MCDwarfFiles[FileNumber];
- // It is an error to use see the same number more than once.
+ // It is an error to see the same number more than once.
if (!File.Name.empty())
- return 0;
+ return make_error<StringError>("file number already allocated",
+ inconvertibleErrorCode());
+
+ // If any files have embedded source, they all must.
+ if (HasSource != (Source != None))
+ return make_error<StringError>("inconsistent use of embedded source",
+ inconvertibleErrorCode());
if (Directory.empty()) {
// Separate the directory part from the basename of the FileName.
@@ -478,6 +622,11 @@ unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory,
File.Name = FileName;
File.DirIndex = DirIndex;
+ File.Checksum = Checksum;
+ trackMD5Usage(Checksum);
+ File.Source = Source;
+ if (Source)
+ HasSource = true;
// return the allocated FileNumber.
return FileNumber;
@@ -1653,6 +1802,8 @@ void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context,
// Scale the address delta by the minimum instruction length.
AddrDelta = ScaleAddrDelta(Context, AddrDelta);
+ support::endianness E =
+ Context.getAsmInfo()->isLittleEndian() ? support::little : support::big;
if (AddrDelta == 0) {
} else if (isUIntN(6, AddrDelta)) {
uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
@@ -1662,16 +1813,10 @@ void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context,
OS << uint8_t(AddrDelta);
} else if (isUInt<16>(AddrDelta)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc2);
- if (Context.getAsmInfo()->isLittleEndian())
- support::endian::Writer<support::little>(OS).write<uint16_t>(AddrDelta);
- else
- support::endian::Writer<support::big>(OS).write<uint16_t>(AddrDelta);
+ support::endian::write<uint16_t>(OS, AddrDelta, E);
} else {
assert(isUInt<32>(AddrDelta));
OS << uint8_t(dwarf::DW_CFA_advance_loc4);
- if (Context.getAsmInfo()->isLittleEndian())
- support::endian::Writer<support::little>(OS).write<uint32_t>(AddrDelta);
- else
- support::endian::Writer<support::big>(OS).write<uint32_t>(AddrDelta);
+ support::endian::write<uint32_t>(OS, AddrDelta, E);
}
}
diff --git a/contrib/llvm/lib/MC/MCELFStreamer.cpp b/contrib/llvm/lib/MC/MCELFStreamer.cpp
index 6b1c589f0389..95b48e6abc74 100644
--- a/contrib/llvm/lib/MC/MCELFStreamer.cpp
+++ b/contrib/llvm/lib/MC/MCELFStreamer.cpp
@@ -41,9 +41,10 @@ using namespace llvm;
MCELFStreamer::MCELFStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> TAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> OW,
std::unique_ptr<MCCodeEmitter> Emitter)
- : MCObjectStreamer(Context, std::move(TAB), OS, std::move(Emitter)) {}
+ : MCObjectStreamer(Context, std::move(TAB), std::move(OW),
+ std::move(Emitter)) {}
bool MCELFStreamer::isBundleLocked() const {
return getCurrentSectionOnly()->isBundleLocked();
@@ -68,13 +69,8 @@ void MCELFStreamer::mergeFragment(MCDataFragment *DF,
if (RequiredBundlePadding > 0) {
SmallString<256> Code;
raw_svector_ostream VecOS(Code);
- {
- auto OW = Assembler.getBackend().createObjectWriter(VecOS);
-
- EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
-
- Assembler.writeFragmentPadding(*EF, FSize, OW.get());
- }
+ EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
+ Assembler.writeFragmentPadding(VecOS, *EF, FSize);
DF->getContents().append(Code.begin(), Code.end());
}
@@ -87,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());
}
@@ -192,17 +189,6 @@ static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) {
bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
auto *Symbol = cast<MCSymbolELF>(S);
- // Indirect symbols are handled differently, to match how 'as' handles
- // them. This makes writing matching .o files easier.
- if (Attribute == MCSA_IndirectSymbol) {
- // Note that we intentionally cannot use the symbol data here; this is
- // important for matching the string table that 'as' generates.
- IndirectSymbolData ISD;
- ISD.Symbol = Symbol;
- ISD.Section = getCurrentSectionOnly();
- getAssembler().getIndirectSymbols().push_back(ISD);
- return true;
- }
// Adding a symbol attribute always introduces the symbol, note that an
// important side effect of calling registerSymbol here is to register
@@ -370,6 +356,12 @@ void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment,
ValueSize, MaxBytesToEmit);
}
+void MCELFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To,
+ uint64_t Count) {
+ getAssembler().CGProfile.push_back({From, To, Count});
+}
+
void MCELFStreamer::EmitIdent(StringRef IdentString) {
MCSection *Comment = getAssembler().getContext().getELFSection(
".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, "");
@@ -419,6 +411,8 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
case MCSymbolRefExpr::VK_PPC_TPREL_LO:
case MCSymbolRefExpr::VK_PPC_TPREL_HI:
case MCSymbolRefExpr::VK_PPC_TPREL_HA:
+ case MCSymbolRefExpr::VK_PPC_TPREL_HIGH:
+ case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA:
case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
@@ -426,6 +420,8 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
+ case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH:
+ case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA:
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
@@ -462,6 +458,37 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
}
}
+void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) {
+ const MCSymbol *S = &SRE->getSymbol();
+ if (S->isTemporary()) {
+ if (!S->isInSection()) {
+ getContext().reportError(
+ SRE->getLoc(), Twine("Reference to undefined temporary symbol ") +
+ "`" + S->getName() + "`");
+ return;
+ }
+ S = S->getSection().getBeginSymbol();
+ S->setUsedInReloc();
+ SRE =
+ MCSymbolRefExpr::create(S, SRE->getKind(), getContext(), SRE->getLoc());
+ return;
+ }
+ // Not a temporary, referece it as a weak undefined.
+ bool Created;
+ getAssembler().registerSymbol(*S, &Created);
+ if (Created) {
+ cast<MCSymbolELF>(S)->setBinding(ELF::STB_WEAK);
+ cast<MCSymbolELF>(S)->setExternal(true);
+ }
+}
+
+void MCELFStreamer::finalizeCGProfile() {
+ for (MCAssembler::CGProfileEntry &E : getAssembler().CGProfile) {
+ finalizeCGProfileEntry(E.From);
+ finalizeCGProfileEntry(E.To);
+ }
+}
+
void MCELFStreamer::EmitInstToFragment(const MCInst &Inst,
const MCSubtargetInfo &STI) {
this->MCObjectStreamer::EmitInstToFragment(Inst, STI);
@@ -471,6 +498,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();
@@ -486,7 +522,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
@@ -501,19 +537,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
@@ -521,6 +561,7 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst,
MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment();
insert(CEIF);
CEIF->getContents().append(Code.begin(), Code.end());
+ CEIF->setHasInstructions(STI);
return;
} else {
DF = new MCDataFragment();
@@ -538,7 +579,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.
@@ -546,12 +587,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;
}
}
@@ -611,7 +652,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;
}
@@ -627,6 +668,7 @@ void MCELFStreamer::FinishImpl() {
MCSection *CurSection = getCurrentSectionOnly();
setSectionAlignmentForBundling(getAssembler(), CurSection);
+ finalizeCGProfile();
EmitFrames(nullptr);
this->MCObjectStreamer::FinishImpl();
@@ -641,7 +683,8 @@ void MCELFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
}
void MCELFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment) {
+ uint64_t Size, unsigned ByteAlignment,
+ SMLoc Loc) {
llvm_unreachable("ELF doesn't support this directive");
}
@@ -652,11 +695,11 @@ void MCELFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
MCStreamer *llvm::createELFStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> &&MAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&CE,
bool RelaxAll) {
MCELFStreamer *S =
- new MCELFStreamer(Context, std::move(MAB), OS, std::move(CE));
+ new MCELFStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
if (RelaxAll)
S->getAssembler().setRelaxAll(true);
return S;
diff --git a/contrib/llvm/lib/MC/MCExpr.cpp b/contrib/llvm/lib/MC/MCExpr.cpp
index f8fff4414f49..0694a8fa620e 100644
--- a/contrib/llvm/lib/MC/MCExpr.cpp
+++ b/contrib/llvm/lib/MC/MCExpr.cpp
@@ -10,6 +10,8 @@
#include "llvm/MC/MCExpr.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
@@ -73,7 +75,10 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const {
case MCUnaryExpr::Not: OS << '~'; break;
case MCUnaryExpr::Plus: OS << '+'; break;
}
+ bool Binary = UE.getSubExpr()->getKind() == MCExpr::Binary;
+ if (Binary) OS << "(";
UE.getSubExpr()->print(OS, MAI);
+ if (Binary) OS << ")";
return;
}
@@ -234,6 +239,8 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_PPC_LO: return "l";
case VK_PPC_HI: return "h";
case VK_PPC_HA: return "ha";
+ case VK_PPC_HIGH: return "high";
+ case VK_PPC_HIGHA: return "higha";
case VK_PPC_HIGHER: return "higher";
case VK_PPC_HIGHERA: return "highera";
case VK_PPC_HIGHEST: return "highest";
@@ -250,6 +257,8 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_PPC_TPREL_LO: return "tprel@l";
case VK_PPC_TPREL_HI: return "tprel@h";
case VK_PPC_TPREL_HA: return "tprel@ha";
+ case VK_PPC_TPREL_HIGH: return "tprel@high";
+ case VK_PPC_TPREL_HIGHA: return "tprel@higha";
case VK_PPC_TPREL_HIGHER: return "tprel@higher";
case VK_PPC_TPREL_HIGHERA: return "tprel@highera";
case VK_PPC_TPREL_HIGHEST: return "tprel@highest";
@@ -257,6 +266,8 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_PPC_DTPREL_LO: return "dtprel@l";
case VK_PPC_DTPREL_HI: return "dtprel@h";
case VK_PPC_DTPREL_HA: return "dtprel@ha";
+ case VK_PPC_DTPREL_HIGH: return "dtprel@high";
+ case VK_PPC_DTPREL_HIGHA: return "dtprel@higha";
case VK_PPC_DTPREL_HIGHER: return "dtprel@higher";
case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera";
case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest";
@@ -298,6 +309,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi";
case VK_AMDGPU_REL32_LO: return "rel32@lo";
case VK_AMDGPU_REL32_HI: return "rel32@hi";
+ case VK_AMDGPU_REL64: return "rel64";
}
llvm_unreachable("Invalid variant kind");
}
@@ -337,6 +349,8 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("l", VK_PPC_LO)
.Case("h", VK_PPC_HI)
.Case("ha", VK_PPC_HA)
+ .Case("high", VK_PPC_HIGH)
+ .Case("higha", VK_PPC_HIGHA)
.Case("higher", VK_PPC_HIGHER)
.Case("highera", VK_PPC_HIGHERA)
.Case("highest", VK_PPC_HIGHEST)
@@ -355,6 +369,8 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("tprel@l", VK_PPC_TPREL_LO)
.Case("tprel@h", VK_PPC_TPREL_HI)
.Case("tprel@ha", VK_PPC_TPREL_HA)
+ .Case("tprel@high", VK_PPC_TPREL_HIGH)
+ .Case("tprel@higha", VK_PPC_TPREL_HIGHA)
.Case("tprel@higher", VK_PPC_TPREL_HIGHER)
.Case("tprel@highera", VK_PPC_TPREL_HIGHERA)
.Case("tprel@highest", VK_PPC_TPREL_HIGHEST)
@@ -362,6 +378,8 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("dtprel@l", VK_PPC_DTPREL_LO)
.Case("dtprel@h", VK_PPC_DTPREL_HI)
.Case("dtprel@ha", VK_PPC_DTPREL_HA)
+ .Case("dtprel@high", VK_PPC_DTPREL_HIGH)
+ .Case("dtprel@higha", VK_PPC_DTPREL_HIGHA)
.Case("dtprel@higher", VK_PPC_DTPREL_HIGHER)
.Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA)
.Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST)
@@ -399,10 +417,13 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("lo8", VK_AVR_LO8)
.Case("hi8", VK_AVR_HI8)
.Case("hlo8", VK_AVR_HLO8)
+ .Case("function", VK_WebAssembly_FUNCTION)
+ .Case("typeindex", VK_WebAssembly_TYPEINDEX)
.Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)
.Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI)
.Case("rel32@lo", VK_AMDGPU_REL32_LO)
.Case("rel32@hi", VK_AMDGPU_REL32_HI)
+ .Case("rel64", VK_AMDGPU_REL64)
.Default(VK_Invalid);
}
@@ -438,6 +459,10 @@ bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {
return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr);
}
+bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const {
+ return evaluateAsAbsolute(Res, Asm, nullptr, nullptr);
+}
+
bool MCExpr::evaluateKnownAbsolute(int64_t &Res,
const MCAsmLayout &Layout) const {
return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr,
@@ -473,7 +498,7 @@ bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
return IsRelocatable && Value.isAbsolute();
}
-/// \brief Helper method for \see EvaluateSymbolAdd().
+/// Helper method for \see EvaluateSymbolAdd().
static void AttemptToFoldSymbolOffsetDifference(
const MCAssembler *Asm, const MCAsmLayout *Layout,
const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A,
@@ -491,7 +516,7 @@ static void AttemptToFoldSymbolOffsetDifference(
return;
if (SA.getFragment() == SB.getFragment() && !SA.isVariable() &&
- !SB.isVariable()) {
+ !SA.isUnset() && !SB.isVariable() && !SB.isUnset()) {
Addend += (SA.getOffset() - SB.getOffset());
// Pointers to Thumb symbols need to have their low-bit set to allow
@@ -530,7 +555,7 @@ static void AttemptToFoldSymbolOffsetDifference(
A = B = nullptr;
}
-/// \brief Evaluate the result of an add between (conceptually) two MCValues.
+/// Evaluate the result of an add between (conceptually) two MCValues.
///
/// This routine conceptually attempts to construct an MCValue:
/// Result = (Result_A - Result_B + Result_Cst)
@@ -566,8 +591,12 @@ EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout,
assert((!Layout || Asm) &&
"Must have an assembler object if layout is given!");
- // If we have a layout, we can fold resolved differences.
- if (Asm) {
+ // If we have a layout, we can fold resolved differences. Do not do this if
+ // the backend requires this to be emitted as individual relocations, unless
+ // the InSet flag is set to get the current difference anyway (used for
+ // example to calculate symbol sizes).
+ if (Asm &&
+ (InSet || !Asm->getBackend().requiresDiffExpressionRelocations())) {
// First, fold out any differences which are fully resolved. By
// reassociating terms in
// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
@@ -749,11 +778,13 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
// Apple as.
int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
int64_t Result = 0;
- switch (ABE->getOpcode()) {
+ auto Op = ABE->getOpcode();
+ switch (Op) {
case MCBinaryExpr::AShr: Result = LHS >> RHS; break;
case MCBinaryExpr::Add: Result = LHS + RHS; break;
case MCBinaryExpr::And: Result = LHS & RHS; break;
case MCBinaryExpr::Div:
+ case MCBinaryExpr::Mod:
// Handle division by zero. gas just emits a warning and keeps going,
// we try to be stricter.
// FIXME: Currently the caller of this function has no way to understand
@@ -762,7 +793,10 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
// change this code to emit a better diagnostic.
if (RHS == 0)
return false;
- Result = LHS / RHS;
+ if (ABE->getOpcode() == MCBinaryExpr::Div)
+ Result = LHS / RHS;
+ else
+ Result = LHS % RHS;
break;
case MCBinaryExpr::EQ: Result = LHS == RHS; break;
case MCBinaryExpr::GT: Result = LHS > RHS; break;
@@ -772,7 +806,6 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break;
case MCBinaryExpr::LT: Result = LHS < RHS; break;
case MCBinaryExpr::LTE: Result = LHS <= RHS; break;
- case MCBinaryExpr::Mod: Result = LHS % RHS; break;
case MCBinaryExpr::Mul: Result = LHS * RHS; break;
case MCBinaryExpr::NE: Result = LHS != RHS; break;
case MCBinaryExpr::Or: Result = LHS | RHS; break;
@@ -781,7 +814,21 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
case MCBinaryExpr::Xor: Result = LHS ^ RHS; break;
}
- Res = MCValue::get(Result);
+ switch (Op) {
+ default:
+ Res = MCValue::get(Result);
+ break;
+ case MCBinaryExpr::EQ:
+ case MCBinaryExpr::GT:
+ case MCBinaryExpr::GTE:
+ case MCBinaryExpr::LT:
+ case MCBinaryExpr::LTE:
+ case MCBinaryExpr::NE:
+ // A comparison operator returns a -1 if true and 0 if false.
+ Res = MCValue::get(Result ? -1 : 0);
+ break;
+ }
+
return true;
}
}
diff --git a/contrib/llvm/lib/MC/MCFragment.cpp b/contrib/llvm/lib/MC/MCFragment.cpp
index 1aed50aaeb77..0ebcf21a422e 100644
--- a/contrib/llvm/lib/MC/MCFragment.cpp
+++ b/contrib/llvm/lib/MC/MCFragment.cpp
@@ -11,6 +11,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
@@ -188,7 +189,7 @@ uint64_t MCAsmLayout::getSectionFileSize(const MCSection *Sec) const {
}
uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler,
- const MCFragment *F,
+ const MCEncodedFragment *F,
uint64_t FOffset, uint64_t FSize) {
uint64_t BundleSize = Assembler.getBundleAlignSize();
assert(BundleSize > 0 &&
@@ -235,10 +236,9 @@ void ilist_alloc_traits<MCFragment>::deleteNode(MCFragment *V) { V->destroy(); }
MCFragment::~MCFragment() = default;
MCFragment::MCFragment(FragmentType Kind, bool HasInstructions,
- uint8_t BundlePadding, MCSection *Parent)
- : Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false),
- BundlePadding(BundlePadding), Parent(Parent), Atom(nullptr),
- Offset(~UINT64_C(0)) {
+ MCSection *Parent)
+ : Kind(Kind), HasInstructions(HasInstructions), Parent(Parent),
+ Atom(nullptr), Offset(~UINT64_C(0)) {
if (Parent && !isDummy())
Parent->getFragmentList().push_back(this);
}
@@ -332,10 +332,11 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break;
}
- OS << "<MCFragment " << (const void*) this << " LayoutOrder:" << LayoutOrder
- << " Offset:" << Offset
- << " HasInstructions:" << hasInstructions()
- << " BundlePadding:" << static_cast<unsigned>(getBundlePadding()) << ">";
+ OS << "<MCFragment " << (const void *)this << " LayoutOrder:" << LayoutOrder
+ << " Offset:" << Offset << " HasInstructions:" << hasInstructions();
+ if (const MCEncodedFragment *EF = dyn_cast<MCEncodedFragment>(this))
+ OS << " BundlePadding:" << static_cast<unsigned>(EF->getBundlePadding());
+ OS << ">";
switch (getKind()) {
case MCFragment::FT_Align: {
@@ -387,7 +388,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
case MCFragment::FT_Fill: {
const MCFillFragment *FF = cast<MCFillFragment>(this);
OS << " Value:" << static_cast<unsigned>(FF->getValue())
- << " Size:" << FF->getSize();
+ << " ValueSize:" << static_cast<unsigned>(FF->getValueSize())
+ << " NumValues:" << FF->getNumValues();
break;
}
case MCFragment::FT_Relaxable: {
@@ -463,26 +465,4 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
}
OS << ">";
}
-
-LLVM_DUMP_METHOD void MCAssembler::dump() const{
- raw_ostream &OS = errs();
-
- OS << "<MCAssembler\n";
- OS << " Sections:[\n ";
- for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
- if (it != begin()) OS << ",\n ";
- it->dump();
- }
- OS << "],\n";
- OS << " Symbols:[";
-
- for (const_symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) {
- if (it != symbol_begin()) OS << ",\n ";
- OS << "(";
- it->dump();
- OS << ", Index:" << it->getIndex() << ", ";
- OS << ")";
- }
- OS << "]>\n";
-}
#endif
diff --git a/contrib/llvm/lib/MC/MCInst.cpp b/contrib/llvm/lib/MC/MCInst.cpp
index f6d1d3cffca0..f9b71caaf91c 100644
--- a/contrib/llvm/lib/MC/MCInst.cpp
+++ b/contrib/llvm/lib/MC/MCInst.cpp
@@ -8,8 +8,10 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCInst.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -35,6 +37,23 @@ void MCOperand::print(raw_ostream &OS) const {
OS << ">";
}
+bool MCOperand::evaluateAsConstantImm(int64_t &Imm) const {
+ if (isImm()) {
+ Imm = getImm();
+ return true;
+ }
+ return false;
+}
+
+bool MCOperand::isBareSymbolRef() const {
+ assert(isExpr() &&
+ "isBareSymbolRef expects only expressions");
+ const MCExpr *Expr = getExpr();
+ MCExpr::ExprKind Kind = getExpr()->getKind();
+ return Kind == MCExpr::SymbolRef &&
+ cast<MCSymbolRefExpr>(Expr)->getKind() == MCSymbolRefExpr::VK_None;
+}
+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MCOperand::dump() const {
print(dbgs());
diff --git a/contrib/llvm/lib/MC/MCInstrAnalysis.cpp b/contrib/llvm/lib/MC/MCInstrAnalysis.cpp
index 280b5cf68c98..8223f3a5c66f 100644
--- a/contrib/llvm/lib/MC/MCInstrAnalysis.cpp
+++ b/contrib/llvm/lib/MC/MCInstrAnalysis.cpp
@@ -8,6 +8,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCInstrAnalysis.h"
+
+#include "llvm/ADT/APInt.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrInfo.h"
@@ -15,6 +17,13 @@
using namespace llvm;
+bool MCInstrAnalysis::clearsSuperRegisters(const MCRegisterInfo &MRI,
+ const MCInst &Inst,
+ APInt &Writes) const {
+ Writes.clearAllBits();
+ return false;
+}
+
bool MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr,
uint64_t Size, uint64_t &Target) const {
if (Inst.getNumOperands() == 0 ||
diff --git a/contrib/llvm/lib/MC/MCLabel.cpp b/contrib/llvm/lib/MC/MCLabel.cpp
index db25a46fce18..c376c83274ef 100644
--- a/contrib/llvm/lib/MC/MCLabel.cpp
+++ b/contrib/llvm/lib/MC/MCLabel.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCLabel.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp b/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp
index 97f95418e054..2f8581470ea6 100644
--- a/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp
+++ b/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp
@@ -36,7 +36,7 @@ void MCLOHDirective::emit_impl(raw_ostream &OutStream,
void MCLOHDirective::emit(MachObjectWriter &ObjWriter,
const MCAsmLayout &Layout) const {
- raw_ostream &OutStream = ObjWriter.getStream();
+ raw_ostream &OutStream = ObjWriter.W.OS;
emit_impl(OutStream, ObjWriter, Layout);
}
diff --git a/contrib/llvm/lib/MC/MCMachOStreamer.cpp b/contrib/llvm/lib/MC/MCMachOStreamer.cpp
index 3969143bb2c7..43e69605787c 100644
--- a/contrib/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/contrib/llvm/lib/MC/MCMachOStreamer.cpp
@@ -24,6 +24,7 @@
#include "llvm/MC/MCLinkerOptimizationHint.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
@@ -63,9 +64,11 @@ private:
public:
MCMachOStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
- raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter,
+ std::unique_ptr<MCObjectWriter> OW,
+ std::unique_ptr<MCCodeEmitter> Emitter,
bool DWARFMustBeAtTheEnd, bool label)
- : MCObjectStreamer(Context, std::move(MAB), OS, std::move(Emitter)),
+ : MCObjectStreamer(Context, std::move(MAB), std::move(OW),
+ std::move(Emitter)),
LabelSections(label), DWARFMustBeAtTheEnd(DWARFMustBeAtTheEnd),
CreatedADWARFSection(false) {}
@@ -99,7 +102,8 @@ public:
void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
- uint64_t Size = 0, unsigned ByteAlignment = 0) override;
+ uint64_t Size = 0, unsigned ByteAlignment = 0,
+ SMLoc Loc = SMLoc()) override;
void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment = 0) override;
@@ -410,9 +414,18 @@ void MCMachOStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
}
void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment) {
- // On darwin all virtual sections have zerofill type.
- assert(Section->isVirtualSection() && "Section does not have zerofill type!");
+ uint64_t Size, unsigned ByteAlignment,
+ SMLoc Loc) {
+ // On darwin all virtual sections have zerofill type. Disallow the usage of
+ // .zerofill in non-virtual functions. If something similar is needed, use
+ // .space or .zero.
+ if (!Section->isVirtualSection()) {
+ getContext().reportError(
+ Loc, "The usage of .zerofill is restricted to sections of "
+ "ZEROFILL type. Use .zero or .space instead.");
+ return; // Early returning here shouldn't harm. EmitZeros should work on any
+ // section.
+ }
PushSection();
SwitchSection(Section);
@@ -447,6 +460,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());
}
@@ -485,12 +499,12 @@ void MCMachOStreamer::FinishImpl() {
MCStreamer *llvm::createMachOStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> &&MAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&CE,
bool RelaxAll, bool DWARFMustBeAtTheEnd,
bool LabelSections) {
MCMachOStreamer *S =
- new MCMachOStreamer(Context, std::move(MAB), OS, std::move(CE),
+ new MCMachOStreamer(Context, std::move(MAB), std::move(OW), std::move(CE),
DWARFMustBeAtTheEnd, LabelSections);
const Triple &Target = Context.getObjectFileInfo()->getTargetTriple();
S->EmitVersionForTarget(Target);
diff --git a/contrib/llvm/lib/MC/MCNullStreamer.cpp b/contrib/llvm/lib/MC/MCNullStreamer.cpp
index ccf658e1d135..a96dec184441 100644
--- a/contrib/llvm/lib/MC/MCNullStreamer.cpp
+++ b/contrib/llvm/lib/MC/MCNullStreamer.cpp
@@ -30,7 +30,8 @@ namespace {
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override {}
void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
- uint64_t Size = 0, unsigned ByteAlignment = 0) override {}
+ uint64_t Size = 0, unsigned ByteAlignment = 0,
+ SMLoc Loc = SMLoc()) override {}
void EmitGPRel32Value(const MCExpr *Value) override {}
void BeginCOFFSymbolDef(const MCSymbol *Symbol) override {}
void EmitCOFFSymbolStorageClass(int StorageClass) override {}
diff --git a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp
index 328f000f37c9..29d34a8c1e3e 100644
--- a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -135,6 +135,10 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
// "__DATA/__datacoal_nt" => section "__DATA/__data"
Triple::ArchType ArchTy = T.getArch();
+ ConstDataSection // .const_data
+ = Ctx->getMachOSection("__DATA", "__const", 0,
+ SectionKind::getReadOnlyWithRel());
+
if (ArchTy == Triple::ppc || ArchTy == Triple::ppc64) {
TextCoalSection
= Ctx->getMachOSection("__TEXT", "__textcoal_nt",
@@ -147,15 +151,14 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
SectionKind::getReadOnly());
DataCoalSection = Ctx->getMachOSection(
"__DATA", "__datacoal_nt", MachO::S_COALESCED, SectionKind::getData());
+ ConstDataCoalSection = DataCoalSection;
} else {
TextCoalSection = TextSection;
ConstTextCoalSection = ReadOnlySection;
DataCoalSection = DataSection;
+ ConstDataCoalSection = ConstDataSection;
}
- ConstDataSection // .const_data
- = Ctx->getMachOSection("__DATA", "__const", 0,
- SectionKind::getReadOnlyWithRel());
DataCommonSection
= Ctx->getMachOSection("__DATA","__common",
MachO::S_ZEROFILL,
@@ -201,6 +204,9 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
}
// Debug Information.
+ DwarfDebugNamesSection =
+ Ctx->getMachOSection("__DWARF", "__debug_names", MachO::S_ATTR_DEBUG,
+ SectionKind::getMetadata(), "debug_names_begin");
DwarfAccelNamesSection =
Ctx->getMachOSection("__DWARF", "__apple_names", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "names_begin");
@@ -228,6 +234,9 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
DwarfLineSection =
Ctx->getMachOSection("__DWARF", "__debug_line", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "section_line");
+ DwarfLineStrSection =
+ Ctx->getMachOSection("__DWARF", "__debug_line_str", MachO::S_ATTR_DEBUG,
+ SectionKind::getMetadata(), "section_line_str");
DwarfFrameSection =
Ctx->getMachOSection("__DWARF", "__debug_frame", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
@@ -258,6 +267,9 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
DwarfRangesSection =
Ctx->getMachOSection("__DWARF", "__debug_ranges", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "debug_range");
+ DwarfRnglistsSection =
+ Ctx->getMachOSection("__DWARF", "__debug_rnglists", MachO::S_ATTR_DEBUG,
+ SectionKind::getMetadata(), "debug_range");
DwarfMacinfoSection =
Ctx->getMachOSection("__DWARF", "__debug_macinfo", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "debug_macinfo");
@@ -520,8 +532,7 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
// MIPS .debug_* sections should have SHT_MIPS_DWARF section type
// to distinguish among sections contain DWARF and ECOFF debug formats.
// Sections with ECOFF debug format are obsoleted and marked by SHT_PROGBITS.
- if (T.getArch() == Triple::mips || T.getArch() == Triple::mipsel ||
- T.getArch() == Triple::mips64 || T.getArch() == Triple::mips64el)
+ if (T.isMIPS())
DebugSecType = ELF::SHT_MIPS_DWARF;
// Debug Info Sections.
@@ -529,6 +540,9 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
Ctx->getELFSection(".debug_abbrev", DebugSecType, 0);
DwarfInfoSection = Ctx->getELFSection(".debug_info", DebugSecType, 0);
DwarfLineSection = Ctx->getELFSection(".debug_line", DebugSecType, 0);
+ DwarfLineStrSection =
+ Ctx->getELFSection(".debug_line_str", DebugSecType,
+ ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, "");
DwarfFrameSection = Ctx->getELFSection(".debug_frame", DebugSecType, 0);
DwarfPubNamesSection =
Ctx->getELFSection(".debug_pubnames", DebugSecType, 0);
@@ -552,6 +566,8 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
// DWARF5 Experimental Debug Info
// Accelerator Tables
+ DwarfDebugNamesSection =
+ Ctx->getELFSection(".debug_names", ELF::SHT_PROGBITS, 0);
DwarfAccelNamesSection =
Ctx->getELFSection(".apple_names", ELF::SHT_PROGBITS, 0);
DwarfAccelObjCSection =
@@ -565,6 +581,7 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
DwarfStrOffSection =
Ctx->getELFSection(".debug_str_offsets", DebugSecType, 0);
DwarfAddrSection = Ctx->getELFSection(".debug_addr", DebugSecType, 0);
+ DwarfRnglistsSection = Ctx->getELFSection(".debug_rnglists", DebugSecType, 0);
// Fission Sections
DwarfInfoDWOSection =
@@ -582,6 +599,8 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
Ctx->getELFSection(".debug_loc.dwo", DebugSecType, 0);
DwarfStrOffDWOSection =
Ctx->getELFSection(".debug_str_offsets.dwo", DebugSecType, 0);
+ DwarfRnglistsDWOSection =
+ Ctx->getELFSection(".debug_rnglists.dwo", DebugSecType, 0);
// DWP Sections
DwarfCUIndexSection =
@@ -679,7 +698,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(), "section_line");
-
+ DwarfLineStrSection = Ctx->getCOFFSection(
+ ".debug_line_str",
+ COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getMetadata(), "section_line_str");
DwarfFrameSection = Ctx->getCOFFSection(
".debug_frame",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
@@ -785,6 +808,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());
+ DwarfDebugNamesSection = Ctx->getCOFFSection(
+ ".debug_names",
+ COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getMetadata(), "debug_names_begin");
DwarfAccelNamesSection = Ctx->getCOFFSection(
".apple_names",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
@@ -821,6 +849,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
SXDataSection = Ctx->getCOFFSection(".sxdata", COFF::IMAGE_SCN_LNK_INFO,
SectionKind::getMetadata());
+ GFIDsSection = Ctx->getCOFFSection(".gfids$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,
@@ -833,22 +866,29 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
}
void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) {
- // TODO: Set the section types and flags.
TextSection = Ctx->getWasmSection(".text", SectionKind::getText());
DataSection = Ctx->getWasmSection(".data", SectionKind::getData());
- // TODO: Set the section types and flags.
- DwarfLineSection = Ctx->getWasmSection(".debug_line", SectionKind::getMetadata());
- DwarfStrSection = Ctx->getWasmSection(".debug_str", SectionKind::getMetadata());
- DwarfLocSection = Ctx->getWasmSection(".debug_loc", SectionKind::getMetadata());
- DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", SectionKind::getMetadata(), "section_abbrev");
+ DwarfLineSection =
+ Ctx->getWasmSection(".debug_line", SectionKind::getMetadata());
+ DwarfLineStrSection =
+ Ctx->getWasmSection(".debug_line_str", SectionKind::getMetadata());
+ DwarfStrSection =
+ Ctx->getWasmSection(".debug_str", SectionKind::getMetadata());
+ DwarfLocSection =
+ Ctx->getWasmSection(".debug_loc", SectionKind::getMetadata());
+ DwarfAbbrevSection =
+ Ctx->getWasmSection(".debug_abbrev", SectionKind::getMetadata());
DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", SectionKind::getMetadata());
- DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", SectionKind::getMetadata(), "debug_range");
- DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", SectionKind::getMetadata(), "debug_macinfo");
+ DwarfRangesSection =
+ Ctx->getWasmSection(".debug_ranges", SectionKind::getMetadata());
+ DwarfMacinfoSection =
+ Ctx->getWasmSection(".debug_macinfo", SectionKind::getMetadata());
DwarfAddrSection = Ctx->getWasmSection(".debug_addr", SectionKind::getMetadata());
DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", SectionKind::getMetadata());
DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", SectionKind::getMetadata());
- DwarfInfoSection = Ctx->getWasmSection(".debug_info", SectionKind::getMetadata(), "section_info");
+ DwarfInfoSection =
+ Ctx->getWasmSection(".debug_info", SectionKind::getMetadata());
DwarfFrameSection = Ctx->getWasmSection(".debug_frame", SectionKind::getMetadata());
DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", SectionKind::getMetadata());
DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", SectionKind::getMetadata());
@@ -913,3 +953,24 @@ MCSection *MCObjectFileInfo::getDwarfTypesSection(uint64_t Hash) const {
return Ctx->getELFSection(".debug_types", ELF::SHT_PROGBITS, ELF::SHF_GROUP,
0, utostr(Hash));
}
+
+MCSection *
+MCObjectFileInfo::getStackSizesSection(const MCSection &TextSec) const {
+ if (Env != IsELF)
+ return StackSizesSection;
+
+ const MCSectionELF &ElfSec = static_cast<const MCSectionELF &>(TextSec);
+ unsigned Flags = ELF::SHF_LINK_ORDER;
+ StringRef GroupName;
+ if (const MCSymbol *Group = ElfSec.getGroup()) {
+ GroupName = Group->getName();
+ Flags |= ELF::SHF_GROUP;
+ }
+
+ const MCSymbol *Link = TextSec.getBeginSymbol();
+ auto It = StackSizesUniquing.insert({Link, StackSizesUniquing.size()});
+ unsigned UniqueID = It.first->second;
+
+ return Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, Flags, 0,
+ GroupName, UniqueID, cast<MCSymbolELF>(Link));
+}
diff --git a/contrib/llvm/lib/MC/MCObjectStreamer.cpp b/contrib/llvm/lib/MC/MCObjectStreamer.cpp
index aecb3844622b..4b6dad5ce8f3 100644
--- a/contrib/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/contrib/llvm/lib/MC/MCObjectStreamer.cpp
@@ -25,16 +25,24 @@ using namespace llvm;
MCObjectStreamer::MCObjectStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> TAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> OW,
std::unique_ptr<MCCodeEmitter> Emitter)
- : MCStreamer(Context), ObjectWriter(TAB->createObjectWriter(OS)),
- TAB(std::move(TAB)), Emitter(std::move(Emitter)),
- Assembler(llvm::make_unique<MCAssembler>(Context, *this->TAB,
- *this->Emitter, *ObjectWriter)),
+ : MCStreamer(Context),
+ Assembler(llvm::make_unique<MCAssembler>(
+ Context, std::move(TAB), std::move(Emitter), std::move(OW))),
EmitEHFrame(true), EmitDebugFrame(false) {}
MCObjectStreamer::~MCObjectStreamer() {}
+// AssemblerPtr is used for evaluation of expressions and causes
+// difference between asm and object outputs. Return nullptr to in
+// inline asm mode to limit divergence to assembly inputs.
+MCAssembler *MCObjectStreamer::getAssemblerPtr() {
+ if (getUseAssemblerInfoForParsing())
+ return Assembler.get();
+ return nullptr;
+}
+
void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
if (PendingLabels.empty())
return;
@@ -51,17 +59,35 @@ void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
PendingLabels.clear();
}
+// As a compile-time optimization, avoid allocating and evaluating an MCExpr
+// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.
+static Optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi,
+ const MCSymbol *Lo) {
+ assert(Hi && Lo);
+ if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||
+ Hi->isVariable() || Lo->isVariable())
+ return None;
+
+ return Hi->getOffset() - Lo->getOffset();
+}
+
void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
const MCSymbol *Lo,
unsigned Size) {
- // If not assigned to the same (valid) fragment, fallback.
- if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||
- Hi->isVariable() || Lo->isVariable()) {
- MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
+ if (Optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) {
+ EmitIntValue(*Diff, Size);
return;
}
+ MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
+}
- EmitIntValue(Hi->getOffset() - Lo->getOffset(), Size);
+void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
+ const MCSymbol *Lo) {
+ if (Optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) {
+ EmitULEB128IntValue(*Diff);
+ return;
+ }
+ MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);
}
void MCObjectStreamer::reset() {
@@ -94,12 +120,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);
}
@@ -137,7 +175,7 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
// Avoid fixups when possible.
int64_t AbsValue;
- if (Value->evaluateAsAbsolute(AbsValue, getAssembler())) {
+ if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) {
if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) {
getContext().reportError(
Loc, "value evaluated as " + Twine(AbsValue) + " is out of range.");
@@ -199,7 +237,7 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) {
void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) {
int64_t IntValue;
- if (Value->evaluateAsAbsolute(IntValue, getAssembler())) {
+ if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
EmitULEB128IntValue(IntValue);
return;
}
@@ -208,7 +246,7 @@ void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) {
void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) {
int64_t IntValue;
- if (Value->evaluateAsAbsolute(IntValue, getAssembler())) {
+ if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
EmitSLEB128IntValue(IntValue);
return;
}
@@ -229,13 +267,14 @@ bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
const MCExpr *Subsection) {
assert(Section && "Cannot switch to a null section!");
flushPendingLabels(nullptr);
+ getContext().clearCVLocSeen();
getContext().clearDwarfLocSeen();
bool Created = getAssembler().registerSection(*Section);
int64_t IntSubsection = 0;
if (Subsection &&
- !Subsection->evaluateAsAbsolute(IntSubsection, getAssembler()))
+ !Subsection->evaluateAsAbsolute(IntSubsection, getAssemblerPtr()))
report_fatal_error("Cannot evaluate subsection number");
if (IntSubsection < 0 || IntSubsection > 8192)
report_fatal_error("Subsection number out of range");
@@ -274,7 +313,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;
}
@@ -288,7 +327,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;
@@ -381,7 +420,7 @@ void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
}
const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
int64_t Res;
- if (AddrDelta->evaluateAsAbsolute(Res, getAssembler())) {
+ if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) {
MCDwarfLineAddr::Emit(this, Assembler->getDWARFLinetableParams(), LineDelta,
Res);
return;
@@ -393,7 +432,7 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
const MCSymbol *Label) {
const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
int64_t Res;
- if (AddrDelta->evaluateAsAbsolute(Res, getAssembler())) {
+ if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) {
MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res);
return;
}
@@ -553,7 +592,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");
@@ -561,7 +601,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);
@@ -583,32 +623,55 @@ void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
flushPendingLabels(DF, DF->getContents().size());
assert(getCurrentSectionOnly() && "need a section");
- insert(new MCFillFragment(FillValue, NumBytes, Loc));
+ insert(new MCFillFragment(FillValue, 1, NumBytes, Loc));
}
void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
int64_t Expr, SMLoc Loc) {
int64_t IntNumValues;
- if (!NumValues.evaluateAsAbsolute(IntNumValues, getAssembler())) {
- getContext().reportError(Loc, "expected absolute expression");
+ // Do additional checking now if we can resolve the value.
+ if (NumValues.evaluateAsAbsolute(IntNumValues, getAssemblerPtr())) {
+ if (IntNumValues < 0) {
+ getContext().getSourceManager()->PrintMessage(
+ Loc, SourceMgr::DK_Warning,
+ "'.fill' directive with negative repeat count has no effect");
+ return;
+ }
+ // Emit now if we can for better errors.
+ int64_t NonZeroSize = Size > 4 ? 4 : Size;
+ Expr &= ~0ULL >> (64 - NonZeroSize * 8);
+ for (uint64_t i = 0, e = IntNumValues; i != e; ++i) {
+ EmitIntValue(Expr, NonZeroSize);
+ if (NonZeroSize < Size)
+ EmitIntValue(0, Size - NonZeroSize);
+ }
return;
}
- if (IntNumValues < 0) {
- getContext().getSourceManager()->PrintMessage(
- Loc, SourceMgr::DK_Warning,
- "'.fill' directive with negative repeat count has no effect");
- return;
- }
+ // Otherwise emit as fragment.
+ MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
- MCStreamer::emitFill(IntNumValues, Size, Expr);
+ assert(getCurrentSectionOnly() && "need a section");
+ insert(new MCFillFragment(Expr, Size, NumValues, Loc));
}
void MCObjectStreamer::EmitFileDirective(StringRef Filename) {
getAssembler().addFileName(Filename);
}
+void MCObjectStreamer::EmitAddrsig() {
+ getAssembler().getWriter().emitAddrsigSection();
+}
+
+void MCObjectStreamer::EmitAddrsigSym(const MCSymbol *Sym) {
+ getAssembler().registerSymbol(*Sym);
+ getAssembler().getWriter().addAddrsigSymbol(Sym);
+}
+
void MCObjectStreamer::FinishImpl() {
+ getContext().RemapDebugPaths();
+
// If we are generating dwarf for assembly source files dump out the sections.
if (getContext().getGenDwarfForAssembly())
MCGenDwarfInfo::Emit(this);
@@ -616,6 +679,6 @@ void MCObjectStreamer::FinishImpl() {
// Dump out the dwarf file & directory tables and line tables.
MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams());
- flushPendingLabels(nullptr);
+ flushPendingLabels();
getAssembler().Finish();
}
diff --git a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp
index ce3b70bed740..39a760826d96 100644
--- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -50,6 +50,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SMLoc.h"
@@ -79,11 +80,11 @@ static cl::opt<unsigned> AsmMacroMaxNestingDepth(
namespace {
-/// \brief Helper types for tracking macro definitions.
+/// Helper types for tracking macro definitions.
typedef std::vector<AsmToken> MCAsmMacroArgument;
typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
-/// \brief Helper class for storing information about an active macro
+/// Helper class for storing information about an active macro
/// instantiation.
struct MacroInstantiation {
/// The location of the instantiation.
@@ -103,13 +104,13 @@ public:
};
struct ParseStatementInfo {
- /// \brief The parsed operands from the last parsed statement.
+ /// The parsed operands from the last parsed statement.
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
- /// \brief The opcode from the last parsed instruction.
+ /// The opcode from the last parsed instruction.
unsigned Opcode = ~0U;
- /// \brief Was there an error parsing the inline assembly?
+ /// Was there an error parsing the inline assembly?
bool ParseError = false;
SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
@@ -119,7 +120,7 @@ struct ParseStatementInfo {
: AsmRewrites(rewrites) {}
};
-/// \brief The concrete assembly parser instance.
+/// The concrete assembly parser instance.
class AsmParser : public MCAsmParser {
private:
AsmLexer Lexer;
@@ -138,21 +139,21 @@ private:
AsmCond TheCondState;
std::vector<AsmCond> TheCondStack;
- /// \brief maps directive names to handler methods in parser
+ /// maps directive names to handler methods in parser
/// extensions. Extensions register themselves in this map by calling
/// addDirectiveHandler.
StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
- /// \brief Stack of active macro instantiations.
+ /// Stack of active macro instantiations.
std::vector<MacroInstantiation*> ActiveMacros;
- /// \brief List of bodies of anonymous macros.
+ /// List of bodies of anonymous macros.
std::deque<MCAsmMacro> MacroLikeBodies;
/// Boolean tracking whether macro substitution is enabled.
unsigned MacrosEnabledFlag : 1;
- /// \brief Keeps track of how many .macro's have been instantiated.
+ /// Keeps track of how many .macro's have been instantiated.
unsigned NumOfMacroInstantiations;
/// The values from the last parsed cpp hash file line comment if any.
@@ -164,26 +165,21 @@ private:
};
CppHashInfoTy CppHashInfo;
- /// \brief List of forward directional labels for diagnosis at the end.
+ /// List of forward directional labels for diagnosis at the end.
SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
- /// When generating dwarf for assembly source files we need to calculate the
- /// logical line number based on the last parsed cpp hash file line comment
- /// and current line. Since this is slow and messes up the SourceMgr's
- /// cache we save the last info we queried with SrcMgr.FindLineNumber().
- SMLoc LastQueryIDLoc;
- unsigned LastQueryBuffer;
- unsigned LastQueryLine;
-
/// AssemblerDialect. ~OU means unset value and use value provided by MAI.
unsigned AssemblerDialect = ~0U;
- /// \brief is Darwin compatibility enabled?
+ /// is Darwin compatibility enabled?
bool IsDarwin = false;
- /// \brief Are we parsing ms-style inline assembly?
+ /// Are we parsing ms-style inline assembly?
bool ParsingInlineAsm = false;
+ /// Did we already inform the user about inconsistent MD5 usage?
+ bool ReportedInconsistentMD5 = false;
+
public:
AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
const MCAsmInfo &MAI, unsigned CB);
@@ -250,11 +246,11 @@ public:
SMLoc &EndLoc) override;
bool parseAbsoluteExpression(int64_t &Res) override;
- /// \brief Parse a floating point expression using the float \p Semantics
+ /// Parse a floating point expression using the float \p Semantics
/// and set \p Res to the value.
bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
- /// \brief Parse an identifier or string (as a quoted identifier)
+ /// Parse an identifier or string (as a quoted identifier)
/// and set \p Res to the identifier contents.
bool parseIdentifier(StringRef &Res) override;
void eatToEndOfStatement() override;
@@ -278,28 +274,28 @@ private:
ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable,
SMLoc L);
- /// \brief Are macros enabled in the parser?
+ /// Are macros enabled in the parser?
bool areMacrosEnabled() {return MacrosEnabledFlag;}
- /// \brief Control a flag in the parser that enables or disables macros.
+ /// Control a flag in the parser that enables or disables macros.
void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
- /// \brief Are we inside a macro instantiation?
+ /// Are we inside a macro instantiation?
bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
- /// \brief Handle entry to macro instantiation.
+ /// Handle entry to macro instantiation.
///
/// \param M The macro.
/// \param NameLoc Instantiation location.
bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
- /// \brief Handle exit from macro instantiation.
+ /// Handle exit from macro instantiation.
void handleMacroExit();
- /// \brief Extract AsmTokens for a macro argument.
+ /// Extract AsmTokens for a macro argument.
bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
- /// \brief Parse all macro arguments for a given macro.
+ /// Parse all macro arguments for a given macro.
bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
void printMacroInstantiations();
@@ -310,15 +306,20 @@ private:
}
static void DiagHandler(const SMDiagnostic &Diag, void *Context);
- /// \brief Enter the specified file. This returns true on failure.
+ /// Should we emit DWARF describing this assembler source? (Returns false if
+ /// the source has .file directives, which means we don't want to generate
+ /// info describing the assembler source itself.)
+ bool enabledGenDwarfForAssembly();
+
+ /// Enter the specified file. This returns true on failure.
bool enterIncludeFile(const std::string &Filename);
- /// \brief Process the specified file for the .incbin directive.
+ /// Process the specified file for the .incbin directive.
/// This returns true on failure.
bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,
const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());
- /// \brief Reset the current lexer position to that given by \p Loc. The
+ /// Reset the current lexer position to that given by \p Loc. The
/// current token is not set; clients should ensure Lex() is called
/// subsequently.
///
@@ -326,17 +327,17 @@ private:
/// location.
void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);
- /// \brief Parse up to the end of statement and a return the contents from the
+ /// Parse up to the end of statement and a return the contents from the
/// current token until the end of the statement; the current token on exit
/// will be either the EndOfStatement or EOF.
StringRef parseStringToEndOfStatement() override;
- /// \brief Parse until the end of a statement or a comma is encountered,
+ /// Parse until the end of a statement or a comma is encountered,
/// return the contents from the current token up to the end or comma.
StringRef parseStringToComma();
bool parseAssignment(StringRef Name, bool allow_redef,
- bool NoDeadStrip = false);
+ bool NoDeadStrip = false, bool AllowExtendedExpr = false);
unsigned getBinOpPrecedence(AsmToken::TokenKind K,
MCBinaryExpr::Opcode &Kind);
@@ -505,10 +506,12 @@ private:
DK_ERROR,
DK_WARNING,
DK_PRINT,
+ DK_ADDRSIG,
+ DK_ADDRSIG_SYM,
DK_END
};
- /// \brief Maps directive name --> DirectiveKind enum, for
+ /// Maps directive name --> DirectiveKind enum, for
/// directives parsed by this class.
StringMap<DirectiveKind> DirectiveKindMap;
@@ -597,7 +600,7 @@ private:
// .sleb128 (Signed=true) and .uleb128 (Signed=false)
bool parseDirectiveLEB128(bool Signed);
- /// \brief Parse a directive like ".globl" which
+ /// Parse a directive like ".globl" which
/// accepts a single symbol (which should be a label or an external).
bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
@@ -653,6 +656,10 @@ private:
// .print <double-quotes-string>
bool parseDirectivePrint(SMLoc DirectiveLoc);
+ // Directives to support address-significance tables.
+ bool parseDirectiveAddrsig();
+ bool parseDirectiveAddrsigSym();
+
void initializeDirectiveKindMap();
};
@@ -693,7 +700,10 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
PlatformParser.reset(createELFAsmParser());
break;
case MCObjectFileInfo::IsWasm:
- llvm_unreachable("Wasm parsing not supported yet");
+ // TODO: WASM will need its own MCAsmParserExtension implementation, but
+ // for now we can re-use the ELF one, since the directives can be the
+ // same for now.
+ PlatformParser.reset(createELFAsmParser());
break;
}
@@ -773,7 +783,7 @@ bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
Bytes = Bytes.drop_front(Skip);
if (Count) {
int64_t Res;
- if (!Count->evaluateAsAbsolute(Res))
+ if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
return Error(Loc, "expected absolute expression");
if (Res < 0)
return Warning(Loc, "negative count has no effect");
@@ -823,6 +833,19 @@ const AsmToken &AsmParser::Lex() {
return *tok;
}
+bool AsmParser::enabledGenDwarfForAssembly() {
+ // Check whether the user specified -g.
+ if (!getContext().getGenDwarfForAssembly())
+ return false;
+ // If we haven't encountered any .file directives (which would imply that
+ // the assembler source was produced with debug info already) then emit one
+ // describing the assembler source file itself.
+ if (getContext().getGenDwarfFileNumber() == 0)
+ getContext().setGenDwarfFileNumber(getStreamer().EmitDwarfFileDirective(
+ 0, StringRef(), getContext().getMainFileName()));
+ return true;
+}
+
bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// Create the initial section, if requested.
if (!NoInitialTextSection)
@@ -836,7 +859,9 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
SmallVector<AsmRewrite, 4> AsmStrRewrites;
// If we are generating dwarf for assembly source files save the initial text
- // section and generate a .file directive.
+ // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't
+ // emitting any actual debug info yet and haven't had a chance to parse any
+ // embedded .file directives.)
if (getContext().getGenDwarfForAssembly()) {
MCSection *Sec = getStreamer().getCurrentSectionOnly();
if (!Sec->getBeginSymbol()) {
@@ -847,8 +872,6 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
bool InsertResult = getContext().addGenDwarfSection(Sec);
assert(InsertResult && ".text section should not have debug info yet");
(void)InsertResult;
- getContext().setGenDwarfFileNumber(getStreamer().EmitDwarfFileDirective(
- 0, StringRef(), getContext().getMainFileName()));
}
// While we have input, parse each statement.
@@ -942,7 +965,7 @@ bool AsmParser::checkForValidSection() {
return false;
}
-/// \brief Throw away the rest of the line for testing purposes.
+/// Throw away the rest of the line for testing purposes.
void AsmParser::eatToEndOfStatement() {
while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
Lexer.Lex();
@@ -973,7 +996,7 @@ StringRef AsmParser::parseStringToComma() {
return StringRef(Start, End - Start);
}
-/// \brief Parse a paren expression and return it.
+/// Parse a paren expression and return it.
/// NOTE: This assumes the leading '(' has already been consumed.
///
/// parenexpr ::= expr)
@@ -988,7 +1011,7 @@ bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
return false;
}
-/// \brief Parse a bracket expression and return it.
+/// Parse a bracket expression and return it.
/// NOTE: This assumes the leading '[' has already been consumed.
///
/// bracketexpr ::= expr]
@@ -1002,7 +1025,7 @@ bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
return false;
}
-/// \brief Parse a primary expression and return it.
+/// Parse a primary expression and return it.
/// primaryexpr ::= (parenexpr
/// primaryexpr ::= symbol
/// primaryexpr ::= number
@@ -1098,13 +1121,17 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
// If this is an absolute variable reference, substitute it now to preserve
// semantics in the face of reassignment.
- if (Sym->isVariable() &&
- isa<MCConstantExpr>(Sym->getVariableValue(/*SetUsed*/ false))) {
- if (Variant)
- return Error(EndLoc, "unexpected modifier on variable reference");
-
- Res = Sym->getVariableValue(/*SetUsed*/ false);
- return false;
+ if (Sym->isVariable()) {
+ auto V = Sym->getVariableValue(/*SetUsed*/ false);
+ bool DoInline = isa<MCConstantExpr>(V);
+ if (auto TV = dyn_cast<MCTargetExpr>(V))
+ DoInline = TV->inlineAssignedExpr();
+ if (DoInline) {
+ if (Variant)
+ return Error(EndLoc, "unexpected modifier on variable reference");
+ Res = Sym->getVariableValue(/*SetUsed*/ false);
+ return false;
+ }
}
// Otherwise create a symbol ref.
@@ -1294,7 +1321,7 @@ AsmParser::applyModifierToExpr(const MCExpr *E,
/// the End argument will be filled with the last location pointed to the '>'
/// character.
-/// There is a gap between the AltMacro's documentation and the single quote implementation.
+/// There is a gap between the AltMacro's documentation and the single quote implementation.
/// GCC does not fully support this feature and so we will not support it.
/// TODO: Adding single quote as a string.
bool AsmParser::isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
@@ -1314,7 +1341,7 @@ bool AsmParser::isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
return false;
}
-/// \brief creating a string without the escape characters '!'.
+/// creating a string without the escape characters '!'.
void AsmParser::altMacroString(StringRef AltMacroStr,std::string &Res) {
for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
if (AltMacroStr[Pos] == '!')
@@ -1323,7 +1350,7 @@ void AsmParser::altMacroString(StringRef AltMacroStr,std::string &Res) {
}
}
-/// \brief Parse an expression and return it.
+/// Parse an expression and return it.
///
/// expr ::= expr &&,|| expr -> lowest.
/// expr ::= expr |,^,&,! expr
@@ -1363,7 +1390,8 @@ bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
Lex();
}
- // Try to constant fold it up front, if possible.
+ // Try to constant fold it up front, if possible. Do not exploit
+ // assembler here.
int64_t Value;
if (Res->evaluateAsAbsolute(Value))
Res = MCConstantExpr::create(Value, getContext());
@@ -1404,7 +1432,7 @@ bool AsmParser::parseAbsoluteExpression(int64_t &Res) {
if (parseExpression(Expr))
return true;
- if (!Expr->evaluateAsAbsolute(Res))
+ if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
return Error(StartLoc, "expected absolute expression");
return false;
@@ -1571,7 +1599,7 @@ unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
: getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr);
}
-/// \brief Parse all binary operators with precedence >= 'Precedence'.
+/// Parse all binary operators with precedence >= 'Precedence'.
/// Res contains the LHS of the expression on input.
bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
SMLoc &EndLoc) {
@@ -1783,7 +1811,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
// If we are generating dwarf for assembly source files then gather the
// info to make a dwarf label entry for this label if needed.
- if (getContext().getGenDwarfForAssembly())
+ if (enabledGenDwarfForAssembly())
MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
IDLoc);
@@ -1798,7 +1826,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
// identifier '=' ... -> assignment statement
Lex();
- return parseAssignment(IDVal, true);
+ return parseAssignment(IDVal, true, /*NoDeadStrip*/ false, /*AllowExtendedExpr*/true);
default: // Normal instruction or directive.
break;
@@ -2105,6 +2133,10 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectiveDS(IDVal, 12);
case DK_PRINT:
return parseDirectivePrint(IDLoc);
+ case DK_ADDRSIG:
+ return parseDirectiveAddrsig();
+ case DK_ADDRSIG_SYM:
+ return parseDirectiveAddrsigSym();
}
return Error(IDLoc, "unknown directive");
@@ -2152,7 +2184,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
// If we are generating dwarf for the current section then generate a .loc
// directive for the instruction.
- if (!ParseHadError && getContext().getGenDwarfForAssembly() &&
+ if (!ParseHadError && enabledGenDwarfForAssembly() &&
getContext().getGenDwarfSectionSyms().count(
getStreamer().getCurrentSectionOnly())) {
unsigned Line;
@@ -2170,20 +2202,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
0, StringRef(), CppHashInfo.Filename);
getContext().setGenDwarfFileNumber(FileNumber);
- // Since SrcMgr.FindLineNumber() is slow and messes up the SourceMgr's
- // cache with the different Loc from the call above we save the last
- // info we queried here with SrcMgr.FindLineNumber().
- unsigned CppHashLocLineNo;
- if (LastQueryIDLoc == CppHashInfo.Loc &&
- LastQueryBuffer == CppHashInfo.Buf)
- CppHashLocLineNo = LastQueryLine;
- else {
- CppHashLocLineNo =
- SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
- LastQueryLine = CppHashLocLineNo;
- LastQueryIDLoc = CppHashInfo.Loc;
- LastQueryBuffer = CppHashInfo.Buf;
- }
+ unsigned CppHashLocLineNo =
+ SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
}
@@ -2205,7 +2225,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
}
// Parse and erase curly braces marking block start/end
-bool
+bool
AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
// Identify curly brace marking block start/end
if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
@@ -2248,7 +2268,7 @@ bool AsmParser::parseCppHashLineFilenameComment(SMLoc L) {
return false;
}
-/// \brief will use the last parsed cpp hash line filename comment
+/// will use the last parsed cpp hash line filename comment
/// for the Filename and LineNo if any in the diagnostic.
void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
const AsmParser *Parser = static_cast<const AsmParser *>(Context);
@@ -2613,7 +2633,8 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
Lex();
if (parseExpression(AbsoluteExp, EndLoc))
return false;
- if (!AbsoluteExp->evaluateAsAbsolute(Value))
+ if (!AbsoluteExp->evaluateAsAbsolute(Value,
+ getStreamer().getAssemblerPtr()))
return Error(StrLoc, "expected absolute expression");
const char *StrChar = StrLoc.getPointer();
const char *EndChar = EndLoc.getPointer();
@@ -2745,11 +2766,11 @@ void AsmParser::handleMacroExit() {
}
bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
- bool NoDeadStrip) {
+ bool NoDeadStrip, bool AllowExtendedExpr) {
MCSymbol *Sym;
const MCExpr *Value;
if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym,
- Value))
+ Value, AllowExtendedExpr))
return true;
if (!Sym) {
@@ -2913,8 +2934,9 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
if (parseExpression(Offset))
return true;
- if (check(!Offset->evaluateAsAbsolute(OffsetValue), OffsetLoc,
- "expression is not a constant value") ||
+ if (check(!Offset->evaluateAsAbsolute(OffsetValue,
+ getStreamer().getAssemblerPtr()),
+ OffsetLoc, "expression is not a constant value") ||
check(OffsetValue < 0, OffsetLoc, "expression is negative") ||
parseToken(AsmToken::Comma, "expected comma") ||
check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
@@ -2939,7 +2961,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;
@@ -2970,6 +2994,25 @@ bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
return false;
}
+static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {
+ if (Asm.getTok().isNot(AsmToken::Integer) &&
+ Asm.getTok().isNot(AsmToken::BigNum))
+ return Asm.TokError("unknown token in expression");
+ SMLoc ExprLoc = Asm.getTok().getLoc();
+ APInt IntValue = Asm.getTok().getAPIntVal();
+ Asm.Lex();
+ if (!IntValue.isIntN(128))
+ return Asm.Error(ExprLoc, "out of range literal value");
+ if (!IntValue.isIntN(64)) {
+ hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
+ lo = IntValue.getLoBits(64).getZExtValue();
+ } else {
+ hi = 0;
+ lo = IntValue.getZExtValue();
+ }
+ return false;
+}
+
/// ParseDirectiveOctaValue
/// ::= .octa [ hexconstant (, hexconstant)* ]
@@ -2977,21 +3020,9 @@ bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
auto parseOp = [&]() -> bool {
if (checkForValidSection())
return true;
- if (getTok().isNot(AsmToken::Integer) && getTok().isNot(AsmToken::BigNum))
- return TokError("unknown token in expression");
- SMLoc ExprLoc = getTok().getLoc();
- APInt IntValue = getTok().getAPIntVal();
uint64_t hi, lo;
- Lex();
- if (!IntValue.isIntN(128))
- return Error(ExprLoc, "out of range literal value");
- if (!IntValue.isIntN(64)) {
- hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
- lo = IntValue.getLoBits(64).getZExtValue();
- } else {
- hi = 0;
- lo = IntValue.getZExtValue();
- }
+ if (parseHexOcta(*this, hi, lo))
+ return true;
if (MAI.isLittleEndian()) {
getStreamer().EmitIntValue(lo, 8);
getStreamer().EmitIntValue(hi, 8);
@@ -3248,21 +3279,20 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
}
/// parseDirectiveFile
-/// ::= .file [number] filename
-/// ::= .file number directory filename
+/// ::= .file filename
+/// ::= .file number [directory] filename [md5 checksum] [source source-text]
bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
// FIXME: I'm not sure what this is.
int64_t FileNumber = -1;
- SMLoc FileNumberLoc = getLexer().getLoc();
if (getLexer().is(AsmToken::Integer)) {
FileNumber = getTok().getIntVal();
Lex();
- if (FileNumber < 1)
- return TokError("file number less than one");
+ if (FileNumber < 0)
+ return TokError("negative file number");
}
- std::string Path = getTok().getString();
+ std::string Path;
// Usually the directory and filename together, otherwise just the directory.
// Allow the strings to have escaped octal character sequence.
@@ -3285,20 +3315,79 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
Filename = Path;
}
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.file' directive"))
- return true;
+ uint64_t MD5Hi, MD5Lo;
+ bool HasMD5 = false;
+
+ Optional<StringRef> Source;
+ bool HasSource = false;
+ std::string SourceString;
+
+ while (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ StringRef Keyword;
+ if (check(getTok().isNot(AsmToken::Identifier),
+ "unexpected token in '.file' directive") ||
+ parseIdentifier(Keyword))
+ return true;
+ if (Keyword == "md5") {
+ HasMD5 = true;
+ if (check(FileNumber == -1,
+ "MD5 checksum specified, but no file number") ||
+ parseHexOcta(*this, MD5Hi, MD5Lo))
+ return true;
+ } else if (Keyword == "source") {
+ HasSource = true;
+ if (check(FileNumber == -1,
+ "source specified, but no file number") ||
+ check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.file' directive") ||
+ parseEscapedString(SourceString))
+ return true;
+ } else {
+ return TokError("unexpected token in '.file' directive");
+ }
+ }
+
+ // In case there is a -g option as well as debug info from directive .file,
+ // we turn off the -g option, directly use the existing debug info instead.
+ // Also reset any implicit ".file 0" for the assembler source.
+ if (Ctx.getGenDwarfForAssembly()) {
+ Ctx.getMCDwarfLineTable(0).resetRootFile();
+ Ctx.setGenDwarfForAssembly(false);
+ }
if (FileNumber == -1)
getStreamer().EmitFileDirective(Filename);
else {
- // If there is -g option as well as debug info from directive file,
- // we turn off -g option, directly use the existing debug info instead.
- if (getContext().getGenDwarfForAssembly())
- getContext().setGenDwarfForAssembly(false);
- else if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename) ==
- 0)
- return Error(FileNumberLoc, "file number already allocated");
+ MD5::MD5Result *CKMem = nullptr;
+ if (HasMD5) {
+ CKMem = (MD5::MD5Result *)Ctx.allocate(sizeof(MD5::MD5Result), 1);
+ for (unsigned i = 0; i != 8; ++i) {
+ CKMem->Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
+ CKMem->Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
+ }
+ }
+ if (HasSource) {
+ char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
+ memcpy(SourceBuf, SourceString.data(), SourceString.size());
+ Source = StringRef(SourceBuf, SourceString.size());
+ }
+ if (FileNumber == 0) {
+ if (Ctx.getDwarfVersion() < 5)
+ return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5");
+ getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
+ } else {
+ Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
+ FileNumber, Directory, Filename, CKMem, Source);
+ if (!FileNumOrErr)
+ return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
+ FileNumber = FileNumOrErr.get();
+ }
+ // Alert the user if there are some .file directives with MD5 and some not.
+ // But only do that once.
+ if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
+ ReportedInconsistentMD5 = true;
+ return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
+ }
}
return false;
@@ -3332,7 +3421,7 @@ bool AsmParser::parseDirectiveLoc() {
int64_t FileNumber = 0, LineNumber = 0;
SMLoc Loc = getTok().getLoc();
if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
- check(FileNumber < 1, Loc,
+ check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
"file number less than one in '.loc' directive") ||
check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
"unassigned file number in '.loc' directive"))
@@ -3816,7 +3905,7 @@ bool AsmParser::parseDirectiveCFIEndProc() {
return false;
}
-/// \brief parse register name or number.
+/// parse register name or number.
bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
SMLoc DirectiveLoc) {
unsigned RegNo;
@@ -4211,7 +4300,10 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
const char *BodyEnd = EndToken.getLoc().getPointer();
StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
- getContext().defineMacro(Name, MCAsmMacro(Name, Body, std::move(Parameters)));
+ MCAsmMacro Macro(Name, Body, std::move(Parameters));
+ DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
+ Macro.dump());
+ getContext().defineMacro(Name, std::move(Macro));
return false;
}
@@ -4374,6 +4466,8 @@ bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
getContext().undefineMacro(Name);
+ DEBUG_WITH_TYPE("asm-macros", dbgs()
+ << "Un-defining macro: " << Name << "\n");
return false;
}
@@ -5207,6 +5301,8 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".ds.w"] = DK_DS_W;
DirectiveKindMap[".ds.x"] = DK_DS_X;
DirectiveKindMap[".print"] = DK_PRINT;
+ DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
+ DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
}
MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
@@ -5221,7 +5317,8 @@ MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
}
if (Lexer.is(AsmToken::Identifier) &&
- (getTok().getIdentifier() == ".rept" ||
+ (getTok().getIdentifier() == ".rep" ||
+ getTok().getIdentifier() == ".rept" ||
getTok().getIdentifier() == ".irp" ||
getTok().getIdentifier() == ".irpc")) {
++NestLevel;
@@ -5283,7 +5380,7 @@ bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
return true;
int64_t Count;
- if (!CountExpr->evaluateAsAbsolute(Count)) {
+ if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
}
@@ -5446,6 +5543,21 @@ bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
return false;
}
+bool AsmParser::parseDirectiveAddrsig() {
+ getStreamer().EmitAddrsig();
+ return false;
+}
+
+bool AsmParser::parseDirectiveAddrsigSym() {
+ StringRef Name;
+ if (check(parseIdentifier(Name),
+ "expected identifier in '.addrsig_sym' directive"))
+ return true;
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ getStreamer().EmitAddrsigSym(Sym);
+ return false;
+}
+
// We are comparing pointers, but the pointers are relative to a single string.
// Thus, this should always be deterministic.
static int rewritesSort(const AsmRewrite *AsmRewriteA,
@@ -5727,14 +5839,17 @@ static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
bool parseAssignmentExpression(StringRef Name, bool allow_redef,
MCAsmParser &Parser, MCSymbol *&Sym,
- const MCExpr *&Value) {
+ const MCExpr *&Value, bool AllowExtendedExpr) {
// FIXME: Use better location, we should use proper tokens.
SMLoc EqualLoc = Parser.getTok().getLoc();
-
- if (Parser.parseExpression(Value)) {
- return Parser.TokError("missing expression");
- }
+ SMLoc EndLoc;
+ if (AllowExtendedExpr) {
+ if (Parser.getTargetParser().parseAssignmentExpression(Value, EndLoc)) {
+ return Parser.TokError("missing expression");
+ }
+ } else if (Parser.parseExpression(Value, EndLoc))
+ return Parser.TokError("missing expression");
// Note: we don't count b as used in "a = b". This is to allow
// a = b
@@ -5780,7 +5895,7 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef,
} // end namespace MCParserUtils
} // end namespace llvm
-/// \brief Create an MCAsmParser instance.
+/// Create an MCAsmParser instance.
MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
MCStreamer &Out, const MCAsmInfo &MAI,
unsigned CB) {
diff --git a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp
index 687e0cc1faa5..388304a72395 100644
--- a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp
@@ -65,9 +65,11 @@ class COFFAsmParser : public MCAsmParserExtension {
addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
// Win64 EH directives.
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
@@ -130,8 +132,10 @@ class COFFAsmParser : public MCAsmParserExtension {
bool ParseDirectiveSecRel32(StringRef, SMLoc);
bool ParseDirectiveSecIdx(StringRef, SMLoc);
bool ParseDirectiveSafeSEH(StringRef, SMLoc);
+ bool ParseDirectiveSymIdx(StringRef, SMLoc);
bool parseCOMDATType(COFF::COMDATType &Type);
bool ParseDirectiveLinkOnce(StringRef, SMLoc);
+ bool ParseDirectiveRVA(StringRef, SMLoc);
// Win64 EH directives.
bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
@@ -490,6 +494,37 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
return false;
}
+bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {
+ auto parseOp = [&]() -> bool {
+ StringRef SymbolID;
+ if (getParser().parseIdentifier(SymbolID))
+ return TokError("expected identifier in directive");
+
+ int64_t Offset = 0;
+ SMLoc OffsetLoc;
+ if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
+ OffsetLoc = getLexer().getLoc();
+ if (getParser().parseAbsoluteExpression(Offset))
+ return true;
+ }
+
+ if (Offset < std::numeric_limits<int32_t>::min() ||
+ Offset > std::numeric_limits<int32_t>::max())
+ return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
+ "than -2147483648 or greater than "
+ "2147483647");
+
+ MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
+
+ getStreamer().EmitCOFFImgRel32(Symbol, Offset);
+ return false;
+ };
+
+ if (getParser().parseMany(parseOp))
+ return addErrorSuffix(" in directive");
+ return false;
+}
+
bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
StringRef SymbolID;
if (getParser().parseIdentifier(SymbolID))
@@ -520,6 +555,21 @@ bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
return false;
}
+bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
+ StringRef SymbolID;
+ if (getParser().parseIdentifier(SymbolID))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
+
+ Lex();
+ getStreamer().EmitCOFFSymbolIndex(Symbol);
+ return false;
+}
+
/// ::= [ identifier ]
bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
StringRef TypeId = getTok().getIdentifier();
diff --git a/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
index 5bbf49290f17..e6fc1fac81ba 100644
--- a/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
+++ b/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -40,7 +40,7 @@ using namespace llvm;
namespace {
-/// \brief Implementation of directive handling which is shared across all
+/// Implementation of directive handling which is shared across all
/// Darwin targets.
class DarwinAsmParser : public MCAsmParserExtension {
template<bool (DarwinAsmParser::*HandlerMethod)(StringRef, SMLoc)>
@@ -888,6 +888,7 @@ bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {
Lex();
StringRef Section;
+ SMLoc SectionLoc = getLexer().getLoc();
if (getParser().parseIdentifier(Section))
return TokError("expected section name after comma in '.zerofill' "
"directive");
@@ -896,9 +897,10 @@ bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {
// the section but with no symbol.
if (getLexer().is(AsmToken::EndOfStatement)) {
// Create the zerofill section but no symbol
- getStreamer().EmitZerofill(getContext().getMachOSection(
- Segment, Section, MachO::S_ZEROFILL,
- 0, SectionKind::getBSS()));
+ getStreamer().EmitZerofill(
+ getContext().getMachOSection(Segment, Section, MachO::S_ZEROFILL, 0,
+ SectionKind::getBSS()),
+ /*Symbol=*/nullptr, /*Size=*/0, /*ByteAlignment=*/0, SectionLoc);
return false;
}
@@ -957,7 +959,7 @@ bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {
getStreamer().EmitZerofill(getContext().getMachOSection(
Segment, Section, MachO::S_ZEROFILL,
0, SectionKind::getBSS()),
- Sym, Size, 1 << Pow2Alignment);
+ Sym, Size, 1 << Pow2Alignment, SectionLoc);
return false;
}
diff --git a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp
index 17f0bf845785..67e3512cc5bd 100644
--- a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp
@@ -85,6 +85,7 @@ public:
addDirectiveHandler<
&ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
}
// FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
@@ -149,6 +150,7 @@ public:
bool ParseDirectiveWeakref(StringRef, SMLoc);
bool ParseDirectiveSymbolAttribute(StringRef, SMLoc);
bool ParseDirectiveSubsection(StringRef, SMLoc);
+ bool ParseDirectiveCGProfile(StringRef, SMLoc);
private:
bool ParseSectionName(StringRef &SectionName);
@@ -380,7 +382,6 @@ bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
return false;
}
-// FIXME: This is a work in progress.
bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) {
return ParseSectionArguments(/*IsPush=*/false, loc);
}
@@ -480,6 +481,34 @@ static bool hasPrefix(StringRef SectionName, StringRef Prefix) {
return SectionName.startswith(Prefix) || SectionName == Prefix.drop_back();
}
+// Return a set of section flags based on the section name that can then
+// be augmented later, otherwise return 0 if we don't have any reasonable
+// defaults.
+static unsigned defaultSectionFlags(StringRef SectionName) {
+
+ if (hasPrefix(SectionName, ".rodata.cst"))
+ return ELF::SHF_ALLOC | ELF::SHF_MERGE;
+
+ if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1")
+ return ELF::SHF_ALLOC;
+
+ if (SectionName == ".fini" || SectionName == ".init" ||
+ hasPrefix(SectionName, ".text."))
+ return ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;
+
+ if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" ||
+ hasPrefix(SectionName, ".bss.") ||
+ hasPrefix(SectionName, ".init_array.") ||
+ hasPrefix(SectionName, ".fini_array.") ||
+ hasPrefix(SectionName, ".preinit_array."))
+ return ELF::SHF_ALLOC | ELF::SHF_WRITE;
+
+ if (hasPrefix(SectionName, ".tdata.") || hasPrefix(SectionName, ".tbss."))
+ return ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS;
+
+ return 0;
+}
+
bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
StringRef SectionName;
@@ -489,27 +518,13 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
StringRef TypeName;
int64_t Size = 0;
StringRef GroupName;
- unsigned Flags = 0;
const MCExpr *Subsection = nullptr;
bool UseLastGroup = false;
MCSymbolELF *Associated = nullptr;
int64_t UniqueID = ~0;
- // Set the defaults first.
- if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1")
- Flags |= ELF::SHF_ALLOC;
- if (SectionName == ".fini" || SectionName == ".init" ||
- hasPrefix(SectionName, ".text."))
- Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;
- if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" ||
- hasPrefix(SectionName, ".bss.") ||
- hasPrefix(SectionName, ".init_array.") ||
- hasPrefix(SectionName, ".fini_array.") ||
- hasPrefix(SectionName, ".preinit_array."))
- Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE;
- if (hasPrefix(SectionName, ".tdata.") ||
- hasPrefix(SectionName, ".tbss."))
- Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS;
+ // Set the default section flags first in case no others are given.
+ unsigned Flags = defaultSectionFlags(SectionName);
if (getLexer().is(AsmToken::Comma)) {
Lex();
@@ -537,6 +552,12 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
if (extraFlags == -1U)
return TokError("unknown flag");
+
+ // If we found additional section flags on a known section then give a
+ // warning.
+ if (Flags && Flags != extraFlags)
+ Warning(loc, "setting incorrect section attributes for " + SectionName);
+
Flags |= extraFlags;
bool Mergeable = Flags & ELF::SHF_MERGE;
@@ -608,6 +629,10 @@ EndStmt:
Type = ELF::SHT_X86_64_UNWIND;
else if (TypeName == "llvm_odrtab")
Type = ELF::SHT_LLVM_ODRTAB;
+ else if (TypeName == "llvm_linker_options")
+ Type = ELF::SHT_LLVM_LINKER_OPTIONS;
+ else if (TypeName == "llvm_call_graph_profile")
+ Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
else if (TypeName.getAsInteger(0, Type))
return TokError("unknown section type");
}
@@ -838,6 +863,47 @@ bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) {
return false;
}
+/// ParseDirectiveCGProfile
+/// ::= .cg_profile identifier, identifier, <number>
+bool ELFAsmParser::ParseDirectiveCGProfile(StringRef, SMLoc) {
+ StringRef From;
+ SMLoc FromLoc = getLexer().getLoc();
+ if (getParser().parseIdentifier(From))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected a comma");
+ Lex();
+
+ StringRef To;
+ SMLoc ToLoc = getLexer().getLoc();
+ if (getParser().parseIdentifier(To))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected a comma");
+ Lex();
+
+ int64_t Count;
+ if (getParser().parseIntToken(
+ Count, "expected integer count in '.cg_profile' directive"))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ MCSymbol *FromSym = getContext().getOrCreateSymbol(From);
+ MCSymbol *ToSym = getContext().getOrCreateSymbol(To);
+
+ getStreamer().emitCGProfileEntry(
+ MCSymbolRefExpr::create(FromSym, MCSymbolRefExpr::VK_None, getContext(),
+ FromLoc),
+ MCSymbolRefExpr::create(ToSym, MCSymbolRefExpr::VK_None, getContext(),
+ ToLoc),
+ Count);
+ return false;
+}
+
namespace llvm {
MCAsmParserExtension *createELFAsmParser() {
diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp
index 8f845ee1d76f..75cd318e4fa3 100644
--- a/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp
+++ b/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp
@@ -10,6 +10,8 @@
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -34,3 +36,94 @@ SMLoc AsmToken::getEndLoc() const {
SMRange AsmToken::getLocRange() const {
return SMRange(getLoc(), getEndLoc());
}
+
+void AsmToken::dump(raw_ostream &OS) const {
+ switch (Kind) {
+ case AsmToken::Error:
+ OS << "error";
+ break;
+ case AsmToken::Identifier:
+ OS << "identifier: " << getString();
+ break;
+ case AsmToken::Integer:
+ OS << "int: " << getString();
+ break;
+ case AsmToken::Real:
+ OS << "real: " << getString();
+ break;
+ case AsmToken::String:
+ OS << "string: " << getString();
+ break;
+
+ case AsmToken::Amp: OS << "Amp"; break;
+ case AsmToken::AmpAmp: OS << "AmpAmp"; break;
+ case AsmToken::At: OS << "At"; break;
+ case AsmToken::BackSlash: OS << "BackSlash"; break;
+ case AsmToken::BigNum: OS << "BigNum"; break;
+ case AsmToken::Caret: OS << "Caret"; break;
+ case AsmToken::Colon: OS << "Colon"; break;
+ case AsmToken::Comma: OS << "Comma"; break;
+ case AsmToken::Comment: OS << "Comment"; break;
+ case AsmToken::Dollar: OS << "Dollar"; break;
+ case AsmToken::Dot: OS << "Dot"; break;
+ case AsmToken::EndOfStatement: OS << "EndOfStatement"; break;
+ case AsmToken::Eof: OS << "Eof"; break;
+ case AsmToken::Equal: OS << "Equal"; break;
+ case AsmToken::EqualEqual: OS << "EqualEqual"; break;
+ case AsmToken::Exclaim: OS << "Exclaim"; break;
+ case AsmToken::ExclaimEqual: OS << "ExclaimEqual"; break;
+ case AsmToken::Greater: OS << "Greater"; break;
+ case AsmToken::GreaterEqual: OS << "GreaterEqual"; break;
+ case AsmToken::GreaterGreater: OS << "GreaterGreater"; break;
+ case AsmToken::Hash: OS << "Hash"; break;
+ case AsmToken::HashDirective: OS << "HashDirective"; break;
+ case AsmToken::LBrac: OS << "LBrac"; break;
+ case AsmToken::LCurly: OS << "LCurly"; break;
+ case AsmToken::LParen: OS << "LParen"; break;
+ case AsmToken::Less: OS << "Less"; break;
+ case AsmToken::LessEqual: OS << "LessEqual"; break;
+ case AsmToken::LessGreater: OS << "LessGreater"; break;
+ case AsmToken::LessLess: OS << "LessLess"; break;
+ case AsmToken::Minus: OS << "Minus"; break;
+ case AsmToken::Percent: OS << "Percent"; break;
+ case AsmToken::Pipe: OS << "Pipe"; break;
+ case AsmToken::PipePipe: OS << "PipePipe"; break;
+ case AsmToken::Plus: OS << "Plus"; break;
+ case AsmToken::RBrac: OS << "RBrac"; break;
+ case AsmToken::RCurly: OS << "RCurly"; break;
+ case AsmToken::RParen: OS << "RParen"; break;
+ case AsmToken::Slash: OS << "Slash"; break;
+ case AsmToken::Space: OS << "Space"; break;
+ case AsmToken::Star: OS << "Star"; break;
+ case AsmToken::Tilde: OS << "Tilde"; break;
+ case AsmToken::PercentCall16: OS << "PercentCall16"; break;
+ case AsmToken::PercentCall_Hi: OS << "PercentCall_Hi"; break;
+ case AsmToken::PercentCall_Lo: OS << "PercentCall_Lo"; break;
+ case AsmToken::PercentDtprel_Hi: OS << "PercentDtprel_Hi"; break;
+ case AsmToken::PercentDtprel_Lo: OS << "PercentDtprel_Lo"; break;
+ case AsmToken::PercentGot: OS << "PercentGot"; break;
+ case AsmToken::PercentGot_Disp: OS << "PercentGot_Disp"; break;
+ case AsmToken::PercentGot_Hi: OS << "PercentGot_Hi"; break;
+ case AsmToken::PercentGot_Lo: OS << "PercentGot_Lo"; break;
+ case AsmToken::PercentGot_Ofst: OS << "PercentGot_Ofst"; break;
+ case AsmToken::PercentGot_Page: OS << "PercentGot_Page"; break;
+ case AsmToken::PercentGottprel: OS << "PercentGottprel"; break;
+ case AsmToken::PercentGp_Rel: OS << "PercentGp_Rel"; break;
+ case AsmToken::PercentHi: OS << "PercentHi"; break;
+ case AsmToken::PercentHigher: OS << "PercentHigher"; break;
+ case AsmToken::PercentHighest: OS << "PercentHighest"; break;
+ case AsmToken::PercentLo: OS << "PercentLo"; break;
+ case AsmToken::PercentNeg: OS << "PercentNeg"; break;
+ case AsmToken::PercentPcrel_Hi: OS << "PercentPcrel_Hi"; break;
+ case AsmToken::PercentPcrel_Lo: OS << "PercentPcrel_Lo"; break;
+ case AsmToken::PercentTlsgd: OS << "PercentTlsgd"; break;
+ case AsmToken::PercentTlsldm: OS << "PercentTlsldm"; break;
+ case AsmToken::PercentTprel_Hi: OS << "PercentTprel_Hi"; break;
+ case AsmToken::PercentTprel_Lo: OS << "PercentTprel_Lo"; break;
+ }
+
+ // Print the token string.
+ OS << " (\"";
+ OS.write_escaped(getString());
+ OS << "\")";
+}
diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp
index 6a4c74cd57fe..d439734e76fc 100644
--- a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp
+++ b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp
@@ -10,6 +10,7 @@
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
@@ -85,7 +86,6 @@ bool MCAsmParser::TokError(const Twine &Msg, SMRange Range) {
}
bool MCAsmParser::Error(SMLoc L, const Twine &Msg, SMRange Range) {
- HadError = true;
MCPendingError PErr;
PErr.Loc = L;
diff --git a/contrib/llvm/lib/MC/MCSchedule.cpp b/contrib/llvm/lib/MC/MCSchedule.cpp
index f3919427bf05..929bd7f6046c 100644
--- a/contrib/llvm/lib/MC/MCSchedule.cpp
+++ b/contrib/llvm/lib/MC/MCSchedule.cpp
@@ -12,6 +12,10 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCSchedule.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
#include <type_traits>
using namespace llvm;
@@ -31,4 +35,118 @@ const MCSchedModel MCSchedModel::Default = {DefaultIssueWidth,
nullptr,
0,
0,
+ nullptr,
nullptr};
+
+int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
+ const MCSchedClassDesc &SCDesc) {
+ int Latency = 0;
+ for (unsigned DefIdx = 0, DefEnd = SCDesc.NumWriteLatencyEntries;
+ DefIdx != DefEnd; ++DefIdx) {
+ // Lookup the definition's write latency in SubtargetInfo.
+ const MCWriteLatencyEntry *WLEntry =
+ STI.getWriteLatencyEntry(&SCDesc, DefIdx);
+ // Early exit if we found an invalid latency.
+ if (WLEntry->Cycles < 0)
+ return WLEntry->Cycles;
+ Latency = std::max(Latency, static_cast<int>(WLEntry->Cycles));
+ }
+ return Latency;
+}
+
+int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
+ unsigned SchedClass) const {
+ const MCSchedClassDesc &SCDesc = *getSchedClassDesc(SchedClass);
+ if (!SCDesc.isValid())
+ return 0;
+ if (!SCDesc.isVariant())
+ return MCSchedModel::computeInstrLatency(STI, SCDesc);
+
+ llvm_unreachable("unsupported variant scheduling class");
+}
+
+int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
+ const MCInstrInfo &MCII,
+ const MCInst &Inst) const {
+ unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
+ const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
+ if (!SCDesc->isValid())
+ return 0;
+
+ unsigned CPUID = getProcessorID();
+ while (SCDesc->isVariant()) {
+ SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, CPUID);
+ SCDesc = getSchedClassDesc(SchedClass);
+ }
+
+ if (SchedClass)
+ return MCSchedModel::computeInstrLatency(STI, *SCDesc);
+
+ llvm_unreachable("unsupported variant scheduling class");
+}
+
+double
+MCSchedModel::getReciprocalThroughput(const MCSubtargetInfo &STI,
+ const MCSchedClassDesc &SCDesc) {
+ Optional<double> Throughput;
+ const MCSchedModel &SM = STI.getSchedModel();
+ const MCWriteProcResEntry *I = STI.getWriteProcResBegin(&SCDesc);
+ const MCWriteProcResEntry *E = STI.getWriteProcResEnd(&SCDesc);
+ for (; I != E; ++I) {
+ if (!I->Cycles)
+ continue;
+ unsigned NumUnits = SM.getProcResource(I->ProcResourceIdx)->NumUnits;
+ double Temp = NumUnits * 1.0 / I->Cycles;
+ Throughput = Throughput ? std::min(Throughput.getValue(), Temp) : Temp;
+ }
+ if (Throughput.hasValue())
+ return 1.0 / Throughput.getValue();
+
+ // If no throughput value was calculated, assume that we can execute at the
+ // maximum issue width scaled by number of micro-ops for the schedule class.
+ return ((double)SCDesc.NumMicroOps) / SM.IssueWidth;
+}
+
+double
+MCSchedModel::getReciprocalThroughput(const MCSubtargetInfo &STI,
+ const MCInstrInfo &MCII,
+ const MCInst &Inst) const {
+ unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
+ const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
+
+ // If there's no valid class, assume that the instruction executes/completes
+ // at the maximum issue width.
+ if (!SCDesc->isValid())
+ return 1.0 / IssueWidth;
+
+ unsigned CPUID = getProcessorID();
+ while (SCDesc->isVariant()) {
+ SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, CPUID);
+ SCDesc = getSchedClassDesc(SchedClass);
+ }
+
+ if (SchedClass)
+ return MCSchedModel::getReciprocalThroughput(STI, *SCDesc);
+
+ llvm_unreachable("unsupported variant scheduling class");
+}
+
+double
+MCSchedModel::getReciprocalThroughput(unsigned SchedClass,
+ const InstrItineraryData &IID) {
+ Optional<double> Throughput;
+ const InstrStage *I = IID.beginStage(SchedClass);
+ const InstrStage *E = IID.endStage(SchedClass);
+ for (; I != E; ++I) {
+ if (!I->getCycles())
+ continue;
+ double Temp = countPopulation(I->getUnits()) * 1.0 / I->getCycles();
+ Throughput = Throughput ? std::min(Throughput.getValue(), Temp) : Temp;
+ }
+ if (Throughput.hasValue())
+ return 1.0 / Throughput.getValue();
+
+ // If there are no execution resources specified for this class, then assume
+ // that it can execute at the maximum default issue width.
+ return 1.0 / DefaultIssueWidth;
+}
diff --git a/contrib/llvm/lib/MC/MCSection.cpp b/contrib/llvm/lib/MC/MCSection.cpp
index d141dd6627c4..97bc65387dd5 100644
--- a/contrib/llvm/lib/MC/MCSection.cpp
+++ b/contrib/llvm/lib/MC/MCSection.cpp
@@ -9,6 +9,7 @@
#include "llvm/MC/MCSection.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCFragment.h"
#include "llvm/MC/MCSymbol.h"
diff --git a/contrib/llvm/lib/MC/MCSectionCOFF.cpp b/contrib/llvm/lib/MC/MCSectionCOFF.cpp
index 72a7fc36a460..c861963eec8a 100644
--- a/contrib/llvm/lib/MC/MCSectionCOFF.cpp
+++ b/contrib/llvm/lib/MC/MCSectionCOFF.cpp
@@ -69,35 +69,40 @@ void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
OS << '"';
if (getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) {
- OS << ",";
+ if (COMDATSymbol)
+ OS << ",";
+ else
+ OS << "\n\t.linkonce\t";
switch (Selection) {
case COFF::IMAGE_COMDAT_SELECT_NODUPLICATES:
- OS << "one_only,";
+ OS << "one_only";
break;
case COFF::IMAGE_COMDAT_SELECT_ANY:
- OS << "discard,";
+ OS << "discard";
break;
case COFF::IMAGE_COMDAT_SELECT_SAME_SIZE:
- OS << "same_size,";
+ OS << "same_size";
break;
case COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH:
- OS << "same_contents,";
+ OS << "same_contents";
break;
case COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE:
- OS << "associative,";
+ OS << "associative";
break;
case COFF::IMAGE_COMDAT_SELECT_LARGEST:
- OS << "largest,";
+ OS << "largest";
break;
case COFF::IMAGE_COMDAT_SELECT_NEWEST:
- OS << "newest,";
+ OS << "newest";
break;
default:
assert(false && "unsupported COFF selection type");
break;
}
- assert(COMDATSymbol);
- COMDATSymbol->print(OS, &MAI);
+ if (COMDATSymbol) {
+ OS << ",";
+ COMDATSymbol->print(OS, &MAI);
+ }
}
OS << '\n';
}
diff --git a/contrib/llvm/lib/MC/MCSectionELF.cpp b/contrib/llvm/lib/MC/MCSectionELF.cpp
index bf1fcb03273c..4d77d05cc505 100644
--- a/contrib/llvm/lib/MC/MCSectionELF.cpp
+++ b/contrib/llvm/lib/MC/MCSectionELF.cpp
@@ -148,6 +148,10 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
OS << "0x7000001e";
else if (Type == ELF::SHT_LLVM_ODRTAB)
OS << "llvm_odrtab";
+ else if (Type == ELF::SHT_LLVM_LINKER_OPTIONS)
+ OS << "llvm_linker_options";
+ else if (Type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE)
+ OS << "llvm_call_graph_profile";
else
report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) +
" for section " + getSectionName());
diff --git a/contrib/llvm/lib/MC/MCStreamer.cpp b/contrib/llvm/lib/MC/MCStreamer.cpp
index db6f81deacf6..8dd4b61be68f 100644
--- a/contrib/llvm/lib/MC/MCStreamer.cpp
+++ b/contrib/llvm/lib/MC/MCStreamer.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCStreamer.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
@@ -74,7 +75,8 @@ void MCTargetStreamer::emitValue(const MCExpr *Value) {
void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {}
MCStreamer::MCStreamer(MCContext &Ctx)
- : Context(Ctx), CurrentWinFrameInfo(nullptr) {
+ : Context(Ctx), CurrentWinFrameInfo(nullptr),
+ UseAssemblerInfoForParsing(false) {
SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
}
@@ -120,20 +122,16 @@ void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
EmitBytes(StringRef(buf, Size));
}
-/// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
+/// EmitULEB128IntValue - Special case of EmitULEB128Value that avoids the
/// client having to pass in a MCExpr for constant integers.
-void MCStreamer::EmitPaddedULEB128IntValue(uint64_t Value, unsigned PadTo) {
+void MCStreamer::EmitULEB128IntValue(uint64_t Value) {
SmallString<128> Tmp;
raw_svector_ostream OSE(Tmp);
- encodeULEB128(Value, OSE, PadTo);
+ encodeULEB128(Value, OSE);
EmitBytes(OSE.str());
}
-void MCStreamer::EmitULEB128IntValue(uint64_t Value) {
- EmitPaddedULEB128IntValue(Value, 0);
-}
-
-/// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
+/// EmitSLEB128IntValue - Special case of EmitSLEB128Value that avoids the
/// client having to pass in a MCExpr for constant integers.
void MCStreamer::EmitSLEB128IntValue(int64_t Value) {
SmallString<128> Tmp;
@@ -187,25 +185,28 @@ void MCStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) {
emitFill(*MCConstantExpr::create(NumBytes, getContext()), FillValue);
}
-void MCStreamer::emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) {
- int64_t NonZeroSize = Size > 4 ? 4 : Size;
- Expr &= ~0ULL >> (64 - NonZeroSize * 8);
- for (uint64_t i = 0, e = NumValues; i != e; ++i) {
- EmitIntValue(Expr, NonZeroSize);
- if (NonZeroSize < Size)
- EmitIntValue(0, Size - NonZeroSize);
- }
-}
-
/// The implementation in this class just redirects to emitFill.
void MCStreamer::EmitZeros(uint64_t NumBytes) {
emitFill(NumBytes, 0);
}
-unsigned MCStreamer::EmitDwarfFileDirective(unsigned FileNo,
- StringRef Directory,
- StringRef Filename, unsigned CUID) {
- return getContext().getDwarfFile(Directory, Filename, FileNo, CUID);
+Expected<unsigned>
+MCStreamer::tryEmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
+ StringRef Filename,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> Source,
+ unsigned CUID) {
+ return getContext().getDwarfFile(Directory, Filename, FileNo, Checksum,
+ Source, CUID);
+}
+
+void MCStreamer::emitDwarfFile0Directive(StringRef Directory,
+ StringRef Filename,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> Source,
+ unsigned CUID) {
+ getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
+ Source);
}
void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
@@ -660,6 +661,10 @@ void MCStreamer::EmitWinEHHandlerData(SMLoc Loc) {
getContext().reportError(Loc, "Chained unwind areas can't have handlers!");
}
+void MCStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To, uint64_t Count) {
+}
+
static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID,
MCSection *MainCFISec,
const MCSection *TextSec) {
@@ -668,16 +673,31 @@ static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID,
return MainCFISec;
const auto *TextSecCOFF = cast<MCSectionCOFF>(TextSec);
+ auto *MainCFISecCOFF = cast<MCSectionCOFF>(MainCFISec);
unsigned UniqueID = TextSecCOFF->getOrAssignWinCFISectionID(NextWinCFIID);
// If this section is COMDAT, this unwind section should be COMDAT associative
// with its group.
const MCSymbol *KeySym = nullptr;
- if (TextSecCOFF->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
+ if (TextSecCOFF->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) {
KeySym = TextSecCOFF->getCOMDATSymbol();
- return Context.getAssociativeCOFFSection(cast<MCSectionCOFF>(MainCFISec),
- KeySym, UniqueID);
+ // In a GNU environment, we can't use associative comdats. Instead, do what
+ // GCC does, which is to make plain comdat selectany section named like
+ // ".[px]data$_Z3foov".
+ if (!Context.getAsmInfo()->hasCOFFAssociativeComdats()) {
+ std::string SectionName =
+ (MainCFISecCOFF->getSectionName() + "$" +
+ TextSecCOFF->getSectionName().split('$').second)
+ .str();
+ return Context.getCOFFSection(
+ SectionName,
+ MainCFISecCOFF->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT,
+ MainCFISecCOFF->getKind(), "", COFF::IMAGE_COMDAT_SELECT_ANY);
+ }
+ }
+
+ return Context.getAssociativeCOFFSection(MainCFISecCOFF, KeySym, UniqueID);
}
MCSection *MCStreamer::getAssociatedPDataSection(const MCSection *TextSec) {
@@ -803,11 +823,15 @@ void MCStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
}
+void MCStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {}
+
void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
}
void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {}
+void MCStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {}
+
/// EmitRawText - 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 hasRawTextSupport() predicate.
@@ -826,10 +850,11 @@ void MCStreamer::EmitWindowsUnwindTables() {
}
void MCStreamer::Finish() {
- if (!DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End)
- getContext().reportError(SMLoc(), "Unfinished frame!");
- if (!WinFrameInfos.empty() && !WinFrameInfos.back()->End)
+ if ((!DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End) ||
+ (!WinFrameInfos.empty() && !WinFrameInfos.back()->End)) {
getContext().reportError(SMLoc(), "Unfinished frame!");
+ return;
+ }
MCTargetStreamer *TS = getTargetStreamer();
if (TS)
@@ -908,6 +933,16 @@ void MCStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
EmitSymbolValue(SetLabel, Size);
}
+void MCStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
+ const MCSymbol *Lo) {
+ // Get the Hi-Lo expression.
+ const MCExpr *Diff =
+ MCBinaryExpr::createSub(MCSymbolRefExpr::create(Hi, Context),
+ MCSymbolRefExpr::create(Lo, Context), Context);
+
+ EmitULEB128Value(Diff);
+}
+
void MCStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {}
void MCStreamer::EmitThumbFunc(MCSymbol *Func) {}
void MCStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
diff --git a/contrib/llvm/lib/MC/MCSubtargetInfo.cpp b/contrib/llvm/lib/MC/MCSubtargetInfo.cpp
index 8b9b076382e2..f6167826fae2 100644
--- a/contrib/llvm/lib/MC/MCSubtargetInfo.cpp
+++ b/contrib/llvm/lib/MC/MCSubtargetInfo.cpp
@@ -51,8 +51,6 @@ MCSubtargetInfo::MCSubtargetInfo(
InitMCProcessorInfo(CPU, FS);
}
-/// ToggleFeature - Toggle a feature and returns the re-computed feature
-/// bits. This version does not change the implied bits.
FeatureBitset MCSubtargetInfo::ToggleFeature(uint64_t FB) {
FeatureBits.flip(FB);
return FeatureBits;
@@ -63,8 +61,6 @@ FeatureBitset MCSubtargetInfo::ToggleFeature(const FeatureBitset &FB) {
return FeatureBits;
}
-/// ToggleFeature - Toggle a feature and returns the re-computed feature
-/// bits. This version will also change all implied bits.
FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef FS) {
SubtargetFeatures::ToggleFeature(FeatureBits, FS, ProcFeatures);
return FeatureBits;
@@ -118,7 +114,6 @@ MCSubtargetInfo::getInstrItineraryForCPU(StringRef CPU) const {
return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths);
}
-/// Initialize an InstrItineraryData instance.
void MCSubtargetInfo::initInstrItins(InstrItineraryData &InstrItins) const {
InstrItins = InstrItineraryData(getSchedModel(), Stages, OperandCycles,
ForwardingPaths);
diff --git a/contrib/llvm/lib/MC/MCSymbol.cpp b/contrib/llvm/lib/MC/MCSymbol.cpp
index 9abaaef2fe84..5502c658f565 100644
--- a/contrib/llvm/lib/MC/MCSymbol.cpp
+++ b/contrib/llvm/lib/MC/MCSymbol.cpp
@@ -9,6 +9,7 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
diff --git a/contrib/llvm/lib/MC/MCValue.cpp b/contrib/llvm/lib/MC/MCValue.cpp
index 32a6adbf224e..7e03913aa680 100644
--- a/contrib/llvm/lib/MC/MCValue.cpp
+++ b/contrib/llvm/lib/MC/MCValue.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCValue.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp
index 301f30d4f6ec..59082a160caf 100644
--- a/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp
+++ b/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp
@@ -7,9 +7,6 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCWasmObjectWriter.h"
using namespace llvm;
diff --git a/contrib/llvm/lib/MC/MCWasmStreamer.cpp b/contrib/llvm/lib/MC/MCWasmStreamer.cpp
index d9cefbd3994f..0e5932214047 100644
--- a/contrib/llvm/lib/MC/MCWasmStreamer.cpp
+++ b/contrib/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());
}
@@ -66,6 +67,7 @@ void MCWasmStreamer::ChangeSection(MCSection *Section,
Asm.registerSymbol(*Grp);
this->MCObjectStreamer::ChangeSection(Section, Subsection);
+ Asm.registerSymbol(*Section->getBeginSymbol());
}
void MCWasmStreamer::EmitWeakReference(MCSymbol *Alias,
@@ -81,9 +83,9 @@ bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
auto *Symbol = cast<MCSymbolWasm>(S);
- // Adding a symbol attribute always introduces the symbol, note that an
- // important side effect of calling registerSymbol here is to register
- // the symbol with the assembler.
+ // Adding a symbol attribute always introduces the symbol; note that an
+ // important side effect of calling registerSymbol here is to register the
+ // symbol with the assembler.
getAssembler().registerSymbol(*Symbol);
switch (Attribute) {
@@ -113,11 +115,11 @@ bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
break;
case MCSA_ELF_TypeFunction:
- Symbol->setIsFunction(true);
+ Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
break;
case MCSA_ELF_TypeObject:
- Symbol->setIsFunction(false);
+ Symbol->setType(wasm::WASM_SYMBOL_TYPE_DATA);
break;
default:
@@ -156,17 +158,8 @@ void MCWasmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
}
void MCWasmStreamer::EmitIdent(StringRef IdentString) {
- MCSection *Comment = getAssembler().getContext().getWasmSection(
- ".comment", SectionKind::getMetadata());
- PushSection();
- SwitchSection(Comment);
- if (!SeenIdent) {
- EmitIntValue(0, 1);
- SeenIdent = true;
- }
- EmitBytes(IdentString);
- EmitIntValue(0, 1);
- PopSection();
+ // TODO(sbc): Add the ident section once we support mergable strings
+ // sections in the object format
}
void MCWasmStreamer::EmitInstToFragment(const MCInst &Inst,
@@ -191,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());
}
@@ -203,11 +196,11 @@ void MCWasmStreamer::FinishImpl() {
MCStreamer *llvm::createWasmStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> &&MAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&CE,
bool RelaxAll) {
MCWasmStreamer *S =
- new MCWasmStreamer(Context, std::move(MAB), OS, std::move(CE));
+ new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
if (RelaxAll)
S->getAssembler().setRelaxAll(true);
return S;
@@ -222,7 +215,8 @@ void MCWasmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
}
void MCWasmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment) {
+ uint64_t Size, unsigned ByteAlignment,
+ SMLoc Loc) {
llvm_unreachable("Wasm doesn't support this directive");
}
diff --git a/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp b/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp
index 8582d9adafb8..7b1dc7abf708 100644
--- a/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp
+++ b/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp
@@ -25,6 +25,7 @@
#include "llvm/MC/MCFragment.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbolCOFF.h"
#include "llvm/MC/MCWinCOFFStreamer.h"
@@ -44,8 +45,8 @@ using namespace llvm;
MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> MAB,
std::unique_ptr<MCCodeEmitter> CE,
- raw_pwrite_stream &OS)
- : MCObjectStreamer(Context, std::move(MAB), OS, std::move(CE)),
+ std::unique_ptr<MCObjectWriter> OW)
+ : MCObjectStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)),
CurSymbol(nullptr) {}
void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst,
@@ -62,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());
}
@@ -193,6 +194,17 @@ void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
<< COFF::SCT_COMPLEX_TYPE_SHIFT);
}
+void MCWinCOFFStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
+ MCSection *Sec = getCurrentSectionOnly();
+ getAssembler().registerSection(*Sec);
+ if (Sec->getAlignment() < 4)
+ Sec->setAlignment(4);
+
+ new MCSymbolIdFragment(Symbol, getCurrentSectionOnly());
+
+ getAssembler().registerSymbol(*Symbol);
+}
+
void MCWinCOFFStreamer::EmitCOFFSectionIndex(const MCSymbol *Symbol) {
visitUsedSymbol(*Symbol);
MCDataFragment *DF = getOrCreateDataFragment();
@@ -220,6 +232,25 @@ void MCWinCOFFStreamer::EmitCOFFSecRel32(const MCSymbol *Symbol,
DF->getContents().resize(DF->getContents().size() + 4, 0);
}
+void MCWinCOFFStreamer::EmitCOFFImgRel32(const MCSymbol *Symbol,
+ int64_t Offset) {
+ visitUsedSymbol(*Symbol);
+ MCDataFragment *DF = getOrCreateDataFragment();
+ // Create Symbol A for the relocation relative reference.
+ const MCExpr *MCE = MCSymbolRefExpr::create(
+ Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32, getContext());
+ // Add the constant offset, if given.
+ if (Offset)
+ MCE = MCBinaryExpr::createAdd(
+ MCE, MCConstantExpr::create(Offset, getContext()), getContext());
+ // Build the imgrel relocation.
+ MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4);
+ // Record the relocation.
+ DF->getFixups().push_back(Fixup);
+ // Emit 4 bytes (zeros) to the object file.
+ DF->getContents().resize(DF->getContents().size() + 4, 0);
+}
+
void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
unsigned ByteAlignment) {
auto *Symbol = cast<MCSymbolCOFF>(S);
@@ -267,7 +298,8 @@ void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
}
void MCWinCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment) {
+ uint64_t Size, unsigned ByteAlignment,
+ SMLoc Loc) {
llvm_unreachable("not implemented");
}
diff --git a/contrib/llvm/lib/MC/MachObjectWriter.cpp b/contrib/llvm/lib/MC/MachObjectWriter.cpp
index c7eaa76ace3c..a464af1d42a7 100644
--- a/contrib/llvm/lib/MC/MachObjectWriter.cpp
+++ b/contrib/llvm/lib/MC/MachObjectWriter.cpp
@@ -141,24 +141,29 @@ void MachObjectWriter::writeHeader(MachO::HeaderFileType Type,
// struct mach_header (28 bytes) or
// struct mach_header_64 (32 bytes)
- uint64_t Start = getStream().tell();
+ uint64_t Start = W.OS.tell();
(void) Start;
- write32(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC);
+ W.write<uint32_t>(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC);
- write32(TargetObjectWriter->getCPUType());
- write32(TargetObjectWriter->getCPUSubtype());
+ W.write<uint32_t>(TargetObjectWriter->getCPUType());
+ W.write<uint32_t>(TargetObjectWriter->getCPUSubtype());
- write32(Type);
- write32(NumLoadCommands);
- write32(LoadCommandsSize);
- write32(Flags);
+ W.write<uint32_t>(Type);
+ W.write<uint32_t>(NumLoadCommands);
+ W.write<uint32_t>(LoadCommandsSize);
+ W.write<uint32_t>(Flags);
if (is64Bit())
- write32(0); // reserved
+ W.write<uint32_t>(0); // reserved
- assert(
- getStream().tell() - Start ==
- (is64Bit() ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header)));
+ assert(W.OS.tell() - Start == (is64Bit() ? sizeof(MachO::mach_header_64)
+ : sizeof(MachO::mach_header)));
+}
+
+void MachObjectWriter::writeWithPadding(StringRef Str, uint64_t Size) {
+ assert(Size >= Str.size());
+ W.OS << Str;
+ W.OS.write_zeros(Size - Str.size());
}
/// writeSegmentLoadCommand - Write a segment load command.
@@ -172,38 +177,37 @@ void MachObjectWriter::writeSegmentLoadCommand(
// struct segment_command (56 bytes) or
// struct segment_command_64 (72 bytes)
- uint64_t Start = getStream().tell();
+ uint64_t Start = W.OS.tell();
(void) Start;
unsigned SegmentLoadCommandSize =
is64Bit() ? sizeof(MachO::segment_command_64):
sizeof(MachO::segment_command);
- write32(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT);
- write32(SegmentLoadCommandSize +
+ W.write<uint32_t>(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT);
+ W.write<uint32_t>(SegmentLoadCommandSize +
NumSections * (is64Bit() ? sizeof(MachO::section_64) :
sizeof(MachO::section)));
- assert(Name.size() <= 16);
- writeBytes(Name, 16);
+ writeWithPadding(Name, 16);
if (is64Bit()) {
- write64(VMAddr); // vmaddr
- write64(VMSize); // vmsize
- write64(SectionDataStartOffset); // file offset
- write64(SectionDataSize); // file size
+ W.write<uint64_t>(VMAddr); // vmaddr
+ W.write<uint64_t>(VMSize); // vmsize
+ W.write<uint64_t>(SectionDataStartOffset); // file offset
+ W.write<uint64_t>(SectionDataSize); // file size
} else {
- write32(VMAddr); // vmaddr
- write32(VMSize); // vmsize
- write32(SectionDataStartOffset); // file offset
- write32(SectionDataSize); // file size
+ W.write<uint32_t>(VMAddr); // vmaddr
+ W.write<uint32_t>(VMSize); // vmsize
+ W.write<uint32_t>(SectionDataStartOffset); // file offset
+ W.write<uint32_t>(SectionDataSize); // file size
}
// maxprot
- write32(MaxProt);
+ W.write<uint32_t>(MaxProt);
// initprot
- write32(InitProt);
- write32(NumSections);
- write32(0); // flags
+ W.write<uint32_t>(InitProt);
+ W.write<uint32_t>(NumSections);
+ W.write<uint32_t>(0); // flags
- assert(getStream().tell() - Start == SegmentLoadCommandSize);
+ assert(W.OS.tell() - Start == SegmentLoadCommandSize);
}
void MachObjectWriter::writeSection(const MCAsmLayout &Layout,
@@ -223,31 +227,31 @@ void MachObjectWriter::writeSection(const MCAsmLayout &Layout,
// struct section (68 bytes) or
// struct section_64 (80 bytes)
- uint64_t Start = getStream().tell();
+ uint64_t Start = W.OS.tell();
(void) Start;
- writeBytes(Section.getSectionName(), 16);
- writeBytes(Section.getSegmentName(), 16);
+ writeWithPadding(Section.getSectionName(), 16);
+ writeWithPadding(Section.getSegmentName(), 16);
if (is64Bit()) {
- write64(VMAddr); // address
- write64(SectionSize); // size
+ W.write<uint64_t>(VMAddr); // address
+ W.write<uint64_t>(SectionSize); // size
} else {
- write32(VMAddr); // address
- write32(SectionSize); // size
+ W.write<uint32_t>(VMAddr); // address
+ W.write<uint32_t>(SectionSize); // size
}
- write32(FileOffset);
+ W.write<uint32_t>(FileOffset);
assert(isPowerOf2_32(Section.getAlignment()) && "Invalid alignment!");
- write32(Log2_32(Section.getAlignment()));
- write32(NumRelocations ? RelocationsStart : 0);
- write32(NumRelocations);
- write32(Flags);
- write32(IndirectSymBase.lookup(&Sec)); // reserved1
- write32(Section.getStubSize()); // reserved2
+ W.write<uint32_t>(Log2_32(Section.getAlignment()));
+ W.write<uint32_t>(NumRelocations ? RelocationsStart : 0);
+ W.write<uint32_t>(NumRelocations);
+ W.write<uint32_t>(Flags);
+ W.write<uint32_t>(IndirectSymBase.lookup(&Sec)); // reserved1
+ W.write<uint32_t>(Section.getStubSize()); // reserved2
if (is64Bit())
- write32(0); // reserved3
+ W.write<uint32_t>(0); // reserved3
- assert(getStream().tell() - Start ==
+ assert(W.OS.tell() - Start ==
(is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section)));
}
@@ -257,17 +261,17 @@ void MachObjectWriter::writeSymtabLoadCommand(uint32_t SymbolOffset,
uint32_t StringTableSize) {
// struct symtab_command (24 bytes)
- uint64_t Start = getStream().tell();
+ uint64_t Start = W.OS.tell();
(void) Start;
- write32(MachO::LC_SYMTAB);
- write32(sizeof(MachO::symtab_command));
- write32(SymbolOffset);
- write32(NumSymbols);
- write32(StringTableOffset);
- write32(StringTableSize);
+ W.write<uint32_t>(MachO::LC_SYMTAB);
+ W.write<uint32_t>(sizeof(MachO::symtab_command));
+ W.write<uint32_t>(SymbolOffset);
+ W.write<uint32_t>(NumSymbols);
+ W.write<uint32_t>(StringTableOffset);
+ W.write<uint32_t>(StringTableSize);
- assert(getStream().tell() - Start == sizeof(MachO::symtab_command));
+ assert(W.OS.tell() - Start == sizeof(MachO::symtab_command));
}
void MachObjectWriter::writeDysymtabLoadCommand(uint32_t FirstLocalSymbol,
@@ -280,31 +284,31 @@ void MachObjectWriter::writeDysymtabLoadCommand(uint32_t FirstLocalSymbol,
uint32_t NumIndirectSymbols) {
// struct dysymtab_command (80 bytes)
- uint64_t Start = getStream().tell();
+ uint64_t Start = W.OS.tell();
(void) Start;
- write32(MachO::LC_DYSYMTAB);
- write32(sizeof(MachO::dysymtab_command));
- write32(FirstLocalSymbol);
- write32(NumLocalSymbols);
- write32(FirstExternalSymbol);
- write32(NumExternalSymbols);
- write32(FirstUndefinedSymbol);
- write32(NumUndefinedSymbols);
- write32(0); // tocoff
- write32(0); // ntoc
- write32(0); // modtaboff
- write32(0); // nmodtab
- write32(0); // extrefsymoff
- write32(0); // nextrefsyms
- write32(IndirectSymbolOffset);
- write32(NumIndirectSymbols);
- write32(0); // extreloff
- write32(0); // nextrel
- write32(0); // locreloff
- write32(0); // nlocrel
-
- assert(getStream().tell() - Start == sizeof(MachO::dysymtab_command));
+ W.write<uint32_t>(MachO::LC_DYSYMTAB);
+ W.write<uint32_t>(sizeof(MachO::dysymtab_command));
+ W.write<uint32_t>(FirstLocalSymbol);
+ W.write<uint32_t>(NumLocalSymbols);
+ W.write<uint32_t>(FirstExternalSymbol);
+ W.write<uint32_t>(NumExternalSymbols);
+ W.write<uint32_t>(FirstUndefinedSymbol);
+ W.write<uint32_t>(NumUndefinedSymbols);
+ W.write<uint32_t>(0); // tocoff
+ W.write<uint32_t>(0); // ntoc
+ W.write<uint32_t>(0); // modtaboff
+ W.write<uint32_t>(0); // nmodtab
+ W.write<uint32_t>(0); // extrefsymoff
+ W.write<uint32_t>(0); // nextrefsyms
+ W.write<uint32_t>(IndirectSymbolOffset);
+ W.write<uint32_t>(NumIndirectSymbols);
+ W.write<uint32_t>(0); // extreloff
+ W.write<uint32_t>(0); // nextrel
+ W.write<uint32_t>(0); // locreloff
+ W.write<uint32_t>(0); // nlocrel
+
+ assert(W.OS.tell() - Start == sizeof(MachO::dysymtab_command));
}
MachObjectWriter::MachSymbolData *
@@ -384,33 +388,33 @@ void MachObjectWriter::writeNlist(MachSymbolData &MSD,
// struct nlist (12 bytes)
- write32(MSD.StringIndex);
- write8(Type);
- write8(SectionIndex);
+ W.write<uint32_t>(MSD.StringIndex);
+ W.OS << char(Type);
+ W.OS << char(SectionIndex);
// The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
// value.
bool EncodeAsAltEntry =
IsAlias && cast<MCSymbolMachO>(OrigSymbol).isAltEntry();
- write16(cast<MCSymbolMachO>(Symbol)->getEncodedFlags(EncodeAsAltEntry));
+ W.write<uint16_t>(cast<MCSymbolMachO>(Symbol)->getEncodedFlags(EncodeAsAltEntry));
if (is64Bit())
- write64(Address);
+ W.write<uint64_t>(Address);
else
- write32(Address);
+ W.write<uint32_t>(Address);
}
void MachObjectWriter::writeLinkeditLoadCommand(uint32_t Type,
uint32_t DataOffset,
uint32_t DataSize) {
- uint64_t Start = getStream().tell();
+ uint64_t Start = W.OS.tell();
(void) Start;
- write32(Type);
- write32(sizeof(MachO::linkedit_data_command));
- write32(DataOffset);
- write32(DataSize);
+ W.write<uint32_t>(Type);
+ W.write<uint32_t>(sizeof(MachO::linkedit_data_command));
+ W.write<uint32_t>(DataOffset);
+ W.write<uint32_t>(DataSize);
- assert(getStream().tell() - Start == sizeof(MachO::linkedit_data_command));
+ assert(W.OS.tell() - Start == sizeof(MachO::linkedit_data_command));
}
static unsigned ComputeLinkerOptionsLoadCommandSize(
@@ -426,23 +430,23 @@ void MachObjectWriter::writeLinkerOptionsLoadCommand(
const std::vector<std::string> &Options)
{
unsigned Size = ComputeLinkerOptionsLoadCommandSize(Options, is64Bit());
- uint64_t Start = getStream().tell();
+ uint64_t Start = W.OS.tell();
(void) Start;
- write32(MachO::LC_LINKER_OPTION);
- write32(Size);
- write32(Options.size());
+ W.write<uint32_t>(MachO::LC_LINKER_OPTION);
+ W.write<uint32_t>(Size);
+ W.write<uint32_t>(Options.size());
uint64_t BytesWritten = sizeof(MachO::linker_option_command);
for (const std::string &Option : Options) {
// Write each string, including the null byte.
- writeBytes(Option, Option.size() + 1);
+ W.OS << Option << '\0';
BytesWritten += Option.size() + 1;
}
// Pad to a multiple of the pointer size.
- writeBytes("", OffsetToAlignment(BytesWritten, is64Bit() ? 8 : 4));
+ W.OS.write_zeros(OffsetToAlignment(BytesWritten, is64Bit() ? 8 : 4));
- assert(getStream().tell() - Start == Size);
+ assert(W.OS.tell() - Start == Size);
}
void MachObjectWriter::recordRelocation(MCAssembler &Asm,
@@ -593,8 +597,8 @@ void MachObjectWriter::computeSymbolTable(
}
// External and undefined symbols are required to be in lexicographic order.
- std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
- std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
+ llvm::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
+ llvm::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
// Set the symbol indices.
Index = 0;
@@ -611,7 +615,7 @@ void MachObjectWriter::computeSymbolTable(
// Set the Index and the IsExtern bit.
unsigned Index = Rel.Sym->getIndex();
assert(isInt<24>(Index));
- if (IsLittleEndian)
+ if (W.Endian == support::little)
Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (~0U << 24)) | Index | (1 << 27);
else
Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4);
@@ -731,8 +735,10 @@ static MachO::LoadCommandType getLCFromMCVM(MCVersionMinType Type) {
llvm_unreachable("Invalid mc version min type");
}
-void MachObjectWriter::writeObject(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
+uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ uint64_t StartOffset = W.OS.tell();
+
// Compute symbol table information and bind symbol indices.
computeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
UndefinedSymbolData);
@@ -847,19 +853,19 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
(VersionInfo.Major << 16);
if (VersionInfo.EmitBuildVersion) {
// FIXME: Currently empty tools. Add clang version in the future.
- write32(MachO::LC_BUILD_VERSION);
- write32(sizeof(MachO::build_version_command));
- write32(VersionInfo.TypeOrPlatform.Platform);
- write32(EncodedVersion);
- write32(0); // SDK version.
- write32(0); // Empty tools list.
+ W.write<uint32_t>(MachO::LC_BUILD_VERSION);
+ W.write<uint32_t>(sizeof(MachO::build_version_command));
+ W.write<uint32_t>(VersionInfo.TypeOrPlatform.Platform);
+ W.write<uint32_t>(EncodedVersion);
+ W.write<uint32_t>(0); // SDK version.
+ W.write<uint32_t>(0); // Empty tools list.
} else {
MachO::LoadCommandType LCType
= getLCFromMCVM(VersionInfo.TypeOrPlatform.Type);
- write32(LCType);
- write32(sizeof(MachO::version_min_command));
- write32(EncodedVersion);
- write32(0); // reserved.
+ W.write<uint32_t>(LCType);
+ W.write<uint32_t>(sizeof(MachO::version_min_command));
+ W.write<uint32_t>(EncodedVersion);
+ W.write<uint32_t>(0); // reserved.
}
}
@@ -919,14 +925,14 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
// Write the actual section data.
for (const MCSection &Sec : Asm) {
- Asm.writeSectionData(&Sec, Layout);
+ Asm.writeSectionData(W.OS, &Sec, Layout);
uint64_t Pad = getPaddingSize(&Sec, Layout);
- WriteZeros(Pad);
+ W.OS.write_zeros(Pad);
}
// Write the extra padding.
- WriteZeros(SectionDataPadding);
+ W.OS.write_zeros(SectionDataPadding);
// Write the relocation entries.
for (const MCSection &Sec : Asm) {
@@ -934,8 +940,8 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
// (approximately, the exact algorithm is more complicated than this).
std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
for (const RelAndSymbol &Rel : make_range(Relocs.rbegin(), Relocs.rend())) {
- write32(Rel.MRE.r_word0);
- write32(Rel.MRE.r_word1);
+ W.write<uint32_t>(Rel.MRE.r_word0);
+ W.write<uint32_t>(Rel.MRE.r_word1);
}
}
@@ -945,26 +951,31 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
it != ie; ++it) {
const DataRegionData *Data = &(*it);
uint64_t Start = getSymbolAddress(*Data->Start, Layout);
- uint64_t End = getSymbolAddress(*Data->End, Layout);
- DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind
- << " start: " << Start << "(" << Data->Start->getName() << ")"
- << " end: " << End << "(" << Data->End->getName() << ")"
- << " size: " << End - Start
- << "\n");
- write32(Start);
- write16(End - Start);
- write16(Data->Kind);
+ uint64_t End;
+ if (Data->End)
+ End = getSymbolAddress(*Data->End, Layout);
+ else
+ report_fatal_error("Data region not terminated");
+
+ LLVM_DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind
+ << " start: " << Start << "(" << Data->Start->getName()
+ << ")"
+ << " end: " << End << "(" << Data->End->getName() << ")"
+ << " size: " << End - Start << "\n");
+ W.write<uint32_t>(Start);
+ W.write<uint16_t>(End - Start);
+ W.write<uint16_t>(Data->Kind);
}
// Write out the loh commands, if there is one.
if (LOHSize) {
#ifndef NDEBUG
- unsigned Start = getStream().tell();
+ unsigned Start = W.OS.tell();
#endif
Asm.getLOHContainer().emit(*this, Layout);
// Pad to a multiple of the pointer size.
- writeBytes("", OffsetToAlignment(LOHRawSize, is64Bit() ? 8 : 4));
- assert(getStream().tell() - Start == LOHSize);
+ W.OS.write_zeros(OffsetToAlignment(LOHRawSize, is64Bit() ? 8 : 4));
+ assert(W.OS.tell() - Start == LOHSize);
}
// Write the symbol table data, if used.
@@ -983,12 +994,12 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL;
if (it->Symbol->isAbsolute())
Flags |= MachO::INDIRECT_SYMBOL_ABS;
- write32(Flags);
+ W.write<uint32_t>(Flags);
continue;
}
}
- write32(it->Symbol->getIndex());
+ W.write<uint32_t>(it->Symbol->getIndex());
}
// FIXME: Check that offsets match computed ones.
@@ -1000,8 +1011,10 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
writeNlist(Entry, Layout);
// Write the string table.
- StringTable.write(getStream());
+ StringTable.write(W.OS);
}
+
+ return W.OS.tell() - StartOffset;
}
std::unique_ptr<MCObjectWriter>
diff --git a/contrib/llvm/lib/MC/StringTableBuilder.cpp b/contrib/llvm/lib/MC/StringTableBuilder.cpp
index 531bc930c89b..de40a7728d3f 100644
--- a/contrib/llvm/lib/MC/StringTableBuilder.cpp
+++ b/contrib/llvm/lib/MC/StringTableBuilder.cpp
@@ -31,6 +31,7 @@ void StringTableBuilder::initSize() {
// correct.
switch (K) {
case RAW:
+ case DWARF:
Size = 0;
break;
case MachO:
@@ -116,6 +117,7 @@ tailcall:
}
void StringTableBuilder::finalize() {
+ assert(K != DWARF);
finalizeStringTable(/*Optimize=*/true);
}
diff --git a/contrib/llvm/lib/MC/SubtargetFeature.cpp b/contrib/llvm/lib/MC/SubtargetFeature.cpp
index b68e88ca5725..b69af24b531e 100644
--- a/contrib/llvm/lib/MC/SubtargetFeature.cpp
+++ b/contrib/llvm/lib/MC/SubtargetFeature.cpp
@@ -17,6 +17,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
diff --git a/contrib/llvm/lib/MC/WasmObjectWriter.cpp b/contrib/llvm/lib/MC/WasmObjectWriter.cpp
index 66236e3abfab..5a979d36e81b 100644
--- a/contrib/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/contrib/llvm/lib/MC/WasmObjectWriter.cpp
@@ -14,6 +14,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/BinaryFormat/Wasm.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
@@ -38,14 +39,21 @@ using namespace llvm;
namespace {
+// Went we ceate the indirect function table we start at 1, so that there is
+// and emtpy slot at 0 and therefore calling a null function pointer will trap.
+static const uint32_t kInitialTableOffset = 1;
+
// For patching purposes, we need to remember where each section starts, both
// for patching up the section size field, and for patching up references to
// locations within the section.
struct SectionBookkeeping {
// Where the size of the section is written.
uint64_t SizeOffset;
- // Where the contents of the section starts (after the header).
+ // Where the section header ends (without custom section name).
+ uint64_t PayloadOffset;
+ // Where the contents of the section starts.
uint64_t ContentsOffset;
+ uint32_t Index;
};
// The signature of a wasm function, in a struct capable of being used as a
@@ -107,35 +115,24 @@ struct WasmDataSegment {
SmallVector<char, 4> Data;
};
-// A wasm import to be written into the import section.
-struct WasmImport {
- StringRef ModuleName;
- StringRef FieldName;
- unsigned Kind;
- int32_t Type;
- bool IsMutable;
-};
-
// A wasm function to be written into the function section.
struct WasmFunction {
int32_t Type;
const MCSymbolWasm *Sym;
};
-// A wasm export to be written into the export section.
-struct WasmExport {
- StringRef FieldName;
- unsigned Kind;
- uint32_t Index;
-};
-
// A wasm global to be written into the global section.
struct WasmGlobal {
- wasm::ValType Type;
- bool IsMutable;
- bool HasImport;
+ wasm::WasmGlobalType Type;
uint64_t InitialValue;
- uint32_t ImportIndex;
+};
+
+// Information about a single item which is part of a COMDAT. For each data
+// segment or function which is in the COMDAT, there is a corresponding
+// WasmComdatEntry.
+struct WasmComdatEntry {
+ unsigned Kind;
+ uint32_t Index;
};
// Information about a single relocation.
@@ -157,6 +154,8 @@ struct WasmRelocationEntry {
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+ case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
return true;
default:
return false;
@@ -164,8 +163,8 @@ struct WasmRelocationEntry {
}
void print(raw_ostream &Out) const {
- Out << "Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend
- << ", Type=" << Type
+ Out << wasm::relocTypetoString(Type)
+ << " Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend
<< ", FixupSection=" << FixupSection->getSectionName();
}
@@ -174,6 +173,21 @@ struct WasmRelocationEntry {
#endif
};
+static const uint32_t INVALID_INDEX = -1;
+
+struct WasmCustomSection {
+
+ StringRef Name;
+ MCSectionWasm *Section;
+
+ uint32_t OutputContentsOffset;
+ uint32_t OutputIndex;
+
+ WasmCustomSection(StringRef Name, MCSectionWasm *Section)
+ : Name(Name), Section(Section), OutputContentsOffset(0),
+ OutputIndex(INVALID_INDEX) {}
+};
+
#if !defined(NDEBUG)
raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
Rel.print(OS);
@@ -182,38 +196,48 @@ raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
#endif
class WasmObjectWriter : public MCObjectWriter {
- /// Helper struct for containing some precomputed information on symbols.
- struct WasmSymbolData {
- const MCSymbolWasm *Symbol;
- StringRef Name;
-
- // Support lexicographic sorting.
- bool operator<(const WasmSymbolData &RHS) const { return Name < RHS.Name; }
- };
+ support::endian::Writer W;
/// The target specific Wasm writer instance.
std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
// Relocations for fixing up references in the code section.
std::vector<WasmRelocationEntry> CodeRelocations;
+ uint32_t CodeSectionIndex;
// Relocations for fixing up references in the data section.
std::vector<WasmRelocationEntry> DataRelocations;
+ uint32_t DataSectionIndex;
// Index values to use for fixing up call_indirect type indices.
// Maps function symbols to the index of the type of the function
DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices;
// Maps function symbols to the table element index space. Used
// for TABLE_INDEX relocation types (i.e. address taken functions).
- DenseMap<const MCSymbolWasm *, uint32_t> IndirectSymbolIndices;
- // Maps function/global symbols to the function/global index space.
- DenseMap<const MCSymbolWasm *, uint32_t> SymbolIndices;
+ DenseMap<const MCSymbolWasm *, uint32_t> TableIndices;
+ // Maps function/global symbols to the function/global/section index space.
+ DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices;
+ // Maps data symbols to the Wasm segment and offset/size with the segment.
+ DenseMap<const MCSymbolWasm *, wasm::WasmDataReference> DataLocations;
+
+ // Stores output data (index, relocations, content offset) for custom
+ // section.
+ std::vector<WasmCustomSection> CustomSections;
+ // Relocations for fixing up references in the custom sections.
+ DenseMap<const MCSectionWasm *, std::vector<WasmRelocationEntry>>
+ CustomSectionsRelocations;
+
+ // Map from section to defining function symbol.
+ DenseMap<const MCSection *, const MCSymbol *> SectionFunctions;
DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo>
FunctionTypeIndices;
SmallVector<WasmFunctionType, 4> FunctionTypes;
SmallVector<WasmGlobal, 4> Globals;
+ SmallVector<WasmDataSegment, 4> DataSegments;
+ unsigned NumFunctionImports = 0;
unsigned NumGlobalImports = 0;
+ uint32_t SectionCount = 0;
// TargetObjectWriter wrappers.
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
@@ -221,30 +245,34 @@ class WasmObjectWriter : public MCObjectWriter {
return TargetObjectWriter->getRelocType(Target, Fixup);
}
- void startSection(SectionBookkeeping &Section, unsigned SectionId,
- const char *Name = nullptr);
+ void startSection(SectionBookkeeping &Section, unsigned SectionId);
+ void startCustomSection(SectionBookkeeping &Section, StringRef Name);
void endSection(SectionBookkeeping &Section);
public:
WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
raw_pwrite_stream &OS)
- : MCObjectWriter(OS, /*IsLittleEndian=*/true),
- TargetObjectWriter(std::move(MOTW)) {}
+ : W(OS, support::little), TargetObjectWriter(std::move(MOTW)) {}
-private:
~WasmObjectWriter() override;
+private:
void reset() override {
CodeRelocations.clear();
DataRelocations.clear();
TypeIndices.clear();
- SymbolIndices.clear();
- IndirectSymbolIndices.clear();
+ WasmIndices.clear();
+ TableIndices.clear();
+ DataLocations.clear();
+ CustomSectionsRelocations.clear();
FunctionTypeIndices.clear();
FunctionTypes.clear();
Globals.clear();
- MCObjectWriter::reset();
+ DataSegments.clear();
+ SectionFunctions.clear();
+ NumFunctionImports = 0;
NumGlobalImports = 0;
+ MCObjectWriter::reset();
}
void writeHeader(const MCAssembler &Asm);
@@ -256,45 +284,46 @@ private:
void executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) override;
- void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+ uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
void writeString(const StringRef Str) {
- encodeULEB128(Str.size(), getStream());
- writeBytes(Str);
+ encodeULEB128(Str.size(), W.OS);
+ W.OS << Str;
}
void writeValueType(wasm::ValType Ty) {
- encodeSLEB128(int32_t(Ty), getStream());
+ W.OS << static_cast<char>(Ty);
}
void writeTypeSection(ArrayRef<WasmFunctionType> FunctionTypes);
- void writeImportSection(ArrayRef<WasmImport> Imports, uint32_t DataSize,
+ void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint32_t DataSize,
uint32_t NumElements);
void writeFunctionSection(ArrayRef<WasmFunction> Functions);
void writeGlobalSection();
- void writeExportSection(ArrayRef<WasmExport> Exports);
+ void writeExportSection(ArrayRef<wasm::WasmExport> Exports);
void writeElemSection(ArrayRef<uint32_t> TableElems);
void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
ArrayRef<WasmFunction> Functions);
- void writeDataSection(ArrayRef<WasmDataSegment> Segments);
- void writeNameSection(ArrayRef<WasmFunction> Functions,
- ArrayRef<WasmImport> Imports,
- uint32_t NumFuncImports);
- void writeCodeRelocSection();
- void writeDataRelocSection();
+ void writeDataSection();
+ void writeRelocSection(uint32_t SectionIndex, StringRef Name,
+ ArrayRef<WasmRelocationEntry> Relocations);
void writeLinkingMetaDataSection(
- ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
- const SmallVector<std::pair<StringRef, uint32_t>, 4> &SymbolFlags,
- const SmallVector<std::pair<uint16_t, uint32_t>, 2> &InitFuncs);
+ ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
+ ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
+ const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats);
+ void writeCustomSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
+ void writeCustomRelocSections();
+ void
+ updateCustomSectionRelocations(const SmallVector<WasmFunction, 4> &Functions,
+ const MCAsmLayout &Layout);
uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
uint64_t ContentsOffset);
- void writeRelocations(ArrayRef<WasmRelocationEntry> Relocations);
uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
- uint32_t getFunctionType(const MCSymbolWasm& Symbol);
- uint32_t registerFunctionType(const MCSymbolWasm& Symbol);
+ uint32_t getFunctionType(const MCSymbolWasm &Symbol);
+ uint32_t registerFunctionType(const MCSymbolWasm &Symbol);
};
} // end anonymous namespace
@@ -303,55 +332,75 @@ WasmObjectWriter::~WasmObjectWriter() {}
// Write out a section header and a patchable section size field.
void WasmObjectWriter::startSection(SectionBookkeeping &Section,
- unsigned SectionId,
- const char *Name) {
- assert((Name != nullptr) == (SectionId == wasm::WASM_SEC_CUSTOM) &&
- "Only custom sections can have names");
-
- DEBUG(dbgs() << "startSection " << SectionId << ": " << Name << "\n");
- encodeULEB128(SectionId, getStream());
+ unsigned SectionId) {
+ LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n");
+ W.OS << char(SectionId);
- Section.SizeOffset = getStream().tell();
+ Section.SizeOffset = W.OS.tell();
// The section size. We don't know the size yet, so reserve enough space
// for any 32-bit value; we'll patch it later.
- encodeULEB128(UINT32_MAX, getStream());
+ encodeULEB128(UINT32_MAX, W.OS);
// The position where the section starts, for measuring its size.
- Section.ContentsOffset = getStream().tell();
+ Section.ContentsOffset = W.OS.tell();
+ Section.PayloadOffset = W.OS.tell();
+ Section.Index = SectionCount++;
+}
+
+void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
+ StringRef Name) {
+ LLVM_DEBUG(dbgs() << "startCustomSection " << Name << "\n");
+ startSection(Section, wasm::WASM_SEC_CUSTOM);
+
+ // The position where the section header ends, for measuring its size.
+ Section.PayloadOffset = W.OS.tell();
// Custom sections in wasm also have a string identifier.
- if (SectionId == wasm::WASM_SEC_CUSTOM) {
- assert(Name);
- writeString(StringRef(Name));
- }
+ writeString(Name);
+
+ // The position where the custom section starts.
+ Section.ContentsOffset = W.OS.tell();
}
// Now that the section is complete and we know how big it is, patch up the
// section size field at the start of the section.
void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
- uint64_t Size = getStream().tell() - Section.ContentsOffset;
+ uint64_t Size = W.OS.tell() - Section.PayloadOffset;
if (uint32_t(Size) != Size)
report_fatal_error("section size does not fit in a uint32_t");
- DEBUG(dbgs() << "endSection size=" << Size << "\n");
+ LLVM_DEBUG(dbgs() << "endSection size=" << Size << "\n");
// Write the final section size to the payload_len field, which follows
// the section id byte.
uint8_t Buffer[16];
unsigned SizeLen = encodeULEB128(Size, Buffer, 5);
assert(SizeLen == 5);
- getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset);
+ static_cast<raw_pwrite_stream &>(W.OS).pwrite((char *)Buffer, SizeLen,
+ Section.SizeOffset);
}
// Emit the Wasm header.
void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
- writeBytes(StringRef(wasm::WasmMagic, sizeof(wasm::WasmMagic)));
- writeLE32(wasm::WasmVersion);
+ W.OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
+ W.write<uint32_t>(wasm::WasmVersion);
}
void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) {
+ // Build a map of sections to the function that defines them, for use
+ // in recordRelocation.
+ for (const MCSymbol &S : Asm.symbols()) {
+ const auto &WS = static_cast<const MCSymbolWasm &>(S);
+ if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {
+ const auto &Sec = static_cast<const MCSectionWasm &>(S.getSection());
+ auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));
+ if (!Pair.second)
+ report_fatal_error("section already has a defining function: " +
+ Sec.getSectionName());
+ }
+ }
}
void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
@@ -428,24 +477,54 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
// be negative and don't wrap.
FixedValue = 0;
- if (SymA)
- SymA->setUsedInReloc();
-
+ unsigned Type = getRelocType(Target, Fixup);
assert(!IsPCRel);
assert(SymA);
- unsigned Type = getRelocType(Target, Fixup);
+ // Absolute offset within a section or a function.
+ // Currently only supported for for metadata sections.
+ // See: test/MC/WebAssembly/blockaddress.ll
+ if (Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32 ||
+ Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32) {
+ if (!FixupSection.getKind().isMetadata())
+ report_fatal_error("relocations for function or section offsets are "
+ "only supported in metadata sections");
+
+ const MCSymbol *SectionSymbol = nullptr;
+ const MCSection &SecA = SymA->getSection();
+ if (SecA.getKind().isText())
+ SectionSymbol = SectionFunctions.find(&SecA)->second;
+ else
+ SectionSymbol = SecA.getBeginSymbol();
+ if (!SectionSymbol)
+ report_fatal_error("section symbol is required for relocation");
+
+ C += Layout.getSymbolOffset(*SymA);
+ SymA = cast<MCSymbolWasm>(SectionSymbol);
+ }
+
+ // Relocation other than R_WEBASSEMBLY_TYPE_INDEX_LEB are required to be
+ // against a named symbol.
+ if (Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) {
+ if (SymA->getName().empty())
+ report_fatal_error("relocations against un-named temporaries are not yet "
+ "supported by wasm");
+
+ SymA->setUsedInReloc();
+ }
WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
- DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
+ LLVM_DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
- if (FixupSection.isWasmData())
+ if (FixupSection.isWasmData()) {
DataRelocations.push_back(Rec);
- else if (FixupSection.getKind().isText())
+ } else if (FixupSection.getKind().isText()) {
CodeRelocations.push_back(Rec);
- else if (!FixupSection.getKind().isMetadata())
- // TODO(sbc): Add support for debug sections.
+ } else if (FixupSection.getKind().isMetadata()) {
+ CustomSectionsRelocations[&FixupSection].push_back(Rec);
+ } else {
llvm_unreachable("unexpected section type");
+ }
}
// Write X as an (unsigned) LEB value at offset Offset in Stream, padded
@@ -485,34 +564,59 @@ static const MCSymbolWasm* ResolveSymbol(const MCSymbolWasm& Symbol) {
}
// Compute a value to write into the code at the location covered
-// by RelEntry. This value isn't used by the static linker, since
-// we have addends; it just serves to make the code more readable
-// and to make standalone wasm modules directly usable.
+// by RelEntry. This value isn't used by the static linker; it just serves
+// to make the object format more readable and more likely to be directly
+// useable.
uint32_t
WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
- const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol);
-
- // For undefined symbols, use a hopefully invalid value.
- if (!Sym->isDefined(/*SetUsed=*/false))
- return UINT32_MAX;
-
- uint32_t GlobalIndex = SymbolIndices[Sym];
- const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports];
- uint64_t Address = Global.InitialValue + RelEntry.Addend;
-
- // Ignore overflow. LLVM allows address arithmetic to silently wrap.
- uint32_t Value = Address;
-
- return Value;
+ switch (RelEntry.Type) {
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: {
+ // Provisional value is table address of the resolved symbol itself
+ const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol);
+ assert(Sym->isFunction());
+ return TableIndices[Sym];
+ }
+ case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
+ // Provisional value is same as the index
+ return getRelocationIndexValue(RelEntry);
+ case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+ // Provisional value is function/global Wasm index
+ if (!WasmIndices.count(RelEntry.Symbol))
+ report_fatal_error("symbol not found in wasm index space: " +
+ RelEntry.Symbol->getName());
+ return WasmIndices[RelEntry.Symbol];
+ case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+ case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: {
+ const auto &Section =
+ static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());
+ return Section.getSectionOffset() + RelEntry.Addend;
+ }
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
+ // Provisional value is address of the global
+ const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol);
+ // For undefined symbols, use zero
+ if (!Sym->isDefined())
+ return 0;
+ const wasm::WasmDataReference &Ref = DataLocations[Sym];
+ const WasmDataSegment &Segment = DataSegments[Ref.Segment];
+ // Ignore overflow. LLVM allows address arithmetic to silently wrap.
+ return Segment.Offset + Ref.Offset + RelEntry.Addend;
+ }
+ default:
+ llvm_unreachable("invalid relocation type");
+ }
}
static void addData(SmallVectorImpl<char> &DataBytes,
MCSectionWasm &DataSection) {
- DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n");
+ LLVM_DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n");
DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
- size_t LastFragmentSize = 0;
for (const MCFragment &Frag : DataSection) {
if (Frag.hasInstructions())
report_fatal_error("only data supported in data sections");
@@ -528,121 +632,70 @@ static void addData(SmallVectorImpl<char> &DataBytes,
Align->getMaxBytesToEmit());
DataBytes.resize(Size, Value);
} else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
- int64_t Size;
- if (!Fill->getSize().evaluateAsAbsolute(Size))
+ int64_t NumValues;
+ if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
llvm_unreachable("The fill should be an assembler constant");
- DataBytes.insert(DataBytes.end(), Size, Fill->getValue());
+ DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues,
+ Fill->getValue());
} else {
const auto &DataFrag = cast<MCDataFragment>(Frag);
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
- LastFragmentSize = Contents.size();
}
}
- // Don't allow empty segments, or segments that end with zero-sized
- // fragment, otherwise the linker cannot map symbols to a unique
- // data segment. This can be triggered by zero-sized structs
- // See: test/MC/WebAssembly/bss.ll
- if (LastFragmentSize == 0)
- DataBytes.resize(DataBytes.size() + 1);
- DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
+ LLVM_DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
}
-uint32_t WasmObjectWriter::getRelocationIndexValue(
- const WasmRelocationEntry &RelEntry) {
- switch (RelEntry.Type) {
- case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
- case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
- if (!IndirectSymbolIndices.count(RelEntry.Symbol))
- report_fatal_error("symbol not found in table index space: " +
- RelEntry.Symbol->getName());
- return IndirectSymbolIndices[RelEntry.Symbol];
- case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
- case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
- case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
- case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
- if (!SymbolIndices.count(RelEntry.Symbol))
- report_fatal_error("symbol not found in function/global index space: " +
- RelEntry.Symbol->getName());
- return SymbolIndices[RelEntry.Symbol];
- case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
+uint32_t
+WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {
+ if (RelEntry.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) {
if (!TypeIndices.count(RelEntry.Symbol))
report_fatal_error("symbol not found in type index space: " +
RelEntry.Symbol->getName());
return TypeIndices[RelEntry.Symbol];
- default:
- llvm_unreachable("invalid relocation type");
}
+
+ return RelEntry.Symbol->getIndex();
}
// Apply the portions of the relocation records that we can handle ourselves
// directly.
void WasmObjectWriter::applyRelocations(
ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset) {
- raw_pwrite_stream &Stream = getStream();
+ auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);
for (const WasmRelocationEntry &RelEntry : Relocations) {
uint64_t Offset = ContentsOffset +
RelEntry.FixupSection->getSectionOffset() +
RelEntry.Offset;
- DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
+ LLVM_DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
+ uint32_t Value = getProvisionalValue(RelEntry);
+
switch (RelEntry.Type) {
- case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: {
- uint32_t Index = getRelocationIndexValue(RelEntry);
- WritePatchableSLEB(Stream, Index, Offset);
- break;
- }
- case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: {
- uint32_t Index = getRelocationIndexValue(RelEntry);
- WriteI32(Stream, Index, Offset);
- break;
- }
- case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
- uint32_t Value = getProvisionalValue(RelEntry);
- WritePatchableSLEB(Stream, Value, Offset);
- break;
- }
- case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: {
- uint32_t Value = getProvisionalValue(RelEntry);
+ case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
WritePatchableLEB(Stream, Value, Offset);
break;
- }
- case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: {
- uint32_t Value = getProvisionalValue(RelEntry);
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+ case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
WriteI32(Stream, Value, Offset);
break;
- }
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ WritePatchableSLEB(Stream, Value, Offset);
+ break;
default:
llvm_unreachable("invalid relocation type");
}
}
}
-// Write out the portions of the relocation records that the linker will
-// need to handle.
-void WasmObjectWriter::writeRelocations(
- ArrayRef<WasmRelocationEntry> Relocations) {
- raw_pwrite_stream &Stream = getStream();
- for (const WasmRelocationEntry& RelEntry : Relocations) {
-
- uint64_t Offset = RelEntry.Offset +
- RelEntry.FixupSection->getSectionOffset();
- uint32_t Index = getRelocationIndexValue(RelEntry);
-
- encodeULEB128(RelEntry.Type, Stream);
- encodeULEB128(Offset, Stream);
- encodeULEB128(Index, Stream);
- if (RelEntry.hasAddend())
- encodeSLEB128(RelEntry.Addend, Stream);
- }
-}
-
void WasmObjectWriter::writeTypeSection(
ArrayRef<WasmFunctionType> FunctionTypes) {
if (FunctionTypes.empty())
@@ -651,14 +704,14 @@ void WasmObjectWriter::writeTypeSection(
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_TYPE);
- encodeULEB128(FunctionTypes.size(), getStream());
+ encodeULEB128(FunctionTypes.size(), W.OS);
for (const WasmFunctionType &FuncTy : FunctionTypes) {
- encodeSLEB128(wasm::WASM_TYPE_FUNC, getStream());
- encodeULEB128(FuncTy.Params.size(), getStream());
+ W.OS << char(wasm::WASM_TYPE_FUNC);
+ encodeULEB128(FuncTy.Params.size(), W.OS);
for (wasm::ValType Ty : FuncTy.Params)
writeValueType(Ty);
- encodeULEB128(FuncTy.Returns.size(), getStream());
+ encodeULEB128(FuncTy.Returns.size(), W.OS);
for (wasm::ValType Ty : FuncTy.Returns)
writeValueType(Ty);
}
@@ -666,7 +719,7 @@ void WasmObjectWriter::writeTypeSection(
endSection(Section);
}
-void WasmObjectWriter::writeImportSection(ArrayRef<WasmImport> Imports,
+void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
uint32_t DataSize,
uint32_t NumElements) {
if (Imports.empty())
@@ -677,29 +730,28 @@ void WasmObjectWriter::writeImportSection(ArrayRef<WasmImport> Imports,
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_IMPORT);
- encodeULEB128(Imports.size(), getStream());
- for (const WasmImport &Import : Imports) {
- writeString(Import.ModuleName);
- writeString(Import.FieldName);
-
- encodeULEB128(Import.Kind, getStream());
+ encodeULEB128(Imports.size(), W.OS);
+ for (const wasm::WasmImport &Import : Imports) {
+ writeString(Import.Module);
+ writeString(Import.Field);
+ W.OS << char(Import.Kind);
switch (Import.Kind) {
case wasm::WASM_EXTERNAL_FUNCTION:
- encodeULEB128(Import.Type, getStream());
+ encodeULEB128(Import.SigIndex, W.OS);
break;
case wasm::WASM_EXTERNAL_GLOBAL:
- encodeSLEB128(int32_t(Import.Type), getStream());
- encodeULEB128(int32_t(Import.IsMutable), getStream());
+ W.OS << char(Import.Global.Type);
+ W.OS << char(Import.Global.Mutable ? 1 : 0);
break;
case wasm::WASM_EXTERNAL_MEMORY:
- encodeULEB128(0, getStream()); // flags
- encodeULEB128(NumPages, getStream()); // initial
+ encodeULEB128(0, W.OS); // flags
+ encodeULEB128(NumPages, W.OS); // initial
break;
case wasm::WASM_EXTERNAL_TABLE:
- encodeSLEB128(int32_t(Import.Type), getStream());
- encodeULEB128(0, getStream()); // flags
- encodeULEB128(NumElements, getStream()); // initial
+ W.OS << char(Import.Table.ElemType);
+ encodeULEB128(0, W.OS); // flags
+ encodeULEB128(NumElements, W.OS); // initial
break;
default:
llvm_unreachable("unsupported import kind");
@@ -716,9 +768,9 @@ void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_FUNCTION);
- encodeULEB128(Functions.size(), getStream());
+ encodeULEB128(Functions.size(), W.OS);
for (const WasmFunction &Func : Functions)
- encodeULEB128(Func.Type, getStream());
+ encodeULEB128(Func.Type, W.OS);
endSection(Section);
}
@@ -730,38 +782,31 @@ void WasmObjectWriter::writeGlobalSection() {
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_GLOBAL);
- encodeULEB128(Globals.size(), getStream());
+ encodeULEB128(Globals.size(), W.OS);
for (const WasmGlobal &Global : Globals) {
- writeValueType(Global.Type);
- write8(Global.IsMutable);
+ writeValueType(static_cast<wasm::ValType>(Global.Type.Type));
+ W.OS << char(Global.Type.Mutable);
- if (Global.HasImport) {
- assert(Global.InitialValue == 0);
- write8(wasm::WASM_OPCODE_GET_GLOBAL);
- encodeULEB128(Global.ImportIndex, getStream());
- } else {
- assert(Global.ImportIndex == 0);
- write8(wasm::WASM_OPCODE_I32_CONST);
- encodeSLEB128(Global.InitialValue, getStream()); // offset
- }
- write8(wasm::WASM_OPCODE_END);
+ W.OS << char(wasm::WASM_OPCODE_I32_CONST);
+ encodeSLEB128(Global.InitialValue, W.OS);
+ W.OS << char(wasm::WASM_OPCODE_END);
}
endSection(Section);
}
-void WasmObjectWriter::writeExportSection(ArrayRef<WasmExport> Exports) {
+void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) {
if (Exports.empty())
return;
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_EXPORT);
- encodeULEB128(Exports.size(), getStream());
- for (const WasmExport &Export : Exports) {
- writeString(Export.FieldName);
- encodeSLEB128(Export.Kind, getStream());
- encodeULEB128(Export.Index, getStream());
+ encodeULEB128(Exports.size(), W.OS);
+ for (const wasm::WasmExport &Export : Exports) {
+ writeString(Export.Name);
+ W.OS << char(Export.Kind);
+ encodeULEB128(Export.Index, W.OS);
}
endSection(Section);
@@ -774,17 +819,17 @@ void WasmObjectWriter::writeElemSection(ArrayRef<uint32_t> TableElems) {
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_ELEM);
- encodeULEB128(1, getStream()); // number of "segments"
- encodeULEB128(0, getStream()); // the table index
+ encodeULEB128(1, W.OS); // number of "segments"
+ encodeULEB128(0, W.OS); // the table index
// init expr for starting offset
- write8(wasm::WASM_OPCODE_I32_CONST);
- encodeSLEB128(0, getStream());
- write8(wasm::WASM_OPCODE_END);
+ W.OS << char(wasm::WASM_OPCODE_I32_CONST);
+ encodeSLEB128(kInitialTableOffset, W.OS);
+ W.OS << char(wasm::WASM_OPCODE_END);
- encodeULEB128(TableElems.size(), getStream());
+ encodeULEB128(TableElems.size(), W.OS);
for (uint32_t Elem : TableElems)
- encodeULEB128(Elem, getStream());
+ encodeULEB128(Elem, W.OS);
endSection(Section);
}
@@ -797,8 +842,9 @@ void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_CODE);
+ CodeSectionIndex = Section.Index;
- encodeULEB128(Functions.size(), getStream());
+ encodeULEB128(Functions.size(), W.OS);
for (const WasmFunction &Func : Functions) {
auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection());
@@ -807,9 +853,9 @@ void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
report_fatal_error(".size expression must be evaluatable");
- encodeULEB128(Size, getStream());
- FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset);
- Asm.writeSectionData(&FuncSection, Layout);
+ encodeULEB128(Size, W.OS);
+ FuncSection.setSectionOffset(W.OS.tell() - Section.ContentsOffset);
+ Asm.writeSectionData(W.OS, &FuncSection, Layout);
}
// Apply fixups.
@@ -818,23 +864,24 @@ void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
endSection(Section);
}
-void WasmObjectWriter::writeDataSection(ArrayRef<WasmDataSegment> Segments) {
- if (Segments.empty())
+void WasmObjectWriter::writeDataSection() {
+ if (DataSegments.empty())
return;
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_DATA);
-
- encodeULEB128(Segments.size(), getStream()); // count
-
- for (const WasmDataSegment & Segment : Segments) {
- encodeULEB128(0, getStream()); // memory index
- write8(wasm::WASM_OPCODE_I32_CONST);
- encodeSLEB128(Segment.Offset, getStream()); // offset
- write8(wasm::WASM_OPCODE_END);
- encodeULEB128(Segment.Data.size(), getStream()); // size
- Segment.Section->setSectionOffset(getStream().tell() - Section.ContentsOffset);
- writeBytes(Segment.Data); // data
+ DataSectionIndex = Section.Index;
+
+ encodeULEB128(DataSegments.size(), W.OS); // count
+
+ for (const WasmDataSegment &Segment : DataSegments) {
+ encodeULEB128(0, W.OS); // memory index
+ W.OS << char(wasm::WASM_OPCODE_I32_CONST);
+ encodeSLEB128(Segment.Offset, W.OS); // offset
+ W.OS << char(wasm::WASM_OPCODE_END);
+ encodeULEB128(Segment.Data.size(), W.OS); // size
+ Segment.Section->setSectionOffset(W.OS.tell() - Section.ContentsOffset);
+ W.OS << Segment.Data; // data
}
// Apply fixups.
@@ -843,115 +890,117 @@ void WasmObjectWriter::writeDataSection(ArrayRef<WasmDataSegment> Segments) {
endSection(Section);
}
-void WasmObjectWriter::writeNameSection(
- ArrayRef<WasmFunction> Functions,
- ArrayRef<WasmImport> Imports,
- unsigned NumFuncImports) {
- uint32_t TotalFunctions = NumFuncImports + Functions.size();
- if (TotalFunctions == 0)
- return;
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_CUSTOM, "name");
- SectionBookkeeping SubSection;
- startSection(SubSection, wasm::WASM_NAMES_FUNCTION);
-
- encodeULEB128(TotalFunctions, getStream());
- uint32_t Index = 0;
- for (const WasmImport &Import : Imports) {
- if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
- encodeULEB128(Index, getStream());
- writeString(Import.FieldName);
- ++Index;
- }
- }
- for (const WasmFunction &Func : Functions) {
- encodeULEB128(Index, getStream());
- writeString(Func.Sym->getName());
- ++Index;
- }
-
- endSection(SubSection);
- endSection(Section);
-}
-
-void WasmObjectWriter::writeCodeRelocSection() {
+void WasmObjectWriter::writeRelocSection(
+ uint32_t SectionIndex, StringRef Name,
+ ArrayRef<WasmRelocationEntry> Relocations) {
// See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
// for descriptions of the reloc sections.
- if (CodeRelocations.empty())
+ if (Relocations.empty())
return;
SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.CODE");
+ startCustomSection(Section, std::string("reloc.") + Name.str());
- encodeULEB128(wasm::WASM_SEC_CODE, getStream());
- encodeULEB128(CodeRelocations.size(), getStream());
+ encodeULEB128(SectionIndex, W.OS);
+ encodeULEB128(Relocations.size(), W.OS);
+ for (const WasmRelocationEntry& RelEntry : Relocations) {
+ uint64_t Offset = RelEntry.Offset +
+ RelEntry.FixupSection->getSectionOffset();
+ uint32_t Index = getRelocationIndexValue(RelEntry);
- writeRelocations(CodeRelocations);
+ W.OS << char(RelEntry.Type);
+ encodeULEB128(Offset, W.OS);
+ encodeULEB128(Index, W.OS);
+ if (RelEntry.hasAddend())
+ encodeSLEB128(RelEntry.Addend, W.OS);
+ }
endSection(Section);
}
-void WasmObjectWriter::writeDataRelocSection() {
- // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
- // for descriptions of the reloc sections.
-
- if (DataRelocations.empty())
- return;
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.DATA");
-
- encodeULEB128(wasm::WASM_SEC_DATA, getStream());
- encodeULEB128(DataRelocations.size(), getStream());
-
- writeRelocations(DataRelocations);
-
- endSection(Section);
+void WasmObjectWriter::writeCustomRelocSections() {
+ for (const auto &Sec : CustomSections) {
+ auto &Relocations = CustomSectionsRelocations[Sec.Section];
+ writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
+ }
}
void WasmObjectWriter::writeLinkingMetaDataSection(
- ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
- const SmallVector<std::pair<StringRef, uint32_t>, 4> &SymbolFlags,
- const SmallVector<std::pair<uint16_t, uint32_t>, 2> &InitFuncs) {
+ ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
+ ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
+ const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) {
SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
- SectionBookkeeping SubSection;
+ startCustomSection(Section, "linking");
+ encodeULEB128(wasm::WasmMetadataVersion, W.OS);
- if (SymbolFlags.size() != 0) {
- startSection(SubSection, wasm::WASM_SYMBOL_INFO);
- encodeULEB128(SymbolFlags.size(), getStream());
- for (auto Pair: SymbolFlags) {
- writeString(Pair.first);
- encodeULEB128(Pair.second, getStream());
+ SectionBookkeeping SubSection;
+ if (SymbolInfos.size() != 0) {
+ startSection(SubSection, wasm::WASM_SYMBOL_TABLE);
+ encodeULEB128(SymbolInfos.size(), W.OS);
+ for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) {
+ encodeULEB128(Sym.Kind, W.OS);
+ encodeULEB128(Sym.Flags, W.OS);
+ switch (Sym.Kind) {
+ case wasm::WASM_SYMBOL_TYPE_FUNCTION:
+ case wasm::WASM_SYMBOL_TYPE_GLOBAL:
+ encodeULEB128(Sym.ElementIndex, W.OS);
+ if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
+ writeString(Sym.Name);
+ break;
+ case wasm::WASM_SYMBOL_TYPE_DATA:
+ writeString(Sym.Name);
+ if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
+ encodeULEB128(Sym.DataRef.Segment, W.OS);
+ encodeULEB128(Sym.DataRef.Offset, W.OS);
+ encodeULEB128(Sym.DataRef.Size, W.OS);
+ }
+ break;
+ case wasm::WASM_SYMBOL_TYPE_SECTION: {
+ const uint32_t SectionIndex =
+ CustomSections[Sym.ElementIndex].OutputIndex;
+ encodeULEB128(SectionIndex, W.OS);
+ break;
+ }
+ default:
+ llvm_unreachable("unexpected kind");
+ }
}
endSection(SubSection);
}
- if (DataSize > 0) {
- startSection(SubSection, wasm::WASM_DATA_SIZE);
- encodeULEB128(DataSize, getStream());
- endSection(SubSection);
- }
-
- if (Segments.size()) {
+ if (DataSegments.size()) {
startSection(SubSection, wasm::WASM_SEGMENT_INFO);
- encodeULEB128(Segments.size(), getStream());
- for (const WasmDataSegment &Segment : Segments) {
+ encodeULEB128(DataSegments.size(), W.OS);
+ for (const WasmDataSegment &Segment : DataSegments) {
writeString(Segment.Name);
- encodeULEB128(Segment.Alignment, getStream());
- encodeULEB128(Segment.Flags, getStream());
+ encodeULEB128(Segment.Alignment, W.OS);
+ encodeULEB128(Segment.Flags, W.OS);
}
endSection(SubSection);
}
if (!InitFuncs.empty()) {
startSection(SubSection, wasm::WASM_INIT_FUNCS);
- encodeULEB128(InitFuncs.size(), getStream());
+ encodeULEB128(InitFuncs.size(), W.OS);
for (auto &StartFunc : InitFuncs) {
- encodeULEB128(StartFunc.first, getStream()); // priority
- encodeULEB128(StartFunc.second, getStream()); // function index
+ encodeULEB128(StartFunc.first, W.OS); // priority
+ encodeULEB128(StartFunc.second, W.OS); // function index
+ }
+ endSection(SubSection);
+ }
+
+ if (Comdats.size()) {
+ startSection(SubSection, wasm::WASM_COMDAT_INFO);
+ encodeULEB128(Comdats.size(), W.OS);
+ for (const auto &C : Comdats) {
+ writeString(C.first);
+ encodeULEB128(0, W.OS); // flags for future use
+ encodeULEB128(C.second.size(), W.OS);
+ for (const WasmComdatEntry &Entry : C.second) {
+ encodeULEB128(Entry.Kind, W.OS);
+ encodeULEB128(Entry.Index, W.OS);
+ }
}
endSection(SubSection);
}
@@ -959,6 +1008,27 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
endSection(Section);
}
+void WasmObjectWriter::writeCustomSections(const MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ for (auto &CustomSection : CustomSections) {
+ SectionBookkeeping Section;
+ auto *Sec = CustomSection.Section;
+ startCustomSection(Section, CustomSection.Name);
+
+ Sec->setSectionOffset(W.OS.tell() - Section.ContentsOffset);
+ Asm.writeSectionData(W.OS, Sec, Layout);
+
+ CustomSection.OutputContentsOffset = Section.ContentsOffset;
+ CustomSection.OutputIndex = Section.Index;
+
+ endSection(Section);
+
+ // Apply fixups.
+ auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
+ applyRelocations(Relocations, CustomSection.OutputContentsOffset);
+ }
+}
+
uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm& Symbol) {
assert(Symbol.isFunction());
assert(TypeIndices.count(&Symbol));
@@ -979,94 +1049,56 @@ uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm& Symbol) {
FunctionTypes.push_back(F);
TypeIndices[&Symbol] = Pair.first->second;
- DEBUG(dbgs() << "registerFunctionType: " << Symbol << " new:" << Pair.second << "\n");
- DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
+ LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol
+ << " new:" << Pair.second << "\n");
+ LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
return Pair.first->second;
}
-void WasmObjectWriter::writeObject(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
+static bool isInSymtab(const MCSymbolWasm &Sym) {
+ if (Sym.isUsedInReloc())
+ return true;
+
+ if (Sym.isComdat() && !Sym.isDefined())
+ return false;
+
+ if (Sym.isTemporary() && Sym.getName().empty())
+ return false;
+
+ if (Sym.isTemporary() && Sym.isData() && !Sym.getSize())
+ return false;
+
+ if (Sym.isSection())
+ return false;
+
+ return true;
+}
+
+uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ uint64_t StartOffset = W.OS.tell();
+
+ LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
MCContext &Ctx = Asm.getContext();
- wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32;
// Collect information from the available symbols.
SmallVector<WasmFunction, 4> Functions;
SmallVector<uint32_t, 4> TableElems;
- SmallVector<WasmImport, 4> Imports;
- SmallVector<WasmExport, 4> Exports;
- SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags;
+ SmallVector<wasm::WasmImport, 4> Imports;
+ SmallVector<wasm::WasmExport, 4> Exports;
+ SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
- unsigned NumFuncImports = 0;
- SmallVector<WasmDataSegment, 4> DataSegments;
+ std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
uint32_t DataSize = 0;
- // In the special .global_variables section, we've encoded global
- // variables used by the function. Translate them into the Globals
- // list.
- MCSectionWasm *GlobalVars =
- Ctx.getWasmSection(".global_variables", SectionKind::getMetadata());
- if (!GlobalVars->getFragmentList().empty()) {
- if (GlobalVars->getFragmentList().size() != 1)
- report_fatal_error("only one .global_variables fragment supported");
- const MCFragment &Frag = *GlobalVars->begin();
- if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
- report_fatal_error("only data supported in .global_variables");
- const auto &DataFrag = cast<MCDataFragment>(Frag);
- if (!DataFrag.getFixups().empty())
- report_fatal_error("fixups not supported in .global_variables");
- const SmallVectorImpl<char> &Contents = DataFrag.getContents();
- for (const uint8_t *p = (const uint8_t *)Contents.data(),
- *end = (const uint8_t *)Contents.data() + Contents.size();
- p != end; ) {
- WasmGlobal G;
- if (end - p < 3)
- report_fatal_error("truncated global variable encoding");
- G.Type = wasm::ValType(int8_t(*p++));
- G.IsMutable = bool(*p++);
- G.HasImport = bool(*p++);
- if (G.HasImport) {
- G.InitialValue = 0;
-
- WasmImport Import;
- Import.ModuleName = (const char *)p;
- const uint8_t *nul = (const uint8_t *)memchr(p, '\0', end - p);
- if (!nul)
- report_fatal_error("global module name must be nul-terminated");
- p = nul + 1;
- nul = (const uint8_t *)memchr(p, '\0', end - p);
- if (!nul)
- report_fatal_error("global base name must be nul-terminated");
- Import.FieldName = (const char *)p;
- p = nul + 1;
-
- Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
- Import.Type = int32_t(G.Type);
-
- G.ImportIndex = NumGlobalImports;
- ++NumGlobalImports;
-
- Imports.push_back(Import);
- } else {
- unsigned n;
- G.InitialValue = decodeSLEB128(p, &n);
- G.ImportIndex = 0;
- if ((ptrdiff_t)n > end - p)
- report_fatal_error("global initial value must be valid SLEB128");
- p += n;
- }
- Globals.push_back(G);
- }
- }
-
// For now, always emit the memory import, since loads and stores are not
// valid without it. In the future, we could perhaps be more clever and omit
// it if there are no loads or stores.
MCSymbolWasm *MemorySym =
cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__linear_memory"));
- WasmImport MemImport;
- MemImport.ModuleName = MemorySym->getModuleName();
- MemImport.FieldName = MemorySym->getName();
+ wasm::WasmImport MemImport;
+ MemImport.Module = MemorySym->getModuleName();
+ MemImport.Field = MemorySym->getName();
MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
Imports.push_back(MemImport);
@@ -1075,20 +1107,21 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
// it if there are no indirect calls.
MCSymbolWasm *TableSym =
cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__indirect_function_table"));
- WasmImport TableImport;
- TableImport.ModuleName = TableSym->getModuleName();
- TableImport.FieldName = TableSym->getName();
+ wasm::WasmImport TableImport;
+ TableImport.Module = TableSym->getModuleName();
+ TableImport.Field = TableSym->getName();
TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
- TableImport.Type = wasm::WASM_TYPE_ANYFUNC;
+ TableImport.Table.ElemType = wasm::WASM_TYPE_ANYFUNC;
Imports.push_back(TableImport);
- // Populate FunctionTypeIndices and Imports.
+ // Populate FunctionTypeIndices, and Imports and WasmIndices for undefined
+ // symbols. This must be done before populating WasmIndices for defined
+ // symbols.
for (const MCSymbol &S : Asm.symbols()) {
const auto &WS = static_cast<const MCSymbolWasm &>(S);
// Register types for all functions, including those with private linkage
- // (making them
- // because wasm always needs a type signature.
+ // (because wasm always needs a type signature).
if (WS.isFunction())
registerFunctionType(WS);
@@ -1096,56 +1129,84 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
continue;
// If the symbol is not defined in this translation unit, import it.
- if (!WS.isDefined(/*SetUsed=*/false) || WS.isVariable()) {
- WasmImport Import;
- Import.ModuleName = WS.getModuleName();
- Import.FieldName = WS.getName();
-
+ if (!WS.isDefined() && !WS.isComdat()) {
if (WS.isFunction()) {
+ wasm::WasmImport Import;
+ Import.Module = WS.getModuleName();
+ Import.Field = WS.getName();
Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
- Import.Type = getFunctionType(WS);
- SymbolIndices[&WS] = NumFuncImports;
- ++NumFuncImports;
- } else {
+ Import.SigIndex = getFunctionType(WS);
+ Imports.push_back(Import);
+ WasmIndices[&WS] = NumFunctionImports++;
+ } else if (WS.isGlobal()) {
+ if (WS.isWeak())
+ report_fatal_error("undefined global symbol cannot be weak");
+
+ wasm::WasmImport Import;
+ Import.Module = WS.getModuleName();
+ Import.Field = WS.getName();
Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
- Import.Type = int32_t(PtrType);
- Import.IsMutable = false;
- SymbolIndices[&WS] = NumGlobalImports;
-
- // If this global is the stack pointer, make it mutable.
- if (WS.getName() == "__stack_pointer")
- Import.IsMutable = true;
-
- ++NumGlobalImports;
+ Import.Global = WS.getGlobalType();
+ Imports.push_back(Import);
+ WasmIndices[&WS] = NumGlobalImports++;
}
-
- Imports.push_back(Import);
}
}
+ // Populate DataSegments and CustomSections, which must be done before
+ // populating DataLocations.
for (MCSection &Sec : Asm) {
auto &Section = static_cast<MCSectionWasm &>(Sec);
- if (!Section.isWasmData())
- continue;
+ StringRef SectionName = Section.getSectionName();
// .init_array sections are handled specially elsewhere.
- if (cast<MCSectionWasm>(Sec).getSectionName().startswith(".init_array"))
+ if (SectionName.startswith(".init_array"))
continue;
- DataSize = alignTo(DataSize, Section.getAlignment());
- DataSegments.emplace_back();
- WasmDataSegment &Segment = DataSegments.back();
- Segment.Name = Section.getSectionName();
- Segment.Offset = DataSize;
- Segment.Section = &Section;
- addData(Segment.Data, Section);
- Segment.Alignment = Section.getAlignment();
- Segment.Flags = 0;
- DataSize += Segment.Data.size();
- Section.setMemoryOffset(Segment.Offset);
+ // Code is handled separately
+ if (Section.getKind().isText())
+ continue;
+
+ if (Section.isWasmData()) {
+ uint32_t SegmentIndex = DataSegments.size();
+ DataSize = alignTo(DataSize, Section.getAlignment());
+ DataSegments.emplace_back();
+ WasmDataSegment &Segment = DataSegments.back();
+ Segment.Name = SectionName;
+ Segment.Offset = DataSize;
+ Segment.Section = &Section;
+ addData(Segment.Data, Section);
+ Segment.Alignment = Section.getAlignment();
+ Segment.Flags = 0;
+ DataSize += Segment.Data.size();
+ Section.setSegmentIndex(SegmentIndex);
+
+ if (const MCSymbolWasm *C = Section.getGroup()) {
+ Comdats[C->getName()].emplace_back(
+ WasmComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex});
+ }
+ } else {
+ // Create custom sections
+ assert(Sec.getKind().isMetadata());
+
+ StringRef Name = SectionName;
+
+ // For user-defined custom sections, strip the prefix
+ if (Name.startswith(".custom_section."))
+ Name = Name.substr(strlen(".custom_section."));
+
+ MCSymbol* Begin = Sec.getBeginSymbol();
+ if (Begin) {
+ WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
+ if (SectionName != Begin->getName())
+ report_fatal_error("section name and begin symbol should match: " +
+ Twine(SectionName));
+ }
+ CustomSections.emplace_back(Name, &Section);
+ }
}
- // Handle regular defined and undefined symbols.
+ // Populate WasmIndices and DataLocations for defined symbols.
for (const MCSymbol &S : Asm.symbols()) {
// Ignore unnamed temporary symbols, which aren't ever exported, imported,
// or used in relocations.
@@ -1153,27 +1214,21 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
continue;
const auto &WS = static_cast<const MCSymbolWasm &>(S);
- DEBUG(dbgs() << "MCSymbol: '" << S << "'"
- << " isDefined=" << S.isDefined() << " isExternal="
- << S.isExternal() << " isTemporary=" << S.isTemporary()
- << " isFunction=" << WS.isFunction()
- << " isWeak=" << WS.isWeak()
- << " isHidden=" << WS.isHidden()
- << " isVariable=" << WS.isVariable() << "\n");
-
- if (WS.isWeak() || WS.isHidden()) {
- uint32_t Flags = (WS.isWeak() ? wasm::WASM_SYMBOL_BINDING_WEAK : 0) |
- (WS.isHidden() ? wasm::WASM_SYMBOL_VISIBILITY_HIDDEN : 0);
- SymbolFlags.emplace_back(WS.getName(), Flags);
- }
+ LLVM_DEBUG(
+ dbgs() << "MCSymbol: " << toString(WS.getType()) << " '" << S << "'"
+ << " isDefined=" << S.isDefined() << " isExternal="
+ << S.isExternal() << " isTemporary=" << S.isTemporary()
+ << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden()
+ << " isVariable=" << WS.isVariable() << "\n");
if (WS.isVariable())
continue;
-
- unsigned Index;
+ if (WS.isComdat() && !WS.isDefined())
+ continue;
if (WS.isFunction()) {
- if (WS.isDefined(/*SetUsed=*/false)) {
+ unsigned Index;
+ if (WS.isDefined()) {
if (WS.getOffset() != 0)
report_fatal_error(
"function sections must contain one function each");
@@ -1182,27 +1237,34 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
report_fatal_error(
"function symbols must have a size set with .size");
- // A definition. Take the next available index.
- Index = NumFuncImports + Functions.size();
-
- // Prepare the function.
+ // A definition. Write out the function body.
+ Index = NumFunctionImports + Functions.size();
WasmFunction Func;
Func.Type = getFunctionType(WS);
Func.Sym = &WS;
- SymbolIndices[&WS] = Index;
+ WasmIndices[&WS] = Index;
Functions.push_back(Func);
+
+ auto &Section = static_cast<MCSectionWasm &>(WS.getSection());
+ if (const MCSymbolWasm *C = Section.getGroup()) {
+ Comdats[C->getName()].emplace_back(
+ WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index});
+ }
} else {
// An import; the index was assigned above.
- Index = SymbolIndices.find(&WS)->second;
+ Index = WasmIndices.find(&WS)->second;
}
- DEBUG(dbgs() << " -> function index: " << Index << "\n");
- } else {
+ LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n");
+ } else if (WS.isData()) {
if (WS.isTemporary() && !WS.getSize())
continue;
- if (!WS.isDefined(/*SetUsed=*/false))
+ if (!WS.isDefined()) {
+ LLVM_DEBUG(dbgs() << " -> segment index: -1"
+ << "\n");
continue;
+ }
if (!WS.getSize())
report_fatal_error("data symbols must have a size set with .size: " +
@@ -1212,90 +1274,113 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
report_fatal_error(".size expression must be evaluatable");
- // For each global, prepare a corresponding wasm global holding its
- // address. For externals these will also be named exports.
- Index = NumGlobalImports + Globals.size();
auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
-
- WasmGlobal Global;
- Global.Type = PtrType;
- Global.IsMutable = false;
- Global.HasImport = false;
- Global.InitialValue = DataSection.getMemoryOffset() + Layout.getSymbolOffset(WS);
- Global.ImportIndex = 0;
- SymbolIndices[&WS] = Index;
- DEBUG(dbgs() << " -> global index: " << Index << "\n");
- Globals.push_back(Global);
- }
-
- // If the symbol is visible outside this translation unit, export it.
- if (WS.isDefined(/*SetUsed=*/false)) {
- WasmExport Export;
- Export.FieldName = WS.getName();
- Export.Index = Index;
- if (WS.isFunction())
- Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
- else
- Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
- DEBUG(dbgs() << " -> export " << Exports.size() << "\n");
- Exports.push_back(Export);
- if (!WS.isExternal())
- SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
+ assert(DataSection.isWasmData());
+
+ // For each data symbol, export it in the symtab as a reference to the
+ // corresponding Wasm data segment.
+ wasm::WasmDataReference Ref = wasm::WasmDataReference{
+ DataSection.getSegmentIndex(),
+ static_cast<uint32_t>(Layout.getSymbolOffset(WS)),
+ static_cast<uint32_t>(Size)};
+ DataLocations[&WS] = Ref;
+ LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n");
+ } else if (WS.isGlobal()) {
+ // A "true" Wasm global (currently just __stack_pointer)
+ if (WS.isDefined())
+ report_fatal_error("don't yet support defined globals");
+
+ // An import; the index was assigned above
+ LLVM_DEBUG(dbgs() << " -> global index: "
+ << WasmIndices.find(&WS)->second << "\n");
+ } else {
+ assert(WS.isSection());
}
}
- // Handle weak aliases. We need to process these in a separate pass because
- // we need to have processed the target of the alias before the alias itself
- // and the symbols are not necessarily ordered in this way.
+ // Populate WasmIndices and DataLocations for aliased symbols. We need to
+ // process these in a separate pass because we need to have processed the
+ // target of the alias before the alias itself and the symbols are not
+ // necessarily ordered in this way.
for (const MCSymbol &S : Asm.symbols()) {
if (!S.isVariable())
continue;
- assert(S.isDefined(/*SetUsed=*/false));
+ assert(S.isDefined());
// Find the target symbol of this weak alias and export that index
const auto &WS = static_cast<const MCSymbolWasm &>(S);
const MCSymbolWasm *ResolvedSym = ResolveSymbol(WS);
- DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym << "'\n");
- assert(SymbolIndices.count(ResolvedSym) > 0);
- uint32_t Index = SymbolIndices.find(ResolvedSym)->second;
- DEBUG(dbgs() << " -> index:" << Index << "\n");
-
- WasmExport Export;
- Export.FieldName = WS.getName();
- Export.Index = Index;
- if (WS.isFunction())
- Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
- else
- Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
- DEBUG(dbgs() << " -> export " << Exports.size() << "\n");
- Exports.push_back(Export);
+ LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym
+ << "'\n");
- if (!WS.isExternal())
- SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
+ if (WS.isFunction()) {
+ assert(WasmIndices.count(ResolvedSym) > 0);
+ uint32_t WasmIndex = WasmIndices.find(ResolvedSym)->second;
+ WasmIndices[&WS] = WasmIndex;
+ LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n");
+ } else if (WS.isData()) {
+ assert(DataLocations.count(ResolvedSym) > 0);
+ const wasm::WasmDataReference &Ref =
+ DataLocations.find(ResolvedSym)->second;
+ DataLocations[&WS] = Ref;
+ LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n");
+ } else {
+ report_fatal_error("don't yet support global aliases");
+ }
+ }
+
+ // Finally, populate the symbol table itself, in its "natural" order.
+ for (const MCSymbol &S : Asm.symbols()) {
+ const auto &WS = static_cast<const MCSymbolWasm &>(S);
+ if (!isInSymtab(WS)) {
+ WS.setIndex(INVALID_INDEX);
+ continue;
+ }
+ LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n");
+
+ uint32_t Flags = 0;
+ if (WS.isWeak())
+ Flags |= wasm::WASM_SYMBOL_BINDING_WEAK;
+ if (WS.isHidden())
+ Flags |= wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
+ if (!WS.isExternal() && WS.isDefined())
+ Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
+ if (WS.isUndefined())
+ Flags |= wasm::WASM_SYMBOL_UNDEFINED;
+
+ wasm::WasmSymbolInfo Info;
+ Info.Name = WS.getName();
+ Info.Kind = WS.getType();
+ Info.Flags = Flags;
+ if (!WS.isData()) {
+ assert(WasmIndices.count(&WS) > 0);
+ Info.ElementIndex = WasmIndices.find(&WS)->second;
+ } else if (WS.isDefined()) {
+ assert(DataLocations.count(&WS) > 0);
+ Info.DataRef = DataLocations.find(&WS)->second;
+ }
+ WS.setIndex(SymbolInfos.size());
+ SymbolInfos.emplace_back(Info);
}
{
auto HandleReloc = [&](const WasmRelocationEntry &Rel) {
- // Functions referenced by a relocation need to prepared to be called
- // indirectly.
- const MCSymbolWasm& WS = *Rel.Symbol;
- if (WS.isFunction() && IndirectSymbolIndices.count(&WS) == 0) {
- switch (Rel.Type) {
- case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
- case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
- case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
- case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
- uint32_t Index = SymbolIndices.find(&WS)->second;
- IndirectSymbolIndices[&WS] = TableElems.size();
- DEBUG(dbgs() << " -> adding to table: " << TableElems.size() << "\n");
- TableElems.push_back(Index);
- registerFunctionType(WS);
- break;
- }
- default:
- break;
- }
+ // Functions referenced by a relocation need to put in the table. This is
+ // purely to make the object file's provisional values readable, and is
+ // ignored by the linker, which re-calculates the relocations itself.
+ if (Rel.Type != wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 &&
+ Rel.Type != wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB)
+ return;
+ assert(Rel.Symbol->isFunction());
+ const MCSymbolWasm &WS = *ResolveSymbol(*Rel.Symbol);
+ uint32_t FunctionIndex = WasmIndices.find(&WS)->second;
+ uint32_t TableIndex = TableElems.size() + kInitialTableOffset;
+ if (TableIndices.try_emplace(&WS, TableIndex).second) {
+ LLVM_DEBUG(dbgs() << " -> adding " << WS.getName()
+ << " to table: " << TableIndex << "\n");
+ TableElems.push_back(FunctionIndex);
+ registerFunctionType(WS);
}
};
@@ -1314,21 +1399,35 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
continue;
if (WS.getFragmentList().empty())
continue;
- if (WS.getFragmentList().size() != 2)
+
+ // init_array is expected to contain a single non-empty data fragment
+ if (WS.getFragmentList().size() != 3)
report_fatal_error("only one .init_array section fragment supported");
- const MCFragment &AlignFrag = *WS.begin();
+
+ auto IT = WS.begin();
+ const MCFragment &EmptyFrag = *IT;
+ if (EmptyFrag.getKind() != MCFragment::FT_Data)
+ report_fatal_error(".init_array section should be aligned");
+
+ IT = std::next(IT);
+ const MCFragment &AlignFrag = *IT;
if (AlignFrag.getKind() != MCFragment::FT_Align)
report_fatal_error(".init_array section should be aligned");
if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (is64Bit() ? 8 : 4))
report_fatal_error(".init_array section should be aligned for pointers");
- const MCFragment &Frag = *std::next(WS.begin());
+
+ const MCFragment &Frag = *std::next(IT);
if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
report_fatal_error("only data supported in .init_array section");
+
uint16_t Priority = UINT16_MAX;
- if (WS.getSectionName().size() != 11) {
- if (WS.getSectionName()[11] != '.')
+ unsigned PrefixLength = strlen(".init_array");
+ if (WS.getSectionName().size() > PrefixLength) {
+ if (WS.getSectionName()[PrefixLength] != '.')
report_fatal_error(".init_array section priority should start with '.'");
- if (WS.getSectionName().substr(12).getAsInteger(10, Priority))
+ if (WS.getSectionName()
+ .substr(PrefixLength + 1)
+ .getAsInteger(10, Priority))
report_fatal_error("invalid .init_array section priority");
}
const auto &DataFrag = cast<MCDataFragment>(Frag);
@@ -1347,11 +1446,10 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
report_fatal_error("fixups in .init_array should be symbol references");
if (Sym->getKind() != MCSymbolRefExpr::VK_WebAssembly_FUNCTION)
report_fatal_error("symbols in .init_array should be for functions");
- auto I = SymbolIndices.find(cast<MCSymbolWasm>(&Sym->getSymbol()));
- if (I == SymbolIndices.end())
- report_fatal_error("symbols in .init_array should be defined");
- uint32_t Index = I->second;
- InitFuncs.push_back(std::make_pair(Priority, Index));
+ if (Sym->getSymbol().getIndex() == INVALID_INDEX)
+ report_fatal_error("symbols in .init_array should exist in symbtab");
+ InitFuncs.push_back(
+ std::make_pair(Priority, Sym->getSymbol().getIndex()));
}
}
@@ -1367,22 +1465,19 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
writeExportSection(Exports);
writeElemSection(TableElems);
writeCodeSection(Asm, Layout, Functions);
- writeDataSection(DataSegments);
- writeNameSection(Functions, Imports, NumFuncImports);
- writeCodeRelocSection();
- writeDataRelocSection();
- writeLinkingMetaDataSection(DataSegments, DataSize, SymbolFlags,
- InitFuncs);
+ writeDataSection();
+ writeCustomSections(Asm, Layout);
+ writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
+ writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);
+ writeRelocSection(DataSectionIndex, "DATA", DataRelocations);
+ writeCustomRelocSections();
// TODO: Translate the .comment section to the output.
- // TODO: Translate debug sections to the output.
+ return W.OS.tell() - StartOffset;
}
std::unique_ptr<MCObjectWriter>
llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
raw_pwrite_stream &OS) {
- // FIXME: Can't use make_unique<WasmObjectWriter>(...) as WasmObjectWriter's
- // destructor is private. Is that necessary?
- return std::unique_ptr<MCObjectWriter>(
- new WasmObjectWriter(std::move(MOTW), OS));
+ return llvm::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
}
diff --git a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp
index 9f1db46939c7..9ffecd99df68 100644
--- a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -125,6 +125,8 @@ public:
class WinCOFFObjectWriter : public MCObjectWriter {
public:
+ support::endian::Writer W;
+
using symbols = std::vector<std::unique_ptr<COFFSymbol>>;
using sections = std::vector<std::unique_ptr<COFFSection>>;
@@ -204,7 +206,7 @@ public:
void assignSectionNumbers();
void assignFileOffsets(MCAssembler &Asm, const MCAsmLayout &Layout);
- void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+ uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
};
} // end anonymous namespace
@@ -225,7 +227,7 @@ void COFFSymbol::set_name_offset(uint32_t Offset) {
WinCOFFObjectWriter::WinCOFFObjectWriter(
std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
- : MCObjectWriter(OS, true), TargetObjectWriter(std::move(MOTW)) {
+ : W(OS, support::little), TargetObjectWriter(std::move(MOTW)) {
Header.Machine = TargetObjectWriter->getMachine();
}
@@ -472,40 +474,40 @@ bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) {
if (UseBigObj) {
- writeLE16(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
- writeLE16(0xFFFF);
- writeLE16(COFF::BigObjHeader::MinBigObjectVersion);
- writeLE16(Header.Machine);
- writeLE32(Header.TimeDateStamp);
- writeBytes(StringRef(COFF::BigObjMagic, sizeof(COFF::BigObjMagic)));
- writeLE32(0);
- writeLE32(0);
- writeLE32(0);
- writeLE32(0);
- writeLE32(Header.NumberOfSections);
- writeLE32(Header.PointerToSymbolTable);
- writeLE32(Header.NumberOfSymbols);
+ W.write<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
+ W.write<uint16_t>(0xFFFF);
+ W.write<uint16_t>(COFF::BigObjHeader::MinBigObjectVersion);
+ W.write<uint16_t>(Header.Machine);
+ W.write<uint32_t>(Header.TimeDateStamp);
+ W.OS.write(COFF::BigObjMagic, sizeof(COFF::BigObjMagic));
+ W.write<uint32_t>(0);
+ W.write<uint32_t>(0);
+ W.write<uint32_t>(0);
+ W.write<uint32_t>(0);
+ W.write<uint32_t>(Header.NumberOfSections);
+ W.write<uint32_t>(Header.PointerToSymbolTable);
+ W.write<uint32_t>(Header.NumberOfSymbols);
} else {
- writeLE16(Header.Machine);
- writeLE16(static_cast<int16_t>(Header.NumberOfSections));
- writeLE32(Header.TimeDateStamp);
- writeLE32(Header.PointerToSymbolTable);
- writeLE32(Header.NumberOfSymbols);
- writeLE16(Header.SizeOfOptionalHeader);
- writeLE16(Header.Characteristics);
+ W.write<uint16_t>(Header.Machine);
+ W.write<uint16_t>(static_cast<int16_t>(Header.NumberOfSections));
+ W.write<uint32_t>(Header.TimeDateStamp);
+ W.write<uint32_t>(Header.PointerToSymbolTable);
+ W.write<uint32_t>(Header.NumberOfSymbols);
+ W.write<uint16_t>(Header.SizeOfOptionalHeader);
+ W.write<uint16_t>(Header.Characteristics);
}
}
void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) {
- writeBytes(StringRef(S.Data.Name, COFF::NameSize));
- writeLE32(S.Data.Value);
+ W.OS.write(S.Data.Name, COFF::NameSize);
+ W.write<uint32_t>(S.Data.Value);
if (UseBigObj)
- writeLE32(S.Data.SectionNumber);
+ W.write<uint32_t>(S.Data.SectionNumber);
else
- writeLE16(static_cast<int16_t>(S.Data.SectionNumber));
- writeLE16(S.Data.Type);
- write8(S.Data.StorageClass);
- write8(S.Data.NumberOfAuxSymbols);
+ W.write<uint16_t>(static_cast<int16_t>(S.Data.SectionNumber));
+ W.write<uint16_t>(S.Data.Type);
+ W.OS << char(S.Data.StorageClass);
+ W.OS << char(S.Data.NumberOfAuxSymbols);
WriteAuxiliarySymbols(S.Aux);
}
@@ -514,46 +516,45 @@ void WinCOFFObjectWriter::WriteAuxiliarySymbols(
for (const AuxSymbol &i : S) {
switch (i.AuxType) {
case ATFunctionDefinition:
- writeLE32(i.Aux.FunctionDefinition.TagIndex);
- writeLE32(i.Aux.FunctionDefinition.TotalSize);
- writeLE32(i.Aux.FunctionDefinition.PointerToLinenumber);
- writeLE32(i.Aux.FunctionDefinition.PointerToNextFunction);
- WriteZeros(sizeof(i.Aux.FunctionDefinition.unused));
+ W.write<uint32_t>(i.Aux.FunctionDefinition.TagIndex);
+ W.write<uint32_t>(i.Aux.FunctionDefinition.TotalSize);
+ W.write<uint32_t>(i.Aux.FunctionDefinition.PointerToLinenumber);
+ W.write<uint32_t>(i.Aux.FunctionDefinition.PointerToNextFunction);
+ W.OS.write_zeros(sizeof(i.Aux.FunctionDefinition.unused));
if (UseBigObj)
- WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
+ W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
case ATbfAndefSymbol:
- WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused1));
- writeLE16(i.Aux.bfAndefSymbol.Linenumber);
- WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused2));
- writeLE32(i.Aux.bfAndefSymbol.PointerToNextFunction);
- WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused3));
+ W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused1));
+ W.write<uint16_t>(i.Aux.bfAndefSymbol.Linenumber);
+ W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused2));
+ W.write<uint32_t>(i.Aux.bfAndefSymbol.PointerToNextFunction);
+ W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused3));
if (UseBigObj)
- WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
+ W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
case ATWeakExternal:
- writeLE32(i.Aux.WeakExternal.TagIndex);
- writeLE32(i.Aux.WeakExternal.Characteristics);
- WriteZeros(sizeof(i.Aux.WeakExternal.unused));
+ W.write<uint32_t>(i.Aux.WeakExternal.TagIndex);
+ W.write<uint32_t>(i.Aux.WeakExternal.Characteristics);
+ W.OS.write_zeros(sizeof(i.Aux.WeakExternal.unused));
if (UseBigObj)
- WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
+ W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
case ATFile:
- writeBytes(
- StringRef(reinterpret_cast<const char *>(&i.Aux),
- UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size));
+ W.OS.write(reinterpret_cast<const char *>(&i.Aux),
+ UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size);
break;
case ATSectionDefinition:
- writeLE32(i.Aux.SectionDefinition.Length);
- writeLE16(i.Aux.SectionDefinition.NumberOfRelocations);
- writeLE16(i.Aux.SectionDefinition.NumberOfLinenumbers);
- writeLE32(i.Aux.SectionDefinition.CheckSum);
- writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number));
- write8(i.Aux.SectionDefinition.Selection);
- WriteZeros(sizeof(i.Aux.SectionDefinition.unused));
- writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16));
+ W.write<uint32_t>(i.Aux.SectionDefinition.Length);
+ W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfRelocations);
+ W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfLinenumbers);
+ W.write<uint32_t>(i.Aux.SectionDefinition.CheckSum);
+ W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number));
+ W.OS << char(i.Aux.SectionDefinition.Selection);
+ W.OS.write_zeros(sizeof(i.Aux.SectionDefinition.unused));
+ W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16));
if (UseBigObj)
- WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
+ W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
}
}
@@ -567,10 +568,10 @@ void WinCOFFObjectWriter::writeSectionHeaders() {
std::vector<COFFSection *> Arr;
for (auto &Section : Sections)
Arr.push_back(Section.get());
- std::sort(Arr.begin(), Arr.end(),
- [](const COFFSection *A, const COFFSection *B) {
- return A->Number < B->Number;
- });
+ llvm::sort(Arr.begin(), Arr.end(),
+ [](const COFFSection *A, const COFFSection *B) {
+ return A->Number < B->Number;
+ });
for (auto &Section : Arr) {
if (Section->Number == -1)
@@ -579,23 +580,23 @@ void WinCOFFObjectWriter::writeSectionHeaders() {
COFF::section &S = Section->Header;
if (Section->Relocations.size() >= 0xffff)
S.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL;
- writeBytes(StringRef(S.Name, COFF::NameSize));
- writeLE32(S.VirtualSize);
- writeLE32(S.VirtualAddress);
- writeLE32(S.SizeOfRawData);
- writeLE32(S.PointerToRawData);
- writeLE32(S.PointerToRelocations);
- writeLE32(S.PointerToLineNumbers);
- writeLE16(S.NumberOfRelocations);
- writeLE16(S.NumberOfLineNumbers);
- writeLE32(S.Characteristics);
+ W.OS.write(S.Name, COFF::NameSize);
+ W.write<uint32_t>(S.VirtualSize);
+ W.write<uint32_t>(S.VirtualAddress);
+ W.write<uint32_t>(S.SizeOfRawData);
+ W.write<uint32_t>(S.PointerToRawData);
+ W.write<uint32_t>(S.PointerToRelocations);
+ W.write<uint32_t>(S.PointerToLineNumbers);
+ W.write<uint16_t>(S.NumberOfRelocations);
+ W.write<uint16_t>(S.NumberOfLineNumbers);
+ W.write<uint32_t>(S.Characteristics);
}
}
void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
- writeLE32(R.VirtualAddress);
- writeLE32(R.SymbolTableIndex);
- writeLE16(R.Type);
+ W.write<uint32_t>(R.VirtualAddress);
+ W.write<uint32_t>(R.SymbolTableIndex);
+ W.write<uint16_t>(R.Type);
}
// Write MCSec's contents. What this function does is essentially
@@ -608,18 +609,10 @@ uint32_t WinCOFFObjectWriter::writeSectionContents(MCAssembler &Asm,
// to CRC the data before we dump it into the object file.
SmallVector<char, 128> Buf;
raw_svector_ostream VecOS(Buf);
- raw_pwrite_stream &OldStream = getStream();
-
- // Redirect the output stream to our buffer and fill our buffer with
- // the section data.
- setStream(VecOS);
- Asm.writeSectionData(&MCSec, Layout);
-
- // Reset the stream back to what it was before.
- setStream(OldStream);
+ Asm.writeSectionData(VecOS, &MCSec, Layout);
// Write the section contents to the object file.
- getStream() << Buf;
+ W.OS << Buf;
// Calculate our CRC with an initial value of '0', this is not how
// JamCRC is specified but it aligns with the expected output.
@@ -637,13 +630,13 @@ void WinCOFFObjectWriter::writeSection(MCAssembler &Asm,
// Write the section contents.
if (Sec.Header.PointerToRawData != 0) {
- assert(getStream().tell() <= Sec.Header.PointerToRawData &&
+ assert(W.OS.tell() <= Sec.Header.PointerToRawData &&
"Section::PointerToRawData is insane!");
- unsigned PaddingSize = Sec.Header.PointerToRawData - getStream().tell();
+ unsigned PaddingSize = Sec.Header.PointerToRawData - W.OS.tell();
assert(PaddingSize < 4 &&
"Should only need at most three bytes of padding!");
- WriteZeros(PaddingSize);
+ W.OS.write_zeros(PaddingSize);
uint32_t CRC = writeSectionContents(Asm, Layout, MCSec);
@@ -662,7 +655,7 @@ void WinCOFFObjectWriter::writeSection(MCAssembler &Asm,
return;
}
- assert(getStream().tell() == Sec.Header.PointerToRelocations &&
+ assert(W.OS.tell() == Sec.Header.PointerToRelocations &&
"Section::PointerToRelocations is insane!");
if (Sec.Relocations.size() >= 0xffff) {
@@ -697,12 +690,14 @@ void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
bool InSet, bool IsPCRel) const {
- // MS LINK expects to be able to replace all references to a function with a
- // thunk to implement their /INCREMENTAL feature. Make sure we don't optimize
- // away any relocations to functions.
+ // Don't drop relocations between functions, even if they are in the same text
+ // section. Multiple Visual C++ linker features depend on having the
+ // relocations present. The /INCREMENTAL flag will cause these relocations to
+ // point to thunks, and the /GUARD:CF flag assumes that it can use relocations
+ // to approximate the set of all address taken functions. LLD's implementation
+ // of /GUARD:CF also relies on the existance of these relocations.
uint16_t Type = cast<MCSymbolCOFF>(SymA).getType();
- if (Asm.isIncrementalLinkerCompatible() &&
- (Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
+ if ((Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
return false;
return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
InSet, IsPCRel);
@@ -906,7 +901,7 @@ void WinCOFFObjectWriter::assignSectionNumbers() {
// Assign file offsets to COFF object file structures.
void WinCOFFObjectWriter::assignFileOffsets(MCAssembler &Asm,
const MCAsmLayout &Layout) {
- unsigned Offset = getInitialOffset();
+ unsigned Offset = W.OS.tell();
Offset += UseBigObj ? COFF::Header32Size : COFF::Header16Size;
Offset += COFF::SectionSize * Header.NumberOfSections;
@@ -967,8 +962,10 @@ void WinCOFFObjectWriter::assignFileOffsets(MCAssembler &Asm,
Header.PointerToSymbolTable = Offset;
}
-void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
+uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ uint64_t StartOffset = W.OS.tell();
+
if (Sections.size() > INT32_MAX)
report_fatal_error(
"PE COFF object files can't have more than 2147483647 sections");
@@ -1064,7 +1061,7 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
for (; I != IE && J != JE; ++I, ++J)
writeSection(Asm, Layout, **I, *J);
- assert(getStream().tell() == Header.PointerToSymbolTable &&
+ assert(W.OS.tell() == Header.PointerToSymbolTable &&
"Header::PointerToSymbolTable is insane!");
// Write a symbol table.
@@ -1073,7 +1070,9 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
WriteSymbol(*Symbol);
// Write a string table, which completes the entire COFF file.
- Strings.write(getStream());
+ Strings.write(W.OS);
+
+ return W.OS.tell() - StartOffset;
}
MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_)