summaryrefslogtreecommitdiff
path: root/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/ConstantPools.cpp6
-rw-r--r--lib/MC/ELFObjectWriter.cpp19
-rw-r--r--lib/MC/MCAsmInfoCOFF.cpp2
-rw-r--r--lib/MC/MCAsmInfoWasm.cpp2
-rw-r--r--lib/MC/MCAsmStreamer.cpp86
-rw-r--r--lib/MC/MCAssembler.cpp1
-rw-r--r--lib/MC/MCCodeView.cpp71
-rw-r--r--lib/MC/MCContext.cpp7
-rw-r--r--lib/MC/MCDwarf.cpp43
-rw-r--r--lib/MC/MCELFObjectTargetWriter.cpp3
-rw-r--r--lib/MC/MCExpr.cpp25
-rw-r--r--lib/MC/MCFragment.cpp4
-rw-r--r--lib/MC/MCInst.cpp12
-rw-r--r--lib/MC/MCInstrAnalysis.cpp5
-rw-r--r--lib/MC/MCInstrDesc.cpp14
-rw-r--r--lib/MC/MCMachOStreamer.cpp20
-rw-r--r--lib/MC/MCNullStreamer.cpp4
-rw-r--r--lib/MC/MCObjectFileInfo.cpp226
-rw-r--r--lib/MC/MCObjectStreamer.cpp98
-rw-r--r--lib/MC/MCParser/AsmLexer.cpp43
-rw-r--r--lib/MC/MCParser/AsmParser.cpp204
-rw-r--r--lib/MC/MCParser/CMakeLists.txt1
-rw-r--r--lib/MC/MCParser/DarwinAsmParser.cpp112
-rw-r--r--lib/MC/MCParser/ELFAsmParser.cpp55
-rw-r--r--lib/MC/MCParser/MCAsmLexer.cpp3
-rw-r--r--lib/MC/MCParser/MCAsmParser.cpp2
-rw-r--r--lib/MC/MCParser/WasmAsmParser.cpp145
-rw-r--r--lib/MC/MCRegisterInfo.cpp5
-rw-r--r--lib/MC/MCSection.cpp3
-rw-r--r--lib/MC/MCSectionELF.cpp3
-rw-r--r--lib/MC/MCStreamer.cpp92
-rw-r--r--lib/MC/MCWasmStreamer.cpp3
-rw-r--r--lib/MC/MCWin64EH.cpp352
-rw-r--r--lib/MC/MachObjectWriter.cpp27
-rw-r--r--lib/MC/WasmObjectWriter.cpp292
-rw-r--r--lib/MC/WinCOFFObjectWriter.cpp101
36 files changed, 1417 insertions, 674 deletions
diff --git a/lib/MC/ConstantPools.cpp b/lib/MC/ConstantPools.cpp
index ca5440237e49..18277a225640 100644
--- a/lib/MC/ConstantPools.cpp
+++ b/lib/MC/ConstantPools.cpp
@@ -97,16 +97,14 @@ void AssemblerConstantPools::emitAll(MCStreamer &Streamer) {
void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) {
MCSection *Section = Streamer.getCurrentSectionOnly();
- if (ConstantPool *CP = getConstantPool(Section)) {
+ if (ConstantPool *CP = getConstantPool(Section))
emitConstantPool(Streamer, Section, *CP);
- }
}
void AssemblerConstantPools::clearCacheForCurrentSection(MCStreamer &Streamer) {
MCSection *Section = Streamer.getCurrentSectionOnly();
- if (ConstantPool *CP = getConstantPool(Section)) {
+ if (ConstantPool *CP = getConstantPool(Section))
CP->clearCache();
- }
}
const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer,
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index db531f75c87c..89f3b30cddd6 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -29,6 +29,7 @@
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCFragment.h"
+#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionELF.h"
@@ -668,6 +669,20 @@ void ELFWriter::computeSymbolTable(
} else {
const MCSectionELF &Section =
static_cast<const MCSectionELF &>(Symbol.getSection());
+
+ // We may end up with a situation when section symbol is technically
+ // defined, but should not be. That happens because we explicitly
+ // pre-create few .debug_* sections to have accessors.
+ // And if these sections were not really defined in the code, but were
+ // referenced, we simply error out.
+ if (!Section.isRegistered()) {
+ assert(static_cast<const MCSymbolELF &>(Symbol).getType() ==
+ ELF::STT_SECTION);
+ Ctx.reportError(SMLoc(),
+ "Undefined section reference: " + Symbol.getName());
+ continue;
+ }
+
if (Mode == NonDwoOnly && isDwoSection(Section))
continue;
MSD.SectionIndex = SectionIndexMap.lookup(&Section);
@@ -1107,6 +1122,8 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
SectionIndexMap[RelSection] = addToSectionTable(RelSection);
Relocations.push_back(RelSection);
}
+
+ OWriter.TargetObjectWriter->addTargetSectionFlags(Ctx, Section);
}
MCSectionELF *CGProfileSection = nullptr;
@@ -1273,6 +1290,8 @@ void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
for (const MCSymbol *&Sym : AddrsigSyms) {
if (const MCSymbol *R = Renames.lookup(cast<MCSymbolELF>(Sym)))
Sym = R;
+ if (Sym->isInSection() && Sym->getName().startswith(".L"))
+ Sym = Sym->getSection().getBeginSymbol();
Sym->setUsedInReloc();
}
}
diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp
index d8fb875b67c6..15886eb619b9 100644
--- a/lib/MC/MCAsmInfoCOFF.cpp
+++ b/lib/MC/MCAsmInfoCOFF.cpp
@@ -25,7 +25,7 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() {
COMMDirectiveAlignmentIsInBytes = false;
LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment;
HasDotTypeDotSizeDirective = false;
- HasSingleParameterDotFile = false;
+ HasSingleParameterDotFile = true;
WeakRefDirective = "\t.weak\t";
HasLinkOnceDirective = true;
diff --git a/lib/MC/MCAsmInfoWasm.cpp b/lib/MC/MCAsmInfoWasm.cpp
index fc55059ff75d..d448664baa14 100644
--- a/lib/MC/MCAsmInfoWasm.cpp
+++ b/lib/MC/MCAsmInfoWasm.cpp
@@ -15,7 +15,7 @@
#include "llvm/MC/MCAsmInfoWasm.h"
using namespace llvm;
-void MCAsmInfoWasm::anchor() { }
+void MCAsmInfoWasm::anchor() {}
MCAsmInfoWasm::MCAsmInfoWasm() {
HasIdentDirective = true;
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index ae02f50bf8bd..e017103070bf 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -147,9 +147,9 @@ public:
void EmitLinkerOptions(ArrayRef<std::string> Options) override;
void EmitDataRegion(MCDataRegionType Kind) override;
void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
- unsigned Update) override;
+ unsigned Update, VersionTuple SDKVersion) override;
void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
- unsigned Update) override;
+ unsigned Update, VersionTuple SDKVersion) override;
void EmitThumbFunc(MCSymbol *Func) override;
void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
@@ -266,6 +266,7 @@ public:
void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
void EmitIdent(StringRef IdentString) override;
+ void EmitCFIBKeyFrame() override;
void EmitCFISections(bool EH, bool Debug) override;
void EmitCFIDefCfa(int64_t Register, int64_t Offset) override;
void EmitCFIDefCfaOffset(int64_t Offset) override;
@@ -285,10 +286,12 @@ public:
void EmitCFIUndefined(int64_t Register) override;
void EmitCFIRegister(int64_t Register1, int64_t Register2) override;
void EmitCFIWindowSave() override;
+ void EmitCFINegateRAState() override;
void EmitCFIReturnColumn(int64_t Register) override;
void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
void EmitWinCFIEndProc(SMLoc Loc) override;
+ void EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) override;
void EmitWinCFIStartChained(SMLoc Loc) override;
void EmitWinCFIEndChained(SMLoc Loc) override;
void EmitWinCFIPushReg(unsigned Register, SMLoc Loc) override;
@@ -513,31 +516,51 @@ static const char *getVersionMinDirective(MCVersionMinType Type) {
llvm_unreachable("Invalid MC version min type");
}
+static void EmitSDKVersionSuffix(raw_ostream &OS,
+ const VersionTuple &SDKVersion) {
+ if (SDKVersion.empty())
+ return;
+ OS << '\t' << "sdk_version " << SDKVersion.getMajor();
+ if (auto Minor = SDKVersion.getMinor()) {
+ OS << ", " << *Minor;
+ if (auto Subminor = SDKVersion.getSubminor()) {
+ OS << ", " << *Subminor;
+ }
+ }
+}
+
void MCAsmStreamer::EmitVersionMin(MCVersionMinType Type, unsigned Major,
- unsigned Minor, unsigned Update) {
+ unsigned Minor, unsigned Update,
+ VersionTuple SDKVersion) {
OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
if (Update)
OS << ", " << Update;
+ EmitSDKVersionSuffix(OS, SDKVersion);
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";
+ 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";
+ case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator";
+ case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator";
+ case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator";
}
llvm_unreachable("Invalid Mach-O platform type");
}
void MCAsmStreamer::EmitBuildVersion(unsigned Platform, unsigned Major,
- unsigned Minor, unsigned Update) {
+ unsigned Minor, unsigned Update,
+ VersionTuple SDKVersion) {
const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;
if (Update)
OS << ", " << Update;
+ EmitSDKVersionSuffix(OS, SDKVersion);
EmitEOL();
}
@@ -858,10 +881,14 @@ void MCAsmStreamer::EmitBytes(StringRef Data) {
// supported, emit as vector of 8bits data.
if (Data.size() == 1 ||
!(MAI->getAscizDirective() || MAI->getAsciiDirective())) {
- const char *Directive = MAI->getData8bitsDirective();
- for (const unsigned char C : Data.bytes()) {
- OS << Directive << (unsigned)C;
- EmitEOL();
+ if (MCTargetStreamer *TS = getTargetStreamer()) {
+ TS->emitRawBytes(Data);
+ } else {
+ const char *Directive = MAI->getData8bitsDirective();
+ for (const unsigned char C : Data.bytes()) {
+ OS << Directive << (unsigned)C;
+ EmitEOL();
+ }
}
return;
}
@@ -1298,20 +1325,17 @@ void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
unsigned Line, unsigned Column,
bool PrologueEnd, bool IsStmt,
StringRef FileName, SMLoc Loc) {
+ // Validate the directive.
+ if (!checkCVLocSection(FunctionId, FileNo, Loc))
+ return;
+
OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
<< Column;
if (PrologueEnd)
OS << " prologue_end";
- unsigned OldIsStmt = getContext().getCVContext().getCurrentCVLoc().isStmt();
- if (IsStmt != OldIsStmt) {
- OS << " is_stmt ";
-
- if (IsStmt)
- OS << "1";
- else
- OS << "0";
- }
+ if (IsStmt)
+ OS << " is_stmt 1";
if (IsVerboseAsm) {
OS.PadToColumn(MAI->getCommentColumn());
@@ -1319,8 +1343,6 @@ void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
<< Column;
}
EmitEOL();
- this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
- PrologueEnd, IsStmt, FileName, Loc);
}
void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
@@ -1569,12 +1591,24 @@ void MCAsmStreamer::EmitCFIWindowSave() {
EmitEOL();
}
+void MCAsmStreamer::EmitCFINegateRAState() {
+ MCStreamer::EmitCFINegateRAState();
+ OS << "\t.cfi_negate_ra_state";
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) {
MCStreamer::EmitCFIReturnColumn(Register);
OS << "\t.cfi_return_column " << Register;
EmitEOL();
}
+void MCAsmStreamer::EmitCFIBKeyFrame() {
+ MCStreamer::EmitCFIBKeyFrame();
+ OS << "\t.cfi_b_key_frame";
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
MCStreamer::EmitWinCFIStartProc(Symbol, Loc);
@@ -1590,6 +1624,10 @@ void MCAsmStreamer::EmitWinCFIEndProc(SMLoc Loc) {
EmitEOL();
}
+// TODO: Implement
+void MCAsmStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
+}
+
void MCAsmStreamer::EmitWinCFIStartChained(SMLoc Loc) {
MCStreamer::EmitWinCFIStartChained(Loc);
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 1e23b6d816e8..cde6a93a1647 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -111,6 +111,7 @@ void MCAssembler::reset() {
ELFHeaderEFlags = 0;
LOHContainer.reset();
VersionInfo.Major = 0;
+ VersionInfo.SDKVersion = VersionTuple();
// reset objects owned by us
if (getBackendPtr())
diff --git a/lib/MC/MCCodeView.cpp b/lib/MC/MCCodeView.cpp
index 155fd7eeb576..978ac789c31e 100644
--- a/lib/MC/MCCodeView.cpp
+++ b/lib/MC/MCCodeView.cpp
@@ -128,6 +128,14 @@ bool CodeViewContext::recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
return true;
}
+void CodeViewContext::recordCVLoc(MCContext &Ctx, const MCSymbol *Label,
+ unsigned FunctionId, unsigned FileNo,
+ unsigned Line, unsigned Column,
+ bool PrologueEnd, bool IsStmt) {
+ addLineEntry(MCCVLoc{
+ Label, FunctionId, FileNo, Line, Column, PrologueEnd, IsStmt});
+}
+
MCDataFragment *CodeViewContext::getStringTableFragment() {
if (!StrTabFragment) {
StrTabFragment = new MCDataFragment();
@@ -255,7 +263,7 @@ void CodeViewContext::emitFileChecksumOffset(MCObjectStreamer &OS,
OS.EmitValueImpl(SRE, 4);
}
-void CodeViewContext::addLineEntry(const MCCVLineEntry &LineEntry) {
+void CodeViewContext::addLineEntry(const MCCVLoc &LineEntry) {
size_t Offset = MCCVLines.size();
auto I = MCCVLineStartStop.insert(
{LineEntry.getFunctionId(), {Offset, Offset + 1}});
@@ -264,9 +272,9 @@ void CodeViewContext::addLineEntry(const MCCVLineEntry &LineEntry) {
MCCVLines.push_back(LineEntry);
}
-std::vector<MCCVLineEntry>
+std::vector<MCCVLoc>
CodeViewContext::getFunctionLineEntries(unsigned FuncId) {
- std::vector<MCCVLineEntry> FilteredLines;
+ std::vector<MCCVLoc> FilteredLines;
auto I = MCCVLineStartStop.find(FuncId);
if (I != MCCVLineStartStop.end()) {
MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(FuncId);
@@ -289,9 +297,9 @@ CodeViewContext::getFunctionLineEntries(unsigned FuncId) {
FilteredLines.back().getFileNum() != IA.File ||
FilteredLines.back().getLine() != IA.Line ||
FilteredLines.back().getColumn() != IA.Col) {
- FilteredLines.push_back(MCCVLineEntry(
+ FilteredLines.push_back(MCCVLoc(
MCCVLines[Idx].getLabel(),
- MCCVLoc(FuncId, IA.File, IA.Line, IA.Col, false, false)));
+ FuncId, IA.File, IA.Line, IA.Col, false, false));
}
}
}
@@ -308,7 +316,7 @@ std::pair<size_t, size_t> CodeViewContext::getLineExtent(unsigned FuncId) {
return I->second;
}
-ArrayRef<MCCVLineEntry> CodeViewContext::getLinesForExtent(size_t L, size_t R) {
+ArrayRef<MCCVLoc> CodeViewContext::getLinesForExtent(size_t L, size_t R) {
if (R <= L)
return None;
if (L >= MCCVLines.size())
@@ -331,8 +339,8 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
OS.EmitCOFFSectionIndex(FuncBegin);
// Actual line info.
- std::vector<MCCVLineEntry> Locs = getFunctionLineEntries(FuncId);
- bool HaveColumns = any_of(Locs, [](const MCCVLineEntry &LineEntry) {
+ std::vector<MCCVLoc> Locs = getFunctionLineEntries(FuncId);
+ bool HaveColumns = any_of(Locs, [](const MCCVLoc &LineEntry) {
return LineEntry.getColumn() != 0;
});
OS.EmitIntValue(HaveColumns ? int(LF_HaveColumns) : 0, 2);
@@ -342,7 +350,7 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
// Emit a file segment for the run of locations that share a file id.
unsigned CurFileNum = I->getFileNum();
auto FileSegEnd =
- std::find_if(I, E, [CurFileNum](const MCCVLineEntry &Loc) {
+ std::find_if(I, E, [CurFileNum](const MCCVLoc &Loc) {
return Loc.getFileNum() != CurFileNum;
});
unsigned EntryCount = FileSegEnd - I;
@@ -424,13 +432,13 @@ void CodeViewContext::emitInlineLineTableForFunction(MCObjectStreamer &OS,
OS.getCurrentSectionOnly());
}
-void CodeViewContext::emitDefRange(
+MCFragment *CodeViewContext::emitDefRange(
MCObjectStreamer &OS,
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
StringRef FixedSizePortion) {
// Create and insert a fragment into the current section that will be encoded
// later.
- new MCCVDefRangeFragment(Ranges, FixedSizePortion,
+ return new MCCVDefRangeFragment(Ranges, FixedSizePortion,
OS.getCurrentSectionOnly());
}
@@ -468,14 +476,14 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
if (LocBegin >= LocEnd)
return;
- ArrayRef<MCCVLineEntry> Locs = getLinesForExtent(LocBegin, LocEnd);
+ ArrayRef<MCCVLoc> Locs = getLinesForExtent(LocBegin, LocEnd);
if (Locs.empty())
return;
// Check that the locations are all in the same section.
#ifndef NDEBUG
const MCSection *FirstSec = &Locs.front().getLabel()->getSection();
- for (const MCCVLineEntry &Loc : Locs) {
+ for (const MCCVLoc &Loc : Locs) {
if (&Loc.getLabel()->getSection() != FirstSec) {
errs() << ".cv_loc " << Loc.getFunctionId() << ' ' << Loc.getFileNum()
<< ' ' << Loc.getLine() << ' ' << Loc.getColumn()
@@ -488,7 +496,8 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
// Make an artificial start location using the function start and the inlinee
// lines start location information. All deltas start relative to this
// location.
- MCCVLineEntry StartLoc(Frag.getFnStartSym(), MCCVLoc(Locs.front()));
+ MCCVLoc StartLoc = Locs.front();
+ StartLoc.setLabel(Frag.getFnStartSym());
StartLoc.setFileNum(Frag.StartFileId);
StartLoc.setLine(Frag.StartLineNum);
bool HaveOpenRange = false;
@@ -500,7 +509,7 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
SmallVectorImpl<char> &Buffer = Frag.getContents();
Buffer.clear(); // Clear old contents if we went through relaxation.
- for (const MCCVLineEntry &Loc : Locs) {
+ for (const MCCVLoc &Loc : Locs) {
// Exit early if our line table would produce an oversized InlineSiteSym
// record. Account for the ChangeCodeLength annotation emitted after the
// loop ends.
@@ -585,10 +594,10 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
unsigned EndSymLength =
computeLabelDiff(Layout, LastLabel, Frag.getFnEndSym());
unsigned LocAfterLength = ~0U;
- ArrayRef<MCCVLineEntry> LocAfter = getLinesForExtent(LocEnd, LocEnd + 1);
+ ArrayRef<MCCVLoc> LocAfter = getLinesForExtent(LocEnd, LocEnd + 1);
if (!LocAfter.empty()) {
// Only try to compute this difference if we're in the same section.
- const MCCVLineEntry &Loc = LocAfter[0];
+ const MCCVLoc &Loc = LocAfter[0];
if (&Loc.getLabel()->getSection() == &LastLabel->getSection())
LocAfterLength = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
}
@@ -686,31 +695,3 @@ void CodeViewContext::encodeDefRange(MCAsmLayout &Layout,
}
}
}
-
-//
-// This is called when an instruction is assembled into the specified section
-// and if there is information from the last .cv_loc directive that has yet to have
-// a line entry made for it is made.
-//
-void MCCVLineEntry::Make(MCObjectStreamer *MCOS) {
- CodeViewContext &CVC = MCOS->getContext().getCVContext();
- if (!CVC.getCVLocSeen())
- return;
-
- // Create a symbol at in the current section for use in the line entry.
- MCSymbol *LineSym = MCOS->getContext().createTempSymbol();
- // Set the value of the symbol to use for the MCCVLineEntry.
- MCOS->EmitLabel(LineSym);
-
- // Get the current .loc info saved in the context.
- const MCCVLoc &CVLoc = CVC.getCurrentCVLoc();
-
- // Create a (local) line entry with the symbol and the current .loc info.
- MCCVLineEntry LineEntry(LineSym, CVLoc);
-
- // clear CVLocSeen saying the current .loc info is now used.
- CVC.clearCVLocSeen();
-
- // Add the line entry to this section's entries.
- CVC.addLineEntry(LineEntry);
-}
diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp
index 606da2526890..fab517075c5a 100644
--- a/lib/MC/MCContext.cpp
+++ b/lib/MC/MCContext.cpp
@@ -592,7 +592,7 @@ bool MCContext::isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID) {
return !LineTable.getMCDwarfFiles()[FileNumber].Name.empty();
}
-/// Remove empty sections from SectionStartEndSyms, to avoid generating
+/// Remove empty sections from SectionsForRanges, to avoid generating
/// useless debug info for them.
void MCContext::finalizeDwarfSections(MCStreamer &MCOS) {
SectionsForRanges.remove_if(
@@ -605,11 +605,6 @@ CodeViewContext &MCContext::getCVContext() {
return *CVContext.get();
}
-void MCContext::clearCVLocSeen() {
- if (CVContext)
- CVContext->clearCVLocSeen();
-}
-
//===----------------------------------------------------------------------===//
// Error Reporting
//===----------------------------------------------------------------------===//
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index 0461c2564ccf..38b02694d81d 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -463,10 +463,7 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym, 4), 4);
// 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
@@ -1335,6 +1332,10 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
Streamer.EmitIntValue(dwarf::DW_CFA_GNU_window_save, 1);
return;
+ case MCCFIInstruction::OpNegateRAState:
+ Streamer.EmitIntValue(dwarf::DW_CFA_AARCH64_negate_ra_state, 1);
+ return;
+
case MCCFIInstruction::OpUndefined: {
unsigned Reg = Instr.getRegister();
Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1);
@@ -1421,7 +1422,12 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
unsigned Reg = Instr.getRegister();
if (!IsEH)
Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
- Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
+ if (Reg < 64) {
+ Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
+ } else {
+ Streamer.EmitIntValue(dwarf::DW_CFA_restore_extended, 1);
+ Streamer.EmitULEB128IntValue(Reg);
+ }
return;
}
case MCCFIInstruction::OpGnuArgsSize:
@@ -1559,9 +1565,8 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
uint8_t CIEVersion = getCIEVersion(IsEH, context.getDwarfVersion());
Streamer.EmitIntValue(CIEVersion, 1);
- // Augmentation String
- SmallString<8> Augmentation;
if (IsEH) {
+ SmallString<8> Augmentation;
Augmentation += "z";
if (Frame.Personality)
Augmentation += "P";
@@ -1570,6 +1575,8 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
Augmentation += "R";
if (Frame.IsSignalFrame)
Augmentation += "S";
+ if (Frame.IsBKeyFrame)
+ Augmentation += "B";
Streamer.EmitBytes(Augmentation);
}
Streamer.EmitIntValue(0, 1);
@@ -1724,25 +1731,28 @@ namespace {
struct CIEKey {
static const CIEKey getEmptyKey() {
- return CIEKey(nullptr, 0, -1, false, false, static_cast<unsigned>(INT_MAX));
+ return CIEKey(nullptr, 0, -1, false, false, static_cast<unsigned>(INT_MAX),
+ false);
}
static const CIEKey getTombstoneKey() {
- return CIEKey(nullptr, -1, 0, false, false, static_cast<unsigned>(INT_MAX));
+ return CIEKey(nullptr, -1, 0, false, false, static_cast<unsigned>(INT_MAX),
+ false);
}
CIEKey(const MCSymbol *Personality, unsigned PersonalityEncoding,
unsigned LSDAEncoding, bool IsSignalFrame, bool IsSimple,
- unsigned RAReg)
+ unsigned RAReg, bool IsBKeyFrame)
: Personality(Personality), PersonalityEncoding(PersonalityEncoding),
LsdaEncoding(LSDAEncoding), IsSignalFrame(IsSignalFrame),
- IsSimple(IsSimple), RAReg(RAReg) {}
+ IsSimple(IsSimple), RAReg(RAReg), IsBKeyFrame(IsBKeyFrame) {}
explicit CIEKey(const MCDwarfFrameInfo &Frame)
: Personality(Frame.Personality),
PersonalityEncoding(Frame.PersonalityEncoding),
LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame),
- IsSimple(Frame.IsSimple), RAReg(Frame.RAReg) {}
+ IsSimple(Frame.IsSimple), RAReg(Frame.RAReg),
+ IsBKeyFrame(Frame.IsBKeyFrame) {}
const MCSymbol *Personality;
unsigned PersonalityEncoding;
@@ -1750,6 +1760,7 @@ struct CIEKey {
bool IsSignalFrame;
bool IsSimple;
unsigned RAReg;
+ bool IsBKeyFrame;
};
} // end anonymous namespace
@@ -1761,9 +1772,9 @@ template <> struct DenseMapInfo<CIEKey> {
static CIEKey getTombstoneKey() { return CIEKey::getTombstoneKey(); }
static unsigned getHashValue(const CIEKey &Key) {
- return static_cast<unsigned>(
- hash_combine(Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding,
- Key.IsSignalFrame, Key.IsSimple, Key.RAReg));
+ return static_cast<unsigned>(hash_combine(
+ Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding,
+ Key.IsSignalFrame, Key.IsSimple, Key.RAReg, Key.IsBKeyFrame));
}
static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) {
@@ -1771,8 +1782,8 @@ template <> struct DenseMapInfo<CIEKey> {
LHS.PersonalityEncoding == RHS.PersonalityEncoding &&
LHS.LsdaEncoding == RHS.LsdaEncoding &&
LHS.IsSignalFrame == RHS.IsSignalFrame &&
- LHS.IsSimple == RHS.IsSimple &&
- LHS.RAReg == RHS.RAReg;
+ LHS.IsSimple == RHS.IsSimple && LHS.RAReg == RHS.RAReg &&
+ LHS.IsBKeyFrame == RHS.IsBKeyFrame;
}
};
diff --git a/lib/MC/MCELFObjectTargetWriter.cpp b/lib/MC/MCELFObjectTargetWriter.cpp
index 483ee94c0db1..ff53dd7299c1 100644
--- a/lib/MC/MCELFObjectTargetWriter.cpp
+++ b/lib/MC/MCELFObjectTargetWriter.cpp
@@ -26,3 +26,6 @@ void
MCELFObjectTargetWriter::sortRelocs(const MCAssembler &Asm,
std::vector<ELFRelocationEntry> &Relocs) {
}
+
+void MCELFObjectTargetWriter::addTargetSectionFlags(MCContext &Ctx,
+ MCSectionELF &Sec) {}
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp
index 0694a8fa620e..3c022199145f 100644
--- a/lib/MC/MCExpr.cpp
+++ b/lib/MC/MCExpr.cpp
@@ -304,7 +304,9 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_Hexagon_IE: return "IE";
case VK_Hexagon_IE_GOT: return "IEGOT";
case VK_WebAssembly_FUNCTION: return "FUNCTION";
+ case VK_WebAssembly_GLOBAL: return "GLOBAL";
case VK_WebAssembly_TYPEINDEX: return "TYPEINDEX";
+ case VK_WebAssembly_EVENT: return "EVENT";
case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo";
case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi";
case VK_AMDGPU_REL32_LO: return "rel32@lo";
@@ -418,7 +420,9 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("hi8", VK_AVR_HI8)
.Case("hlo8", VK_AVR_HLO8)
.Case("function", VK_WebAssembly_FUNCTION)
+ .Case("global", VK_WebAssembly_GLOBAL)
.Case("typeindex", VK_WebAssembly_TYPEINDEX)
+ .Case("event", VK_WebAssembly_EVENT)
.Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)
.Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI)
.Case("rel32@lo", VK_AMDGPU_REL32_LO)
@@ -524,6 +528,11 @@ static void AttemptToFoldSymbolOffsetDifference(
if (Asm->isThumbFunc(&SA))
Addend |= 1;
+ // If symbol is labeled as micromips, we set low-bit to ensure
+ // correct offset in .gcc_except_table
+ if (Asm->getBackend().isMicroMips(&SA))
+ Addend |= 1;
+
// Clear the symbol expr pointers to indicate we have folded these
// operands.
A = B = nullptr;
@@ -750,8 +759,22 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
if (!ABE->getLHS()->evaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup,
Addrs, InSet) ||
!ABE->getRHS()->evaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup,
- Addrs, InSet))
+ Addrs, InSet)) {
+ // Check if both are Target Expressions, see if we can compare them.
+ if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(ABE->getLHS()))
+ if (const MCTargetExpr *R = cast<MCTargetExpr>(ABE->getRHS())) {
+ switch (ABE->getOpcode()) {
+ case MCBinaryExpr::EQ:
+ Res = MCValue::get((L->isEqualTo(R)) ? -1 : 0);
+ return true;
+ case MCBinaryExpr::NE:
+ Res = MCValue::get((R->isEqualTo(R)) ? 0 : -1);
+ return true;
+ default: break;
+ }
+ }
return false;
+ }
// We only support a few operations on non-constant expressions, handle
// those first.
diff --git a/lib/MC/MCFragment.cpp b/lib/MC/MCFragment.cpp
index 0ebcf21a422e..d22b117972bf 100644
--- a/lib/MC/MCFragment.cpp
+++ b/lib/MC/MCFragment.cpp
@@ -237,8 +237,8 @@ MCFragment::~MCFragment() = default;
MCFragment::MCFragment(FragmentType Kind, bool HasInstructions,
MCSection *Parent)
- : Kind(Kind), HasInstructions(HasInstructions), Parent(Parent),
- Atom(nullptr), Offset(~UINT64_C(0)) {
+ : Kind(Kind), HasInstructions(HasInstructions), LayoutOrder(0),
+ Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)) {
if (Parent && !isDummy())
Parent->getFragmentList().push_back(this);
}
diff --git a/lib/MC/MCInst.cpp b/lib/MC/MCInst.cpp
index f9b71caaf91c..64f111fc7114 100644
--- a/lib/MC/MCInst.cpp
+++ b/lib/MC/MCInst.cpp
@@ -72,11 +72,17 @@ void MCInst::print(raw_ostream &OS) const {
void MCInst::dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer,
StringRef Separator) const {
+ StringRef InstName = Printer ? Printer->getOpcodeName(getOpcode()) : "";
+ dump_pretty(OS, InstName, Separator);
+}
+
+void MCInst::dump_pretty(raw_ostream &OS, StringRef Name,
+ StringRef Separator) const {
OS << "<MCInst #" << getOpcode();
- // Show the instruction opcode name if we have access to a printer.
- if (Printer)
- OS << ' ' << Printer->getOpcodeName(getOpcode());
+ // Show the instruction opcode name if we have it.
+ if (!Name.empty())
+ OS << ' ' << Name;
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
OS << Separator;
diff --git a/lib/MC/MCInstrAnalysis.cpp b/lib/MC/MCInstrAnalysis.cpp
index 4d7c89116893..8223f3a5c66f 100644
--- a/lib/MC/MCInstrAnalysis.cpp
+++ b/lib/MC/MCInstrAnalysis.cpp
@@ -24,11 +24,6 @@ bool MCInstrAnalysis::clearsSuperRegisters(const MCRegisterInfo &MRI,
return false;
}
-bool MCInstrAnalysis::isDependencyBreaking(const MCSubtargetInfo &STI,
- const MCInst &Inst) const {
- return false;
-}
-
bool MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr,
uint64_t Size, uint64_t &Target) const {
if (Inst.getNumOperands() == 0 ||
diff --git a/lib/MC/MCInstrDesc.cpp b/lib/MC/MCInstrDesc.cpp
index ee55f3eff3ac..53cba864a85d 100644
--- a/lib/MC/MCInstrDesc.cpp
+++ b/lib/MC/MCInstrDesc.cpp
@@ -39,15 +39,6 @@ bool MCInstrDesc::mayAffectControlFlow(const MCInst &MI,
return false;
if (hasDefOfPhysReg(MI, PC, RI))
return true;
- // A variadic instruction may define PC in the variable operand list.
- // There's currently no indication of which entries in a variable
- // list are defs and which are uses. While that's the case, this function
- // needs to assume they're defs in order to be conservatively correct.
- for (int i = NumOperands, e = MI.getNumOperands(); i != e; ++i) {
- if (MI.getOperand(i).isReg() &&
- RI.isSubRegisterEq(PC, MI.getOperand(i).getReg()))
- return true;
- }
return false;
}
@@ -66,5 +57,10 @@ bool MCInstrDesc::hasDefOfPhysReg(const MCInst &MI, unsigned Reg,
if (MI.getOperand(i).isReg() &&
RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg()))
return true;
+ if (variadicOpsAreDefs())
+ for (int i = NumOperands - 1, e = MI.getNumOperands(); i != e; ++i)
+ if (MI.getOperand(i).isReg() &&
+ RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg()))
+ return true;
return hasImplicitDefOfPhysReg(Reg, &RI);
}
diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp
index 43e69605787c..b30317e74672 100644
--- a/lib/MC/MCMachOStreamer.cpp
+++ b/lib/MC/MCMachOStreamer.cpp
@@ -89,10 +89,10 @@ public:
void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
void EmitLinkerOptions(ArrayRef<std::string> Options) override;
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 EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
+ unsigned Update, VersionTuple SDKVersion) override;
+ void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
+ unsigned Update, VersionTuple SDKVersion) override;
void EmitThumbFunc(MCSymbol *Func) override;
bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
@@ -270,14 +270,16 @@ void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) {
}
void MCMachOStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major,
- unsigned Minor, unsigned Update) {
- getAssembler().setVersionMin(Kind, Major, Minor, Update);
+ unsigned Minor, unsigned Update,
+ VersionTuple SDKVersion) {
+ getAssembler().setVersionMin(Kind, Major, Minor, Update, SDKVersion);
}
void MCMachOStreamer::EmitBuildVersion(unsigned Platform, unsigned Major,
- unsigned Minor, unsigned Update) {
+ unsigned Minor, unsigned Update,
+ VersionTuple SDKVersion) {
getAssembler().setBuildVersion((MachO::PlatformType)Platform, Major, Minor,
- Update);
+ Update, SDKVersion);
}
void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) {
@@ -507,7 +509,7 @@ MCStreamer *llvm::createMachOStreamer(MCContext &Context,
new MCMachOStreamer(Context, std::move(MAB), std::move(OW), std::move(CE),
DWARFMustBeAtTheEnd, LabelSections);
const Triple &Target = Context.getObjectFileInfo()->getTargetTriple();
- S->EmitVersionForTarget(Target);
+ S->EmitVersionForTarget(Target, Context.getObjectFileInfo()->getSDKVersion());
if (RelaxAll)
S->getAssembler().setRelaxAll(true);
return S;
diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp
index a96dec184441..4e97e7550bcb 100644
--- a/lib/MC/MCNullStreamer.cpp
+++ b/lib/MC/MCNullStreamer.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
@@ -22,6 +23,9 @@ namespace {
/// @name MCStreamer Interface
/// @{
+ bool hasRawTextSupport() const override { return true; }
+ void EmitRawTextImpl(StringRef String) override {}
+
bool EmitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) override {
return true;
diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp
index b88d2d801822..9e35355d06e0 100644
--- a/lib/MC/MCObjectFileInfo.cpp
+++ b/lib/MC/MCObjectFileInfo.cpp
@@ -63,11 +63,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
if (T.isWatchABI())
OmitDwarfIfHaveCompactUnwind = true;
- PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel
- | dwarf::DW_EH_PE_sdata4;
- LSDAEncoding = FDECFIEncoding = dwarf::DW_EH_PE_pcrel;
- TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_sdata4;
+ FDECFIEncoding = dwarf::DW_EH_PE_pcrel;
// .comm doesn't support alignment before Leopard.
if (T.isMacOSX() && T.isMacOSXVersionLT(10, 5))
@@ -258,9 +254,16 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
DwarfStrOffSection =
Ctx->getMachOSection("__DWARF", "__debug_str_offs", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "section_str_off");
+ DwarfAddrSection =
+ Ctx->getMachOSection("__DWARF", "__debug_addr", MachO::S_ATTR_DEBUG,
+ SectionKind::getMetadata(), "section_info");
DwarfLocSection =
Ctx->getMachOSection("__DWARF", "__debug_loc", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "section_debug_loc");
+ DwarfLoclistsSection =
+ Ctx->getMachOSection("__DWARF", "__debug_loclists", MachO::S_ATTR_DEBUG,
+ SectionKind::getMetadata(), "section_debug_loc");
+
DwarfARangesSection =
Ctx->getMachOSection("__DWARF", "__debug_aranges", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
@@ -295,11 +298,11 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
switch (T.getArch()) {
case Triple::mips:
case Triple::mipsel:
- FDECFIEncoding = dwarf::DW_EH_PE_sdata4;
- break;
case Triple::mips64:
case Triple::mips64el:
- FDECFIEncoding = dwarf::DW_EH_PE_sdata8;
+ FDECFIEncoding = Ctx->getAsmInfo()->getCodePointerSize() == 4
+ ? dwarf::DW_EH_PE_sdata4
+ : dwarf::DW_EH_PE_sdata8;
break;
case Triple::ppc64:
case Triple::ppc64le:
@@ -311,158 +314,12 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
case Triple::bpfeb:
FDECFIEncoding = dwarf::DW_EH_PE_sdata8;
break;
- default:
- FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
- break;
- }
-
- switch (T.getArch()) {
- case Triple::arm:
- case Triple::armeb:
- case Triple::thumb:
- case Triple::thumbeb:
- if (Ctx->getAsmInfo()->getExceptionHandlingType() == ExceptionHandling::ARM)
- break;
- // Fallthrough if not using EHABI
- LLVM_FALLTHROUGH;
- case Triple::ppc:
- case Triple::x86:
- PersonalityEncoding = PositionIndependent
- ? dwarf::DW_EH_PE_indirect |
- dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_sdata4
- : dwarf::DW_EH_PE_absptr;
- LSDAEncoding = PositionIndependent
- ? dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4
- : dwarf::DW_EH_PE_absptr;
- TTypeEncoding = PositionIndependent
- ? dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_sdata4
- : dwarf::DW_EH_PE_absptr;
- break;
- case Triple::x86_64:
- if (PositionIndependent) {
- 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 |
- (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4);
- TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4);
- } else {
- PersonalityEncoding =
- 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:
- PersonalityEncoding = dwarf::DW_EH_PE_absptr;
- LSDAEncoding = dwarf::DW_EH_PE_absptr;
- FDECFIEncoding = dwarf::DW_EH_PE_absptr;
- TTypeEncoding = dwarf::DW_EH_PE_absptr;
- if (PositionIndependent) {
- PersonalityEncoding |= dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel;
- LSDAEncoding |= dwarf::DW_EH_PE_pcrel;
- FDECFIEncoding |= dwarf::DW_EH_PE_pcrel;
- TTypeEncoding |= dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel;
- }
- break;
- case Triple::aarch64:
- case Triple::aarch64_be:
- // The small model guarantees static code/data size < 4GB, but not where it
- // will be in memory. Most of these could end up >2GB away so even a signed
- // pc-relative 32-bit address is insufficient, theoretically.
- if (PositionIndependent) {
- PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_sdata8;
- LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8;
- TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_sdata8;
- } else {
- PersonalityEncoding = dwarf::DW_EH_PE_absptr;
- LSDAEncoding = dwarf::DW_EH_PE_absptr;
- TTypeEncoding = dwarf::DW_EH_PE_absptr;
- }
- break;
- case Triple::lanai:
- LSDAEncoding = dwarf::DW_EH_PE_absptr;
- PersonalityEncoding = dwarf::DW_EH_PE_absptr;
- TTypeEncoding = dwarf::DW_EH_PE_absptr;
- break;
- case Triple::mips:
- case Triple::mipsel:
- case Triple::mips64:
- case Triple::mips64el:
- // MIPS uses indirect pointer to refer personality functions and types, so
- // that the eh_frame section can be read-only. DW.ref.personality will be
- // generated for relocation.
- PersonalityEncoding = dwarf::DW_EH_PE_indirect;
- // FIXME: The N64 ABI probably ought to use DW_EH_PE_sdata8 but we can't
- // identify N64 from just a triple.
- TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_sdata4;
- // We don't support PC-relative LSDA references in GAS so we use the default
- // DW_EH_PE_absptr for those.
-
- // FreeBSD must be explicit about the data size and using pcrel since it's
- // assembler/linker won't do the automatic conversion that the Linux tools
- // do.
- if (T.isOSFreeBSD()) {
- PersonalityEncoding |= dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
- LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
- }
- break;
- case Triple::ppc64:
- case Triple::ppc64le:
- PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_udata8;
- LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8;
- TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_udata8;
- break;
- case Triple::sparcel:
- case Triple::sparc:
- if (PositionIndependent) {
- LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
- PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_sdata4;
- TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_sdata4;
- } else {
- LSDAEncoding = dwarf::DW_EH_PE_absptr;
- PersonalityEncoding = dwarf::DW_EH_PE_absptr;
- TTypeEncoding = dwarf::DW_EH_PE_absptr;
- }
- break;
- case Triple::sparcv9:
- LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
- if (PositionIndependent) {
- PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_sdata4;
- TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_sdata4;
- } else {
- PersonalityEncoding = dwarf::DW_EH_PE_absptr;
- TTypeEncoding = dwarf::DW_EH_PE_absptr;
- }
- break;
- case Triple::systemz:
- // All currently-defined code models guarantee that 4-byte PC-relative
- // values will be in range.
- if (PositionIndependent) {
- PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_sdata4;
- LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
- TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
- dwarf::DW_EH_PE_sdata4;
- } else {
- PersonalityEncoding = dwarf::DW_EH_PE_absptr;
- LSDAEncoding = dwarf::DW_EH_PE_absptr;
- TTypeEncoding = dwarf::DW_EH_PE_absptr;
- }
+ FDECFIEncoding =
+ PositionIndependent ? dwarf::DW_EH_PE_pcrel : dwarf::DW_EH_PE_absptr;
break;
default:
+ FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
break;
}
@@ -582,25 +439,26 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
Ctx->getELFSection(".debug_str_offsets", DebugSecType, 0);
DwarfAddrSection = Ctx->getELFSection(".debug_addr", DebugSecType, 0);
DwarfRnglistsSection = Ctx->getELFSection(".debug_rnglists", DebugSecType, 0);
+ DwarfLoclistsSection = Ctx->getELFSection(".debug_loclists", DebugSecType, 0);
// Fission Sections
DwarfInfoDWOSection =
- Ctx->getELFSection(".debug_info.dwo", DebugSecType, 0);
+ Ctx->getELFSection(".debug_info.dwo", DebugSecType, ELF::SHF_EXCLUDE);
DwarfTypesDWOSection =
- Ctx->getELFSection(".debug_types.dwo", DebugSecType, 0);
+ Ctx->getELFSection(".debug_types.dwo", DebugSecType, ELF::SHF_EXCLUDE);
DwarfAbbrevDWOSection =
- Ctx->getELFSection(".debug_abbrev.dwo", DebugSecType, 0);
- DwarfStrDWOSection =
- Ctx->getELFSection(".debug_str.dwo", DebugSecType,
- ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, "");
+ Ctx->getELFSection(".debug_abbrev.dwo", DebugSecType, ELF::SHF_EXCLUDE);
+ DwarfStrDWOSection = Ctx->getELFSection(
+ ".debug_str.dwo", DebugSecType,
+ ELF::SHF_MERGE | ELF::SHF_STRINGS | ELF::SHF_EXCLUDE, 1, "");
DwarfLineDWOSection =
- Ctx->getELFSection(".debug_line.dwo", DebugSecType, 0);
+ Ctx->getELFSection(".debug_line.dwo", DebugSecType, ELF::SHF_EXCLUDE);
DwarfLocDWOSection =
- Ctx->getELFSection(".debug_loc.dwo", DebugSecType, 0);
- DwarfStrOffDWOSection =
- Ctx->getELFSection(".debug_str_offsets.dwo", DebugSecType, 0);
+ Ctx->getELFSection(".debug_loc.dwo", DebugSecType, ELF::SHF_EXCLUDE);
+ DwarfStrOffDWOSection = Ctx->getELFSection(".debug_str_offsets.dwo",
+ DebugSecType, ELF::SHF_EXCLUDE);
DwarfRnglistsDWOSection =
- Ctx->getELFSection(".debug_rnglists.dwo", DebugSecType, 0);
+ Ctx->getELFSection(".debug_rnglists.dwo", DebugSecType, ELF::SHF_EXCLUDE);
// DWP Sections
DwarfCUIndexSection =
@@ -621,10 +479,10 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
}
void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
- EHFrameSection = Ctx->getCOFFSection(
- ".eh_frame", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE,
- SectionKind::getData());
+ EHFrameSection =
+ Ctx->getCOFFSection(".eh_frame", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getData());
// Set the `IMAGE_SCN_MEM_16BIT` flag when compiling for thumb mode. This is
// used to indicate to the linker that the text segment contains thumb instructions
@@ -652,11 +510,7 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
".rdata", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ,
SectionKind::getReadOnly());
- // FIXME: We're emitting LSDA info into a readonly section on COFF, even
- // though it contains relocatable pointers. In PIC mode, this is probably a
- // big runtime hit for C++ apps. Either the contents of the LSDA need to be
- // adjusted or this should be a data section.
- if (T.getArch() == Triple::x86_64) {
+ if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::aarch64) {
// On Windows 64 with SEH, the LSDA is emitted into the .xdata section
LSDASection = nullptr;
} else {
@@ -893,6 +747,12 @@ void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) {
DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", SectionKind::getMetadata());
DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", SectionKind::getMetadata());
+ // Wasm use data section for LSDA.
+ // TODO Consider putting each function's exception table in a separate
+ // section, as in -function-sections, to facilitate lld's --gc-section.
+ LSDASection = Ctx->getWasmSection(".rodata.gcc_except_table",
+ SectionKind::getReadOnlyWithRel());
+
// TODO: Define more sections.
}
@@ -908,8 +768,7 @@ void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC,
SupportsCompactUnwindWithoutEHFrame = false;
OmitDwarfIfHaveCompactUnwind = false;
- PersonalityEncoding = LSDAEncoding = FDECFIEncoding = TTypeEncoding =
- dwarf::DW_EH_PE_absptr;
+ FDECFIEncoding = dwarf::DW_EH_PE_absptr;
CompactUnwindDwarfEHFrameOnly = 0;
@@ -949,16 +808,17 @@ void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC,
}
}
-MCSection *MCObjectFileInfo::getDwarfTypesSection(uint64_t Hash) const {
+MCSection *MCObjectFileInfo::getDwarfComdatSection(const char *Name,
+ uint64_t Hash) const {
switch (TT.getObjectFormat()) {
case Triple::ELF:
- return Ctx->getELFSection(".debug_types", ELF::SHT_PROGBITS, ELF::SHF_GROUP,
- 0, utostr(Hash));
+ return Ctx->getELFSection(Name, ELF::SHT_PROGBITS, ELF::SHF_GROUP, 0,
+ utostr(Hash));
case Triple::MachO:
case Triple::COFF:
case Triple::Wasm:
case Triple::UnknownObjectFormat:
- report_fatal_error("Cannot get DWARF types section for this object file "
+ report_fatal_error("Cannot get DWARF comdat section for this object file "
"format: not implemented.");
break;
}
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index 4b6dad5ce8f3..6ec705bdddb7 100644
--- a/lib/MC/MCObjectStreamer.cpp
+++ b/lib/MC/MCObjectStreamer.cpp
@@ -59,11 +59,35 @@ void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
PendingLabels.clear();
}
+// When fixup's offset is a forward declared label, e.g.:
+//
+// .reloc 1f, R_MIPS_JALR, foo
+// 1: nop
+//
+// postpone adding it to Fixups vector until the label is defined and its offset
+// is known.
+void MCObjectStreamer::resolvePendingFixups() {
+ for (PendingMCFixup &PendingFixup : PendingFixups) {
+ if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) {
+ getContext().reportError(PendingFixup.Fixup.getLoc(),
+ "unresolved relocation offset");
+ continue;
+ }
+ flushPendingLabels(PendingFixup.DF, PendingFixup.DF->getContents().size());
+ PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset());
+ PendingFixup.DF->getFixups().push_back(PendingFixup.Fixup);
+ }
+ PendingFixups.clear();
+}
+
// As a compile-time optimization, avoid allocating and evaluating an MCExpr
// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.
-static Optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi,
- const MCSymbol *Lo) {
+static Optional<uint64_t>
+absoluteSymbolDiff(MCAssembler &Asm, const MCSymbol *Hi, const MCSymbol *Lo) {
assert(Hi && Lo);
+ if (Asm.getBackendPtr()->requiresDiffExpressionRelocations())
+ return None;
+
if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||
Hi->isVariable() || Lo->isVariable())
return None;
@@ -74,7 +98,7 @@ static Optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi,
void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
const MCSymbol *Lo,
unsigned Size) {
- if (Optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) {
+ if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) {
EmitIntValue(*Diff, Size);
return;
}
@@ -83,7 +107,7 @@ void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
const MCSymbol *Lo) {
- if (Optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) {
+ if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) {
EmitULEB128IntValue(*Diff);
return;
}
@@ -170,7 +194,6 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
- MCCVLineEntry::Make(this);
MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
// Avoid fixups when possible.
@@ -267,7 +290,6 @@ bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
const MCExpr *Subsection) {
assert(Section && "Cannot switch to a null section!");
flushPendingLabels(nullptr);
- getContext().clearCVLocSeen();
getContext().clearDwarfLocSeen();
bool Created = getAssembler().registerSection(*Section);
@@ -308,7 +330,6 @@ void MCObjectStreamer::EmitInstructionImpl(const MCInst &Inst,
// Now that a machine instruction has been assembled into this section, make
// a line entry for any .loc directive that has been seen.
- MCCVLineEntry::Make(this);
MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
// If this instruction doesn't need relaxation, just emit it as data.
@@ -443,12 +464,16 @@ void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
unsigned Line, unsigned Column,
bool PrologueEnd, bool IsStmt,
StringRef FileName, SMLoc Loc) {
- // In case we see two .cv_loc directives in a row, make sure the
- // first one gets a line entry.
- MCCVLineEntry::Make(this);
+ // Validate the directive.
+ if (!checkCVLocSection(FunctionId, FileNo, Loc))
+ return;
- this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
- PrologueEnd, IsStmt, FileName, Loc);
+ // Emit a label at the current position and record it in the CodeViewContext.
+ MCSymbol *LineSym = getContext().createTempSymbol();
+ EmitLabel(LineSym);
+ getContext().getCVContext().recordCVLoc(getContext(), LineSym, FunctionId,
+ FileNo, Line, Column, PrologueEnd,
+ IsStmt);
}
void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId,
@@ -472,7 +497,11 @@ void MCObjectStreamer::EmitCVInlineLinetableDirective(
void MCObjectStreamer::EmitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
StringRef FixedSizePortion) {
- getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion);
+ MCFragment *Frag =
+ getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion);
+ // Attach labels that were pending before we created the defrange fragment to
+ // the beginning of the new fragment.
+ flushPendingLabels(Frag, 0);
this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
}
@@ -488,11 +517,16 @@ void MCObjectStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
}
void MCObjectStreamer::EmitBytes(StringRef Data) {
- MCCVLineEntry::Make(this);
MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
DF->getContents().append(Data.begin(), Data.end());
+
+ // EmitBytes might not cover all possible ways we emit data (or could be used
+ // to emit executable code in some cases), but is the best method we have
+ // right now for checking this.
+ MCSection *Sec = getCurrentSectionOnly();
+ Sec->setHasData(true);
}
void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment,
@@ -594,16 +628,6 @@ void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) {
bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
const MCExpr *Expr, SMLoc Loc,
const MCSubtargetInfo &STI) {
- int64_t OffsetValue;
- if (!Offset.evaluateAsAbsolute(OffsetValue))
- llvm_unreachable("Offset is not absolute");
-
- if (OffsetValue < 0)
- llvm_unreachable("Offset is negative");
-
- MCDataFragment *DF = getOrCreateDataFragment(&STI);
- flushPendingLabels(DF, DF->getContents().size());
-
Optional<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name);
if (!MaybeKind.hasValue())
return true;
@@ -613,7 +637,30 @@ bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
if (Expr == nullptr)
Expr =
MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
- DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc));
+
+ MCDataFragment *DF = getOrCreateDataFragment(&STI);
+ flushPendingLabels(DF, DF->getContents().size());
+
+ int64_t OffsetValue;
+ if (Offset.evaluateAsAbsolute(OffsetValue)) {
+ if (OffsetValue < 0)
+ llvm_unreachable(".reloc offset is negative");
+ DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc));
+ return false;
+ }
+
+ if (Offset.getKind() != llvm::MCExpr::SymbolRef)
+ llvm_unreachable(".reloc offset is not absolute nor a label");
+
+ const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(Offset);
+ if (SRE.getSymbol().isDefined()) {
+ DF->getFixups().push_back(MCFixup::create(SRE.getSymbol().getOffset(),
+ Expr, Kind, Loc));
+ return false;
+ }
+
+ PendingFixups.emplace_back(&SRE.getSymbol(), DF,
+ MCFixup::create(-1, Expr, Kind, Loc));
return false;
}
@@ -680,5 +727,6 @@ void MCObjectStreamer::FinishImpl() {
MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams());
flushPendingLabels();
+ resolvePendingFixups();
getAssembler().Finish();
}
diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp
index 74835fd70c04..2b0d20f9b8e2 100644
--- a/lib/MC/MCParser/AsmLexer.cpp
+++ b/lib/MC/MCParser/AsmLexer.cpp
@@ -243,22 +243,26 @@ static void SkipIgnoredIntegerSuffix(const char *&CurPtr) {
// Look ahead to search for first non-hex digit, if it's [hH], then we treat the
// integer as a hexadecimal, possibly with leading zeroes.
-static unsigned doLookAhead(const char *&CurPtr, unsigned DefaultRadix) {
- const char *FirstHex = nullptr;
+static unsigned doHexLookAhead(const char *&CurPtr, unsigned DefaultRadix,
+ bool LexHex) {
+ const char *FirstNonDec = nullptr;
const char *LookAhead = CurPtr;
while (true) {
if (isDigit(*LookAhead)) {
++LookAhead;
- } else if (isHexDigit(*LookAhead)) {
- if (!FirstHex)
- FirstHex = LookAhead;
- ++LookAhead;
} else {
- break;
+ if (!FirstNonDec)
+ FirstNonDec = LookAhead;
+
+ // Keep going if we are looking for a 'h' suffix.
+ if (LexHex && isHexDigit(*LookAhead))
+ ++LookAhead;
+ else
+ break;
}
}
- bool isHex = *LookAhead == 'h' || *LookAhead == 'H';
- CurPtr = isHex || !FirstHex ? LookAhead : FirstHex;
+ bool isHex = LexHex && (*LookAhead == 'h' || *LookAhead == 'H');
+ CurPtr = isHex || !FirstNonDec ? LookAhead : FirstNonDec;
if (isHex)
return 16;
return DefaultRadix;
@@ -281,7 +285,7 @@ static AsmToken intToken(StringRef Ref, APInt &Value)
AsmToken AsmLexer::LexDigit() {
// MASM-flavor binary integer: [01]+[bB]
// MASM-flavor hexadecimal integer: [0-9][0-9a-fA-F]*[hH]
- if (IsParsingMSInlineAsm && isdigit(CurPtr[-1])) {
+ if (LexMasmIntegers && isdigit(CurPtr[-1])) {
const char *FirstNonBinary = (CurPtr[-1] != '0' && CurPtr[-1] != '1') ?
CurPtr - 1 : nullptr;
const char *OldCurPtr = CurPtr;
@@ -320,7 +324,7 @@ AsmToken AsmLexer::LexDigit() {
// Decimal integer: [1-9][0-9]*
if (CurPtr[-1] != '0' || CurPtr[0] == '.') {
- unsigned Radix = doLookAhead(CurPtr, 10);
+ unsigned Radix = doHexLookAhead(CurPtr, 10, LexMasmIntegers);
bool isHex = Radix == 16;
// Check for floating point literals.
if (!isHex && (*CurPtr == '.' || *CurPtr == 'e')) {
@@ -335,8 +339,8 @@ AsmToken AsmLexer::LexDigit() {
return ReturnError(TokStart, !isHex ? "invalid decimal number" :
"invalid hexdecimal number");
- // Consume the [bB][hH].
- if (Radix == 2 || Radix == 16)
+ // Consume the [hH].
+ if (LexMasmIntegers && Radix == 16)
++CurPtr;
// The darwin/x86 (and x86-64) assembler accepts and ignores type
@@ -346,7 +350,7 @@ AsmToken AsmLexer::LexDigit() {
return intToken(Result, Value);
}
- if (!IsParsingMSInlineAsm && ((*CurPtr == 'b') || (*CurPtr == 'B'))) {
+ if (!LexMasmIntegers && ((*CurPtr == 'b') || (*CurPtr == 'B'))) {
++CurPtr;
// See if we actually have "0b" as part of something like "jmp 0b\n"
if (!isDigit(CurPtr[0])) {
@@ -395,7 +399,7 @@ AsmToken AsmLexer::LexDigit() {
return ReturnError(TokStart, "invalid hexadecimal number");
// Consume the optional [hH].
- if (!IsParsingMSInlineAsm && (*CurPtr == 'h' || *CurPtr == 'H'))
+ if (LexMasmIntegers && (*CurPtr == 'h' || *CurPtr == 'H'))
++CurPtr;
// The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
@@ -407,7 +411,7 @@ AsmToken AsmLexer::LexDigit() {
// Either octal or hexadecimal.
APInt Value(128, 0, true);
- unsigned Radix = doLookAhead(CurPtr, 8);
+ unsigned Radix = doHexLookAhead(CurPtr, 8, LexMasmIntegers);
bool isHex = Radix == 16;
StringRef Result(TokStart, CurPtr - TokStart);
if (Result.getAsInteger(Radix, Value))
@@ -623,7 +627,6 @@ AsmToken AsmLexer::LexToken() {
return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
- case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
@@ -642,6 +645,12 @@ AsmToken AsmLexer::LexToken() {
return AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
}
return AsmToken(AsmToken::Equal, StringRef(TokStart, 1));
+ case '-':
+ if (*CurPtr == '>') {
+ ++CurPtr;
+ return AsmToken(AsmToken::MinusGreater, StringRef(TokStart, 2));
+ }
+ return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
case '|':
if (*CurPtr == '|') {
++CurPtr;
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 39a760826d96..cf42a6f7075b 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -180,6 +180,9 @@ private:
/// Did we already inform the user about inconsistent MD5 usage?
bool ReportedInconsistentMD5 = false;
+ // Is alt macro mode enabled.
+ bool AltMacroMode = false;
+
public:
AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
const MCAsmInfo &MAI, unsigned CB);
@@ -226,7 +229,9 @@ public:
void setParsingInlineAsm(bool V) override {
ParsingInlineAsm = V;
- Lexer.setParsingMSInlineAsm(V);
+ // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
+ // hex integer literals.
+ Lexer.setLexMasmIntegers(V);
}
bool isParsingInlineAsm() override { return ParsingInlineAsm; }
@@ -260,8 +265,6 @@ public:
/// }
private:
- bool isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc);
- void altMacroString(StringRef AltMacroStr, std::string &Res);
bool parseStatement(ParseStatementInfo &Info,
MCAsmParserSemaCallback *SI);
bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
@@ -337,7 +340,7 @@ private:
StringRef parseStringToComma();
bool parseAssignment(StringRef Name, bool allow_redef,
- bool NoDeadStrip = false, bool AllowExtendedExpr = false);
+ bool NoDeadStrip = false);
unsigned getBinOpPrecedence(AsmToken::TokenKind K,
MCBinaryExpr::Opcode &Kind);
@@ -467,6 +470,7 @@ private:
DK_CV_INLINE_LINETABLE,
DK_CV_DEF_RANGE,
DK_CV_STRINGTABLE,
+ DK_CV_STRING,
DK_CV_FILECHECKSUMS,
DK_CV_FILECHECKSUM_OFFSET,
DK_CV_FPO_DATA,
@@ -491,6 +495,7 @@ private:
DK_CFI_UNDEFINED,
DK_CFI_REGISTER,
DK_CFI_WINDOW_SAVE,
+ DK_CFI_B_KEY_FRAME,
DK_MACROS_ON,
DK_MACROS_OFF,
DK_ALTMACRO,
@@ -538,7 +543,7 @@ private:
bool parseDirectiveStabs();
// ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
- // ".cv_inline_linetable", ".cv_def_range"
+ // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
bool parseDirectiveCVFile();
bool parseDirectiveCVFuncId();
bool parseDirectiveCVInlineSiteId();
@@ -546,6 +551,7 @@ private:
bool parseDirectiveCVLinetable();
bool parseDirectiveCVInlineLinetable();
bool parseDirectiveCVDefRange();
+ bool parseDirectiveCVString();
bool parseDirectiveCVStringTable();
bool parseDirectiveCVFileChecksums();
bool parseDirectiveCVFileChecksumOffset();
@@ -670,6 +676,7 @@ namespace llvm {
extern MCAsmParserExtension *createDarwinAsmParser();
extern MCAsmParserExtension *createELFAsmParser();
extern MCAsmParserExtension *createCOFFAsmParser();
+extern MCAsmParserExtension *createWasmAsmParser();
} // end namespace llvm
@@ -700,10 +707,7 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
PlatformParser.reset(createELFAsmParser());
break;
case MCObjectFileInfo::IsWasm:
- // TODO: WASM will need its own MCAsmParserExtension implementation, but
- // for now we can re-use the ELF one, since the directives can be the
- // same for now.
- PlatformParser.reset(createELFAsmParser());
+ PlatformParser.reset(createWasmAsmParser());
break;
}
@@ -895,6 +899,9 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
eatToEndOfStatement();
}
+ getTargetParser().onEndOfFile();
+ printPendingErrors();
+
// All errors should have been emitted.
assert(!hasPendingError() && "unexpected error from parseStatement");
@@ -1100,7 +1107,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
// This is a symbol reference.
StringRef SymbolName = Identifier;
if (SymbolName.empty())
- return true;
+ return Error(getLexer().getLoc(), "expected a symbol reference");
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
@@ -1123,7 +1130,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
// semantics in the face of reassignment.
if (Sym->isVariable()) {
auto V = Sym->getVariableValue(/*SetUsed*/ false);
- bool DoInline = isa<MCConstantExpr>(V);
+ bool DoInline = isa<MCConstantExpr>(V) && !Variant;
if (auto TV = dyn_cast<MCTargetExpr>(V))
DoInline = TV->inlineAssignedExpr();
if (DoInline) {
@@ -1321,11 +1328,12 @@ AsmParser::applyModifierToExpr(const MCExpr *E,
/// the End argument will be filled with the last location pointed to the '>'
/// character.
-/// There is a gap between the AltMacro's documentation and the single quote implementation.
-/// GCC does not fully support this feature and so we will not support it.
+/// There is a gap between the AltMacro's documentation and the single quote
+/// implementation. GCC does not fully support this feature and so we will not
+/// support it.
/// TODO: Adding single quote as a string.
-bool AsmParser::isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
- assert((StrLoc.getPointer() != NULL) &&
+static bool isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
+ assert((StrLoc.getPointer() != nullptr) &&
"Argument to the function cannot be a NULL value");
const char *CharPtr = StrLoc.getPointer();
while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
@@ -1342,12 +1350,14 @@ bool AsmParser::isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
}
/// creating a string without the escape characters '!'.
-void AsmParser::altMacroString(StringRef AltMacroStr,std::string &Res) {
+static std::string altMacroString(StringRef AltMacroStr) {
+ std::string Res;
for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
if (AltMacroStr[Pos] == '!')
Pos++;
Res += AltMacroStr[Pos];
}
+ return Res;
}
/// Parse an expression and return it.
@@ -1363,7 +1373,8 @@ void AsmParser::altMacroString(StringRef AltMacroStr,std::string &Res) {
bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
// Parse the expression.
Res = nullptr;
- if (parsePrimaryExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc))
+ if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
+ parseBinOpRHS(1, Res, EndLoc))
return true;
// As a special case, we support 'a op b @ modifier' by rewriting the
@@ -1617,7 +1628,7 @@ bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
// Eat the next primary expression.
const MCExpr *RHS;
- if (parsePrimaryExpr(RHS, EndLoc))
+ if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
return true;
// If BinOp binds less tightly with RHS than the operator after RHS, let
@@ -1805,6 +1816,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
Lex();
}
+ getTargetParser().doBeforeLabelEmit(Sym);
+
// Emit the label.
if (!getTargetParser().isParsingInlineAsm())
Out.EmitLabel(Sym, IDLoc);
@@ -1826,7 +1839,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
// identifier '=' ... -> assignment statement
Lex();
- return parseAssignment(IDVal, true, /*NoDeadStrip*/ false, /*AllowExtendedExpr*/true);
+ return parseAssignment(IDVal, true);
default: // Normal instruction or directive.
break;
@@ -1841,7 +1854,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
// Otherwise, we have a normal instruction or directive.
// Directives start with "."
- if (IDVal[0] == '.' && IDVal != ".") {
+ if (IDVal.startswith(".") && IDVal != ".") {
// There are several entities interested in parsing directives:
//
// 1. The target-specific assembly parser. Some directives are target
@@ -2028,6 +2041,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectiveCVInlineLinetable();
case DK_CV_DEF_RANGE:
return parseDirectiveCVDefRange();
+ case DK_CV_STRING:
+ return parseDirectiveCVString();
case DK_CV_STRINGTABLE:
return parseDirectiveCVStringTable();
case DK_CV_FILECHECKSUMS:
@@ -2430,21 +2445,20 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
for (const AsmToken &Token : A[Index])
// For altmacro mode, you can write '%expr'.
// The prefix '%' evaluates the expression 'expr'
- // and uses the result as a string (e.g. replace %(1+2) with the string "3").
+ // and uses the result as a string (e.g. replace %(1+2) with the
+ // string "3").
// Here, we identify the integer token which is the result of the
- // absolute expression evaluation and replace it with its string representation.
- if ((Lexer.IsaAltMacroMode()) &&
- (*(Token.getString().begin()) == '%') && Token.is(AsmToken::Integer))
+ // absolute expression evaluation and replace it with its string
+ // representation.
+ if (AltMacroMode && Token.getString().front() == '%' &&
+ Token.is(AsmToken::Integer))
// Emit an integer value to the buffer.
OS << Token.getIntVal();
// Only Token that was validated as a string and begins with '<'
// is considered altMacroString!!!
- else if ((Lexer.IsaAltMacroMode()) &&
- (*(Token.getString().begin()) == '<') &&
+ else if (AltMacroMode && Token.getString().front() == '<' &&
Token.is(AsmToken::String)) {
- std::string Res;
- altMacroString(Token.getStringContents(), Res);
- OS << Res;
+ OS << altMacroString(Token.getStringContents());
}
// We expect no quotes around the string's contents when
// parsing for varargs.
@@ -2626,31 +2640,33 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
SMLoc StrLoc = Lexer.getLoc();
SMLoc EndLoc;
- if (Lexer.IsaAltMacroMode() && Lexer.is(AsmToken::Percent)) {
- const MCExpr *AbsoluteExp;
- int64_t Value;
- /// Eat '%'
- Lex();
- if (parseExpression(AbsoluteExp, EndLoc))
- return false;
- if (!AbsoluteExp->evaluateAsAbsolute(Value,
- getStreamer().getAssemblerPtr()))
- return Error(StrLoc, "expected absolute expression");
- const char *StrChar = StrLoc.getPointer();
- const char *EndChar = EndLoc.getPointer();
- AsmToken newToken(AsmToken::Integer, StringRef(StrChar , EndChar - StrChar), Value);
- FA.Value.push_back(newToken);
- } else if (Lexer.IsaAltMacroMode() && Lexer.is(AsmToken::Less) &&
+ if (AltMacroMode && Lexer.is(AsmToken::Percent)) {
+ const MCExpr *AbsoluteExp;
+ int64_t Value;
+ /// Eat '%'
+ Lex();
+ if (parseExpression(AbsoluteExp, EndLoc))
+ return false;
+ if (!AbsoluteExp->evaluateAsAbsolute(Value,
+ getStreamer().getAssemblerPtr()))
+ return Error(StrLoc, "expected absolute expression");
+ const char *StrChar = StrLoc.getPointer();
+ const char *EndChar = EndLoc.getPointer();
+ AsmToken newToken(AsmToken::Integer,
+ StringRef(StrChar, EndChar - StrChar), Value);
+ FA.Value.push_back(newToken);
+ } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
isAltmacroString(StrLoc, EndLoc)) {
- const char *StrChar = StrLoc.getPointer();
- const char *EndChar = EndLoc.getPointer();
- jumpToLoc(EndLoc, CurBuffer);
- /// Eat from '<' to '>'
- Lex();
- AsmToken newToken(AsmToken::String, StringRef(StrChar, EndChar - StrChar));
- FA.Value.push_back(newToken);
+ const char *StrChar = StrLoc.getPointer();
+ const char *EndChar = EndLoc.getPointer();
+ jumpToLoc(EndLoc, CurBuffer);
+ /// Eat from '<' to '>'
+ Lex();
+ AsmToken newToken(AsmToken::String,
+ StringRef(StrChar, EndChar - StrChar));
+ FA.Value.push_back(newToken);
} else if(parseMacroArgument(FA.Value, Vararg))
- return true;
+ return true;
unsigned PI = Parameter;
if (!FA.Name.empty()) {
@@ -2766,11 +2782,11 @@ void AsmParser::handleMacroExit() {
}
bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
- bool NoDeadStrip, bool AllowExtendedExpr) {
+ bool NoDeadStrip) {
MCSymbol *Sym;
const MCExpr *Value;
if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym,
- Value, AllowExtendedExpr))
+ Value))
return true;
if (!Sym) {
@@ -2926,20 +2942,20 @@ bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
const MCExpr *Offset;
const MCExpr *Expr = nullptr;
-
- SMLoc OffsetLoc = Lexer.getTok().getLoc();
int64_t OffsetValue;
- // We can only deal with constant expressions at the moment.
+ SMLoc OffsetLoc = Lexer.getTok().getLoc();
if (parseExpression(Offset))
return true;
- if (check(!Offset->evaluateAsAbsolute(OffsetValue,
- getStreamer().getAssemblerPtr()),
- OffsetLoc, "expression is not a constant value") ||
- check(OffsetValue < 0, OffsetLoc, "expression is negative") ||
- parseToken(AsmToken::Comma, "expected comma") ||
- check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
+ if ((Offset->evaluateAsAbsolute(OffsetValue,
+ getStreamer().getAssemblerPtr()) &&
+ check(OffsetValue < 0, OffsetLoc, "expression is negative")) ||
+ (check(Offset->getKind() != llvm::MCExpr::Constant &&
+ Offset->getKind() != llvm::MCExpr::SymbolRef,
+ OffsetLoc, "expected non-negative number or a label")) ||
+ (parseToken(AsmToken::Comma, "expected comma") ||
+ check(getTok().isNot(AsmToken::Identifier), "expected relocation name")))
return true;
SMLoc NameLoc = Lexer.getTok().getLoc();
@@ -3347,17 +3363,20 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
}
}
- // In case there is a -g option as well as debug info from directive .file,
- // we turn off the -g option, directly use the existing debug info instead.
- // Also reset any implicit ".file 0" for the assembler source.
- if (Ctx.getGenDwarfForAssembly()) {
- Ctx.getMCDwarfLineTable(0).resetRootFile();
- Ctx.setGenDwarfForAssembly(false);
- }
-
- if (FileNumber == -1)
+ if (FileNumber == -1) {
+ if (!getContext().getAsmInfo()->hasSingleParameterDotFile())
+ return Error(DirectiveLoc,
+ "target does not support '.file' without a number");
getStreamer().EmitFileDirective(Filename);
- else {
+ } else {
+ // In case there is a -g option as well as debug info from directive .file,
+ // we turn off the -g option, directly use the existing debug info instead.
+ // Also reset any implicit ".file 0" for the assembler source.
+ if (Ctx.getGenDwarfForAssembly()) {
+ Ctx.getMCDwarfLineTable(0).resetRootFile();
+ Ctx.setGenDwarfForAssembly(false);
+ }
+
MD5::MD5Result *CKMem = nullptr;
if (HasMD5) {
CKMem = (MD5::MD5Result *)Ctx.allocate(sizeof(MD5::MD5Result), 1);
@@ -3812,6 +3831,20 @@ bool AsmParser::parseDirectiveCVDefRange() {
return false;
}
+/// parseDirectiveCVString
+/// ::= .cv_stringtable "string"
+bool AsmParser::parseDirectiveCVString() {
+ std::string Data;
+ if (checkForValidSection() || parseEscapedString(Data))
+ return addErrorSuffix(" in '.cv_string' directive");
+
+ // Put the string in the table and emit the offset.
+ std::pair<StringRef, unsigned> Insertion =
+ getCVContext().addToStringTable(Data);
+ getStreamer().EmitIntValue(Insertion.second, 4);
+ return false;
+}
+
/// parseDirectiveCVStringTable
/// ::= .cv_stringtable
bool AsmParser::parseDirectiveCVStringTable() {
@@ -3894,7 +3927,12 @@ bool AsmParser::parseDirectiveCFIStartProc() {
return addErrorSuffix(" in '.cfi_startproc' directive");
}
- getStreamer().EmitCFIStartProc(!Simple.empty());
+ // TODO(kristina): Deal with a corner case of incorrect diagnostic context
+ // being produced if this directive is emitted as part of preprocessor macro
+ // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
+ // Tools like llvm-mc on the other hand are not affected by it, and report
+ // correct context information.
+ getStreamer().EmitCFIStartProc(!Simple.empty(), Lexer.getLoc());
return false;
}
@@ -4162,10 +4200,7 @@ bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '" + Directive + "' directive");
- if (Directive == ".altmacro")
- getLexer().SetAltMacroMode(true);
- else
- getLexer().SetAltMacroMode(false);
+ AltMacroMode = (Directive == ".altmacro");
return false;
}
@@ -5237,6 +5272,7 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
+ DirectiveKindMap[".cv_string"] = DK_CV_STRING;
DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
@@ -5264,6 +5300,7 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
+ DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
DirectiveKindMap[".macro"] = DK_MACRO;
@@ -5839,17 +5876,12 @@ static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
bool parseAssignmentExpression(StringRef Name, bool allow_redef,
MCAsmParser &Parser, MCSymbol *&Sym,
- const MCExpr *&Value, bool AllowExtendedExpr) {
+ const MCExpr *&Value) {
// FIXME: Use better location, we should use proper tokens.
SMLoc EqualLoc = Parser.getTok().getLoc();
- SMLoc EndLoc;
- if (AllowExtendedExpr) {
- if (Parser.getTargetParser().parseAssignmentExpression(Value, EndLoc)) {
- return Parser.TokError("missing expression");
- }
- } else if (Parser.parseExpression(Value, EndLoc))
- return Parser.TokError("missing expression");
+ if (Parser.parseExpression(Value))
+ return Parser.TokError("missing expression");
// Note: we don't count b as used in "a = b". This is to allow
// a = b
diff --git a/lib/MC/MCParser/CMakeLists.txt b/lib/MC/MCParser/CMakeLists.txt
index 99fdd0167993..0c54e8e90193 100644
--- a/lib/MC/MCParser/CMakeLists.txt
+++ b/lib/MC/MCParser/CMakeLists.txt
@@ -8,6 +8,7 @@ add_llvm_library(LLVMMCParser
MCAsmParser.cpp
MCAsmParserExtension.cpp
MCTargetAsmParser.cpp
+ WasmAsmParser.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/MC/MCParser
diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp
index e6fc1fac81ba..cd99112292a9 100644
--- a/lib/MC/MCParser/DarwinAsmParser.cpp
+++ b/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -459,7 +459,12 @@ public:
bool parseBuildVersion(StringRef Directive, SMLoc Loc);
bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type);
+ bool parseMajorMinorVersionComponent(unsigned *Major, unsigned *Minor,
+ const char *VersionName);
+ bool parseOptionalTrailingVersionComponent(unsigned *Component,
+ const char *ComponentName);
bool parseVersion(unsigned *Major, unsigned *Minor, unsigned *Update);
+ bool parseSDKVersion(VersionTuple &SDKVersion);
void checkVersion(StringRef Directive, StringRef Arg, SMLoc Loc,
Triple::OSType ExpectedOS);
};
@@ -1000,43 +1005,89 @@ bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) {
return false;
}
-/// parseVersion ::= major, minor [, update]
-bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor,
- unsigned *Update) {
+static bool isSDKVersionToken(const AsmToken &Tok) {
+ return Tok.is(AsmToken::Identifier) && Tok.getIdentifier() == "sdk_version";
+}
+
+/// parseMajorMinorVersionComponent ::= major, minor
+bool DarwinAsmParser::parseMajorMinorVersionComponent(unsigned *Major,
+ unsigned *Minor,
+ const char *VersionName) {
// Get the major version number.
if (getLexer().isNot(AsmToken::Integer))
- return TokError("invalid OS major version number, integer expected");
+ return TokError(Twine("invalid ") + VersionName +
+ " major version number, integer expected");
int64_t MajorVal = getLexer().getTok().getIntVal();
if (MajorVal > 65535 || MajorVal <= 0)
- return TokError("invalid OS major version number");
+ return TokError(Twine("invalid ") + VersionName + " major version number");
*Major = (unsigned)MajorVal;
Lex();
if (getLexer().isNot(AsmToken::Comma))
- return TokError("OS minor version number required, comma expected");
+ return TokError(Twine(VersionName) +
+ " 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");
+ return TokError(Twine("invalid ") + VersionName +
+ " minor version number, integer expected");
int64_t MinorVal = getLexer().getTok().getIntVal();
if (MinorVal > 255 || MinorVal < 0)
- return TokError("invalid OS minor version number");
+ return TokError(Twine("invalid ") + VersionName + " minor version number");
*Minor = MinorVal;
Lex();
+ return false;
+}
+
+/// parseOptionalTrailingVersionComponent ::= , version_number
+bool DarwinAsmParser::parseOptionalTrailingVersionComponent(
+ unsigned *Component, const char *ComponentName) {
+ assert(getLexer().is(AsmToken::Comma) && "comma expected");
+ Lex();
+ if (getLexer().isNot(AsmToken::Integer))
+ return TokError(Twine("invalid ") + ComponentName +
+ " version number, integer expected");
+ int64_t Val = getLexer().getTok().getIntVal();
+ if (Val > 255 || Val < 0)
+ return TokError(Twine("invalid ") + ComponentName + " version number");
+ *Component = Val;
+ Lex();
+ return false;
+}
+
+/// parseVersion ::= parseMajorMinorVersionComponent
+/// parseOptionalTrailingVersionComponent
+bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor,
+ unsigned *Update) {
+ if (parseMajorMinorVersionComponent(Major, Minor, "OS"))
+ return true;
// Get the update level, if specified
*Update = 0;
- if (getLexer().is(AsmToken::EndOfStatement))
+ if (getLexer().is(AsmToken::EndOfStatement) ||
+ isSDKVersionToken(getLexer().getTok()))
return false;
if (getLexer().isNot(AsmToken::Comma))
return TokError("invalid OS update specifier, comma expected");
+ if (parseOptionalTrailingVersionComponent(Update, "OS update"))
+ return true;
+ return false;
+}
+
+bool DarwinAsmParser::parseSDKVersion(VersionTuple &SDKVersion) {
+ assert(isSDKVersionToken(getLexer().getTok()) && "expected sdk_version");
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();
+ unsigned Major, Minor;
+ if (parseMajorMinorVersionComponent(&Major, &Minor, "SDK"))
+ return true;
+ SDKVersion = VersionTuple(Major, Minor);
+
+ // Get the subminor version, if specified.
+ if (getLexer().is(AsmToken::Comma)) {
+ unsigned Subminor;
+ if (parseOptionalTrailingVersionComponent(&Subminor, "SDK subminor"))
+ return true;
+ SDKVersion = VersionTuple(Major, Minor, Subminor);
+ }
return false;
}
@@ -1066,10 +1117,10 @@ static Triple::OSType getOSTypeFromMCVM(MCVersionMinType Type) {
}
/// parseVersionMin
-/// ::= .ios_version_min parseVersion
-/// | .macosx_version_min parseVersion
-/// | .tvos_version_min parseVersion
-/// | .watchos_version_min parseVersion
+/// ::= .ios_version_min parseVersion parseSDKVersion
+/// | .macosx_version_min parseVersion parseSDKVersion
+/// | .tvos_version_min parseVersion parseSDKVersion
+/// | .watchos_version_min parseVersion parseSDKVersion
bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc,
MCVersionMinType Type) {
unsigned Major;
@@ -1078,13 +1129,16 @@ bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc,
if (parseVersion(&Major, &Minor, &Update))
return true;
+ VersionTuple SDKVersion;
+ if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion))
+ 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);
+ getStreamer().EmitVersionMin(Type, Major, Minor, Update, SDKVersion);
return false;
}
@@ -1094,13 +1148,16 @@ static Triple::OSType getOSTypeFromPlatform(MachO::PlatformType Type) {
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;
+ case MachO::PLATFORM_BRIDGEOS: /* silence warning */ break;
+ case MachO::PLATFORM_IOSSIMULATOR: /* silence warning */ break;
+ case MachO::PLATFORM_TVOSSIMULATOR: /* silence warning */ break;
+ case MachO::PLATFORM_WATCHOSSIMULATOR: /* silence warning */ break;
}
llvm_unreachable("Invalid mach-o platform type");
}
/// parseBuildVersion
-/// ::= .build_version (macos|ios|tvos|watchos), parseVersion
+/// ::= .build_version (macos|ios|tvos|watchos), parseVersion parseSDKVersion
bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) {
StringRef PlatformName;
SMLoc PlatformLoc = getTok().getLoc();
@@ -1126,14 +1183,17 @@ bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) {
if (parseVersion(&Major, &Minor, &Update))
return true;
+ VersionTuple SDKVersion;
+ if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion))
+ 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);
+ getStreamer().EmitBuildVersion(Platform, Major, Minor, Update, SDKVersion);
return false;
}
diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp
index 7bf14968c973..d568f7a71eeb 100644
--- a/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/lib/MC/MCParser/ELFAsmParser.cpp
@@ -321,6 +321,9 @@ static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) {
case 'y':
flags |= ELF::SHF_ARM_PURECODE;
break;
+ case 's':
+ flags |= ELF::SHF_HEX_GPREL;
+ break;
case 'G':
flags |= ELF::SHF_GROUP;
break;
@@ -481,34 +484,6 @@ static bool hasPrefix(StringRef SectionName, StringRef Prefix) {
return SectionName.startswith(Prefix) || SectionName == Prefix.drop_back();
}
-// Return a set of section flags based on the section name that can then
-// be augmented later, otherwise return 0 if we don't have any reasonable
-// defaults.
-static unsigned defaultSectionFlags(StringRef SectionName) {
-
- if (hasPrefix(SectionName, ".rodata.cst"))
- return ELF::SHF_ALLOC | ELF::SHF_MERGE;
-
- if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1")
- return ELF::SHF_ALLOC;
-
- if (SectionName == ".fini" || SectionName == ".init" ||
- hasPrefix(SectionName, ".text."))
- return ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;
-
- if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" ||
- hasPrefix(SectionName, ".bss.") ||
- hasPrefix(SectionName, ".init_array.") ||
- hasPrefix(SectionName, ".fini_array.") ||
- hasPrefix(SectionName, ".preinit_array."))
- return ELF::SHF_ALLOC | ELF::SHF_WRITE;
-
- if (hasPrefix(SectionName, ".tdata.") || hasPrefix(SectionName, ".tbss."))
- return ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS;
-
- return 0;
-}
-
bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
StringRef SectionName;
@@ -518,13 +493,27 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
StringRef TypeName;
int64_t Size = 0;
StringRef GroupName;
+ unsigned Flags = 0;
const MCExpr *Subsection = nullptr;
bool UseLastGroup = false;
MCSymbolELF *Associated = nullptr;
int64_t UniqueID = ~0;
- // Set the default section flags first in case no others are given.
- unsigned Flags = defaultSectionFlags(SectionName);
+ // Set the defaults first.
+ if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1")
+ Flags |= ELF::SHF_ALLOC;
+ else if (SectionName == ".fini" || SectionName == ".init" ||
+ hasPrefix(SectionName, ".text."))
+ Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;
+ else if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" ||
+ hasPrefix(SectionName, ".bss.") ||
+ hasPrefix(SectionName, ".init_array.") ||
+ hasPrefix(SectionName, ".fini_array.") ||
+ hasPrefix(SectionName, ".preinit_array."))
+ Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE;
+ else if (hasPrefix(SectionName, ".tdata.") ||
+ hasPrefix(SectionName, ".tbss."))
+ Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS;
if (getLexer().is(AsmToken::Comma)) {
Lex();
@@ -552,12 +541,6 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
if (extraFlags == -1U)
return TokError("unknown flag");
-
- // If we found additional section flags on a known section then give a
- // warning.
- if (Flags && Flags != extraFlags)
- Warning(loc, "setting incorrect section attributes for " + SectionName);
-
Flags |= extraFlags;
bool Mergeable = Flags & ELF::SHF_MERGE;
diff --git a/lib/MC/MCParser/MCAsmLexer.cpp b/lib/MC/MCParser/MCAsmLexer.cpp
index 75cd318e4fa3..10960fc69633 100644
--- a/lib/MC/MCParser/MCAsmLexer.cpp
+++ b/lib/MC/MCParser/MCAsmLexer.cpp
@@ -15,7 +15,7 @@
using namespace llvm;
-MCAsmLexer::MCAsmLexer() : AltMacroMode(false) {
+MCAsmLexer::MCAsmLexer() {
CurTok.emplace_back(AsmToken::Space, StringRef());
}
@@ -85,6 +85,7 @@ void AsmToken::dump(raw_ostream &OS) const {
case AsmToken::LessGreater: OS << "LessGreater"; break;
case AsmToken::LessLess: OS << "LessLess"; break;
case AsmToken::Minus: OS << "Minus"; break;
+ case AsmToken::MinusGreater: OS << "MinusGreater"; break;
case AsmToken::Percent: OS << "Percent"; break;
case AsmToken::Pipe: OS << "Pipe"; break;
case AsmToken::PipePipe: OS << "PipePipe"; break;
diff --git a/lib/MC/MCParser/MCAsmParser.cpp b/lib/MC/MCParser/MCAsmParser.cpp
index d439734e76fc..efedcdc5a314 100644
--- a/lib/MC/MCParser/MCAsmParser.cpp
+++ b/lib/MC/MCParser/MCAsmParser.cpp
@@ -21,7 +21,7 @@
using namespace llvm;
-MCAsmParser::MCAsmParser() : ShowParsedOperands(0) {}
+MCAsmParser::MCAsmParser() {}
MCAsmParser::~MCAsmParser() = default;
diff --git a/lib/MC/MCParser/WasmAsmParser.cpp b/lib/MC/MCParser/WasmAsmParser.cpp
new file mode 100644
index 000000000000..93bb0cb3c72e
--- /dev/null
+++ b/lib/MC/MCParser/WasmAsmParser.cpp
@@ -0,0 +1,145 @@
+//===- WasmAsmParser.cpp - Wasm Assembly Parser -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// --
+//
+// Note, this is for wasm, the binary format (analogous to ELF), not wasm,
+// the instruction set (analogous to x86), for which parsing code lives in
+// WebAssemblyAsmParser.
+//
+// This file contains processing for generic directives implemented using
+// MCTargetStreamer, the ones that depend on WebAssemblyTargetStreamer are in
+// WebAssemblyAsmParser.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/Wasm.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCSymbolWasm.h"
+#include "llvm/Support/MachineValueType.h"
+
+using namespace llvm;
+
+namespace {
+
+class WasmAsmParser : public MCAsmParserExtension {
+ MCAsmParser *Parser;
+ MCAsmLexer *Lexer;
+
+ template<bool (WasmAsmParser::*HandlerMethod)(StringRef, SMLoc)>
+ void addDirectiveHandler(StringRef Directive) {
+ MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
+ this, HandleDirective<WasmAsmParser, HandlerMethod>);
+
+ getParser().addDirectiveHandler(Directive, Handler);
+ }
+
+public:
+ WasmAsmParser() : Parser(nullptr), Lexer(nullptr) {
+ BracketExpressionsSupported = true;
+ }
+
+ void Initialize(MCAsmParser &P) override {
+ Parser = &P;
+ Lexer = &Parser->getLexer();
+ // Call the base implementation.
+ this->MCAsmParserExtension::Initialize(*Parser);
+
+ addDirectiveHandler<&WasmAsmParser::parseSectionDirectiveText>(".text");
+ addDirectiveHandler<&WasmAsmParser::parseSectionDirective>(".section");
+ addDirectiveHandler<&WasmAsmParser::parseDirectiveSize>(".size");
+ addDirectiveHandler<&WasmAsmParser::parseDirectiveType>(".type");
+ }
+
+ bool Error(const StringRef &msg, const AsmToken &tok) {
+ return Parser->Error(tok.getLoc(), msg + tok.getString());
+ }
+
+ bool IsNext(AsmToken::TokenKind Kind) {
+ auto ok = Lexer->is(Kind);
+ if (ok) Lex();
+ return ok;
+ }
+
+ bool Expect(AsmToken::TokenKind Kind, const char *KindName) {
+ if (!IsNext(Kind))
+ return Error(std::string("Expected ") + KindName + ", instead got: ",
+ Lexer->getTok());
+ return false;
+ }
+
+ bool parseSectionDirectiveText(StringRef, SMLoc) {
+ // FIXME: .text currently no-op.
+ return false;
+ }
+
+ bool parseSectionDirective(StringRef, SMLoc) {
+ // FIXME: .section currently no-op.
+ while (Lexer->isNot(AsmToken::EndOfStatement)) Parser->Lex();
+ return false;
+ }
+
+ // TODO: This function is almost the same as ELFAsmParser::ParseDirectiveSize
+ // so maybe could be shared somehow.
+ bool parseDirectiveSize(StringRef, SMLoc) {
+ StringRef Name;
+ if (Parser->parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+ auto Sym = getContext().getOrCreateSymbol(Name);
+ if (Lexer->isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+ const MCExpr *Expr;
+ if (Parser->parseExpression(Expr))
+ return true;
+ if (Lexer->isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+ Lex();
+ // MCWasmStreamer implements this.
+ getStreamer().emitELFSize(Sym, Expr);
+ return false;
+ }
+
+ bool parseDirectiveType(StringRef, SMLoc) {
+ // This could be the start of a function, check if followed by
+ // "label,@function"
+ if (!Lexer->is(AsmToken::Identifier))
+ return Error("Expected label after .type directive, got: ",
+ Lexer->getTok());
+ auto WasmSym = cast<MCSymbolWasm>(
+ getStreamer().getContext().getOrCreateSymbol(
+ Lexer->getTok().getString()));
+ Lex();
+ if (!(IsNext(AsmToken::Comma) && IsNext(AsmToken::At) &&
+ Lexer->is(AsmToken::Identifier)))
+ return Error("Expected label,@type declaration, got: ", Lexer->getTok());
+ auto TypeName = Lexer->getTok().getString();
+ if (TypeName == "function")
+ WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
+ else if (TypeName == "global")
+ WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
+ else
+ return Error("Unknown WASM symbol type: ", Lexer->getTok());
+ Lex();
+ return Expect(AsmToken::EndOfStatement, "EOL");
+ }
+};
+
+} // end anonymous namespace
+
+namespace llvm {
+
+MCAsmParserExtension *createWasmAsmParser() {
+ return new WasmAsmParser;
+}
+
+} // end namespace llvm
diff --git a/lib/MC/MCRegisterInfo.cpp b/lib/MC/MCRegisterInfo.cpp
index 8e47963b4418..5abae5379867 100644
--- a/lib/MC/MCRegisterInfo.cpp
+++ b/lib/MC/MCRegisterInfo.cpp
@@ -13,6 +13,7 @@
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <cassert>
@@ -127,6 +128,8 @@ int MCRegisterInfo::getCodeViewRegNum(unsigned RegNum) const {
report_fatal_error("target does not implement codeview register mapping");
const DenseMap<unsigned, int>::const_iterator I = L2CVRegs.find(RegNum);
if (I == L2CVRegs.end())
- report_fatal_error("unknown codeview register");
+ report_fatal_error("unknown codeview register " + (RegNum < getNumRegs()
+ ? getName(RegNum)
+ : Twine(RegNum)));
return I->second;
}
diff --git a/lib/MC/MCSection.cpp b/lib/MC/MCSection.cpp
index 97bc65387dd5..d4f11d10136a 100644
--- a/lib/MC/MCSection.cpp
+++ b/lib/MC/MCSection.cpp
@@ -23,7 +23,8 @@ using namespace llvm;
MCSection::MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin)
: Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false),
- IsRegistered(false), DummyFragment(this), Variant(V), Kind(K) {}
+ HasData(false), IsRegistered(false), DummyFragment(this), Variant(V),
+ Kind(K) {}
MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) {
if (!End)
diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp
index 4d77d05cc505..7ee1694ebbf7 100644
--- a/lib/MC/MCSectionELF.cpp
+++ b/lib/MC/MCSectionELF.cpp
@@ -116,6 +116,9 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
} else if (T.isARM() || T.isThumb()) {
if (Flags & ELF::SHF_ARM_PURECODE)
OS << 'y';
+ } else if (Arch == Triple::hexagon) {
+ if (Flags & ELF::SHF_HEX_GPREL)
+ OS << 's';
}
OS << '"';
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index 21a9c3604cfc..6a8471bc61b4 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/lib/MC/MCStreamer.cpp
@@ -72,6 +72,18 @@ void MCTargetStreamer::emitValue(const MCExpr *Value) {
Streamer.EmitRawText(OS.str());
}
+void MCTargetStreamer::emitRawBytes(StringRef Data) {
+ const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
+ const char *Directive = MAI->getData8bitsDirective();
+ for (const unsigned char C : Data.bytes()) {
+ SmallString<128> Str;
+ raw_svector_ostream OS(Str);
+
+ OS << Directive << (unsigned)C;
+ Streamer.EmitRawText(OS.str());
+ }
+}
+
void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {}
MCStreamer::MCStreamer(MCContext &Ctx)
@@ -209,6 +221,13 @@ void MCStreamer::emitDwarfFile0Directive(StringRef Directory,
Source);
}
+void MCStreamer::EmitCFIBKeyFrame() {
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
+ CurFrame->IsBKeyFrame = true;
+}
+
void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags,
unsigned Isa,
@@ -270,22 +289,28 @@ bool MCStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
void MCStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
unsigned Line, unsigned Column,
bool PrologueEnd, bool IsStmt,
- StringRef FileName, SMLoc Loc) {
+ StringRef FileName, SMLoc Loc) {}
+
+bool MCStreamer::checkCVLocSection(unsigned FuncId, unsigned FileNo,
+ SMLoc Loc) {
CodeViewContext &CVC = getContext().getCVContext();
- MCCVFunctionInfo *FI = CVC.getCVFunctionInfo(FunctionId);
- if (!FI)
- return getContext().reportError(
+ MCCVFunctionInfo *FI = CVC.getCVFunctionInfo(FuncId);
+ if (!FI) {
+ getContext().reportError(
Loc, "function id not introduced by .cv_func_id or .cv_inline_site_id");
+ return false;
+ }
// Track the section
if (FI->Section == nullptr)
FI->Section = getCurrentSectionOnly();
- else if (FI->Section != getCurrentSectionOnly())
- return getContext().reportError(
+ else if (FI->Section != getCurrentSectionOnly()) {
+ getContext().reportError(
Loc,
"all .cv_loc directives for a function must be in the same section");
-
- CVC.setCurrentCVLoc(FunctionId, FileNo, Line, Column, PrologueEnd, IsStmt);
+ return false;
+ }
+ return true;
}
void MCStreamer::EmitCVLinetableDirective(unsigned FunctionId,
@@ -341,10 +366,10 @@ void MCStreamer::EmitCFISections(bool EH, bool Debug) {
assert(EH || Debug);
}
-void MCStreamer::EmitCFIStartProc(bool IsSimple) {
+void MCStreamer::EmitCFIStartProc(bool IsSimple, SMLoc Loc) {
if (hasUnfinishedDwarfFrameInfo())
- getContext().reportError(
- SMLoc(), "starting new .cfi frame before finishing the previous one");
+ return getContext().reportError(
+ Loc, "starting new .cfi frame before finishing the previous one");
MCDwarfFrameInfo Frame;
Frame.IsSimple = IsSimple;
@@ -559,6 +584,15 @@ void MCStreamer::EmitCFIWindowSave() {
CurFrame->Instructions.push_back(Instruction);
}
+void MCStreamer::EmitCFINegateRAState() {
+ MCSymbol *Label = EmitCFILabel();
+ MCCFIInstruction Instruction = MCCFIInstruction::createNegateRAState(Label);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame)
+ return;
+ CurFrame->Instructions.push_back(Instruction);
+}
+
void MCStreamer::EmitCFIReturnColumn(int64_t Register) {
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
@@ -609,6 +643,17 @@ void MCStreamer::EmitWinCFIEndProc(SMLoc Loc) {
CurFrame->End = Label;
}
+void MCStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
+ WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
+ if (!CurFrame)
+ return;
+ if (CurFrame->ChainedParent)
+ getContext().reportError(Loc, "Not all chained regions terminated!");
+
+ MCSymbol *Label = EmitCFILabel();
+ CurFrame->FuncletOrFuncEnd = Label;
+}
+
void MCStreamer::EmitWinCFIStartChained(SMLoc Loc) {
WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
if (!CurFrame)
@@ -820,13 +865,11 @@ void MCStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
CurFrame->PrologEnd = Label;
}
-void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
-}
+void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {}
void MCStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {}
-void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
-}
+void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {}
void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {}
@@ -836,9 +879,12 @@ void MCStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {}
/// the specified string in the output .s file. This capability is
/// indicated by the hasRawTextSupport() predicate.
void MCStreamer::EmitRawTextImpl(StringRef String) {
- errs() << "EmitRawText called on an MCStreamer that doesn't support it, "
- " something must not be fully mc'ized\n";
- abort();
+ // This is not llvm_unreachable for the sake of out of tree backend
+ // developers who may not have assembly streamers and should serve as a
+ // reminder to not accidentally call EmitRawText in the absence of such.
+ report_fatal_error("EmitRawText called on an MCStreamer that doesn't support "
+ "it (target backend is likely missing an AsmStreamer "
+ "implementation)");
}
void MCStreamer::EmitRawText(const Twine &T) {
@@ -872,8 +918,9 @@ void MCStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
TS->emitAssignment(Symbol, Value);
}
-void MCTargetStreamer::prettyPrintAsm(MCInstPrinter &InstPrinter, raw_ostream &OS,
- const MCInst &Inst, const MCSubtargetInfo &STI) {
+void MCTargetStreamer::prettyPrintAsm(MCInstPrinter &InstPrinter,
+ raw_ostream &OS, const MCInst &Inst,
+ const MCSubtargetInfo &STI) {
InstPrinter.printInst(&Inst, OS, "", STI);
}
@@ -1016,7 +1063,8 @@ MCSymbol *MCStreamer::endSection(MCSection *Section) {
return Sym;
}
-void MCStreamer::EmitVersionForTarget(const Triple &Target) {
+void MCStreamer::EmitVersionForTarget(const Triple &Target,
+ const VersionTuple &SDKVersion) {
if (!Target.isOSBinFormatMachO() || !Target.isOSDarwin())
return;
// Do we even know the version?
@@ -1042,5 +1090,5 @@ void MCStreamer::EmitVersionForTarget(const Triple &Target) {
Target.getiOSVersion(Major, Minor, Update);
}
if (Major != 0)
- EmitVersionMin(VersionType, Major, Minor, Update);
+ EmitVersionMin(VersionType, Major, Minor, Update, SDKVersion);
}
diff --git a/lib/MC/MCWasmStreamer.cpp b/lib/MC/MCWasmStreamer.cpp
index 0e5932214047..d2a152058b90 100644
--- a/lib/MC/MCWasmStreamer.cpp
+++ b/lib/MC/MCWasmStreamer.cpp
@@ -61,7 +61,7 @@ void MCWasmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
void MCWasmStreamer::ChangeSection(MCSection *Section,
const MCExpr *Subsection) {
MCAssembler &Asm = getAssembler();
- auto *SectionWasm = static_cast<const MCSectionWasm *>(Section);
+ auto *SectionWasm = cast<MCSectionWasm>(Section);
const MCSymbol *Grp = SectionWasm->getGroup();
if (Grp)
Asm.registerSymbol(*Grp);
@@ -119,7 +119,6 @@ bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
break;
case MCSA_ELF_TypeObject:
- Symbol->setType(wasm::WASM_SYMBOL_TYPE_DATA);
break;
default:
diff --git a/lib/MC/MCWin64EH.cpp b/lib/MC/MCWin64EH.cpp
index 1407f25e6f2a..0724b109e1a1 100644
--- a/lib/MC/MCWin64EH.cpp
+++ b/lib/MC/MCWin64EH.cpp
@@ -11,6 +11,9 @@
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Win64EH.h"
@@ -23,6 +26,8 @@ static uint8_t CountOfUnwindCodes(std::vector<WinEH::Instruction> &Insns) {
uint8_t Count = 0;
for (const auto &I : Insns) {
switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
+ default:
+ llvm_unreachable("Unsupported unwind code");
case Win64EH::UOP_PushNonVol:
case Win64EH::UOP_AllocSmall:
case Win64EH::UOP_SetFPReg:
@@ -60,6 +65,8 @@ static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
uint16_t w;
b2 = (inst.Operation & 0x0F);
switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
+ default:
+ llvm_unreachable("Unsupported unwind code");
case Win64EH::UOP_PushNonVol:
EmitAbsDifference(streamer, inst.Label, begin);
b2 |= (inst.Register & 0x0F) << 4;
@@ -242,3 +249,348 @@ void llvm::Win64EH::UnwindEmitter::EmitUnwindInfo(
::EmitUnwindInfo(Streamer, info);
}
+static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
+ const MCSymbol *RHS) {
+ MCContext &Context = Streamer.getContext();
+ const MCExpr *Diff =
+ MCBinaryExpr::createSub(MCSymbolRefExpr::create(LHS, Context),
+ MCSymbolRefExpr::create(RHS, Context), Context);
+ MCObjectStreamer *OS = (MCObjectStreamer *)(&Streamer);
+ int64_t value;
+ Diff->evaluateAsAbsolute(value, OS->getAssembler());
+ return value;
+}
+
+static uint32_t
+ARM64CountOfUnwindCodes(const std::vector<WinEH::Instruction> &Insns) {
+ uint32_t Count = 0;
+ for (const auto &I : Insns) {
+ switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
+ default:
+ llvm_unreachable("Unsupported ARM64 unwind code");
+ case Win64EH::UOP_AllocSmall:
+ Count += 1;
+ break;
+ case Win64EH::UOP_AllocMedium:
+ Count += 2;
+ break;
+ case Win64EH::UOP_AllocLarge:
+ Count += 4;
+ break;
+ case Win64EH::UOP_SaveFPLRX:
+ Count += 1;
+ break;
+ case Win64EH::UOP_SaveFPLR:
+ Count += 1;
+ break;
+ case Win64EH::UOP_SaveReg:
+ Count += 2;
+ break;
+ case Win64EH::UOP_SaveRegP:
+ Count += 2;
+ break;
+ case Win64EH::UOP_SaveRegPX:
+ Count += 2;
+ break;
+ case Win64EH::UOP_SaveRegX:
+ Count += 2;
+ break;
+ case Win64EH::UOP_SaveFReg:
+ Count += 2;
+ break;
+ case Win64EH::UOP_SaveFRegP:
+ Count += 2;
+ break;
+ case Win64EH::UOP_SaveFRegX:
+ Count += 2;
+ break;
+ case Win64EH::UOP_SaveFRegPX:
+ Count += 2;
+ break;
+ case Win64EH::UOP_SetFP:
+ Count += 1;
+ break;
+ case Win64EH::UOP_AddFP:
+ Count += 2;
+ break;
+ case Win64EH::UOP_Nop:
+ Count += 1;
+ break;
+ case Win64EH::UOP_End:
+ Count += 1;
+ break;
+ }
+ }
+ return Count;
+}
+
+// Unwind opcode encodings and restrictions are documented at
+// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
+static void ARM64EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
+ WinEH::Instruction &inst) {
+ uint8_t b, reg;
+ switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
+ default:
+ llvm_unreachable("Unsupported ARM64 unwind code");
+ case Win64EH::UOP_AllocSmall:
+ b = (inst.Offset >> 4) & 0x1F;
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_AllocMedium: {
+ uint16_t hw = (inst.Offset >> 4) & 0x7FF;
+ b = 0xC0;
+ b |= (hw >> 8);
+ streamer.EmitIntValue(b, 1);
+ b = hw & 0xFF;
+ streamer.EmitIntValue(b, 1);
+ break;
+ }
+ case Win64EH::UOP_AllocLarge: {
+ uint32_t w;
+ b = 0xE0;
+ streamer.EmitIntValue(b, 1);
+ w = inst.Offset >> 4;
+ b = (w & 0x00FF0000) >> 16;
+ streamer.EmitIntValue(b, 1);
+ b = (w & 0x0000FF00) >> 8;
+ streamer.EmitIntValue(b, 1);
+ b = w & 0x000000FF;
+ streamer.EmitIntValue(b, 1);
+ break;
+ }
+ case Win64EH::UOP_SetFP:
+ b = 0xE1;
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_AddFP:
+ b = 0xE2;
+ streamer.EmitIntValue(b, 1);
+ b = (inst.Offset >> 3);
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_Nop:
+ b = 0xE3;
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_SaveFPLRX:
+ b = 0x80;
+ b |= ((inst.Offset - 1) >> 3) & 0x3F;
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_SaveFPLR:
+ b = 0x40;
+ b |= (inst.Offset >> 3) & 0x3F;
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_SaveReg:
+ assert(inst.Register >= 19 && "Saved reg must be >= 19");
+ reg = inst.Register - 19;
+ b = 0xD0 | ((reg & 0xC) >> 2);
+ streamer.EmitIntValue(b, 1);
+ b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_SaveRegX:
+ assert(inst.Register >= 19 && "Saved reg must be >= 19");
+ reg = inst.Register - 19;
+ b = 0xD4 | ((reg & 0x8) >> 3);
+ streamer.EmitIntValue(b, 1);
+ b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_SaveRegP:
+ assert(inst.Register >= 19 && "Saved registers must be >= 19");
+ reg = inst.Register - 19;
+ b = 0xC8 | ((reg & 0xC) >> 2);
+ streamer.EmitIntValue(b, 1);
+ b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_SaveRegPX:
+ assert(inst.Register >= 19 && "Saved registers must be >= 19");
+ reg = inst.Register - 19;
+ b = 0xCC | ((reg & 0xC) >> 2);
+ streamer.EmitIntValue(b, 1);
+ b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_SaveFReg:
+ assert(inst.Register >= 8 && "Saved dreg must be >= 8");
+ reg = inst.Register - 8;
+ b = 0xDC | ((reg & 0x4) >> 2);
+ streamer.EmitIntValue(b, 1);
+ b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_SaveFRegX:
+ assert(inst.Register >= 8 && "Saved dreg must be >= 8");
+ reg = inst.Register - 8;
+ b = 0xDE;
+ streamer.EmitIntValue(b, 1);
+ b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_SaveFRegP:
+ assert(inst.Register >= 8 && "Saved dregs must be >= 8");
+ reg = inst.Register - 8;
+ b = 0xD8 | ((reg & 0x4) >> 2);
+ streamer.EmitIntValue(b, 1);
+ b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_SaveFRegPX:
+ assert(inst.Register >= 8 && "Saved dregs must be >= 8");
+ reg = inst.Register - 8;
+ b = 0xDA | ((reg & 0x4) >> 2);
+ streamer.EmitIntValue(b, 1);
+ b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
+ streamer.EmitIntValue(b, 1);
+ break;
+ case Win64EH::UOP_End:
+ b = 0xE4;
+ streamer.EmitIntValue(b, 1);
+ break;
+ }
+}
+
+// Populate the .xdata section. The format of .xdata on ARM64 is documented at
+// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
+static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
+ // If this UNWIND_INFO already has a symbol, it's already been emitted.
+ if (info->Symbol)
+ return;
+
+ MCContext &context = streamer.getContext();
+ MCSymbol *Label = context.createTempSymbol();
+
+ streamer.EmitValueToAlignment(4);
+ streamer.EmitLabel(Label);
+ info->Symbol = Label;
+
+ uint32_t FuncLength = 0x0;
+ if (info->FuncletOrFuncEnd)
+ FuncLength = (uint32_t)GetAbsDifference(streamer, info->FuncletOrFuncEnd,
+ info->Begin);
+ FuncLength /= 4;
+ uint32_t PrologCodeBytes = ARM64CountOfUnwindCodes(info->Instructions);
+ uint32_t TotalCodeBytes = PrologCodeBytes;
+
+ // Process epilogs.
+ MapVector<MCSymbol *, uint32_t> EpilogInfo;
+ for (auto &I : info->EpilogMap) {
+ MCSymbol *EpilogStart = I.first;
+ auto &EpilogInstrs = I.second;
+ uint32_t CodeBytes = ARM64CountOfUnwindCodes(EpilogInstrs);
+ EpilogInfo[EpilogStart] = TotalCodeBytes;
+ TotalCodeBytes += CodeBytes;
+ }
+
+ // Code Words, Epilog count, E, X, Vers, Function Length
+ uint32_t row1 = 0x0;
+ uint32_t CodeWords = TotalCodeBytes / 4;
+ uint32_t CodeWordsMod = TotalCodeBytes % 4;
+ if (CodeWordsMod)
+ CodeWords++;
+ uint32_t EpilogCount = info->EpilogMap.size();
+ bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
+ if (!ExtensionWord) {
+ row1 |= (EpilogCount & 0x1F) << 22;
+ row1 |= (CodeWords & 0x1F) << 27;
+ }
+ // E is always 0 right now, TODO: packed epilog setup
+ if (info->HandlesExceptions) // X
+ row1 |= 1 << 20;
+ row1 |= FuncLength & 0x3FFFF;
+ streamer.EmitIntValue(row1, 4);
+
+ // Extended Code Words, Extended Epilog Count
+ if (ExtensionWord) {
+ // FIXME: We should be able to split unwind info into multiple sections.
+ // FIXME: We should share epilog codes across epilogs, where possible,
+ // which would make this issue show up less frequently.
+ if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
+ report_fatal_error("SEH unwind data splitting not yet implemented");
+ uint32_t row2 = 0x0;
+ row2 |= (CodeWords & 0xFF) << 16;
+ row2 |= (EpilogCount & 0xFFFF);
+ streamer.EmitIntValue(row2, 4);
+ }
+
+ // Epilog Start Index, Epilog Start Offset
+ for (auto &I : EpilogInfo) {
+ MCSymbol *EpilogStart = I.first;
+ uint32_t EpilogIndex = I.second;
+ uint32_t EpilogOffset =
+ (uint32_t)GetAbsDifference(streamer, EpilogStart, info->Begin);
+ if (EpilogOffset)
+ EpilogOffset /= 4;
+ uint32_t row3 = EpilogOffset;
+ row3 |= (EpilogIndex & 0x3FF) << 22;
+ streamer.EmitIntValue(row3, 4);
+ }
+
+ // Emit prolog unwind instructions (in reverse order).
+ uint8_t numInst = info->Instructions.size();
+ for (uint8_t c = 0; c < numInst; ++c) {
+ WinEH::Instruction inst = info->Instructions.back();
+ info->Instructions.pop_back();
+ ARM64EmitUnwindCode(streamer, info->Begin, inst);
+ }
+
+ // Emit epilog unwind instructions
+ for (auto &I : info->EpilogMap) {
+ auto &EpilogInstrs = I.second;
+ for (uint32_t i = 0; i < EpilogInstrs.size(); i++) {
+ WinEH::Instruction inst = EpilogInstrs[i];
+ ARM64EmitUnwindCode(streamer, info->Begin, inst);
+ }
+ }
+
+ int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
+ assert(BytesMod >= 0);
+ for (int i = 0; i < BytesMod; i++)
+ streamer.EmitIntValue(0xE3, 1);
+
+ if (info->HandlesExceptions)
+ streamer.EmitValue(
+ MCSymbolRefExpr::create(info->ExceptionHandler,
+ MCSymbolRefExpr::VK_COFF_IMGREL32, context),
+ 4);
+}
+
+static void ARM64EmitRuntimeFunction(MCStreamer &streamer,
+ const WinEH::FrameInfo *info) {
+ MCContext &context = streamer.getContext();
+
+ streamer.EmitValueToAlignment(4);
+ EmitSymbolRefWithOfs(streamer, info->Function, info->Begin);
+ streamer.EmitValue(MCSymbolRefExpr::create(info->Symbol,
+ MCSymbolRefExpr::VK_COFF_IMGREL32,
+ context),
+ 4);
+}
+
+void llvm::Win64EH::ARM64UnwindEmitter::Emit(MCStreamer &Streamer) const {
+ // Emit the unwind info structs first.
+ for (const auto &CFI : Streamer.getWinFrameInfos()) {
+ MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
+ Streamer.SwitchSection(XData);
+ ARM64EmitUnwindInfo(Streamer, CFI.get());
+ }
+
+ // Now emit RUNTIME_FUNCTION entries.
+ for (const auto &CFI : Streamer.getWinFrameInfos()) {
+ MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
+ Streamer.SwitchSection(PData);
+ ARM64EmitRuntimeFunction(Streamer, CFI.get());
+ }
+}
+
+void llvm::Win64EH::ARM64UnwindEmitter::EmitUnwindInfo(
+ MCStreamer &Streamer, WinEH::FrameInfo *info) const {
+ // Switch sections (the static function above is meant to be called from
+ // here and from Emit().
+ MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
+ Streamer.SwitchSection(XData);
+ ARM64EmitUnwindInfo(Streamer, info);
+}
diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp
index 2664528909af..2fa65658ccfa 100644
--- a/lib/MC/MachObjectWriter.cpp
+++ b/lib/MC/MachObjectWriter.cpp
@@ -597,8 +597,8 @@ void MachObjectWriter::computeSymbolTable(
}
// External and undefined symbols are required to be in lexicographic order.
- llvm::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
- llvm::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
+ llvm::sort(ExternalSymbolData);
+ llvm::sort(UndefinedSymbolData);
// Set the symbol indices.
Index = 0;
@@ -846,18 +846,27 @@ uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
// Write out the deployment target information, if it's available.
if (VersionInfo.Major != 0) {
- assert(VersionInfo.Update < 256 && "unencodable update target version");
- assert(VersionInfo.Minor < 256 && "unencodable minor target version");
- assert(VersionInfo.Major < 65536 && "unencodable major target version");
- uint32_t EncodedVersion = VersionInfo.Update | (VersionInfo.Minor << 8) |
- (VersionInfo.Major << 16);
+ auto EncodeVersion = [](VersionTuple V) -> uint32_t {
+ assert(!V.empty() && "empty version");
+ unsigned Update = V.getSubminor() ? *V.getSubminor() : 0;
+ unsigned Minor = V.getMinor() ? *V.getMinor() : 0;
+ assert(Update < 256 && "unencodable update target version");
+ assert(Minor < 256 && "unencodable minor target version");
+ assert(V.getMajor() < 65536 && "unencodable major target version");
+ return Update | (Minor << 8) | (V.getMajor() << 16);
+ };
+ uint32_t EncodedVersion = EncodeVersion(
+ VersionTuple(VersionInfo.Major, VersionInfo.Minor, VersionInfo.Update));
+ uint32_t SDKVersion = !VersionInfo.SDKVersion.empty()
+ ? EncodeVersion(VersionInfo.SDKVersion)
+ : 0;
if (VersionInfo.EmitBuildVersion) {
// FIXME: Currently empty tools. Add clang version in the future.
W.write<uint32_t>(MachO::LC_BUILD_VERSION);
W.write<uint32_t>(sizeof(MachO::build_version_command));
W.write<uint32_t>(VersionInfo.TypeOrPlatform.Platform);
W.write<uint32_t>(EncodedVersion);
- W.write<uint32_t>(0); // SDK version.
+ W.write<uint32_t>(SDKVersion);
W.write<uint32_t>(0); // Empty tools list.
} else {
MachO::LoadCommandType LCType
@@ -865,7 +874,7 @@ uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
W.write<uint32_t>(LCType);
W.write<uint32_t>(sizeof(MachO::version_min_command));
W.write<uint32_t>(EncodedVersion);
- W.write<uint32_t>(0); // reserved.
+ W.write<uint32_t>(SDKVersion);
}
}
diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp
index 5a979d36e81b..0cca3757be90 100644
--- a/lib/MC/WasmObjectWriter.cpp
+++ b/lib/MC/WasmObjectWriter.cpp
@@ -56,9 +56,10 @@ struct SectionBookkeeping {
uint32_t Index;
};
-// The signature of a wasm function, in a struct capable of being used as a
-// DenseMap key.
-struct WasmFunctionType {
+// The signature of a wasm function or event, in a struct capable of being used
+// as a DenseMap key.
+// TODO: Consider using wasm::WasmSignature directly instead.
+struct WasmSignature {
// Support empty and tombstone instances, needed by DenseMap.
enum { Plain, Empty, Tombstone } State;
@@ -68,36 +69,35 @@ struct WasmFunctionType {
// The parameter types of the function.
SmallVector<wasm::ValType, 4> Params;
- WasmFunctionType() : State(Plain) {}
+ WasmSignature() : State(Plain) {}
- bool operator==(const WasmFunctionType &Other) const {
+ bool operator==(const WasmSignature &Other) const {
return State == Other.State && Returns == Other.Returns &&
Params == Other.Params;
}
};
-// Traits for using WasmFunctionType in a DenseMap.
-struct WasmFunctionTypeDenseMapInfo {
- static WasmFunctionType getEmptyKey() {
- WasmFunctionType FuncTy;
- FuncTy.State = WasmFunctionType::Empty;
- return FuncTy;
+// Traits for using WasmSignature in a DenseMap.
+struct WasmSignatureDenseMapInfo {
+ static WasmSignature getEmptyKey() {
+ WasmSignature Sig;
+ Sig.State = WasmSignature::Empty;
+ return Sig;
}
- static WasmFunctionType getTombstoneKey() {
- WasmFunctionType FuncTy;
- FuncTy.State = WasmFunctionType::Tombstone;
- return FuncTy;
+ static WasmSignature getTombstoneKey() {
+ WasmSignature Sig;
+ Sig.State = WasmSignature::Tombstone;
+ return Sig;
}
- static unsigned getHashValue(const WasmFunctionType &FuncTy) {
- uintptr_t Value = FuncTy.State;
- for (wasm::ValType Ret : FuncTy.Returns)
- Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Ret));
- for (wasm::ValType Param : FuncTy.Params)
- Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Param));
+ static unsigned getHashValue(const WasmSignature &Sig) {
+ uintptr_t Value = Sig.State;
+ for (wasm::ValType Ret : Sig.Returns)
+ Value += DenseMapInfo<uint32_t>::getHashValue(uint32_t(Ret));
+ for (wasm::ValType Param : Sig.Params)
+ Value += DenseMapInfo<uint32_t>::getHashValue(uint32_t(Param));
return Value;
}
- static bool isEqual(const WasmFunctionType &LHS,
- const WasmFunctionType &RHS) {
+ static bool isEqual(const WasmSignature &LHS, const WasmSignature &RHS) {
return LHS == RHS;
}
};
@@ -117,7 +117,7 @@ struct WasmDataSegment {
// A wasm function to be written into the function section.
struct WasmFunction {
- int32_t Type;
+ uint32_t SigIndex;
const MCSymbolWasm *Sym;
};
@@ -137,11 +137,11 @@ struct WasmComdatEntry {
// Information about a single relocation.
struct WasmRelocationEntry {
- uint64_t Offset; // Where is the relocation.
- const MCSymbolWasm *Symbol; // The symbol to relocate with.
- int64_t Addend; // A value to add to the symbol.
- unsigned Type; // The type of the relocation.
- const MCSectionWasm *FixupSection;// The section the relocation is targeting.
+ uint64_t Offset; // Where is the relocation.
+ const MCSymbolWasm *Symbol; // The symbol to relocate with.
+ int64_t Addend; // A value to add to the symbol.
+ unsigned Type; // The type of the relocation.
+ const MCSectionWasm *FixupSection; // The section the relocation is targeting.
WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
int64_t Addend, unsigned Type,
@@ -163,8 +163,8 @@ struct WasmRelocationEntry {
}
void print(raw_ostream &Out) const {
- Out << wasm::relocTypetoString(Type)
- << " Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend
+ Out << wasm::relocTypetoString(Type) << " Off=" << Offset
+ << ", Sym=" << *Symbol << ", Addend=" << Addend
<< ", FixupSection=" << FixupSection->getSectionName();
}
@@ -215,7 +215,8 @@ class WasmObjectWriter : public MCObjectWriter {
// Maps function symbols to the table element index space. Used
// for TABLE_INDEX relocation types (i.e. address taken functions).
DenseMap<const MCSymbolWasm *, uint32_t> TableIndices;
- // Maps function/global symbols to the function/global/section index space.
+ // Maps function/global symbols to the function/global/event/section index
+ // space.
DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices;
// Maps data symbols to the Wasm segment and offset/size with the segment.
DenseMap<const MCSymbolWasm *, wasm::WasmDataReference> DataLocations;
@@ -230,13 +231,13 @@ class WasmObjectWriter : public MCObjectWriter {
// Map from section to defining function symbol.
DenseMap<const MCSection *, const MCSymbol *> SectionFunctions;
- DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo>
- FunctionTypeIndices;
- SmallVector<WasmFunctionType, 4> FunctionTypes;
+ DenseMap<WasmSignature, uint32_t, WasmSignatureDenseMapInfo> SignatureIndices;
+ SmallVector<WasmSignature, 4> Signatures;
SmallVector<WasmGlobal, 4> Globals;
SmallVector<WasmDataSegment, 4> DataSegments;
unsigned NumFunctionImports = 0;
unsigned NumGlobalImports = 0;
+ unsigned NumEventImports = 0;
uint32_t SectionCount = 0;
// TargetObjectWriter wrappers.
@@ -265,8 +266,8 @@ private:
TableIndices.clear();
DataLocations.clear();
CustomSectionsRelocations.clear();
- FunctionTypeIndices.clear();
- FunctionTypes.clear();
+ SignatureIndices.clear();
+ Signatures.clear();
Globals.clear();
DataSegments.clear();
SectionFunctions.clear();
@@ -291,11 +292,9 @@ private:
W.OS << Str;
}
- void writeValueType(wasm::ValType Ty) {
- W.OS << static_cast<char>(Ty);
- }
+ void writeValueType(wasm::ValType Ty) { W.OS << static_cast<char>(Ty); }
- void writeTypeSection(ArrayRef<WasmFunctionType> FunctionTypes);
+ void writeTypeSection(ArrayRef<WasmSignature> Signatures);
void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint32_t DataSize,
uint32_t NumElements);
void writeFunctionSection(ArrayRef<WasmFunction> Functions);
@@ -305,8 +304,9 @@ private:
void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
ArrayRef<WasmFunction> Functions);
void writeDataSection();
+ void writeEventSection(ArrayRef<wasm::WasmEventType> Events);
void writeRelocSection(uint32_t SectionIndex, StringRef Name,
- ArrayRef<WasmRelocationEntry> Relocations);
+ std::vector<WasmRelocationEntry> &Relocations);
void writeLinkingMetaDataSection(
ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
@@ -323,7 +323,9 @@ private:
uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
uint32_t getFunctionType(const MCSymbolWasm &Symbol);
- uint32_t registerFunctionType(const MCSymbolWasm &Symbol);
+ uint32_t getEventType(const MCSymbolWasm &Symbol);
+ void registerFunctionType(const MCSymbolWasm &Symbol);
+ void registerEventType(const MCSymbolWasm &Symbol);
};
} // end anonymous namespace
@@ -529,8 +531,8 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
// Write X as an (unsigned) LEB value at offset Offset in Stream, padded
// to allow patching.
-static void
-WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
+static void WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X,
+ uint64_t Offset) {
uint8_t Buffer[5];
unsigned SizeLen = encodeULEB128(X, Buffer, 5);
assert(SizeLen == 5);
@@ -539,8 +541,8 @@ WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
// Write X as an signed LEB value at offset Offset in Stream, padded
// to allow patching.
-static void
-WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) {
+static void WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X,
+ uint64_t Offset) {
uint8_t Buffer[5];
unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
assert(SizeLen == 5);
@@ -554,7 +556,7 @@ 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) {
+static const MCSymbolWasm *ResolveSymbol(const MCSymbolWasm &Symbol) {
if (Symbol.isVariable()) {
const MCExpr *Expr = Symbol.getVariableValue();
auto *Inner = cast<MCSymbolRefExpr>(Expr);
@@ -582,7 +584,8 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
return getRelocationIndexValue(RelEntry);
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
- // Provisional value is function/global Wasm index
+ case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
+ // Provisional value is function/global/event Wasm index
if (!WasmIndices.count(RelEntry.Symbol))
report_fatal_error("symbol not found in wasm index space: " +
RelEntry.Symbol->getName());
@@ -626,10 +629,9 @@ static void addData(SmallVectorImpl<char> &DataBytes,
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());
+ 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)) {
int64_t NumValues;
@@ -637,10 +639,12 @@ static void addData(SmallVectorImpl<char> &DataBytes,
llvm_unreachable("The fill should be an assembler constant");
DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues,
Fill->getValue());
+ } else if (auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) {
+ const SmallVectorImpl<char> &Contents = LEB->getContents();
+ DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
} else {
const auto &DataFrag = cast<MCDataFragment>(Frag);
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
-
DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
}
}
@@ -678,6 +682,7 @@ void WasmObjectWriter::applyRelocations(
case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
WritePatchableLEB(Stream, Value, Offset);
break;
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
@@ -696,23 +701,22 @@ void WasmObjectWriter::applyRelocations(
}
}
-void WasmObjectWriter::writeTypeSection(
- ArrayRef<WasmFunctionType> FunctionTypes) {
- if (FunctionTypes.empty())
+void WasmObjectWriter::writeTypeSection(ArrayRef<WasmSignature> Signatures) {
+ if (Signatures.empty())
return;
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_TYPE);
- encodeULEB128(FunctionTypes.size(), W.OS);
+ encodeULEB128(Signatures.size(), W.OS);
- for (const WasmFunctionType &FuncTy : FunctionTypes) {
+ for (const WasmSignature &Sig : Signatures) {
W.OS << char(wasm::WASM_TYPE_FUNC);
- encodeULEB128(FuncTy.Params.size(), W.OS);
- for (wasm::ValType Ty : FuncTy.Params)
+ encodeULEB128(Sig.Params.size(), W.OS);
+ for (wasm::ValType Ty : Sig.Params)
writeValueType(Ty);
- encodeULEB128(FuncTy.Returns.size(), W.OS);
- for (wasm::ValType Ty : FuncTy.Returns)
+ encodeULEB128(Sig.Returns.size(), W.OS);
+ for (wasm::ValType Ty : Sig.Returns)
writeValueType(Ty);
}
@@ -745,14 +749,18 @@ void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
W.OS << char(Import.Global.Mutable ? 1 : 0);
break;
case wasm::WASM_EXTERNAL_MEMORY:
- encodeULEB128(0, W.OS); // flags
+ encodeULEB128(0, W.OS); // flags
encodeULEB128(NumPages, W.OS); // initial
break;
case wasm::WASM_EXTERNAL_TABLE:
W.OS << char(Import.Table.ElemType);
- encodeULEB128(0, W.OS); // flags
+ encodeULEB128(0, W.OS); // flags
encodeULEB128(NumElements, W.OS); // initial
break;
+ case wasm::WASM_EXTERNAL_EVENT:
+ encodeULEB128(Import.Event.Attribute, W.OS);
+ encodeULEB128(Import.Event.SigIndex, W.OS);
+ break;
default:
llvm_unreachable("unsupported import kind");
}
@@ -770,7 +778,7 @@ void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
encodeULEB128(Functions.size(), W.OS);
for (const WasmFunction &Func : Functions)
- encodeULEB128(Func.Type, W.OS);
+ encodeULEB128(Func.SigIndex, W.OS);
endSection(Section);
}
@@ -795,6 +803,22 @@ void WasmObjectWriter::writeGlobalSection() {
endSection(Section);
}
+void WasmObjectWriter::writeEventSection(ArrayRef<wasm::WasmEventType> Events) {
+ if (Events.empty())
+ return;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_EVENT);
+
+ encodeULEB128(Events.size(), W.OS);
+ for (const wasm::WasmEventType &Event : Events) {
+ encodeULEB128(Event.Attribute, W.OS);
+ encodeULEB128(Event.SigIndex, W.OS);
+ }
+
+ endSection(Section);
+}
+
void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) {
if (Exports.empty())
return;
@@ -892,21 +916,33 @@ void WasmObjectWriter::writeDataSection() {
void WasmObjectWriter::writeRelocSection(
uint32_t SectionIndex, StringRef Name,
- ArrayRef<WasmRelocationEntry> Relocations) {
+ std::vector<WasmRelocationEntry> &Relocs) {
// See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
// for descriptions of the reloc sections.
- if (Relocations.empty())
+ if (Relocs.empty())
return;
+ // First, ensure the relocations are sorted in offset order. In general they
+ // should already be sorted since `recordRelocation` is called in offset
+ // order, but for the code section we combine many MC sections into single
+ // wasm section, and this order is determined by the order of Asm.Symbols()
+ // not the sections order.
+ std::stable_sort(
+ Relocs.begin(), Relocs.end(),
+ [](const WasmRelocationEntry &A, const WasmRelocationEntry &B) {
+ return (A.Offset + A.FixupSection->getSectionOffset()) <
+ (B.Offset + B.FixupSection->getSectionOffset());
+ });
+
SectionBookkeeping Section;
startCustomSection(Section, std::string("reloc.") + Name.str());
encodeULEB128(SectionIndex, W.OS);
- encodeULEB128(Relocations.size(), W.OS);
- for (const WasmRelocationEntry& RelEntry : Relocations) {
- uint64_t Offset = RelEntry.Offset +
- RelEntry.FixupSection->getSectionOffset();
+ encodeULEB128(Relocs.size(), W.OS);
+ for (const WasmRelocationEntry &RelEntry : Relocs) {
+ uint64_t Offset =
+ RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
uint32_t Index = getRelocationIndexValue(RelEntry);
W.OS << char(RelEntry.Type);
@@ -944,6 +980,7 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
switch (Sym.Kind) {
case wasm::WASM_SYMBOL_TYPE_FUNCTION:
case wasm::WASM_SYMBOL_TYPE_GLOBAL:
+ case wasm::WASM_SYMBOL_TYPE_EVENT:
encodeULEB128(Sym.ElementIndex, W.OS);
if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
writeString(Sym.Name);
@@ -984,7 +1021,7 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
startSection(SubSection, wasm::WASM_INIT_FUNCS);
encodeULEB128(InitFuncs.size(), W.OS);
for (auto &StartFunc : InitFuncs) {
- encodeULEB128(StartFunc.first, W.OS); // priority
+ encodeULEB128(StartFunc.first, W.OS); // priority
encodeULEB128(StartFunc.second, W.OS); // function index
}
endSection(SubSection);
@@ -1029,30 +1066,57 @@ void WasmObjectWriter::writeCustomSections(const MCAssembler &Asm,
}
}
-uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm& Symbol) {
+uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {
assert(Symbol.isFunction());
assert(TypeIndices.count(&Symbol));
return TypeIndices[&Symbol];
}
-uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm& Symbol) {
+uint32_t WasmObjectWriter::getEventType(const MCSymbolWasm &Symbol) {
+ assert(Symbol.isEvent());
+ assert(TypeIndices.count(&Symbol));
+ return TypeIndices[&Symbol];
+}
+
+void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
assert(Symbol.isFunction());
- WasmFunctionType F;
- const MCSymbolWasm* ResolvedSym = ResolveSymbol(Symbol);
- F.Returns = ResolvedSym->getReturns();
- F.Params = ResolvedSym->getParams();
+ WasmSignature S;
+ const MCSymbolWasm *ResolvedSym = ResolveSymbol(Symbol);
+ if (auto *Sig = ResolvedSym->getSignature()) {
+ S.Returns = Sig->Returns;
+ S.Params = Sig->Params;
+ }
- auto Pair =
- FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
+ auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
if (Pair.second)
- FunctionTypes.push_back(F);
+ Signatures.push_back(S);
TypeIndices[&Symbol] = Pair.first->second;
LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol
<< " new:" << Pair.second << "\n");
LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
- return Pair.first->second;
+}
+
+void WasmObjectWriter::registerEventType(const MCSymbolWasm &Symbol) {
+ assert(Symbol.isEvent());
+
+ // TODO Currently we don't generate imported exceptions, but if we do, we
+ // should have a way of infering types of imported exceptions.
+ WasmSignature S;
+ if (auto *Sig = Symbol.getSignature()) {
+ S.Returns = Sig->Returns;
+ S.Params = Sig->Params;
+ }
+
+ auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
+ if (Pair.second)
+ Signatures.push_back(S);
+ TypeIndices[&Symbol] = Pair.first->second;
+
+ LLVM_DEBUG(dbgs() << "registerEventType: " << Symbol << " new:" << Pair.second
+ << "\n");
+ LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
}
static bool isInSymtab(const MCSymbolWasm &Sym) {
@@ -1086,6 +1150,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
SmallVector<uint32_t, 4> TableElems;
SmallVector<wasm::WasmImport, 4> Imports;
SmallVector<wasm::WasmExport, 4> Exports;
+ SmallVector<wasm::WasmEventType, 1> Events;
SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
@@ -1111,10 +1176,10 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
TableImport.Module = TableSym->getModuleName();
TableImport.Field = TableSym->getName();
TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
- TableImport.Table.ElemType = wasm::WASM_TYPE_ANYFUNC;
+ TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF;
Imports.push_back(TableImport);
- // Populate FunctionTypeIndices, and Imports and WasmIndices for undefined
+ // Populate SignatureIndices, and Imports and WasmIndices for undefined
// symbols. This must be done before populating WasmIndices for defined
// symbols.
for (const MCSymbol &S : Asm.symbols()) {
@@ -1125,6 +1190,9 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
if (WS.isFunction())
registerFunctionType(WS);
+ if (WS.isEvent())
+ registerEventType(WS);
+
if (WS.isTemporary())
continue;
@@ -1149,6 +1217,18 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
Import.Global = WS.getGlobalType();
Imports.push_back(Import);
WasmIndices[&WS] = NumGlobalImports++;
+ } else if (WS.isEvent()) {
+ if (WS.isWeak())
+ report_fatal_error("undefined event symbol cannot be weak");
+
+ wasm::WasmImport Import;
+ Import.Module = WS.getModuleName();
+ Import.Field = WS.getName();
+ Import.Kind = wasm::WASM_EXTERNAL_EVENT;
+ Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
+ Import.Event.SigIndex = getEventType(WS);
+ Imports.push_back(Import);
+ WasmIndices[&WS] = NumEventImports++;
}
}
}
@@ -1176,7 +1256,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
Segment.Offset = DataSize;
Segment.Section = &Section;
addData(Segment.Data, Section);
- Segment.Alignment = Section.getAlignment();
+ Segment.Alignment = Log2_32(Section.getAlignment());
Segment.Flags = 0;
DataSize += Segment.Data.size();
Section.setSegmentIndex(SegmentIndex);
@@ -1195,7 +1275,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
if (Name.startswith(".custom_section."))
Name = Name.substr(strlen(".custom_section."));
- MCSymbol* Begin = Sec.getBeginSymbol();
+ MCSymbol *Begin = Sec.getBeginSymbol();
if (Begin) {
WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
if (SectionName != Begin->getName())
@@ -1240,7 +1320,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
// A definition. Write out the function body.
Index = NumFunctionImports + Functions.size();
WasmFunction Func;
- Func.Type = getFunctionType(WS);
+ Func.SigIndex = getFunctionType(WS);
Func.Sym = &WS;
WasmIndices[&WS] = Index;
Functions.push_back(Func);
@@ -1256,6 +1336,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
}
LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n");
+
} else if (WS.isData()) {
if (WS.isTemporary() && !WS.getSize())
continue;
@@ -1285,6 +1366,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
static_cast<uint32_t>(Size)};
DataLocations[&WS] = Ref;
LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n");
+
} else if (WS.isGlobal()) {
// A "true" Wasm global (currently just __stack_pointer)
if (WS.isDefined())
@@ -1293,6 +1375,24 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
// An import; the index was assigned above
LLVM_DEBUG(dbgs() << " -> global index: "
<< WasmIndices.find(&WS)->second << "\n");
+
+ } else if (WS.isEvent()) {
+ // C++ exception symbol (__cpp_exception)
+ unsigned Index;
+ if (WS.isDefined()) {
+ Index = NumEventImports + Events.size();
+ wasm::WasmEventType Event;
+ Event.SigIndex = getEventType(WS);
+ Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
+ WasmIndices[&WS] = Index;
+ Events.push_back(Event);
+ } else {
+ // An import; the index was assigned above.
+ Index = WasmIndices.find(&WS)->second;
+ }
+ LLVM_DEBUG(dbgs() << " -> event index: " << WasmIndices.find(&WS)->second
+ << "\n");
+
} else {
assert(WS.isSection());
}
@@ -1326,7 +1426,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
DataLocations[&WS] = Ref;
LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n");
} else {
- report_fatal_error("don't yet support global aliases");
+ report_fatal_error("don't yet support global/event aliases");
}
}
@@ -1424,7 +1524,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
unsigned PrefixLength = strlen(".init_array");
if (WS.getSectionName().size() > PrefixLength) {
if (WS.getSectionName()[PrefixLength] != '.')
- report_fatal_error(".init_array section priority should start with '.'");
+ report_fatal_error(
+ ".init_array section priority should start with '.'");
if (WS.getSectionName()
.substr(PrefixLength + 1)
.getAsInteger(10, Priority))
@@ -1432,14 +1533,16 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
}
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();
+ 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));
+ assert(Fixup.getKind() ==
+ MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
const MCExpr *Expr = Fixup.getValue();
auto *Sym = dyn_cast<MCSymbolRefExpr>(Expr);
if (!Sym)
@@ -1456,12 +1559,13 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
// Write out the Wasm header.
writeHeader(Asm);
- writeTypeSection(FunctionTypes);
+ writeTypeSection(Signatures);
writeImportSection(Imports, DataSize, TableElems.size());
writeFunctionSection(Functions);
// Skip the "table" section; we import the table instead.
// Skip the "memory" section; we import the memory instead.
writeGlobalSection();
+ writeEventSection(Events);
writeExportSection(Exports);
writeElemSection(TableElems);
writeCodeSection(Asm, Layout, Functions);
diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp
index 9ffecd99df68..b774852eabe6 100644
--- a/lib/MC/WinCOFFObjectWriter.cpp
+++ b/lib/MC/WinCOFFObjectWriter.cpp
@@ -36,6 +36,7 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/JamCRC.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -58,8 +59,6 @@ namespace {
using name = SmallString<COFF::NameSize>;
enum AuxiliaryType {
- ATFunctionDefinition,
- ATbfAndefSymbol,
ATWeakExternal,
ATFile,
ATSectionDefinition
@@ -147,6 +146,10 @@ public:
bool UseBigObj;
+ bool EmitAddrsigSection = false;
+ MCSectionCOFF *AddrsigSection;
+ std::vector<const MCSymbol *> AddrsigSyms;
+
WinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS);
@@ -206,6 +209,11 @@ public:
void assignSectionNumbers();
void assignFileOffsets(MCAssembler &Asm, const MCAsmLayout &Layout);
+ void emitAddrsigSection() override { EmitAddrsigSection = true; }
+ void addAddrsigSymbol(const MCSymbol *Sym) override {
+ AddrsigSyms.push_back(Sym);
+ }
+
uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
};
@@ -515,24 +523,6 @@ void WinCOFFObjectWriter::WriteAuxiliarySymbols(
const COFFSymbol::AuxiliarySymbols &S) {
for (const AuxSymbol &i : S) {
switch (i.AuxType) {
- case ATFunctionDefinition:
- W.write<uint32_t>(i.Aux.FunctionDefinition.TagIndex);
- W.write<uint32_t>(i.Aux.FunctionDefinition.TotalSize);
- W.write<uint32_t>(i.Aux.FunctionDefinition.PointerToLinenumber);
- W.write<uint32_t>(i.Aux.FunctionDefinition.PointerToNextFunction);
- W.OS.write_zeros(sizeof(i.Aux.FunctionDefinition.unused));
- if (UseBigObj)
- W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
- break;
- case ATbfAndefSymbol:
- W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused1));
- W.write<uint16_t>(i.Aux.bfAndefSymbol.Linenumber);
- W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused2));
- W.write<uint32_t>(i.Aux.bfAndefSymbol.PointerToNextFunction);
- W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused3));
- if (UseBigObj)
- W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
- break;
case ATWeakExternal:
W.write<uint32_t>(i.Aux.WeakExternal.TagIndex);
W.write<uint32_t>(i.Aux.WeakExternal.Characteristics);
@@ -568,10 +558,9 @@ void WinCOFFObjectWriter::writeSectionHeaders() {
std::vector<COFFSection *> Arr;
for (auto &Section : Sections)
Arr.push_back(Section.get());
- llvm::sort(Arr.begin(), Arr.end(),
- [](const COFFSection *A, const COFFSection *B) {
- return A->Number < B->Number;
- });
+ llvm::sort(Arr, [](const COFFSection *A, const COFFSection *B) {
+ return A->Number < B->Number;
+ });
for (auto &Section : Arr) {
if (Section->Number == -1)
@@ -630,14 +619,9 @@ void WinCOFFObjectWriter::writeSection(MCAssembler &Asm,
// Write the section contents.
if (Sec.Header.PointerToRawData != 0) {
- assert(W.OS.tell() <= Sec.Header.PointerToRawData &&
+ assert(W.OS.tell() == Sec.Header.PointerToRawData &&
"Section::PointerToRawData is insane!");
- unsigned PaddingSize = Sec.Header.PointerToRawData - W.OS.tell();
- assert(PaddingSize < 4 &&
- "Should only need at most three bytes of padding!");
- W.OS.write_zeros(PaddingSize);
-
uint32_t CRC = writeSectionContents(Asm, Layout, MCSec);
// Update the section definition auxiliary symbol to record the CRC.
@@ -677,6 +661,13 @@ void WinCOFFObjectWriter::writeSection(MCAssembler &Asm,
void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) {
+ if (EmitAddrsigSection) {
+ AddrsigSection = Asm.getContext().getCOFFSection(
+ ".llvm_addrsig", COFF::IMAGE_SCN_LNK_REMOVE,
+ SectionKind::getMetadata());
+ Asm.registerSection(*AddrsigSection);
+ }
+
// "Define" each section & symbol. This creates section & symbol
// entries in the staging area.
for (const auto &Section : Asm)
@@ -915,10 +906,7 @@ void WinCOFFObjectWriter::assignFileOffsets(MCAssembler &Asm,
Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(&Section);
if (IsPhysicalSection(Sec)) {
- // Align the section data to a four byte boundary.
- Offset = alignTo(Offset, 4);
Sec->Header.PointerToRawData = Offset;
-
Offset += Sec->Header.SizeOfRawData;
}
@@ -1020,22 +1008,47 @@ uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
continue;
const MCSectionCOFF &MCSec = *Section->MCSection;
+ const MCSymbol *AssocMCSym = MCSec.getCOMDATSymbol();
+ assert(AssocMCSym);
+
+ // It's an error to try to associate with an undefined symbol or a symbol
+ // without a section.
+ if (!AssocMCSym->isInSection()) {
+ Asm.getContext().reportError(
+ SMLoc(), Twine("cannot make section ") + MCSec.getSectionName() +
+ Twine(" associative with sectionless symbol ") +
+ AssocMCSym->getName());
+ continue;
+ }
- const MCSymbol *COMDAT = MCSec.getCOMDATSymbol();
- assert(COMDAT);
- COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(COMDAT);
- assert(COMDATSymbol);
- COFFSection *Assoc = COMDATSymbol->Section;
- if (!Assoc)
- report_fatal_error(
- Twine("Missing associated COMDAT section for section ") +
- MCSec.getSectionName());
+ const auto *AssocMCSec = cast<MCSectionCOFF>(&AssocMCSym->getSection());
+ assert(SectionMap.count(AssocMCSec));
+ COFFSection *AssocSec = SectionMap[AssocMCSec];
// Skip this section if the associated section is unused.
- if (Assoc->Number == -1)
+ if (AssocSec->Number == -1)
continue;
- Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Assoc->Number;
+ Section->Symbol->Aux[0].Aux.SectionDefinition.Number = AssocSec->Number;
+ }
+
+ // Create the contents of the .llvm_addrsig section.
+ if (EmitAddrsigSection) {
+ auto Frag = new MCDataFragment(AddrsigSection);
+ Frag->setLayoutOrder(0);
+ raw_svector_ostream OS(Frag->getContents());
+ for (const MCSymbol *S : AddrsigSyms) {
+ if (!S->isTemporary()) {
+ encodeULEB128(S->getIndex(), OS);
+ continue;
+ }
+
+ MCSection *TargetSection = &S->getSection();
+ assert(SectionMap.find(TargetSection) != SectionMap.end() &&
+ "Section must already have been defined in "
+ "executePostLayoutBinding!");
+ encodeULEB128(SectionMap[TargetSection]->Symbol->getIndex(), OS);
+ }
}
assignFileOffsets(Asm, Layout);