aboutsummaryrefslogtreecommitdiff
path: root/lib/MC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-10-23 17:51:42 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-10-23 17:51:42 +0000
commit1d5ae1026e831016fc29fd927877c86af904481f (patch)
tree2cdfd12620fcfa5d9e4a0389f85368e8e36f63f9 /lib/MC
parente6d1592492a3a379186bfb02bd0f4eda0669c0d5 (diff)
downloadsrc-1d5ae1026e831016fc29fd927877c86af904481f.tar.gz
src-1d5ae1026e831016fc29fd927877c86af904481f.zip
Vendor import of stripped llvm trunk r375505, the last commit before thevendor/llvm/llvm-trunk-r375505vendor/llvm
upstream Subversion repository was made read-only, and the LLVM project migrated to GitHub: https://llvm.org/svn/llvm-project/llvm/trunk@375505
Notes
Notes: svn path=/vendor/llvm/dist/; revision=353940 svn path=/vendor/llvm/llvm-r375505/; revision=353941; tag=vendor/llvm/llvm-trunk-r375505
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/ELFObjectWriter.cpp86
-rw-r--r--lib/MC/MCAsmBackend.cpp5
-rw-r--r--lib/MC/MCAsmInfoXCOFF.cpp17
-rw-r--r--lib/MC/MCAsmMacro.cpp2
-rw-r--r--lib/MC/MCAsmStreamer.cpp140
-rw-r--r--lib/MC/MCAssembler.cpp38
-rw-r--r--lib/MC/MCContext.cpp29
-rw-r--r--lib/MC/MCDwarf.cpp44
-rw-r--r--lib/MC/MCELFStreamer.cpp7
-rw-r--r--lib/MC/MCExpr.cpp46
-rw-r--r--lib/MC/MCInstPrinter.cpp31
-rw-r--r--lib/MC/MCInstrAnalysis.cpp6
-rw-r--r--lib/MC/MCMachOStreamer.cpp1
-rw-r--r--lib/MC/MCObjectFileInfo.cpp14
-rw-r--r--lib/MC/MCObjectStreamer.cpp4
-rw-r--r--lib/MC/MCParser/AsmParser.cpp142
-rw-r--r--lib/MC/MCParser/COFFAsmParser.cpp155
-rw-r--r--lib/MC/MCParser/DarwinAsmParser.cpp4
-rw-r--r--lib/MC/MCParser/WasmAsmParser.cpp1
-rw-r--r--lib/MC/MCRegisterInfo.cpp48
-rw-r--r--lib/MC/MCSectionXCOFF.cpp50
-rw-r--r--lib/MC/MCStreamer.cpp84
-rw-r--r--lib/MC/MCSubtargetInfo.cpp25
-rw-r--r--lib/MC/MCWasmObjectTargetWriter.cpp5
-rw-r--r--lib/MC/MCWasmStreamer.cpp2
-rw-r--r--lib/MC/MCWinCOFFStreamer.cpp18
-rw-r--r--lib/MC/MCXCOFFStreamer.cpp54
-rw-r--r--lib/MC/MachObjectWriter.cpp14
-rw-r--r--lib/MC/StringTableBuilder.cpp10
-rw-r--r--lib/MC/WasmObjectWriter.cpp77
-rw-r--r--lib/MC/WinCOFFObjectWriter.cpp10
-rw-r--r--lib/MC/XCOFFObjectWriter.cpp533
32 files changed, 1272 insertions, 430 deletions
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index 2c68723a12f8..6f160e491cea 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -36,6 +36,7 @@
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compression.h"
@@ -336,7 +337,7 @@ public:
} // end anonymous namespace
void ELFWriter::align(unsigned Alignment) {
- uint64_t Padding = OffsetToAlignment(W.OS.tell(), Alignment);
+ uint64_t Padding = offsetToAlignment(W.OS.tell(), Align(Alignment));
W.OS.write_zeros(Padding);
}
@@ -511,6 +512,19 @@ static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) {
return Type;
}
+static bool isIFunc(const MCSymbolELF *Symbol) {
+ while (Symbol->getType() != ELF::STT_GNU_IFUNC) {
+ const MCSymbolRefExpr *Value;
+ if (!Symbol->isVariable() ||
+ !(Value = dyn_cast<MCSymbolRefExpr>(Symbol->getVariableValue())) ||
+ Value->getKind() != MCSymbolRefExpr::VK_None ||
+ mergeTypeForSet(Symbol->getType(), ELF::STT_GNU_IFUNC) != ELF::STT_GNU_IFUNC)
+ return false;
+ Symbol = &cast<MCSymbolELF>(Value->getSymbol());
+ }
+ return true;
+}
+
void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
ELFSymbolData &MSD, const MCAsmLayout &Layout) {
const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol);
@@ -524,6 +538,8 @@ void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
// Binding and Type share the same byte as upper and lower nibbles
uint8_t Binding = Symbol.getBinding();
uint8_t Type = Symbol.getType();
+ if (isIFunc(&Symbol))
+ Type = ELF::STT_GNU_IFUNC;
if (Base) {
Type = mergeTypeForSet(Type, Base->getType());
}
@@ -622,7 +638,7 @@ void ELFWriter::computeSymbolTable(
unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
MCSectionELF *SymtabSection =
Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, "");
- SymtabSection->setAlignment(is64Bit() ? 8 : 4);
+ SymtabSection->setAlignment(is64Bit() ? Align(8) : Align(4));
SymbolTableIndex = addToSectionTable(SymtabSection);
align(SymtabSection->getAlignment());
@@ -720,7 +736,7 @@ void ELFWriter::computeSymbolTable(
MCSectionELF *SymtabShndxSection =
Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0, 4, "");
SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection);
- SymtabShndxSection->setAlignment(4);
+ SymtabShndxSection->setAlignment(Align(4));
}
ArrayRef<std::string> FileNames = Asm.getFileNames();
@@ -808,7 +824,7 @@ MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx,
MCSectionELF *RelaSection = Ctx.createELFRelSection(
RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL,
Flags, EntrySize, Sec.getGroup(), &Sec);
- RelaSection->setAlignment(is64Bit() ? 8 : 4);
+ RelaSection->setAlignment(is64Bit() ? Align(8) : Align(4));
return RelaSection;
}
@@ -895,7 +911,7 @@ void ELFWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED);
// Alignment field should reflect the requirements of
// the compressed section header.
- Section.setAlignment(is64Bit() ? 8 : 4);
+ Section.setAlignment(is64Bit() ? Align(8) : Align(4));
} else {
// Add "z" prefix to section name. This is zlib-gnu style.
MC.renameELFSection(&Section, (".z" + SectionName.drop_front(1)).str());
@@ -1119,7 +1135,7 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
if (!GroupIdx) {
MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol);
GroupIdx = addToSectionTable(Group);
- Group->setAlignment(4);
+ Group->setAlignment(Align(4));
Groups.push_back(Group);
}
std::vector<const MCSectionELF *> &Members =
@@ -1437,22 +1453,7 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
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() +
@@ -1468,10 +1469,9 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
return;
}
- uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
- uint64_t K = SymBOffset - FixupOffset;
+ assert(!IsPCRel && "should have been folded");
IsPCRel = true;
- C -= K;
+ C += FixupOffset - Layout.getSymbolOffset(SymB);
}
// We either rejected the fixup or folded B into C at this point.
@@ -1489,38 +1489,35 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
}
}
- 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;
+ unsigned Type = TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel);
+ bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type);
+ uint64_t Addend = 0;
+
+ FixedValue = !RelocateWithSymbol && SymA && !SymA->isUndefined()
+ ? C + Layout.getSymbolOffset(*SymA)
+ : C;
+ if (hasRelocationAddend()) {
+ Addend = FixedValue;
+ FixedValue = 0;
+ }
+
if (!RelocateWithSymbol) {
const auto *SectionSymbol =
SecA ? cast<MCSymbolELF>(SecA->getBeginSymbol()) : nullptr;
if (SectionSymbol)
SectionSymbol->setUsedInReloc();
- ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend, SymA,
- OriginalC);
+ ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend, SymA, C);
Relocations[&FixupSection].push_back(Rec);
return;
}
- const auto *RenamedSymA = SymA;
+ const MCSymbolELF *RenamedSymA = SymA;
if (SymA) {
if (const MCSymbolELF *R = Renames.lookup(SymA))
RenamedSymA = R;
@@ -1530,8 +1527,7 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
else
RenamedSymA->setUsedInReloc();
}
- ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend, SymA,
- OriginalC);
+ ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend, SymA, C);
Relocations[&FixupSection].push_back(Rec);
}
@@ -1551,7 +1547,7 @@ bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
std::unique_ptr<MCObjectWriter>
llvm::createELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS, bool IsLittleEndian) {
- return llvm::make_unique<ELFSingleObjectWriter>(std::move(MOTW), OS,
+ return std::make_unique<ELFSingleObjectWriter>(std::move(MOTW), OS,
IsLittleEndian);
}
@@ -1559,6 +1555,6 @@ 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,
+ return std::make_unique<ELFDwoObjectWriter>(std::move(MOTW), OS, DwoOS,
IsLittleEndian);
}
diff --git a/lib/MC/MCAsmBackend.cpp b/lib/MC/MCAsmBackend.cpp
index 9b1102cbe7d1..b800e9caee22 100644
--- a/lib/MC/MCAsmBackend.cpp
+++ b/lib/MC/MCAsmBackend.cpp
@@ -73,6 +73,7 @@ const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"FK_Data_2", 0, 16, 0},
{"FK_Data_4", 0, 32, 0},
{"FK_Data_8", 0, 64, 0},
+ {"FK_Data_6b", 0, 6, 0},
{"FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel},
{"FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
{"FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
@@ -93,10 +94,12 @@ const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"FK_Data_Add_2", 0, 16, 0},
{"FK_Data_Add_4", 0, 32, 0},
{"FK_Data_Add_8", 0, 64, 0},
+ {"FK_Data_Add_6b", 0, 6, 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}};
+ {"FK_Data_Sub_8", 0, 64, 0},
+ {"FK_Data_Sub_6b", 0, 6, 0}};
assert((size_t)Kind <= array_lengthof(Builtins) && "Unknown fixup kind");
return Builtins[Kind];
diff --git a/lib/MC/MCAsmInfoXCOFF.cpp b/lib/MC/MCAsmInfoXCOFF.cpp
index 74c21f0c9e6d..65fe8848e20f 100644
--- a/lib/MC/MCAsmInfoXCOFF.cpp
+++ b/lib/MC/MCAsmInfoXCOFF.cpp
@@ -15,4 +15,21 @@ void MCAsmInfoXCOFF::anchor() {}
MCAsmInfoXCOFF::MCAsmInfoXCOFF() {
IsLittleEndian = false;
HasDotTypeDotSizeDirective = false;
+ COMMDirectiveAlignmentIsInBytes = false;
+ LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment;
+ UseDotAlignForAlignment = true;
+ AsciiDirective = nullptr; // not supported
+ AscizDirective = nullptr; // not supported
+ NeedsFunctionDescriptors = true;
+ HasDotLGloblDirective = true;
+ Data64bitsDirective = "\t.llong\t";
+ SupportsQuotedNames = false;
+}
+
+bool MCAsmInfoXCOFF::isValidUnquotedName(StringRef Name) const {
+ // FIXME: Remove this function when we stop using "TOC[TC0]" as a symbol name.
+ if (Name.equals("TOC[TC0]"))
+ return true;
+
+ return MCAsmInfo::isValidUnquotedName(Name);
}
diff --git a/lib/MC/MCAsmMacro.cpp b/lib/MC/MCAsmMacro.cpp
index ba4fb7d4f387..186a68b02a29 100644
--- a/lib/MC/MCAsmMacro.cpp
+++ b/lib/MC/MCAsmMacro.cpp
@@ -11,6 +11,7 @@
using namespace llvm;
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void MCAsmMacroParameter::dump(raw_ostream &OS) const {
OS << "\"" << Name << "\"";
if (Required)
@@ -39,3 +40,4 @@ void MCAsmMacro::dump(raw_ostream &OS) const {
}
OS << " (BEGIN BODY)" << Body << "(END BODY)\n";
}
+#endif
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index 7a2b0b8a1220..2d9c2cb21255 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -11,6 +11,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAssembler.h"
@@ -23,6 +24,7 @@
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCRegister.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
@@ -66,7 +68,7 @@ public:
std::unique_ptr<MCAsmBackend> asmbackend, bool showInst)
: MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
MAI(Context.getAsmInfo()), InstPrinter(printer),
- Assembler(llvm::make_unique<MCAssembler>(
+ Assembler(std::make_unique<MCAssembler>(
Context, std::move(asmbackend), std::move(emitter),
(asmbackend) ? asmbackend->createObjectWriter(NullStream)
: nullptr)),
@@ -162,6 +164,8 @@ public:
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
+ void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlign) override;
void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
@@ -254,9 +258,26 @@ public:
unsigned SourceLineNum,
const MCSymbol *FnStartSym,
const MCSymbol *FnEndSym) override;
+
+ void PrintCVDefRangePrefix(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges);
+
+ void EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeRegisterRelHeader DRHdr) override;
+
+ void EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeSubfieldRegisterHeader DRHdr) override;
+
+ void EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeRegisterHeader DRHdr) override;
+
void EmitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
- StringRef FixedSizePortion) override;
+ codeview::DefRangeFramePointerRelHeader DRHdr) override;
+
void EmitCVStringTableDirective() override;
void EmitCVFileChecksumsDirective() override;
void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override;
@@ -291,13 +312,13 @@ public:
void EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) override;
void EmitWinCFIStartChained(SMLoc Loc) override;
void EmitWinCFIEndChained(SMLoc Loc) override;
- void EmitWinCFIPushReg(unsigned Register, SMLoc Loc) override;
- void EmitWinCFISetFrame(unsigned Register, unsigned Offset,
+ void EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) override;
+ void EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
SMLoc Loc) override;
void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;
- void EmitWinCFISaveReg(unsigned Register, unsigned Offset,
+ void EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
SMLoc Loc) override;
- void EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
+ void EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
SMLoc Loc) override;
void EmitWinCFIPushFrame(bool Code, SMLoc Loc) override;
void EmitWinCFIEndProlog(SMLoc Loc) override;
@@ -630,6 +651,7 @@ bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
case MCSA_Global: // .globl/.global
OS << MAI->getGlobalDirective();
break;
+ case MCSA_LGlobal: OS << "\t.lglobl\t"; break;
case MCSA_Hidden: OS << "\t.hidden\t"; break;
case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
case MCSA_Internal: OS << "\t.internal\t"; break;
@@ -740,6 +762,24 @@ void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
EmitEOL();
}
+// We need an XCOFF-specific version of this directive as the AIX syntax
+// requires a QualName argument identifying the csect name and storage mapping
+// class to appear before the alignment if we are specifying it.
+void MCAsmStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) {
+ assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment &&
+ "We only support writing log base-2 alignment format with XCOFF.");
+ assert(isPowerOf2_32(ByteAlignment) && "Alignment must be a power of 2.");
+
+ OS << "\t.lcomm\t";
+ Symbol->print(OS, MAI);
+ OS << ',' << Size;
+ OS << ',' << Symbol->getName();
+ OS << ',' << Log2_32(ByteAlignment);
+
+ EmitEOL();
+}
+
void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
assert(MAI->hasDotTypeDotSizeDirective());
OS << "\t.size\t";
@@ -1082,6 +1122,16 @@ void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
unsigned ValueSize,
unsigned MaxBytesToEmit) {
+ if (MAI->useDotAlignForAlignment()) {
+ if (!isPowerOf2_32(ByteAlignment))
+ report_fatal_error("Only power-of-two alignments are supported "
+ "with .align.");
+ OS << "\t.align\t";
+ OS << Log2_32(ByteAlignment);
+ EmitEOL();
+ return;
+ }
+
// Some assemblers don't support non-power of two alignments, so we always
// emit alignments as a power of two if possible.
if (isPowerOf2_32(ByteAlignment)) {
@@ -1376,9 +1426,8 @@ void MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
}
-void MCAsmStreamer::EmitCVDefRangeDirective(
- ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
- StringRef FixedSizePortion) {
+void MCAsmStreamer::PrintCVDefRangePrefix(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges) {
OS << "\t.cv_def_range\t";
for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
OS << ' ';
@@ -1386,10 +1435,43 @@ void MCAsmStreamer::EmitCVDefRangeDirective(
OS << ' ';
Range.second->print(OS, MAI);
}
- OS << ", ";
- PrintQuotedString(FixedSizePortion, OS);
+}
+
+void MCAsmStreamer::EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeRegisterRelHeader DRHdr) {
+ PrintCVDefRangePrefix(Ranges);
+ OS << ", reg_rel, ";
+ OS << DRHdr.Register << ", " << DRHdr.Flags << ", "
+ << DRHdr.BasePointerOffset;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeSubfieldRegisterHeader DRHdr) {
+ PrintCVDefRangePrefix(Ranges);
+ OS << ", subfield_reg, ";
+ OS << DRHdr.Register << ", " << DRHdr.OffsetInParent;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeRegisterHeader DRHdr) {
+ PrintCVDefRangePrefix(Ranges);
+ OS << ", reg, ";
+ OS << DRHdr.Register;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeFramePointerRelHeader DRHdr) {
+ PrintCVDefRangePrefix(Ranges);
+ OS << ", frame_ptr_rel, ";
+ OS << DRHdr.Offset;
EmitEOL();
- this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
}
void MCAsmStreamer::EmitCVStringTableDirective() {
@@ -1453,9 +1535,8 @@ void MCAsmStreamer::EmitRegisterName(int64_t Register) {
// just ones that map to LLVM register numbers and have known names.
// Fall back to using the original number directly if no name is known.
const MCRegisterInfo *MRI = getContext().getRegisterInfo();
- int LLVMRegister = MRI->getLLVMRegNumFromEH(Register);
- if (LLVMRegister != -1) {
- InstPrinter->printRegName(OS, LLVMRegister);
+ if (Optional<unsigned> LLVMRegister = MRI->getLLVMRegNum(Register, true)) {
+ InstPrinter->printRegName(OS, *LLVMRegister);
return;
}
}
@@ -1668,6 +1749,12 @@ void MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) {
// We only do this so the section switch that terminates the handler
// data block is visible.
WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
+
+ // Do nothing if no frame is open. MCStreamer should've already reported an
+ // error.
+ if (!CurFrame)
+ return;
+
MCSection *TextSec = &CurFrame->Function->getSection();
MCSection *XData = getAssociatedXDataSection(TextSec);
SwitchSectionNoChange(XData);
@@ -1676,18 +1763,21 @@ void MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) {
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register, SMLoc Loc) {
+void MCAsmStreamer::EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
MCStreamer::EmitWinCFIPushReg(Register, Loc);
- OS << "\t.seh_pushreg " << Register;
+ OS << "\t.seh_pushreg ";
+ InstPrinter->printRegName(OS, Register);
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset,
+void MCAsmStreamer::EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
SMLoc Loc) {
MCStreamer::EmitWinCFISetFrame(Register, Offset, Loc);
- OS << "\t.seh_setframe " << Register << ", " << Offset;
+ OS << "\t.seh_setframe ";
+ InstPrinter->printRegName(OS, Register);
+ OS << ", " << Offset;
EmitEOL();
}
@@ -1698,19 +1788,23 @@ void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset,
+void MCAsmStreamer::EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
SMLoc Loc) {
MCStreamer::EmitWinCFISaveReg(Register, Offset, Loc);
- OS << "\t.seh_savereg " << Register << ", " << Offset;
+ OS << "\t.seh_savereg ";
+ InstPrinter->printRegName(OS, Register);
+ OS << ", " << Offset;
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
+void MCAsmStreamer::EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
SMLoc Loc) {
MCStreamer::EmitWinCFISaveXMM(Register, Offset, Loc);
- OS << "\t.seh_savexmm " << Register << ", " << Offset;
+ OS << "\t.seh_savexmm ";
+ InstPrinter->printRegName(OS, Register);
+ OS << ", " << Offset;
EmitEOL();
}
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index c4f4d4c2870e..cf42fe85b8e5 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -30,6 +30,7 @@
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -321,7 +322,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
case MCFragment::FT_Align: {
const MCAlignFragment &AF = cast<MCAlignFragment>(F);
unsigned Offset = Layout.getFragmentOffset(&AF);
- unsigned Size = OffsetToAlignment(Offset, AF.getAlignment());
+ unsigned Size = offsetToAlignment(Offset, Align(AF.getAlignment()));
// Insert extra Nops for code alignment if the target define
// shouldInsertExtraNopBytesForCodeAlign target hook.
@@ -840,6 +841,10 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
getBackend().shouldInsertFixupForCodeAlign(*this, Layout, *AF);
}
continue;
+ } else if (auto *FragWithFixups =
+ dyn_cast<MCDwarfCallFrameFragment>(&Frag)) {
+ Fixups = FragWithFixups->getFixups();
+ Contents = FragWithFixups->getContents();
} else
llvm_unreachable("Unknown fragment with fixups!");
for (const MCFixup &Fixup : Fixups) {
@@ -969,13 +974,9 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout,
MCContext &Context = Layout.getAssembler().getContext();
uint64_t OldSize = DF.getContents().size();
int64_t AddrDelta;
- bool Abs;
- if (getBackend().requiresDiffExpressionRelocations())
- Abs = DF.getAddrDelta().evaluateAsAbsolute(AddrDelta, Layout);
- else {
- Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
- assert(Abs && "We created a line delta with an invalid expression");
- }
+ bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
+ assert(Abs && "We created a line delta with an invalid expression");
+ (void)Abs;
int64_t LineDelta;
LineDelta = DF.getLineDelta();
SmallVectorImpl<char> &Data = DF.getContents();
@@ -983,7 +984,7 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout,
raw_svector_ostream OSE(Data);
DF.getFixups().clear();
- if (Abs) {
+ if (!getBackend().requiresDiffExpressionRelocations()) {
MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
AddrDelta, OSE);
} else {
@@ -1017,10 +1018,25 @@ bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout,
bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
assert(Abs && "We created call frame with an invalid expression");
(void) Abs;
- SmallString<8> &Data = DF.getContents();
+ SmallVectorImpl<char> &Data = DF.getContents();
Data.clear();
raw_svector_ostream OSE(Data);
- MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE);
+ DF.getFixups().clear();
+
+ if (getBackend().requiresDiffExpressionRelocations()) {
+ uint32_t Offset;
+ uint32_t Size;
+ MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE, &Offset,
+ &Size);
+ if (Size) {
+ DF.getFixups().push_back(MCFixup::create(
+ Offset, &DF.getAddrDelta(),
+ MCFixup::getKindForSizeInBits(Size /*In bits.*/, false /*isPCRel*/)));
+ }
+ } else {
+ MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE);
+ }
+
return OldSize != Data.size();
}
diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp
index 0dc2e2d37caf..a69ee19e1a1a 100644
--- a/lib/MC/MCContext.cpp
+++ b/lib/MC/MCContext.cpp
@@ -58,11 +58,12 @@ AsSecureLogFileName("as-secure-log-file-name",
MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri,
const MCObjectFileInfo *mofi, const SourceMgr *mgr,
- bool DoAutoReset)
+ MCTargetOptions const *TargetOpts, bool DoAutoReset)
: SrcMgr(mgr), InlineSrcMgr(nullptr), MAI(mai), MRI(mri), MOFI(mofi),
Symbols(Allocator), UsedNames(Allocator),
+ InlineAsmUsedLabelNames(Allocator),
CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0),
- AutoReset(DoAutoReset) {
+ AutoReset(DoAutoReset), TargetOptions(TargetOpts) {
SecureLogFile = AsSecureLogFileName;
if (SrcMgr && SrcMgr->getNumBuffers())
@@ -90,6 +91,7 @@ void MCContext::reset() {
XCOFFAllocator.DestroyAll();
MCSubtargetAllocator.DestroyAll();
+ InlineAsmUsedLabelNames.clear();
UsedNames.clear();
Symbols.clear();
Allocator.Reset();
@@ -272,6 +274,10 @@ void MCContext::setSymbolValue(MCStreamer &Streamer,
Streamer.EmitAssignment(Symbol, MCConstantExpr::create(Val, *this));
}
+void MCContext::registerInlineAsmLabel(MCSymbol *Sym) {
+ InlineAsmUsedLabelNames[Sym->getName()] = Sym;
+}
+
//===----------------------------------------------------------------------===//
// Section Management
//===----------------------------------------------------------------------===//
@@ -531,6 +537,8 @@ MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind Kind,
MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section,
XCOFF::StorageMappingClass SMC,
+ XCOFF::SymbolType Type,
+ XCOFF::StorageClass SC,
SectionKind Kind,
const char *BeginSymName) {
// Do the lookup. If we have a hit, return it.
@@ -548,7 +556,7 @@ MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section,
Begin = createTempSymbol(BeginSymName, false);
MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate())
- MCSectionXCOFF(CachedName, SMC, Kind, Begin);
+ MCSectionXCOFF(CachedName, SMC, Type, SC, Kind, Begin);
Entry.second = Result;
auto *F = new MCDataFragment();
@@ -690,6 +698,21 @@ void MCContext::reportError(SMLoc Loc, const Twine &Msg) {
report_fatal_error(Msg, false);
}
+void MCContext::reportWarning(SMLoc Loc, const Twine &Msg) {
+ if (TargetOptions && TargetOptions->MCNoWarn)
+ return;
+ if (TargetOptions && TargetOptions->MCFatalWarnings)
+ reportError(Loc, Msg);
+ else {
+ // If we have a source manager use it. Otherwise, try using the inline
+ // source manager.
+ if (SrcMgr)
+ SrcMgr->PrintMessage(Loc, SourceMgr::DK_Warning, Msg);
+ else if (InlineSrcMgr)
+ InlineSrcMgr->PrintMessage(Loc, SourceMgr::DK_Warning, Msg);
+ }
+}
+
void MCContext::reportFatalError(SMLoc Loc, const Twine &Msg) {
reportError(Loc, Msg);
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index aae6fdf90931..bcc7c45afc01 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -544,8 +544,8 @@ Expected<unsigned> MCDwarfLineTable::tryGetFile(StringRef &Directory,
FileNumber);
}
-bool isRootFile(const MCDwarfFile &RootFile, StringRef &Directory,
- StringRef &FileName, Optional<MD5::MD5Result> Checksum) {
+static bool isRootFile(const MCDwarfFile &RootFile, StringRef &Directory,
+ StringRef &FileName, Optional<MD5::MD5Result> Checksum) {
if (RootFile.Name.empty() || RootFile.Name != FileName.data())
return false;
return RootFile.Checksum == Checksum;
@@ -1897,26 +1897,54 @@ void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer,
}
void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context,
- uint64_t AddrDelta,
- raw_ostream &OS) {
+ uint64_t AddrDelta, raw_ostream &OS,
+ uint32_t *Offset, uint32_t *Size) {
// Scale the address delta by the minimum instruction length.
AddrDelta = ScaleAddrDelta(Context, AddrDelta);
+ bool WithFixups = false;
+ if (Offset && Size)
+ WithFixups = true;
+
support::endianness E =
Context.getAsmInfo()->isLittleEndian() ? support::little : support::big;
if (AddrDelta == 0) {
+ if (WithFixups) {
+ *Offset = 0;
+ *Size = 0;
+ }
} else if (isUIntN(6, AddrDelta)) {
uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
- OS << Opcode;
+ if (WithFixups) {
+ *Offset = OS.tell();
+ *Size = 6;
+ OS << uint8_t(dwarf::DW_CFA_advance_loc);
+ } else
+ OS << Opcode;
} else if (isUInt<8>(AddrDelta)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc1);
- OS << uint8_t(AddrDelta);
+ if (WithFixups) {
+ *Offset = OS.tell();
+ *Size = 8;
+ OS.write_zeros(1);
+ } else
+ OS << uint8_t(AddrDelta);
} else if (isUInt<16>(AddrDelta)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc2);
- support::endian::write<uint16_t>(OS, AddrDelta, E);
+ if (WithFixups) {
+ *Offset = OS.tell();
+ *Size = 16;
+ OS.write_zeros(2);
+ } else
+ support::endian::write<uint16_t>(OS, AddrDelta, E);
} else {
assert(isUInt<32>(AddrDelta));
OS << uint8_t(dwarf::DW_CFA_advance_loc4);
- support::endian::write<uint32_t>(OS, AddrDelta, E);
+ if (WithFixups) {
+ *Offset = OS.tell();
+ *Size = 32;
+ OS.write_zeros(4);
+ } else
+ support::endian::write<uint32_t>(OS, AddrDelta, E);
}
}
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp
index 245dd063004f..fa2133078bfe 100644
--- a/lib/MC/MCELFStreamer.cpp
+++ b/lib/MC/MCELFStreamer.cpp
@@ -139,7 +139,7 @@ static void setSectionAlignmentForBundling(const MCAssembler &Assembler,
MCSection *Section) {
if (Section && Assembler.isBundlingEnabled() && Section->hasInstructions() &&
Section->getAlignment() < Assembler.getBundleAlignSize())
- Section->setAlignment(Assembler.getBundleAlignSize());
+ Section->setAlignment(Align(Assembler.getBundleAlignSize()));
}
void MCELFStreamer::ChangeSection(MCSection *Section,
@@ -277,6 +277,9 @@ bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
case MCSA_AltEntry:
llvm_unreachable("ELF doesn't support the .alt_entry attribute");
+
+ case MCSA_LGlobal:
+ llvm_unreachable("ELF doesn't support the .lglobl attribute");
}
return true;
@@ -306,7 +309,7 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
// Update the maximum alignment of the section if necessary.
if (ByteAlignment > Section.getAlignment())
- Section.setAlignment(ByteAlignment);
+ Section.setAlignment(Align(ByteAlignment));
SwitchSection(P.first, P.second);
} else {
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp
index ab53ed42778e..813c00f6f3bb 100644
--- a/lib/MC/MCExpr.cpp
+++ b/lib/MC/MCExpr.cpp
@@ -259,6 +259,8 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_PPC_TOC_LO: return "toc@l";
case VK_PPC_TOC_HI: return "toc@h";
case VK_PPC_TOC_HA: return "toc@ha";
+ case VK_PPC_U: return "u";
+ case VK_PPC_L: return "l";
case VK_PPC_DTPMOD: return "dtpmod";
case VK_PPC_TPREL_LO: return "tprel@l";
case VK_PPC_TPREL_HI: return "tprel@h";
@@ -373,6 +375,8 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("toc@l", VK_PPC_TOC_LO)
.Case("toc@h", VK_PPC_TOC_HI)
.Case("toc@ha", VK_PPC_TOC_HA)
+ .Case("u", VK_PPC_U)
+ .Case("l", VK_PPC_L)
.Case("tls", VK_PPC_TLS)
.Case("dtpmod", VK_PPC_DTPMOD)
.Case("tprel@l", VK_PPC_TPREL_LO)
@@ -453,26 +457,28 @@ void MCTargetExpr::anchor() {}
/* *** */
bool MCExpr::evaluateAsAbsolute(int64_t &Res) const {
- return evaluateAsAbsolute(Res, nullptr, nullptr, nullptr);
+ return evaluateAsAbsolute(Res, nullptr, nullptr, nullptr, false);
}
bool MCExpr::evaluateAsAbsolute(int64_t &Res,
const MCAsmLayout &Layout) const {
- return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr);
+ return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, false);
}
bool MCExpr::evaluateAsAbsolute(int64_t &Res,
const MCAsmLayout &Layout,
const SectionAddrMap &Addrs) const {
- return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs);
+ // Setting InSet causes us to absolutize differences across sections and that
+ // is what the MachO writer uses Addrs for.
+ return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs, true);
}
bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {
- return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr);
+ return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr, false);
}
bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const {
- return evaluateAsAbsolute(Res, Asm, nullptr, nullptr);
+ return evaluateAsAbsolute(Res, Asm, nullptr, nullptr, false);
}
bool MCExpr::evaluateKnownAbsolute(int64_t &Res,
@@ -483,15 +489,6 @@ bool MCExpr::evaluateKnownAbsolute(int64_t &Res,
bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout,
- const SectionAddrMap *Addrs) const {
- // FIXME: The use if InSet = Addrs is a hack. Setting InSet causes us
- // absolutize differences across sections and that is what the MachO writer
- // uses Addrs for.
- return evaluateAsAbsolute(Res, Asm, Layout, Addrs, Addrs);
-}
-
-bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
- const MCAsmLayout *Layout,
const SectionAddrMap *Addrs, bool InSet) const {
MCValue Value;
@@ -577,6 +574,24 @@ static void AttemptToFoldSymbolOffsetDifference(
A = B = nullptr;
}
+static bool canFold(const MCAssembler *Asm, const MCSymbolRefExpr *A,
+ const MCSymbolRefExpr *B, bool InSet) {
+ if (InSet)
+ return true;
+
+ if (!Asm->getBackend().requiresDiffExpressionRelocations())
+ return true;
+
+ const MCSymbol &CheckSym = A ? A->getSymbol() : B->getSymbol();
+ if (!CheckSym.isInSection())
+ return true;
+
+ if (!CheckSym.getSection().hasInstructions())
+ return true;
+
+ return false;
+}
+
/// Evaluate the result of an add between (conceptually) two MCValues.
///
/// This routine conceptually attempts to construct an MCValue:
@@ -617,8 +632,7 @@ EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout,
// 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())) {
+ if (Asm && canFold(Asm, LHS_A, LHS_B, InSet)) {
// 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).
diff --git a/lib/MC/MCInstPrinter.cpp b/lib/MC/MCInstPrinter.cpp
index 159f4070fe9f..c5c06f323e68 100644
--- a/lib/MC/MCInstPrinter.cpp
+++ b/lib/MC/MCInstPrinter.cpp
@@ -64,12 +64,6 @@ StringRef MCInstPrinter::markup(StringRef s) const {
else
return "";
}
-StringRef MCInstPrinter::markup(StringRef a, StringRef b) const {
- if (getUseMarkup())
- return a;
- else
- return b;
-}
// For asm-style hex (e.g. 0ffh) the first digit always has to be a number.
static bool needsLeadingZero(uint64_t Value)
@@ -89,24 +83,25 @@ format_object<int64_t> MCInstPrinter::formatDec(int64_t Value) const {
}
format_object<int64_t> MCInstPrinter::formatHex(int64_t Value) const {
- switch(PrintHexStyle) {
+ switch (PrintHexStyle) {
case HexStyle::C:
- if (Value < 0)
+ if (Value < 0) {
+ if (Value == std::numeric_limits<int64_t>::min())
+ return format<int64_t>("-0x8000000000000000", Value);
return format("-0x%" PRIx64, -Value);
- else
- return format("0x%" PRIx64, Value);
+ }
+ return format("0x%" PRIx64, Value);
case HexStyle::Asm:
if (Value < 0) {
- if (needsLeadingZero((uint64_t)(-Value)))
+ if (Value == std::numeric_limits<int64_t>::min())
+ return format<int64_t>("-8000000000000000h", Value);
+ if (needsLeadingZero(-(uint64_t)(Value)))
return format("-0%" PRIx64 "h", -Value);
- else
- return format("-%" PRIx64 "h", -Value);
- } else {
- if (needsLeadingZero((uint64_t)(Value)))
- return format("0%" PRIx64 "h", Value);
- else
- return format("%" PRIx64 "h", Value);
+ return format("-%" PRIx64 "h", -Value);
}
+ if (needsLeadingZero((uint64_t)(Value)))
+ return format("0%" PRIx64 "h", Value);
+ return format("%" PRIx64 "h", Value);
}
llvm_unreachable("unsupported print style");
}
diff --git a/lib/MC/MCInstrAnalysis.cpp b/lib/MC/MCInstrAnalysis.cpp
index eca87f940bf5..54741fdd686d 100644
--- a/lib/MC/MCInstrAnalysis.cpp
+++ b/lib/MC/MCInstrAnalysis.cpp
@@ -33,3 +33,9 @@ bool MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr,
Target = Addr+Size+Imm;
return true;
}
+
+Optional<uint64_t>
+MCInstrAnalysis::evaluateMemoryOperandAddress(const MCInst &Inst, uint64_t Addr,
+ uint64_t Size) const {
+ return None;
+}
diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp
index 613f255a4ea4..8e558a36b7a1 100644
--- a/lib/MC/MCMachOStreamer.cpp
+++ b/lib/MC/MCMachOStreamer.cpp
@@ -330,6 +330,7 @@ bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Sym,
case MCSA_Protected:
case MCSA_Weak:
case MCSA_Local:
+ case MCSA_LGlobal:
return false;
case MCSA_Global:
diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp
index 9f555abe1404..70c0409ece7a 100644
--- a/lib/MC/MCObjectFileInfo.cpp
+++ b/lib/MC/MCObjectFileInfo.cpp
@@ -28,7 +28,7 @@ static bool useCompactUnwind(const Triple &T) {
return false;
// aarch64 always has it.
- if (T.getArch() == Triple::aarch64)
+ if (T.getArch() == Triple::aarch64 || T.getArch() == Triple::aarch64_32)
return true;
// armv7k always has it.
@@ -57,7 +57,8 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
MachO::S_ATTR_STRIP_STATIC_SYMS | MachO::S_ATTR_LIVE_SUPPORT,
SectionKind::getReadOnly());
- if (T.isOSDarwin() && T.getArch() == Triple::aarch64)
+ if (T.isOSDarwin() &&
+ (T.getArch() == Triple::aarch64 || T.getArch() == Triple::aarch64_32))
SupportsCompactUnwindWithoutEHFrame = true;
if (T.isWatchABI())
@@ -193,7 +194,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86)
CompactUnwindDwarfEHFrameOnly = 0x04000000; // UNWIND_X86_64_MODE_DWARF
- else if (T.getArch() == Triple::aarch64)
+ else if (T.getArch() == Triple::aarch64 || T.getArch() == Triple::aarch64_32)
CompactUnwindDwarfEHFrameOnly = 0x03000000; // UNWIND_ARM64_MODE_DWARF
else if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
CompactUnwindDwarfEHFrameOnly = 0x04000000; // UNWIND_ARM_MODE_DWARF
@@ -768,7 +769,12 @@ void MCObjectFileInfo::initXCOFFMCObjectFileInfo(const Triple &T) {
// the ABI or object file format. For example, the XL compiler uses an unnamed
// csect for program code.
TextSection = Ctx->getXCOFFSection(
- ".text", XCOFF::StorageMappingClass::XMC_PR, SectionKind::getText());
+ ".text", XCOFF::StorageMappingClass::XMC_PR, XCOFF::XTY_SD,
+ XCOFF::C_HIDEXT, SectionKind::getText());
+
+ DataSection = Ctx->getXCOFFSection(
+ ".data", XCOFF::StorageMappingClass::XMC_RW, XCOFF::XTY_SD,
+ XCOFF::C_HIDEXT, SectionKind::getData());
}
void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC,
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index 1587d8498666..83f6ab8fe332 100644
--- a/lib/MC/MCObjectStreamer.cpp
+++ b/lib/MC/MCObjectStreamer.cpp
@@ -27,7 +27,7 @@ MCObjectStreamer::MCObjectStreamer(MCContext &Context,
std::unique_ptr<MCObjectWriter> OW,
std::unique_ptr<MCCodeEmitter> Emitter)
: MCStreamer(Context),
- Assembler(llvm::make_unique<MCAssembler>(
+ Assembler(std::make_unique<MCAssembler>(
Context, std::move(TAB), std::move(Emitter), std::move(OW))),
EmitEHFrame(true), EmitDebugFrame(false) {}
@@ -539,7 +539,7 @@ void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment,
// Update the maximum alignment on the current section if necessary.
MCSection *CurSec = getCurrentSectionOnly();
if (ByteAlignment > CurSec->getAlignment())
- CurSec->setAlignment(ByteAlignment);
+ CurSec->setAlignment(Align(ByteAlignment));
}
void MCObjectStreamer::EmitCodeAlignment(unsigned ByteAlignment,
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 084f6a7a2e14..b59ac08ad6cc 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -22,6 +22,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeView.h"
#include "llvm/MC/MCContext.h"
@@ -524,6 +525,19 @@ private:
/// directives parsed by this class.
StringMap<DirectiveKind> DirectiveKindMap;
+ // Codeview def_range type parsing.
+ enum CVDefRangeType {
+ CVDR_DEFRANGE = 0, // Placeholder
+ CVDR_DEFRANGE_REGISTER,
+ CVDR_DEFRANGE_FRAMEPOINTER_REL,
+ CVDR_DEFRANGE_SUBFIELD_REGISTER,
+ CVDR_DEFRANGE_REGISTER_REL
+ };
+
+ /// Maps Codeview def_range types --> CVDefRangeType enum, for
+ /// Codeview def_range types parsed by this class.
+ StringMap<CVDefRangeType> CVDefRangeTypeMap;
+
// ".ascii", ".asciz", ".string"
bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
@@ -671,6 +685,7 @@ private:
bool parseDirectiveAddrsigSym();
void initializeDirectiveKindMap();
+ void initializeCVDefRangeTypeMap();
};
} // end anonymous namespace
@@ -714,12 +729,14 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
PlatformParser.reset(createWasmAsmParser());
break;
case MCObjectFileInfo::IsXCOFF:
- // TODO: Need to implement createXCOFFAsmParser for XCOFF format.
+ report_fatal_error(
+ "Need to implement createXCOFFAsmParser for XCOFF format.");
break;
}
PlatformParser->Initialize(*this);
initializeDirectiveKindMap();
+ initializeCVDefRangeTypeMap();
NumOfMacroInstantiations = 0;
}
@@ -1142,7 +1159,9 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
}
}
- MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
+ MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
+ if (!Sym)
+ Sym = getContext().getOrCreateSymbol(SymbolName);
// If this is an absolute variable reference, substitute it now to preserve
// semantics in the face of reassignment.
@@ -1737,6 +1756,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
StringMap<DirectiveKind>::const_iterator DirKindIt =
DirectiveKindMap.find(IDVal);
DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
+
? DK_NO_DIRECTIVE
: DirKindIt->getValue();
switch (DirKind) {
@@ -2895,11 +2915,27 @@ bool AsmParser::parseEscapedString(std::string &Data) {
}
// Recognize escaped characters. Note that this escape semantics currently
- // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes.
+ // loosely follows Darwin 'as'.
++i;
if (i == e)
return TokError("unexpected backslash at end of string");
+ // Recognize hex sequences similarly to GNU 'as'.
+ if (Str[i] == 'x' || Str[i] == 'X') {
+ size_t length = Str.size();
+ if (i + 1 >= length || !isHexDigit(Str[i + 1]))
+ return TokError("invalid hexadecimal escape sequence");
+
+ // Consume hex characters. GNU 'as' reads all hexadecimal characters and
+ // then truncates to the lower 16 bits. Seems reasonable.
+ unsigned Value = 0;
+ while (i + 1 < length && isHexDigit(Str[i + 1]))
+ Value = Value * 16 + hexDigitValue(Str[++i]);
+
+ Data += (unsigned char)(Value & 0xFF);
+ continue;
+ }
+
// Recognize octal sequences.
if ((unsigned)(Str[i] - '0') <= 7) {
// Consume up to three octal characters.
@@ -3825,6 +3861,13 @@ bool AsmParser::parseDirectiveCVInlineLinetable() {
return false;
}
+void AsmParser::initializeCVDefRangeTypeMap() {
+ CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
+ CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
+ CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
+ CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
+}
+
/// parseDirectiveCVDefRange
/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
bool AsmParser::parseDirectiveCVDefRange() {
@@ -3846,13 +3889,92 @@ bool AsmParser::parseDirectiveCVDefRange() {
Ranges.push_back({GapStartSym, GapEndSym});
}
- std::string FixedSizePortion;
- if (parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseEscapedString(FixedSizePortion))
- return true;
-
- getStreamer().EmitCVDefRangeDirective(Ranges, FixedSizePortion);
- return false;
+ StringRef CVDefRangeTypeStr;
+ if (parseToken(
+ AsmToken::Comma,
+ "expected comma before def_range type in .cv_def_range directive") ||
+ parseIdentifier(CVDefRangeTypeStr))
+ return Error(Loc, "expected def_range type in directive");
+
+ StringMap<CVDefRangeType>::const_iterator CVTypeIt =
+ CVDefRangeTypeMap.find(CVDefRangeTypeStr);
+ CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
+ ? CVDR_DEFRANGE
+ : CVTypeIt->getValue();
+ switch (CVDRType) {
+ case CVDR_DEFRANGE_REGISTER: {
+ int64_t DRRegister;
+ if (parseToken(AsmToken::Comma, "expected comma before register number in "
+ ".cv_def_range directive") ||
+ parseAbsoluteExpression(DRRegister))
+ return Error(Loc, "expected register number");
+
+ codeview::DefRangeRegisterHeader DRHdr;
+ DRHdr.Register = DRRegister;
+ DRHdr.MayHaveNoName = 0;
+ getStreamer().EmitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
+ int64_t DROffset;
+ if (parseToken(AsmToken::Comma,
+ "expected comma before offset in .cv_def_range directive") ||
+ parseAbsoluteExpression(DROffset))
+ return Error(Loc, "expected offset value");
+
+ codeview::DefRangeFramePointerRelHeader DRHdr;
+ DRHdr.Offset = DROffset;
+ getStreamer().EmitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
+ int64_t DRRegister;
+ int64_t DROffsetInParent;
+ if (parseToken(AsmToken::Comma, "expected comma before register number in "
+ ".cv_def_range directive") ||
+ parseAbsoluteExpression(DRRegister))
+ return Error(Loc, "expected register number");
+ if (parseToken(AsmToken::Comma,
+ "expected comma before offset in .cv_def_range directive") ||
+ parseAbsoluteExpression(DROffsetInParent))
+ return Error(Loc, "expected offset value");
+
+ codeview::DefRangeSubfieldRegisterHeader DRHdr;
+ DRHdr.Register = DRRegister;
+ DRHdr.MayHaveNoName = 0;
+ DRHdr.OffsetInParent = DROffsetInParent;
+ getStreamer().EmitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ case CVDR_DEFRANGE_REGISTER_REL: {
+ int64_t DRRegister;
+ int64_t DRFlags;
+ int64_t DRBasePointerOffset;
+ if (parseToken(AsmToken::Comma, "expected comma before register number in "
+ ".cv_def_range directive") ||
+ parseAbsoluteExpression(DRRegister))
+ return Error(Loc, "expected register value");
+ if (parseToken(
+ AsmToken::Comma,
+ "expected comma before flag value in .cv_def_range directive") ||
+ parseAbsoluteExpression(DRFlags))
+ return Error(Loc, "expected flag value");
+ if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
+ "in .cv_def_range directive") ||
+ parseAbsoluteExpression(DRBasePointerOffset))
+ return Error(Loc, "expected base pointer offset value");
+
+ codeview::DefRangeRegisterRelHeader DRHdr;
+ DRHdr.Register = DRRegister;
+ DRHdr.Flags = DRFlags;
+ DRHdr.BasePointerOffset = DRBasePointerOffset;
+ getStreamer().EmitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ default:
+ return Error(Loc, "unexpected def_range type in .cv_def_range directive");
+ }
+ return true;
}
/// parseDirectiveCVString
diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp
index 1217ea99e465..06f8310ae061 100644
--- a/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/lib/MC/MCParser/COFFAsmParser.cpp
@@ -69,6 +69,7 @@ class COFFAsmParser : public MCAsmParserExtension {
addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
// Win64 EH directives.
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
@@ -83,21 +84,10 @@ class COFFAsmParser : public MCAsmParserExtension {
".seh_handler");
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
".seh_handlerdata");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
- ".seh_pushreg");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
- ".seh_setframe");
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
".seh_stackalloc");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
- ".seh_savereg");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
- ".seh_savexmm");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
- ".seh_pushframe");
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
".seh_endprologue");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
}
bool ParseSectionDirectiveText(StringRef, SMLoc) {
@@ -143,12 +133,7 @@ class COFFAsmParser : public MCAsmParserExtension {
bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
bool ParseSEHDirectiveHandler(StringRef, SMLoc);
bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
- bool ParseSEHDirectivePushReg(StringRef, SMLoc);
- bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
- bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
- bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
- bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
@@ -682,39 +667,6 @@ bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
return false;
}
-bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc Loc) {
- unsigned Reg = 0;
- if (ParseSEHRegisterNumber(Reg))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- getStreamer().EmitWinCFIPushReg(Reg, Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc Loc) {
- unsigned Reg = 0;
- int64_t Off;
- if (ParseSEHRegisterNumber(Reg))
- return true;
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("you must specify a stack pointer offset");
-
- Lex();
- if (getParser().parseAbsoluteExpression(Off))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- getStreamer().EmitWinCFISetFrame(Reg, Off, Loc);
- return false;
-}
-
bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
int64_t Size;
if (getParser().parseAbsoluteExpression(Size))
@@ -728,71 +680,6 @@ bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
return false;
}
-bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc Loc) {
- unsigned Reg = 0;
- int64_t Off;
- if (ParseSEHRegisterNumber(Reg))
- return true;
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("you must specify an offset on the stack");
-
- Lex();
- if (getParser().parseAbsoluteExpression(Off))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- // FIXME: Err on %xmm* registers
- getStreamer().EmitWinCFISaveReg(Reg, Off, Loc);
- return false;
-}
-
-// FIXME: This method is inherently x86-specific. It should really be in the
-// x86 backend.
-bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc Loc) {
- unsigned Reg = 0;
- int64_t Off;
- if (ParseSEHRegisterNumber(Reg))
- return true;
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("you must specify an offset on the stack");
-
- Lex();
- if (getParser().parseAbsoluteExpression(Off))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- // FIXME: Err on non-%xmm* registers
- getStreamer().EmitWinCFISaveXMM(Reg, Off, Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc Loc) {
- bool Code = false;
- StringRef CodeID;
- if (getLexer().is(AsmToken::At)) {
- SMLoc startLoc = getLexer().getLoc();
- Lex();
- if (!getParser().parseIdentifier(CodeID)) {
- if (CodeID != "code")
- return Error(startLoc, "expected @code");
- Code = true;
- }
- }
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- getStreamer().EmitWinCFIPushFrame(Code, Loc);
- return false;
-}
-
bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
Lex();
getStreamer().EmitWinCFIEndProlog(Loc);
@@ -816,46 +703,6 @@ bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
return false;
}
-bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
- SMLoc startLoc = getLexer().getLoc();
- if (getLexer().is(AsmToken::Percent)) {
- const MCRegisterInfo *MRI = getContext().getRegisterInfo();
- SMLoc endLoc;
- unsigned LLVMRegNo;
- if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
- return true;
-
-#if 0
- // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
- // violation so this validation code is disabled.
-
- // Check that this is a non-volatile register.
- const unsigned *NVRegs = TAI.getCalleeSavedRegs();
- unsigned i;
- for (i = 0; NVRegs[i] != 0; ++i)
- if (NVRegs[i] == LLVMRegNo)
- break;
- if (NVRegs[i] == 0)
- return Error(startLoc, "expected non-volatile register");
-#endif
-
- int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
- if (SEHRegNo < 0)
- return Error(startLoc,"register can't be represented in SEH unwind info");
- RegNo = SEHRegNo;
- }
- else {
- int64_t n;
- if (getParser().parseAbsoluteExpression(n))
- return true;
- if (n > 15)
- return Error(startLoc, "register number is too high");
- RegNo = n;
- }
-
- return false;
-}
-
namespace llvm {
MCAsmParserExtension *createCOFFAsmParser() {
diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp
index 1160934dc62c..bd66e5f39c0d 100644
--- a/lib/MC/MCParser/DarwinAsmParser.cpp
+++ b/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -778,8 +778,8 @@ bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) {
raw_fd_ostream *OS = getContext().getSecureLog();
if (!OS) {
std::error_code EC;
- auto NewOS = llvm::make_unique<raw_fd_ostream>(
- StringRef(SecureLogFile), EC, sys::fs::F_Append | sys::fs::F_Text);
+ auto NewOS = std::make_unique<raw_fd_ostream>(
+ StringRef(SecureLogFile), EC, sys::fs::OF_Append | sys::fs::OF_Text);
if (EC)
return Error(IDLoc, Twine("can't open secure log file: ") +
SecureLogFile + " (" + EC.message() + ")");
diff --git a/lib/MC/MCParser/WasmAsmParser.cpp b/lib/MC/MCParser/WasmAsmParser.cpp
index 28d4459fecd4..0c242aed706d 100644
--- a/lib/MC/MCParser/WasmAsmParser.cpp
+++ b/lib/MC/MCParser/WasmAsmParser.cpp
@@ -123,6 +123,7 @@ public:
// See use of .init_array in WasmObjectWriter and
// TargetLoweringObjectFileWasm
.StartsWith(".init_array", SectionKind::getData())
+ .StartsWith(".debug_", SectionKind::getMetadata())
.Default(Optional<SectionKind>());
if (!Kind.hasValue())
return Parser->Error(Lexer->getLoc(), "unknown section kind: " + Name);
diff --git a/lib/MC/MCRegisterInfo.cpp b/lib/MC/MCRegisterInfo.cpp
index 4273b876b7bb..d491c0eb7e06 100644
--- a/lib/MC/MCRegisterInfo.cpp
+++ b/lib/MC/MCRegisterInfo.cpp
@@ -20,15 +20,16 @@
using namespace llvm;
-unsigned MCRegisterInfo::getMatchingSuperReg(unsigned Reg, unsigned SubIdx,
- const MCRegisterClass *RC) const {
+MCRegister
+MCRegisterInfo::getMatchingSuperReg(MCRegister Reg, unsigned SubIdx,
+ const MCRegisterClass *RC) const {
for (MCSuperRegIterator Supers(Reg, this); Supers.isValid(); ++Supers)
if (RC->contains(*Supers) && Reg == getSubReg(*Supers, SubIdx))
return *Supers;
return 0;
}
-unsigned MCRegisterInfo::getSubReg(unsigned Reg, unsigned Idx) const {
+MCRegister MCRegisterInfo::getSubReg(MCRegister Reg, unsigned Idx) const {
assert(Idx && Idx < getNumSubRegIndices() &&
"This is not a subregister index");
// Get a pointer to the corresponding SubRegIndices list. This list has the
@@ -40,7 +41,8 @@ unsigned MCRegisterInfo::getSubReg(unsigned Reg, unsigned Idx) const {
return 0;
}
-unsigned MCRegisterInfo::getSubRegIndex(unsigned Reg, unsigned SubReg) const {
+unsigned MCRegisterInfo::getSubRegIndex(MCRegister Reg,
+ MCRegister SubReg) const {
assert(SubReg && SubReg < getNumRegs() && "This is not a register");
// Get a pointer to the corresponding SubRegIndices list. This list has the
// name of each sub-register in the same order as MCSubRegIterator.
@@ -63,7 +65,7 @@ unsigned MCRegisterInfo::getSubRegIdxOffset(unsigned Idx) const {
return SubRegIdxRanges[Idx].Offset;
}
-int MCRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
+int MCRegisterInfo::getDwarfRegNum(MCRegister RegNum, bool isEH) const {
const DwarfLLVMRegPair *M = isEH ? EHL2DwarfRegs : L2DwarfRegs;
unsigned Size = isEH ? EHL2DwarfRegsSize : L2DwarfRegsSize;
@@ -76,29 +78,18 @@ int MCRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
return I->ToReg;
}
-int MCRegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const {
+Optional<unsigned> MCRegisterInfo::getLLVMRegNum(unsigned RegNum,
+ bool isEH) const {
const DwarfLLVMRegPair *M = isEH ? EHDwarf2LRegs : Dwarf2LRegs;
unsigned Size = isEH ? EHDwarf2LRegsSize : Dwarf2LRegsSize;
if (!M)
- return -1;
- DwarfLLVMRegPair Key = { RegNum, 0 };
- const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key);
- assert(I != M+Size && I->FromReg == RegNum && "Invalid RegNum");
- return I->ToReg;
-}
-
-int MCRegisterInfo::getLLVMRegNumFromEH(unsigned RegNum) const {
- const DwarfLLVMRegPair *M = EHDwarf2LRegs;
- unsigned Size = EHDwarf2LRegsSize;
-
- if (!M)
- return -1;
+ return None;
DwarfLLVMRegPair Key = { RegNum, 0 };
const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key);
- if (I == M+Size || I->FromReg != RegNum)
- return -1;
- return I->ToReg;
+ if (I != M + Size && I->FromReg == RegNum)
+ return I->ToReg;
+ return None;
}
int MCRegisterInfo::getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const {
@@ -110,22 +101,21 @@ int MCRegisterInfo::getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const {
// a corresponding LLVM register number at all. So if we can't map the
// EH register number to an LLVM register number, assume it's just a
// valid DWARF register number as is.
- int LRegNum = getLLVMRegNumFromEH(RegNum);
- if (LRegNum != -1)
- return getDwarfRegNum(LRegNum, false);
+ if (Optional<unsigned> LRegNum = getLLVMRegNum(RegNum, true))
+ return getDwarfRegNum(*LRegNum, false);
return RegNum;
}
-int MCRegisterInfo::getSEHRegNum(unsigned RegNum) const {
- const DenseMap<unsigned, int>::const_iterator I = L2SEHRegs.find(RegNum);
+int MCRegisterInfo::getSEHRegNum(MCRegister RegNum) const {
+ const DenseMap<MCRegister, int>::const_iterator I = L2SEHRegs.find(RegNum);
if (I == L2SEHRegs.end()) return (int)RegNum;
return I->second;
}
-int MCRegisterInfo::getCodeViewRegNum(unsigned RegNum) const {
+int MCRegisterInfo::getCodeViewRegNum(MCRegister RegNum) const {
if (L2CVRegs.empty())
report_fatal_error("target does not implement codeview register mapping");
- const DenseMap<unsigned, int>::const_iterator I = L2CVRegs.find(RegNum);
+ const DenseMap<MCRegister, int>::const_iterator I = L2CVRegs.find(RegNum);
if (I == L2CVRegs.end())
report_fatal_error("unknown codeview register " + (RegNum < getNumRegs()
? getName(RegNum)
diff --git a/lib/MC/MCSectionXCOFF.cpp b/lib/MC/MCSectionXCOFF.cpp
index d1a637345024..d52959f15f92 100644
--- a/lib/MC/MCSectionXCOFF.cpp
+++ b/lib/MC/MCSectionXCOFF.cpp
@@ -15,19 +15,65 @@ using namespace llvm;
MCSectionXCOFF::~MCSectionXCOFF() = default;
+static StringRef getMappingClassString(XCOFF::StorageMappingClass SMC) {
+ switch (SMC) {
+ case XCOFF::XMC_DS:
+ return "DS";
+ case XCOFF::XMC_RW:
+ return "RW";
+ case XCOFF::XMC_PR:
+ return "PR";
+ default:
+ report_fatal_error("Unhandled storage-mapping class.");
+ }
+}
+
void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
raw_ostream &OS,
const MCExpr *Subsection) const {
if (getKind().isText()) {
+ if (getMappingClass() != XCOFF::XMC_PR)
+ report_fatal_error("Unhandled storage-mapping class for .text csect");
+
OS << "\t.csect " << getSectionName() << "["
- << "PR"
+ << getMappingClassString(getMappingClass())
<< "]" << '\n';
return;
}
+ if (getKind().isData()) {
+ switch (getMappingClass()) {
+ case XCOFF::XMC_RW:
+ case XCOFF::XMC_DS:
+ OS << "\t.csect " << getSectionName() << "["
+ << getMappingClassString(getMappingClass()) << "]" << '\n';
+ break;
+ case XCOFF::XMC_TC0:
+ OS << "\t.toc\n";
+ break;
+ default:
+ report_fatal_error(
+ "Unhandled storage-mapping class for .data csect.");
+ }
+ return;
+ }
+
+ if (getKind().isBSSLocal() || getKind().isCommon()) {
+ assert((getMappingClass() == XCOFF::XMC_RW ||
+ getMappingClass() == XCOFF::XMC_BS) &&
+ "Generated a storage-mapping class for a common/bss csect we don't "
+ "understand how to switch to.");
+ assert(getCSectType() == XCOFF::XTY_CM &&
+ "wrong csect type for .bss csect");
+ // Don't have to print a directive for switching to section for commons.
+ // '.comm' and '.lcomm' directives for the variable will create the needed
+ // csect.
+ return;
+ }
+
report_fatal_error("Printing for this SectionKind is unimplemented.");
}
bool MCSectionXCOFF::UseCodeAlign() const { return getKind().isText(); }
-bool MCSectionXCOFF::isVirtualSection() const { return !getKind().isCommon(); }
+bool MCSectionXCOFF::isVirtualSection() const { return XCOFF::XTY_CM == Type; }
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index decbb96817e3..b8278cb11079 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/lib/MC/MCStreamer.cpp
@@ -12,6 +12,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeView.h"
@@ -21,6 +22,8 @@
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCRegister.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSymbol.h"
@@ -327,10 +330,56 @@ void MCStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
const MCSymbol *FnStartSym,
const MCSymbol *FnEndSym) {}
+/// Only call this on endian-specific types like ulittle16_t and little32_t, or
+/// structs composed of them.
+template <typename T>
+static void copyBytesForDefRange(SmallString<20> &BytePrefix,
+ codeview::SymbolKind SymKind,
+ const T &DefRangeHeader) {
+ BytePrefix.resize(2 + sizeof(T));
+ codeview::ulittle16_t SymKindLE = codeview::ulittle16_t(SymKind);
+ memcpy(&BytePrefix[0], &SymKindLE, 2);
+ memcpy(&BytePrefix[2], &DefRangeHeader, sizeof(T));
+}
+
void MCStreamer::EmitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
StringRef FixedSizePortion) {}
+void MCStreamer::EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeRegisterRelHeader DRHdr) {
+ SmallString<20> BytePrefix;
+ copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_REGISTER_REL, DRHdr);
+ EmitCVDefRangeDirective(Ranges, BytePrefix);
+}
+
+void MCStreamer::EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeSubfieldRegisterHeader DRHdr) {
+ SmallString<20> BytePrefix;
+ copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_SUBFIELD_REGISTER,
+ DRHdr);
+ EmitCVDefRangeDirective(Ranges, BytePrefix);
+}
+
+void MCStreamer::EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeRegisterHeader DRHdr) {
+ SmallString<20> BytePrefix;
+ copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_REGISTER, DRHdr);
+ EmitCVDefRangeDirective(Ranges, BytePrefix);
+}
+
+void MCStreamer::EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeFramePointerRelHeader DRHdr) {
+ SmallString<20> BytePrefix;
+ copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_FRAMEPOINTER_REL,
+ DRHdr);
+ EmitCVDefRangeDirective(Ranges, BytePrefix);
+}
+
void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
MCSymbol *EHSymbol) {
}
@@ -631,7 +680,7 @@ void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
MCSymbol *StartProc = EmitCFILabel();
WinFrameInfos.emplace_back(
- llvm::make_unique<WinEH::FrameInfo>(Symbol, StartProc));
+ std::make_unique<WinEH::FrameInfo>(Symbol, StartProc));
CurrentWinFrameInfo = WinFrameInfos.back().get();
CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
}
@@ -665,7 +714,7 @@ void MCStreamer::EmitWinCFIStartChained(SMLoc Loc) {
MCSymbol *StartProc = EmitCFILabel();
- WinFrameInfos.emplace_back(llvm::make_unique<WinEH::FrameInfo>(
+ WinFrameInfos.emplace_back(std::make_unique<WinEH::FrameInfo>(
CurFrame->Function, StartProc, CurFrame));
CurrentWinFrameInfo = WinFrameInfos.back().get();
CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
@@ -763,18 +812,23 @@ MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) {
void MCStreamer::EmitSyntaxDirective() {}
-void MCStreamer::EmitWinCFIPushReg(unsigned Register, SMLoc Loc) {
+static unsigned encodeSEHRegNum(MCContext &Ctx, MCRegister Reg) {
+ return Ctx.getRegisterInfo()->getSEHRegNum(Reg);
+}
+
+void MCStreamer::EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
if (!CurFrame)
return;
MCSymbol *Label = EmitCFILabel();
- WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(Label, Register);
+ WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(
+ Label, encodeSEHRegNum(Context, Register));
CurFrame->Instructions.push_back(Inst);
}
-void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset,
+void MCStreamer::EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
SMLoc Loc) {
WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
if (!CurFrame)
@@ -790,8 +844,8 @@ void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset,
MCSymbol *Label = EmitCFILabel();
- WinEH::Instruction Inst =
- Win64EH::Instruction::SetFPReg(Label, Register, Offset);
+ WinEH::Instruction Inst = Win64EH::Instruction::SetFPReg(
+ Label, encodeSEHRegNum(getContext(), Register), Offset);
CurFrame->LastFrameInst = CurFrame->Instructions.size();
CurFrame->Instructions.push_back(Inst);
}
@@ -813,7 +867,7 @@ void MCStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
CurFrame->Instructions.push_back(Inst);
}
-void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset,
+void MCStreamer::EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
SMLoc Loc) {
WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
if (!CurFrame)
@@ -825,12 +879,12 @@ void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset,
MCSymbol *Label = EmitCFILabel();
- WinEH::Instruction Inst =
- Win64EH::Instruction::SaveNonVol(Label, Register, Offset);
+ WinEH::Instruction Inst = Win64EH::Instruction::SaveNonVol(
+ Label, encodeSEHRegNum(Context, Register), Offset);
CurFrame->Instructions.push_back(Inst);
}
-void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
+void MCStreamer::EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
SMLoc Loc) {
WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
if (!CurFrame)
@@ -840,8 +894,8 @@ void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
MCSymbol *Label = EmitCFILabel();
- WinEH::Instruction Inst =
- Win64EH::Instruction::SaveXMM(Label, Register, Offset);
+ WinEH::Instruction Inst = Win64EH::Instruction::SaveXMM(
+ Label, encodeSEHRegNum(Context, Register), Offset);
CurFrame->Instructions.push_back(Inst);
}
@@ -1009,6 +1063,10 @@ void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
void MCStreamer::EmitCOFFSymbolType(int Type) {
llvm_unreachable("this directive only supported on COFF targets");
}
+void MCStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlign) {
+ llvm_unreachable("this directive only supported on XCOFF targets");
+}
void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
void MCStreamer::emitELFSymverDirective(StringRef AliasName,
const MCSymbol *Aliasee) {}
diff --git a/lib/MC/MCSubtargetInfo.cpp b/lib/MC/MCSubtargetInfo.cpp
index 5fd48d9e1010..c8678df02bfd 100644
--- a/lib/MC/MCSubtargetInfo.cpp
+++ b/lib/MC/MCSubtargetInfo.cpp
@@ -315,3 +315,28 @@ void MCSubtargetInfo::initInstrItins(InstrItineraryData &InstrItins) const {
InstrItins = InstrItineraryData(getSchedModel(), Stages, OperandCycles,
ForwardingPaths);
}
+
+Optional<unsigned> MCSubtargetInfo::getCacheSize(unsigned Level) const {
+ return Optional<unsigned>();
+}
+
+Optional<unsigned>
+MCSubtargetInfo::getCacheAssociativity(unsigned Level) const {
+ return Optional<unsigned>();
+}
+
+Optional<unsigned> MCSubtargetInfo::getCacheLineSize(unsigned Level) const {
+ return Optional<unsigned>();
+}
+
+unsigned MCSubtargetInfo::getPrefetchDistance() const {
+ return 0;
+}
+
+unsigned MCSubtargetInfo::getMaxPrefetchIterationsAhead() const {
+ return UINT_MAX;
+}
+
+unsigned MCSubtargetInfo::getMinPrefetchStride() const {
+ return 1;
+}
diff --git a/lib/MC/MCWasmObjectTargetWriter.cpp b/lib/MC/MCWasmObjectTargetWriter.cpp
index e46257823e34..1ccb3a58d5c1 100644
--- a/lib/MC/MCWasmObjectTargetWriter.cpp
+++ b/lib/MC/MCWasmObjectTargetWriter.cpp
@@ -10,8 +10,9 @@
using namespace llvm;
-MCWasmObjectTargetWriter::MCWasmObjectTargetWriter(bool Is64Bit)
- : Is64Bit(Is64Bit) {}
+MCWasmObjectTargetWriter::MCWasmObjectTargetWriter(bool Is64Bit,
+ bool IsEmscripten)
+ : Is64Bit(Is64Bit), IsEmscripten(IsEmscripten) {}
// Pin the vtable to this object file
MCWasmObjectTargetWriter::~MCWasmObjectTargetWriter() = default;
diff --git a/lib/MC/MCWasmStreamer.cpp b/lib/MC/MCWasmStreamer.cpp
index 86fa72197855..e7e96ecbb3a0 100644
--- a/lib/MC/MCWasmStreamer.cpp
+++ b/lib/MC/MCWasmStreamer.cpp
@@ -122,7 +122,7 @@ bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
break;
case MCSA_NoDeadStrip:
- Symbol->setExported();
+ Symbol->setNoStrip();
break;
default:
diff --git a/lib/MC/MCWinCOFFStreamer.cpp b/lib/MC/MCWinCOFFStreamer.cpp
index 04d5f100a2ff..c5a21312140b 100644
--- a/lib/MC/MCWinCOFFStreamer.cpp
+++ b/lib/MC/MCWinCOFFStreamer.cpp
@@ -88,7 +88,19 @@ void MCWinCOFFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) {
}
void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
- llvm_unreachable("not implemented");
+ // Let the target do whatever target specific stuff it needs to do.
+ getAssembler().getBackend().handleAssemblerFlag(Flag);
+
+ switch (Flag) {
+ // None of these require COFF specific handling.
+ case MCAF_SyntaxUnified:
+ case MCAF_Code16:
+ case MCAF_Code32:
+ case MCAF_Code64:
+ break;
+ case MCAF_SubsectionsViaSymbols:
+ llvm_unreachable("COFF doesn't support .subsections_via_symbols");
+ }
}
void MCWinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) {
@@ -180,7 +192,7 @@ void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection();
getAssembler().registerSection(*SXData);
if (SXData->getAlignment() < 4)
- SXData->setAlignment(4);
+ SXData->setAlignment(Align(4));
new MCSymbolIdFragment(Symbol, SXData);
@@ -197,7 +209,7 @@ void MCWinCOFFStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
MCSection *Sec = getCurrentSectionOnly();
getAssembler().registerSection(*Sec);
if (Sec->getAlignment() < 4)
- Sec->setAlignment(4);
+ Sec->setAlignment(Align(4));
new MCSymbolIdFragment(Symbol, getCurrentSectionOnly());
diff --git a/lib/MC/MCXCOFFStreamer.cpp b/lib/MC/MCXCOFFStreamer.cpp
index 071de024a3fa..50937d6adc0c 100644
--- a/lib/MC/MCXCOFFStreamer.cpp
+++ b/lib/MC/MCXCOFFStreamer.cpp
@@ -10,10 +10,12 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/MC/MCXCOFFStreamer.h"
+#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSymbolXCOFF.h"
+#include "llvm/MC/MCXCOFFStreamer.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
@@ -25,14 +27,38 @@ MCXCOFFStreamer::MCXCOFFStreamer(MCContext &Context,
: MCObjectStreamer(Context, std::move(MAB), std::move(OW),
std::move(Emitter)) {}
-bool MCXCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
+bool MCXCOFFStreamer::EmitSymbolAttribute(MCSymbol *Sym,
MCSymbolAttr Attribute) {
- report_fatal_error("Symbol attributes not implemented for XCOFF.");
+ auto *Symbol = cast<MCSymbolXCOFF>(Sym);
+ getAssembler().registerSymbol(*Symbol);
+
+ switch (Attribute) {
+ case MCSA_Global:
+ Symbol->setStorageClass(XCOFF::C_EXT);
+ Symbol->setExternal(true);
+ break;
+ default:
+ report_fatal_error("Not implemented yet.");
+ }
+ return true;
}
void MCXCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {
- report_fatal_error("Emiting common symbols not implemented for XCOFF.");
+ getAssembler().registerSymbol(*Symbol);
+ Symbol->setExternal(cast<MCSymbolXCOFF>(Symbol)->getStorageClass() !=
+ XCOFF::C_HIDEXT);
+ Symbol->setCommon(Size, ByteAlignment);
+
+ // Need to add this symbol to the current Fragment which will belong to the
+ // containing CSECT.
+ auto *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
+ assert(F && "Expected a valid section with a fragment set.");
+ Symbol->setFragment(F);
+
+ // Emit the alignment and storage for the variable to the section.
+ EmitValueToAlignment(ByteAlignment);
+ EmitZeros(Size);
}
void MCXCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
@@ -42,8 +68,18 @@ void MCXCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
}
void MCXCOFFStreamer::EmitInstToData(const MCInst &Inst,
- const MCSubtargetInfo &) {
- report_fatal_error("Instruction emission not implemented for XCOFF.");
+ const MCSubtargetInfo &STI) {
+ MCAssembler &Assembler = getAssembler();
+ SmallVector<MCFixup, 4> Fixups;
+ SmallString<256> Code;
+ raw_svector_ostream VecOS(Code);
+ Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
+
+ // TODO: Handle Fixups later
+
+ MCDataFragment *DF = getOrCreateDataFragment(&STI);
+ DF->setHasInstructions(STI);
+ DF->getContents().append(Code.begin(), Code.end());
}
MCStreamer *llvm::createXCOFFStreamer(MCContext &Context,
@@ -57,3 +93,9 @@ MCStreamer *llvm::createXCOFFStreamer(MCContext &Context,
S->getAssembler().setRelaxAll(true);
return S;
}
+
+void MCXCOFFStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol,
+ uint64_t Size,
+ unsigned ByteAlignment) {
+ EmitCommonSymbol(Symbol, Size, ByteAlignment);
+}
diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp
index f0ceb86b25af..9f6af981aca1 100644
--- a/lib/MC/MachObjectWriter.cpp
+++ b/lib/MC/MachObjectWriter.cpp
@@ -25,6 +25,7 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolMachO.h"
#include "llvm/MC/MCValue.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -126,7 +127,7 @@ uint64_t MachObjectWriter::getPaddingSize(const MCSection *Sec,
const MCSection &NextSec = *Layout.getSectionOrder()[Next];
if (NextSec.isVirtualSection())
return 0;
- return OffsetToAlignment(EndAddr, NextSec.getAlignment());
+ return offsetToAlignment(EndAddr, Align(NextSec.getAlignment()));
}
void MachObjectWriter::writeHeader(MachO::HeaderFileType Type,
@@ -444,7 +445,8 @@ void MachObjectWriter::writeLinkerOptionsLoadCommand(
}
// Pad to a multiple of the pointer size.
- W.OS.write_zeros(OffsetToAlignment(BytesWritten, is64Bit() ? 8 : 4));
+ W.OS.write_zeros(
+ offsetToAlignment(BytesWritten, is64Bit() ? Align(8) : Align(4)));
assert(W.OS.tell() - Start == Size);
}
@@ -832,7 +834,8 @@ uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
// The section data is padded to 4 bytes.
//
// FIXME: Is this machine dependent?
- unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4);
+ unsigned SectionDataPadding =
+ offsetToAlignment(SectionDataFileSize, Align(4));
SectionDataFileSize += SectionDataPadding;
// Write the prolog, starting with the header and load command...
@@ -997,7 +1000,8 @@ uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
#endif
Asm.getLOHContainer().emit(*this, Layout);
// Pad to a multiple of the pointer size.
- W.OS.write_zeros(OffsetToAlignment(LOHRawSize, is64Bit() ? 8 : 4));
+ W.OS.write_zeros(
+ offsetToAlignment(LOHRawSize, is64Bit() ? Align(8) : Align(4)));
assert(W.OS.tell() - Start == LOHSize);
}
@@ -1043,6 +1047,6 @@ uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
std::unique_ptr<MCObjectWriter>
llvm::createMachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
raw_pwrite_stream &OS, bool IsLittleEndian) {
- return llvm::make_unique<MachObjectWriter>(std::move(MOTW), OS,
+ return std::make_unique<MachObjectWriter>(std::move(MOTW), OS,
IsLittleEndian);
}
diff --git a/lib/MC/StringTableBuilder.cpp b/lib/MC/StringTableBuilder.cpp
index cb3db8e2268c..c9c88ec58432 100644
--- a/lib/MC/StringTableBuilder.cpp
+++ b/lib/MC/StringTableBuilder.cpp
@@ -38,6 +38,7 @@ void StringTableBuilder::initSize() {
// Start the table with a NUL byte.
Size = 1;
break;
+ case XCOFF:
case WinCOFF:
// Make room to write the table size later.
Size = 4;
@@ -67,9 +68,12 @@ void StringTableBuilder::write(uint8_t *Buf) const {
if (!Data.empty())
memcpy(Buf + P.second, Data.data(), Data.size());
}
- if (K != WinCOFF)
- return;
- support::endian::write32le(Buf, Size);
+ // The COFF formats store the size of the string table in the first 4 bytes.
+ // For Windows, the format is little-endian; for AIX, it is big-endian.
+ if (K == WinCOFF)
+ support::endian::write32le(Buf, Size);
+ else if (K == XCOFF)
+ support::endian::write32be(Buf, Size);
}
// Returns the character at Pos from end of a string.
diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp
index 098343cd0107..c1ff3cc2480c 100644
--- a/lib/MC/WasmObjectWriter.cpp
+++ b/lib/MC/WasmObjectWriter.cpp
@@ -258,6 +258,7 @@ class WasmObjectWriter : public MCObjectWriter {
// TargetObjectWriter wrappers.
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
+ bool isEmscripten() const { return TargetObjectWriter->isEmscripten(); }
void startSection(SectionBookkeeping &Section, unsigned SectionId);
void startCustomSection(SectionBookkeeping &Section, StringRef Name);
@@ -426,9 +427,10 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
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;
+ // The WebAssembly backend should never generate FKF_IsPCRel fixups
+ assert(!(Asm.getBackend().getFixupKindInfo(Fixup.getKind()).Flags &
+ MCFixupKindInfo::FKF_IsPCRel));
+
const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
uint64_t C = Target.getConstant();
uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
@@ -439,51 +441,22 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
return;
if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
- assert(RefB->getKind() == MCSymbolRefExpr::VK_None &&
- "Should not have constructed this");
-
- // 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, Wasm 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;
- }
-
+ // To get here the A - B expression must have failed evaluateAsRelocatable.
+ // This means either A or B must be undefined and in WebAssembly we can't
+ // support either of those cases.
const auto &SymB = cast<MCSymbolWasm>(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;
+ Ctx.reportError(
+ Fixup.getLoc(),
+ Twine("symbol '") + SymB.getName() +
+ "': unsupported subtraction expression used in relocation.");
+ return;
}
// We either rejected the fixup or folded B into C at this point.
const MCSymbolRefExpr *RefA = Target.getSymA();
- const auto *SymA = RefA ? cast<MCSymbolWasm>(&RefA->getSymbol()) : nullptr;
+ const auto *SymA = cast<MCSymbolWasm>(&RefA->getSymbol());
- if (SymA && SymA->isVariable()) {
+ if (SymA->isVariable()) {
const MCExpr *Expr = SymA->getVariableValue();
const auto *Inner = cast<MCSymbolRefExpr>(Expr);
if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
@@ -496,8 +469,6 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
FixedValue = 0;
unsigned Type = TargetObjectWriter->getRelocType(Target, Fixup);
- assert(!IsPCRel);
- assert(SymA);
// Absolute offset within a section or a function.
// Currently only supported for for metadata sections.
@@ -1296,12 +1267,12 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
// Separate out the producers and target features sections
if (Name == "producers") {
- ProducersSection = llvm::make_unique<WasmCustomSection>(Name, &Section);
+ ProducersSection = std::make_unique<WasmCustomSection>(Name, &Section);
continue;
}
if (Name == "target_features") {
TargetFeaturesSection =
- llvm::make_unique<WasmCustomSection>(Name, &Section);
+ std::make_unique<WasmCustomSection>(Name, &Section);
continue;
}
@@ -1379,7 +1350,9 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
report_fatal_error(".size expression must be evaluatable");
auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
- assert(DataSection.isWasmData());
+ if (!DataSection.isWasmData())
+ report_fatal_error("data symbols must live in a data section: " +
+ WS.getName());
// For each data symbol, export it in the symtab as a reference to the
// corresponding Wasm data segment.
@@ -1473,8 +1446,12 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
if (WS.isUndefined())
Flags |= wasm::WASM_SYMBOL_UNDEFINED;
- if (WS.isExported())
- Flags |= wasm::WASM_SYMBOL_EXPORTED;
+ if (WS.isNoStrip()) {
+ Flags |= wasm::WASM_SYMBOL_NO_STRIP;
+ if (isEmscripten()) {
+ Flags |= wasm::WASM_SYMBOL_EXPORTED;
+ }
+ }
if (WS.getName() != WS.getImportName())
Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME;
@@ -1618,5 +1595,5 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
std::unique_ptr<MCObjectWriter>
llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
raw_pwrite_stream &OS) {
- return llvm::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
+ return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
}
diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp
index 0e6c05bc726d..749ed8badfaa 100644
--- a/lib/MC/WinCOFFObjectWriter.cpp
+++ b/lib/MC/WinCOFFObjectWriter.cpp
@@ -31,10 +31,10 @@
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCWinCOFFObjectWriter.h"
#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/CRC.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/JamCRC.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
@@ -239,7 +239,7 @@ WinCOFFObjectWriter::WinCOFFObjectWriter(
}
COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) {
- Symbols.push_back(make_unique<COFFSymbol>(Name));
+ Symbols.push_back(std::make_unique<COFFSymbol>(Name));
return Symbols.back().get();
}
@@ -251,7 +251,7 @@ COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol *Symbol) {
}
COFFSection *WinCOFFObjectWriter::createSection(StringRef Name) {
- Sections.emplace_back(make_unique<COFFSection>(Name));
+ Sections.emplace_back(std::make_unique<COFFSection>(Name));
return Sections.back().get();
}
@@ -605,7 +605,7 @@ uint32_t WinCOFFObjectWriter::writeSectionContents(MCAssembler &Asm,
// Calculate our CRC with an initial value of '0', this is not how
// JamCRC is specified but it aligns with the expected output.
JamCRC JC(/*Init=*/0);
- JC.update(Buf);
+ JC.update(makeArrayRef(reinterpret_cast<uint8_t*>(Buf.data()), Buf.size()));
return JC.getCRC();
}
@@ -1098,5 +1098,5 @@ void MCWinCOFFObjectTargetWriter::anchor() {}
std::unique_ptr<MCObjectWriter> llvm::createWinCOFFObjectWriter(
std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) {
- return llvm::make_unique<WinCOFFObjectWriter>(std::move(MOTW), OS);
+ return std::make_unique<WinCOFFObjectWriter>(std::move(MOTW), OS);
}
diff --git a/lib/MC/XCOFFObjectWriter.cpp b/lib/MC/XCOFFObjectWriter.cpp
index 9b9a7b6c118c..353c21068735 100644
--- a/lib/MC/XCOFFObjectWriter.cpp
+++ b/lib/MC/XCOFFObjectWriter.cpp
@@ -10,18 +10,135 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/BinaryFormat/XCOFF.h"
+#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSectionXCOFF.h"
+#include "llvm/MC/MCSymbolXCOFF.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCXCOFFObjectWriter.h"
+#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+
+#include <deque>
using namespace llvm;
+// An XCOFF object file has a limited set of predefined sections. The most
+// important ones for us (right now) are:
+// .text --> contains program code and read-only data.
+// .data --> contains initialized data, function descriptors, and the TOC.
+// .bss --> contains uninitialized data.
+// Each of these sections is composed of 'Control Sections'. A Control Section
+// is more commonly referred to as a csect. A csect is an indivisible unit of
+// code or data, and acts as a container for symbols. A csect is mapped
+// into a section based on its storage-mapping class, with the exception of
+// XMC_RW which gets mapped to either .data or .bss based on whether it's
+// explicitly initialized or not.
+//
+// We don't represent the sections in the MC layer as there is nothing
+// interesting about them at at that level: they carry information that is
+// only relevant to the ObjectWriter, so we materialize them in this class.
namespace {
+constexpr unsigned DefaultSectionAlign = 4;
+
+// Packs the csect's alignment and type into a byte.
+uint8_t getEncodedType(const MCSectionXCOFF *);
+
+// Wrapper around an MCSymbolXCOFF.
+struct Symbol {
+ const MCSymbolXCOFF *const MCSym;
+ uint32_t SymbolTableIndex;
+
+ XCOFF::StorageClass getStorageClass() const {
+ return MCSym->getStorageClass();
+ }
+ StringRef getName() const { return MCSym->getName(); }
+ Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
+};
+
+// Wrapper for an MCSectionXCOFF.
+struct ControlSection {
+ const MCSectionXCOFF *const MCCsect;
+ uint32_t SymbolTableIndex;
+ uint32_t Address;
+ uint32_t Size;
+
+ SmallVector<Symbol, 1> Syms;
+ StringRef getName() const { return MCCsect->getSectionName(); }
+ ControlSection(const MCSectionXCOFF *MCSec)
+ : MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
+};
+
+// Represents the data related to a section excluding the csects that make up
+// the raw data of the section. The csects are stored separately as not all
+// sections contain csects, and some sections contain csects which are better
+// stored separately, e.g. the .data section containing read-write, descriptor,
+// TOCBase and TOC-entry csects.
+struct Section {
+ char Name[XCOFF::NameSize];
+ // The physical/virtual address of the section. For an object file
+ // these values are equivalent.
+ uint32_t Address;
+ uint32_t Size;
+ uint32_t FileOffsetToData;
+ uint32_t FileOffsetToRelocations;
+ uint32_t RelocationCount;
+ int32_t Flags;
+
+ int16_t Index;
+
+ // Virtual sections do not need storage allocated in the object file.
+ const bool IsVirtual;
+
+ void reset() {
+ Address = 0;
+ Size = 0;
+ FileOffsetToData = 0;
+ FileOffsetToRelocations = 0;
+ RelocationCount = 0;
+ Index = -1;
+ }
+
+ Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual)
+ : Address(0), Size(0), FileOffsetToData(0), FileOffsetToRelocations(0),
+ RelocationCount(0), Flags(Flags), Index(-1), IsVirtual(IsVirtual) {
+ strncpy(Name, N, XCOFF::NameSize);
+ }
+};
+
class XCOFFObjectWriter : public MCObjectWriter {
+ // Type to be used for a container representing a set of csects with
+ // (approximately) the same storage mapping class. For example all the csects
+ // with a storage mapping class of `xmc_pr` will get placed into the same
+ // container.
+ using CsectGroup = std::deque<ControlSection>;
+
support::endian::Writer W;
std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
+ StringTableBuilder Strings;
+
+ // The non-empty sections, in the order they will appear in the section header
+ // table.
+ std::vector<Section *> Sections;
+
+ // The Predefined sections.
+ Section Text;
+ Section BSS;
+
+ // CsectGroups. These store the csects which make up different parts of
+ // the sections. Should have one for each set of csects that get mapped into
+ // the same section and get handled in a 'similar' way.
+ CsectGroup ProgramCodeCsects;
+ CsectGroup BSSCsects;
+
+ uint32_t SymbolTableEntryCount = 0;
+ uint32_t SymbolTableOffset = 0;
+
+ virtual void reset() override;
void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override;
@@ -30,6 +147,40 @@ class XCOFFObjectWriter : public MCObjectWriter {
uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
+ static bool nameShouldBeInStringTable(const StringRef &);
+ void writeSymbolName(const StringRef &);
+ void writeSymbolTableEntryForCsectMemberLabel(const Symbol &,
+ const ControlSection &, int16_t,
+ uint64_t);
+ void writeSymbolTableEntryForControlSection(const ControlSection &, int16_t,
+ XCOFF::StorageClass);
+ void writeFileHeader();
+ void writeSectionHeaderTable();
+ void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
+ void writeSymbolTable(const MCAsmLayout &Layout);
+
+ // Called after all the csects and symbols have been processed by
+ // `executePostLayoutBinding`, this function handles building up the majority
+ // of the structures in the object file representation. Namely:
+ // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
+ // sizes.
+ // *) Assigns symbol table indices.
+ // *) Builds up the section header table by adding any non-empty sections to
+ // `Sections`.
+ void assignAddressesAndIndices(const MCAsmLayout &);
+
+ bool
+ needsAuxiliaryHeader() const { /* TODO aux header support not implemented. */
+ return false;
+ }
+
+ // Returns the size of the auxiliary header to be written to the object file.
+ size_t auxiliaryHeaderSize() const {
+ assert(!needsAuxiliaryHeader() &&
+ "Auxiliary header support not implemented.");
+ return 0;
+ }
+
public:
XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS);
@@ -37,11 +188,100 @@ public:
XCOFFObjectWriter::XCOFFObjectWriter(
std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
- : W(OS, support::big), TargetObjectWriter(std::move(MOTW)) {}
+ : W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
+ Strings(StringTableBuilder::XCOFF),
+ Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false),
+ BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true) {}
+
+void XCOFFObjectWriter::reset() {
+ // Reset any sections we have written to, and empty the section header table.
+ for (auto *Sec : Sections)
+ Sec->reset();
+ Sections.clear();
+
+ // Clear any csects we have stored.
+ ProgramCodeCsects.clear();
+ BSSCsects.clear();
+
+ // Reset the symbol table and string table.
+ SymbolTableEntryCount = 0;
+ SymbolTableOffset = 0;
+ Strings.clear();
+
+ MCObjectWriter::reset();
+}
+
+void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ if (TargetObjectWriter->is64Bit())
+ report_fatal_error("64-bit XCOFF object files are not supported yet.");
+
+ // Maps the MC Section representation to its corresponding ControlSection
+ // wrapper. Needed for finding the ControlSection to insert an MCSymbol into
+ // from its containing MCSectionXCOFF.
+ DenseMap<const MCSectionXCOFF *, ControlSection *> WrapperMap;
+
+ for (const auto &S : Asm) {
+ const auto *MCSec = cast<const MCSectionXCOFF>(&S);
+ assert(WrapperMap.find(MCSec) == WrapperMap.end() &&
+ "Cannot add a csect twice.");
-void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &,
- const MCAsmLayout &) {
- // TODO Implement once we have sections and symbols to handle.
+ // If the name does not fit in the storage provided in the symbol table
+ // entry, add it to the string table.
+ if (nameShouldBeInStringTable(MCSec->getSectionName()))
+ Strings.add(MCSec->getSectionName());
+
+ switch (MCSec->getMappingClass()) {
+ case XCOFF::XMC_PR:
+ assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
+ "Only an initialized csect can contain program code.");
+ ProgramCodeCsects.emplace_back(MCSec);
+ WrapperMap[MCSec] = &ProgramCodeCsects.back();
+ break;
+ case XCOFF::XMC_RW:
+ if (XCOFF::XTY_CM == MCSec->getCSectType()) {
+ BSSCsects.emplace_back(MCSec);
+ WrapperMap[MCSec] = &BSSCsects.back();
+ break;
+ }
+ report_fatal_error("Unhandled mapping of read-write csect to section.");
+ case XCOFF::XMC_TC0:
+ // TODO FIXME Handle emiting the TOC base.
+ break;
+ case XCOFF::XMC_BS:
+ assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
+ "Mapping invalid csect. CSECT with bss storage class must be "
+ "common type.");
+ BSSCsects.emplace_back(MCSec);
+ WrapperMap[MCSec] = &BSSCsects.back();
+ break;
+ default:
+ report_fatal_error("Unhandled mapping of csect to section.");
+ }
+ }
+
+ for (const MCSymbol &S : Asm.symbols()) {
+ // Nothing to do for temporary symbols.
+ if (S.isTemporary())
+ continue;
+ const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
+
+ // Map the symbol into its containing csect.
+ const MCSectionXCOFF *ContainingCsect = XSym->getContainingCsect();
+ assert(WrapperMap.find(ContainingCsect) != WrapperMap.end() &&
+ "Expected containing csect to exist in map");
+
+ // Lookup the containing csect and add the symbol to it.
+ WrapperMap[ContainingCsect]->Syms.emplace_back(XSym);
+
+ // If the name does not fit in the storage provided in the symbol table
+ // entry, add it to the string table.
+ if (nameShouldBeInStringTable(XSym->getName()))
+ Strings.add(XSym->getName());
+ }
+
+ Strings.finalize();
+ assignAddressesAndIndices(Layout);
}
void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &,
@@ -50,7 +290,29 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &,
report_fatal_error("XCOFF relocations not supported.");
}
-uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &) {
+void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ // Write the program code control sections one at a time.
+ uint32_t CurrentAddressLocation = Text.Address;
+ for (const auto &Csect : ProgramCodeCsects) {
+ if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
+ W.OS.write_zeros(PaddingSize);
+ Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
+ CurrentAddressLocation = Csect.Address + Csect.Size;
+ }
+
+ if (Text.Index != -1) {
+ // The size of the tail padding in a section is the end virtual address of
+ // the current section minus the the end virtual address of the last csect
+ // in that section.
+ if (uint32_t PaddingSize =
+ Text.Address + Text.Size - CurrentAddressLocation)
+ W.OS.write_zeros(PaddingSize);
+ }
+}
+
+uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
// We always emit a timestamp of 0 for reproducibility, so ensure incremental
// linking is not enabled, in case, like with Windows COFF, such a timestamp
// is incompatible with incremental linking of XCOFF.
@@ -62,27 +324,274 @@ uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &) {
uint64_t StartOffset = W.OS.tell();
- // TODO FIXME Assign section numbers/finalize sections.
+ writeFileHeader();
+ writeSectionHeaderTable();
+ writeSections(Asm, Layout);
+ // TODO writeRelocations();
- // TODO FIXME Finalize symbols.
+ writeSymbolTable(Layout);
+ // Write the string table.
+ Strings.write(W.OS);
+
+ return W.OS.tell() - StartOffset;
+}
+bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
+ return SymbolName.size() > XCOFF::NameSize;
+}
+
+void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
+ if (nameShouldBeInStringTable(SymbolName)) {
+ W.write<int32_t>(0);
+ W.write<uint32_t>(Strings.getOffset(SymbolName));
+ } else {
+ char Name[XCOFF::NameSize];
+ std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
+ ArrayRef<char> NameRef(Name, XCOFF::NameSize);
+ W.write(NameRef);
+ }
+}
+
+void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
+ const Symbol &SymbolRef, const ControlSection &CSectionRef,
+ int16_t SectionIndex, uint64_t SymbolOffset) {
+ // Name or Zeros and string table offset
+ writeSymbolName(SymbolRef.getName());
+ assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address &&
+ "Symbol address overflows.");
+ W.write<uint32_t>(CSectionRef.Address + SymbolOffset);
+ W.write<int16_t>(SectionIndex);
+ // Basic/Derived type. See the description of the n_type field for symbol
+ // table entries for a detailed description. Since we don't yet support
+ // visibility, and all other bits are either optionally set or reserved, this
+ // is always zero.
+ // TODO FIXME How to assert a symbol's visibilty is default?
+ // TODO Set the function indicator (bit 10, 0x0020) for functions
+ // when debugging is enabled.
+ W.write<uint16_t>(0);
+ W.write<uint8_t>(SymbolRef.getStorageClass());
+ // Always 1 aux entry for now.
+ W.write<uint8_t>(1);
+
+ // Now output the auxiliary entry.
+ W.write<uint32_t>(CSectionRef.SymbolTableIndex);
+ // Parameter typecheck hash. Not supported.
+ W.write<uint32_t>(0);
+ // Typecheck section number. Not supported.
+ W.write<uint16_t>(0);
+ // Symbol type: Label
+ W.write<uint8_t>(XCOFF::XTY_LD);
+ // Storage mapping class.
+ W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
+ // Reserved (x_stab).
+ W.write<uint32_t>(0);
+ // Reserved (x_snstab).
+ W.write<uint16_t>(0);
+}
+
+void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
+ const ControlSection &CSectionRef, int16_t SectionIndex,
+ XCOFF::StorageClass StorageClass) {
+ // n_name, n_zeros, n_offset
+ writeSymbolName(CSectionRef.getName());
+ // n_value
+ W.write<uint32_t>(CSectionRef.Address);
+ // n_scnum
+ W.write<int16_t>(SectionIndex);
+ // Basic/Derived type. See the description of the n_type field for symbol
+ // table entries for a detailed description. Since we don't yet support
+ // visibility, and all other bits are either optionally set or reserved, this
+ // is always zero.
+ // TODO FIXME How to assert a symbol's visibilty is default?
+ // TODO Set the function indicator (bit 10, 0x0020) for functions
+ // when debugging is enabled.
+ W.write<uint16_t>(0);
+ // n_sclass
+ W.write<uint8_t>(StorageClass);
+ // Always 1 aux entry for now.
+ W.write<uint8_t>(1);
+
+ // Now output the auxiliary entry.
+ W.write<uint32_t>(CSectionRef.Size);
+ // Parameter typecheck hash. Not supported.
+ W.write<uint32_t>(0);
+ // Typecheck section number. Not supported.
+ W.write<uint16_t>(0);
+ // Symbol type.
+ W.write<uint8_t>(getEncodedType(CSectionRef.MCCsect));
+ // Storage mapping class.
+ W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
+ // Reserved (x_stab).
+ W.write<uint32_t>(0);
+ // Reserved (x_snstab).
+ W.write<uint16_t>(0);
+}
+
+void XCOFFObjectWriter::writeFileHeader() {
// Magic.
W.write<uint16_t>(0x01df);
// Number of sections.
- W.write<uint16_t>(0);
+ W.write<uint16_t>(Sections.size());
// Timestamp field. For reproducible output we write a 0, which represents no
// timestamp.
W.write<int32_t>(0);
// Byte Offset to the start of the symbol table.
- W.write<uint32_t>(0);
+ W.write<uint32_t>(SymbolTableOffset);
// Number of entries in the symbol table.
- W.write<int32_t>(0);
+ W.write<int32_t>(SymbolTableEntryCount);
// Size of the optional header.
W.write<uint16_t>(0);
// Flags.
W.write<uint16_t>(0);
+}
- return W.OS.tell() - StartOffset;
+void XCOFFObjectWriter::writeSectionHeaderTable() {
+ for (const auto *Sec : Sections) {
+ // Write Name.
+ ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
+ W.write(NameRef);
+
+ // Write the Physical Address and Virtual Address. In an object file these
+ // are the same.
+ W.write<uint32_t>(Sec->Address);
+ W.write<uint32_t>(Sec->Address);
+
+ W.write<uint32_t>(Sec->Size);
+ W.write<uint32_t>(Sec->FileOffsetToData);
+
+ // Relocation pointer and Lineno pointer. Not supported yet.
+ W.write<uint32_t>(0);
+ W.write<uint32_t>(0);
+
+ // Relocation and line-number counts. Not supported yet.
+ W.write<uint16_t>(0);
+ W.write<uint16_t>(0);
+
+ W.write<int32_t>(Sec->Flags);
+ }
+}
+
+void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
+ // Print out symbol table for the program code.
+ for (const auto &Csect : ProgramCodeCsects) {
+ // Write out the control section first and then each symbol in it.
+ writeSymbolTableEntryForControlSection(Csect, Text.Index,
+ Csect.MCCsect->getStorageClass());
+ for (const auto &Sym : Csect.Syms)
+ writeSymbolTableEntryForCsectMemberLabel(
+ Sym, Csect, Text.Index, Layout.getSymbolOffset(*Sym.MCSym));
+ }
+
+ // The BSS Section is special in that the csects must contain a single symbol,
+ // and the contained symbol cannot be represented in the symbol table as a
+ // label definition.
+ for (auto &Csect : BSSCsects) {
+ assert(Csect.Syms.size() == 1 &&
+ "Uninitialized csect cannot contain more then 1 symbol.");
+ Symbol &Sym = Csect.Syms.back();
+ writeSymbolTableEntryForControlSection(Csect, BSS.Index,
+ Sym.getStorageClass());
+ }
+}
+
+void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
+ // The address corrresponds to the address of sections and symbols in the
+ // object file. We place the shared address 0 immediately after the
+ // section header table.
+ uint32_t Address = 0;
+ // Section indices are 1-based in XCOFF.
+ int16_t SectionIndex = 1;
+ // The first symbol table entry is for the file name. We are not emitting it
+ // yet, so start at index 0.
+ uint32_t SymbolTableIndex = 0;
+
+ // Text section comes first.
+ if (!ProgramCodeCsects.empty()) {
+ Sections.push_back(&Text);
+ Text.Index = SectionIndex++;
+ for (auto &Csect : ProgramCodeCsects) {
+ const MCSectionXCOFF *MCSec = Csect.MCCsect;
+ Csect.Address = alignTo(Address, MCSec->getAlignment());
+ Csect.Size = Layout.getSectionAddressSize(MCSec);
+ Address = Csect.Address + Csect.Size;
+ Csect.SymbolTableIndex = SymbolTableIndex;
+ // 1 main and 1 auxiliary symbol table entry for the csect.
+ SymbolTableIndex += 2;
+ for (auto &Sym : Csect.Syms) {
+ Sym.SymbolTableIndex = SymbolTableIndex;
+ // 1 main and 1 auxiliary symbol table entry for each contained symbol
+ SymbolTableIndex += 2;
+ }
+ }
+ Address = alignTo(Address, DefaultSectionAlign);
+
+ // The first csect of a section can be aligned by adjusting the virtual
+ // address of its containing section instead of writing zeroes into the
+ // object file.
+ Text.Address = ProgramCodeCsects.front().Address;
+
+ Text.Size = Address - Text.Address;
+ }
+
+ // Data section Second. TODO
+
+ // BSS Section third.
+ if (!BSSCsects.empty()) {
+ Sections.push_back(&BSS);
+ BSS.Index = SectionIndex++;
+ for (auto &Csect : BSSCsects) {
+ const MCSectionXCOFF *MCSec = Csect.MCCsect;
+ Csect.Address = alignTo(Address, MCSec->getAlignment());
+ Csect.Size = Layout.getSectionAddressSize(MCSec);
+ Address = Csect.Address + Csect.Size;
+ Csect.SymbolTableIndex = SymbolTableIndex;
+ // 1 main and 1 auxiliary symbol table entry for the csect.
+ SymbolTableIndex += 2;
+
+ assert(Csect.Syms.size() == 1 &&
+ "csect in the BSS can only contain a single symbol.");
+ Csect.Syms[0].SymbolTableIndex = Csect.SymbolTableIndex;
+ }
+ // Pad out Address to the default alignment. This is to match how the system
+ // assembler handles the .bss section. Its size is always a multiple of 4.
+ Address = alignTo(Address, DefaultSectionAlign);
+
+ BSS.Address = BSSCsects.front().Address;
+ BSS.Size = Address - BSS.Address;
+ }
+
+ SymbolTableEntryCount = SymbolTableIndex;
+
+ // Calculate the RawPointer value for each section.
+ uint64_t RawPointer = sizeof(XCOFF::FileHeader32) + auxiliaryHeaderSize() +
+ Sections.size() * sizeof(XCOFF::SectionHeader32);
+ for (auto *Sec : Sections) {
+ if (!Sec->IsVirtual) {
+ Sec->FileOffsetToData = RawPointer;
+ RawPointer += Sec->Size;
+ }
+ }
+
+ // TODO Add in Relocation storage to the RawPointer Calculation.
+ // TODO What to align the SymbolTable to?
+ // TODO Error check that the number of symbol table entries fits in 32-bits
+ // signed ...
+ if (SymbolTableEntryCount)
+ SymbolTableOffset = RawPointer;
+}
+
+// Takes the log base 2 of the alignment and shifts the result into the 5 most
+// significant bits of a byte, then or's in the csect type into the least
+// significant 3 bits.
+uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
+ unsigned Align = Sec->getAlignment();
+ assert(isPowerOf2_32(Align) && "Alignment must be a power of 2.");
+ unsigned Log2Align = Log2_32(Align);
+ // Result is a number in the range [0, 31] which fits in the 5 least
+ // significant bits. Shift this value into the 5 most significant bits, and
+ // bitwise-or in the csect type.
+ uint8_t EncodedAlign = Log2Align << 3;
+ return EncodedAlign | Sec->getCSectType();
}
} // end anonymous namespace
@@ -90,5 +599,5 @@ uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &) {
std::unique_ptr<MCObjectWriter>
llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS) {
- return llvm::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
+ return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
}