summaryrefslogtreecommitdiff
path: root/lib/MC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
commit044eb2f6afba375a914ac9d8024f8f5142bb912e (patch)
tree1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/MC
parenteb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff)
Notes
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/CMakeLists.txt1
-rw-r--r--lib/MC/ELFObjectWriter.cpp35
-rw-r--r--lib/MC/MCAsmBackend.cpp28
-rw-r--r--lib/MC/MCAsmInfoWasm.cpp2
-rw-r--r--lib/MC/MCAsmStreamer.cpp197
-rw-r--r--lib/MC/MCAssembler.cpp40
-rw-r--r--lib/MC/MCCodePadder.cpp371
-rw-r--r--lib/MC/MCCodeView.cpp122
-rw-r--r--lib/MC/MCContext.cpp46
-rw-r--r--lib/MC/MCDwarf.cpp217
-rw-r--r--lib/MC/MCELFObjectTargetWriter.cpp12
-rw-r--r--lib/MC/MCELFStreamer.cpp24
-rw-r--r--lib/MC/MCExpr.cpp10
-rw-r--r--lib/MC/MCFragment.cpp29
-rw-r--r--lib/MC/MCMachOStreamer.cpp53
-rw-r--r--lib/MC/MCNullStreamer.cpp2
-rw-r--r--lib/MC/MCObjectFileInfo.cpp77
-rw-r--r--lib/MC/MCObjectStreamer.cpp57
-rw-r--r--lib/MC/MCParser/AsmLexer.cpp37
-rw-r--r--lib/MC/MCParser/AsmParser.cpp336
-rw-r--r--lib/MC/MCParser/COFFAsmParser.cpp66
-rw-r--r--lib/MC/MCParser/DarwinAsmParser.cpp194
-rw-r--r--lib/MC/MCParser/ELFAsmParser.cpp3
-rw-r--r--lib/MC/MCParser/MCAsmParser.cpp8
-rw-r--r--lib/MC/MCParser/MCTargetAsmParser.cpp5
-rw-r--r--lib/MC/MCRegisterInfo.cpp28
-rw-r--r--lib/MC/MCSectionELF.cpp3
-rw-r--r--lib/MC/MCSectionWasm.cpp1
-rw-r--r--lib/MC/MCStreamer.cpp362
-rw-r--r--lib/MC/MCSubtargetInfo.cpp14
-rw-r--r--lib/MC/MCSymbolELF.cpp1
-rw-r--r--lib/MC/MCWasmStreamer.cpp20
-rw-r--r--lib/MC/MCWin64EH.cpp10
-rw-r--r--lib/MC/MCWinCOFFStreamer.cpp13
-rw-r--r--lib/MC/MachObjectWriter.cpp61
-rw-r--r--lib/MC/StringTableBuilder.cpp43
-rw-r--r--lib/MC/WasmObjectWriter.cpp648
-rw-r--r--lib/MC/WinCOFFObjectWriter.cpp16
38 files changed, 2207 insertions, 985 deletions
diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt
index 562f136a3ce2..b9e23d106e25 100644
--- a/lib/MC/CMakeLists.txt
+++ b/lib/MC/CMakeLists.txt
@@ -10,6 +10,7 @@ add_llvm_library(LLVMMC
MCAsmStreamer.cpp
MCAssembler.cpp
MCCodeEmitter.cpp
+ MCCodePadder.cpp
MCCodeView.cpp
MCContext.cpp
MCDwarf.cpp
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index c8dd63011943..e11eaaa30603 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -162,9 +162,10 @@ class ELFObjectWriter : public MCObjectWriter {
bool ZLibStyle, unsigned Alignment);
public:
- ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS,
- bool IsLittleEndian)
- : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {}
+ ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS, bool IsLittleEndian)
+ : MCObjectWriter(OS, IsLittleEndian),
+ TargetObjectWriter(std::move(MOTW)) {}
~ELFObjectWriter() override = default;
@@ -1108,7 +1109,7 @@ void ELFObjectWriter::writeRelocations(const MCAssembler &Asm,
if (is64Bit()) {
write(Entry.Offset);
- if (TargetObjectWriter->isN64()) {
+ if (TargetObjectWriter->getEMachine() == ELF::EM_MIPS) {
write(uint32_t(Index));
write(TargetObjectWriter->getRSsym(Entry.Type));
@@ -1131,6 +1132,23 @@ void ELFObjectWriter::writeRelocations(const MCAssembler &Asm,
if (hasRelocationAddend())
write(uint32_t(Entry.Addend));
+
+ if (TargetObjectWriter->getEMachine() == ELF::EM_MIPS) {
+ if (uint32_t RType = TargetObjectWriter->getRType2(Entry.Type)) {
+ write(uint32_t(Entry.Offset));
+
+ ERE32.setSymbolAndType(0, RType);
+ write(ERE32.r_info);
+ write(uint32_t(0));
+ }
+ if (uint32_t RType = TargetObjectWriter->getRType3(Entry.Type)) {
+ write(uint32_t(Entry.Offset));
+
+ ERE32.setSymbolAndType(0, RType);
+ write(ERE32.r_info);
+ write(uint32_t(0));
+ }
+ }
}
}
}
@@ -1369,8 +1387,9 @@ bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
InSet, IsPCRel);
}
-MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
- raw_pwrite_stream &OS,
- bool IsLittleEndian) {
- return new ELFObjectWriter(MOTW, OS, IsLittleEndian);
+std::unique_ptr<MCObjectWriter>
+llvm::createELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS, bool IsLittleEndian) {
+ return llvm::make_unique<ELFObjectWriter>(std::move(MOTW), OS,
+ IsLittleEndian);
}
diff --git a/lib/MC/MCAsmBackend.cpp b/lib/MC/MCAsmBackend.cpp
index 3642f37aa855..b4a4d0a89966 100644
--- a/lib/MC/MCAsmBackend.cpp
+++ b/lib/MC/MCAsmBackend.cpp
@@ -10,6 +10,7 @@
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/MC/MCCodePadder.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include <cassert>
#include <cstddef>
@@ -17,7 +18,10 @@
using namespace llvm;
-MCAsmBackend::MCAsmBackend() = default;
+MCAsmBackend::MCAsmBackend() : CodePadder(new MCCodePadder()) {}
+
+MCAsmBackend::MCAsmBackend(std::unique_ptr<MCCodePadder> TargetCodePadder)
+ : CodePadder(std::move(TargetCodePadder)) {}
MCAsmBackend::~MCAsmBackend() = default;
@@ -59,3 +63,25 @@ bool MCAsmBackend::fixupNeedsRelaxationAdvanced(
return true;
return fixupNeedsRelaxation(Fixup, Value, DF, Layout);
}
+
+void MCAsmBackend::handleCodePaddingBasicBlockStart(
+ MCObjectStreamer *OS, const MCCodePaddingContext &Context) {
+ CodePadder->handleBasicBlockStart(OS, Context);
+}
+
+void MCAsmBackend::handleCodePaddingBasicBlockEnd(
+ const MCCodePaddingContext &Context) {
+ CodePadder->handleBasicBlockEnd(Context);
+}
+
+void MCAsmBackend::handleCodePaddingInstructionBegin(const MCInst &Inst) {
+ CodePadder->handleInstructionBegin(Inst);
+}
+
+void MCAsmBackend::handleCodePaddingInstructionEnd(const MCInst &Inst) {
+ CodePadder->handleInstructionEnd(Inst);
+}
+
+bool MCAsmBackend::relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout) {
+ return CodePadder->relaxFragment(PF, Layout);
+} \ No newline at end of file
diff --git a/lib/MC/MCAsmInfoWasm.cpp b/lib/MC/MCAsmInfoWasm.cpp
index aa26616dda36..fc55059ff75d 100644
--- a/lib/MC/MCAsmInfoWasm.cpp
+++ b/lib/MC/MCAsmInfoWasm.cpp
@@ -13,8 +13,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCAsmInfoWasm.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCSectionWasm.h"
using namespace llvm;
void MCAsmInfoWasm::anchor() { }
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index 9e5553fa8d42..3357553cf19f 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -22,17 +22,14 @@
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbolELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/SourceMgr.h"
#include <cctype>
using namespace llvm;
@@ -140,6 +137,8 @@ public:
void EmitDataRegion(MCDataRegionType Kind) override;
void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
unsigned Update) override;
+ void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
+ unsigned Update) override;
void EmitThumbFunc(MCSymbol *Func) override;
void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
@@ -225,7 +224,9 @@ public:
StringRef FileName) override;
MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
- bool EmitCVFileDirective(unsigned FileNo, StringRef Filename) override;
+ bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
+ ArrayRef<uint8_t> Checksum,
+ unsigned ChecksumKind) override;
bool EmitCVFuncIdDirective(unsigned FuncId) override;
bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
unsigned IAFile, unsigned IALine,
@@ -245,6 +246,8 @@ public:
StringRef FixedSizePortion) override;
void EmitCVStringTableDirective() override;
void EmitCVFileChecksumsDirective() override;
+ void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override;
+ void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
void EmitIdent(StringRef IdentString) override;
void EmitCFISections(bool EH, bool Debug) override;
@@ -256,6 +259,7 @@ public:
void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
void EmitCFIRememberState() override;
void EmitCFIRestoreState() override;
+ void EmitCFIRestore(int64_t Register) override;
void EmitCFISameValue(int64_t Register) override;
void EmitCFIRelOffset(int64_t Register, int64_t Offset) override;
void EmitCFIAdjustCfaOffset(int64_t Adjustment) override;
@@ -265,21 +269,26 @@ public:
void EmitCFIUndefined(int64_t Register) override;
void EmitCFIRegister(int64_t Register1, int64_t Register2) override;
void EmitCFIWindowSave() override;
+ void EmitCFIReturnColumn(int64_t Register) override;
+
+ void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
+ void EmitWinCFIEndProc(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,
+ SMLoc Loc) override;
+ void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;
+ void EmitWinCFISaveReg(unsigned Register, unsigned Offset,
+ SMLoc Loc) override;
+ void EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
+ SMLoc Loc) override;
+ void EmitWinCFIPushFrame(bool Code, SMLoc Loc) override;
+ void EmitWinCFIEndProlog(SMLoc Loc) override;
- void EmitWinCFIStartProc(const MCSymbol *Symbol) override;
- void EmitWinCFIEndProc() override;
- void EmitWinCFIStartChained() override;
- void EmitWinCFIEndChained() override;
- void EmitWinCFIPushReg(unsigned Register) override;
- void EmitWinCFISetFrame(unsigned Register, unsigned Offset) override;
- void EmitWinCFIAllocStack(unsigned Size) override;
- void EmitWinCFISaveReg(unsigned Register, unsigned Offset) override;
- void EmitWinCFISaveXMM(unsigned Register, unsigned Offset) override;
- void EmitWinCFIPushFrame(bool Code) override;
- void EmitWinCFIEndProlog() override;
-
- void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except) override;
- void EmitWinEHHandlerData() override;
+ void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
+ SMLoc Loc) override;
+ void EmitWinEHHandlerData(SMLoc Loc) override;
void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
bool PrintSchedInfo) override;
@@ -464,15 +473,39 @@ void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) {
EmitEOL();
}
-void MCAsmStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major,
+static const char *getVersionMinDirective(MCVersionMinType Type) {
+ switch (Type) {
+ case MCVM_WatchOSVersionMin: return ".watchos_version_min";
+ case MCVM_TvOSVersionMin: return ".tvos_version_min";
+ case MCVM_IOSVersionMin: return ".ios_version_min";
+ case MCVM_OSXVersionMin: return ".macosx_version_min";
+ }
+ llvm_unreachable("Invalid MC version min type");
+}
+
+void MCAsmStreamer::EmitVersionMin(MCVersionMinType Type, unsigned Major,
unsigned Minor, unsigned Update) {
- switch (Kind) {
- case MCVM_WatchOSVersionMin: OS << "\t.watchos_version_min"; break;
- case MCVM_TvOSVersionMin: OS << "\t.tvos_version_min"; break;
- case MCVM_IOSVersionMin: OS << "\t.ios_version_min"; break;
- case MCVM_OSXVersionMin: OS << "\t.macosx_version_min"; break;
+ OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
+ if (Update)
+ OS << ", " << Update;
+ EmitEOL();
+}
+
+static const char *getPlatformName(MachO::PlatformType Type) {
+ switch (Type) {
+ case MachO::PLATFORM_MACOS: return "macos";
+ case MachO::PLATFORM_IOS: return "ios";
+ case MachO::PLATFORM_TVOS: return "tvos";
+ case MachO::PLATFORM_WATCHOS: return "watchos";
+ case MachO::PLATFORM_BRIDGEOS: return "bridgeos";
}
- OS << " " << Major << ", " << Minor;
+ llvm_unreachable("Invalid Mach-O platform type");
+}
+
+void MCAsmStreamer::EmitBuildVersion(unsigned Platform, unsigned Major,
+ unsigned Minor, unsigned Update) {
+ const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
+ OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;
if (Update)
OS << ", " << Update;
EmitEOL();
@@ -1119,13 +1152,25 @@ MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
return MCStreamer::getDwarfLineTableSymbol(0);
}
-bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
- if (!getContext().getCVContext().addFile(FileNo, Filename))
+bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
+ ArrayRef<uint8_t> Checksum,
+ unsigned ChecksumKind) {
+ if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
+ ChecksumKind))
return false;
OS << "\t.cv_file\t" << FileNo << ' ';
-
PrintQuotedString(Filename, OS);
+
+ if (!ChecksumKind) {
+ EmitEOL();
+ return true;
+ }
+
+ OS << ' ';
+ PrintQuotedString(toHex(Checksum), OS);
+ OS << ' ' << ChecksumKind;
+
EmitEOL();
return true;
}
@@ -1227,6 +1272,17 @@ void MCAsmStreamer::EmitCVFileChecksumsDirective() {
EmitEOL();
}
+void MCAsmStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
+ OS << "\t.cv_filechecksumoffset\t" << FileNo;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
+ OS << "\t.cv_fpo_data\t";
+ ProcSym->print(OS, MAI);
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitIdent(StringRef IdentString) {
assert(MAI->hasIdentDirective() && ".ident directive not supported");
OS << "\t.ident\t";
@@ -1263,12 +1319,17 @@ void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
void MCAsmStreamer::EmitRegisterName(int64_t Register) {
if (!MAI->useDwarfRegNumForCFI()) {
+ // User .cfi_* directives can use arbitrary DWARF register numbers, not
+ // 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();
- unsigned LLVMRegister = MRI->getLLVMRegNum(Register, true);
- InstPrinter->printRegName(OS, LLVMRegister);
- } else {
- OS << Register;
+ int LLVMRegister = MRI->getLLVMRegNumFromEH(Register);
+ if (LLVMRegister != -1) {
+ InstPrinter->printRegName(OS, LLVMRegister);
+ return;
+ }
}
+ OS << Register;
}
void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
@@ -1353,6 +1414,13 @@ void MCAsmStreamer::EmitCFIRestoreState() {
EmitEOL();
}
+void MCAsmStreamer::EmitCFIRestore(int64_t Register) {
+ MCStreamer::EmitCFIRestore(Register);
+ OS << "\t.cfi_restore ";
+ EmitRegisterName(Register);
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitCFISameValue(int64_t Register) {
MCStreamer::EmitCFISameValue(Register);
OS << "\t.cfi_same_value ";
@@ -1398,38 +1466,44 @@ void MCAsmStreamer::EmitCFIWindowSave() {
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) {
- MCStreamer::EmitWinCFIStartProc(Symbol);
+void MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) {
+ MCStreamer::EmitCFIReturnColumn(Register);
+ OS << "\t.cfi_return_column " << Register;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
+ MCStreamer::EmitWinCFIStartProc(Symbol, Loc);
OS << ".seh_proc ";
Symbol->print(OS, MAI);
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFIEndProc() {
- MCStreamer::EmitWinCFIEndProc();
+void MCAsmStreamer::EmitWinCFIEndProc(SMLoc Loc) {
+ MCStreamer::EmitWinCFIEndProc(Loc);
OS << "\t.seh_endproc";
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFIStartChained() {
- MCStreamer::EmitWinCFIStartChained();
+void MCAsmStreamer::EmitWinCFIStartChained(SMLoc Loc) {
+ MCStreamer::EmitWinCFIStartChained(Loc);
OS << "\t.seh_startchained";
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFIEndChained() {
- MCStreamer::EmitWinCFIEndChained();
+void MCAsmStreamer::EmitWinCFIEndChained(SMLoc Loc) {
+ MCStreamer::EmitWinCFIEndChained(Loc);
OS << "\t.seh_endchained";
EmitEOL();
}
void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
- bool Except) {
- MCStreamer::EmitWinEHHandler(Sym, Unwind, Except);
+ bool Except, SMLoc Loc) {
+ MCStreamer::EmitWinEHHandler(Sym, Unwind, Except, Loc);
OS << "\t.seh_handler ";
Sym->print(OS, MAI);
@@ -1440,8 +1514,8 @@ void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
EmitEOL();
}
-void MCAsmStreamer::EmitWinEHHandlerData() {
- MCStreamer::EmitWinEHHandlerData();
+void MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) {
+ MCStreamer::EmitWinEHHandlerData(Loc);
// Switch sections. Don't call SwitchSection directly, because that will
// cause the section switch to be visible in the emitted assembly.
@@ -1456,43 +1530,46 @@ void MCAsmStreamer::EmitWinEHHandlerData() {
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register) {
- MCStreamer::EmitWinCFIPushReg(Register);
+void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register, SMLoc Loc) {
+ MCStreamer::EmitWinCFIPushReg(Register, Loc);
OS << "\t.seh_pushreg " << Register;
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) {
- MCStreamer::EmitWinCFISetFrame(Register, Offset);
+void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset,
+ SMLoc Loc) {
+ MCStreamer::EmitWinCFISetFrame(Register, Offset, Loc);
OS << "\t.seh_setframe " << Register << ", " << Offset;
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size) {
- MCStreamer::EmitWinCFIAllocStack(Size);
+void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
+ MCStreamer::EmitWinCFIAllocStack(Size, Loc);
OS << "\t.seh_stackalloc " << Size;
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) {
- MCStreamer::EmitWinCFISaveReg(Register, Offset);
+void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset,
+ SMLoc Loc) {
+ MCStreamer::EmitWinCFISaveReg(Register, Offset, Loc);
OS << "\t.seh_savereg " << Register << ", " << Offset;
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) {
- MCStreamer::EmitWinCFISaveXMM(Register, Offset);
+void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
+ SMLoc Loc) {
+ MCStreamer::EmitWinCFISaveXMM(Register, Offset, Loc);
OS << "\t.seh_savexmm " << Register << ", " << Offset;
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFIPushFrame(bool Code) {
- MCStreamer::EmitWinCFIPushFrame(Code);
+void MCAsmStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) {
+ MCStreamer::EmitWinCFIPushFrame(Code, Loc);
OS << "\t.seh_pushframe";
if (Code)
@@ -1500,8 +1577,8 @@ void MCAsmStreamer::EmitWinCFIPushFrame(bool Code) {
EmitEOL();
}
-void MCAsmStreamer::EmitWinCFIEndProlog() {
- MCStreamer::EmitWinCFIEndProlog();
+void MCAsmStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
+ MCStreamer::EmitWinCFIEndProlog(Loc);
OS << "\t.seh_endprologue";
EmitEOL();
@@ -1583,8 +1660,8 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
}
}
OS << "]";
- // If we are not going to add fixup or schedul comments after this point then
- // we have to end the current comment line with "\n".
+ // If we are not going to add fixup or schedule comments after this point
+ // then we have to end the current comment line with "\n".
if (Fixups.size() || !PrintSchedInfo)
OS << "\n";
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index eaf6f19326eb..01d165944bec 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -68,6 +68,10 @@ STATISTIC(FragmentLayouts, "Number of fragment layouts");
STATISTIC(ObjectBytes, "Number of emitted object file bytes");
STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps");
STATISTIC(RelaxedInstructions, "Number of relaxed instructions");
+STATISTIC(PaddingFragmentsRelaxations,
+ "Number of Padding Fragments relaxations");
+STATISTIC(PaddingFragmentsBytes,
+ "Total size of all padding from adding Fragments");
} // end namespace stats
} // end anonymous namespace
@@ -84,7 +88,7 @@ MCAssembler::MCAssembler(MCContext &Context, MCAsmBackend &Backend,
: Context(Context), Backend(Backend), Emitter(Emitter), Writer(Writer),
BundleAlignSize(0), RelaxAll(false), SubsectionsViaSymbols(false),
IncrementalLinkerCompatible(false), ELFHeaderEFlags(0) {
- VersionMinInfo.Major = 0; // Major version == 0 for "none specified"
+ VersionInfo.Major = 0; // Major version == 0 for "none specified"
}
MCAssembler::~MCAssembler() = default;
@@ -103,7 +107,7 @@ void MCAssembler::reset() {
IncrementalLinkerCompatible = false;
ELFHeaderEFlags = 0;
LOHContainer.reset();
- VersionMinInfo.Major = 0;
+ VersionInfo.Major = 0;
// reset objects owned by us
getBackend().reset();
@@ -283,7 +287,10 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
case MCFragment::FT_LEB:
return cast<MCLEBFragment>(F).getContents().size();
- case MCFragment::FT_SafeSEH:
+ case MCFragment::FT_Padding:
+ return cast<MCPaddingFragment>(F).getSize();
+
+ case MCFragment::FT_SymbolId:
return 4;
case MCFragment::FT_Align: {
@@ -549,8 +556,15 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
break;
}
- case MCFragment::FT_SafeSEH: {
- const MCSafeSEHFragment &SF = cast<MCSafeSEHFragment>(F);
+ case MCFragment::FT_Padding: {
+ if (!Asm.getBackend().writeNopData(FragmentSize, OW))
+ report_fatal_error("unable to write nop sequence of " +
+ Twine(FragmentSize) + " bytes");
+ break;
+ }
+
+ case MCFragment::FT_SymbolId: {
+ const MCSymbolIdFragment &SF = cast<MCSymbolIdFragment>(F);
OW->write32(SF.getSymbol()->getIndex());
break;
}
@@ -822,6 +836,19 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
return true;
}
+bool MCAssembler::relaxPaddingFragment(MCAsmLayout &Layout,
+ MCPaddingFragment &PF) {
+ uint64_t OldSize = PF.getSize();
+ if (!getBackend().relaxFragment(&PF, Layout))
+ return false;
+ uint64_t NewSize = PF.getSize();
+
+ ++stats::PaddingFragmentsRelaxations;
+ stats::PaddingFragmentsBytes += NewSize;
+ stats::PaddingFragmentsBytes -= OldSize;
+ return true;
+}
+
bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) {
uint64_t OldSize = LF.getContents().size();
int64_t Value;
@@ -916,6 +943,9 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) {
case MCFragment::FT_LEB:
RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(I));
break;
+ case MCFragment::FT_Padding:
+ RelaxedFrag = relaxPaddingFragment(Layout, *cast<MCPaddingFragment>(I));
+ break;
case MCFragment::FT_CVInlineLines:
RelaxedFrag =
relaxCVInlineLineTable(Layout, *cast<MCCVInlineLineTableFragment>(I));
diff --git a/lib/MC/MCCodePadder.cpp b/lib/MC/MCCodePadder.cpp
new file mode 100644
index 000000000000..57547814e595
--- /dev/null
+++ b/lib/MC/MCCodePadder.cpp
@@ -0,0 +1,371 @@
+//===- MCCodePadder.cpp - Target MC Code Padder ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmLayout.h"
+#include "llvm/MC/MCCodePadder.h"
+#include "llvm/MC/MCObjectStreamer.h"
+#include <algorithm>
+#include <limits>
+#include <numeric>
+
+using namespace llvm;
+
+//---------------------------------------------------------------------------
+// MCCodePadder
+//
+
+MCCodePadder::~MCCodePadder() {
+ for (auto *Policy : CodePaddingPolicies)
+ delete Policy;
+}
+
+bool MCCodePadder::addPolicy(MCCodePaddingPolicy *Policy) {
+ assert(Policy && "Policy must be valid");
+ return CodePaddingPolicies.insert(Policy).second;
+}
+
+void MCCodePadder::handleBasicBlockStart(MCObjectStreamer *OS,
+ const MCCodePaddingContext &Context) {
+ assert(OS != nullptr && "OS must be valid");
+ assert(this->OS == nullptr && "Still handling another basic block");
+ this->OS = OS;
+
+ ArePoliciesActive = usePoliciesForBasicBlock(Context);
+
+ bool InsertionPoint = basicBlockRequiresInsertionPoint(Context);
+ assert((!InsertionPoint ||
+ OS->getCurrentFragment()->getKind() != MCFragment::FT_Align) &&
+ "Cannot insert padding nops right after an alignment fragment as it "
+ "will ruin the alignment");
+
+ uint64_t PoliciesMask = MCPaddingFragment::PFK_None;
+ if (ArePoliciesActive) {
+ PoliciesMask = std::accumulate(
+ CodePaddingPolicies.begin(), CodePaddingPolicies.end(),
+ MCPaddingFragment::PFK_None,
+ [&Context](uint64_t Mask,
+ const MCCodePaddingPolicy *Policy) -> uint64_t {
+ return Policy->basicBlockRequiresPaddingFragment(Context)
+ ? (Mask | Policy->getKindMask())
+ : Mask;
+ });
+ }
+
+ if (InsertionPoint || PoliciesMask != MCPaddingFragment::PFK_None) {
+ MCPaddingFragment *PaddingFragment = OS->getOrCreatePaddingFragment();
+ if (InsertionPoint)
+ PaddingFragment->setAsInsertionPoint();
+ PaddingFragment->setPaddingPoliciesMask(
+ PaddingFragment->getPaddingPoliciesMask() | PoliciesMask);
+ }
+}
+
+void MCCodePadder::handleBasicBlockEnd(const MCCodePaddingContext &Context) {
+ assert(this->OS != nullptr && "Not handling a basic block");
+ OS = nullptr;
+}
+
+void MCCodePadder::handleInstructionBegin(const MCInst &Inst) {
+ if (!OS)
+ return; // instruction was emitted outside a function
+
+ assert(CurrHandledInstFragment == nullptr && "Can't start handling an "
+ "instruction while still "
+ "handling another instruction");
+
+ bool InsertionPoint = instructionRequiresInsertionPoint(Inst);
+ assert((!InsertionPoint ||
+ OS->getCurrentFragment()->getKind() != MCFragment::FT_Align) &&
+ "Cannot insert padding nops right after an alignment fragment as it "
+ "will ruin the alignment");
+
+ uint64_t PoliciesMask = MCPaddingFragment::PFK_None;
+ if (ArePoliciesActive) {
+ PoliciesMask = std::accumulate(
+ CodePaddingPolicies.begin(), CodePaddingPolicies.end(),
+ MCPaddingFragment::PFK_None,
+ [&Inst](uint64_t Mask, const MCCodePaddingPolicy *Policy) -> uint64_t {
+ return Policy->instructionRequiresPaddingFragment(Inst)
+ ? (Mask | Policy->getKindMask())
+ : Mask;
+ });
+ }
+ MCFragment *CurrFragment = OS->getCurrentFragment();
+ // CurrFragment can be a previously created MCPaddingFragment. If so, let's
+ // update it with the information we have, such as the instruction that it
+ // should point to.
+ bool needToUpdateCurrFragment =
+ CurrFragment != nullptr &&
+ CurrFragment->getKind() == MCFragment::FT_Padding;
+ if (InsertionPoint || PoliciesMask != MCPaddingFragment::PFK_None ||
+ needToUpdateCurrFragment) {
+ // temporarily holding the fragment as CurrHandledInstFragment, to be
+ // updated after the instruction will be written
+ CurrHandledInstFragment = OS->getOrCreatePaddingFragment();
+ if (InsertionPoint)
+ CurrHandledInstFragment->setAsInsertionPoint();
+ CurrHandledInstFragment->setPaddingPoliciesMask(
+ CurrHandledInstFragment->getPaddingPoliciesMask() | PoliciesMask);
+ }
+}
+
+void MCCodePadder::handleInstructionEnd(const MCInst &Inst) {
+ if (!OS)
+ return; // instruction was emitted outside a function
+ if (CurrHandledInstFragment == nullptr)
+ return;
+
+ MCFragment *InstFragment = OS->getCurrentFragment();
+ if (MCDataFragment *InstDataFragment =
+ dyn_cast_or_null<MCDataFragment>(InstFragment))
+ // Inst is a fixed size instruction and was encoded into a MCDataFragment.
+ // Let the fragment hold it and its size. Its size is the current size of
+ // the data fragment, as the padding fragment was inserted right before it
+ // and nothing was written yet except Inst
+ CurrHandledInstFragment->setInstAndInstSize(
+ Inst, InstDataFragment->getContents().size());
+ else if (MCRelaxableFragment *InstRelaxableFragment =
+ dyn_cast_or_null<MCRelaxableFragment>(InstFragment))
+ // Inst may be relaxed and its size may vary.
+ // Let the fragment hold the instruction and the MCRelaxableFragment
+ // that's holding it.
+ CurrHandledInstFragment->setInstAndInstFragment(Inst,
+ InstRelaxableFragment);
+ else
+ llvm_unreachable("After encoding an instruction current fragment must be "
+ "either a MCDataFragment or a MCRelaxableFragment");
+
+ CurrHandledInstFragment = nullptr;
+}
+
+MCPFRange &MCCodePadder::getJurisdiction(MCPaddingFragment *Fragment,
+ MCAsmLayout &Layout) {
+ auto JurisdictionLocation = FragmentToJurisdiction.find(Fragment);
+ if (JurisdictionLocation != FragmentToJurisdiction.end())
+ return JurisdictionLocation->second;
+
+ MCPFRange Jurisdiction;
+
+ // Forward scanning the fragments in this section, starting from the given
+ // fragments, and adding relevant MCPaddingFragments to the Jurisdiction
+ for (MCFragment *CurrFragment = Fragment; CurrFragment != nullptr;
+ CurrFragment = CurrFragment->getNextNode()) {
+
+ MCPaddingFragment *CurrPaddingFragment =
+ dyn_cast<MCPaddingFragment>(CurrFragment);
+ if (CurrPaddingFragment == nullptr)
+ continue;
+
+ if (CurrPaddingFragment != Fragment &&
+ CurrPaddingFragment->isInsertionPoint())
+ // Found next insertion point Fragment. From now on it's its jurisdiction.
+ break;
+ for (const auto *Policy : CodePaddingPolicies) {
+ if (CurrPaddingFragment->hasPaddingPolicy(Policy->getKindMask())) {
+ Jurisdiction.push_back(CurrPaddingFragment);
+ break;
+ }
+ }
+ }
+
+ auto InsertionResult =
+ FragmentToJurisdiction.insert(std::make_pair(Fragment, Jurisdiction));
+ assert(InsertionResult.second &&
+ "Insertion to FragmentToJurisdiction failed");
+ return InsertionResult.first->second;
+}
+
+uint64_t MCCodePadder::getMaxWindowSize(MCPaddingFragment *Fragment,
+ MCAsmLayout &Layout) {
+ auto MaxFragmentSizeLocation = FragmentToMaxWindowSize.find(Fragment);
+ if (MaxFragmentSizeLocation != FragmentToMaxWindowSize.end())
+ return MaxFragmentSizeLocation->second;
+
+ MCPFRange &Jurisdiction = getJurisdiction(Fragment, Layout);
+ uint64_t JurisdictionMask = MCPaddingFragment::PFK_None;
+ for (const auto *Protege : Jurisdiction)
+ JurisdictionMask |= Protege->getPaddingPoliciesMask();
+
+ uint64_t MaxFragmentSize = UINT64_C(0);
+ for (const auto *Policy : CodePaddingPolicies)
+ if ((JurisdictionMask & Policy->getKindMask()) !=
+ MCPaddingFragment::PFK_None)
+ MaxFragmentSize = std::max(MaxFragmentSize, Policy->getWindowSize());
+
+ auto InsertionResult =
+ FragmentToMaxWindowSize.insert(std::make_pair(Fragment, MaxFragmentSize));
+ assert(InsertionResult.second &&
+ "Insertion to FragmentToMaxWindowSize failed");
+ return InsertionResult.first->second;
+}
+
+bool MCCodePadder::relaxFragment(MCPaddingFragment *Fragment,
+ MCAsmLayout &Layout) {
+ if (!Fragment->isInsertionPoint())
+ return false;
+ uint64_t OldSize = Fragment->getSize();
+
+ uint64_t MaxWindowSize = getMaxWindowSize(Fragment, Layout);
+ if (MaxWindowSize == UINT64_C(0))
+ return false;
+ assert(isPowerOf2_64(MaxWindowSize) &&
+ "MaxWindowSize must be an integer power of 2");
+ uint64_t SectionAlignment = Fragment->getParent()->getAlignment();
+ assert(isPowerOf2_64(SectionAlignment) &&
+ "SectionAlignment must be an integer power of 2");
+
+ MCPFRange &Jurisdiction = getJurisdiction(Fragment, Layout);
+ uint64_t OptimalSize = UINT64_C(0);
+ double OptimalWeight = std::numeric_limits<double>::max();
+ uint64_t MaxFragmentSize = MaxWindowSize - UINT16_C(1);
+ for (uint64_t Size = UINT64_C(0); Size <= MaxFragmentSize; ++Size) {
+ Fragment->setSize(Size);
+ Layout.invalidateFragmentsFrom(Fragment);
+ double SizeWeight = 0.0;
+ // The section is guaranteed to be aligned to SectionAlignment, but that
+ // doesn't guarantee the exact section offset w.r.t. the policies window
+ // size.
+ // As a concrete example, the section could be aligned to 16B, but a
+ // policy's window size can be 32B. That means that the section actual start
+ // address can either be 0mod32 or 16mod32. The said policy will act
+ // differently for each case, so we need to take both into consideration.
+ for (uint64_t Offset = UINT64_C(0); Offset < MaxWindowSize;
+ Offset += SectionAlignment) {
+ double OffsetWeight = std::accumulate(
+ CodePaddingPolicies.begin(), CodePaddingPolicies.end(), 0.0,
+ [&Jurisdiction, &Offset, &Layout](
+ double Weight, const MCCodePaddingPolicy *Policy) -> double {
+ double PolicyWeight =
+ Policy->computeRangePenaltyWeight(Jurisdiction, Offset, Layout);
+ assert(PolicyWeight >= 0.0 && "A penalty weight must be positive");
+ return Weight + PolicyWeight;
+ });
+ SizeWeight = std::max(SizeWeight, OffsetWeight);
+ }
+ if (SizeWeight < OptimalWeight) {
+ OptimalWeight = SizeWeight;
+ OptimalSize = Size;
+ }
+ if (OptimalWeight == 0.0)
+ break;
+ }
+
+ Fragment->setSize(OptimalSize);
+ Layout.invalidateFragmentsFrom(Fragment);
+ return OldSize != OptimalSize;
+}
+
+//---------------------------------------------------------------------------
+// MCCodePaddingPolicy
+//
+
+uint64_t MCCodePaddingPolicy::getNextFragmentOffset(const MCFragment *Fragment,
+ const MCAsmLayout &Layout) {
+ assert(Fragment != nullptr && "Fragment cannot be null");
+ MCFragment const *NextFragment = Fragment->getNextNode();
+ return NextFragment == nullptr
+ ? Layout.getSectionAddressSize(Fragment->getParent())
+ : Layout.getFragmentOffset(NextFragment);
+}
+
+uint64_t
+MCCodePaddingPolicy::getFragmentInstByte(const MCPaddingFragment *Fragment,
+ MCAsmLayout &Layout) const {
+ uint64_t InstByte = getNextFragmentOffset(Fragment, Layout);
+ if (InstByteIsLastByte)
+ InstByte += Fragment->getInstSize() - UINT64_C(1);
+ return InstByte;
+}
+
+uint64_t
+MCCodePaddingPolicy::computeWindowEndAddress(const MCPaddingFragment *Fragment,
+ uint64_t Offset,
+ MCAsmLayout &Layout) const {
+ uint64_t InstByte = getFragmentInstByte(Fragment, Layout);
+ return alignTo(InstByte + UINT64_C(1) + Offset, WindowSize) - Offset;
+}
+
+double MCCodePaddingPolicy::computeRangePenaltyWeight(
+ const MCPFRange &Range, uint64_t Offset, MCAsmLayout &Layout) const {
+
+ SmallVector<MCPFRange, 8> Windows;
+ SmallVector<MCPFRange, 8>::iterator CurrWindowLocation = Windows.end();
+ for (const MCPaddingFragment *Fragment : Range) {
+ if (!Fragment->hasPaddingPolicy(getKindMask()))
+ continue;
+ uint64_t FragmentWindowEndAddress =
+ computeWindowEndAddress(Fragment, Offset, Layout);
+ if (CurrWindowLocation == Windows.end() ||
+ FragmentWindowEndAddress !=
+ computeWindowEndAddress(*CurrWindowLocation->begin(), Offset,
+ Layout)) {
+ // next window is starting
+ Windows.push_back(MCPFRange());
+ CurrWindowLocation = Windows.end() - 1;
+ }
+ CurrWindowLocation->push_back(Fragment);
+ }
+
+ if (Windows.empty())
+ return 0.0;
+
+ double RangeWeight = 0.0;
+ SmallVector<MCPFRange, 8>::iterator I = Windows.begin();
+ RangeWeight += computeFirstWindowPenaltyWeight(*I, Offset, Layout);
+ ++I;
+ RangeWeight += std::accumulate(
+ I, Windows.end(), 0.0,
+ [this, &Layout, &Offset](double Weight, MCPFRange &Window) -> double {
+ return Weight += computeWindowPenaltyWeight(Window, Offset, Layout);
+ });
+ return RangeWeight;
+}
+
+double MCCodePaddingPolicy::computeFirstWindowPenaltyWeight(
+ const MCPFRange &Window, uint64_t Offset, MCAsmLayout &Layout) const {
+ if (Window.empty())
+ return 0.0;
+ uint64_t WindowEndAddress =
+ computeWindowEndAddress(*Window.begin(), Offset, Layout);
+
+ MCPFRange FullWindowFirstPart; // will hold all the fragments that are in the
+ // same window as the fragments in the given
+ // window but their penalty weight should not
+ // be added
+ for (const MCFragment *Fragment = (*Window.begin())->getPrevNode();
+ Fragment != nullptr; Fragment = Fragment->getPrevNode()) {
+ const MCPaddingFragment *PaddingNopFragment =
+ dyn_cast<MCPaddingFragment>(Fragment);
+ if (PaddingNopFragment == nullptr ||
+ !PaddingNopFragment->hasPaddingPolicy(getKindMask()))
+ continue;
+ if (WindowEndAddress !=
+ computeWindowEndAddress(PaddingNopFragment, Offset, Layout))
+ break;
+
+ FullWindowFirstPart.push_back(PaddingNopFragment);
+ }
+
+ std::reverse(FullWindowFirstPart.begin(), FullWindowFirstPart.end());
+ double FullWindowFirstPartWeight =
+ computeWindowPenaltyWeight(FullWindowFirstPart, Offset, Layout);
+
+ MCPFRange FullWindow(
+ FullWindowFirstPart); // will hold all the fragments that are in the
+ // same window as the fragments in the given
+ // window, whether their weight should be added
+ // or not
+ FullWindow.append(Window.begin(), Window.end());
+ double FullWindowWeight =
+ computeWindowPenaltyWeight(FullWindow, Offset, Layout);
+
+ assert(FullWindowWeight >= FullWindowFirstPartWeight &&
+ "More fragments necessarily means bigger weight");
+ return FullWindowWeight - FullWindowFirstPartWeight;
+}
diff --git a/lib/MC/MCCodeView.cpp b/lib/MC/MCCodeView.cpp
index 92b1e12da552..82b81ccc24da 100644
--- a/lib/MC/MCCodeView.cpp
+++ b/lib/MC/MCCodeView.cpp
@@ -13,7 +13,7 @@
#include "llvm/MC/MCCodeView.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
@@ -39,29 +39,40 @@ CodeViewContext::~CodeViewContext() {
/// for it.
bool CodeViewContext::isValidFileNumber(unsigned FileNumber) const {
unsigned Idx = FileNumber - 1;
- if (Idx < Filenames.size())
- return !Filenames[Idx].empty();
+ if (Idx < Files.size())
+ return Files[Idx].Assigned;
return false;
}
-bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename) {
+bool CodeViewContext::addFile(MCStreamer &OS, unsigned FileNumber,
+ StringRef Filename,
+ ArrayRef<uint8_t> ChecksumBytes,
+ uint8_t ChecksumKind) {
assert(FileNumber > 0);
- Filename = addToStringTable(Filename);
+ auto FilenameOffset = addToStringTable(Filename);
+ Filename = FilenameOffset.first;
unsigned Idx = FileNumber - 1;
- if (Idx >= Filenames.size())
- Filenames.resize(Idx + 1);
+ if (Idx >= Files.size())
+ Files.resize(Idx + 1);
if (Filename.empty())
Filename = "<stdin>";
- if (!Filenames[Idx].empty())
+ if (Files[Idx].Assigned)
return false;
- // FIXME: We should store the string table offset of the filename, rather than
- // the filename itself for efficiency.
- Filename = addToStringTable(Filename);
+ FilenameOffset = addToStringTable(Filename);
+ Filename = FilenameOffset.first;
+ unsigned Offset = FilenameOffset.second;
+
+ auto ChecksumOffsetSymbol =
+ OS.getContext().createTempSymbol("checksum_offset", false);
+ Files[Idx].StringTableOffset = Offset;
+ Files[Idx].ChecksumTableOffset = ChecksumOffsetSymbol;
+ Files[Idx].Assigned = true;
+ Files[Idx].Checksum = ChecksumBytes;
+ Files[Idx].ChecksumKind = ChecksumKind;
- Filenames[Idx] = Filename;
return true;
}
@@ -118,17 +129,18 @@ MCDataFragment *CodeViewContext::getStringTableFragment() {
return StrTabFragment;
}
-StringRef CodeViewContext::addToStringTable(StringRef S) {
+std::pair<StringRef, unsigned> CodeViewContext::addToStringTable(StringRef S) {
SmallVectorImpl<char> &Contents = getStringTableFragment()->getContents();
auto Insertion =
StringTable.insert(std::make_pair(S, unsigned(Contents.size())));
// Return the string from the table, since it is stable.
- S = Insertion.first->first();
+ std::pair<StringRef, unsigned> Ret =
+ std::make_pair(Insertion.first->first(), Insertion.first->second);
if (Insertion.second) {
// The string map key is always null terminated.
- Contents.append(S.begin(), S.end() + 1);
+ Contents.append(Ret.first.begin(), Ret.first.end() + 1);
}
- return S;
+ return Ret;
}
unsigned CodeViewContext::getStringTableOffset(StringRef S) {
@@ -165,7 +177,7 @@ void CodeViewContext::emitStringTable(MCObjectStreamer &OS) {
void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
// Do nothing if there are no file checksums. Microsoft's linker rejects empty
// CodeView substreams.
- if (Filenames.empty())
+ if (Files.empty())
return;
MCContext &Ctx = OS.getContext();
@@ -176,17 +188,63 @@ void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4);
OS.EmitLabel(FileBegin);
+ unsigned CurrentOffset = 0;
+
// Emit an array of FileChecksum entries. We index into this table using the
- // user-provided file number. Each entry is currently 8 bytes, as we don't
- // emit checksums.
- for (StringRef Filename : Filenames) {
- OS.EmitIntValue(getStringTableOffset(Filename), 4);
- // Zero the next two fields and align back to 4 bytes. This indicates that
- // no checksum is present.
- OS.EmitIntValue(0, 4);
+ // user-provided file number. Each entry may be a variable number of bytes
+ // determined by the checksum kind and size.
+ for (auto File : Files) {
+ OS.EmitAssignment(File.ChecksumTableOffset,
+ MCConstantExpr::create(CurrentOffset, Ctx));
+ CurrentOffset += 4; // String table offset.
+ if (!File.ChecksumKind) {
+ CurrentOffset +=
+ 4; // One byte each for checksum size and kind, then align to 4 bytes.
+ } else {
+ CurrentOffset += 2; // One byte each for checksum size and kind.
+ CurrentOffset += File.Checksum.size();
+ CurrentOffset = alignTo(CurrentOffset, 4);
+ }
+
+ OS.EmitIntValue(File.StringTableOffset, 4);
+
+ if (!File.ChecksumKind) {
+ // There is no checksum. Therefore zero the next two fields and align
+ // back to 4 bytes.
+ OS.EmitIntValue(0, 4);
+ continue;
+ }
+ OS.EmitIntValue(static_cast<uint8_t>(File.Checksum.size()), 1);
+ OS.EmitIntValue(File.ChecksumKind, 1);
+ OS.EmitBytes(toStringRef(File.Checksum));
+ OS.EmitValueToAlignment(4);
}
OS.EmitLabel(FileEnd);
+
+ ChecksumOffsetsAssigned = true;
+}
+
+// Output checksum table offset of the given file number. It is possible that
+// not all files have been registered yet, and so the offset cannot be
+// calculated. In this case a symbol representing the offset is emitted, and
+// the value of this symbol will be fixed up at a later time.
+void CodeViewContext::emitFileChecksumOffset(MCObjectStreamer &OS,
+ unsigned FileNo) {
+ unsigned Idx = FileNo - 1;
+
+ if (Idx >= Files.size())
+ Files.resize(Idx + 1);
+
+ if (ChecksumOffsetsAssigned) {
+ OS.EmitSymbolValue(Files[Idx].ChecksumTableOffset, 4);
+ return;
+ }
+
+ const MCSymbolRefExpr *SRE =
+ MCSymbolRefExpr::create(Files[Idx].ChecksumTableOffset, OS.getContext());
+
+ OS.EmitValueImpl(SRE, 4);
}
void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
@@ -219,9 +277,12 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
return Loc.getFileNum() != CurFileNum;
});
unsigned EntryCount = FileSegEnd - I;
- OS.AddComment("Segment for file '" + Twine(Filenames[CurFileNum - 1]) +
- "' begins");
- OS.EmitIntValue(8 * (CurFileNum - 1), 4);
+ OS.AddComment(
+ "Segment for file '" +
+ Twine(getStringTableFragment()
+ ->getContents()[Files[CurFileNum - 1].StringTableOffset]) +
+ "' begins");
+ OS.EmitCVFileChecksumOffsetDirective(CurFileNum);
OS.EmitIntValue(EntryCount, 4);
uint32_t SegmentSize = 12;
SegmentSize += 8 * EntryCount;
@@ -401,9 +462,10 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
HaveOpenRange = true;
if (CurSourceLoc.File != LastSourceLoc.File) {
- // File ids are 1 based, and each file checksum table entry is 8 bytes
- // long. See emitFileChecksums above.
- unsigned FileOffset = 8 * (CurSourceLoc.File - 1);
+ unsigned FileOffset = static_cast<const MCConstantExpr *>(
+ Files[CurSourceLoc.File - 1]
+ .ChecksumTableOffset->getVariableValue())
+ ->getValue();
compressAnnotation(BinaryAnnotationsOpCode::ChangeFile, Buffer);
compressAnnotation(FileOffset, Buffer);
}
diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp
index 48ee84edb096..5c25e902bbe7 100644
--- a/lib/MC/MCContext.cpp
+++ b/lib/MC/MCContext.cpp
@@ -486,53 +486,17 @@ MCSectionCOFF *MCContext::getAssociativeCOFFSection(MCSectionCOFF *Sec,
"", 0, UniqueID);
}
-void MCContext::renameWasmSection(MCSectionWasm *Section, StringRef Name) {
- StringRef GroupName;
- assert(!Section->getGroup() && "not yet implemented");
-
- unsigned UniqueID = Section->getUniqueID();
- WasmUniquingMap.erase(
- WasmSectionKey{Section->getSectionName(), GroupName, UniqueID});
- auto I = WasmUniquingMap.insert(std::make_pair(
- WasmSectionKey{Name, GroupName, UniqueID},
- Section))
- .first;
- StringRef CachedName = I->first.SectionName;
- const_cast<MCSectionWasm *>(Section)->setSectionName(CachedName);
-}
-
-MCSectionWasm *MCContext::createWasmRelSection(const Twine &Name, unsigned Type,
- unsigned Flags,
- const MCSymbolWasm *Group) {
- StringMap<bool>::iterator I;
- bool Inserted;
- std::tie(I, Inserted) =
- RelSecNames.insert(std::make_pair(Name.str(), true));
-
- return new (WasmAllocator.Allocate())
- MCSectionWasm(I->getKey(), Type, Flags, SectionKind::getReadOnly(),
- Group, ~0, nullptr);
-}
-
-MCSectionWasm *MCContext::getWasmNamedSection(const Twine &Prefix,
- const Twine &Suffix, unsigned Type,
- unsigned Flags) {
- return getWasmSection(Prefix + "." + Suffix, Type, Flags, Suffix);
-}
-
-MCSectionWasm *MCContext::getWasmSection(const Twine &Section, unsigned Type,
- unsigned Flags,
+MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind K,
const Twine &Group, unsigned UniqueID,
const char *BeginSymName) {
MCSymbolWasm *GroupSym = nullptr;
if (!Group.isTriviallyEmpty() && !Group.str().empty())
GroupSym = cast<MCSymbolWasm>(getOrCreateSymbol(Group));
- return getWasmSection(Section, Type, Flags, GroupSym, UniqueID, BeginSymName);
+ return getWasmSection(Section, K, GroupSym, UniqueID, BeginSymName);
}
-MCSectionWasm *MCContext::getWasmSection(const Twine &Section, unsigned Type,
- unsigned Flags,
+MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind Kind,
const MCSymbolWasm *GroupSym,
unsigned UniqueID,
const char *BeginSymName) {
@@ -548,14 +512,12 @@ MCSectionWasm *MCContext::getWasmSection(const Twine &Section, unsigned Type,
StringRef CachedName = Entry.first.SectionName;
- SectionKind Kind = SectionKind::getText();
-
MCSymbol *Begin = nullptr;
if (BeginSymName)
Begin = createTempSymbol(BeginSymName, false);
MCSectionWasm *Result = new (WasmAllocator.Allocate())
- MCSectionWasm(CachedName, Type, Flags, Kind, GroupSym, UniqueID, Begin);
+ MCSectionWasm(CachedName, Kind, GroupSym, UniqueID, Begin);
Entry.second = Result;
return Result;
}
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index a2beee32f2cb..9e5d9ff73c76 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -257,6 +257,66 @@ static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) {
OS.EmitValue(ABS, Size);
}
+static void
+emitV2FileDirTables(MCStreamer *MCOS,
+ const SmallVectorImpl<std::string> &MCDwarfDirs,
+ const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles) {
+ // First the directory table.
+ for (auto Dir : MCDwarfDirs) {
+ MCOS->EmitBytes(Dir); // The DirectoryName, and...
+ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ }
+ MCOS->EmitIntValue(0, 1); // Terminate the directory list.
+
+ // Second the file table.
+ for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
+ assert(!MCDwarfFiles[i].Name.empty());
+ MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName and...
+ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.
+ MCOS->EmitIntValue(0, 1); // Last modification timestamp (always 0).
+ MCOS->EmitIntValue(0, 1); // File size (always 0).
+ }
+ MCOS->EmitIntValue(0, 1); // Terminate the file list.
+}
+
+static void
+emitV5FileDirTables(MCStreamer *MCOS,
+ const SmallVectorImpl<std::string> &MCDwarfDirs,
+ const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles,
+ StringRef CompilationDir) {
+ // The directory format, which is just inline null-terminated strings.
+ MCOS->EmitIntValue(1, 1);
+ MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
+ MCOS->EmitULEB128IntValue(dwarf::DW_FORM_string);
+ // Then the list of directory paths. CompilationDir comes first.
+ MCOS->EmitULEB128IntValue(MCDwarfDirs.size() + 1);
+ MCOS->EmitBytes(CompilationDir);
+ MCOS->EmitBytes(StringRef("\0", 1));
+ for (auto Dir : MCDwarfDirs) {
+ MCOS->EmitBytes(Dir); // The DirectoryName, and...
+ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ }
+
+ // The file format, which is the inline null-terminated filename and a
+ // directory index. We don't track file size/timestamp so don't emit them
+ // in the v5 table.
+ // FIXME: Arrange to emit MD5 signatures for the source files.
+ MCOS->EmitIntValue(2, 1);
+ MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
+ MCOS->EmitULEB128IntValue(dwarf::DW_FORM_string);
+ MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_directory_index);
+ MCOS->EmitULEB128IntValue(dwarf::DW_FORM_udata);
+ // Then the list of file names. These start at 1 for some reason.
+ MCOS->EmitULEB128IntValue(MCDwarfFiles.size() - 1);
+ for (unsigned i = 1; i < MCDwarfFiles.size(); ++i) {
+ assert(!MCDwarfFiles[i].Name.empty());
+ MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName and...
+ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.
+ }
+}
+
std::pair<MCSymbol *, MCSymbol *>
MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
ArrayRef<char> StandardOpcodeLengths) const {
@@ -277,22 +337,41 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
emitAbsValue(*MCOS,
MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym, 4), 4);
- // Next 2 bytes is the Version, which is Dwarf 2.
- MCOS->EmitIntValue(2, 2);
+ // Next 2 bytes is the Version.
+ // FIXME: On Darwin we still default to V2.
+ unsigned LineTableVersion = context.getDwarfVersion();
+ if (context.getObjectFileInfo()->getTargetTriple().isOSDarwin())
+ LineTableVersion = 2;
+ MCOS->EmitIntValue(LineTableVersion, 2);
+
+ // Keep track of the bytes between the very start and where the header length
+ // comes out.
+ unsigned PreHeaderLengthBytes = 4 + 2;
+
+ // In v5, we get address info next.
+ if (LineTableVersion >= 5) {
+ MCOS->EmitIntValue(context.getAsmInfo()->getCodePointerSize(), 1);
+ MCOS->EmitIntValue(0, 1); // Segment selector; same as EmitGenDwarfAranges.
+ PreHeaderLengthBytes += 2;
+ }
// Create a symbol for the end of the prologue (to be set when we get there).
MCSymbol *ProEndSym = context.createTempSymbol(); // Lprologue_end
- // Length of the prologue, is the next 4 bytes. Which is the start of the
- // section to the end of the prologue. Not including the 4 bytes for the
- // total length, the 2 bytes for the version, and these 4 bytes for the
- // length of the prologue.
- emitAbsValue(
- *MCOS,
- MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, (4 + 2 + 4)), 4);
+ // Length of the prologue, is the next 4 bytes. This is actually the length
+ // from after the length word, to the end of the prologue.
+ emitAbsValue(*MCOS,
+ MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym,
+ (PreHeaderLengthBytes + 4)),
+ 4);
// Parameters of the state machine, are next.
MCOS->EmitIntValue(context.getAsmInfo()->getMinInstAlignment(), 1);
+ // maximum_operations_per_instruction
+ // For non-VLIW architectures this field is always 1.
+ // FIXME: VLIW architectures need to update this field accordingly.
+ if (LineTableVersion >= 4)
+ MCOS->EmitIntValue(1, 1);
MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1);
MCOS->EmitIntValue(Params.DWARF2LineBase, 1);
MCOS->EmitIntValue(Params.DWARF2LineRange, 1);
@@ -302,26 +381,12 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
for (char Length : StandardOpcodeLengths)
MCOS->EmitIntValue(Length, 1);
- // Put out the directory and file tables.
-
- // First the directory table.
- for (unsigned i = 0; i < MCDwarfDirs.size(); i++) {
- MCOS->EmitBytes(MCDwarfDirs[i]); // the DirectoryName
- MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string
- }
- MCOS->EmitIntValue(0, 1); // Terminate the directory list
-
- // Second the file table.
- for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
- assert(!MCDwarfFiles[i].Name.empty());
- MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName
- MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string
- // the Directory num
- MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex);
- MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0)
- MCOS->EmitIntValue(0, 1); // filesize (always 0)
- }
- MCOS->EmitIntValue(0, 1); // Terminate the file list
+ // Put out the directory and file tables. The formats vary depending on
+ // the version.
+ if (LineTableVersion >= 5)
+ emitV5FileDirTables(MCOS, MCDwarfDirs, MCDwarfFiles, CompilationDir);
+ else
+ emitV2FileDirTables(MCOS, MCDwarfDirs, MCDwarfFiles);
// This is the end of the prologue, so set the value of the symbol at the
// end of the prologue (that was used in a previous expression).
@@ -370,7 +435,8 @@ unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory,
return IterBool.first->second;
}
// Make space for this FileNumber in the MCDwarfFiles vector if needed.
- MCDwarfFiles.resize(FileNumber + 1);
+ if (FileNumber >= MCDwarfFiles.size())
+ MCDwarfFiles.resize(FileNumber + 1);
// Get the new MCDwarfFile slot for this FileNumber.
MCDwarfFile &File = MCDwarfFiles[FileNumber];
@@ -1034,10 +1100,7 @@ public:
/// Emit the unwind information in a compact way.
void EmitCompactUnwind(const MCDwarfFrameInfo &frame);
- const MCSymbol &EmitCIE(const MCSymbol *personality,
- unsigned personalityEncoding, const MCSymbol *lsda,
- bool IsSignalFrame, unsigned lsdaEncoding,
- bool IsSimple);
+ const MCSymbol &EmitCIE(const MCDwarfFrameInfo &F);
void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame,
bool LastInSection, const MCSymbol &SectionStart);
void EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
@@ -1060,8 +1123,8 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
unsigned Reg1 = Instr.getRegister();
unsigned Reg2 = Instr.getRegister2();
if (!IsEH) {
- Reg1 = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg1, true), false);
- Reg2 = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg2, true), false);
+ Reg1 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg1);
+ Reg2 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg2);
}
Streamer.EmitIntValue(dwarf::DW_CFA_register, 1);
Streamer.EmitULEB128IntValue(Reg1);
@@ -1097,7 +1160,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
case MCCFIInstruction::OpDefCfa: {
unsigned Reg = Instr.getRegister();
if (!IsEH)
- Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
+ Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);
Streamer.EmitULEB128IntValue(Reg);
CFAOffset = -Instr.getOffset();
@@ -1108,7 +1171,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
case MCCFIInstruction::OpDefCfaRegister: {
unsigned Reg = Instr.getRegister();
if (!IsEH)
- Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
+ Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1);
Streamer.EmitULEB128IntValue(Reg);
@@ -1121,7 +1184,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
unsigned Reg = Instr.getRegister();
if (!IsEH)
- Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
+ Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
int Offset = Instr.getOffset();
if (IsRelative)
@@ -1157,7 +1220,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
case MCCFIInstruction::OpRestore: {
unsigned Reg = Instr.getRegister();
if (!IsEH)
- Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
+ Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
return;
}
@@ -1273,12 +1336,7 @@ static unsigned getCIEVersion(bool IsEH, unsigned DwarfVersion) {
llvm_unreachable("Unknown version");
}
-const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality,
- unsigned personalityEncoding,
- const MCSymbol *lsda,
- bool IsSignalFrame,
- unsigned lsdaEncoding,
- bool IsSimple) {
+const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
MCContext &context = Streamer.getContext();
const MCRegisterInfo *MRI = context.getRegisterInfo();
const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
@@ -1305,12 +1363,12 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality,
SmallString<8> Augmentation;
if (IsEH) {
Augmentation += "z";
- if (personality)
+ if (Frame.Personality)
Augmentation += "P";
- if (lsda)
+ if (Frame.Lsda)
Augmentation += "L";
Augmentation += "R";
- if (IsSignalFrame)
+ if (Frame.IsSignalFrame)
Augmentation += "S";
Streamer.EmitBytes(Augmentation);
}
@@ -1331,26 +1389,29 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality,
Streamer.EmitSLEB128IntValue(getDataAlignmentFactor(Streamer));
// Return Address Register
+ unsigned RAReg = Frame.RAReg;
+ if (RAReg == static_cast<unsigned>(INT_MAX))
+ RAReg = MRI->getDwarfRegNum(MRI->getRARegister(), IsEH);
+
if (CIEVersion == 1) {
- assert(MRI->getRARegister() <= 255 &&
+ assert(RAReg <= 255 &&
"DWARF 2 encodes return_address_register in one byte");
- Streamer.EmitIntValue(MRI->getDwarfRegNum(MRI->getRARegister(), IsEH), 1);
+ Streamer.EmitIntValue(RAReg, 1);
} else {
- Streamer.EmitULEB128IntValue(
- MRI->getDwarfRegNum(MRI->getRARegister(), IsEH));
+ Streamer.EmitULEB128IntValue(RAReg);
}
// Augmentation Data Length (optional)
-
unsigned augmentationLength = 0;
if (IsEH) {
- if (personality) {
+ if (Frame.Personality) {
// Personality Encoding
augmentationLength += 1;
// Personality
- augmentationLength += getSizeForEncoding(Streamer, personalityEncoding);
+ augmentationLength +=
+ getSizeForEncoding(Streamer, Frame.PersonalityEncoding);
}
- if (lsda)
+ if (Frame.Lsda)
augmentationLength += 1;
// Encoding of the FDE pointers
augmentationLength += 1;
@@ -1358,15 +1419,15 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality,
Streamer.EmitULEB128IntValue(augmentationLength);
// Augmentation Data (optional)
- if (personality) {
+ if (Frame.Personality) {
// Personality Encoding
- emitEncodingByte(Streamer, personalityEncoding);
+ emitEncodingByte(Streamer, Frame.PersonalityEncoding);
// Personality
- EmitPersonality(Streamer, *personality, personalityEncoding);
+ EmitPersonality(Streamer, *Frame.Personality, Frame.PersonalityEncoding);
}
- if (lsda)
- emitEncodingByte(Streamer, lsdaEncoding);
+ if (Frame.Lsda)
+ emitEncodingByte(Streamer, Frame.LsdaEncoding);
// Encoding of the FDE pointers
emitEncodingByte(Streamer, MOFI->getFDEEncoding());
@@ -1375,7 +1436,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality,
// Initial Instructions
const MCAsmInfo *MAI = context.getAsmInfo();
- if (!IsSimple) {
+ if (!Frame.IsSimple) {
const std::vector<MCCFIInstruction> &Instructions =
MAI->getInitialFrameState();
EmitCFIInstructions(Instructions, nullptr);
@@ -1463,24 +1524,32 @@ namespace {
struct CIEKey {
static const CIEKey getEmptyKey() {
- return CIEKey(nullptr, 0, -1, false, false);
+ return CIEKey(nullptr, 0, -1, false, false, static_cast<unsigned>(INT_MAX));
}
static const CIEKey getTombstoneKey() {
- return CIEKey(nullptr, -1, 0, false, false);
+ return CIEKey(nullptr, -1, 0, false, false, static_cast<unsigned>(INT_MAX));
}
CIEKey(const MCSymbol *Personality, unsigned PersonalityEncoding,
- unsigned LsdaEncoding, bool IsSignalFrame, bool IsSimple)
+ unsigned LSDAEncoding, bool IsSignalFrame, bool IsSimple,
+ unsigned RAReg)
: Personality(Personality), PersonalityEncoding(PersonalityEncoding),
- LsdaEncoding(LsdaEncoding), IsSignalFrame(IsSignalFrame),
- IsSimple(IsSimple) {}
+ LsdaEncoding(LSDAEncoding), IsSignalFrame(IsSignalFrame),
+ IsSimple(IsSimple), RAReg(RAReg) {}
+
+ explicit CIEKey(const MCDwarfFrameInfo &Frame)
+ : Personality(Frame.Personality),
+ PersonalityEncoding(Frame.PersonalityEncoding),
+ LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame),
+ IsSimple(Frame.IsSimple), RAReg(Frame.RAReg) {}
const MCSymbol *Personality;
unsigned PersonalityEncoding;
unsigned LsdaEncoding;
bool IsSignalFrame;
bool IsSimple;
+ unsigned RAReg;
};
} // end anonymous namespace
@@ -1494,7 +1563,7 @@ template <> struct DenseMapInfo<CIEKey> {
static unsigned getHashValue(const CIEKey &Key) {
return static_cast<unsigned>(
hash_combine(Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding,
- Key.IsSignalFrame, Key.IsSimple));
+ Key.IsSignalFrame, Key.IsSimple, Key.RAReg));
}
static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) {
@@ -1502,7 +1571,8 @@ template <> struct DenseMapInfo<CIEKey> {
LHS.PersonalityEncoding == RHS.PersonalityEncoding &&
LHS.LsdaEncoding == RHS.LsdaEncoding &&
LHS.IsSignalFrame == RHS.IsSignalFrame &&
- LHS.IsSimple == RHS.IsSimple;
+ LHS.IsSimple == RHS.IsSimple &&
+ LHS.RAReg == RHS.RAReg;
}
};
@@ -1559,13 +1629,10 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
// of by the compact unwind encoding.
continue;
- CIEKey Key(Frame.Personality, Frame.PersonalityEncoding,
- Frame.LsdaEncoding, Frame.IsSignalFrame, Frame.IsSimple);
+ CIEKey Key(Frame);
const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
if (!CIEStart)
- CIEStart = &Emitter.EmitCIE(Frame.Personality, Frame.PersonalityEncoding,
- Frame.Lsda, Frame.IsSignalFrame,
- Frame.LsdaEncoding, Frame.IsSimple);
+ CIEStart = &Emitter.EmitCIE(Frame);
Emitter.EmitFDE(*CIEStart, Frame, I == E, *SectionStart);
}
diff --git a/lib/MC/MCELFObjectTargetWriter.cpp b/lib/MC/MCELFObjectTargetWriter.cpp
index 68fb5e7cbb3d..483ee94c0db1 100644
--- a/lib/MC/MCELFObjectTargetWriter.cpp
+++ b/lib/MC/MCELFObjectTargetWriter.cpp
@@ -11,15 +11,11 @@
using namespace llvm;
-MCELFObjectTargetWriter::MCELFObjectTargetWriter(bool Is64Bit_,
- uint8_t OSABI_,
+MCELFObjectTargetWriter::MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_,
uint16_t EMachine_,
- bool HasRelocationAddend_,
- bool IsN64_)
- : OSABI(OSABI_), EMachine(EMachine_),
- HasRelocationAddend(HasRelocationAddend_), Is64Bit(Is64Bit_),
- IsN64(IsN64_){
-}
+ bool HasRelocationAddend_)
+ : OSABI(OSABI_), EMachine(EMachine_),
+ HasRelocationAddend(HasRelocationAddend_), Is64Bit(Is64Bit_) {}
bool MCELFObjectTargetWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
unsigned Type) const {
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp
index 50c1f6e79f8a..366125962a5e 100644
--- a/lib/MC/MCELFStreamer.cpp
+++ b/lib/MC/MCELFStreamer.cpp
@@ -39,6 +39,12 @@
using namespace llvm;
+MCELFStreamer::MCELFStreamer(MCContext &Context,
+ std::unique_ptr<MCAsmBackend> TAB,
+ raw_pwrite_stream &OS,
+ std::unique_ptr<MCCodeEmitter> Emitter)
+ : MCObjectStreamer(Context, std::move(TAB), OS, std::move(Emitter)) {}
+
bool MCELFStreamer::isBundleLocked() const {
return getCurrentSectionOnly()->isBundleLocked();
}
@@ -62,12 +68,13 @@ void MCELFStreamer::mergeFragment(MCDataFragment *DF,
if (RequiredBundlePadding > 0) {
SmallString<256> Code;
raw_svector_ostream VecOS(Code);
- MCObjectWriter *OW = Assembler.getBackend().createObjectWriter(VecOS);
+ {
+ auto OW = Assembler.getBackend().createObjectWriter(VecOS);
- EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
+ EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
- Assembler.writeFragmentPadding(*EF, FSize, OW);
- delete OW;
+ Assembler.writeFragmentPadding(*EF, FSize, OW.get());
+ }
DF->getContents().append(Code.begin(), Code.end());
}
@@ -638,10 +645,13 @@ void MCELFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
llvm_unreachable("ELF doesn't support this directive");
}
-MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB,
- raw_pwrite_stream &OS, MCCodeEmitter *CE,
+MCStreamer *llvm::createELFStreamer(MCContext &Context,
+ std::unique_ptr<MCAsmBackend> &&MAB,
+ raw_pwrite_stream &OS,
+ std::unique_ptr<MCCodeEmitter> &&CE,
bool RelaxAll) {
- MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, CE);
+ MCELFStreamer *S =
+ new MCELFStreamer(Context, std::move(MAB), OS, std::move(CE));
if (RelaxAll)
S->getAssembler().setRelaxAll(true);
return S;
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp
index 38a8af49c194..f8fff4414f49 100644
--- a/lib/MC/MCExpr.cpp
+++ b/lib/MC/MCExpr.cpp
@@ -224,6 +224,13 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_ARM_SBREL: return "sbrel";
case VK_ARM_TLSLDO: return "tlsldo";
case VK_ARM_TLSDESCSEQ: return "tlsdescseq";
+ case VK_AVR_NONE: return "none";
+ case VK_AVR_LO8: return "lo8";
+ case VK_AVR_HI8: return "hi8";
+ case VK_AVR_HLO8: return "hlo8";
+ case VK_AVR_DIFF8: return "diff8";
+ case VK_AVR_DIFF16: return "diff16";
+ case VK_AVR_DIFF32: return "diff32";
case VK_PPC_LO: return "l";
case VK_PPC_HI: return "h";
case VK_PPC_HA: return "ha";
@@ -389,6 +396,9 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("prel31", VK_ARM_PREL31)
.Case("sbrel", VK_ARM_SBREL)
.Case("tlsldo", VK_ARM_TLSLDO)
+ .Case("lo8", VK_AVR_LO8)
+ .Case("hi8", VK_AVR_HI8)
+ .Case("hlo8", VK_AVR_HLO8)
.Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)
.Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI)
.Case("rel32@lo", VK_AMDGPU_REL32_LO)
diff --git a/lib/MC/MCFragment.cpp b/lib/MC/MCFragment.cpp
index 6e0249377a89..1aed50aaeb77 100644
--- a/lib/MC/MCFragment.cpp
+++ b/lib/MC/MCFragment.cpp
@@ -80,7 +80,7 @@ uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const {
return F->Offset;
}
-// Simple getSymbolOffset helper for the non-varibale case.
+// Simple getSymbolOffset helper for the non-variable case.
static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S,
bool ReportError, uint64_t &Val) {
if (!S.getFragment()) {
@@ -278,8 +278,11 @@ void MCFragment::destroy() {
case FT_LEB:
delete cast<MCLEBFragment>(this);
return;
- case FT_SafeSEH:
- delete cast<MCSafeSEHFragment>(this);
+ case FT_Padding:
+ delete cast<MCPaddingFragment>(this);
+ return;
+ case FT_SymbolId:
+ delete cast<MCSymbolIdFragment>(this);
return;
case FT_CVInlineLines:
delete cast<MCCVInlineLineTableFragment>(this);
@@ -322,7 +325,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
case MCFragment::FT_LEB: OS << "MCLEBFragment"; break;
- case MCFragment::FT_SafeSEH: OS << "MCSafeSEHFragment"; break;
+ case MCFragment::FT_Padding: OS << "MCPaddingFragment"; break;
+ case MCFragment::FT_SymbolId: OS << "MCSymbolIdFragment"; break;
case MCFragment::FT_CVInlineLines: OS << "MCCVInlineLineTableFragment"; break;
case MCFragment::FT_CVDefRange: OS << "MCCVDefRangeTableFragment"; break;
case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break;
@@ -419,8 +423,21 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
break;
}
- case MCFragment::FT_SafeSEH: {
- const MCSafeSEHFragment *F = cast<MCSafeSEHFragment>(this);
+ case MCFragment::FT_Padding: {
+ const MCPaddingFragment *F = cast<MCPaddingFragment>(this);
+ OS << "\n ";
+ OS << " PaddingPoliciesMask:" << F->getPaddingPoliciesMask()
+ << " IsInsertionPoint:" << F->isInsertionPoint()
+ << " Size:" << F->getSize();
+ OS << "\n ";
+ OS << " Inst:";
+ F->getInst().dump_pretty(OS);
+ OS << " InstSize:" << F->getInstSize();
+ OS << "\n ";
+ break;
+ }
+ case MCFragment::FT_SymbolId: {
+ const MCSymbolIdFragment *F = cast<MCSymbolIdFragment>(this);
OS << "\n ";
OS << " Sym:" << F->getSymbol();
break;
diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp
index 674c7b9bf619..82b75afabb3c 100644
--- a/lib/MC/MCMachOStreamer.cpp
+++ b/lib/MC/MCMachOStreamer.cpp
@@ -62,10 +62,12 @@ private:
void EmitDataRegionEnd();
public:
- MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_pwrite_stream &OS,
- MCCodeEmitter *Emitter, bool DWARFMustBeAtTheEnd, bool label)
- : MCObjectStreamer(Context, MAB, OS, Emitter), LabelSections(label),
- DWARFMustBeAtTheEnd(DWARFMustBeAtTheEnd), CreatedADWARFSection(false) {}
+ MCMachOStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
+ raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter,
+ bool DWARFMustBeAtTheEnd, bool label)
+ : MCObjectStreamer(Context, std::move(MAB), OS, std::move(Emitter)),
+ LabelSections(label), DWARFMustBeAtTheEnd(DWARFMustBeAtTheEnd),
+ CreatedADWARFSection(false) {}
/// state management
void reset() override {
@@ -86,6 +88,8 @@ public:
void EmitDataRegion(MCDataRegionType Kind) override;
void EmitVersionMin(MCVersionMinType Kind, unsigned Major,
unsigned Minor, unsigned Update) override;
+ void EmitBuildVersion(unsigned Platform, unsigned Major,
+ unsigned Minor, unsigned Update) override;
void EmitThumbFunc(MCSymbol *Func) override;
bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
@@ -263,7 +267,13 @@ void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) {
void MCMachOStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major,
unsigned Minor, unsigned Update) {
- getAssembler().setVersionMinInfo(Kind, Major, Minor, Update);
+ getAssembler().setVersionMin(Kind, Major, Minor, Update);
+}
+
+void MCMachOStreamer::EmitBuildVersion(unsigned Platform, unsigned Major,
+ unsigned Minor, unsigned Update) {
+ getAssembler().setBuildVersion((MachO::PlatformType)Platform, Major, Minor,
+ Update);
}
void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) {
@@ -483,32 +493,17 @@ void MCMachOStreamer::FinishImpl() {
this->MCObjectStreamer::FinishImpl();
}
-MCStreamer *llvm::createMachOStreamer(MCContext &Context, MCAsmBackend &MAB,
- raw_pwrite_stream &OS, MCCodeEmitter *CE,
+MCStreamer *llvm::createMachOStreamer(MCContext &Context,
+ std::unique_ptr<MCAsmBackend> &&MAB,
+ raw_pwrite_stream &OS,
+ std::unique_ptr<MCCodeEmitter> &&CE,
bool RelaxAll, bool DWARFMustBeAtTheEnd,
bool LabelSections) {
- MCMachOStreamer *S = new MCMachOStreamer(Context, MAB, OS, CE,
- DWARFMustBeAtTheEnd, LabelSections);
- const Triple &TT = Context.getObjectFileInfo()->getTargetTriple();
- if (TT.isOSDarwin()) {
- unsigned Major, Minor, Update;
- TT.getOSVersion(Major, Minor, Update);
- // If there is a version specified, Major will be non-zero.
- if (Major) {
- MCVersionMinType VersionType;
- if (TT.isWatchOS())
- VersionType = MCVM_WatchOSVersionMin;
- else if (TT.isTvOS())
- VersionType = MCVM_TvOSVersionMin;
- else if (TT.isMacOSX())
- VersionType = MCVM_OSXVersionMin;
- else {
- assert(TT.isiOS() && "Must only be iOS platform left");
- VersionType = MCVM_IOSVersionMin;
- }
- S->EmitVersionMin(VersionType, Major, Minor, Update);
- }
- }
+ MCMachOStreamer *S =
+ new MCMachOStreamer(Context, std::move(MAB), OS, std::move(CE),
+ DWARFMustBeAtTheEnd, LabelSections);
+ const Triple &Target = Context.getObjectFileInfo()->getTargetTriple();
+ S->EmitVersionForTarget(Target);
if (RelaxAll)
S->getAssembler().setRelaxAll(true);
return S;
diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp
index 4db9a2c8d8de..ccf658e1d135 100644
--- a/lib/MC/MCNullStreamer.cpp
+++ b/lib/MC/MCNullStreamer.cpp
@@ -7,9 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp
index 21c5516785ef..a6b5c43f1d2a 100644
--- a/lib/MC/MCObjectFileInfo.cpp
+++ b/lib/MC/MCObjectFileInfo.cpp
@@ -185,6 +185,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
COFFDebugSymbolsSection = nullptr;
COFFDebugTypesSection = nullptr;
+ COFFGlobalTypeHashesSection = nullptr;
if (useCompactUnwind(T)) {
CompactUnwindSection =
@@ -214,6 +215,10 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
Ctx->getMachOSection("__DWARF", "__apple_types", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "types_begin");
+ DwarfSwiftASTSection =
+ Ctx->getMachOSection("__DWARF", "__swift_ast", MachO::S_ATTR_DEBUG,
+ SectionKind::getMetadata());
+
DwarfAbbrevSection =
Ctx->getMachOSection("__DWARF", "__debug_abbrev", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "section_abbrev");
@@ -274,7 +279,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
TLSExtraDataSection = TLSTLVSection;
}
-void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) {
+void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
switch (T.getArch()) {
case Triple::mips:
case Triple::mipsel:
@@ -286,8 +291,7 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) {
break;
case Triple::x86_64:
FDECFIEncoding = dwarf::DW_EH_PE_pcrel |
- ((CMModel == CodeModel::Large) ? dwarf::DW_EH_PE_sdata8
- : dwarf::DW_EH_PE_sdata4);
+ (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4);
break;
case Triple::bpfel:
case Triple::bpfeb:
@@ -324,23 +328,18 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) {
break;
case Triple::x86_64:
if (PositionIndependent) {
- PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- ((CMModel == CodeModel::Small || CMModel == CodeModel::Medium)
- ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8);
+ PersonalityEncoding =
+ dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4);
LSDAEncoding = dwarf::DW_EH_PE_pcrel |
- (CMModel == CodeModel::Small
- ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8);
+ (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4);
TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- ((CMModel == CodeModel::Small || CMModel == CodeModel::Medium)
- ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8);
+ (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4);
} else {
PersonalityEncoding =
- (CMModel == CodeModel::Small || CMModel == CodeModel::Medium)
- ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr;
- LSDAEncoding = (CMModel == CodeModel::Small)
- ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr;
- TTypeEncoding = (CMModel == CodeModel::Small)
- ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr;
+ Large ? dwarf::DW_EH_PE_absptr : dwarf::DW_EH_PE_udata4;
+ LSDAEncoding = Large ? dwarf::DW_EH_PE_absptr : dwarf::DW_EH_PE_udata4;
+ TTypeEncoding = Large ? dwarf::DW_EH_PE_absptr : dwarf::DW_EH_PE_udata4;
}
break;
case Triple::hexagon:
@@ -596,6 +595,8 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) {
EHFrameSection =
Ctx->getELFSection(".eh_frame", EHSectionType, EHSectionFlags);
+
+ StackSizesSection = Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, 0);
}
void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
@@ -655,6 +656,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ),
SectionKind::getMetadata());
+ COFFGlobalTypeHashesSection = Ctx->getCOFFSection(
+ ".debug$H",
+ (COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ),
+ SectionKind::getMetadata());
DwarfAbbrevSection = Ctx->getCOFFSection(
".debug_abbrev",
@@ -826,33 +832,32 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) {
// TODO: Set the section types and flags.
- TextSection = Ctx->getWasmSection(".text", 0, 0);
- DataSection = Ctx->getWasmSection(".data", 0, 0);
+ TextSection = Ctx->getWasmSection(".text", SectionKind::getText());
+ DataSection = Ctx->getWasmSection(".data", SectionKind::getData());
// TODO: Set the section types and flags.
- DwarfLineSection = Ctx->getWasmSection(".debug_line", 0, 0);
- DwarfStrSection = Ctx->getWasmSection(".debug_str", 0, 0);
- DwarfLocSection = Ctx->getWasmSection(".debug_loc", 0, 0);
- DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", 0, 0, "section_abbrev");
- DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", 0, 0);
- DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", 0, 0, "debug_range");
- DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", 0, 0, "debug_macinfo");
- DwarfAddrSection = Ctx->getWasmSection(".debug_addr", 0, 0);
- DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", 0, 0);
- DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", 0, 0);
- DwarfInfoSection = Ctx->getWasmSection(".debug_info", 0, 0, "section_info");
- DwarfFrameSection = Ctx->getWasmSection(".debug_frame", 0, 0);
- DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", 0, 0);
- DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", 0, 0);
+ DwarfLineSection = Ctx->getWasmSection(".debug_line", SectionKind::getMetadata());
+ DwarfStrSection = Ctx->getWasmSection(".debug_str", SectionKind::getMetadata());
+ DwarfLocSection = Ctx->getWasmSection(".debug_loc", SectionKind::getMetadata());
+ DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", SectionKind::getMetadata(), "section_abbrev");
+ DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", SectionKind::getMetadata());
+ DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", SectionKind::getMetadata(), "debug_range");
+ DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", SectionKind::getMetadata(), "debug_macinfo");
+ DwarfAddrSection = Ctx->getWasmSection(".debug_addr", SectionKind::getMetadata());
+ DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", SectionKind::getMetadata());
+ DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", SectionKind::getMetadata());
+ DwarfInfoSection = Ctx->getWasmSection(".debug_info", SectionKind::getMetadata(), "section_info");
+ DwarfFrameSection = Ctx->getWasmSection(".debug_frame", SectionKind::getMetadata());
+ DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", SectionKind::getMetadata());
+ DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", SectionKind::getMetadata());
// TODO: Define more sections.
}
void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC,
- CodeModel::Model cm,
- MCContext &ctx) {
+ MCContext &ctx,
+ bool LargeCodeModel) {
PositionIndependent = PIC;
- CMModel = cm;
Ctx = &ctx;
// Common.
@@ -890,7 +895,7 @@ void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC,
break;
case Triple::ELF:
Env = IsELF;
- initELFMCObjectFileInfo(TT);
+ initELFMCObjectFileInfo(TT, LargeCodeModel);
break;
case Triple::Wasm:
Env = IsWasm;
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index 174397e27396..15cc0faf5407 100644
--- a/lib/MC/MCObjectStreamer.cpp
+++ b/lib/MC/MCObjectStreamer.cpp
@@ -10,7 +10,6 @@
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCCodeView.h"
@@ -22,23 +21,19 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
-MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB,
+MCObjectStreamer::MCObjectStreamer(MCContext &Context,
+ std::unique_ptr<MCAsmBackend> TAB,
raw_pwrite_stream &OS,
- MCCodeEmitter *Emitter_)
- : MCStreamer(Context),
- Assembler(new MCAssembler(Context, TAB, *Emitter_,
- *TAB.createObjectWriter(OS))),
+ std::unique_ptr<MCCodeEmitter> Emitter)
+ : MCStreamer(Context), ObjectWriter(TAB->createObjectWriter(OS)),
+ TAB(std::move(TAB)), Emitter(std::move(Emitter)),
+ Assembler(llvm::make_unique<MCAssembler>(Context, *this->TAB,
+ *this->Emitter, *ObjectWriter)),
EmitEHFrame(true), EmitDebugFrame(false) {}
-MCObjectStreamer::~MCObjectStreamer() {
- delete &Assembler->getBackend();
- delete &Assembler->getEmitter();
- delete &Assembler->getWriter();
- delete Assembler;
-}
+MCObjectStreamer::~MCObjectStreamer() {}
void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
if (PendingLabels.empty())
@@ -111,6 +106,16 @@ MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() {
return F;
}
+MCPaddingFragment *MCObjectStreamer::getOrCreatePaddingFragment() {
+ MCPaddingFragment *F =
+ dyn_cast_or_null<MCPaddingFragment>(getCurrentFragment());
+ if (!F) {
+ F = new MCPaddingFragment();
+ insert(F);
+ }
+ return F;
+}
+
void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
Assembler->registerSymbol(Sym);
}
@@ -147,6 +152,12 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
DF->getContents().resize(DF->getContents().size() + Size, 0);
}
+MCSymbol *MCObjectStreamer::EmitCFILabel() {
+ MCSymbol *Label = getContext().createTempSymbol("cfi", true);
+ EmitLabel(Label);
+ return Label;
+}
+
void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
// We need to create a local symbol to avoid relocations.
Frame.Begin = getContext().createTempSymbol();
@@ -244,6 +255,13 @@ bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {
void MCObjectStreamer::EmitInstruction(const MCInst &Inst,
const MCSubtargetInfo &STI, bool) {
+ getAssembler().getBackend().handleCodePaddingInstructionBegin(Inst);
+ EmitInstructionImpl(Inst, STI);
+ getAssembler().getBackend().handleCodePaddingInstructionEnd(Inst);
+}
+
+void MCObjectStreamer::EmitInstructionImpl(const MCInst &Inst,
+ const MCSubtargetInfo &STI) {
MCStreamer::EmitInstruction(Inst, STI);
MCSection *Sec = getCurrentSectionOnly();
@@ -426,6 +444,9 @@ void MCObjectStreamer::EmitCVFileChecksumsDirective() {
getContext().getCVContext().emitFileChecksums(*this);
}
+void MCObjectStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
+ getContext().getCVContext().emitFileChecksumOffset(*this, FileNo);
+}
void MCObjectStreamer::EmitBytes(StringRef Data) {
MCCVLineEntry::Make(this);
@@ -461,6 +482,16 @@ void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
insert(new MCOrgFragment(*Offset, Value, Loc));
}
+void MCObjectStreamer::EmitCodePaddingBasicBlockStart(
+ const MCCodePaddingContext &Context) {
+ getAssembler().getBackend().handleCodePaddingBasicBlockStart(this, Context);
+}
+
+void MCObjectStreamer::EmitCodePaddingBasicBlockEnd(
+ const MCCodePaddingContext &Context) {
+ getAssembler().getBackend().handleCodePaddingBasicBlockEnd(Context);
+}
+
// Associate DTPRel32 fixup with data and resize data area
void MCObjectStreamer::EmitDTPRel32Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp
index 2b963607b837..74835fd70c04 100644
--- a/lib/MC/MCParser/AsmLexer.cpp
+++ b/lib/MC/MCParser/AsmLexer.cpp
@@ -14,6 +14,7 @@
#include "llvm/MC/MCParser/AsmLexer.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -68,7 +69,7 @@ int AsmLexer::getNextChar() {
/// consumed.
AsmToken AsmLexer::LexFloatLiteral() {
// Skip the fractional digit sequence.
- while (isdigit(*CurPtr))
+ while (isDigit(*CurPtr))
++CurPtr;
// Check for exponent; we intentionally accept a slighlty wider set of
@@ -78,7 +79,7 @@ AsmToken AsmLexer::LexFloatLiteral() {
++CurPtr;
if (*CurPtr == '-' || *CurPtr == '+')
++CurPtr;
- while (isdigit(*CurPtr))
+ while (isDigit(*CurPtr))
++CurPtr;
}
@@ -102,7 +103,7 @@ AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) {
++CurPtr;
const char *FracStart = CurPtr;
- while (isxdigit(*CurPtr))
+ while (isHexDigit(*CurPtr))
++CurPtr;
NoFracDigits = CurPtr == FracStart;
@@ -123,7 +124,7 @@ AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) {
// N.b. exponent digits are *not* hex
const char *ExpStart = CurPtr;
- while (isdigit(*CurPtr))
+ while (isDigit(*CurPtr))
++CurPtr;
if (CurPtr == ExpStart)
@@ -135,15 +136,15 @@ AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) {
/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@?]*
static bool IsIdentifierChar(char c, bool AllowAt) {
- return isalnum(c) || c == '_' || c == '$' || c == '.' ||
+ return isAlnum(c) || c == '_' || c == '$' || c == '.' ||
(c == '@' && AllowAt) || c == '?';
}
AsmToken AsmLexer::LexIdentifier() {
// Check for floating point literals.
- if (CurPtr[-1] == '.' && isdigit(*CurPtr)) {
+ if (CurPtr[-1] == '.' && isDigit(*CurPtr)) {
// Disambiguate a .1243foo identifier from a floating literal.
- while (isdigit(*CurPtr))
+ while (isDigit(*CurPtr))
++CurPtr;
if (*CurPtr == 'e' || *CurPtr == 'E' ||
!IsIdentifierChar(*CurPtr, AllowAtInIdentifier))
@@ -209,6 +210,8 @@ AsmToken AsmLexer::LexLineComment() {
int CurChar = getNextChar();
while (CurChar != '\n' && CurChar != '\r' && CurChar != EOF)
CurChar = getNextChar();
+ if (CurChar == '\r' && CurPtr != CurBuf.end() && *CurPtr == '\n')
+ ++CurPtr;
// If we have a CommentConsumer, notify it about the comment.
if (CommentConsumer) {
@@ -244,9 +247,9 @@ static unsigned doLookAhead(const char *&CurPtr, unsigned DefaultRadix) {
const char *FirstHex = nullptr;
const char *LookAhead = CurPtr;
while (true) {
- if (isdigit(*LookAhead)) {
+ if (isDigit(*LookAhead)) {
++LookAhead;
- } else if (isxdigit(*LookAhead)) {
+ } else if (isHexDigit(*LookAhead)) {
if (!FirstHex)
FirstHex = LookAhead;
++LookAhead;
@@ -282,7 +285,7 @@ AsmToken AsmLexer::LexDigit() {
const char *FirstNonBinary = (CurPtr[-1] != '0' && CurPtr[-1] != '1') ?
CurPtr - 1 : nullptr;
const char *OldCurPtr = CurPtr;
- while (isxdigit(*CurPtr)) {
+ while (isHexDigit(*CurPtr)) {
if (*CurPtr != '0' && *CurPtr != '1' && !FirstNonBinary)
FirstNonBinary = CurPtr;
++CurPtr;
@@ -346,7 +349,7 @@ AsmToken AsmLexer::LexDigit() {
if (!IsParsingMSInlineAsm && ((*CurPtr == 'b') || (*CurPtr == 'B'))) {
++CurPtr;
// See if we actually have "0b" as part of something like "jmp 0b\n"
- if (!isdigit(CurPtr[0])) {
+ if (!isDigit(CurPtr[0])) {
--CurPtr;
StringRef Result(TokStart, CurPtr - TokStart);
return AsmToken(AsmToken::Integer, Result, 0);
@@ -375,7 +378,7 @@ AsmToken AsmLexer::LexDigit() {
if ((*CurPtr == 'x') || (*CurPtr == 'X')) {
++CurPtr;
const char *NumStart = CurPtr;
- while (isxdigit(CurPtr[0]))
+ while (isHexDigit(CurPtr[0]))
++CurPtr;
// "0x.0p0" is valid, and "0x0p0" (but not "0xp0" for example, which will be
@@ -605,8 +608,16 @@ AsmToken AsmLexer::LexToken() {
return LexToken(); // Ignore whitespace.
else
return AsmToken(AsmToken::Space, StringRef(TokStart, CurPtr - TokStart));
+ case '\r': {
+ IsAtStartOfLine = true;
+ IsAtStartOfStatement = true;
+ // If this is a CR followed by LF, treat that as one token.
+ if (CurPtr != CurBuf.end() && *CurPtr == '\n')
+ ++CurPtr;
+ return AsmToken(AsmToken::EndOfStatement,
+ StringRef(TokStart, CurPtr - TokStart));
+ }
case '\n':
- case '\r':
IsAtStartOfLine = true;
IsAtStartOfStatement = true;
return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index dad47e49e2c2..2259136c6ec4 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
@@ -387,37 +388,158 @@ private:
// Generic (target and platform independent) directive parsing.
enum DirectiveKind {
DK_NO_DIRECTIVE, // Placeholder
- DK_SET, DK_EQU, DK_EQUIV, DK_ASCII, DK_ASCIZ, DK_STRING, DK_BYTE, DK_SHORT,
+ DK_SET,
+ DK_EQU,
+ DK_EQUIV,
+ DK_ASCII,
+ DK_ASCIZ,
+ DK_STRING,
+ DK_BYTE,
+ DK_SHORT,
DK_RELOC,
- DK_VALUE, DK_2BYTE, DK_LONG, DK_INT, DK_4BYTE, DK_QUAD, DK_8BYTE, DK_OCTA,
- DK_DC, DK_DC_A, DK_DC_B, DK_DC_D, DK_DC_L, DK_DC_S, DK_DC_W, DK_DC_X,
- DK_DCB, DK_DCB_B, DK_DCB_D, DK_DCB_L, DK_DCB_S, DK_DCB_W, DK_DCB_X,
- DK_DS, DK_DS_B, DK_DS_D, DK_DS_L, DK_DS_P, DK_DS_S, DK_DS_W, DK_DS_X,
- DK_SINGLE, DK_FLOAT, DK_DOUBLE, DK_ALIGN, DK_ALIGN32, DK_BALIGN, DK_BALIGNW,
- DK_BALIGNL, DK_P2ALIGN, DK_P2ALIGNW, DK_P2ALIGNL, DK_ORG, DK_FILL, DK_ENDR,
- DK_BUNDLE_ALIGN_MODE, DK_BUNDLE_LOCK, DK_BUNDLE_UNLOCK,
- DK_ZERO, DK_EXTERN, DK_GLOBL, DK_GLOBAL,
- DK_LAZY_REFERENCE, DK_NO_DEAD_STRIP, DK_SYMBOL_RESOLVER,
- DK_PRIVATE_EXTERN, DK_REFERENCE, DK_WEAK_DEFINITION, DK_WEAK_REFERENCE,
- DK_WEAK_DEF_CAN_BE_HIDDEN, DK_COMM, DK_COMMON, DK_LCOMM, DK_ABORT,
- DK_INCLUDE, DK_INCBIN, DK_CODE16, DK_CODE16GCC, DK_REPT, DK_IRP, DK_IRPC,
- DK_IF, DK_IFEQ, DK_IFGE, DK_IFGT, DK_IFLE, DK_IFLT, DK_IFNE, DK_IFB,
- DK_IFNB, DK_IFC, DK_IFEQS, DK_IFNC, DK_IFNES, DK_IFDEF, DK_IFNDEF,
- DK_IFNOTDEF, DK_ELSEIF, DK_ELSE, DK_ENDIF,
- DK_SPACE, DK_SKIP, DK_FILE, DK_LINE, DK_LOC, DK_STABS,
- DK_CV_FILE, DK_CV_FUNC_ID, DK_CV_INLINE_SITE_ID, DK_CV_LOC, DK_CV_LINETABLE,
- DK_CV_INLINE_LINETABLE, DK_CV_DEF_RANGE, DK_CV_STRINGTABLE,
+ DK_VALUE,
+ DK_2BYTE,
+ DK_LONG,
+ DK_INT,
+ DK_4BYTE,
+ DK_QUAD,
+ DK_8BYTE,
+ DK_OCTA,
+ DK_DC,
+ DK_DC_A,
+ DK_DC_B,
+ DK_DC_D,
+ DK_DC_L,
+ DK_DC_S,
+ DK_DC_W,
+ DK_DC_X,
+ DK_DCB,
+ DK_DCB_B,
+ DK_DCB_D,
+ DK_DCB_L,
+ DK_DCB_S,
+ DK_DCB_W,
+ DK_DCB_X,
+ DK_DS,
+ DK_DS_B,
+ DK_DS_D,
+ DK_DS_L,
+ DK_DS_P,
+ DK_DS_S,
+ DK_DS_W,
+ DK_DS_X,
+ DK_SINGLE,
+ DK_FLOAT,
+ DK_DOUBLE,
+ DK_ALIGN,
+ DK_ALIGN32,
+ DK_BALIGN,
+ DK_BALIGNW,
+ DK_BALIGNL,
+ DK_P2ALIGN,
+ DK_P2ALIGNW,
+ DK_P2ALIGNL,
+ DK_ORG,
+ DK_FILL,
+ DK_ENDR,
+ DK_BUNDLE_ALIGN_MODE,
+ DK_BUNDLE_LOCK,
+ DK_BUNDLE_UNLOCK,
+ DK_ZERO,
+ DK_EXTERN,
+ DK_GLOBL,
+ DK_GLOBAL,
+ DK_LAZY_REFERENCE,
+ DK_NO_DEAD_STRIP,
+ DK_SYMBOL_RESOLVER,
+ DK_PRIVATE_EXTERN,
+ DK_REFERENCE,
+ DK_WEAK_DEFINITION,
+ DK_WEAK_REFERENCE,
+ DK_WEAK_DEF_CAN_BE_HIDDEN,
+ DK_COMM,
+ DK_COMMON,
+ DK_LCOMM,
+ DK_ABORT,
+ DK_INCLUDE,
+ DK_INCBIN,
+ DK_CODE16,
+ DK_CODE16GCC,
+ DK_REPT,
+ DK_IRP,
+ DK_IRPC,
+ DK_IF,
+ DK_IFEQ,
+ DK_IFGE,
+ DK_IFGT,
+ DK_IFLE,
+ DK_IFLT,
+ DK_IFNE,
+ DK_IFB,
+ DK_IFNB,
+ DK_IFC,
+ DK_IFEQS,
+ DK_IFNC,
+ DK_IFNES,
+ DK_IFDEF,
+ DK_IFNDEF,
+ DK_IFNOTDEF,
+ DK_ELSEIF,
+ DK_ELSE,
+ DK_ENDIF,
+ DK_SPACE,
+ DK_SKIP,
+ DK_FILE,
+ DK_LINE,
+ DK_LOC,
+ DK_STABS,
+ DK_CV_FILE,
+ DK_CV_FUNC_ID,
+ DK_CV_INLINE_SITE_ID,
+ DK_CV_LOC,
+ DK_CV_LINETABLE,
+ DK_CV_INLINE_LINETABLE,
+ DK_CV_DEF_RANGE,
+ DK_CV_STRINGTABLE,
DK_CV_FILECHECKSUMS,
- DK_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA,
- DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET, DK_CFI_DEF_CFA_REGISTER,
- DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, DK_CFI_LSDA,
- DK_CFI_REMEMBER_STATE, DK_CFI_RESTORE_STATE, DK_CFI_SAME_VALUE,
- DK_CFI_RESTORE, DK_CFI_ESCAPE, DK_CFI_SIGNAL_FRAME, DK_CFI_UNDEFINED,
- DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE,
- DK_MACROS_ON, DK_MACROS_OFF, DK_ALTMACRO, DK_NOALTMACRO,
- DK_MACRO, DK_EXITM, DK_ENDM, DK_ENDMACRO, DK_PURGEM,
- DK_SLEB128, DK_ULEB128,
- DK_ERR, DK_ERROR, DK_WARNING,
+ DK_CV_FILECHECKSUM_OFFSET,
+ DK_CV_FPO_DATA,
+ DK_CFI_SECTIONS,
+ DK_CFI_STARTPROC,
+ DK_CFI_ENDPROC,
+ DK_CFI_DEF_CFA,
+ DK_CFI_DEF_CFA_OFFSET,
+ DK_CFI_ADJUST_CFA_OFFSET,
+ DK_CFI_DEF_CFA_REGISTER,
+ DK_CFI_OFFSET,
+ DK_CFI_REL_OFFSET,
+ DK_CFI_PERSONALITY,
+ DK_CFI_LSDA,
+ DK_CFI_REMEMBER_STATE,
+ DK_CFI_RESTORE_STATE,
+ DK_CFI_SAME_VALUE,
+ DK_CFI_RESTORE,
+ DK_CFI_ESCAPE,
+ DK_CFI_RETURN_COLUMN,
+ DK_CFI_SIGNAL_FRAME,
+ DK_CFI_UNDEFINED,
+ DK_CFI_REGISTER,
+ DK_CFI_WINDOW_SAVE,
+ DK_MACROS_ON,
+ DK_MACROS_OFF,
+ DK_ALTMACRO,
+ DK_NOALTMACRO,
+ DK_MACRO,
+ DK_EXITM,
+ DK_ENDM,
+ DK_ENDMACRO,
+ DK_PURGEM,
+ DK_SLEB128,
+ DK_ULEB128,
+ DK_ERR,
+ DK_ERROR,
+ DK_WARNING,
+ DK_PRINT,
DK_END
};
@@ -458,6 +580,8 @@ private:
bool parseDirectiveCVDefRange();
bool parseDirectiveCVStringTable();
bool parseDirectiveCVFileChecksums();
+ bool parseDirectiveCVFileChecksumOffset();
+ bool parseDirectiveCVFPOData();
// .cfi directives
bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
@@ -477,6 +601,7 @@ private:
bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
bool parseDirectiveCFIEscape();
+ bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
bool parseDirectiveCFISignalFrame();
bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
@@ -560,6 +685,9 @@ private:
// ".warning"
bool parseDirectiveWarning(SMLoc DirectiveLoc);
+ // .print <double-quotes-string>
+ bool parseDirectivePrint(SMLoc DirectiveLoc);
+
void initializeDirectiveKindMap();
};
@@ -1208,10 +1336,10 @@ bool AsmParser::isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
assert((StrLoc.getPointer() != NULL) &&
"Argument to the function cannot be a NULL value");
const char *CharPtr = StrLoc.getPointer();
- while ((*CharPtr != '>') && (*CharPtr != '\n') &&
- (*CharPtr != '\r') && (*CharPtr != '\0')){
- if(*CharPtr == '!')
- CharPtr++;
+ while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
+ (*CharPtr != '\0')) {
+ if (*CharPtr == '!')
+ CharPtr++;
CharPtr++;
}
if (*CharPtr == '>') {
@@ -1529,16 +1657,6 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
Lex();
return false;
}
- if (Lexer.is(AsmToken::Hash)) {
- // Seeing a hash here means that it was an end-of-line comment in
- // an asm syntax where hash's are not comment and the previous
- // statement parser did not check the end of statement. Relex as
- // EndOfStatement.
- StringRef CommentStr = parseStringToEndOfStatement();
- Lexer.Lex();
- Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
- return false;
- }
// Statements always start with an identifier.
AsmToken ID = getTok();
SMLoc IDLoc = ID.getLoc();
@@ -1578,6 +1696,11 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
// Treat '}' as a valid identifier in this context.
Lex();
IDVal = "}";
+ } else if (Lexer.is(AsmToken::Star) &&
+ getTargetParser().starIsStartOfStatement()) {
+ // Accept '*' as a valid start of statement.
+ Lex();
+ IDVal = "*";
} else if (parseIdentifier(IDVal)) {
if (!TheCondState.Ignore) {
Lex(); // always eat a token
@@ -1916,6 +2039,10 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectiveCVStringTable();
case DK_CV_FILECHECKSUMS:
return parseDirectiveCVFileChecksums();
+ case DK_CV_FILECHECKSUM_OFFSET:
+ return parseDirectiveCVFileChecksumOffset();
+ case DK_CV_FPO_DATA:
+ return parseDirectiveCVFPOData();
case DK_CFI_SECTIONS:
return parseDirectiveCFISections();
case DK_CFI_STARTPROC:
@@ -1948,6 +2075,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectiveCFIRestore(IDLoc);
case DK_CFI_ESCAPE:
return parseDirectiveCFIEscape();
+ case DK_CFI_RETURN_COLUMN:
+ return parseDirectiveCFIReturnColumn(IDLoc);
case DK_CFI_SIGNAL_FRAME:
return parseDirectiveCFISignalFrame();
case DK_CFI_UNDEFINED:
@@ -2009,6 +2138,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
case DK_DS_P:
case DK_DS_X:
return parseDirectiveDS(IDVal, 12);
+ case DK_PRINT:
+ return parseDirectivePrint(IDLoc);
}
return Error(IDLoc, "unknown directive");
@@ -3078,7 +3209,7 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
int64_t MaxBytesToFill = 0;
auto parseAlign = [&]() -> bool {
- if (checkForValidSection() || parseAbsoluteExpression(Alignment))
+ if (parseAbsoluteExpression(Alignment))
return true;
if (parseOptionalToken(AsmToken::Comma)) {
// The fill expression can be omitted while specifying a maximum number of
@@ -3097,6 +3228,13 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
return parseToken(AsmToken::EndOfStatement);
};
+ if (checkForValidSection())
+ return addErrorSuffix(" in directive");
+ // Ignore empty '.p2align' directives for GNU-as compatibility
+ if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
+ Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
+ return parseToken(AsmToken::EndOfStatement);
+ }
if (parseAlign())
return addErrorSuffix(" in directive");
@@ -3334,25 +3472,40 @@ bool AsmParser::parseDirectiveStabs() {
}
/// parseDirectiveCVFile
-/// ::= .cv_file number filename
+/// ::= .cv_file number filename [checksum] [checksumkind]
bool AsmParser::parseDirectiveCVFile() {
SMLoc FileNumberLoc = getTok().getLoc();
int64_t FileNumber;
std::string Filename;
+ std::string Checksum;
+ int64_t ChecksumKind = 0;
if (parseIntToken(FileNumber,
"expected file number in '.cv_file' directive") ||
check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
check(getTok().isNot(AsmToken::String),
"unexpected token in '.cv_file' directive") ||
- // Usually directory and filename are together, otherwise just
- // directory. Allow the strings to have escaped octal character sequence.
- parseEscapedString(Filename) ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.cv_file' directive"))
+ parseEscapedString(Filename))
return true;
+ if (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ if (check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.cv_file' directive") ||
+ parseEscapedString(Checksum) ||
+ parseIntToken(ChecksumKind,
+ "expected checksum kind in '.cv_file' directive") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cv_file' directive"))
+ return true;
+ }
- if (!getStreamer().EmitCVFileDirective(FileNumber, Filename))
+ Checksum = fromHex(Checksum);
+ void *CKMem = Ctx.allocate(Checksum.size(), 1);
+ memcpy(CKMem, Checksum.data(), Checksum.size());
+ ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
+ Checksum.size());
+
+ if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
+ static_cast<uint8_t>(ChecksumKind)))
return Error(FileNumberLoc, "file number already allocated");
return false;
@@ -3468,7 +3621,6 @@ bool AsmParser::parseDirectiveCVInlineSiteId() {
/// optional items are .loc sub-directives.
bool AsmParser::parseDirectiveCVLoc() {
SMLoc DirectiveLoc = getTok().getLoc();
- SMLoc Loc;
int64_t FunctionId, FileNumber;
if (parseCVFunctionId(FunctionId, ".cv_loc") ||
parseCVFileId(FileNumber, ".cv_loc"))
@@ -3631,6 +3783,32 @@ bool AsmParser::parseDirectiveCVFileChecksums() {
return false;
}
+/// parseDirectiveCVFileChecksumOffset
+/// ::= .cv_filechecksumoffset fileno
+bool AsmParser::parseDirectiveCVFileChecksumOffset() {
+ int64_t FileNo;
+ if (parseIntToken(FileNo, "expected identifier in directive"))
+ return true;
+ if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
+ return true;
+ getStreamer().EmitCVFileChecksumOffsetDirective(FileNo);
+ return false;
+}
+
+/// parseDirectiveCVFPOData
+/// ::= .cv_fpo_data procsym
+bool AsmParser::parseDirectiveCVFPOData() {
+ SMLoc DirLoc = getLexer().getLoc();
+ StringRef ProcName;
+ if (parseIdentifier(ProcName))
+ return TokError("expected symbol name");
+ if (parseEOL("unexpected tokens"))
+ return addErrorSuffix(" in '.cv_fpo_data' directive");
+ MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
+ getStreamer().EmitCVFPOData(ProcSym, DirLoc);
+ return false;
+}
+
/// parseDirectiveCFISections
/// ::= .cfi_sections section [, section]
bool AsmParser::parseDirectiveCFISections() {
@@ -3902,6 +4080,16 @@ bool AsmParser::parseDirectiveCFIEscape() {
return false;
}
+/// parseDirectiveCFIReturnColumn
+/// ::= .cfi_return_column register
+bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+ getStreamer().EmitCFIReturnColumn(Register);
+ return false;
+}
+
/// parseDirectiveCFISignalFrame
/// ::= .cfi_signal_frame
bool AsmParser::parseDirectiveCFISignalFrame() {
@@ -5003,6 +5191,8 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
+ DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
+ DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
DirectiveKindMap[".sleb128"] = DK_SLEB128;
DirectiveKindMap[".uleb128"] = DK_ULEB128;
DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
@@ -5021,6 +5211,7 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
+ DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
@@ -5061,6 +5252,7 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".ds.s"] = DK_DS_S;
DirectiveKindMap[".ds.w"] = DK_DS_W;
DirectiveKindMap[".ds.x"] = DK_DS_X;
+ DirectiveKindMap[".print"] = DK_PRINT;
}
MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
@@ -5289,6 +5481,17 @@ bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
return false;
}
+bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
+ const AsmToken StrTok = getTok();
+ Lex();
+ if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
+ return Error(DirectiveLoc, "expected double quoted string after .print");
+ if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
+ return true;
+ llvm::outs() << StrTok.getStringContents() << '\n';
+ return false;
+}
+
// We are comparing pointers, but the pointers are relative to a single string.
// Thus, this should always be deterministic.
static int rewritesSort(const AsmRewrite *AsmRewriteA,
@@ -5444,8 +5647,6 @@ bool AsmParser::parseMSInlineAsm(
array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
for (const AsmRewrite &AR : AsmStrRewrites) {
AsmRewriteKind Kind = AR.Kind;
- if (Kind == AOK_Delete)
- continue;
const char *Loc = AR.Loc.getPointer();
assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
@@ -5465,11 +5666,21 @@ bool AsmParser::parseMSInlineAsm(
switch (Kind) {
default:
break;
- case AOK_Imm:
- OS << "$$" << AR.Val;
- break;
- case AOK_ImmPrefix:
- OS << "$$";
+ case AOK_IntelExpr:
+ assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
+ if (AR.IntelExp.NeedBracs)
+ OS << "[";
+ if (AR.IntelExp.hasBaseReg())
+ OS << AR.IntelExp.BaseReg;
+ if (AR.IntelExp.hasIndexReg())
+ OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
+ << AR.IntelExp.IndexReg;
+ if (AR.IntelExp.Scale > 1)
+ OS << " * $$" << AR.IntelExp.Scale;
+ if (AR.IntelExp.Imm || !AR.IntelExp.hasRegs())
+ OS << (AR.IntelExp.hasRegs() ? " + $$" : "$$") << AR.IntelExp.Imm;
+ if (AR.IntelExp.NeedBracs)
+ OS << "]";
break;
case AOK_Label:
OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
@@ -5513,13 +5724,6 @@ bool AsmParser::parseMSInlineAsm(
case AOK_EVEN:
OS << ".even";
break;
- case AOK_DotOperator:
- // Insert the dot if the user omitted it.
- OS.flush();
- if (AsmStringIR.back() != '.')
- OS << '.';
- OS << AR.Val;
- break;
case AOK_EndOfStatement:
OS << "\n\t";
break;
diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp
index b83d68d4fe20..687e0cc1faa5 100644
--- a/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/lib/MC/MCParser/COFFAsmParser.cpp
@@ -568,7 +568,7 @@ bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
return false;
}
-bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
+bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
StringRef SymbolID;
if (getParser().parseIdentifier(SymbolID))
return true;
@@ -579,29 +579,29 @@ bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Lex();
- getStreamer().EmitWinCFIStartProc(Symbol);
+ getStreamer().EmitWinCFIStartProc(Symbol, Loc);
return false;
}
-bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
+bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
Lex();
- getStreamer().EmitWinCFIEndProc();
+ getStreamer().EmitWinCFIEndProc(Loc);
return false;
}
-bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
+bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
Lex();
- getStreamer().EmitWinCFIStartChained();
+ getStreamer().EmitWinCFIStartChained(Loc);
return false;
}
-bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
+bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
Lex();
- getStreamer().EmitWinCFIEndChained();
+ getStreamer().EmitWinCFIEndChained(Loc);
return false;
}
-bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
+bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
StringRef SymbolID;
if (getParser().parseIdentifier(SymbolID))
return true;
@@ -623,17 +623,17 @@ bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
Lex();
- getStreamer().EmitWinEHHandler(handler, unwind, except);
+ getStreamer().EmitWinEHHandler(handler, unwind, except, Loc);
return false;
}
-bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
+bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
Lex();
getStreamer().EmitWinEHHandlerData();
return false;
}
-bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
+bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc Loc) {
unsigned Reg = 0;
if (ParseSEHRegisterNumber(Reg))
return true;
@@ -642,11 +642,11 @@ bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
return TokError("unexpected token in directive");
Lex();
- getStreamer().EmitWinCFIPushReg(Reg);
+ getStreamer().EmitWinCFIPushReg(Reg, Loc);
return false;
}
-bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
+bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc Loc) {
unsigned Reg = 0;
int64_t Off;
if (ParseSEHRegisterNumber(Reg))
@@ -655,39 +655,31 @@ bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
return TokError("you must specify a stack pointer offset");
Lex();
- SMLoc startLoc = getLexer().getLoc();
if (getParser().parseAbsoluteExpression(Off))
return true;
- if (Off & 0x0F)
- return Error(startLoc, "offset is not a multiple of 16");
-
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in directive");
Lex();
- getStreamer().EmitWinCFISetFrame(Reg, Off);
+ getStreamer().EmitWinCFISetFrame(Reg, Off, Loc);
return false;
}
-bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
+bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
int64_t Size;
- SMLoc startLoc = getLexer().getLoc();
if (getParser().parseAbsoluteExpression(Size))
return true;
- if (Size & 7)
- return Error(startLoc, "size is not a multiple of 8");
-
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in directive");
Lex();
- getStreamer().EmitWinCFIAllocStack(Size);
+ getStreamer().EmitWinCFIAllocStack(Size, Loc);
return false;
}
-bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
+bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc Loc) {
unsigned Reg = 0;
int64_t Off;
if (ParseSEHRegisterNumber(Reg))
@@ -696,25 +688,21 @@ bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
return TokError("you must specify an offset on the stack");
Lex();
- SMLoc startLoc = getLexer().getLoc();
if (getParser().parseAbsoluteExpression(Off))
return true;
- if (Off & 7)
- return Error(startLoc, "size is not a multiple of 8");
-
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in directive");
Lex();
// FIXME: Err on %xmm* registers
- getStreamer().EmitWinCFISaveReg(Reg, Off);
+ 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 L) {
+bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc Loc) {
unsigned Reg = 0;
int64_t Off;
if (ParseSEHRegisterNumber(Reg))
@@ -723,23 +711,19 @@ bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
return TokError("you must specify an offset on the stack");
Lex();
- SMLoc startLoc = getLexer().getLoc();
if (getParser().parseAbsoluteExpression(Off))
return true;
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in directive");
- if (Off & 0x0F)
- return Error(startLoc, "offset is not a multiple of 16");
-
Lex();
// FIXME: Err on non-%xmm* registers
- getStreamer().EmitWinCFISaveXMM(Reg, Off);
+ getStreamer().EmitWinCFISaveXMM(Reg, Off, Loc);
return false;
}
-bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
+bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc Loc) {
bool Code = false;
StringRef CodeID;
if (getLexer().is(AsmToken::At)) {
@@ -756,13 +740,13 @@ bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
return TokError("unexpected token in directive");
Lex();
- getStreamer().EmitWinCFIPushFrame(Code);
+ getStreamer().EmitWinCFIPushFrame(Code, Loc);
return false;
}
-bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
+bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
Lex();
- getStreamer().EmitWinCFIEndProlog();
+ getStreamer().EmitWinCFIEndProlog(Loc);
return false;
}
diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp
index f4152a9067a0..195ddc78d454 100644
--- a/lib/MC/MCParser/DarwinAsmParser.cpp
+++ b/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -54,7 +54,7 @@ class DarwinAsmParser : public MCAsmParserExtension {
unsigned TAA = 0, unsigned ImplicitAlign = 0,
unsigned StubSize = 0);
- SMLoc LastVersionMinDirective;
+ SMLoc LastVersionDirective;
public:
DarwinAsmParser() = default;
@@ -186,14 +186,17 @@ public:
addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(".tlv");
addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(".ident");
- addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(
+ addDirectiveHandler<&DarwinAsmParser::parseWatchOSVersionMin>(
".watchos_version_min");
- addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(".tvos_version_min");
- addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(".ios_version_min");
- addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(
+ addDirectiveHandler<&DarwinAsmParser::parseTvOSVersionMin>(
+ ".tvos_version_min");
+ addDirectiveHandler<&DarwinAsmParser::parseIOSVersionMin>(
+ ".ios_version_min");
+ addDirectiveHandler<&DarwinAsmParser::parseMacOSXVersionMin>(
".macosx_version_min");
+ addDirectiveHandler<&DarwinAsmParser::parseBuildVersion>(".build_version");
- LastVersionMinDirective = SMLoc();
+ LastVersionDirective = SMLoc();
}
bool parseDirectiveAltEntry(StringRef, SMLoc);
@@ -441,7 +444,24 @@ public:
MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
}
- bool parseVersionMin(StringRef, SMLoc);
+ bool parseWatchOSVersionMin(StringRef Directive, SMLoc Loc) {
+ return parseVersionMin(Directive, Loc, MCVM_WatchOSVersionMin);
+ }
+ bool parseTvOSVersionMin(StringRef Directive, SMLoc Loc) {
+ return parseVersionMin(Directive, Loc, MCVM_TvOSVersionMin);
+ }
+ bool parseIOSVersionMin(StringRef Directive, SMLoc Loc) {
+ return parseVersionMin(Directive, Loc, MCVM_IOSVersionMin);
+ }
+ bool parseMacOSXVersionMin(StringRef Directive, SMLoc Loc) {
+ return parseVersionMin(Directive, Loc, MCVM_OSXVersionMin);
+ }
+
+ bool parseBuildVersion(StringRef Directive, SMLoc Loc);
+ bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type);
+ bool parseVersion(unsigned *Major, unsigned *Minor, unsigned *Update);
+ void checkVersion(StringRef Directive, StringRef Arg, SMLoc Loc,
+ Triple::OSType ExpectedOS);
};
} // end anonymous namespace
@@ -978,70 +998,144 @@ bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) {
return false;
}
-/// parseVersionMin
-/// ::= .ios_version_min major,minor[,update]
-/// ::= .macosx_version_min major,minor[,update]
-bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc) {
- int64_t Major = 0, Minor = 0, Update = 0;
- int Kind = StringSwitch<int>(Directive)
- .Case(".watchos_version_min", MCVM_WatchOSVersionMin)
- .Case(".tvos_version_min", MCVM_TvOSVersionMin)
- .Case(".ios_version_min", MCVM_IOSVersionMin)
- .Case(".macosx_version_min", MCVM_OSXVersionMin);
+/// parseVersion ::= major, minor [, update]
+bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor,
+ unsigned *Update) {
// Get the major version number.
if (getLexer().isNot(AsmToken::Integer))
+ return TokError("invalid OS major version number, integer expected");
+ int64_t MajorVal = getLexer().getTok().getIntVal();
+ if (MajorVal > 65535 || MajorVal <= 0)
return TokError("invalid OS major version number");
- Major = getLexer().getTok().getIntVal();
- if (Major > 65535 || Major <= 0)
- return TokError("invalid OS major version number");
+ *Major = (unsigned)MajorVal;
Lex();
if (getLexer().isNot(AsmToken::Comma))
- return TokError("minor OS version number required, comma expected");
+ return TokError("OS minor version number required, comma expected");
Lex();
// Get the minor version number.
if (getLexer().isNot(AsmToken::Integer))
+ return TokError("invalid OS minor version number, integer expected");
+ int64_t MinorVal = getLexer().getTok().getIntVal();
+ if (MinorVal > 255 || MinorVal < 0)
return TokError("invalid OS minor version number");
- Minor = getLexer().getTok().getIntVal();
- if (Minor > 255 || Minor < 0)
- return TokError("invalid OS minor version number");
+ *Minor = MinorVal;
Lex();
+
// Get the update level, if specified
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("invalid update specifier, comma expected");
- Lex();
- if (getLexer().isNot(AsmToken::Integer))
- return TokError("invalid OS update number");
- Update = getLexer().getTok().getIntVal();
- if (Update > 255 || Update < 0)
- return TokError("invalid OS update number");
- Lex();
+ *Update = 0;
+ if (getLexer().is(AsmToken::EndOfStatement))
+ return false;
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("invalid OS update specifier, comma expected");
+ Lex();
+ if (getLexer().isNot(AsmToken::Integer))
+ return TokError("invalid OS update version number, integer expected");
+ int64_t UpdateVal = getLexer().getTok().getIntVal();
+ if (UpdateVal > 255 || UpdateVal < 0)
+ return TokError("invalid OS update version number");
+ *Update = UpdateVal;
+ Lex();
+ return false;
+}
+
+void DarwinAsmParser::checkVersion(StringRef Directive, StringRef Arg,
+ SMLoc Loc, Triple::OSType ExpectedOS) {
+ const Triple &Target = getContext().getObjectFileInfo()->getTargetTriple();
+ if (Target.getOS() != ExpectedOS)
+ Warning(Loc, Twine(Directive) +
+ (Arg.empty() ? Twine() : Twine(' ') + Arg) +
+ " used while targeting " + Target.getOSName());
+
+ if (LastVersionDirective.isValid()) {
+ Warning(Loc, "overriding previous version directive");
+ Note(LastVersionDirective, "previous definition is here");
}
+ LastVersionDirective = Loc;
+}
- const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
- Triple::OSType ExpectedOS = Triple::UnknownOS;
- switch ((MCVersionMinType)Kind) {
- case MCVM_WatchOSVersionMin: ExpectedOS = Triple::WatchOS; break;
- case MCVM_TvOSVersionMin: ExpectedOS = Triple::TvOS; break;
- case MCVM_IOSVersionMin: ExpectedOS = Triple::IOS; break;
- case MCVM_OSXVersionMin: ExpectedOS = Triple::MacOSX; break;
+static Triple::OSType getOSTypeFromMCVM(MCVersionMinType Type) {
+ switch (Type) {
+ case MCVM_WatchOSVersionMin: return Triple::WatchOS;
+ case MCVM_TvOSVersionMin: return Triple::TvOS;
+ case MCVM_IOSVersionMin: return Triple::IOS;
+ case MCVM_OSXVersionMin: return Triple::MacOSX;
}
- if (T.getOS() != ExpectedOS)
- Warning(Loc, Directive + " should only be used for " +
- Triple::getOSTypeName(ExpectedOS) + " targets");
+ llvm_unreachable("Invalid mc version min type");
+}
+
+/// parseVersionMin
+/// ::= .ios_version_min parseVersion
+/// | .macosx_version_min parseVersion
+/// | .tvos_version_min parseVersion
+/// | .watchos_version_min parseVersion
+bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc,
+ MCVersionMinType Type) {
+ unsigned Major;
+ unsigned Minor;
+ unsigned Update;
+ if (parseVersion(&Major, &Minor, &Update))
+ return true;
+
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(Twine(" in '") + Directive + "' directive");
+
+ Triple::OSType ExpectedOS = getOSTypeFromMCVM(Type);
+ checkVersion(Directive, StringRef(), Loc, ExpectedOS);
+
+ getStreamer().EmitVersionMin(Type, Major, Minor, Update);
+ return false;
+}
- if (LastVersionMinDirective.isValid()) {
- Warning(Loc, "overriding previous version_min directive");
- Note(LastVersionMinDirective, "previous definition is here");
+Triple::OSType getOSTypeFromPlatform(MachO::PlatformType Type) {
+ switch (Type) {
+ case MachO::PLATFORM_MACOS: return Triple::MacOSX;
+ case MachO::PLATFORM_IOS: return Triple::IOS;
+ case MachO::PLATFORM_TVOS: return Triple::TvOS;
+ case MachO::PLATFORM_WATCHOS: return Triple::WatchOS;
+ case MachO::PLATFORM_BRIDGEOS: /* silence warning */break;
}
- LastVersionMinDirective = Loc;
+ llvm_unreachable("Invalid mach-o platform type");
+}
- // We've parsed a correct version specifier, so send it to the streamer.
- getStreamer().EmitVersionMin((MCVersionMinType)Kind, Major, Minor, Update);
+/// parseBuildVersion
+/// ::= .build_version (macos|ios|tvos|watchos), parseVersion
+bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) {
+ StringRef PlatformName;
+ SMLoc PlatformLoc = getTok().getLoc();
+ if (getParser().parseIdentifier(PlatformName))
+ return TokError("platform name expected");
+
+ unsigned Platform = StringSwitch<unsigned>(PlatformName)
+ .Case("macos", MachO::PLATFORM_MACOS)
+ .Case("ios", MachO::PLATFORM_IOS)
+ .Case("tvos", MachO::PLATFORM_TVOS)
+ .Case("watchos", MachO::PLATFORM_WATCHOS)
+ .Default(0);
+ if (Platform == 0)
+ return Error(PlatformLoc, "unknown platform name");
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("version number required, comma expected");
+ Lex();
+
+ unsigned Major;
+ unsigned Minor;
+ unsigned Update;
+ if (parseVersion(&Major, &Minor, &Update))
+ return true;
+
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '.build_version' directive");
+
+ Triple::OSType ExpectedOS
+ = getOSTypeFromPlatform((MachO::PlatformType)Platform);
+ checkVersion(Directive, PlatformName, Loc, ExpectedOS);
+
+ getStreamer().EmitBuildVersion(Platform, Major, Minor, Update);
return false;
}
+
namespace llvm {
MCAsmParserExtension *createDarwinAsmParser() {
diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp
index a407691b0bd1..38720c23ff26 100644
--- a/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/lib/MC/MCParser/ELFAsmParser.cpp
@@ -247,7 +247,7 @@ bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {
return false;
}
- while (true) {
+ while (!getParser().hasPendingError()) {
SMLoc PrevLoc = getLexer().getLoc();
if (getLexer().is(AsmToken::Comma) ||
getLexer().is(AsmToken::EndOfStatement))
@@ -488,7 +488,6 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
unsigned Flags = 0;
const MCExpr *Subsection = nullptr;
bool UseLastGroup = false;
- StringRef UniqueStr;
MCSymbolELF *Associated = nullptr;
int64_t UniqueID = ~0;
diff --git a/lib/MC/MCParser/MCAsmParser.cpp b/lib/MC/MCParser/MCAsmParser.cpp
index ea36b3b9b3b2..6a4c74cd57fe 100644
--- a/lib/MC/MCParser/MCAsmParser.cpp
+++ b/lib/MC/MCParser/MCAsmParser.cpp
@@ -40,11 +40,6 @@ bool MCAsmParser::parseTokenLoc(SMLoc &Loc) {
}
bool MCAsmParser::parseEOL(const Twine &Msg) {
- if (getTok().getKind() == AsmToken::Hash) {
- StringRef CommentStr = parseStringToEndOfStatement();
- getLexer().Lex();
- getLexer().UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
- }
if (getTok().getKind() != AsmToken::EndOfStatement)
return Error(getTok().getLoc(), Msg);
Lex();
@@ -70,9 +65,6 @@ bool MCAsmParser::parseIntToken(int64_t &V, const Twine &Msg) {
bool MCAsmParser::parseOptionalToken(AsmToken::TokenKind T) {
bool Present = (getTok().getKind() == T);
- // if token is EOL and current token is # this is an EOL comment.
- if (getTok().getKind() == AsmToken::Hash && T == AsmToken::EndOfStatement)
- Present = true;
if (Present)
parseToken(T);
return Present;
diff --git a/lib/MC/MCParser/MCTargetAsmParser.cpp b/lib/MC/MCParser/MCTargetAsmParser.cpp
index 64ac82a6c66f..a0c06c9d5018 100644
--- a/lib/MC/MCParser/MCTargetAsmParser.cpp
+++ b/lib/MC/MCParser/MCTargetAsmParser.cpp
@@ -13,8 +13,9 @@
using namespace llvm;
MCTargetAsmParser::MCTargetAsmParser(MCTargetOptions const &MCOptions,
- const MCSubtargetInfo &STI)
- : MCOptions(MCOptions), STI(&STI) {}
+ const MCSubtargetInfo &STI,
+ const MCInstrInfo &MII)
+ : MCOptions(MCOptions), STI(&STI), MII(MII) {}
MCTargetAsmParser::~MCTargetAsmParser() = default;
diff --git a/lib/MC/MCRegisterInfo.cpp b/lib/MC/MCRegisterInfo.cpp
index 0f76c1838b51..8e47963b4418 100644
--- a/lib/MC/MCRegisterInfo.cpp
+++ b/lib/MC/MCRegisterInfo.cpp
@@ -88,6 +88,34 @@ int MCRegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const {
return I->ToReg;
}
+int MCRegisterInfo::getLLVMRegNumFromEH(unsigned RegNum) const {
+ const DwarfLLVMRegPair *M = EHDwarf2LRegs;
+ unsigned Size = EHDwarf2LRegsSize;
+
+ if (!M)
+ return -1;
+ 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;
+}
+
+int MCRegisterInfo::getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const {
+ // On ELF platforms, DWARF EH register numbers are the same as DWARF
+ // other register numbers. On Darwin x86, they differ and so need to be
+ // mapped. The .cfi_* directives accept integer literals as well as
+ // register names and should generate exactly what the assembly code
+ // asked for, so there might be DWARF/EH register numbers that don't have
+ // 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);
+ return RegNum;
+}
+
int MCRegisterInfo::getSEHRegNum(unsigned RegNum) const {
const DenseMap<unsigned, int>::const_iterator I = L2SEHRegs.find(RegNum);
if (I == L2SEHRegs.end()) return (int)RegNum;
diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp
index 2f4f61aa4d50..bf1fcb03273c 100644
--- a/lib/MC/MCSectionELF.cpp
+++ b/lib/MC/MCSectionELF.cpp
@@ -113,8 +113,7 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
OS << 'c';
if (Flags & ELF::XCORE_SHF_DP_SECTION)
OS << 'd';
- } else if (Arch == Triple::arm || Arch == Triple::armeb ||
- Arch == Triple::thumb || Arch == Triple::thumbeb) {
+ } else if (T.isARM() || T.isThumb()) {
if (Flags & ELF::SHF_ARM_PURECODE)
OS << 'y';
}
diff --git a/lib/MC/MCSectionWasm.cpp b/lib/MC/MCSectionWasm.cpp
index c61f28e129f5..626027a24f97 100644
--- a/lib/MC/MCSectionWasm.cpp
+++ b/lib/MC/MCSectionWasm.cpp
@@ -9,7 +9,6 @@
#include "llvm/MC/MCSectionWasm.h"
#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index 2bfb9a63eedb..6f3647d61932 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/lib/MC/MCStreamer.cpp
@@ -56,17 +56,12 @@ MCStreamer::MCStreamer(MCContext &Ctx)
SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
}
-MCStreamer::~MCStreamer() {
- for (unsigned i = 0; i < getNumWinFrameInfos(); ++i)
- delete WinFrameInfos[i];
-}
+MCStreamer::~MCStreamer() {}
void MCStreamer::reset() {
DwarfFrameInfos.clear();
- for (unsigned i = 0; i < getNumWinFrameInfos(); ++i)
- delete WinFrameInfos[i];
- WinFrameInfos.clear();
CurrentWinFrameInfo = nullptr;
+ WinFrameInfos.clear();
SymbolOrdering.clear();
SectionStack.clear();
SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
@@ -105,13 +100,17 @@ void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
/// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
/// client having to pass in a MCExpr for constant integers.
-void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned Padding) {
+void MCStreamer::EmitPaddedULEB128IntValue(uint64_t Value, unsigned PadTo) {
SmallString<128> Tmp;
raw_svector_ostream OSE(Tmp);
- encodeULEB128(Value, OSE, Padding);
+ encodeULEB128(Value, OSE, PadTo);
EmitBytes(OSE.str());
}
+void MCStreamer::EmitULEB128IntValue(uint64_t Value) {
+ EmitPaddedULEB128IntValue(Value, 0);
+}
+
/// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
/// client having to pass in a MCExpr for constant integers.
void MCStreamer::EmitSLEB128IntValue(int64_t Value) {
@@ -207,25 +206,25 @@ MCSymbol *MCStreamer::getDwarfLineTableSymbol(unsigned CUID) {
return Table.getLabel();
}
-MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() {
- if (DwarfFrameInfos.empty())
- return nullptr;
- return &DwarfFrameInfos.back();
-}
-
bool MCStreamer::hasUnfinishedDwarfFrameInfo() {
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- return CurFrame && !CurFrame->End;
+ return !DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End;
}
-void MCStreamer::EnsureValidDwarfFrame() {
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame || CurFrame->End)
- report_fatal_error("No open frame");
+MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() {
+ if (!hasUnfinishedDwarfFrameInfo()) {
+ getContext().reportError(SMLoc(), "this directive must appear between "
+ ".cfi_startproc and .cfi_endproc "
+ "directives");
+ return nullptr;
+ }
+ return &DwarfFrameInfos.back();
}
-bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
- return getContext().getCVContext().addFile(FileNo, Filename);
+bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
+ ArrayRef<uint8_t> Checksum,
+ unsigned ChecksumKind) {
+ return getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
+ ChecksumKind);
}
bool MCStreamer::EmitCVFuncIdDirective(unsigned FunctionId) {
@@ -322,7 +321,8 @@ void MCStreamer::EmitCFISections(bool EH, bool Debug) {
void MCStreamer::EmitCFIStartProc(bool IsSimple) {
if (hasUnfinishedDwarfFrameInfo())
- report_fatal_error("Starting a frame before finishing the previous one!");
+ getContext().reportError(
+ SMLoc(), "starting new .cfi frame before finishing the previous one");
MCDwarfFrameInfo Frame;
Frame.IsSimple = IsSimple;
@@ -345,241 +345,298 @@ void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
}
void MCStreamer::EmitCFIEndProc() {
- EnsureValidDwarfFrame();
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
EmitCFIEndProcImpl(*CurFrame);
}
void MCStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
// Put a dummy non-null value in Frame.End to mark that this frame has been
// closed.
- Frame.End = (MCSymbol *) 1;
+ Frame.End = (MCSymbol *)1;
}
MCSymbol *MCStreamer::EmitCFILabel() {
- MCSymbol *Label = getContext().createTempSymbol("cfi", true);
- EmitLabel(Label);
- return Label;
-}
-
-MCSymbol *MCStreamer::EmitCFICommon() {
- EnsureValidDwarfFrame();
- return EmitCFILabel();
+ // Return a dummy non-null value so that label fields appear filled in when
+ // generating textual assembly.
+ return (MCSymbol *)1;
}
void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createDefCfa(Label, Register, Offset);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
}
void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createDefCfaOffset(Label, Offset);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createAdjustCfaOffset(Label, Adjustment);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createDefCfaRegister(Label, Register);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
}
void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createOffset(Label, Register, Offset);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createRelOffset(Label, Register, Offset);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFIPersonality(const MCSymbol *Sym,
unsigned Encoding) {
- EnsureValidDwarfFrame();
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Personality = Sym;
CurFrame->PersonalityEncoding = Encoding;
}
void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
- EnsureValidDwarfFrame();
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Lsda = Sym;
CurFrame->LsdaEncoding = Encoding;
}
void MCStreamer::EmitCFIRememberState() {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction = MCCFIInstruction::createRememberState(Label);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFIRestoreState() {
// FIXME: Error if there is no matching cfi_remember_state.
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction = MCCFIInstruction::createRestoreState(Label);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFISameValue(int64_t Register) {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createSameValue(Label, Register);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFIRestore(int64_t Register) {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createRestore(Label, Register);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFIEscape(StringRef Values) {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction = MCCFIInstruction::createEscape(Label, Values);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFIGnuArgsSize(int64_t Size) {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createGnuArgsSize(Label, Size);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFISignalFrame() {
- EnsureValidDwarfFrame();
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->IsSignalFrame = true;
}
void MCStreamer::EmitCFIUndefined(int64_t Register) {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createUndefined(Label, Register);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createRegister(Label, Register1, Register2);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFIWindowSave() {
- MCSymbol *Label = EmitCFICommon();
+ MCSymbol *Label = EmitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createWindowSave(Label);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EnsureValidWinFrameInfo() {
+void MCStreamer::EmitCFIReturnColumn(int64_t Register) {
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
+ CurFrame->RAReg = Register;
+}
+
+WinEH::FrameInfo *MCStreamer::EnsureValidWinFrameInfo(SMLoc Loc) {
const MCAsmInfo *MAI = Context.getAsmInfo();
- if (!MAI->usesWindowsCFI())
- report_fatal_error(".seh_* directives are not supported on this target");
- if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End)
- report_fatal_error("No open Win64 EH frame function!");
+ if (!MAI->usesWindowsCFI()) {
+ getContext().reportError(
+ Loc, ".seh_* directives are not supported on this target");
+ return nullptr;
+ }
+ if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End) {
+ getContext().reportError(
+ Loc, ".seh_ directive must appear within an active frame");
+ return nullptr;
+ }
+ return CurrentWinFrameInfo;
}
-void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) {
+void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
const MCAsmInfo *MAI = Context.getAsmInfo();
if (!MAI->usesWindowsCFI())
- report_fatal_error(".seh_* directives are not supported on this target");
+ return getContext().reportError(
+ Loc, ".seh_* directives are not supported on this target");
if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End)
- report_fatal_error("Starting a function before ending the previous one!");
+ getContext().reportError(
+ Loc, "Starting a function before ending the previous one!");
MCSymbol *StartProc = EmitCFILabel();
- WinFrameInfos.push_back(new WinEH::FrameInfo(Symbol, StartProc));
- CurrentWinFrameInfo = WinFrameInfos.back();
+ WinFrameInfos.emplace_back(
+ llvm::make_unique<WinEH::FrameInfo>(Symbol, StartProc));
+ CurrentWinFrameInfo = WinFrameInfos.back().get();
CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
}
-void MCStreamer::EmitWinCFIEndProc() {
- EnsureValidWinFrameInfo();
- if (CurrentWinFrameInfo->ChainedParent)
- report_fatal_error("Not all chained regions terminated!");
+void MCStreamer::EmitWinCFIEndProc(SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
+ if (CurFrame->ChainedParent)
+ getContext().reportError(Loc, "Not all chained regions terminated!");
MCSymbol *Label = EmitCFILabel();
- CurrentWinFrameInfo->End = Label;
+ CurFrame->End = Label;
}
-void MCStreamer::EmitWinCFIStartChained() {
- EnsureValidWinFrameInfo();
+void MCStreamer::EmitWinCFIStartChained(SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
MCSymbol *StartProc = EmitCFILabel();
- WinFrameInfos.push_back(new WinEH::FrameInfo(CurrentWinFrameInfo->Function,
- StartProc, CurrentWinFrameInfo));
- CurrentWinFrameInfo = WinFrameInfos.back();
+ WinFrameInfos.emplace_back(llvm::make_unique<WinEH::FrameInfo>(
+ CurFrame->Function, StartProc, CurFrame));
+ CurrentWinFrameInfo = WinFrameInfos.back().get();
CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
}
-void MCStreamer::EmitWinCFIEndChained() {
- EnsureValidWinFrameInfo();
- if (!CurrentWinFrameInfo->ChainedParent)
- report_fatal_error("End of a chained region outside a chained region!");
+void MCStreamer::EmitWinCFIEndChained(SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
+ if (!CurFrame->ChainedParent)
+ return getContext().reportError(
+ Loc, "End of a chained region outside a chained region!");
MCSymbol *Label = EmitCFILabel();
- CurrentWinFrameInfo->End = Label;
- CurrentWinFrameInfo =
- const_cast<WinEH::FrameInfo *>(CurrentWinFrameInfo->ChainedParent);
+ CurFrame->End = Label;
+ CurrentWinFrameInfo = const_cast<WinEH::FrameInfo *>(CurFrame->ChainedParent);
}
-void MCStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
- bool Except) {
- EnsureValidWinFrameInfo();
- if (CurrentWinFrameInfo->ChainedParent)
- report_fatal_error("Chained unwind areas can't have handlers!");
- CurrentWinFrameInfo->ExceptionHandler = Sym;
+void MCStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
+ SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
+ if (CurFrame->ChainedParent)
+ return getContext().reportError(
+ Loc, "Chained unwind areas can't have handlers!");
+ CurFrame->ExceptionHandler = Sym;
if (!Except && !Unwind)
- report_fatal_error("Don't know what kind of handler this is!");
+ getContext().reportError(Loc, "Don't know what kind of handler this is!");
if (Unwind)
- CurrentWinFrameInfo->HandlesUnwind = true;
+ CurFrame->HandlesUnwind = true;
if (Except)
- CurrentWinFrameInfo->HandlesExceptions = true;
+ CurFrame->HandlesExceptions = true;
}
-void MCStreamer::EmitWinEHHandlerData() {
- EnsureValidWinFrameInfo();
- if (CurrentWinFrameInfo->ChainedParent)
- report_fatal_error("Chained unwind areas can't have handlers!");
+void MCStreamer::EmitWinEHHandlerData(SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
+ if (CurFrame->ChainedParent)
+ getContext().reportError(Loc, "Chained unwind areas can't have handlers!");
}
static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID,
@@ -616,86 +673,110 @@ MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) {
void MCStreamer::EmitSyntaxDirective() {}
-void MCStreamer::EmitWinCFIPushReg(unsigned Register) {
- EnsureValidWinFrameInfo();
+void MCStreamer::EmitWinCFIPushReg(unsigned Register, SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
MCSymbol *Label = EmitCFILabel();
WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(Label, Register);
- CurrentWinFrameInfo->Instructions.push_back(Inst);
+ CurFrame->Instructions.push_back(Inst);
}
-void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) {
- EnsureValidWinFrameInfo();
- if (CurrentWinFrameInfo->LastFrameInst >= 0)
- report_fatal_error("Frame register and offset already specified!");
+void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset,
+ SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
+ if (CurFrame->LastFrameInst >= 0)
+ return getContext().reportError(
+ Loc, "frame register and offset can be set at most once");
if (Offset & 0x0F)
- report_fatal_error("Misaligned frame pointer offset!");
+ return getContext().reportError(Loc, "offset is not a multiple of 16");
if (Offset > 240)
- report_fatal_error("Frame offset must be less than or equal to 240!");
+ return getContext().reportError(
+ Loc, "frame offset must be less than or equal to 240");
MCSymbol *Label = EmitCFILabel();
WinEH::Instruction Inst =
Win64EH::Instruction::SetFPReg(Label, Register, Offset);
- CurrentWinFrameInfo->LastFrameInst = CurrentWinFrameInfo->Instructions.size();
- CurrentWinFrameInfo->Instructions.push_back(Inst);
+ CurFrame->LastFrameInst = CurFrame->Instructions.size();
+ CurFrame->Instructions.push_back(Inst);
}
-void MCStreamer::EmitWinCFIAllocStack(unsigned Size) {
- EnsureValidWinFrameInfo();
+void MCStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
if (Size == 0)
- report_fatal_error("Allocation size must be non-zero!");
+ return getContext().reportError(Loc,
+ "stack allocation size must be non-zero");
if (Size & 7)
- report_fatal_error("Misaligned stack allocation!");
+ return getContext().reportError(
+ Loc, "stack allocation size is not a multiple of 8");
MCSymbol *Label = EmitCFILabel();
WinEH::Instruction Inst = Win64EH::Instruction::Alloc(Label, Size);
- CurrentWinFrameInfo->Instructions.push_back(Inst);
+ CurFrame->Instructions.push_back(Inst);
}
-void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) {
- EnsureValidWinFrameInfo();
+void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset,
+ SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
+
if (Offset & 7)
- report_fatal_error("Misaligned saved register offset!");
+ return getContext().reportError(
+ Loc, "register save offset is not 8 byte aligned");
MCSymbol *Label = EmitCFILabel();
WinEH::Instruction Inst =
Win64EH::Instruction::SaveNonVol(Label, Register, Offset);
- CurrentWinFrameInfo->Instructions.push_back(Inst);
+ CurFrame->Instructions.push_back(Inst);
}
-void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) {
- EnsureValidWinFrameInfo();
+void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
+ SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
if (Offset & 0x0F)
- report_fatal_error("Misaligned saved vector register offset!");
+ return getContext().reportError(Loc, "offset is not a multiple of 16");
MCSymbol *Label = EmitCFILabel();
WinEH::Instruction Inst =
Win64EH::Instruction::SaveXMM(Label, Register, Offset);
- CurrentWinFrameInfo->Instructions.push_back(Inst);
+ CurFrame->Instructions.push_back(Inst);
}
-void MCStreamer::EmitWinCFIPushFrame(bool Code) {
- EnsureValidWinFrameInfo();
- if (!CurrentWinFrameInfo->Instructions.empty())
- report_fatal_error("If present, PushMachFrame must be the first UOP");
+void MCStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
+ if (!CurFrame->Instructions.empty())
+ return getContext().reportError(
+ Loc, "If present, PushMachFrame must be the first UOP");
MCSymbol *Label = EmitCFILabel();
WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(Label, Code);
- CurrentWinFrameInfo->Instructions.push_back(Inst);
+ CurFrame->Instructions.push_back(Inst);
}
-void MCStreamer::EmitWinCFIEndProlog() {
- EnsureValidWinFrameInfo();
+void MCStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
MCSymbol *Label = EmitCFILabel();
- CurrentWinFrameInfo->PrologEnd = Label;
+ CurFrame->PrologEnd = Label;
}
void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
@@ -725,7 +806,9 @@ void MCStreamer::EmitWindowsUnwindTables() {
void MCStreamer::Finish() {
if (!DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End)
- report_fatal_error("Unfinished frame!");
+ getContext().reportError(SMLoc(), "Unfinished frame!");
+ if (!WinFrameInfos.empty() && !WinFrameInfos.back()->End)
+ getContext().reportError(SMLoc(), "Unfinished frame!");
MCTargetStreamer *TS = getTargetStreamer();
if (TS)
@@ -876,3 +959,32 @@ MCSymbol *MCStreamer::endSection(MCSection *Section) {
EmitLabel(Sym);
return Sym;
}
+
+void MCStreamer::EmitVersionForTarget(const Triple &Target) {
+ if (!Target.isOSBinFormatMachO() || !Target.isOSDarwin())
+ return;
+ // Do we even know the version?
+ if (Target.getOSMajorVersion() == 0)
+ return;
+
+ unsigned Major;
+ unsigned Minor;
+ unsigned Update;
+ MCVersionMinType VersionType;
+ if (Target.isWatchOS()) {
+ VersionType = MCVM_WatchOSVersionMin;
+ Target.getWatchOSVersion(Major, Minor, Update);
+ } else if (Target.isTvOS()) {
+ VersionType = MCVM_TvOSVersionMin;
+ Target.getiOSVersion(Major, Minor, Update);
+ } else if (Target.isMacOSX()) {
+ VersionType = MCVM_OSXVersionMin;
+ if (!Target.getMacOSXVersion(Major, Minor, Update))
+ Major = 0;
+ } else {
+ VersionType = MCVM_IOSVersionMin;
+ Target.getiOSVersion(Major, Minor, Update);
+ }
+ if (Major != 0)
+ EmitVersionMin(VersionType, Major, Minor, Update);
+}
diff --git a/lib/MC/MCSubtargetInfo.cpp b/lib/MC/MCSubtargetInfo.cpp
index 385cdcc62320..8b9b076382e2 100644
--- a/lib/MC/MCSubtargetInfo.cpp
+++ b/lib/MC/MCSubtargetInfo.cpp
@@ -75,6 +75,18 @@ FeatureBitset MCSubtargetInfo::ApplyFeatureFlag(StringRef FS) {
return FeatureBits;
}
+bool MCSubtargetInfo::checkFeatures(StringRef FS) const {
+ SubtargetFeatures T(FS);
+ FeatureBitset Set, All;
+ for (std::string F : T.getFeatures()) {
+ SubtargetFeatures::ApplyFeatureFlag(Set, F, ProcFeatures);
+ if (F[0] == '-')
+ F[0] = '+';
+ SubtargetFeatures::ApplyFeatureFlag(All, F, ProcFeatures);
+ }
+ return (FeatureBits & All) == Set;
+}
+
const MCSchedModel &MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
assert(ProcSchedModels && "Processor machine model not available!");
@@ -102,7 +114,7 @@ const MCSchedModel &MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
InstrItineraryData
MCSubtargetInfo::getInstrItineraryForCPU(StringRef CPU) const {
- const MCSchedModel SchedModel = getSchedModelForCPU(CPU);
+ const MCSchedModel &SchedModel = getSchedModelForCPU(CPU);
return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths);
}
diff --git a/lib/MC/MCSymbolELF.cpp b/lib/MC/MCSymbolELF.cpp
index 67449eb6dcf9..12c724f6b1ee 100644
--- a/lib/MC/MCSymbolELF.cpp
+++ b/lib/MC/MCSymbolELF.cpp
@@ -9,7 +9,6 @@
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCFixupKindInfo.h"
namespace llvm {
diff --git a/lib/MC/MCWasmStreamer.cpp b/lib/MC/MCWasmStreamer.cpp
index 02fa070f0c57..d9cefbd3994f 100644
--- a/lib/MC/MCWasmStreamer.cpp
+++ b/lib/MC/MCWasmStreamer.cpp
@@ -15,16 +15,13 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectStreamer.h"
-#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionWasm.h"
#include "llvm/MC/MCSymbol.h"
@@ -98,9 +95,13 @@ bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
case MCSA_WeakDefAutoPrivate:
case MCSA_Invalid:
case MCSA_IndirectSymbol:
- case MCSA_Hidden:
+ case MCSA_Protected:
return false;
+ case MCSA_Hidden:
+ Symbol->setHidden(true);
+ break;
+
case MCSA_Weak:
case MCSA_WeakReference:
Symbol->setWeak(true);
@@ -156,7 +157,7 @@ void MCWasmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
void MCWasmStreamer::EmitIdent(StringRef IdentString) {
MCSection *Comment = getAssembler().getContext().getWasmSection(
- ".comment", 0, 0);
+ ".comment", SectionKind::getMetadata());
PushSection();
SwitchSection(Comment);
if (!SeenIdent) {
@@ -200,10 +201,13 @@ void MCWasmStreamer::FinishImpl() {
this->MCObjectStreamer::FinishImpl();
}
-MCStreamer *llvm::createWasmStreamer(MCContext &Context, MCAsmBackend &MAB,
- raw_pwrite_stream &OS, MCCodeEmitter *CE,
+MCStreamer *llvm::createWasmStreamer(MCContext &Context,
+ std::unique_ptr<MCAsmBackend> &&MAB,
+ raw_pwrite_stream &OS,
+ std::unique_ptr<MCCodeEmitter> &&CE,
bool RelaxAll) {
- MCWasmStreamer *S = new MCWasmStreamer(Context, MAB, OS, CE);
+ MCWasmStreamer *S =
+ new MCWasmStreamer(Context, std::move(MAB), OS, std::move(CE));
if (RelaxAll)
S->getAssembler().setRelaxAll(true);
return S;
diff --git a/lib/MC/MCWin64EH.cpp b/lib/MC/MCWin64EH.cpp
index fdc4c10cd6ce..1407f25e6f2a 100644
--- a/lib/MC/MCWin64EH.cpp
+++ b/lib/MC/MCWin64EH.cpp
@@ -11,8 +11,6 @@
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Win64EH.h"
@@ -220,17 +218,17 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
void llvm::Win64EH::UnwindEmitter::Emit(MCStreamer &Streamer) const {
// Emit the unwind info structs first.
- for (WinEH::FrameInfo *CFI : Streamer.getWinFrameInfos()) {
+ for (const auto &CFI : Streamer.getWinFrameInfos()) {
MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
Streamer.SwitchSection(XData);
- ::EmitUnwindInfo(Streamer, CFI);
+ ::EmitUnwindInfo(Streamer, CFI.get());
}
// Now emit RUNTIME_FUNCTION entries.
- for (WinEH::FrameInfo *CFI : Streamer.getWinFrameInfos()) {
+ for (const auto &CFI : Streamer.getWinFrameInfos()) {
MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
Streamer.SwitchSection(PData);
- EmitRuntimeFunction(Streamer, CFI);
+ EmitRuntimeFunction(Streamer, CFI.get());
}
}
diff --git a/lib/MC/MCWinCOFFStreamer.cpp b/lib/MC/MCWinCOFFStreamer.cpp
index bf341bb1f451..c2583d95c5ed 100644
--- a/lib/MC/MCWinCOFFStreamer.cpp
+++ b/lib/MC/MCWinCOFFStreamer.cpp
@@ -41,9 +41,12 @@ using namespace llvm;
#define DEBUG_TYPE "WinCOFFStreamer"
-MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB,
- MCCodeEmitter &CE, raw_pwrite_stream &OS)
- : MCObjectStreamer(Context, MAB, OS, &CE), CurSymbol(nullptr) {}
+MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context,
+ std::unique_ptr<MCAsmBackend> MAB,
+ std::unique_ptr<MCCodeEmitter> CE,
+ raw_pwrite_stream &OS)
+ : MCObjectStreamer(Context, std::move(MAB), OS, std::move(CE)),
+ CurSymbol(nullptr) {}
void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst,
const MCSubtargetInfo &STI) {
@@ -179,7 +182,7 @@ void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
if (SXData->getAlignment() < 4)
SXData->setAlignment(4);
- new MCSafeSEHFragment(Symbol, SXData);
+ new MCSymbolIdFragment(Symbol, SXData);
getAssembler().registerSymbol(*Symbol);
CSymbol->setIsSafeSEH();
@@ -285,7 +288,7 @@ void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) {
llvm_unreachable("not implemented");
}
-void MCWinCOFFStreamer::EmitWinEHHandlerData() {
+void MCWinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) {
llvm_unreachable("not implemented");
}
diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp
index 62bf0a58fdfa..c7eaa76ace3c 100644
--- a/lib/MC/MachObjectWriter.cpp
+++ b/lib/MC/MachObjectWriter.cpp
@@ -721,6 +721,16 @@ bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
return false;
}
+static MachO::LoadCommandType getLCFromMCVM(MCVersionMinType Type) {
+ switch (Type) {
+ case MCVM_OSXVersionMin: return MachO::LC_VERSION_MIN_MACOSX;
+ case MCVM_IOSVersionMin: return MachO::LC_VERSION_MIN_IPHONEOS;
+ case MCVM_TvOSVersionMin: return MachO::LC_VERSION_MIN_TVOS;
+ case MCVM_WatchOSVersionMin: return MachO::LC_VERSION_MIN_WATCHOS;
+ }
+ llvm_unreachable("Invalid mc version min type");
+}
+
void MachObjectWriter::writeObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
// Compute symbol table information and bind symbol indices.
@@ -728,8 +738,8 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
UndefinedSymbolData);
unsigned NumSections = Asm.size();
- const MCAssembler::VersionMinInfoType &VersionInfo =
- Layout.getAssembler().getVersionMinInfo();
+ const MCAssembler::VersionInfoType &VersionInfo =
+ Layout.getAssembler().getVersionInfo();
// The section data starts after the header, the segment load command (and
// section headers) and the symbol table.
@@ -741,7 +751,10 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
// Add the deployment target version info load command size, if used.
if (VersionInfo.Major != 0) {
++NumLoadCommands;
- LoadCommandsSize += sizeof(MachO::version_min_command);
+ if (VersionInfo.EmitBuildVersion)
+ LoadCommandsSize += sizeof(MachO::build_version_command);
+ else
+ LoadCommandsSize += sizeof(MachO::version_min_command);
}
// Add the data-in-code load command size, if used.
@@ -832,25 +845,22 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
assert(VersionInfo.Major < 65536 && "unencodable major target version");
uint32_t EncodedVersion = VersionInfo.Update | (VersionInfo.Minor << 8) |
(VersionInfo.Major << 16);
- MachO::LoadCommandType LCType;
- switch (VersionInfo.Kind) {
- case MCVM_OSXVersionMin:
- LCType = MachO::LC_VERSION_MIN_MACOSX;
- break;
- case MCVM_IOSVersionMin:
- LCType = MachO::LC_VERSION_MIN_IPHONEOS;
- break;
- case MCVM_TvOSVersionMin:
- LCType = MachO::LC_VERSION_MIN_TVOS;
- break;
- case MCVM_WatchOSVersionMin:
- LCType = MachO::LC_VERSION_MIN_WATCHOS;
- break;
+ if (VersionInfo.EmitBuildVersion) {
+ // FIXME: Currently empty tools. Add clang version in the future.
+ write32(MachO::LC_BUILD_VERSION);
+ write32(sizeof(MachO::build_version_command));
+ write32(VersionInfo.TypeOrPlatform.Platform);
+ write32(EncodedVersion);
+ write32(0); // SDK version.
+ write32(0); // Empty tools list.
+ } else {
+ MachO::LoadCommandType LCType
+ = getLCFromMCVM(VersionInfo.TypeOrPlatform.Type);
+ write32(LCType);
+ write32(sizeof(MachO::version_min_command));
+ write32(EncodedVersion);
+ write32(0); // reserved.
}
- write32(LCType);
- write32(sizeof(MachO::version_min_command));
- write32(EncodedVersion);
- write32(0); // reserved.
}
// Write the data-in-code load command, if used.
@@ -994,8 +1004,9 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
}
}
-MCObjectWriter *llvm::createMachObjectWriter(MCMachObjectTargetWriter *MOTW,
- raw_pwrite_stream &OS,
- bool IsLittleEndian) {
- return new MachObjectWriter(MOTW, OS, IsLittleEndian);
+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,
+ IsLittleEndian);
}
diff --git a/lib/MC/StringTableBuilder.cpp b/lib/MC/StringTableBuilder.cpp
index 6025a20a9c19..531bc930c89b 100644
--- a/lib/MC/StringTableBuilder.cpp
+++ b/lib/MC/StringTableBuilder.cpp
@@ -82,32 +82,34 @@ static int charTailAt(StringPair *P, size_t Pos) {
// Three-way radix quicksort. This is much faster than std::sort with strcmp
// because it does not compare characters that we already know the same.
-static void multikey_qsort(StringPair **Begin, StringPair **End, int Pos) {
+static void multikeySort(MutableArrayRef<StringPair *> Vec, int Pos) {
tailcall:
- if (End - Begin <= 1)
+ if (Vec.size() <= 1)
return;
- // Partition items. Items in [Begin, P) are greater than the pivot,
- // [P, Q) are the same as the pivot, and [Q, End) are less than the pivot.
- int Pivot = charTailAt(*Begin, Pos);
- StringPair **P = Begin;
- StringPair **Q = End;
- for (StringPair **R = Begin + 1; R < Q;) {
- int C = charTailAt(*R, Pos);
+ // Partition items so that items in [0, I) are greater than the pivot,
+ // [I, J) are the same as the pivot, and [J, Vec.size()) are less than
+ // the pivot.
+ int Pivot = charTailAt(Vec[0], Pos);
+ size_t I = 0;
+ size_t J = Vec.size();
+ for (size_t K = 1; K < J;) {
+ int C = charTailAt(Vec[K], Pos);
if (C > Pivot)
- std::swap(*P++, *R++);
+ std::swap(Vec[I++], Vec[K++]);
else if (C < Pivot)
- std::swap(*--Q, *R);
+ std::swap(Vec[--J], Vec[K]);
else
- R++;
+ K++;
}
- multikey_qsort(Begin, P, Pos);
- multikey_qsort(Q, End, Pos);
+ multikeySort(Vec.slice(0, I), Pos);
+ multikeySort(Vec.slice(J), Pos);
+
+ // multikeySort(Vec.slice(I, J - I), Pos + 1), but with
+ // tail call optimization.
if (Pivot != -1) {
- // qsort(P, Q, Pos + 1), but with tail call optimization.
- Begin = P;
- End = Q;
+ Vec = Vec.slice(I, J - I);
++Pos;
goto tailcall;
}
@@ -130,12 +132,7 @@ void StringTableBuilder::finalizeStringTable(bool Optimize) {
for (StringPair &P : StringIndexMap)
Strings.push_back(&P);
- if (!Strings.empty()) {
- // If we're optimizing, sort by name. If not, sort by previously assigned
- // offset.
- multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 0);
- }
-
+ multikeySort(Strings, 0);
initSize();
StringRef Previous;
diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp
index 0d31f65c49d9..6e76c5fac35f 100644
--- a/lib/MC/WasmObjectWriter.cpp
+++ b/lib/MC/WasmObjectWriter.cpp
@@ -15,13 +15,11 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixupKindInfo.h"
-#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionWasm.h"
#include "llvm/MC/MCSymbolWasm.h"
@@ -96,12 +94,26 @@ struct WasmFunctionTypeDenseMapInfo {
}
};
+// A wasm data segment. A wasm binary contains only a single data section
+// but that can contain many segments, each with their own virtual location
+// in memory. Each MCSection data created by llvm is modeled as its own
+// wasm data segment.
+struct WasmDataSegment {
+ MCSectionWasm *Section;
+ StringRef Name;
+ uint32_t Offset;
+ uint32_t Alignment;
+ uint32_t Flags;
+ SmallVector<char, 4> Data;
+};
+
// A wasm import to be written into the import section.
struct WasmImport {
StringRef ModuleName;
StringRef FieldName;
unsigned Kind;
int32_t Type;
+ bool IsMutable;
};
// A wasm function to be written into the function section.
@@ -142,9 +154,9 @@ struct WasmRelocationEntry {
bool hasAddend() const {
switch (Type) {
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
return true;
default:
return false;
@@ -153,7 +165,8 @@ struct WasmRelocationEntry {
void print(raw_ostream &Out) const {
Out << "Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend
- << ", Type=" << Type << ", FixupSection=" << FixupSection;
+ << ", Type=" << Type
+ << ", FixupSection=" << FixupSection->getSectionName();
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -199,6 +212,8 @@ class WasmObjectWriter : public MCObjectWriter {
DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo>
FunctionTypeIndices;
SmallVector<WasmFunctionType, 4> FunctionTypes;
+ SmallVector<WasmGlobal, 4> Globals;
+ unsigned NumGlobalImports = 0;
// TargetObjectWriter wrappers.
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
@@ -211,8 +226,10 @@ class WasmObjectWriter : public MCObjectWriter {
void endSection(SectionBookkeeping &Section);
public:
- WasmObjectWriter(MCWasmObjectTargetWriter *MOTW, raw_pwrite_stream &OS)
- : MCObjectWriter(OS, /*IsLittleEndian=*/true), TargetObjectWriter(MOTW) {}
+ WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS)
+ : MCObjectWriter(OS, /*IsLittleEndian=*/true),
+ TargetObjectWriter(std::move(MOTW)) {}
private:
~WasmObjectWriter() override;
@@ -225,7 +242,9 @@ private:
IndirectSymbolIndices.clear();
FunctionTypeIndices.clear();
FunctionTypes.clear();
+ Globals.clear();
MCObjectWriter::reset();
+ NumGlobalImports = 0;
}
void writeHeader(const MCAssembler &Asm);
@@ -248,33 +267,31 @@ private:
encodeSLEB128(int32_t(Ty), getStream());
}
- void writeTypeSection(const SmallVector<WasmFunctionType, 4> &FunctionTypes);
- void writeImportSection(const SmallVector<WasmImport, 4> &Imports);
- void writeFunctionSection(const SmallVector<WasmFunction, 4> &Functions);
- void writeTableSection(uint32_t NumElements);
- void writeMemorySection(const SmallVector<char, 0> &DataBytes);
- void writeGlobalSection(const SmallVector<WasmGlobal, 4> &Globals);
- void writeExportSection(const SmallVector<WasmExport, 4> &Exports);
- void writeElemSection(const SmallVector<uint32_t, 4> &TableElems);
+ void writeTypeSection(ArrayRef<WasmFunctionType> FunctionTypes);
+ void writeImportSection(ArrayRef<WasmImport> Imports, uint32_t DataSize,
+ uint32_t NumElements);
+ void writeFunctionSection(ArrayRef<WasmFunction> Functions);
+ void writeGlobalSection();
+ void writeExportSection(ArrayRef<WasmExport> Exports);
+ void writeElemSection(ArrayRef<uint32_t> TableElems);
void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
- const SmallVector<WasmFunction, 4> &Functions);
- uint64_t
- writeDataSection(const SmallVector<char, 0> &DataBytes);
- void writeNameSection(const SmallVector<WasmFunction, 4> &Functions,
- const SmallVector<WasmImport, 4> &Imports,
+ ArrayRef<WasmFunction> Functions);
+ void writeDataSection(ArrayRef<WasmDataSegment> Segments);
+ void writeNameSection(ArrayRef<WasmFunction> Functions,
+ ArrayRef<WasmImport> Imports,
uint32_t NumFuncImports);
void writeCodeRelocSection();
- void writeDataRelocSection(uint64_t DataSectionHeaderSize);
- void writeLinkingMetaDataSection(uint32_t DataSize, uint32_t DataAlignment,
- ArrayRef<StringRef> WeakSymbols,
- bool HasStackPointer,
- uint32_t StackPointerGlobal);
+ void writeDataRelocSection();
+ void writeLinkingMetaDataSection(
+ ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
+ const SmallVector<std::pair<StringRef, uint32_t>, 4> &SymbolFlags,
+ const SmallVector<std::pair<uint16_t, uint32_t>, 2> &InitFuncs);
+ uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
uint64_t ContentsOffset);
- void writeRelocations(ArrayRef<WasmRelocationEntry> Relocations,
- uint64_t HeaderSize);
+ void writeRelocations(ArrayRef<WasmRelocationEntry> Relocations);
uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
uint32_t getFunctionType(const MCSymbolWasm& Symbol);
uint32_t registerFunctionType(const MCSymbolWasm& Symbol);
@@ -284,16 +301,6 @@ private:
WasmObjectWriter::~WasmObjectWriter() {}
-// Return the padding size to write a 32-bit value into a 5-byte ULEB128.
-static unsigned PaddingFor5ByteULEB128(uint32_t X) {
- return X == 0 ? 4 : (4u - (31u - countLeadingZeros(X)) / 7u);
-}
-
-// Return the padding size to write a 32-bit value into a 5-byte SLEB128.
-static unsigned PaddingFor5ByteSLEB128(int32_t X) {
- return 5 - getSLEB128Size(X);
-}
-
// Write out a section header and a patchable section size field.
void WasmObjectWriter::startSection(SectionBookkeeping &Section,
unsigned SectionId,
@@ -328,12 +335,11 @@ void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
report_fatal_error("section size does not fit in a uint32_t");
DEBUG(dbgs() << "endSection size=" << Size << "\n");
- unsigned Padding = PaddingFor5ByteULEB128(Size);
// Write the final section size to the payload_len field, which follows
// the section id byte.
uint8_t Buffer[16];
- unsigned SizeLen = encodeULEB128(Size, Buffer, Padding);
+ unsigned SizeLen = encodeULEB128(Size, Buffer, 5);
assert(SizeLen == 5);
getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset);
}
@@ -361,6 +367,10 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
MCContext &Ctx = Asm.getContext();
+ // The .init_array isn't translated as data, so don't do relocations in it.
+ if (FixupSection.getSectionName().startswith(".init_array"))
+ return;
+
if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
assert(RefB->getKind() == MCSymbolRefExpr::VK_None &&
"Should not have constructed this");
@@ -429,10 +439,13 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
- if (FixupSection.hasInstructions())
- CodeRelocations.push_back(Rec);
- else
+ if (FixupSection.isWasmData())
DataRelocations.push_back(Rec);
+ else if (FixupSection.getKind().isText())
+ CodeRelocations.push_back(Rec);
+ else if (!FixupSection.getKind().isMetadata())
+ // TODO(sbc): Add support for debug sections.
+ llvm_unreachable("unexpected section type");
}
// Write X as an (unsigned) LEB value at offset Offset in Stream, padded
@@ -440,8 +453,7 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
static void
WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
uint8_t Buffer[5];
- unsigned Padding = PaddingFor5ByteULEB128(X);
- unsigned SizeLen = encodeULEB128(X, Buffer, Padding);
+ unsigned SizeLen = encodeULEB128(X, Buffer, 5);
assert(SizeLen == 5);
Stream.pwrite((char *)Buffer, SizeLen, Offset);
}
@@ -451,8 +463,7 @@ WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
static void
WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) {
uint8_t Buffer[5];
- unsigned Padding = PaddingFor5ByteSLEB128(X);
- unsigned SizeLen = encodeSLEB128(X, Buffer, Padding);
+ unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
assert(SizeLen == 5);
Stream.pwrite((char *)Buffer, SizeLen, Offset);
}
@@ -464,19 +475,30 @@ static void WriteI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
}
+static const MCSymbolWasm* ResolveSymbol(const MCSymbolWasm& Symbol) {
+ if (Symbol.isVariable()) {
+ const MCExpr *Expr = Symbol.getVariableValue();
+ auto *Inner = cast<MCSymbolRefExpr>(Expr);
+ return cast<MCSymbolWasm>(&Inner->getSymbol());
+ }
+ return &Symbol;
+}
+
// Compute a value to write into the code at the location covered
// by RelEntry. This value isn't used by the static linker, since
// we have addends; it just serves to make the code more readable
// and to make standalone wasm modules directly usable.
-static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) {
- const MCSymbolWasm *Sym = RelEntry.Symbol;
+uint32_t
+WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
+ const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol);
// For undefined symbols, use a hopefully invalid value.
if (!Sym->isDefined(/*SetUsed=*/false))
return UINT32_MAX;
- const auto &Section = cast<MCSectionWasm>(RelEntry.Symbol->getSection(false));
- uint64_t Address = Section.getSectionOffset() + RelEntry.Addend;
+ uint32_t GlobalIndex = SymbolIndices[Sym];
+ const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports];
+ uint64_t Address = Global.InitialValue + RelEntry.Addend;
// Ignore overflow. LLVM allows address arithmetic to silently wrap.
uint32_t Value = Address;
@@ -484,6 +506,47 @@ static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) {
return Value;
}
+static void addData(SmallVectorImpl<char> &DataBytes,
+ MCSectionWasm &DataSection) {
+ DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n");
+
+ DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
+
+ size_t LastFragmentSize = 0;
+ for (const MCFragment &Frag : DataSection) {
+ if (Frag.hasInstructions())
+ report_fatal_error("only data supported in data sections");
+
+ if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
+ if (Align->getValueSize() != 1)
+ report_fatal_error("only byte values supported for alignment");
+ // If nops are requested, use zeros, as this is the data section.
+ uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
+ uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(),
+ Align->getAlignment()),
+ DataBytes.size() +
+ Align->getMaxBytesToEmit());
+ DataBytes.resize(Size, Value);
+ } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
+ DataBytes.insert(DataBytes.end(), Fill->getSize(), Fill->getValue());
+ } else {
+ const auto &DataFrag = cast<MCDataFragment>(Frag);
+ const SmallVectorImpl<char> &Contents = DataFrag.getContents();
+
+ DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
+ LastFragmentSize = Contents.size();
+ }
+ }
+
+ // Don't allow empty segments, or segments that end with zero-sized
+ // fragment, otherwise the linker cannot map symbols to a unique
+ // data segment. This can be triggered by zero-sized structs
+ // See: test/MC/WebAssembly/bss.ll
+ if (LastFragmentSize == 0)
+ DataBytes.resize(DataBytes.size() + 1);
+ DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
+}
+
uint32_t WasmObjectWriter::getRelocationIndexValue(
const WasmRelocationEntry &RelEntry) {
switch (RelEntry.Type) {
@@ -495,9 +558,9 @@ uint32_t WasmObjectWriter::getRelocationIndexValue(
return IndirectSymbolIndices[RelEntry.Symbol];
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
if (!SymbolIndices.count(RelEntry.Symbol))
report_fatal_error("symbol not found function/global index space: " +
RelEntry.Symbol->getName());
@@ -537,18 +600,18 @@ void WasmObjectWriter::applyRelocations(
WriteI32(Stream, Index, Offset);
break;
}
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: {
- uint32_t Value = ProvisionalValue(RelEntry);
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
+ uint32_t Value = getProvisionalValue(RelEntry);
WritePatchableSLEB(Stream, Value, Offset);
break;
}
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: {
- uint32_t Value = ProvisionalValue(RelEntry);
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: {
+ uint32_t Value = getProvisionalValue(RelEntry);
WritePatchableLEB(Stream, Value, Offset);
break;
}
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: {
- uint32_t Value = ProvisionalValue(RelEntry);
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: {
+ uint32_t Value = getProvisionalValue(RelEntry);
WriteI32(Stream, Value, Offset);
break;
}
@@ -561,12 +624,12 @@ void WasmObjectWriter::applyRelocations(
// Write out the portions of the relocation records that the linker will
// need to handle.
void WasmObjectWriter::writeRelocations(
- ArrayRef<WasmRelocationEntry> Relocations, uint64_t HeaderSize) {
+ ArrayRef<WasmRelocationEntry> Relocations) {
raw_pwrite_stream &Stream = getStream();
for (const WasmRelocationEntry& RelEntry : Relocations) {
uint64_t Offset = RelEntry.Offset +
- RelEntry.FixupSection->getSectionOffset() + HeaderSize;
+ RelEntry.FixupSection->getSectionOffset();
uint32_t Index = getRelocationIndexValue(RelEntry);
encodeULEB128(RelEntry.Type, Stream);
@@ -578,7 +641,7 @@ void WasmObjectWriter::writeRelocations(
}
void WasmObjectWriter::writeTypeSection(
- const SmallVector<WasmFunctionType, 4> &FunctionTypes) {
+ ArrayRef<WasmFunctionType> FunctionTypes) {
if (FunctionTypes.empty())
return;
@@ -600,12 +663,14 @@ void WasmObjectWriter::writeTypeSection(
endSection(Section);
}
-
-void WasmObjectWriter::writeImportSection(
- const SmallVector<WasmImport, 4> &Imports) {
+void WasmObjectWriter::writeImportSection(ArrayRef<WasmImport> Imports,
+ uint32_t DataSize,
+ uint32_t NumElements) {
if (Imports.empty())
return;
+ uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
+
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_IMPORT);
@@ -622,7 +687,16 @@ void WasmObjectWriter::writeImportSection(
break;
case wasm::WASM_EXTERNAL_GLOBAL:
encodeSLEB128(int32_t(Import.Type), getStream());
- encodeULEB128(0, getStream()); // mutability
+ encodeULEB128(int32_t(Import.IsMutable), getStream());
+ break;
+ case wasm::WASM_EXTERNAL_MEMORY:
+ encodeULEB128(0, getStream()); // flags
+ encodeULEB128(NumPages, getStream()); // initial
+ break;
+ case wasm::WASM_EXTERNAL_TABLE:
+ encodeSLEB128(int32_t(Import.Type), getStream());
+ encodeULEB128(0, getStream()); // flags
+ encodeULEB128(NumElements, getStream()); // initial
break;
default:
llvm_unreachable("unsupported import kind");
@@ -632,8 +706,7 @@ void WasmObjectWriter::writeImportSection(
endSection(Section);
}
-void WasmObjectWriter::writeFunctionSection(
- const SmallVector<WasmFunction, 4> &Functions) {
+void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
if (Functions.empty())
return;
@@ -647,43 +720,7 @@ void WasmObjectWriter::writeFunctionSection(
endSection(Section);
}
-void WasmObjectWriter::writeTableSection(uint32_t NumElements) {
- // For now, always emit the table section, since indirect calls are not
- // valid without it. In the future, we could perhaps be more clever and omit
- // it if there are no indirect calls.
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_TABLE);
-
- encodeULEB128(1, getStream()); // The number of tables.
- // Fixed to 1 for now.
- encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); // Type of table
- encodeULEB128(0, getStream()); // flags
- encodeULEB128(NumElements, getStream()); // initial
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeMemorySection(
- const SmallVector<char, 0> &DataBytes) {
- // For now, always emit the memory section, since loads and stores are not
- // valid without it. In the future, we could perhaps be more clever and omit
- // it if there are no loads or stores.
- SectionBookkeeping Section;
- uint32_t NumPages =
- (DataBytes.size() + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
-
- startSection(Section, wasm::WASM_SEC_MEMORY);
- encodeULEB128(1, getStream()); // number of memory spaces
-
- encodeULEB128(0, getStream()); // flags
- encodeULEB128(NumPages, getStream()); // initial
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeGlobalSection(
- const SmallVector<WasmGlobal, 4> &Globals) {
+void WasmObjectWriter::writeGlobalSection() {
if (Globals.empty())
return;
@@ -710,8 +747,7 @@ void WasmObjectWriter::writeGlobalSection(
endSection(Section);
}
-void WasmObjectWriter::writeExportSection(
- const SmallVector<WasmExport, 4> &Exports) {
+void WasmObjectWriter::writeExportSection(ArrayRef<WasmExport> Exports) {
if (Exports.empty())
return;
@@ -728,8 +764,7 @@ void WasmObjectWriter::writeExportSection(
endSection(Section);
}
-void WasmObjectWriter::writeElemSection(
- const SmallVector<uint32_t, 4> &TableElems) {
+void WasmObjectWriter::writeElemSection(ArrayRef<uint32_t> TableElems) {
if (TableElems.empty())
return;
@@ -751,9 +786,9 @@ void WasmObjectWriter::writeElemSection(
endSection(Section);
}
-void WasmObjectWriter::writeCodeSection(
- const MCAssembler &Asm, const MCAsmLayout &Layout,
- const SmallVector<WasmFunction, 4> &Functions) {
+void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ ArrayRef<WasmFunction> Functions) {
if (Functions.empty())
return;
@@ -770,9 +805,7 @@ void WasmObjectWriter::writeCodeSection(
report_fatal_error(".size expression must be evaluatable");
encodeULEB128(Size, getStream());
-
FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset);
-
Asm.writeSectionData(&FuncSection, Layout);
}
@@ -782,33 +815,34 @@ void WasmObjectWriter::writeCodeSection(
endSection(Section);
}
-uint64_t WasmObjectWriter::writeDataSection(
- const SmallVector<char, 0> &DataBytes) {
- if (DataBytes.empty())
- return 0;
+void WasmObjectWriter::writeDataSection(ArrayRef<WasmDataSegment> Segments) {
+ if (Segments.empty())
+ return;
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_DATA);
- encodeULEB128(1, getStream()); // count
- encodeULEB128(0, getStream()); // memory index
- write8(wasm::WASM_OPCODE_I32_CONST);
- encodeSLEB128(0, getStream()); // offset
- write8(wasm::WASM_OPCODE_END);
- encodeULEB128(DataBytes.size(), getStream()); // size
- uint32_t HeaderSize = getStream().tell() - Section.ContentsOffset;
- writeBytes(DataBytes); // data
+ encodeULEB128(Segments.size(), getStream()); // count
+
+ for (const WasmDataSegment & Segment : Segments) {
+ encodeULEB128(0, getStream()); // memory index
+ write8(wasm::WASM_OPCODE_I32_CONST);
+ encodeSLEB128(Segment.Offset, getStream()); // offset
+ write8(wasm::WASM_OPCODE_END);
+ encodeULEB128(Segment.Data.size(), getStream()); // size
+ Segment.Section->setSectionOffset(getStream().tell() - Section.ContentsOffset);
+ writeBytes(Segment.Data); // data
+ }
// Apply fixups.
- applyRelocations(DataRelocations, Section.ContentsOffset + HeaderSize);
+ applyRelocations(DataRelocations, Section.ContentsOffset);
endSection(Section);
- return HeaderSize;
}
void WasmObjectWriter::writeNameSection(
- const SmallVector<WasmFunction, 4> &Functions,
- const SmallVector<WasmImport, 4> &Imports,
+ ArrayRef<WasmFunction> Functions,
+ ArrayRef<WasmImport> Imports,
unsigned NumFuncImports) {
uint32_t TotalFunctions = NumFuncImports + Functions.size();
if (TotalFunctions == 0)
@@ -851,12 +885,12 @@ void WasmObjectWriter::writeCodeRelocSection() {
encodeULEB128(wasm::WASM_SEC_CODE, getStream());
encodeULEB128(CodeRelocations.size(), getStream());
- writeRelocations(CodeRelocations, 0);
+ writeRelocations(CodeRelocations);
endSection(Section);
}
-void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) {
+void WasmObjectWriter::writeDataRelocSection() {
// See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
// for descriptions of the reloc sections.
@@ -869,30 +903,25 @@ void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) {
encodeULEB128(wasm::WASM_SEC_DATA, getStream());
encodeULEB128(DataRelocations.size(), getStream());
- writeRelocations(DataRelocations, DataSectionHeaderSize);
+ writeRelocations(DataRelocations);
endSection(Section);
}
void WasmObjectWriter::writeLinkingMetaDataSection(
- uint32_t DataSize, uint32_t DataAlignment, ArrayRef<StringRef> WeakSymbols,
- bool HasStackPointer, uint32_t StackPointerGlobal) {
+ ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
+ const SmallVector<std::pair<StringRef, uint32_t>, 4> &SymbolFlags,
+ const SmallVector<std::pair<uint16_t, uint32_t>, 2> &InitFuncs) {
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
SectionBookkeeping SubSection;
- if (HasStackPointer) {
- startSection(SubSection, wasm::WASM_STACK_POINTER);
- encodeULEB128(StackPointerGlobal, getStream()); // id
- endSection(SubSection);
- }
-
- if (WeakSymbols.size() != 0) {
+ if (SymbolFlags.size() != 0) {
startSection(SubSection, wasm::WASM_SYMBOL_INFO);
- encodeULEB128(WeakSymbols.size(), getStream());
- for (const StringRef Export: WeakSymbols) {
- writeString(Export);
- encodeULEB128(wasm::WASM_SYMBOL_FLAG_WEAK, getStream());
+ encodeULEB128(SymbolFlags.size(), getStream());
+ for (auto Pair: SymbolFlags) {
+ writeString(Pair.first);
+ encodeULEB128(Pair.second, getStream());
}
endSection(SubSection);
}
@@ -901,9 +930,26 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
startSection(SubSection, wasm::WASM_DATA_SIZE);
encodeULEB128(DataSize, getStream());
endSection(SubSection);
+ }
- startSection(SubSection, wasm::WASM_DATA_ALIGNMENT);
- encodeULEB128(DataAlignment, getStream());
+ if (Segments.size()) {
+ startSection(SubSection, wasm::WASM_SEGMENT_INFO);
+ encodeULEB128(Segments.size(), getStream());
+ for (const WasmDataSegment &Segment : Segments) {
+ writeString(Segment.Name);
+ encodeULEB128(Segment.Alignment, getStream());
+ encodeULEB128(Segment.Flags, getStream());
+ }
+ endSection(SubSection);
+ }
+
+ if (!InitFuncs.empty()) {
+ startSection(SubSection, wasm::WASM_INIT_FUNCS);
+ encodeULEB128(InitFuncs.size(), getStream());
+ for (auto &StartFunc : InitFuncs) {
+ encodeULEB128(StartFunc.first, getStream()); // priority
+ encodeULEB128(StartFunc.second, getStream()); // function index
+ }
endSection(SubSection);
}
@@ -920,16 +966,9 @@ uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm& Symbol) {
assert(Symbol.isFunction());
WasmFunctionType F;
- if (Symbol.isVariable()) {
- const MCExpr *Expr = Symbol.getVariableValue();
- auto *Inner = cast<MCSymbolRefExpr>(Expr);
- const auto *ResolvedSym = cast<MCSymbolWasm>(&Inner->getSymbol());
- F.Returns = ResolvedSym->getReturns();
- F.Params = ResolvedSym->getParams();
- } else {
- F.Returns = Symbol.getReturns();
- F.Params = Symbol.getParams();
- }
+ const MCSymbolWasm* ResolvedSym = ResolveSymbol(Symbol);
+ F.Returns = ResolvedSym->getReturns();
+ F.Params = ResolvedSym->getParams();
auto Pair =
FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
@@ -951,23 +990,20 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
// Collect information from the available symbols.
SmallVector<WasmFunction, 4> Functions;
SmallVector<uint32_t, 4> TableElems;
- SmallVector<WasmGlobal, 4> Globals;
SmallVector<WasmImport, 4> Imports;
SmallVector<WasmExport, 4> Exports;
- SmallVector<StringRef, 4> WeakSymbols;
+ SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags;
+ SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken;
unsigned NumFuncImports = 0;
- unsigned NumGlobalImports = 0;
- SmallVector<char, 0> DataBytes;
- uint32_t DataAlignment = 1;
- uint32_t StackPointerGlobal = 0;
- bool HasStackPointer = false;
+ SmallVector<WasmDataSegment, 4> DataSegments;
+ uint32_t DataSize = 0;
// Populate the IsAddressTaken set.
for (const WasmRelocationEntry &RelEntry : CodeRelocations) {
switch (RelEntry.Type) {
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
IsAddressTaken.insert(RelEntry.Symbol);
break;
default:
@@ -977,7 +1013,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
for (const WasmRelocationEntry &RelEntry : DataRelocations) {
switch (RelEntry.Type) {
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
IsAddressTaken.insert(RelEntry.Symbol);
break;
default:
@@ -985,42 +1021,11 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
}
}
- // Populate the Imports set.
- for (const MCSymbol &S : Asm.symbols()) {
- const auto &WS = static_cast<const MCSymbolWasm &>(S);
-
- if (WS.isTemporary())
- continue;
-
- if (WS.isFunction())
- registerFunctionType(WS);
-
- // If the symbol is not defined in this translation unit, import it.
- if (!WS.isDefined(/*SetUsed=*/false) || WS.isVariable()) {
- WasmImport Import;
- Import.ModuleName = WS.getModuleName();
- Import.FieldName = WS.getName();
-
- if (WS.isFunction()) {
- Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
- Import.Type = getFunctionType(WS);
- SymbolIndices[&WS] = NumFuncImports;
- ++NumFuncImports;
- } else {
- Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
- Import.Type = int32_t(PtrType);
- SymbolIndices[&WS] = NumGlobalImports;
- ++NumGlobalImports;
- }
-
- Imports.push_back(Import);
- }
- }
-
// In the special .global_variables section, we've encoded global
// variables used by the function. Translate them into the Globals
// list.
- MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0);
+ MCSectionWasm *GlobalVars =
+ Ctx.getWasmSection(".global_variables", SectionKind::getMetadata());
if (!GlobalVars->getFragmentList().empty()) {
if (GlobalVars->getFragmentList().size() != 1)
report_fatal_error("only one .global_variables fragment supported");
@@ -1074,23 +1079,91 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
}
}
- // In the special .stack_pointer section, we've encoded the stack pointer
- // index.
- MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", 0, 0);
- if (!StackPtr->getFragmentList().empty()) {
- if (StackPtr->getFragmentList().size() != 1)
- report_fatal_error("only one .stack_pointer fragment supported");
- const MCFragment &Frag = *StackPtr->begin();
- if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
- report_fatal_error("only data supported in .stack_pointer");
- const auto &DataFrag = cast<MCDataFragment>(Frag);
- if (!DataFrag.getFixups().empty())
- report_fatal_error("fixups not supported in .stack_pointer");
- const SmallVectorImpl<char> &Contents = DataFrag.getContents();
- if (Contents.size() != 4)
- report_fatal_error("only one entry supported in .stack_pointer");
- HasStackPointer = true;
- StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
+ // For now, always emit the memory import, since loads and stores are not
+ // valid without it. In the future, we could perhaps be more clever and omit
+ // it if there are no loads or stores.
+ MCSymbolWasm *MemorySym =
+ cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__linear_memory"));
+ WasmImport MemImport;
+ MemImport.ModuleName = MemorySym->getModuleName();
+ MemImport.FieldName = MemorySym->getName();
+ MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
+ Imports.push_back(MemImport);
+
+ // For now, always emit the table section, since indirect calls are not
+ // valid without it. In the future, we could perhaps be more clever and omit
+ // it if there are no indirect calls.
+ MCSymbolWasm *TableSym =
+ cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__indirect_function_table"));
+ WasmImport TableImport;
+ TableImport.ModuleName = TableSym->getModuleName();
+ TableImport.FieldName = TableSym->getName();
+ TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
+ TableImport.Type = wasm::WASM_TYPE_ANYFUNC;
+ Imports.push_back(TableImport);
+
+ // Populate FunctionTypeIndices and Imports.
+ for (const MCSymbol &S : Asm.symbols()) {
+ const auto &WS = static_cast<const MCSymbolWasm &>(S);
+
+ // Register types for all functions, including those with private linkage
+ // (making them
+ // because wasm always needs a type signature.
+ if (WS.isFunction())
+ registerFunctionType(WS);
+
+ if (WS.isTemporary())
+ continue;
+
+ // If the symbol is not defined in this translation unit, import it.
+ if (!WS.isDefined(/*SetUsed=*/false)) {
+ WasmImport Import;
+ Import.ModuleName = WS.getModuleName();
+ Import.FieldName = WS.getName();
+
+ if (WS.isFunction()) {
+ Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
+ Import.Type = getFunctionType(WS);
+ SymbolIndices[&WS] = NumFuncImports;
+ ++NumFuncImports;
+ } else {
+ Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
+ Import.Type = int32_t(PtrType);
+ Import.IsMutable = false;
+ SymbolIndices[&WS] = NumGlobalImports;
+
+ // If this global is the stack pointer, make it mutable and remember it
+ // so that we can emit metadata for it.
+ if (WS.getName() == "__stack_pointer")
+ Import.IsMutable = true;
+
+ ++NumGlobalImports;
+ }
+
+ Imports.push_back(Import);
+ }
+ }
+
+ for (MCSection &Sec : Asm) {
+ auto &Section = static_cast<MCSectionWasm &>(Sec);
+ if (!Section.isWasmData())
+ continue;
+
+ // .init_array sections are handled specially elsewhere.
+ if (cast<MCSectionWasm>(Sec).getSectionName().startswith(".init_array"))
+ continue;
+
+ DataSize = alignTo(DataSize, Section.getAlignment());
+ DataSegments.emplace_back();
+ WasmDataSegment &Segment = DataSegments.back();
+ Segment.Name = Section.getSectionName();
+ Segment.Offset = DataSize;
+ Segment.Section = &Section;
+ addData(Segment.Data, Section);
+ Segment.Alignment = Section.getAlignment();
+ Segment.Flags = 0;
+ DataSize += Segment.Data.size();
+ Section.setMemoryOffset(Segment.Offset);
}
// Handle regular defined and undefined symbols.
@@ -1106,10 +1179,14 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
<< S.isExternal() << " isTemporary=" << S.isTemporary()
<< " isFunction=" << WS.isFunction()
<< " isWeak=" << WS.isWeak()
+ << " isHidden=" << WS.isHidden()
<< " isVariable=" << WS.isVariable() << "\n");
- if (WS.isWeak())
- WeakSymbols.push_back(WS.getName());
+ if (WS.isWeak() || WS.isHidden()) {
+ uint32_t Flags = (WS.isWeak() ? wasm::WASM_SYMBOL_BINDING_WEAK : 0) |
+ (WS.isHidden() ? wasm::WASM_SYMBOL_VISIBILITY_HIDDEN : 0);
+ SymbolFlags.emplace_back(WS.getName(), Flags);
+ }
if (WS.isVariable())
continue;
@@ -1155,9 +1232,6 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
if (!WS.isDefined(/*SetUsed=*/false))
continue;
- if (WS.getOffset() != 0)
- report_fatal_error("data sections must contain one variable each: " +
- WS.getName());
if (!WS.getSize())
report_fatal_error("data symbols must have a size set with .size: " +
WS.getName());
@@ -1166,49 +1240,16 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
report_fatal_error(".size expression must be evaluatable");
- auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
-
- if (uint64_t(Size) != Layout.getSectionFileSize(&DataSection))
- report_fatal_error("data sections must contain at most one variable");
-
- DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
- DataAlignment = std::max(DataAlignment, DataSection.getAlignment());
-
- DataSection.setSectionOffset(DataBytes.size());
-
- for (const MCFragment &Frag : DataSection) {
- if (Frag.hasInstructions())
- report_fatal_error("only data supported in data sections");
-
- if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
- if (Align->getValueSize() != 1)
- report_fatal_error("only byte values supported for alignment");
- // If nops are requested, use zeros, as this is the data section.
- uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
- uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(),
- Align->getAlignment()),
- DataBytes.size() +
- Align->getMaxBytesToEmit());
- DataBytes.resize(Size, Value);
- } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
- DataBytes.insert(DataBytes.end(), Fill->getSize(), Fill->getValue());
- } else {
- const auto &DataFrag = cast<MCDataFragment>(Frag);
- const SmallVectorImpl<char> &Contents = DataFrag.getContents();
-
- DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
- }
- }
-
// For each global, prepare a corresponding wasm global holding its
// address. For externals these will also be named exports.
Index = NumGlobalImports + Globals.size();
+ auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
WasmGlobal Global;
Global.Type = PtrType;
Global.IsMutable = false;
Global.HasImport = false;
- Global.InitialValue = DataSection.getSectionOffset();
+ Global.InitialValue = DataSection.getMemoryOffset() + Layout.getSymbolOffset(WS);
Global.ImportIndex = 0;
SymbolIndices[&WS] = Index;
DEBUG(dbgs() << " -> global index: " << Index << "\n");
@@ -1216,7 +1257,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
}
// If the symbol is visible outside this translation unit, export it.
- if ((WS.isExternal() && WS.isDefined(/*SetUsed=*/false))) {
+ if (WS.isDefined(/*SetUsed=*/false)) {
WasmExport Export;
Export.FieldName = WS.getName();
Export.Index = Index;
@@ -1226,6 +1267,8 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
DEBUG(dbgs() << " -> export " << Exports.size() << "\n");
Exports.push_back(Export);
+ if (!WS.isExternal())
+ SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
}
}
@@ -1235,18 +1278,18 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
for (const MCSymbol &S : Asm.symbols()) {
if (!S.isVariable())
continue;
+
assert(S.isDefined(/*SetUsed=*/false));
- const auto &WS = static_cast<const MCSymbolWasm &>(S);
// Find the target symbol of this weak alias and export that index
- const MCExpr *Expr = WS.getVariableValue();
- auto *Inner = cast<MCSymbolRefExpr>(Expr);
- const auto *ResolvedSym = cast<MCSymbolWasm>(&Inner->getSymbol());
+ const auto &WS = static_cast<const MCSymbolWasm &>(S);
+ const MCSymbolWasm *ResolvedSym = ResolveSymbol(WS);
DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym << "'\n");
assert(SymbolIndices.count(ResolvedSym) > 0);
uint32_t Index = SymbolIndices.find(ResolvedSym)->second;
DEBUG(dbgs() << " -> index:" << Index << "\n");
+ SymbolIndices[&WS] = Index;
WasmExport Export;
Export.FieldName = WS.getName();
Export.Index = Index;
@@ -1256,6 +1299,9 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
DEBUG(dbgs() << " -> export " << Exports.size() << "\n");
Exports.push_back(Export);
+
+ if (!WS.isExternal())
+ SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
}
// Add types for indirect function calls.
@@ -1266,30 +1312,84 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
registerFunctionType(*Fixup.Symbol);
}
+ // Translate .init_array section contents into start functions.
+ for (const MCSection &S : Asm) {
+ const auto &WS = static_cast<const MCSectionWasm &>(S);
+ if (WS.getSectionName().startswith(".fini_array"))
+ report_fatal_error(".fini_array sections are unsupported");
+ if (!WS.getSectionName().startswith(".init_array"))
+ continue;
+ if (WS.getFragmentList().empty())
+ continue;
+ if (WS.getFragmentList().size() != 2)
+ report_fatal_error("only one .init_array section fragment supported");
+ const MCFragment &AlignFrag = *WS.begin();
+ if (AlignFrag.getKind() != MCFragment::FT_Align)
+ report_fatal_error(".init_array section should be aligned");
+ if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (is64Bit() ? 8 : 4))
+ report_fatal_error(".init_array section should be aligned for pointers");
+ const MCFragment &Frag = *std::next(WS.begin());
+ if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
+ report_fatal_error("only data supported in .init_array section");
+ uint16_t Priority = UINT16_MAX;
+ if (WS.getSectionName().size() != 11) {
+ if (WS.getSectionName()[11] != '.')
+ report_fatal_error(".init_array section priority should start with '.'");
+ if (WS.getSectionName().substr(12).getAsInteger(10, Priority))
+ report_fatal_error("invalid .init_array section priority");
+ }
+ const auto &DataFrag = cast<MCDataFragment>(Frag);
+ const SmallVectorImpl<char> &Contents = DataFrag.getContents();
+ for (const uint8_t *p = (const uint8_t *)Contents.data(),
+ *end = (const uint8_t *)Contents.data() + Contents.size();
+ p != end; ++p) {
+ if (*p != 0)
+ report_fatal_error("non-symbolic data in .init_array section");
+ }
+ for (const MCFixup &Fixup : DataFrag.getFixups()) {
+ assert(Fixup.getKind() == MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
+ const MCExpr *Expr = Fixup.getValue();
+ auto *Sym = dyn_cast<MCSymbolRefExpr>(Expr);
+ if (!Sym)
+ report_fatal_error("fixups in .init_array should be symbol references");
+ if (Sym->getKind() != MCSymbolRefExpr::VK_WebAssembly_FUNCTION)
+ report_fatal_error("symbols in .init_array should be for functions");
+ auto I = SymbolIndices.find(cast<MCSymbolWasm>(&Sym->getSymbol()));
+ if (I == SymbolIndices.end())
+ report_fatal_error("symbols in .init_array should be defined");
+ uint32_t Index = I->second;
+ InitFuncs.push_back(std::make_pair(Priority, Index));
+ }
+ }
+
// Write out the Wasm header.
writeHeader(Asm);
writeTypeSection(FunctionTypes);
- writeImportSection(Imports);
+ writeImportSection(Imports, DataSize, TableElems.size());
writeFunctionSection(Functions);
- writeTableSection(TableElems.size());
- writeMemorySection(DataBytes);
- writeGlobalSection(Globals);
+ // Skip the "table" section; we import the table instead.
+ // Skip the "memory" section; we import the memory instead.
+ writeGlobalSection();
writeExportSection(Exports);
- // TODO: Start Section
writeElemSection(TableElems);
writeCodeSection(Asm, Layout, Functions);
- uint64_t DataSectionHeaderSize = writeDataSection(DataBytes);
+ writeDataSection(DataSegments);
writeNameSection(Functions, Imports, NumFuncImports);
writeCodeRelocSection();
- writeDataRelocSection(DataSectionHeaderSize);
- writeLinkingMetaDataSection(DataBytes.size(), DataAlignment, WeakSymbols, HasStackPointer, StackPointerGlobal);
+ writeDataRelocSection();
+ writeLinkingMetaDataSection(DataSegments, DataSize, SymbolFlags,
+ InitFuncs);
// TODO: Translate the .comment section to the output.
// TODO: Translate debug sections to the output.
}
-MCObjectWriter *llvm::createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW,
- raw_pwrite_stream &OS) {
- return new WasmObjectWriter(MOTW, OS);
+std::unique_ptr<MCObjectWriter>
+llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS) {
+ // FIXME: Can't use make_unique<WasmObjectWriter>(...) as WasmObjectWriter's
+ // destructor is private. Is that necessary?
+ return std::unique_ptr<MCObjectWriter>(
+ new WasmObjectWriter(std::move(MOTW), OS));
}
diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp
index 956ae70b38d1..9f1db46939c7 100644
--- a/lib/MC/WinCOFFObjectWriter.cpp
+++ b/lib/MC/WinCOFFObjectWriter.cpp
@@ -145,7 +145,8 @@ public:
bool UseBigObj;
- WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_pwrite_stream &OS);
+ WinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS);
void reset() override {
memset(&Header, 0, sizeof(Header));
@@ -222,9 +223,9 @@ void COFFSymbol::set_name_offset(uint32_t Offset) {
//------------------------------------------------------------------------------
// WinCOFFObjectWriter class implementation
-WinCOFFObjectWriter::WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW,
- raw_pwrite_stream &OS)
- : MCObjectWriter(OS, true), TargetObjectWriter(MOTW) {
+WinCOFFObjectWriter::WinCOFFObjectWriter(
+ std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
+ : MCObjectWriter(OS, true), TargetObjectWriter(std::move(MOTW)) {
Header.Machine = TargetObjectWriter->getMachine();
}
@@ -1084,8 +1085,7 @@ void MCWinCOFFObjectTargetWriter::anchor() {}
//------------------------------------------------------------------------------
// WinCOFFObjectWriter factory function
-MCObjectWriter *
-llvm::createWinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW,
- raw_pwrite_stream &OS) {
- return new WinCOFFObjectWriter(MOTW, OS);
+std::unique_ptr<MCObjectWriter> llvm::createWinCOFFObjectWriter(
+ std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) {
+ return llvm::make_unique<WinCOFFObjectWriter>(std::move(MOTW), OS);
}