aboutsummaryrefslogtreecommitdiff
path: root/lib/MC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:17:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:17:04 +0000
commitb915e9e0fc85ba6f398b3fab0db6a81a8913af94 (patch)
tree98b8f811c7aff2547cab8642daf372d6c59502fb /lib/MC
parent6421cca32f69ac849537a3cff78c352195e99f1b (diff)
downloadsrc-b915e9e0fc85ba6f398b3fab0db6a81a8913af94.tar.gz
src-b915e9e0fc85ba6f398b3fab0db6a81a8913af94.zip
Vendor import of llvm trunk r290819:vendor/llvm/llvm-trunk-r290819
Notes
Notes: svn path=/vendor/llvm/dist/; revision=311116 svn path=/vendor/llvm/llvm-trunk-r290819/; revision=311117; tag=vendor/llvm/llvm-trunk-r290819
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/ConstantPools.cpp16
-rw-r--r--lib/MC/ELFObjectWriter.cpp34
-rw-r--r--lib/MC/MCAsmBackend.cpp4
-rw-r--r--lib/MC/MCAsmInfo.cpp1
-rw-r--r--lib/MC/MCAsmInfoDarwin.cpp1
-rw-r--r--lib/MC/MCAsmStreamer.cpp144
-rw-r--r--lib/MC/MCAssembler.cpp34
-rw-r--r--lib/MC/MCCodeView.cpp220
-rw-r--r--lib/MC/MCContext.cpp27
-rw-r--r--lib/MC/MCDisassembler/Disassembler.cpp31
-rw-r--r--lib/MC/MCDwarf.cpp5
-rw-r--r--lib/MC/MCELFStreamer.cpp4
-rw-r--r--lib/MC/MCExpr.cpp10
-rw-r--r--lib/MC/MCFragment.cpp11
-rw-r--r--lib/MC/MCInst.cpp4
-rw-r--r--lib/MC/MCLabel.cpp2
-rw-r--r--lib/MC/MCObjectFileInfo.cpp49
-rw-r--r--lib/MC/MCObjectStreamer.cpp74
-rw-r--r--lib/MC/MCParser/AsmLexer.cpp159
-rw-r--r--lib/MC/MCParser/AsmParser.cpp1556
-rw-r--r--lib/MC/MCParser/COFFAsmParser.cpp56
-rw-r--r--lib/MC/MCParser/DarwinAsmParser.cpp13
-rw-r--r--lib/MC/MCParser/ELFAsmParser.cpp7
-rw-r--r--lib/MC/MCParser/MCAsmLexer.cpp4
-rw-r--r--lib/MC/MCParser/MCAsmParser.cpp104
-rw-r--r--lib/MC/MCRegisterInfo.cpp6
-rw-r--r--lib/MC/MCSection.cpp10
-rw-r--r--lib/MC/MCSectionCOFF.cpp3
-rw-r--r--lib/MC/MCSectionELF.cpp2
-rw-r--r--lib/MC/MCSectionMachO.cpp30
-rw-r--r--lib/MC/MCStreamer.cpp122
-rw-r--r--lib/MC/MCSymbol.cpp7
-rw-r--r--lib/MC/MCTargetOptions.cpp8
-rw-r--r--lib/MC/MCValue.cpp2
-rw-r--r--lib/MC/MachObjectWriter.cpp6
-rw-r--r--lib/MC/StringTableBuilder.cpp159
-rw-r--r--lib/MC/SubtargetFeature.cpp2
-rw-r--r--lib/MC/WinCOFFObjectWriter.cpp5
-rw-r--r--lib/MC/WinCOFFStreamer.cpp15
39 files changed, 1853 insertions, 1094 deletions
diff --git a/lib/MC/ConstantPools.cpp b/lib/MC/ConstantPools.cpp
index 17a23d063b7d..9608c2c656b7 100644
--- a/lib/MC/ConstantPools.cpp
+++ b/lib/MC/ConstantPools.cpp
@@ -36,10 +36,20 @@ void ConstantPool::emitEntries(MCStreamer &Streamer) {
const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context,
unsigned Size, SMLoc Loc) {
+ const MCConstantExpr *C = dyn_cast<MCConstantExpr>(Value);
+
+ // Check if there is existing entry for the same constant. If so, reuse it.
+ auto Itr = C ? CachedEntries.find(C->getValue()) : CachedEntries.end();
+ if (Itr != CachedEntries.end())
+ return Itr->second;
+
MCSymbol *CPEntryLabel = Context.createTempSymbol();
Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size, Loc));
- return MCSymbolRefExpr::create(CPEntryLabel, Context);
+ const auto SymRef = MCSymbolRefExpr::create(CPEntryLabel, Context);
+ if (C)
+ CachedEntries[C->getValue()] = SymRef;
+ return SymRef;
}
bool ConstantPool::empty() { return Entries.empty(); }
@@ -79,7 +89,7 @@ void AssemblerConstantPools::emitAll(MCStreamer &Streamer) {
}
void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) {
- MCSection *Section = Streamer.getCurrentSection().first;
+ MCSection *Section = Streamer.getCurrentSectionOnly();
if (ConstantPool *CP = getConstantPool(Section)) {
emitConstantPool(Streamer, Section, *CP);
}
@@ -88,7 +98,7 @@ void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) {
const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer,
const MCExpr *Expr,
unsigned Size, SMLoc Loc) {
- MCSection *Section = Streamer.getCurrentSection().first;
+ MCSection *Section = Streamer.getCurrentSectionOnly();
return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext(),
Size, Loc);
}
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index dc21b48ca6f6..a8c88dda6936 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -568,25 +568,27 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
// If we change such a relocation to use the section, the linker would think
// that it pointed to another string and subtracting 42 at runtime will
// produce the wrong value.
- auto &Sec = cast<MCSectionELF>(Sym->getSection());
- unsigned Flags = Sec.getFlags();
- if (Flags & ELF::SHF_MERGE) {
- if (C != 0)
- return true;
+ if (Sym->isInSection()) {
+ auto &Sec = cast<MCSectionELF>(Sym->getSection());
+ unsigned Flags = Sec.getFlags();
+ if (Flags & ELF::SHF_MERGE) {
+ if (C != 0)
+ return true;
- // It looks like gold has a bug (http://sourceware.org/PR16794) and can
- // only handle section relocations to mergeable sections if using RELA.
- if (!hasRelocationAddend())
+ // It looks like gold has a bug (http://sourceware.org/PR16794) and can
+ // only handle section relocations to mergeable sections if using RELA.
+ if (!hasRelocationAddend())
+ return true;
+ }
+
+ // Most TLS relocations use a got, so they need the symbol. Even those that
+ // are just an offset (@tpoff), require a symbol in gold versions before
+ // 5efeedf61e4fe720fd3e9a08e6c91c10abb66d42 (2014-09-26) which fixed
+ // http://sourceware.org/PR16773.
+ if (Flags & ELF::SHF_TLS)
return true;
}
- // Most TLS relocations use a got, so they need the symbol. Even those that
- // are just an offset (@tpoff), require a symbol in gold versions before
- // 5efeedf61e4fe720fd3e9a08e6c91c10abb66d42 (2014-09-26) which fixed
- // http://sourceware.org/PR16773.
- if (Flags & ELF::SHF_TLS)
- return true;
-
// If the symbol is a thumb function the final relocation must set the lowest
// bit. With a symbol that is done by just having the symbol have that bit
// set, so we would lose the bit if we relocated with the section.
@@ -1127,7 +1129,7 @@ void ELFObjectWriter::writeRelocations(const MCAssembler &Asm,
const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) {
const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1];
- getStream() << StrTabBuilder.data();
+ StrTabBuilder.write(getStream());
return StrtabSection;
}
diff --git a/lib/MC/MCAsmBackend.cpp b/lib/MC/MCAsmBackend.cpp
index b868b9d48896..570f764f6642 100644
--- a/lib/MC/MCAsmBackend.cpp
+++ b/lib/MC/MCAsmBackend.cpp
@@ -34,6 +34,10 @@ const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"FK_GPRel_2", 0, 16, 0},
{"FK_GPRel_4", 0, 32, 0},
{"FK_GPRel_8", 0, 64, 0},
+ {"FK_DTPRel_4", 0, 32, 0},
+ {"FK_DTPRel_8", 0, 64, 0},
+ {"FK_TPRel_4", 0, 32, 0},
+ {"FK_TPRel_8", 0, 64, 0},
{"FK_SecRel_1", 0, 8, 0},
{"FK_SecRel_2", 0, 16, 0},
{"FK_SecRel_4", 0, 32, 0},
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
index 4a05175fdec3..3eb8f50de5a8 100644
--- a/lib/MC/MCAsmInfo.cpp
+++ b/lib/MC/MCAsmInfo.cpp
@@ -31,7 +31,6 @@ MCAsmInfo::MCAsmInfo() {
HasSubsectionsViaSymbols = false;
HasMachoZeroFillDirective = false;
HasMachoTBSSDirective = false;
- HasStaticCtorDtorReferenceInStaticMode = false;
MaxInstLength = 4;
MinInstAlignment = 1;
DollarIsPC = false;
diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp
index fc60313dd6b2..e95cf488cd30 100644
--- a/lib/MC/MCAsmInfoDarwin.cpp
+++ b/lib/MC/MCAsmInfoDarwin.cpp
@@ -76,7 +76,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
ZeroDirective = "\t.space\t"; // ".space N" emits N zeros.
HasMachoZeroFillDirective = true; // Uses .zerofill
HasMachoTBSSDirective = true; // Uses .tbss
- HasStaticCtorDtorReferenceInStaticMode = true;
// FIXME: Change this once MC is the system assembler.
HasAggressiveSymbolFolding = false;
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index ef2f7810deaa..817009a65363 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -14,6 +14,7 @@
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCCodeView.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixupKindInfo.h"
@@ -99,7 +100,7 @@ public:
/// file if applicable as a QoI issue to make the output of the compiler
/// more readable. This only affects the MCAsmStreamer, and only when
/// verbose assembly output is enabled.
- void AddComment(const Twine &T) override;
+ void AddComment(const Twine &T, bool EOL = true) override;
/// AddEncodingComment - Add a comment showing the encoding of an instruction.
void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &);
@@ -149,8 +150,8 @@ public:
void EndCOFFSymbolDef() override;
void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
- void EmitCOFFSecRel32(MCSymbol const *Symbol) override;
- void emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) override;
+ void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
+ void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
@@ -180,6 +181,11 @@ public:
void EmitSLEB128Value(const MCExpr *Value) override;
+ void EmitDTPRel32Value(const MCExpr *Value) override;
+ void EmitDTPRel64Value(const MCExpr *Value) override;
+ void EmitTPRel32Value(const MCExpr *Value) override;
+ void EmitTPRel64Value(const MCExpr *Value) override;
+
void EmitGPRel64Value(const MCExpr *Value) override;
void EmitGPRel32Value(const MCExpr *Value) override;
@@ -203,7 +209,8 @@ public:
unsigned MaxBytesToEmit = 0) override;
void emitValueToOffset(const MCExpr *Offset,
- unsigned char Value = 0) override;
+ unsigned char Value,
+ SMLoc Loc) override;
void EmitFileDirective(StringRef Filename) override;
unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
@@ -215,16 +222,21 @@ public:
StringRef FileName) override;
MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
- unsigned EmitCVFileDirective(unsigned FileNo, StringRef Filename) override;
+ bool EmitCVFileDirective(unsigned FileNo, StringRef Filename) override;
+ bool EmitCVFuncIdDirective(unsigned FuncId) override;
+ bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
+ unsigned IAFile, unsigned IALine,
+ unsigned IACol, SMLoc Loc) override;
void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
unsigned Column, bool PrologueEnd, bool IsStmt,
- StringRef FileName) override;
+ StringRef FileName, SMLoc Loc) override;
void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
const MCSymbol *FnEnd) override;
- void EmitCVInlineLinetableDirective(
- unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
- const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
- ArrayRef<unsigned> SecondaryFunctionIds) override;
+ void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
+ unsigned SourceFileId,
+ unsigned SourceLineNum,
+ const MCSymbol *FnStartSym,
+ const MCSymbol *FnEndSym) override;
void EmitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
StringRef FixedSizePortion) override;
@@ -289,12 +301,14 @@ public:
/// file if applicable as a QoI issue to make the output of the compiler
/// more readable. This only affects the MCAsmStreamer, and only when
/// verbose assembly output is enabled.
-void MCAsmStreamer::AddComment(const Twine &T) {
+/// By deafult EOL is set to true so that each comment goes on its own line.
+void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
if (!IsVerboseAsm) return;
T.toVector(CommentToEmit);
- // Each comment goes on its own line.
- CommentToEmit.push_back('\n');
+
+ if (EOL)
+ CommentToEmit.push_back('\n'); // Place comment in a new line.
}
void MCAsmStreamer::EmitCommentsAndEOL() {
@@ -357,9 +371,10 @@ void MCAsmStreamer::addExplicitComment(const Twine &T) {
ExplicitCommentToEmit.append("\t");
ExplicitCommentToEmit.append(c.str());
} else if (c.front() == '#') {
- // # are comments for ## commentString. Output extra #.
- ExplicitCommentToEmit.append("\t#");
- ExplicitCommentToEmit.append(c.str());
+
+ ExplicitCommentToEmit.append("\t");
+ ExplicitCommentToEmit.append(MAI->getCommentString());
+ ExplicitCommentToEmit.append(c.slice(1, c.size()).str());
} else
assert(false && "Unexpected Assembly Comment");
// full line comments immediately output
@@ -602,13 +617,15 @@ void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
EmitEOL();
}
-void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {
+void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
OS << "\t.secrel32\t";
Symbol->print(OS, MAI);
+ if (Offset != 0)
+ OS << '+' << Offset;
EmitEOL();
}
-void MCAsmStreamer::emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) {
+void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
assert(MAI->hasDotTypeDotSizeDirective());
OS << "\t.size\t";
Symbol->print(OS, MAI);
@@ -737,7 +754,7 @@ static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
}
void MCAsmStreamer::EmitBytes(StringRef Data) {
- assert(getCurrentSection().first &&
+ assert(getCurrentSectionOnly() &&
"Cannot emit contents before setting section!");
if (Data.empty()) return;
@@ -782,7 +799,7 @@ void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
SMLoc Loc) {
assert(Size <= 8 && "Invalid size");
- assert(getCurrentSection().first &&
+ assert(getCurrentSectionOnly() &&
"Cannot emit contents before setting section!");
const char *Directive = nullptr;
switch (Size) {
@@ -855,6 +872,34 @@ void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) {
EmitEOL();
}
+void MCAsmStreamer::EmitDTPRel64Value(const MCExpr *Value) {
+ assert(MAI->getDTPRel64Directive() != nullptr);
+ OS << MAI->getDTPRel64Directive();
+ Value->print(OS, MAI);
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitDTPRel32Value(const MCExpr *Value) {
+ assert(MAI->getDTPRel32Directive() != nullptr);
+ OS << MAI->getDTPRel32Directive();
+ Value->print(OS, MAI);
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitTPRel64Value(const MCExpr *Value) {
+ assert(MAI->getTPRel64Directive() != nullptr);
+ OS << MAI->getTPRel64Directive();
+ Value->print(OS, MAI);
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitTPRel32Value(const MCExpr *Value) {
+ assert(MAI->getTPRel32Directive() != nullptr);
+ OS << MAI->getTPRel32Directive();
+ Value->print(OS, MAI);
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) {
assert(MAI->getGPRel64Directive() != nullptr);
OS << MAI->getGPRel64Directive();
@@ -971,7 +1016,8 @@ void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment,
}
void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
- unsigned char Value) {
+ unsigned char Value,
+ SMLoc Loc) {
// FIXME: Verify that Offset is associated with the current section.
OS << ".org ";
Offset->print(OS, MAI);
@@ -1068,29 +1114,43 @@ MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
return MCStreamer::getDwarfLineTableSymbol(0);
}
-unsigned MCAsmStreamer::EmitCVFileDirective(unsigned FileNo,
- StringRef Filename) {
- if (!getContext().getCVFile(Filename, FileNo))
- return 0;
+bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
+ if (!getContext().getCVContext().addFile(FileNo, Filename))
+ return false;
OS << "\t.cv_file\t" << FileNo << ' ';
PrintQuotedString(Filename, OS);
EmitEOL();
+ return true;
+}
- return FileNo;
+bool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) {
+ OS << "\t.cv_func_id " << FuncId << '\n';
+ return MCStreamer::EmitCVFuncIdDirective(FuncId);
+}
+
+bool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
+ unsigned IAFunc,
+ unsigned IAFile,
+ unsigned IALine, unsigned IACol,
+ SMLoc Loc) {
+ OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
+ << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
+ return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
+ IALine, IACol, Loc);
}
void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
unsigned Line, unsigned Column,
bool PrologueEnd, bool IsStmt,
- StringRef FileName) {
+ StringRef FileName, SMLoc Loc) {
OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
<< Column;
if (PrologueEnd)
OS << " prologue_end";
- unsigned OldIsStmt = getContext().getCurrentCVLoc().isStmt();
+ unsigned OldIsStmt = getContext().getCVContext().getCurrentCVLoc().isStmt();
if (IsStmt != OldIsStmt) {
OS << " is_stmt ";
@@ -1102,12 +1162,12 @@ void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
if (IsVerboseAsm) {
OS.PadToColumn(MAI->getCommentColumn());
- OS << MAI->getCommentString() << ' ' << FileName << ':'
- << Line << ':' << Column;
+ OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
+ << Column;
}
EmitEOL();
this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
- PrologueEnd, IsStmt, FileName);
+ PrologueEnd, IsStmt, FileName, Loc);
}
void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
@@ -1121,24 +1181,19 @@ void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd);
}
-void MCAsmStreamer::EmitCVInlineLinetableDirective(
- unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
- const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
- ArrayRef<unsigned> SecondaryFunctionIds) {
+void MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
+ unsigned SourceFileId,
+ unsigned SourceLineNum,
+ const MCSymbol *FnStartSym,
+ const MCSymbol *FnEndSym) {
OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
<< ' ' << SourceLineNum << ' ';
FnStartSym->print(OS, MAI);
OS << ' ';
FnEndSym->print(OS, MAI);
- if (!SecondaryFunctionIds.empty()) {
- OS << " contains";
- for (unsigned SecondaryFunctionId : SecondaryFunctionIds)
- OS << ' ' << SecondaryFunctionId;
- }
EmitEOL();
this->MCStreamer::EmitCVInlineLinetableDirective(
- PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym,
- SecondaryFunctionIds);
+ PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
}
void MCAsmStreamer::EmitCVDefRangeDirective(
@@ -1531,8 +1586,9 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
}
}
-void MCAsmStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) {
- assert(getCurrentSection().first &&
+void MCAsmStreamer::EmitInstruction(const MCInst &Inst,
+ const MCSubtargetInfo &STI) {
+ assert(getCurrentSectionOnly() &&
"Cannot emit contents before setting section!");
// Show the encoding in a comment if we have a code emitter.
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 7a42108ceaf3..83fcec92e2b5 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -278,22 +278,29 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
case MCFragment::FT_Org: {
const MCOrgFragment &OF = cast<MCOrgFragment>(F);
MCValue Value;
- if (!OF.getOffset().evaluateAsValue(Value, Layout))
- report_fatal_error("expected assembly-time absolute expression");
+ if (!OF.getOffset().evaluateAsValue(Value, Layout)) {
+ getContext().reportError(OF.getLoc(),
+ "expected assembly-time absolute expression");
+ return 0;
+ }
- // FIXME: We need a way to communicate this error.
uint64_t FragmentOffset = Layout.getFragmentOffset(&OF);
int64_t TargetLocation = Value.getConstant();
if (const MCSymbolRefExpr *A = Value.getSymA()) {
uint64_t Val;
- if (!Layout.getSymbolOffset(A->getSymbol(), Val))
- report_fatal_error("expected absolute expression");
+ if (!Layout.getSymbolOffset(A->getSymbol(), Val)) {
+ getContext().reportError(OF.getLoc(), "expected absolute expression");
+ return 0;
+ }
TargetLocation += Val;
}
int64_t Size = TargetLocation - FragmentOffset;
- if (Size < 0 || Size >= 0x40000000)
- report_fatal_error("invalid .org offset '" + Twine(TargetLocation) +
- "' (at offset '" + Twine(FragmentOffset) + "')");
+ if (Size < 0 || Size >= 0x40000000) {
+ getContext().reportError(
+ OF.getLoc(), "invalid .org offset '" + Twine(TargetLocation) +
+ "' (at offset '" + Twine(FragmentOffset) + "')");
+ return 0;
+ }
return Size;
}
@@ -575,8 +582,8 @@ void MCAssembler::writeSectionData(const MCSection *Sec,
// into a virtual section. This is to support clients which use standard
// directives to fill the contents of virtual sections.
const MCDataFragment &DF = cast<MCDataFragment>(F);
- assert(DF.fixup_begin() == DF.fixup_end() &&
- "Cannot have fixups in virtual section!");
+ if (DF.fixup_begin() != DF.fixup_end())
+ report_fatal_error("cannot have fixups in virtual section!");
for (unsigned i = 0, e = DF.getContents().size(); i != e; ++i)
if (DF.getContents()[i]) {
if (auto *ELFSec = dyn_cast<const MCSectionELF>(Sec))
@@ -660,7 +667,8 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
// Layout until everything fits.
while (layoutOnce(Layout))
- continue;
+ if (getContext().hadError())
+ return;
DEBUG_WITH_TYPE("mc-dump", {
llvm::errs() << "assembler backend - post-relaxation\n--\n";
@@ -912,7 +920,9 @@ bool MCAssembler::layoutOnce(MCAsmLayout &Layout) {
void MCAssembler::finishLayout(MCAsmLayout &Layout) {
// The layout is done. Mark every fragment as valid.
for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) {
- Layout.getFragmentOffset(&*Layout.getSectionOrder()[i]->rbegin());
+ MCSection &Section = *Layout.getSectionOrder()[i];
+ Layout.getFragmentOffset(&*Section.rbegin());
+ computeFragmentSize(Layout, *Section.rbegin());
}
getBackend().finishLayout(*this, Layout);
}
diff --git a/lib/MC/MCCodeView.cpp b/lib/MC/MCCodeView.cpp
index 65cff41abebe..3773542cf8a2 100644
--- a/lib/MC/MCCodeView.cpp
+++ b/lib/MC/MCCodeView.cpp
@@ -65,6 +65,50 @@ bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename) {
return true;
}
+bool CodeViewContext::recordFunctionId(unsigned FuncId) {
+ if (FuncId >= Functions.size())
+ Functions.resize(FuncId + 1);
+
+ // Return false if this function info was already allocated.
+ if (!Functions[FuncId].isUnallocatedFunctionInfo())
+ return false;
+
+ // Mark this as an allocated normal function, and leave the rest alone.
+ Functions[FuncId].ParentFuncIdPlusOne = MCCVFunctionInfo::FunctionSentinel;
+ return true;
+}
+
+bool CodeViewContext::recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
+ unsigned IAFile, unsigned IALine,
+ unsigned IACol) {
+ if (FuncId >= Functions.size())
+ Functions.resize(FuncId + 1);
+
+ // Return false if this function info was already allocated.
+ if (!Functions[FuncId].isUnallocatedFunctionInfo())
+ return false;
+
+ MCCVFunctionInfo::LineInfo InlinedAt;
+ InlinedAt.File = IAFile;
+ InlinedAt.Line = IALine;
+ InlinedAt.Col = IACol;
+
+ // Mark this as an inlined call site and record call site line info.
+ MCCVFunctionInfo *Info = &Functions[FuncId];
+ Info->ParentFuncIdPlusOne = IAFunc + 1;
+ Info->InlinedAt = InlinedAt;
+
+ // Walk up the call chain adding this function id to the InlinedAtMap of all
+ // transitive callers until we hit a real function.
+ while (Info->isInlinedCallSite()) {
+ InlinedAt = Info->InlinedAt;
+ Info = getCVFunctionInfo(Info->getParentFuncId());
+ Info->InlinedAtMap[FuncId] = InlinedAt;
+ }
+
+ return true;
+}
+
MCDataFragment *CodeViewContext::getStringTableFragment() {
if (!StrTabFragment) {
StrTabFragment = new MCDataFragment();
@@ -156,7 +200,7 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
OS.EmitIntValue(unsigned(ModuleSubstreamKind::Lines), 4);
OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4);
OS.EmitLabel(LineBegin);
- OS.EmitCOFFSecRel32(FuncBegin);
+ OS.EmitCOFFSecRel32(FuncBegin, /*Offset=*/0);
OS.EmitCOFFSectionIndex(FuncBegin);
// Actual line info.
@@ -237,15 +281,17 @@ static uint32_t encodeSignedNumber(uint32_t Data) {
return Data << 1;
}
-void CodeViewContext::emitInlineLineTableForFunction(
- MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId,
- unsigned SourceLineNum, const MCSymbol *FnStartSym,
- const MCSymbol *FnEndSym, ArrayRef<unsigned> SecondaryFunctionIds) {
+void CodeViewContext::emitInlineLineTableForFunction(MCObjectStreamer &OS,
+ unsigned PrimaryFunctionId,
+ unsigned SourceFileId,
+ unsigned SourceLineNum,
+ const MCSymbol *FnStartSym,
+ const MCSymbol *FnEndSym) {
// Create and insert a fragment into the current section that will be encoded
// later.
- new MCCVInlineLineTableFragment(
- PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym,
- SecondaryFunctionIds, OS.getCurrentSectionOnly());
+ new MCCVInlineLineTableFragment(PrimaryFunctionId, SourceFileId,
+ SourceLineNum, FnStartSym, FnEndSym,
+ OS.getCurrentSectionOnly());
}
void CodeViewContext::emitDefRange(
@@ -280,69 +326,92 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
size_t LocBegin;
size_t LocEnd;
std::tie(LocBegin, LocEnd) = getLineExtent(Frag.SiteFuncId);
- for (unsigned SecondaryId : Frag.SecondaryFuncs) {
- auto Extent = getLineExtent(SecondaryId);
+
+ // Include all child inline call sites in our .cv_loc extent.
+ MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(Frag.SiteFuncId);
+ for (auto &KV : SiteInfo->InlinedAtMap) {
+ unsigned ChildId = KV.first;
+ auto Extent = getLineExtent(ChildId);
LocBegin = std::min(LocBegin, Extent.first);
LocEnd = std::max(LocEnd, Extent.second);
}
+
if (LocBegin >= LocEnd)
return;
ArrayRef<MCCVLineEntry> Locs = getLinesForExtent(LocBegin, LocEnd);
if (Locs.empty())
return;
- SmallSet<unsigned, 8> InlinedFuncIds;
- InlinedFuncIds.insert(Frag.SiteFuncId);
- InlinedFuncIds.insert(Frag.SecondaryFuncs.begin(), Frag.SecondaryFuncs.end());
-
// 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()));
StartLoc.setFileNum(Frag.StartFileId);
StartLoc.setLine(Frag.StartLineNum);
- const MCCVLineEntry *LastLoc = &StartLoc;
bool HaveOpenRange = false;
+ const MCSymbol *LastLabel = Frag.getFnStartSym();
+ MCCVFunctionInfo::LineInfo LastSourceLoc, CurSourceLoc;
+ LastSourceLoc.File = Frag.StartFileId;
+ LastSourceLoc.Line = Frag.StartLineNum;
+
SmallVectorImpl<char> &Buffer = Frag.getContents();
Buffer.clear(); // Clear old contents if we went through relaxation.
for (const MCCVLineEntry &Loc : Locs) {
- if (!InlinedFuncIds.count(Loc.getFunctionId())) {
- // We've hit a cv_loc not attributed to this inline call site. Use this
- // label to end the PC range.
- if (HaveOpenRange) {
- unsigned Length =
- computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel());
- compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);
- compressAnnotation(Length, Buffer);
+ // Exit early if our line table would produce an oversized InlineSiteSym
+ // record. Account for the ChangeCodeLength annotation emitted after the
+ // loop ends.
+ constexpr uint32_t InlineSiteSize = 12;
+ constexpr uint32_t AnnotationSize = 8;
+ size_t MaxBufferSize = MaxRecordLength - InlineSiteSize - AnnotationSize;
+ if (Buffer.size() >= MaxBufferSize)
+ break;
+
+ if (Loc.getFunctionId() == Frag.SiteFuncId) {
+ CurSourceLoc.File = Loc.getFileNum();
+ CurSourceLoc.Line = Loc.getLine();
+ } else {
+ auto I = SiteInfo->InlinedAtMap.find(Loc.getFunctionId());
+ if (I != SiteInfo->InlinedAtMap.end()) {
+ // This .cv_loc is from a child inline call site. Use the source
+ // location of the inlined call site instead of the .cv_loc directive
+ // source location.
+ CurSourceLoc = I->second;
+ } else {
+ // We've hit a cv_loc not attributed to this inline call site. Use this
+ // label to end the PC range.
+ if (HaveOpenRange) {
+ unsigned Length = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
+ compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);
+ compressAnnotation(Length, Buffer);
+ LastLabel = Loc.getLabel();
+ }
+ HaveOpenRange = false;
+ continue;
}
- HaveOpenRange = false;
- continue;
}
- // If we've already opened the function and we're at an indirectly inlined
- // location, continue until the next directly inlined location.
- bool DirectlyInlined = Loc.getFunctionId() == Frag.SiteFuncId;
- if (!DirectlyInlined && HaveOpenRange)
+ // Skip this .cv_loc if we have an open range and this isn't a meaningful
+ // source location update. The current table format does not support column
+ // info, so we can skip updates for those.
+ if (HaveOpenRange && CurSourceLoc.File == LastSourceLoc.File &&
+ CurSourceLoc.Line == LastSourceLoc.Line)
continue;
+
HaveOpenRange = true;
- if (Loc.getFileNum() != LastLoc->getFileNum()) {
+ if (CurSourceLoc.File != LastSourceLoc.File) {
// File ids are 1 based, and each file checksum table entry is 8 bytes
// long. See emitFileChecksums above.
- unsigned FileOffset = 8 * (Loc.getFileNum() - 1);
+ unsigned FileOffset = 8 * (CurSourceLoc.File - 1);
compressAnnotation(BinaryAnnotationsOpCode::ChangeFile, Buffer);
compressAnnotation(FileOffset, Buffer);
}
- int LineDelta = Loc.getLine() - LastLoc->getLine();
- if (LineDelta == 0)
- continue;
-
+ int LineDelta = CurSourceLoc.Line - LastSourceLoc.Line;
unsigned EncodedLineDelta = encodeSignedNumber(LineDelta);
- unsigned CodeDelta =
- computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel());
- if (CodeDelta == 0) {
+ unsigned CodeDelta = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
+ if (CodeDelta == 0 && LineDelta != 0) {
compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
compressAnnotation(EncodedLineDelta, Buffer);
} else if (EncodedLineDelta < 0x8 && CodeDelta <= 0xf) {
@@ -355,29 +424,29 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
compressAnnotation(Operand, Buffer);
} else {
// Otherwise use the separate line and code deltas.
- compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
- compressAnnotation(EncodedLineDelta, Buffer);
+ if (LineDelta != 0) {
+ compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
+ compressAnnotation(EncodedLineDelta, Buffer);
+ }
compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffset, Buffer);
compressAnnotation(CodeDelta, Buffer);
}
- LastLoc = &Loc;
+ LastLabel = Loc.getLabel();
+ LastSourceLoc = CurSourceLoc;
}
assert(HaveOpenRange);
unsigned EndSymLength =
- computeLabelDiff(Layout, LastLoc->getLabel(), Frag.getFnEndSym());
+ computeLabelDiff(Layout, LastLabel, Frag.getFnEndSym());
unsigned LocAfterLength = ~0U;
ArrayRef<MCCVLineEntry> 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];
- if (&Loc.getLabel()->getSection(false) ==
- &LastLoc->getLabel()->getSection(false)) {
- LocAfterLength =
- computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel());
- }
+ if (&Loc.getLabel()->getSection(false) == &LastLabel->getSection(false))
+ LocAfterLength = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
}
compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);
@@ -393,16 +462,41 @@ void CodeViewContext::encodeDefRange(MCAsmLayout &Layout,
Fixups.clear();
raw_svector_ostream OS(Contents);
- // Write down each range where the variable is defined.
+ // Compute all the sizes up front.
+ SmallVector<std::pair<unsigned, unsigned>, 4> GapAndRangeSizes;
+ const MCSymbol *LastLabel = nullptr;
for (std::pair<const MCSymbol *, const MCSymbol *> Range : Frag.getRanges()) {
+ unsigned GapSize =
+ LastLabel ? computeLabelDiff(Layout, LastLabel, Range.first) : 0;
unsigned RangeSize = computeLabelDiff(Layout, Range.first, Range.second);
+ GapAndRangeSizes.push_back({GapSize, RangeSize});
+ LastLabel = Range.second;
+ }
+
+ // Write down each range where the variable is defined.
+ for (size_t I = 0, E = Frag.getRanges().size(); I != E;) {
+ // If the range size of multiple consecutive ranges is under the max,
+ // combine the ranges and emit some gaps.
+ const MCSymbol *RangeBegin = Frag.getRanges()[I].first;
+ unsigned RangeSize = GapAndRangeSizes[I].second;
+ size_t J = I + 1;
+ for (; J != E; ++J) {
+ unsigned GapAndRangeSize = GapAndRangeSizes[J].first + GapAndRangeSizes[J].second;
+ if (RangeSize + GapAndRangeSize > MaxDefRange)
+ break;
+ RangeSize += GapAndRangeSize;
+ }
+ unsigned NumGaps = J - I - 1;
+
+ support::endian::Writer<support::little> LEWriter(OS);
+
unsigned Bias = 0;
// We must split the range into chunks of MaxDefRange, this is a fundamental
// limitation of the file format.
do {
uint16_t Chunk = std::min((uint32_t)MaxDefRange, RangeSize);
- const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Range.first, Ctx);
+ const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(RangeBegin, Ctx);
const MCBinaryExpr *BE =
MCBinaryExpr::createAdd(SRE, MCConstantExpr::create(Bias, Ctx), Ctx);
MCValue Res;
@@ -413,8 +507,8 @@ void CodeViewContext::encodeDefRange(MCAsmLayout &Layout,
StringRef FixedSizePortion = Frag.getFixedSizePortion();
// Our record is a fixed sized prefix and a LocalVariableAddrRange that we
// are artificially constructing.
- size_t RecordSize =
- FixedSizePortion.size() + sizeof(LocalVariableAddrRange);
+ size_t RecordSize = FixedSizePortion.size() +
+ sizeof(LocalVariableAddrRange) + 4 * NumGaps;
// Write out the recrod size.
support::endian::Writer<support::little>(OS).write<uint16_t>(RecordSize);
// Write out the fixed size prefix.
@@ -427,12 +521,25 @@ void CodeViewContext::encodeDefRange(MCAsmLayout &Layout,
Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_2));
Contents.resize(Contents.size() + 2); // Fixup for section index.
// Write down the range's extent.
- support::endian::Writer<support::little>(OS).write<uint16_t>(Chunk);
+ LEWriter.write<uint16_t>(Chunk);
// Move on to the next range.
Bias += Chunk;
RangeSize -= Chunk;
} while (RangeSize > 0);
+
+ // Emit the gaps afterwards.
+ assert((NumGaps == 0 || Bias < MaxDefRange) &&
+ "large ranges should not have gaps");
+ unsigned GapStartOffset = GapAndRangeSizes[I].second;
+ for (++I; I != J; ++I) {
+ unsigned GapSize, RangeSize;
+ assert(I < GapAndRangeSizes.size());
+ std::tie(GapSize, RangeSize) = GapAndRangeSizes[I];
+ LEWriter.write<uint16_t>(GapStartOffset);
+ LEWriter.write<uint16_t>(RangeSize);
+ GapStartOffset += GapSize + RangeSize;
+ }
}
}
@@ -442,7 +549,8 @@ void CodeViewContext::encodeDefRange(MCAsmLayout &Layout,
// a line entry made for it is made.
//
void MCCVLineEntry::Make(MCObjectStreamer *MCOS) {
- if (!MCOS->getContext().getCVLocSeen())
+ CodeViewContext &CVC = MCOS->getContext().getCVContext();
+ if (!CVC.getCVLocSeen())
return;
// Create a symbol at in the current section for use in the line entry.
@@ -451,14 +559,14 @@ void MCCVLineEntry::Make(MCObjectStreamer *MCOS) {
MCOS->EmitLabel(LineSym);
// Get the current .loc info saved in the context.
- const MCCVLoc &CVLoc = MCOS->getContext().getCurrentCVLoc();
+ 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.
- MCOS->getContext().clearCVLocSeen();
+ CVC.clearCVLocSeen();
// Add the line entry to this section's entries.
- MCOS->getContext().getCVContext().addLineEntry(LineEntry);
+ CVC.addLineEntry(LineEntry);
}
diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp
index 47ed1ca3add5..4798991ceed6 100644
--- a/lib/MC/MCContext.cpp
+++ b/lib/MC/MCContext.cpp
@@ -125,15 +125,15 @@ MCSymbol *MCContext::getOrCreateSymbol(const Twine &Name) {
}
MCSymbolELF *MCContext::getOrCreateSectionSymbol(const MCSectionELF &Section) {
- MCSymbolELF *&Sym = SectionSymbols[&Section];
+ MCSymbol *&Sym = SectionSymbols[&Section];
if (Sym)
- return Sym;
+ return cast<MCSymbolELF>(Sym);
StringRef Name = Section.getSectionName();
auto NameIter = UsedNames.insert(std::make_pair(Name, false)).first;
Sym = new (&*NameIter, *this) MCSymbolELF(&*NameIter, /*isTemporary*/ false);
- return Sym;
+ return cast<MCSymbolELF>(Sym);
}
MCSymbol *MCContext::getOrCreateFrameAllocSymbol(StringRef FuncName,
@@ -173,7 +173,7 @@ MCSymbol *MCContext::createSymbol(StringRef Name, bool AlwaysAddSuffix,
if (CanBeUnnamed && !UseNamesOnTempLabels)
return createSymbolImpl(nullptr, true);
- // Determine whether this is an user writter assembler temporary or normal
+ // Determine whether this is a user written assembler temporary or normal
// label, if used.
bool IsTemporary = CanBeUnnamed;
if (AllowTemporaryLabels && !IsTemporary)
@@ -260,6 +260,13 @@ MCSymbol *MCContext::lookupSymbol(const Twine &Name) const {
return Symbols.lookup(NameRef);
}
+void MCContext::setSymbolValue(MCStreamer &Streamer,
+ StringRef Sym,
+ uint64_t Val) {
+ auto Symbol = getOrCreateSymbol(Sym);
+ Streamer.EmitAssignment(Symbol, MCConstantExpr::create(Val, *this));
+}
+
//===----------------------------------------------------------------------===//
// Section Management
//===----------------------------------------------------------------------===//
@@ -361,7 +368,9 @@ MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
StringRef CachedName = Entry.first.SectionName;
SectionKind Kind;
- if (Flags & ELF::SHF_EXECINSTR)
+ if (Flags & ELF::SHF_ARM_PURECODE)
+ Kind = SectionKind::getExecuteOnly();
+ else if (Flags & ELF::SHF_EXECINSTR)
Kind = SectionKind::getText();
else
Kind = SectionKind::getReadOnly();
@@ -494,14 +503,6 @@ CodeViewContext &MCContext::getCVContext() {
return *CVContext.get();
}
-unsigned MCContext::getCVFile(StringRef FileName, unsigned FileNumber) {
- return getCVContext().addFile(FileNumber, FileName) ? FileNumber : 0;
-}
-
-bool MCContext::isValidCVFileNumber(unsigned FileNumber) {
- return getCVContext().isValidFileNumber(FileNumber);
-}
-
//===----------------------------------------------------------------------===//
// Error Reporting
//===----------------------------------------------------------------------===//
diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp
index 21e8748b797a..aa5072743bdf 100644
--- a/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/lib/MC/MCDisassembler/Disassembler.cpp
@@ -9,6 +9,9 @@
#include "Disassembler.h"
#include "llvm-c/Disassembler.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
@@ -16,12 +19,19 @@
#include "llvm/MC/MCDisassembler/MCSymbolizer.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSchedule.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetRegistry.h"
+#include <cassert>
+#include <cstddef>
+#include <cstring>
using namespace llvm;
@@ -116,7 +126,7 @@ LLVMDisasmContextRef LLVMCreateDisasm(const char *TT, void *DisInfo,
// LLVMDisasmDispose() disposes of the disassembler specified by the context.
//
void LLVMDisasmDispose(LLVMDisasmContextRef DCR){
- LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
delete DC;
}
@@ -128,7 +138,7 @@ static void emitComments(LLVMDisasmContext *DC,
StringRef Comments = DC->CommentsToEmit.str();
// Get the default information for printing a comment.
const MCAsmInfo *MAI = DC->getAsmInfo();
- const char *CommentBegin = MAI->getCommentString();
+ StringRef CommentBegin = MAI->getCommentString();
unsigned CommentColumn = MAI->getCommentColumn();
bool IsFirst = true;
while (!Comments.empty()) {
@@ -211,7 +221,6 @@ static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
return Latency;
}
-
/// \brief Emits latency information in DC->CommentStream for \p Inst, based
/// on the information available in \p DC.
static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
@@ -239,7 +248,7 @@ static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
uint64_t BytesSize, uint64_t PC, char *OutString,
size_t OutStringSize){
- LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
// Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject.
ArrayRef<uint8_t> Data(Bytes, BytesSize);
@@ -288,21 +297,21 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
//
int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){
if (Options & LLVMDisassembler_Option_UseMarkup){
- LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
MCInstPrinter *IP = DC->getIP();
- IP->setUseMarkup(1);
+ IP->setUseMarkup(true);
DC->addOptions(LLVMDisassembler_Option_UseMarkup);
Options &= ~LLVMDisassembler_Option_UseMarkup;
}
if (Options & LLVMDisassembler_Option_PrintImmHex){
- LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
MCInstPrinter *IP = DC->getIP();
- IP->setPrintImmHex(1);
+ IP->setPrintImmHex(true);
DC->addOptions(LLVMDisassembler_Option_PrintImmHex);
Options &= ~LLVMDisassembler_Option_PrintImmHex;
}
if (Options & LLVMDisassembler_Option_AsmPrinterVariant){
- LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
// Try to set up the new instruction printer.
const MCAsmInfo *MAI = DC->getAsmInfo();
const MCInstrInfo *MII = DC->getInstrInfo();
@@ -318,14 +327,14 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){
}
}
if (Options & LLVMDisassembler_Option_SetInstrComments) {
- LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
MCInstPrinter *IP = DC->getIP();
IP->setCommentStream(DC->CommentStream);
DC->addOptions(LLVMDisassembler_Option_SetInstrComments);
Options &= ~LLVMDisassembler_Option_SetInstrComments;
}
if (Options & LLVMDisassembler_Option_PrintLatency) {
- LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
DC->addOptions(LLVMDisassembler_Option_PrintLatency);
Options &= ~LLVMDisassembler_Option_PrintLatency;
}
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index 54b2c918c849..a7551a3283a3 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -122,7 +122,8 @@ EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section,
MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1);
MCOS->EmitULEB128IntValue(Column);
}
- if (Discriminator != LineEntry.getDiscriminator()) {
+ if (Discriminator != LineEntry.getDiscriminator() &&
+ MCOS->getContext().getDwarfVersion() >= 4) {
Discriminator = LineEntry.getDiscriminator();
unsigned Size = getULEB128Size(Discriminator);
MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
@@ -916,7 +917,7 @@ void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
MCContext &context = MCOS->getContext();
// We won't create dwarf labels for symbols in sections that we are not
// generating debug info for.
- if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSection().first))
+ if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSectionOnly()))
return;
// The dwarf label's name does not have the symbol name's leading
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp
index 7d858c306d2e..0ef1b2a8bdca 100644
--- a/lib/MC/MCELFStreamer.cpp
+++ b/lib/MC/MCELFStreamer.cpp
@@ -329,8 +329,8 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
->setSize(MCConstantExpr::create(Size, getContext()));
}
-void MCELFStreamer::emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) {
- Symbol->setSize(Value);
+void MCELFStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
+ cast<MCSymbolELF>(Symbol)->setSize(Value);
}
void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp
index 6f90ff843bd0..bcc43a54d620 100644
--- a/lib/MC/MCExpr.cpp
+++ b/lib/MC/MCExpr.cpp
@@ -129,12 +129,10 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const {
llvm_unreachable("Invalid expression kind!");
}
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MCExpr::dump() const {
dbgs() << *this;
dbgs() << '\n';
}
-#endif
/* *** */
@@ -277,6 +275,10 @@ 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_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo";
+ case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi";
+ case VK_AMDGPU_REL32_LO: return "rel32@lo";
+ case VK_AMDGPU_REL32_HI: return "rel32@hi";
}
llvm_unreachable("Invalid variant kind");
}
@@ -374,6 +376,10 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("prel31", VK_ARM_PREL31)
.Case("sbrel", VK_ARM_SBREL)
.Case("tlsldo", VK_ARM_TLSLDO)
+ .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)
+ .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI)
+ .Case("rel32@lo", VK_AMDGPU_REL32_LO)
+ .Case("rel32@hi", VK_AMDGPU_REL32_HI)
.Default(VK_Invalid);
}
diff --git a/lib/MC/MCFragment.cpp b/lib/MC/MCFragment.cpp
index 1eb1d2996cb1..8ff8f8aba1c1 100644
--- a/lib/MC/MCFragment.cpp
+++ b/lib/MC/MCFragment.cpp
@@ -10,6 +10,7 @@
#include "llvm/MC/MCFragment.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
@@ -231,13 +232,7 @@ uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler,
/* *** */
-void ilist_node_traits<MCFragment>::deleteNode(MCFragment *V) {
- V->destroy();
-}
-
-MCFragment::MCFragment() : Kind(FragmentType(~0)), HasInstructions(false),
- AlignToBundleEnd(false), BundlePadding(0) {
-}
+void ilist_alloc_traits<MCFragment>::deleteNode(MCFragment *V) { V->destroy(); }
MCFragment::~MCFragment() { }
@@ -315,7 +310,6 @@ raw_ostream &operator<<(raw_ostream &OS, const MCFixup &AF) {
}
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MCFragment::dump() {
raw_ostream &OS = llvm::errs();
@@ -475,4 +469,3 @@ LLVM_DUMP_METHOD void MCAssembler::dump() {
}
OS << "]>\n";
}
-#endif
diff --git a/lib/MC/MCInst.cpp b/lib/MC/MCInst.cpp
index 16bc597cf3a2..2da8ecc4ff6a 100644
--- a/lib/MC/MCInst.cpp
+++ b/lib/MC/MCInst.cpp
@@ -34,12 +34,10 @@ void MCOperand::print(raw_ostream &OS) const {
OS << ">";
}
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MCOperand::dump() const {
print(dbgs());
dbgs() << "\n";
}
-#endif
void MCInst::print(raw_ostream &OS) const {
OS << "<MCInst " << getOpcode();
@@ -65,9 +63,7 @@ void MCInst::dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer,
OS << ">";
}
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MCInst::dump() const {
print(dbgs());
dbgs() << "\n";
}
-#endif
diff --git a/lib/MC/MCLabel.cpp b/lib/MC/MCLabel.cpp
index d973fc93b98c..b443cbbbf43e 100644
--- a/lib/MC/MCLabel.cpp
+++ b/lib/MC/MCLabel.cpp
@@ -16,8 +16,6 @@ void MCLabel::print(raw_ostream &OS) const {
OS << '"' << getInstance() << '"';
}
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MCLabel::dump() const {
print(dbgs());
}
-#endif
diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp
index d05bcea14c98..8fd71f62e4e5 100644
--- a/lib/MC/MCObjectFileInfo.cpp
+++ b/lib/MC/MCObjectFileInfo.cpp
@@ -177,20 +177,6 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
MachO::S_THREAD_LOCAL_VARIABLE_POINTERS,
SectionKind::getMetadata());
- if (!PositionIndependent) {
- StaticCtorSection = Ctx->getMachOSection("__TEXT", "__constructor", 0,
- SectionKind::getData());
- StaticDtorSection = Ctx->getMachOSection("__TEXT", "__destructor", 0,
- SectionKind::getData());
- } else {
- StaticCtorSection = Ctx->getMachOSection("__DATA", "__mod_init_func",
- MachO::S_MOD_INIT_FUNC_POINTERS,
- SectionKind::getData());
- StaticDtorSection = Ctx->getMachOSection("__DATA", "__mod_term_func",
- MachO::S_MOD_TERM_FUNC_POINTERS,
- SectionKind::getData());
- }
-
// Exception Handling.
LSDASection = Ctx->getMachOSection("__TEXT", "__gcc_except_tab", 0,
SectionKind::getReadOnlyWithRel());
@@ -311,6 +297,7 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) {
if (Ctx->getAsmInfo()->getExceptionHandlingType() == ExceptionHandling::ARM)
break;
// Fallthrough if not using EHABI
+ LLVM_FALLTHROUGH;
case Triple::ppc:
case Triple::x86:
PersonalityEncoding = PositionIndependent
@@ -395,6 +382,14 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) {
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:
@@ -498,12 +493,6 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) {
Ctx->getELFSection(".rodata.cst32", ELF::SHT_PROGBITS,
ELF::SHF_ALLOC | ELF::SHF_MERGE, 32, "");
- StaticCtorSection = Ctx->getELFSection(".ctors", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHF_WRITE);
-
- StaticDtorSection = Ctx->getELFSection(".dtors", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHF_WRITE);
-
// Exception Handling Sections.
// FIXME: We're emitting LSDA info into a readonly section on ELF, even though
@@ -621,26 +610,6 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
".rdata", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ,
SectionKind::getReadOnly());
- if (T.isKnownWindowsMSVCEnvironment() || T.isWindowsItaniumEnvironment()) {
- StaticCtorSection =
- Ctx->getCOFFSection(".CRT$XCU", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getReadOnly());
- StaticDtorSection =
- Ctx->getCOFFSection(".CRT$XTX", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getReadOnly());
- } else {
- StaticCtorSection = Ctx->getCOFFSection(
- ".ctors", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE,
- SectionKind::getData());
- StaticDtorSection = Ctx->getCOFFSection(
- ".dtors", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE,
- SectionKind::getData());
- }
-
// 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
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index d2ac0f50261d..cae5c1f8d156 100644
--- a/lib/MC/MCObjectStreamer.cpp
+++ b/lib/MC/MCObjectStreamer.cpp
@@ -13,6 +13,7 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCCodeView.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCExpr.h"
@@ -127,7 +128,7 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
flushPendingLabels(DF, DF->getContents().size());
MCCVLineEntry::Make(this);
- MCDwarfLineEntry::Make(this, getCurrentSection().first);
+ MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
// Avoid fixups when possible.
int64_t AbsValue;
@@ -235,7 +236,7 @@ void MCObjectStreamer::EmitInstruction(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, getCurrentSection().first);
+ MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
// If this instruction doesn't need relaxation, just emit it as data.
MCAssembler &Assembler = getAssembler();
@@ -304,7 +305,7 @@ void MCObjectStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
StringRef FileName) {
// In case we see two .loc directives in a row, make sure the
// first one gets a line entry.
- MCDwarfLineEntry::Make(this, getCurrentSection().first);
+ MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
Isa, Discriminator, FileName);
@@ -368,13 +369,13 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
unsigned Line, unsigned Column,
bool PrologueEnd, bool IsStmt,
- StringRef FileName) {
+ 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);
this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
- PrologueEnd, IsStmt, FileName);
+ PrologueEnd, IsStmt, FileName, Loc);
}
void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId,
@@ -387,14 +388,12 @@ void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId,
void MCObjectStreamer::EmitCVInlineLinetableDirective(
unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
- const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
- ArrayRef<unsigned> SecondaryFunctionIds) {
+ const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {
getContext().getCVContext().emitInlineLineTableForFunction(
*this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
- FnEndSym, SecondaryFunctionIds);
+ FnEndSym);
this->MCStreamer::EmitCVInlineLinetableDirective(
- PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym,
- SecondaryFunctionIds);
+ PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
}
void MCObjectStreamer::EmitCVDefRangeDirective(
@@ -414,7 +413,7 @@ void MCObjectStreamer::EmitCVFileChecksumsDirective() {
void MCObjectStreamer::EmitBytes(StringRef Data) {
MCCVLineEntry::Make(this);
- MCDwarfLineEntry::Make(this, getCurrentSection().first);
+ MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
DF->getContents().append(Data.begin(), Data.end());
@@ -429,7 +428,7 @@ void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment,
insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit));
// Update the maximum alignment on the current section if necessary.
- MCSection *CurSec = getCurrentSection().first;
+ MCSection *CurSec = getCurrentSectionOnly();
if (ByteAlignment > CurSec->getAlignment())
CurSec->setAlignment(ByteAlignment);
}
@@ -441,8 +440,49 @@ void MCObjectStreamer::EmitCodeAlignment(unsigned ByteAlignment,
}
void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
- unsigned char Value) {
- insert(new MCOrgFragment(*Offset, Value));
+ unsigned char Value,
+ SMLoc Loc) {
+ insert(new MCOrgFragment(*Offset, Value, Loc));
+}
+
+// Associate DTPRel32 fixup with data and resize data area
+void MCObjectStreamer::EmitDTPRel32Value(const MCExpr *Value) {
+ MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
+
+ DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
+ Value, FK_DTPRel_4));
+ DF->getContents().resize(DF->getContents().size() + 4, 0);
+}
+
+// Associate DTPRel64 fixup with data and resize data area
+void MCObjectStreamer::EmitDTPRel64Value(const MCExpr *Value) {
+ MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
+
+ DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
+ Value, FK_DTPRel_8));
+ DF->getContents().resize(DF->getContents().size() + 8, 0);
+}
+
+// Associate TPRel32 fixup with data and resize data area
+void MCObjectStreamer::EmitTPRel32Value(const MCExpr *Value) {
+ MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
+
+ DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
+ Value, FK_TPRel_4));
+ DF->getContents().resize(DF->getContents().size() + 4, 0);
+}
+
+// Associate TPRel64 fixup with data and resize data area
+void MCObjectStreamer::EmitTPRel64Value(const MCExpr *Value) {
+ MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
+
+ DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
+ Value, FK_TPRel_8));
+ DF->getContents().resize(DF->getContents().size() + 8, 0);
}
// Associate GPRel32 fixup with data and resize data area
@@ -455,7 +495,7 @@ void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) {
DF->getContents().resize(DF->getContents().size() + 4, 0);
}
-// Associate GPRel32 fixup with data and resize data area
+// Associate GPRel64 fixup with data and resize data area
void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
@@ -491,9 +531,7 @@ bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
}
void MCObjectStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) {
- const MCSection *Sec = getCurrentSection().first;
- (void)Sec;
- assert(Sec && "need a section");
+ assert(getCurrentSectionOnly() && "need a section");
insert(new MCFillFragment(FillValue, NumBytes));
}
diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp
index d56071aea4df..87ecf9e0227f 100644
--- a/lib/MC/MCParser/AsmLexer.cpp
+++ b/lib/MC/MCParser/AsmLexer.cpp
@@ -12,19 +12,28 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCParser/AsmLexer.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include <cassert>
#include <cctype>
-#include <cerrno>
#include <cstdio>
-#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <tuple>
+#include <utility>
+
using namespace llvm;
-AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) {
- CurPtr = nullptr;
- IsAtStartOfLine = true;
- IsAtStartOfStatement = true;
+AsmLexer::AsmLexer(const MCAsmInfo &MAI)
+ : MAI(MAI), CurPtr(nullptr), IsAtStartOfLine(true),
+ IsAtStartOfStatement(true), IsParsingMSInlineAsm(false),
+ IsPeeking(false) {
AllowAtInIdentifier = !StringRef(MAI.getCommentString()).startswith("@");
}
@@ -133,6 +142,7 @@ static bool IsIdentifierChar(char c, bool AllowAt) {
return isalnum(c) || c == '_' || c == '$' || c == '.' ||
(c == '@' && AllowAt) || c == '?';
}
+
AsmToken AsmLexer::LexIdentifier() {
// Check for floating point literals.
if (CurPtr[-1] == '.' && isdigit(*CurPtr)) {
@@ -171,12 +181,19 @@ AsmToken AsmLexer::LexSlash() {
// C Style comment.
++CurPtr; // skip the star.
+ const char *CommentTextStart = CurPtr;
while (CurPtr != CurBuf.end()) {
switch (*CurPtr++) {
case '*':
// End of the comment?
if (*CurPtr != '/')
break;
+ // If we have a CommentConsumer, notify it about the comment.
+ if (CommentConsumer) {
+ CommentConsumer->HandleComment(
+ SMLoc::getFromPointer(CommentTextStart),
+ StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
+ }
++CurPtr; // End the */.
return AsmToken(AsmToken::Comment,
StringRef(TokStart, CurPtr - TokStart));
@@ -192,12 +209,20 @@ AsmToken AsmLexer::LexLineComment() {
// comment. While it would be nicer to leave this two tokens,
// backwards compatability with TargetParsers makes keeping this in this form
// better.
+ const char *CommentTextStart = CurPtr;
int CurChar = getNextChar();
while (CurChar != '\n' && CurChar != '\r' && CurChar != EOF)
CurChar = getNextChar();
+ // If we have a CommentConsumer, notify it about the comment.
+ if (CommentConsumer) {
+ CommentConsumer->HandleComment(
+ SMLoc::getFromPointer(CommentTextStart),
+ StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
+ }
+
IsAtStartOfLine = true;
- // Whis is a whole line comment. leave newline
+ // This is a whole line comment. leave newline
if (IsAtStartOfStatement)
return AsmToken(AsmToken::EndOfStatement,
StringRef(TokStart, CurPtr - TokStart));
@@ -222,7 +247,7 @@ static void SkipIgnoredIntegerSuffix(const char *&CurPtr) {
static unsigned doLookAhead(const char *&CurPtr, unsigned DefaultRadix) {
const char *FirstHex = nullptr;
const char *LookAhead = CurPtr;
- while (1) {
+ while (true) {
if (isdigit(*LookAhead)) {
++LookAhead;
} else if (isxdigit(*LookAhead)) {
@@ -255,6 +280,45 @@ static AsmToken intToken(StringRef Ref, APInt &Value)
/// Hex integer: 0x[0-9a-fA-F]+ or [0x]?[0-9][0-9a-fA-F]*[hH]
/// Decimal integer: [1-9][0-9]*
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])) {
+ const char *FirstNonBinary = (CurPtr[-1] != '0' && CurPtr[-1] != '1') ?
+ CurPtr - 1 : nullptr;
+ const char *OldCurPtr = CurPtr;
+ while (isxdigit(*CurPtr)) {
+ if (*CurPtr != '0' && *CurPtr != '1' && !FirstNonBinary)
+ FirstNonBinary = CurPtr;
+ ++CurPtr;
+ }
+
+ unsigned Radix = 0;
+ if (*CurPtr == 'h' || *CurPtr == 'H') {
+ // hexadecimal number
+ ++CurPtr;
+ Radix = 16;
+ } else if (FirstNonBinary && FirstNonBinary + 1 == CurPtr &&
+ (*FirstNonBinary == 'b' || *FirstNonBinary == 'B'))
+ Radix = 2;
+
+ if (Radix == 2 || Radix == 16) {
+ StringRef Result(TokStart, CurPtr - TokStart);
+ APInt Value(128, 0, true);
+
+ if (Result.drop_back().getAsInteger(Radix, Value))
+ return ReturnError(TokStart, Radix == 2 ? "invalid binary number" :
+ "invalid hexdecimal number");
+
+ // MSVC accepts and ignores type suffices on integer literals.
+ SkipIgnoredIntegerSuffix(CurPtr);
+
+ return intToken(Result, Value);
+ }
+
+ // octal/decimal integers, or floating point numbers, fall through
+ CurPtr = OldCurPtr;
+ }
+
// Decimal integer: [1-9][0-9]*
if (CurPtr[-1] != '0' || CurPtr[0] == '.') {
unsigned Radix = doLookAhead(CurPtr, 10);
@@ -283,7 +347,7 @@ AsmToken AsmLexer::LexDigit() {
return intToken(Result, Value);
}
- if ((*CurPtr == 'b') || (*CurPtr == 'B')) {
+ if (!IsParsingMSInlineAsm && ((*CurPtr == 'b') || (*CurPtr == 'B'))) {
++CurPtr;
// See if we actually have "0b" as part of something like "jmp 0b\n"
if (!isdigit(CurPtr[0])) {
@@ -332,7 +396,7 @@ AsmToken AsmLexer::LexDigit() {
return ReturnError(TokStart, "invalid hexadecimal number");
// Consume the optional [hH].
- if (*CurPtr == 'h' || *CurPtr == 'H')
+ if (!IsParsingMSInlineAsm && (*CurPtr == 'h' || *CurPtr == 'H'))
++CurPtr;
// The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
@@ -397,7 +461,6 @@ AsmToken AsmLexer::LexSingleQuote() {
return AsmToken(AsmToken::Integer, Res, Value);
}
-
/// LexQuote: String: "..."
AsmToken AsmLexer::LexQuote() {
int CurChar = getNextChar();
@@ -439,17 +502,15 @@ StringRef AsmLexer::LexUntilEndOfLine() {
size_t AsmLexer::peekTokens(MutableArrayRef<AsmToken> Buf,
bool ShouldSkipSpace) {
- const char *SavedTokStart = TokStart;
- const char *SavedCurPtr = CurPtr;
- bool SavedAtStartOfLine = IsAtStartOfLine;
- bool SavedAtStartOfStatement = IsAtStartOfStatement;
- bool SavedSkipSpace = SkipSpace;
-
+ SaveAndRestore<const char *> SavedTokenStart(TokStart);
+ SaveAndRestore<const char *> SavedCurPtr(CurPtr);
+ SaveAndRestore<bool> SavedAtStartOfLine(IsAtStartOfLine);
+ SaveAndRestore<bool> SavedAtStartOfStatement(IsAtStartOfStatement);
+ SaveAndRestore<bool> SavedSkipSpace(SkipSpace, ShouldSkipSpace);
+ SaveAndRestore<bool> SavedIsPeeking(IsPeeking, true);
std::string SavedErr = getErr();
SMLoc SavedErrLoc = getErrLoc();
- SkipSpace = ShouldSkipSpace;
-
size_t ReadCount;
for (ReadCount = 0; ReadCount < Buf.size(); ++ReadCount) {
AsmToken Token = LexToken();
@@ -461,27 +522,20 @@ size_t AsmLexer::peekTokens(MutableArrayRef<AsmToken> Buf,
}
SetError(SavedErrLoc, SavedErr);
-
- SkipSpace = SavedSkipSpace;
- IsAtStartOfLine = SavedAtStartOfLine;
- IsAtStartOfStatement = SavedAtStartOfStatement;
- CurPtr = SavedCurPtr;
- TokStart = SavedTokStart;
-
return ReadCount;
}
bool AsmLexer::isAtStartOfComment(const char *Ptr) {
- const char *CommentString = MAI.getCommentString();
+ StringRef CommentString = MAI.getCommentString();
- if (CommentString[1] == '\0')
+ if (CommentString.size() == 1)
return CommentString[0] == Ptr[0];
- // FIXME: special case for the bogus "##" comment string in X86MCAsmInfoDarwin
+ // Allow # preprocessor commments also be counted as comments for "##" cases
if (CommentString[1] == '#')
return CommentString[0] == Ptr[0];
- return strncmp(Ptr, CommentString, strlen(CommentString)) == 0;
+ return strncmp(Ptr, CommentString.data(), CommentString.size()) == 0;
}
bool AsmLexer::isAtStatementSeparator(const char *Ptr) {
@@ -494,7 +548,7 @@ AsmToken AsmLexer::LexToken() {
// This always consumes at least one character.
int CurChar = getNextChar();
- if (CurChar == '#' && IsAtStartOfStatement) {
+ if (!IsPeeking && CurChar == '#' && IsAtStartOfStatement) {
// If this starts with a '#', this may be a cpp
// hash directive and otherwise a line comment.
AsmToken TokenBuf[2];
@@ -600,7 +654,46 @@ AsmToken AsmLexer::LexToken() {
return AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2));
}
return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1));
- case '%': return AsmToken(AsmToken::Percent, StringRef(TokStart, 1));
+ case '%':
+ if (MAI.hasMipsExpressions()) {
+ AsmToken::TokenKind Operator;
+ unsigned OperatorLength;
+
+ std::tie(Operator, OperatorLength) =
+ StringSwitch<std::pair<AsmToken::TokenKind, unsigned>>(
+ StringRef(CurPtr))
+ .StartsWith("call16", {AsmToken::PercentCall16, 7})
+ .StartsWith("call_hi", {AsmToken::PercentCall_Hi, 8})
+ .StartsWith("call_lo", {AsmToken::PercentCall_Lo, 8})
+ .StartsWith("dtprel_hi", {AsmToken::PercentDtprel_Hi, 10})
+ .StartsWith("dtprel_lo", {AsmToken::PercentDtprel_Lo, 10})
+ .StartsWith("got_disp", {AsmToken::PercentGot_Disp, 9})
+ .StartsWith("got_hi", {AsmToken::PercentGot_Hi, 7})
+ .StartsWith("got_lo", {AsmToken::PercentGot_Lo, 7})
+ .StartsWith("got_ofst", {AsmToken::PercentGot_Ofst, 9})
+ .StartsWith("got_page", {AsmToken::PercentGot_Page, 9})
+ .StartsWith("gottprel", {AsmToken::PercentGottprel, 9})
+ .StartsWith("got", {AsmToken::PercentGot, 4})
+ .StartsWith("gp_rel", {AsmToken::PercentGp_Rel, 7})
+ .StartsWith("higher", {AsmToken::PercentHigher, 7})
+ .StartsWith("highest", {AsmToken::PercentHighest, 8})
+ .StartsWith("hi", {AsmToken::PercentHi, 3})
+ .StartsWith("lo", {AsmToken::PercentLo, 3})
+ .StartsWith("neg", {AsmToken::PercentNeg, 4})
+ .StartsWith("pcrel_hi", {AsmToken::PercentPcrel_Hi, 9})
+ .StartsWith("pcrel_lo", {AsmToken::PercentPcrel_Lo, 9})
+ .StartsWith("tlsgd", {AsmToken::PercentTlsgd, 6})
+ .StartsWith("tlsldm", {AsmToken::PercentTlsldm, 7})
+ .StartsWith("tprel_hi", {AsmToken::PercentTprel_Hi, 9})
+ .StartsWith("tprel_lo", {AsmToken::PercentTprel_Lo, 9})
+ .Default({AsmToken::Percent, 1});
+
+ if (Operator != AsmToken::Percent) {
+ CurPtr += OperatorLength - 1;
+ return AsmToken(Operator, StringRef(TokStart, OperatorLength));
+ }
+ }
+ return AsmToken(AsmToken::Percent, StringRef(TokStart, 1));
case '/':
IsAtStartOfStatement = OldIsAtStartOfStatement;
return LexSlash();
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 1548aee84227..da54155b3b9d 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -12,42 +12,69 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeView.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/AsmCond.h"
#include "llvm/MC/MCParser/AsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCAsmParserUtils.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
#include <cctype>
+#include <cstddef>
+#include <cstdint>
#include <deque>
+#include <memory>
+#include <sstream>
#include <string>
+#include <tuple>
+#include <utility>
#include <vector>
+
using namespace llvm;
MCAsmParserSemaCallback::~MCAsmParserSemaCallback() {}
+static cl::opt<unsigned> AsmMacroMaxNestingDepth(
+ "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,
+ cl::desc("The maximum nesting depth allowed for assembly macros."));
+
namespace {
+
/// \brief Helper types for tracking macro definitions.
typedef std::vector<AsmToken> MCAsmMacroArgument;
typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
@@ -113,6 +140,7 @@ struct ParseStatementInfo {
class AsmParser : public MCAsmParser {
AsmParser(const AsmParser &) = delete;
void operator=(const AsmParser &) = delete;
+
private:
AsmLexer Lexer;
MCContext &Ctx;
@@ -150,9 +178,6 @@ private:
/// \brief Keeps track of how many .macro's have been instantiated.
unsigned NumOfMacroInstantiations;
- /// Flag tracking whether any errors have been encountered.
- unsigned HadError : 1;
-
/// The values from the last parsed cpp hash file line comment if any.
struct CppHashInfoTy {
StringRef Filename;
@@ -206,6 +231,9 @@ public:
MCAsmLexer &getLexer() override { return Lexer; }
MCContext &getContext() override { return Ctx; }
MCStreamer &getStreamer() override { return Out; }
+
+ CodeViewContext &getCVContext() { return Ctx.getCVContext(); }
+
unsigned getAssemblerDialect() override {
if (AssemblerDialect == ~0U)
return MAI.getAssemblerDialect();
@@ -216,16 +244,16 @@ public:
AssemblerDialect = i;
}
- void Note(SMLoc L, const Twine &Msg,
- ArrayRef<SMRange> Ranges = None) override;
- bool Warning(SMLoc L, const Twine &Msg,
- ArrayRef<SMRange> Ranges = None) override;
- bool Error(SMLoc L, const Twine &Msg,
- ArrayRef<SMRange> Ranges = None) override;
+ void Note(SMLoc L, const Twine &Msg, SMRange Range = None) override;
+ bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) override;
+ bool printError(SMLoc L, const Twine &Msg, SMRange Range = None) override;
const AsmToken &Lex() override;
- void setParsingInlineAsm(bool V) override { ParsingInlineAsm = V; }
+ void setParsingInlineAsm(bool V) override {
+ ParsingInlineAsm = V;
+ Lexer.setParsingMSInlineAsm(V);
+ }
bool isParsingInlineAsm() override { return ParsingInlineAsm; }
bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
@@ -244,39 +272,20 @@ public:
SMLoc &EndLoc) override;
bool parseAbsoluteExpression(int64_t &Res) override;
+ /// \brief Parse a floating point expression using the float \p Semantics
+ /// and set \p Res to the value.
+ bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
+
/// \brief Parse an identifier or string (as a quoted identifier)
/// and set \p Res to the identifier contents.
bool parseIdentifier(StringRef &Res) override;
void eatToEndOfStatement() override;
- void checkForValidSection() override;
-
- bool getTokenLoc(SMLoc &Loc) {
- Loc = getTok().getLoc();
- return false;
- }
-
- /// parseToken - If current token has the specified kind, eat it and
- /// return success. Otherwise, emit the specified error and return failure.
- bool parseToken(AsmToken::TokenKind T, const Twine &ErrMsg) {
- if (getTok().getKind() != T)
- return TokError(ErrMsg);
- Lex();
- return false;
- }
-
- bool parseIntToken(int64_t &V, const Twine &ErrMsg) {
- if (getTok().getKind() != AsmToken::Integer)
- return TokError(ErrMsg);
- V = getTok().getIntVal();
- Lex();
- return false;
- }
+ bool checkForValidSection() override;
/// }
private:
-
bool parseStatement(ParseStatementInfo &Info,
MCAsmParserSemaCallback *SI);
bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
@@ -326,29 +335,19 @@ private:
void printMacroInstantiations();
void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
- ArrayRef<SMRange> Ranges = None) const {
+ SMRange Range = None) const {
+ ArrayRef<SMRange> Ranges(Range);
SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
}
static void DiagHandler(const SMDiagnostic &Diag, void *Context);
- bool check(bool P, SMLoc Loc, const Twine &Msg) {
- if (P)
- return Error(Loc, Msg);
- return false;
- }
-
- bool check(bool P, const Twine &Msg) {
- if (P)
- return TokError(Msg);
- return false;
- }
-
/// \brief Enter the specified file. This returns true on failure.
bool enterIncludeFile(const std::string &Filename);
/// \brief Process the specified file for the .incbin directive.
/// This returns true on failure.
- bool processIncbinFile(const std::string &Filename);
+ bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,
+ const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());
/// \brief Reset the current lexer position to that given by \p Loc. The
/// current token is not set; clients should ensure Lex() is called
@@ -379,12 +378,18 @@ private:
bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
+ bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);
+ bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);
+
// Generic (target and platform independent) directive parsing.
enum DirectiveKind {
DK_NO_DIRECTIVE, // Placeholder
DK_SET, DK_EQU, DK_EQUIV, DK_ASCII, DK_ASCIZ, DK_STRING, DK_BYTE, DK_SHORT,
DK_RELOC,
DK_VALUE, DK_2BYTE, DK_LONG, DK_INT, DK_4BYTE, DK_QUAD, DK_8BYTE, DK_OCTA,
+ DK_DC, DK_DC_A, DK_DC_B, DK_DC_D, DK_DC_L, DK_DC_S, DK_DC_W, DK_DC_X,
+ DK_DCB, DK_DCB_B, DK_DCB_D, DK_DCB_L, DK_DCB_S, DK_DCB_W, DK_DCB_X,
+ DK_DS, DK_DS_B, DK_DS_D, DK_DS_L, DK_DS_P, DK_DS_S, DK_DS_W, DK_DS_X,
DK_SINGLE, DK_FLOAT, DK_DOUBLE, DK_ALIGN, DK_ALIGN32, DK_BALIGN, DK_BALIGNW,
DK_BALIGNL, DK_P2ALIGN, DK_P2ALIGNW, DK_P2ALIGNL, DK_ORG, DK_FILL, DK_ENDR,
DK_BUNDLE_ALIGN_MODE, DK_BUNDLE_LOCK, DK_BUNDLE_UNLOCK,
@@ -397,8 +402,9 @@ private:
DK_IFNB, DK_IFC, DK_IFEQS, DK_IFNC, DK_IFNES, DK_IFDEF, DK_IFNDEF,
DK_IFNOTDEF, DK_ELSEIF, DK_ELSE, DK_ENDIF,
DK_SPACE, DK_SKIP, DK_FILE, DK_LINE, DK_LOC, DK_STABS,
- DK_CV_FILE, DK_CV_LOC, DK_CV_LINETABLE, DK_CV_INLINE_LINETABLE,
- DK_CV_DEF_RANGE, DK_CV_STRINGTABLE, DK_CV_FILECHECKSUMS,
+ DK_CV_FILE, DK_CV_FUNC_ID, DK_CV_INLINE_SITE_ID, DK_CV_LOC, DK_CV_LINETABLE,
+ DK_CV_INLINE_LINETABLE, DK_CV_DEF_RANGE, DK_CV_STRINGTABLE,
+ DK_CV_FILECHECKSUMS,
DK_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA,
DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET, DK_CFI_DEF_CFA_REGISTER,
DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, DK_CFI_LSDA,
@@ -419,9 +425,11 @@ private:
// ".ascii", ".asciz", ".string"
bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
- bool parseDirectiveValue(unsigned Size); // ".byte", ".long", ...
- bool parseDirectiveOctaValue(); // ".octa"
- bool parseDirectiveRealValue(const fltSemantics &); // ".single", ...
+ bool parseDirectiveValue(StringRef IDVal,
+ unsigned Size); // ".byte", ".long", ...
+ bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ...
+ bool parseDirectiveRealValue(StringRef IDVal,
+ const fltSemantics &); // ".single", ...
bool parseDirectiveFill(); // ".fill"
bool parseDirectiveZero(); // ".zero"
// ".set", ".equ", ".equiv"
@@ -436,9 +444,11 @@ private:
bool parseDirectiveLoc();
bool parseDirectiveStabs();
- // ".cv_file", ".cv_loc", ".cv_linetable", "cv_inline_linetable",
- // ".cv_def_range"
+ // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
+ // ".cv_inline_linetable", ".cv_def_range"
bool parseDirectiveCVFile();
+ bool parseDirectiveCVFuncId();
+ bool parseDirectiveCVInlineSiteId();
bool parseDirectiveCVLoc();
bool parseDirectiveCVLinetable();
bool parseDirectiveCVInlineLinetable();
@@ -484,6 +494,12 @@ private:
// ".space", ".skip"
bool parseDirectiveSpace(StringRef IDVal);
+ // ".dcb"
+ bool parseDirectiveDCB(StringRef IDVal, unsigned Size);
+ bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &);
+ // ".ds"
+ bool parseDirectiveDS(StringRef IDVal, unsigned Size);
+
// .sleb128 (Signed=true) and .uleb128 (Signed=false)
bool parseDirectiveLEB128(bool Signed);
@@ -542,7 +558,8 @@ private:
void initializeDirectiveKindMap();
};
-}
+
+} // end anonymous namespace
namespace llvm {
@@ -550,7 +567,7 @@ extern MCAsmParserExtension *createDarwinAsmParser();
extern MCAsmParserExtension *createELFAsmParser();
extern MCAsmParserExtension *createCOFFAsmParser();
-}
+} // end namespace llvm
enum { DEFAULT_ADDRSPACE = 0 };
@@ -558,8 +575,9 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
const MCAsmInfo &MAI)
: Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
PlatformParser(nullptr), CurBuffer(SM.getMainFileID()),
- MacrosEnabledFlag(true), HadError(false), CppHashInfo(),
- AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false) {
+ MacrosEnabledFlag(true), CppHashInfo(), AssemblerDialect(~0U),
+ IsDarwin(false), ParsingInlineAsm(false) {
+ HadError = false;
// Save the old handler.
SavedDiagHandler = SrcMgr.getDiagHandler();
SavedDiagContext = SrcMgr.getDiagContext();
@@ -602,24 +620,25 @@ void AsmParser::printMacroInstantiations() {
"while in macro instantiation");
}
-void AsmParser::Note(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) {
- printMessage(L, SourceMgr::DK_Note, Msg, Ranges);
+void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
+ printPendingErrors();
+ printMessage(L, SourceMgr::DK_Note, Msg, Range);
printMacroInstantiations();
}
-bool AsmParser::Warning(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) {
+bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
if(getTargetParser().getTargetOptions().MCNoWarn)
return false;
if (getTargetParser().getTargetOptions().MCFatalWarnings)
- return Error(L, Msg, Ranges);
- printMessage(L, SourceMgr::DK_Warning, Msg, Ranges);
+ return Error(L, Msg, Range);
+ printMessage(L, SourceMgr::DK_Warning, Msg, Range);
printMacroInstantiations();
return false;
}
-bool AsmParser::Error(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) {
+bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
HadError = true;
- printMessage(L, SourceMgr::DK_Error, Msg, Ranges);
+ printMessage(L, SourceMgr::DK_Error, Msg, Range);
printMacroInstantiations();
return true;
}
@@ -639,7 +658,8 @@ bool AsmParser::enterIncludeFile(const std::string &Filename) {
/// Process the specified .incbin file by searching for it in the include paths
/// then just emitting the byte contents of the file to the streamer. This
/// returns true on failure.
-bool AsmParser::processIncbinFile(const std::string &Filename) {
+bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
+ const MCExpr *Count, SMLoc Loc) {
std::string IncludedFile;
unsigned NewBuf =
SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
@@ -647,7 +667,17 @@ bool AsmParser::processIncbinFile(const std::string &Filename) {
return true;
// Pick up the bytes from the file and emit them.
- getStreamer().EmitBytes(SrcMgr.getMemoryBuffer(NewBuf)->getBuffer());
+ StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();
+ Bytes = Bytes.drop_front(Skip);
+ if (Count) {
+ int64_t Res;
+ if (!Count->evaluateAsAbsolute(Res))
+ return Error(Loc, "expected absolute expression");
+ if (Res < 0)
+ return Warning(Loc, "negative count has no effect");
+ Bytes = Bytes.take_front(Res);
+ }
+ getStreamer().EmitBytes(Bytes);
return false;
}
@@ -688,7 +718,6 @@ const AsmToken &AsmParser::Lex() {
}
}
-
return *tok;
}
@@ -706,7 +735,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// If we are generating dwarf for assembly source files save the initial text
// section and generate a .file directive.
if (getContext().getGenDwarfForAssembly()) {
- MCSection *Sec = getStreamer().getCurrentSection().first;
+ MCSection *Sec = getStreamer().getCurrentSectionOnly();
if (!Sec->getBeginSymbol()) {
MCSymbol *SectionStartSym = getContext().createTempSymbol();
getStreamer().EmitLabel(SectionStartSym);
@@ -725,30 +754,38 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
if (!parseStatement(Info, nullptr))
continue;
- // If we've failed, but on a Error Token, but did not consume it in
- // favor of a better message, emit it now.
- if (Lexer.getTok().is(AsmToken::Error)) {
+ // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
+ // for printing ErrMsg via Lex() only if no (presumably better) parser error
+ // exists.
+ if (!hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
Lex();
}
- // We had an error, validate that one was emitted and recover by skipping to
- // the next line.
- assert(HadError && "Parse statement returned an error, but none emitted!");
- eatToEndOfStatement();
+ // parseStatement returned true so may need to emit an error.
+ printPendingErrors();
+
+ // Skipping to the next line if needed.
+ if (!getLexer().isAtStartOfStatement())
+ eatToEndOfStatement();
}
+ // All errors should have been emitted.
+ assert(!hasPendingError() && "unexpected error from parseStatement");
+
+ getTargetParser().flushPendingInstructions(getStreamer());
+
if (TheCondState.TheCond != StartingCondState.TheCond ||
TheCondState.Ignore != StartingCondState.Ignore)
- return TokError("unmatched .ifs or .elses");
-
+ printError(getTok().getLoc(), "unmatched .ifs or .elses");
// Check to see there are no empty DwarfFile slots.
const auto &LineTables = getContext().getMCDwarfLineTables();
if (!LineTables.empty()) {
unsigned Index = 0;
for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {
if (File.Name.empty() && Index != 0)
- TokError("unassigned file number: " + Twine(Index) +
- " for .file directives");
+ printError(getTok().getLoc(), "unassigned file number: " +
+ Twine(Index) +
+ " for .file directives");
++Index;
}
}
@@ -768,9 +805,8 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// FIXME: We would really like to refer back to where the symbol was
// first referenced for a source location. We need to add something
// to track that. Currently, we just point to the end of the file.
- HadError |=
- Error(getTok().getLoc(), "assembler local symbol '" +
- Sym->getName() + "' not defined");
+ printError(getTok().getLoc(), "assembler local symbol '" +
+ Sym->getName() + "' not defined");
}
}
@@ -781,7 +817,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// Reset the state of any "# line file" directives we've seen to the
// context as it was at the diagnostic site.
CppHashInfo = std::get<1>(LocSym);
- HadError |= Error(std::get<0>(LocSym), "directional label undefined");
+ printError(std::get<0>(LocSym), "directional label undefined");
}
}
}
@@ -794,11 +830,13 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
return HadError || getContext().hadError();
}
-void AsmParser::checkForValidSection() {
- if (!ParsingInlineAsm && !getStreamer().getCurrentSection().first) {
- TokError("expected section directive before assembly directive");
+bool AsmParser::checkForValidSection() {
+ if (!ParsingInlineAsm && !getStreamer().getCurrentSectionOnly()) {
Out.InitSections(false);
+ return Error(getTok().getLoc(),
+ "expected section directive before assembly directive");
}
+ return false;
}
/// \brief Throw away the rest of the line for testing purposes.
@@ -888,8 +926,10 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
case AsmToken::Identifier: {
StringRef Identifier;
if (parseIdentifier(Identifier)) {
- if (FirstTokenKind == AsmToken::Dollar) {
+ // We may have failed but $ may be a valid token.
+ if (getTok().is(AsmToken::Dollar)) {
if (Lexer.getMAI().getDollarIsPC()) {
+ Lex();
// This is a '$' reference, which references the current PC. Emit a
// temporary label to the streamer and refer to it.
MCSymbol *Sym = Ctx.createTempSymbol();
@@ -933,6 +973,9 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
// This is a symbol reference.
StringRef SymbolName = Identifier;
+ if (SymbolName.empty())
+ return true;
+
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
// Lookup the symbol variant if used.
@@ -999,7 +1042,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
return false;
}
case AsmToken::Real: {
- APFloat RealVal(APFloat::IEEEdouble, getTok().getString());
+ APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Res = MCConstantExpr::create(IntVal, getContext());
EndLoc = Lexer.getTok().getEndLoc();
@@ -1042,6 +1085,43 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
return true;
Res = MCUnaryExpr::createNot(Res, getContext());
return false;
+ // MIPS unary expression operators. The lexer won't generate these tokens if
+ // MCAsmInfo::HasMipsExpressions is false for the target.
+ case AsmToken::PercentCall16:
+ case AsmToken::PercentCall_Hi:
+ case AsmToken::PercentCall_Lo:
+ case AsmToken::PercentDtprel_Hi:
+ case AsmToken::PercentDtprel_Lo:
+ case AsmToken::PercentGot:
+ case AsmToken::PercentGot_Disp:
+ case AsmToken::PercentGot_Hi:
+ case AsmToken::PercentGot_Lo:
+ case AsmToken::PercentGot_Ofst:
+ case AsmToken::PercentGot_Page:
+ case AsmToken::PercentGottprel:
+ case AsmToken::PercentGp_Rel:
+ case AsmToken::PercentHi:
+ case AsmToken::PercentHigher:
+ case AsmToken::PercentHighest:
+ case AsmToken::PercentLo:
+ case AsmToken::PercentNeg:
+ case AsmToken::PercentPcrel_Hi:
+ case AsmToken::PercentPcrel_Lo:
+ case AsmToken::PercentTlsgd:
+ case AsmToken::PercentTlsldm:
+ case AsmToken::PercentTprel_Hi:
+ case AsmToken::PercentTprel_Lo:
+ Lex(); // Eat the operator.
+ if (Lexer.isNot(AsmToken::LParen))
+ return TokError("expected '(' after operator");
+ Lex(); // Eat the operator.
+ if (parseExpression(Res, EndLoc))
+ return true;
+ if (Lexer.isNot(AsmToken::RParen))
+ return TokError("expected ')'");
+ Lex(); // Eat the operator.
+ Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
+ return !Res;
}
}
@@ -1356,7 +1436,7 @@ unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
/// Res contains the LHS of the expression on input.
bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
SMLoc &EndLoc) {
- while (1) {
+ while (true) {
MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
@@ -1390,6 +1470,7 @@ bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
/// ::= Label* Identifier OperandList* EndOfStatement
bool AsmParser::parseStatement(ParseStatementInfo &Info,
MCAsmParserSemaCallback *SI) {
+ assert(!hasPendingError() && "parseStatement started with pending error");
// Eat initial spaces and comments
while (Lexer.is(AsmToken::Space))
Lex();
@@ -1401,6 +1482,16 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
Lex();
return false;
}
+ if (Lexer.is(AsmToken::Hash)) {
+ // Seeing a hash here means that it was an end-of-line comment in
+ // an asm syntax where hash's are not comment and the previous
+ // statement parser did not check the end of statement. Relex as
+ // EndOfStatement.
+ StringRef CommentStr = parseStringToEndOfStatement();
+ Lexer.Lex();
+ Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
+ return false;
+ }
// Statements always start with an identifier.
AsmToken ID = getTok();
SMLoc IDLoc = ID.getLoc();
@@ -1412,15 +1503,19 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
if (Lexer.is(AsmToken::Integer)) {
LocalLabelVal = getTok().getIntVal();
if (LocalLabelVal < 0) {
- if (!TheCondState.Ignore)
- return TokError("unexpected token at start of statement");
+ if (!TheCondState.Ignore) {
+ Lex(); // always eat a token
+ return Error(IDLoc, "unexpected token at start of statement");
+ }
IDVal = "";
} else {
IDVal = getTok().getString();
Lex(); // Consume the integer token to be used as an identifier token.
if (Lexer.getKind() != AsmToken::Colon) {
- if (!TheCondState.Ignore)
- return TokError("unexpected token at start of statement");
+ if (!TheCondState.Ignore) {
+ Lex(); // always eat a token
+ return Error(IDLoc, "unexpected token at start of statement");
+ }
}
}
} else if (Lexer.is(AsmToken::Dot)) {
@@ -1437,8 +1532,10 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
Lex();
IDVal = "}";
} else if (parseIdentifier(IDVal)) {
- if (!TheCondState.Ignore)
- return TokError("unexpected token at start of statement");
+ if (!TheCondState.Ignore) {
+ Lex(); // always eat a token
+ return Error(IDLoc, "unexpected token at start of statement");
+ }
IDVal = "";
}
@@ -1500,7 +1597,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
case AsmToken::Colon: {
if (!getTargetParser().isLabel(ID))
break;
- checkForValidSection();
+ if (checkForValidSection())
+ return true;
// identifier ':' -> Label.
Lex();
@@ -1534,6 +1632,16 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
if (!Sym->isUndefined() || Sym->isVariable())
return Error(IDLoc, "invalid symbol redefinition");
+ // End of Labels should be treated as end of line for lexing
+ // purposes but that information is not available to the Lexer who
+ // does not understand Labels. This may cause us to see a Hash
+ // here instead of a preprocessor line comment.
+ if (getTok().is(AsmToken::Hash)) {
+ StringRef CommentStr = parseStringToEndOfStatement();
+ Lexer.Lex();
+ Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
+ }
+
// Consume any end of statement token, if present, to avoid spurious
// AddBlankLine calls().
if (getTok().is(AsmToken::EndOfStatement)) {
@@ -1552,8 +1660,6 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
getTargetParser().onLabelParsed(Sym);
-
-
return false;
}
@@ -1590,9 +1696,22 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
// manner, or at least have a default behavior that's shared between
// all targets and platforms.
- // First query the target-specific parser. It will return 'true' if it
- // isn't interested in this directive.
- if (!getTargetParser().ParseDirective(ID))
+ getTargetParser().flushPendingInstructions(getStreamer());
+
+ SMLoc StartTokLoc = getTok().getLoc();
+ bool TPDirectiveReturn = getTargetParser().ParseDirective(ID);
+
+ if (hasPendingError())
+ return true;
+ // Currently the return value should be true if we are
+ // uninterested but as this is at odds with the standard parsing
+ // convention (return true = error) we have instances of a parsed
+ // directive that fails returning true as an error. Catch these
+ // cases as best as possible errors here.
+ if (TPDirectiveReturn && StartTokLoc != getTok().getLoc())
+ return true;
+ // Return if we did some parsing or believe we succeeded.
+ if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc())
return false;
// Next, check the extension directive map to see if any extension has
@@ -1618,25 +1737,34 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
case DK_STRING:
return parseDirectiveAscii(IDVal, true);
case DK_BYTE:
- return parseDirectiveValue(1);
+ case DK_DC_B:
+ return parseDirectiveValue(IDVal, 1);
+ case DK_DC:
+ case DK_DC_W:
case DK_SHORT:
case DK_VALUE:
case DK_2BYTE:
- return parseDirectiveValue(2);
+ return parseDirectiveValue(IDVal, 2);
case DK_LONG:
case DK_INT:
case DK_4BYTE:
- return parseDirectiveValue(4);
+ case DK_DC_L:
+ return parseDirectiveValue(IDVal, 4);
case DK_QUAD:
case DK_8BYTE:
- return parseDirectiveValue(8);
+ return parseDirectiveValue(IDVal, 8);
+ case DK_DC_A:
+ return parseDirectiveValue(IDVal,
+ getContext().getAsmInfo()->getPointerSize());
case DK_OCTA:
- return parseDirectiveOctaValue();
+ return parseDirectiveOctaValue(IDVal);
case DK_SINGLE:
case DK_FLOAT:
- return parseDirectiveRealValue(APFloat::IEEEsingle);
+ case DK_DC_S:
+ return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());
case DK_DOUBLE:
- return parseDirectiveRealValue(APFloat::IEEEdouble);
+ case DK_DC_D:
+ return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());
case DK_ALIGN: {
bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);
@@ -1731,6 +1859,10 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectiveStabs();
case DK_CV_FILE:
return parseDirectiveCVFile();
+ case DK_CV_FUNC_ID:
+ return parseDirectiveCVFuncId();
+ case DK_CV_INLINE_SITE_ID:
+ return parseDirectiveCVInlineSiteId();
case DK_CV_LOC:
return parseDirectiveCVLoc();
case DK_CV_LINETABLE:
@@ -1805,6 +1937,34 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectiveWarning(IDLoc);
case DK_RELOC:
return parseDirectiveReloc(IDLoc);
+ case DK_DCB:
+ case DK_DCB_W:
+ return parseDirectiveDCB(IDVal, 2);
+ case DK_DCB_B:
+ return parseDirectiveDCB(IDVal, 1);
+ case DK_DCB_D:
+ return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble());
+ case DK_DCB_L:
+ return parseDirectiveDCB(IDVal, 4);
+ case DK_DCB_S:
+ return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle());
+ case DK_DC_X:
+ case DK_DCB_X:
+ return TokError(Twine(IDVal) +
+ " not currently supported for this target");
+ case DK_DS:
+ case DK_DS_W:
+ return parseDirectiveDS(IDVal, 2);
+ case DK_DS_B:
+ return parseDirectiveDS(IDVal, 1);
+ case DK_DS_D:
+ return parseDirectiveDS(IDVal, 8);
+ case DK_DS_L:
+ case DK_DS_S:
+ return parseDirectiveDS(IDVal, 4);
+ case DK_DS_P:
+ case DK_DS_X:
+ return parseDirectiveDS(IDVal, 12);
}
return Error(IDLoc, "unknown directive");
@@ -1821,14 +1981,15 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
if (ParsingInlineAsm && (IDVal == "even"))
Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
- checkForValidSection();
+ if (checkForValidSection())
+ return true;
// Canonicalize the opcode to lower case.
std::string OpcodeStr = IDVal.lower();
ParseInstructionInfo IInfo(Info.AsmRewrites);
- bool HadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
- Info.ParsedOperands);
- Info.ParseError = HadError;
+ bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
+ Info.ParsedOperands);
+ Info.ParseError = ParseHadError;
// Dump the parsed representation, if requested.
if (getShowParsedOperands()) {
@@ -1845,11 +2006,15 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
}
+ // Fail even if ParseInstruction erroneously returns false.
+ if (hasPendingError() || ParseHadError)
+ return true;
+
// If we are generating dwarf for the current section then generate a .loc
// directive for the instruction.
- if (!HadError && getContext().getGenDwarfForAssembly() &&
+ if (!ParseHadError && getContext().getGenDwarfForAssembly() &&
getContext().getGenDwarfSectionSyms().count(
- getStreamer().getCurrentSection().first)) {
+ getStreamer().getCurrentSectionOnly())) {
unsigned Line;
if (ActiveMacros.empty())
Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
@@ -1889,15 +2054,13 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
}
// If parsing succeeded, match the instruction.
- if (!HadError) {
+ if (!ParseHadError) {
uint64_t ErrorInfo;
- getTargetParser().MatchAndEmitInstruction(IDLoc, Info.Opcode,
- Info.ParsedOperands, Out,
- ErrorInfo, ParsingInlineAsm);
+ if (getTargetParser().MatchAndEmitInstruction(IDLoc, Info.Opcode,
+ Info.ParsedOperands, Out,
+ ErrorInfo, ParsingInlineAsm))
+ return true;
}
-
- // Don't skip the rest of the line, the instruction parser is responsible for
- // that.
return false;
}
@@ -1933,6 +2096,7 @@ bool AsmParser::parseCppHashLineFilenameComment(SMLoc L) {
"Lexing Cpp line comment: Expected String");
StringRef Filename = getTok().getString();
Lex();
+
// Get rid of the enclosing quotes.
Filename = Filename.substr(1, Filename.size() - 2);
@@ -2158,6 +2322,7 @@ static bool isOperator(AsmToken::TokenKind kind) {
}
namespace {
+
class AsmLexerSkipSpaceRAII {
public:
AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
@@ -2171,7 +2336,8 @@ public:
private:
AsmLexer &Lexer;
};
-}
+
+} // end anonymous namespace
bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
@@ -2190,7 +2356,7 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
bool SpaceEaten;
- for (;;) {
+ while (true) {
SpaceEaten = false;
if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
return TokError("unexpected token in macro instantiation");
@@ -2265,27 +2431,19 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
MCAsmMacroParameter FA;
if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
- if (parseIdentifier(FA.Name)) {
- Error(IDLoc, "invalid argument identifier for formal argument");
- eatToEndOfStatement();
- return true;
- }
+ if (parseIdentifier(FA.Name))
+ return Error(IDLoc, "invalid argument identifier for formal argument");
+
+ if (Lexer.isNot(AsmToken::Equal))
+ return TokError("expected '=' after formal parameter identifier");
- if (Lexer.isNot(AsmToken::Equal)) {
- TokError("expected '=' after formal parameter identifier");
- eatToEndOfStatement();
- return true;
- }
Lex();
NamedParametersFound = true;
}
- if (NamedParametersFound && FA.Name.empty()) {
- Error(IDLoc, "cannot mix positional and keyword arguments");
- eatToEndOfStatement();
- return true;
- }
+ if (NamedParametersFound && FA.Name.empty())
+ return Error(IDLoc, "cannot mix positional and keyword arguments");
bool Vararg = HasVararg && Parameter == (NParameters - 1);
if (parseMacroArgument(FA.Value, Vararg))
@@ -2300,10 +2458,8 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
if (FAI >= NParameters) {
assert(M && "expected macro to be defined");
- Error(IDLoc,
- "parameter named '" + FA.Name + "' does not exist for macro '" +
- M->Name + "'");
- return true;
+ return Error(IDLoc, "parameter named '" + FA.Name +
+ "' does not exist for macro '" + M->Name + "'");
}
PI = FAI;
}
@@ -2359,10 +2515,17 @@ void AsmParser::defineMacro(StringRef Name, MCAsmMacro Macro) {
void AsmParser::undefineMacro(StringRef Name) { MacroMap.erase(Name); }
bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
- // Arbitrarily limit macro nesting depth, to match 'as'. We can eliminate
- // this, although we should protect against infinite loops.
- if (ActiveMacros.size() == 20)
- return TokError("macros cannot be nested more than 20 levels deep");
+ // Arbitrarily limit macro nesting depth (default matches 'as'). We can
+ // eliminate this, although we should protect against infinite loops.
+ unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
+ if (ActiveMacros.size() == MaxNestingDepth) {
+ std::ostringstream MaxNestingDepthError;
+ MaxNestingDepthError << "macros cannot be nested more than "
+ << MaxNestingDepth << " levels deep."
+ << " Use -asm-macro-max-nesting-depth to increase "
+ "this limit.";
+ return TokError(MaxNestingDepthError.str());
+ }
MCAsmMacroArguments A;
if (parseMacroArguments(M, A))
@@ -2446,14 +2609,19 @@ bool AsmParser::parseIdentifier(StringRef &Res) {
SMLoc PrefixLoc = getLexer().getLoc();
// Consume the prefix character, and check for a following identifier.
- Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
- if (Lexer.isNot(AsmToken::Identifier))
+
+ AsmToken Buf[1];
+ Lexer.peekTokens(Buf, false);
+
+ if (Buf[0].isNot(AsmToken::Identifier))
return true;
// We have a '$' or '@' followed by an identifier, make sure they are adjacent.
- if (PrefixLoc.getPointer() + 1 != getTok().getLoc().getPointer())
+ if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())
return true;
+ // eat $ or @
+ Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
// Construct the joined identifier and consume the token.
Res =
StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1);
@@ -2477,17 +2645,15 @@ bool AsmParser::parseIdentifier(StringRef &Res) {
/// ::= .set identifier ',' expression
bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) {
StringRef Name;
-
- if (check(parseIdentifier(Name),
- "expected identifier after '" + Twine(IDVal) + "'") ||
- parseToken(AsmToken::Comma, "unexpected token in '" + Twine(IDVal) + "'"))
- return true;
-
- return parseAssignment(Name, allow_redef, true);
+ if (check(parseIdentifier(Name), "expected identifier") ||
+ parseToken(AsmToken::Comma) || parseAssignment(Name, allow_redef, true))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ return false;
}
bool AsmParser::parseEscapedString(std::string &Data) {
- assert(getLexer().is(AsmToken::String) && "Unexpected current token!");
+ if (check(getTok().isNot(AsmToken::String), "expected string"))
+ return true;
Data = "";
StringRef Str = getTok().getStringContents();
@@ -2548,30 +2714,18 @@ bool AsmParser::parseEscapedString(std::string &Data) {
/// parseDirectiveAscii:
/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- checkForValidSection();
-
- for (;;) {
- std::string Data;
- if (check(getTok().isNot(AsmToken::String),
- "expected string in '" + Twine(IDVal) + "' directive") ||
- parseEscapedString(Data))
- return true;
-
- getStreamer().EmitBytes(Data);
- if (ZeroTerminated)
- getStreamer().EmitBytes(StringRef("\0", 1));
-
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
-
- if (parseToken(AsmToken::Comma,
- "unexpected token in '" + Twine(IDVal) + "' directive"))
- return true;
- }
- }
+ auto parseOp = [&]() -> bool {
+ std::string Data;
+ if (checkForValidSection() || parseEscapedString(Data))
+ return true;
+ getStreamer().EmitBytes(Data);
+ if (ZeroTerminated)
+ getStreamer().EmitBytes(StringRef("\0", 1));
+ return false;
+ };
- Lex();
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
return false;
}
@@ -2582,11 +2736,12 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
const MCExpr *Expr = nullptr;
SMLoc OffsetLoc = Lexer.getTok().getLoc();
+ int64_t OffsetValue;
+ // We can only deal with constant expressions at the moment.
+
if (parseExpression(Offset))
return true;
- // We can only deal with constant expressions at the moment.
- int64_t OffsetValue;
if (check(!Offset->evaluateAsAbsolute(OffsetValue), OffsetLoc,
"expression is not a constant value") ||
check(OffsetValue < 0, OffsetLoc, "expression is negative") ||
@@ -2610,162 +2765,141 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
}
if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in .reloc directive") ||
- check(getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc),
- NameLoc, "unknown relocation name"))
- return true;
+ "unexpected token in .reloc directive"))
+ return true;
+
+ if (getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc))
+ return Error(NameLoc, "unknown relocation name");
+
return false;
}
/// parseDirectiveValue
/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
-bool AsmParser::parseDirectiveValue(unsigned Size) {
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- checkForValidSection();
-
- for (;;) {
- const MCExpr *Value;
- SMLoc ExprLoc = getLexer().getLoc();
- if (parseExpression(Value))
- return true;
-
- // Special case constant expressions to match code generator.
- if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
- assert(Size <= 8 && "Invalid size");
- uint64_t IntValue = MCE->getValue();
- if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
- return Error(ExprLoc, "literal value out of range for directive");
- getStreamer().EmitIntValue(IntValue, Size);
- } else
- getStreamer().EmitValue(Value, Size, ExprLoc);
-
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
-
- // FIXME: Improve diagnostic.
- if (parseToken(AsmToken::Comma, "unexpected token in directive"))
- return true;
- }
- }
+bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
+ auto parseOp = [&]() -> bool {
+ const MCExpr *Value;
+ SMLoc ExprLoc = getLexer().getLoc();
+ if (checkForValidSection() || parseExpression(Value))
+ return true;
+ // Special case constant expressions to match code generator.
+ if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
+ assert(Size <= 8 && "Invalid size");
+ uint64_t IntValue = MCE->getValue();
+ if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
+ return Error(ExprLoc, "out of range literal value");
+ getStreamer().EmitIntValue(IntValue, Size);
+ } else
+ getStreamer().EmitValue(Value, Size, ExprLoc);
+ return false;
+ };
- Lex();
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
return false;
}
/// ParseDirectiveOctaValue
/// ::= .octa [ hexconstant (, hexconstant)* ]
-bool AsmParser::parseDirectiveOctaValue() {
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- checkForValidSection();
-
- for (;;) {
- if (getTok().is(AsmToken::Error))
- return true;
- if (getTok().isNot(AsmToken::Integer) && getTok().isNot(AsmToken::BigNum))
- return TokError("unknown token in expression");
- SMLoc ExprLoc = getLexer().getLoc();
- APInt IntValue = getTok().getAPIntVal();
- Lex();
+bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
+ auto parseOp = [&]() -> bool {
+ if (checkForValidSection())
+ return true;
+ if (getTok().isNot(AsmToken::Integer) && getTok().isNot(AsmToken::BigNum))
+ return TokError("unknown token in expression");
+ SMLoc ExprLoc = getTok().getLoc();
+ APInt IntValue = getTok().getAPIntVal();
+ uint64_t hi, lo;
+ Lex();
+ if (!IntValue.isIntN(128))
+ return Error(ExprLoc, "out of range literal value");
+ if (!IntValue.isIntN(64)) {
+ hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
+ lo = IntValue.getLoBits(64).getZExtValue();
+ } else {
+ hi = 0;
+ lo = IntValue.getZExtValue();
+ }
+ if (MAI.isLittleEndian()) {
+ getStreamer().EmitIntValue(lo, 8);
+ getStreamer().EmitIntValue(hi, 8);
+ } else {
+ getStreamer().EmitIntValue(hi, 8);
+ getStreamer().EmitIntValue(lo, 8);
+ }
+ return false;
+ };
- uint64_t hi, lo;
- if (IntValue.isIntN(64)) {
- hi = 0;
- lo = IntValue.getZExtValue();
- } else if (IntValue.isIntN(128)) {
- // It might actually have more than 128 bits, but the top ones are zero.
- hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
- lo = IntValue.getLoBits(64).getZExtValue();
- } else
- return Error(ExprLoc, "literal value out of range for directive");
-
- if (MAI.isLittleEndian()) {
- getStreamer().EmitIntValue(lo, 8);
- getStreamer().EmitIntValue(hi, 8);
- } else {
- getStreamer().EmitIntValue(hi, 8);
- getStreamer().EmitIntValue(lo, 8);
- }
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ return false;
+}
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
+bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
+ // We don't truly support arithmetic on floating point expressions, so we
+ // have to manually parse unary prefixes.
+ bool IsNeg = false;
+ if (getLexer().is(AsmToken::Minus)) {
+ Lexer.Lex();
+ IsNeg = true;
+ } else if (getLexer().is(AsmToken::Plus))
+ Lexer.Lex();
- // FIXME: Improve diagnostic.
- if (parseToken(AsmToken::Comma, "unexpected token in directive"))
- return true;
- }
- }
+ if (Lexer.is(AsmToken::Error))
+ return TokError(Lexer.getErr());
+ if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
+ Lexer.isNot(AsmToken::Identifier))
+ return TokError("unexpected token in directive");
+ // Convert to an APFloat.
+ APFloat Value(Semantics);
+ StringRef IDVal = getTok().getString();
+ if (getLexer().is(AsmToken::Identifier)) {
+ if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf"))
+ Value = APFloat::getInf(Semantics);
+ else if (!IDVal.compare_lower("nan"))
+ Value = APFloat::getNaN(Semantics, false, ~0);
+ else
+ return TokError("invalid floating point literal");
+ } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) ==
+ APFloat::opInvalidOp)
+ return TokError("invalid floating point literal");
+ if (IsNeg)
+ Value.changeSign();
+
+ // Consume the numeric token.
Lex();
+
+ Res = Value.bitcastToAPInt();
+
return false;
}
/// parseDirectiveRealValue
/// ::= (.single | .double) [ expression (, expression)* ]
-bool AsmParser::parseDirectiveRealValue(const fltSemantics &Semantics) {
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- checkForValidSection();
-
- for (;;) {
- // We don't truly support arithmetic on floating point expressions, so we
- // have to manually parse unary prefixes.
- bool IsNeg = false;
- if (getLexer().is(AsmToken::Minus)) {
- Lexer.Lex();
- IsNeg = true;
- } else if (getLexer().is(AsmToken::Plus))
- Lexer.Lex();
-
- if (Lexer.is(AsmToken::Error))
- return TokError(Lexer.getErr());
- if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
- Lexer.isNot(AsmToken::Identifier))
- return TokError("unexpected token in directive");
-
- // Convert to an APFloat.
- APFloat Value(Semantics);
- StringRef IDVal = getTok().getString();
- if (getLexer().is(AsmToken::Identifier)) {
- if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf"))
- Value = APFloat::getInf(Semantics);
- else if (!IDVal.compare_lower("nan"))
- Value = APFloat::getNaN(Semantics, false, ~0);
- else
- return TokError("invalid floating point literal");
- } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) ==
- APFloat::opInvalidOp)
- return TokError("invalid floating point literal");
- if (IsNeg)
- Value.changeSign();
-
- // Consume the numeric token.
- Lex();
-
- // Emit the value as an integer.
- APInt AsInt = Value.bitcastToAPInt();
- getStreamer().EmitIntValue(AsInt.getLimitedValue(),
- AsInt.getBitWidth() / 8);
-
- if (Lexer.is(AsmToken::EndOfStatement))
- break;
-
- if (parseToken(AsmToken::Comma, "unexpected token in directive"))
- return true;
- }
- }
+bool AsmParser::parseDirectiveRealValue(StringRef IDVal,
+ const fltSemantics &Semantics) {
+ auto parseOp = [&]() -> bool {
+ APInt AsInt;
+ if (checkForValidSection() || parseRealValue(Semantics, AsInt))
+ return true;
+ getStreamer().EmitIntValue(AsInt.getLimitedValue(),
+ AsInt.getBitWidth() / 8);
+ return false;
+ };
- Lex();
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
return false;
}
/// parseDirectiveZero
/// ::= .zero expression
bool AsmParser::parseDirectiveZero() {
- checkForValidSection();
-
SMLoc NumBytesLoc = Lexer.getLoc();
const MCExpr *NumBytes;
- if (parseExpression(NumBytes))
+ if (checkForValidSection() || parseExpression(NumBytes))
return true;
int64_t Val = 0;
@@ -2786,32 +2920,29 @@ bool AsmParser::parseDirectiveZero() {
/// parseDirectiveFill
/// ::= .fill expression [ , expression [ , expression ] ]
bool AsmParser::parseDirectiveFill() {
- checkForValidSection();
-
SMLoc NumValuesLoc = Lexer.getLoc();
const MCExpr *NumValues;
- if (parseExpression(NumValues))
+ if (checkForValidSection() || parseExpression(NumValues))
return true;
int64_t FillSize = 1;
int64_t FillExpr = 0;
SMLoc SizeLoc, ExprLoc;
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- if (parseToken(AsmToken::Comma, "unexpected token in '.fill' directive") ||
- getTokenLoc(SizeLoc) || parseAbsoluteExpression(FillSize))
+ if (parseOptionalToken(AsmToken::Comma)) {
+ SizeLoc = getTok().getLoc();
+ if (parseAbsoluteExpression(FillSize))
return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- if (parseToken(AsmToken::Comma,
- "unexpected token in '.fill' directive") ||
- getTokenLoc(ExprLoc) || parseAbsoluteExpression(FillExpr) ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.fill' directive"))
+ if (parseOptionalToken(AsmToken::Comma)) {
+ ExprLoc = getTok().getLoc();
+ if (parseAbsoluteExpression(FillExpr))
return true;
}
}
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.fill' directive"))
+ return true;
if (FillSize < 0) {
Warning(SizeLoc, "'.fill' directive with negative size has no effect");
@@ -2833,73 +2964,64 @@ bool AsmParser::parseDirectiveFill() {
/// parseDirectiveOrg
/// ::= .org expression [ , expression ]
bool AsmParser::parseDirectiveOrg() {
- checkForValidSection();
-
const MCExpr *Offset;
- if (parseExpression(Offset))
+ SMLoc OffsetLoc = Lexer.getLoc();
+ if (checkForValidSection() || parseExpression(Offset))
return true;
// Parse optional fill expression.
int64_t FillExpr = 0;
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- if (parseToken(AsmToken::Comma, "unexpected token in '.org' directive") ||
- parseAbsoluteExpression(FillExpr))
- return true;
- }
+ if (parseOptionalToken(AsmToken::Comma))
+ if (parseAbsoluteExpression(FillExpr))
+ return addErrorSuffix(" in '.org' directive");
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '.org' directive");
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.org' directive"))
- return true;
-
- getStreamer().emitValueToOffset(Offset, FillExpr);
+ getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
return false;
}
/// parseDirectiveAlign
/// ::= {.align, ...} expression [ , expression [ , expression ]]
bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
- checkForValidSection();
-
SMLoc AlignmentLoc = getLexer().getLoc();
int64_t Alignment;
- if (parseAbsoluteExpression(Alignment))
- return true;
-
SMLoc MaxBytesLoc;
bool HasFillExpr = false;
int64_t FillExpr = 0;
int64_t MaxBytesToFill = 0;
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- if (parseToken(AsmToken::Comma, "unexpected token in directive"))
- return true;
-
- // The fill expression can be omitted while specifying a maximum number of
- // alignment bytes, e.g:
- // .align 3,,4
- if (getTok().isNot(AsmToken::Comma)) {
- HasFillExpr = true;
- if (parseAbsoluteExpression(FillExpr))
- return true;
- }
- if (getTok().isNot(AsmToken::EndOfStatement)) {
- if (parseToken(AsmToken::Comma, "unexpected token in directive") ||
- getTokenLoc(MaxBytesLoc) || parseAbsoluteExpression(MaxBytesToFill))
- return true;
+ auto parseAlign = [&]() -> bool {
+ if (checkForValidSection() || parseAbsoluteExpression(Alignment))
+ return true;
+ if (parseOptionalToken(AsmToken::Comma)) {
+ // The fill expression can be omitted while specifying a maximum number of
+ // alignment bytes, e.g:
+ // .align 3,,4
+ if (getTok().isNot(AsmToken::Comma)) {
+ HasFillExpr = true;
+ if (parseAbsoluteExpression(FillExpr))
+ return true;
+ }
+ if (parseOptionalToken(AsmToken::Comma))
+ if (parseTokenLoc(MaxBytesLoc) ||
+ parseAbsoluteExpression(MaxBytesToFill))
+ return true;
}
- }
+ return parseToken(AsmToken::EndOfStatement);
+ };
- if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
- return true;
+ if (parseAlign())
+ return addErrorSuffix(" in directive");
- if (!HasFillExpr)
- FillExpr = 0;
+ // Always emit an alignment here even if we thrown an error.
+ bool ReturnVal = false;
// Compute alignment in bytes.
if (IsPow2) {
// FIXME: Diagnose overflow.
if (Alignment >= 32) {
- Error(AlignmentLoc, "invalid alignment value");
+ ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
Alignment = 31;
}
@@ -2911,13 +3033,14 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
if (Alignment == 0)
Alignment = 1;
if (!isPowerOf2_64(Alignment))
- Error(AlignmentLoc, "alignment must be a power of 2");
+ ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
}
// Diagnose non-sensical max bytes to align.
if (MaxBytesLoc.isValid()) {
if (MaxBytesToFill < 1) {
- Error(MaxBytesLoc, "alignment directive can never be satisfied in this "
+ ReturnVal |= Error(MaxBytesLoc,
+ "alignment directive can never be satisfied in this "
"many bytes, ignoring maximum bytes expression");
MaxBytesToFill = 0;
}
@@ -2931,7 +3054,7 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
// Check whether we should use optimal code alignment for this .align
// directive.
- const MCSection *Section = getStreamer().getCurrentSection().first;
+ const MCSection *Section = getStreamer().getCurrentSectionOnly();
assert(Section && "must have section to emit alignment");
bool UseCodeAlign = Section->UseCodeAlign();
if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
@@ -2943,7 +3066,7 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
MaxBytesToFill);
}
- return false;
+ return ReturnVal;
}
/// parseDirectiveFile
@@ -2997,7 +3120,7 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
getContext().setGenDwarfForAssembly(false);
else if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename) ==
0)
- Error(FileNumberLoc, "file number already allocated");
+ return Error(FileNumberLoc, "file number already allocated");
}
return false;
@@ -3007,7 +3130,7 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
/// ::= .line [number]
bool AsmParser::parseDirectiveLine() {
int64_t LineNumber;
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ if (getLexer().is(AsmToken::Integer)) {
if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
return true;
(void)LineNumber;
@@ -3056,65 +3179,61 @@ bool AsmParser::parseDirectiveLoc() {
unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
unsigned Isa = 0;
int64_t Discriminator = 0;
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- for (;;) {
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
- StringRef Name;
- SMLoc Loc = getTok().getLoc();
- if (parseIdentifier(Name))
- return TokError("unexpected token in '.loc' directive");
-
- if (Name == "basic_block")
- Flags |= DWARF2_FLAG_BASIC_BLOCK;
- else if (Name == "prologue_end")
- Flags |= DWARF2_FLAG_PROLOGUE_END;
- else if (Name == "epilogue_begin")
- Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
- else if (Name == "is_stmt") {
- Loc = getTok().getLoc();
- const MCExpr *Value;
- if (parseExpression(Value))
- return true;
- // The expression must be the constant 0 or 1.
- if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
- int Value = MCE->getValue();
- if (Value == 0)
- Flags &= ~DWARF2_FLAG_IS_STMT;
- else if (Value == 1)
- Flags |= DWARF2_FLAG_IS_STMT;
- else
- return Error(Loc, "is_stmt value not 0 or 1");
- } else {
- return Error(Loc, "is_stmt value not the constant value of 0 or 1");
- }
- } else if (Name == "isa") {
- Loc = getTok().getLoc();
- const MCExpr *Value;
- if (parseExpression(Value))
- return true;
- // The expression must be a constant greater or equal to 0.
- if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
- int Value = MCE->getValue();
- if (Value < 0)
- return Error(Loc, "isa number less than zero");
- Isa = Value;
- } else {
- return Error(Loc, "isa number not a constant value");
- }
- } else if (Name == "discriminator") {
- if (parseAbsoluteExpression(Discriminator))
- return true;
+ auto parseLocOp = [&]() -> bool {
+ StringRef Name;
+ SMLoc Loc = getTok().getLoc();
+ if (parseIdentifier(Name))
+ return TokError("unexpected token in '.loc' directive");
+
+ if (Name == "basic_block")
+ Flags |= DWARF2_FLAG_BASIC_BLOCK;
+ else if (Name == "prologue_end")
+ Flags |= DWARF2_FLAG_PROLOGUE_END;
+ else if (Name == "epilogue_begin")
+ Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
+ else if (Name == "is_stmt") {
+ Loc = getTok().getLoc();
+ const MCExpr *Value;
+ if (parseExpression(Value))
+ return true;
+ // The expression must be the constant 0 or 1.
+ if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
+ int Value = MCE->getValue();
+ if (Value == 0)
+ Flags &= ~DWARF2_FLAG_IS_STMT;
+ else if (Value == 1)
+ Flags |= DWARF2_FLAG_IS_STMT;
+ else
+ return Error(Loc, "is_stmt value not 0 or 1");
} else {
- return Error(Loc, "unknown sub-directive in '.loc' directive");
+ return Error(Loc, "is_stmt value not the constant value of 0 or 1");
}
-
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
+ } else if (Name == "isa") {
+ Loc = getTok().getLoc();
+ const MCExpr *Value;
+ if (parseExpression(Value))
+ return true;
+ // The expression must be a constant greater or equal to 0.
+ if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
+ int Value = MCE->getValue();
+ if (Value < 0)
+ return Error(Loc, "isa number less than zero");
+ Isa = Value;
+ } else {
+ return Error(Loc, "isa number not a constant value");
+ }
+ } else if (Name == "discriminator") {
+ if (parseAbsoluteExpression(Discriminator))
+ return true;
+ } else {
+ return Error(Loc, "unknown sub-directive in '.loc' directive");
}
- }
- Lex();
+ return false;
+ };
+
+ if (parseMany(parseLocOp, false /*hasComma*/))
+ return true;
getStreamer().EmitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
Isa, Discriminator, StringRef());
@@ -3144,11 +3263,113 @@ bool AsmParser::parseDirectiveCVFile() {
// directory. Allow the strings to have escaped octal character sequence.
parseEscapedString(Filename) ||
parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.cv_file' directive") ||
- check(getStreamer().EmitCVFileDirective(FileNumber, Filename) == 0,
- FileNumberLoc, "file number already allocated"))
+ "unexpected token in '.cv_file' directive"))
return true;
+ if (!getStreamer().EmitCVFileDirective(FileNumber, Filename))
+ return Error(FileNumberLoc, "file number already allocated");
+
+ return false;
+}
+
+bool AsmParser::parseCVFunctionId(int64_t &FunctionId,
+ StringRef DirectiveName) {
+ SMLoc Loc;
+ return parseTokenLoc(Loc) ||
+ parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
+ "' directive") ||
+ check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
+ "expected function id within range [0, UINT_MAX)");
+}
+
+bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
+ SMLoc Loc;
+ return parseTokenLoc(Loc) ||
+ parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
+ "' directive") ||
+ check(FileNumber < 1, Loc, "file number less than one in '" +
+ DirectiveName + "' directive") ||
+ check(!getCVContext().isValidFileNumber(FileNumber), Loc,
+ "unassigned file number in '" + DirectiveName + "' directive");
+}
+
+/// parseDirectiveCVFuncId
+/// ::= .cv_func_id FunctionId
+///
+/// Introduces a function ID that can be used with .cv_loc.
+bool AsmParser::parseDirectiveCVFuncId() {
+ SMLoc FunctionIdLoc = getTok().getLoc();
+ int64_t FunctionId;
+
+ if (parseCVFunctionId(FunctionId, ".cv_func_id") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cv_func_id' directive"))
+ return true;
+
+ if (!getStreamer().EmitCVFuncIdDirective(FunctionId))
+ return Error(FunctionIdLoc, "function id already allocated");
+
+ return false;
+}
+
+/// parseDirectiveCVInlineSiteId
+/// ::= .cv_inline_site_id FunctionId
+/// "within" IAFunc
+/// "inlined_at" IAFile IALine [IACol]
+///
+/// Introduces a function ID that can be used with .cv_loc. Includes "inlined
+/// at" source location information for use in the line table of the caller,
+/// whether the caller is a real function or another inlined call site.
+bool AsmParser::parseDirectiveCVInlineSiteId() {
+ SMLoc FunctionIdLoc = getTok().getLoc();
+ int64_t FunctionId;
+ int64_t IAFunc;
+ int64_t IAFile;
+ int64_t IALine;
+ int64_t IACol = 0;
+
+ // FunctionId
+ if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
+ return true;
+
+ // "within"
+ if (check((getLexer().isNot(AsmToken::Identifier) ||
+ getTok().getIdentifier() != "within"),
+ "expected 'within' identifier in '.cv_inline_site_id' directive"))
+ return true;
+ Lex();
+
+ // IAFunc
+ if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
+ return true;
+
+ // "inlined_at"
+ if (check((getLexer().isNot(AsmToken::Identifier) ||
+ getTok().getIdentifier() != "inlined_at"),
+ "expected 'inlined_at' identifier in '.cv_inline_site_id' "
+ "directive") )
+ return true;
+ Lex();
+
+ // IAFile IALine
+ if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
+ parseIntToken(IALine, "expected line number after 'inlined_at'"))
+ return true;
+
+ // [IACol]
+ if (getLexer().is(AsmToken::Integer)) {
+ IACol = getTok().getIntVal();
+ Lex();
+ }
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cv_inline_site_id' directive"))
+ return true;
+
+ if (!getStreamer().EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
+ IALine, IACol, FunctionIdLoc))
+ return Error(FunctionIdLoc, "function id already allocated");
+
return false;
}
@@ -3160,18 +3381,11 @@ bool AsmParser::parseDirectiveCVFile() {
/// third number is a column position (zero if not specified). The remaining
/// optional items are .loc sub-directives.
bool AsmParser::parseDirectiveCVLoc() {
+ SMLoc DirectiveLoc = getTok().getLoc();
SMLoc Loc;
int64_t FunctionId, FileNumber;
- if (getTokenLoc(Loc) ||
- parseIntToken(FunctionId, "unexpected token in '.cv_loc' directive") ||
- check(FunctionId < 0, Loc,
- "function id less than zero in '.cv_loc' directive") ||
- getTokenLoc(Loc) ||
- parseIntToken(FileNumber, "expected integer in '.cv_loc' directive") ||
- check(FileNumber < 1, Loc,
- "file number less than one in '.cv_loc' directive") ||
- check(!getContext().isValidCVFileNumber(FileNumber), Loc,
- "unassigned file number in '.cv_loc' directive"))
+ if (parseCVFunctionId(FunctionId, ".cv_loc") ||
+ parseCVFileId(FileNumber, ".cv_loc"))
return true;
int64_t LineNumber = 0;
@@ -3192,12 +3406,12 @@ bool AsmParser::parseDirectiveCVLoc() {
bool PrologueEnd = false;
uint64_t IsStmt = 0;
- while (getLexer().isNot(AsmToken::EndOfStatement)) {
+
+ auto parseOp = [&]() -> bool {
StringRef Name;
SMLoc Loc = getTok().getLoc();
if (parseIdentifier(Name))
return TokError("unexpected token in '.cv_loc' directive");
-
if (Name == "prologue_end")
PrologueEnd = true;
else if (Name == "is_stmt") {
@@ -3215,11 +3429,15 @@ bool AsmParser::parseDirectiveCVLoc() {
} else {
return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
}
- }
- Lex();
+ return false;
+ };
+
+ if (parseMany(parseOp, false /*hasComma*/))
+ return true;
getStreamer().EmitCVLocDirective(FunctionId, FileNumber, LineNumber,
- ColumnPos, PrologueEnd, IsStmt, StringRef());
+ ColumnPos, PrologueEnd, IsStmt, StringRef(),
+ DirectiveLoc);
return false;
}
@@ -3229,18 +3447,15 @@ bool AsmParser::parseDirectiveCVLinetable() {
int64_t FunctionId;
StringRef FnStartName, FnEndName;
SMLoc Loc = getTok().getLoc();
- if (parseIntToken(FunctionId,
- "expected Integer in '.cv_linetable' directive") ||
- check(FunctionId < 0, Loc,
- "function id less than zero in '.cv_linetable' directive") ||
+ if (parseCVFunctionId(FunctionId, ".cv_linetable") ||
parseToken(AsmToken::Comma,
"unexpected token in '.cv_linetable' directive") ||
- getTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
- "expected identifier in directive") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
+ "expected identifier in directive") ||
parseToken(AsmToken::Comma,
"unexpected token in '.cv_linetable' directive") ||
- getTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
- "expected identifier in directive"))
+ parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
+ "expected identifier in directive"))
return true;
MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
@@ -3252,52 +3467,29 @@ bool AsmParser::parseDirectiveCVLinetable() {
/// parseDirectiveCVInlineLinetable
/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
-/// ("contains" SecondaryFunctionId+)?
bool AsmParser::parseDirectiveCVInlineLinetable() {
int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
StringRef FnStartName, FnEndName;
SMLoc Loc = getTok().getLoc();
- if (parseIntToken(
- PrimaryFunctionId,
- "expected PrimaryFunctionId in '.cv_inline_linetable' directive") ||
- check(PrimaryFunctionId < 0, Loc,
- "function id less than zero in '.cv_inline_linetable' directive") ||
- getTokenLoc(Loc) ||
+ if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
+ parseTokenLoc(Loc) ||
parseIntToken(
SourceFileId,
"expected SourceField in '.cv_inline_linetable' directive") ||
check(SourceFileId <= 0, Loc,
"File id less than zero in '.cv_inline_linetable' directive") ||
- getTokenLoc(Loc) ||
+ parseTokenLoc(Loc) ||
parseIntToken(
SourceLineNum,
"expected SourceLineNum in '.cv_inline_linetable' directive") ||
check(SourceLineNum < 0, Loc,
"Line number less than zero in '.cv_inline_linetable' directive") ||
- getTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
- "expected identifier in directive") ||
- getTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
- "expected identifier in directive"))
+ parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
+ "expected identifier in directive") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
+ "expected identifier in directive"))
return true;
- SmallVector<unsigned, 8> SecondaryFunctionIds;
- if (getLexer().is(AsmToken::Identifier)) {
- if (getTok().getIdentifier() != "contains")
- return TokError(
- "unexpected identifier in '.cv_inline_linetable' directive");
- Lex();
-
- while (getLexer().isNot(AsmToken::EndOfStatement)) {
- int64_t SecondaryFunctionId = getTok().getIntVal();
- if (SecondaryFunctionId < 0)
- return TokError(
- "function id less than zero in '.cv_inline_linetable' directive");
- Lex();
-
- SecondaryFunctionIds.push_back(SecondaryFunctionId);
- }
- }
-
if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
return true;
@@ -3305,7 +3497,7 @@ bool AsmParser::parseDirectiveCVInlineLinetable() {
MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
getStreamer().EmitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
SourceLineNum, FnStartSym,
- FnEndSym, SecondaryFunctionIds);
+ FnEndSym);
return false;
}
@@ -3388,12 +3580,12 @@ bool AsmParser::parseDirectiveCFISections() {
/// ::= .cfi_startproc [simple]
bool AsmParser::parseDirectiveCFIStartProc() {
StringRef Simple;
- if (getLexer().isNot(AsmToken::EndOfStatement))
- if (parseIdentifier(Simple) || Simple != "simple")
- return TokError("unexpected token in .cfi_startproc directive");
-
- if (parseToken(AsmToken::EndOfStatement, "Expected end of statement"))
- return true;
+ if (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ if (check(parseIdentifier(Simple) || Simple != "simple",
+ "unexpected token") ||
+ parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '.cfi_startproc' directive");
+ }
getStreamer().EmitCFIStartProc(!Simple.empty());
return false;
@@ -3728,7 +3920,7 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
AsmToken EndToken, StartToken = getTok();
unsigned MacroDepth = 0;
// Lex the macro definition.
- for (;;) {
+ while (true) {
// Ignore Lexing errors in macros.
while (Lexer.is(AsmToken::Error)) {
Lexer.Lex();
@@ -3924,14 +4116,16 @@ bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
StringRef Name;
SMLoc Loc;
- if (getTokenLoc(Loc) || check(parseIdentifier(Name), Loc,
- "expected identifier in '.purgem' directive") ||
+ if (parseTokenLoc(Loc) ||
+ check(parseIdentifier(Name), Loc,
+ "expected identifier in '.purgem' directive") ||
parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.purgem' directive") ||
- check(!lookupMacro(Name), DirectiveLoc,
- "macro '" + Name + "' is not defined"))
+ "unexpected token in '.purgem' directive"))
return true;
+ if (!lookupMacro(Name))
+ return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
+
undefineMacro(Name);
return false;
}
@@ -3939,13 +4133,11 @@ bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
/// parseDirectiveBundleAlignMode
/// ::= {.bundle_align_mode} expression
bool AsmParser::parseDirectiveBundleAlignMode() {
- checkForValidSection();
-
// Expect a single argument: an expression that evaluates to a constant
// in the inclusive range 0-30.
SMLoc ExprLoc = getLexer().getLoc();
int64_t AlignSizePow2;
- if (parseAbsoluteExpression(AlignSizePow2) ||
+ if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||
parseToken(AsmToken::EndOfStatement, "unexpected token after expression "
"in '.bundle_align_mode' "
"directive") ||
@@ -3962,25 +4154,24 @@ bool AsmParser::parseDirectiveBundleAlignMode() {
/// parseDirectiveBundleLock
/// ::= {.bundle_lock} [align_to_end]
bool AsmParser::parseDirectiveBundleLock() {
- checkForValidSection();
+ if (checkForValidSection())
+ return true;
bool AlignToEnd = false;
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- StringRef Option;
- SMLoc Loc = getTok().getLoc();
- const char *kInvalidOptionError =
- "invalid option for '.bundle_lock' directive";
+ StringRef Option;
+ SMLoc Loc = getTok().getLoc();
+ const char *kInvalidOptionError =
+ "invalid option for '.bundle_lock' directive";
+ if (!parseOptionalToken(AsmToken::EndOfStatement)) {
if (check(parseIdentifier(Option), Loc, kInvalidOptionError) ||
check(Option != "align_to_end", Loc, kInvalidOptionError) ||
- check(getTok().isNot(AsmToken::EndOfStatement), Loc,
- "unexpected token after '.bundle_lock' directive option"))
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token after '.bundle_lock' directive option"))
return true;
AlignToEnd = true;
}
- Lex();
-
getStreamer().EmitBundleLock(AlignToEnd);
return false;
}
@@ -3988,9 +4179,8 @@ bool AsmParser::parseDirectiveBundleLock() {
/// parseDirectiveBundleLock
/// ::= {.bundle_lock}
bool AsmParser::parseDirectiveBundleUnlock() {
- checkForValidSection();
-
- if (parseToken(AsmToken::EndOfStatement,
+ if (checkForValidSection() ||
+ parseToken(AsmToken::EndOfStatement,
"unexpected token in '.bundle_unlock' directive"))
return true;
@@ -4001,28 +4191,119 @@ bool AsmParser::parseDirectiveBundleUnlock() {
/// parseDirectiveSpace
/// ::= (.skip | .space) expression [ , expression ]
bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
- checkForValidSection();
SMLoc NumBytesLoc = Lexer.getLoc();
const MCExpr *NumBytes;
- if (parseExpression(NumBytes))
+ if (checkForValidSection() || parseExpression(NumBytes))
return true;
int64_t FillExpr = 0;
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ if (parseOptionalToken(AsmToken::Comma))
+ if (parseAbsoluteExpression(FillExpr))
+ return addErrorSuffix("in '" + Twine(IDVal) + "' directive");
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix("in '" + Twine(IDVal) + "' directive");
- if (parseToken(AsmToken::Comma,
- "unexpected token in '" + Twine(IDVal) + "' directive") ||
- parseAbsoluteExpression(FillExpr))
- return true;
+ // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
+ getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
+
+ return false;
+}
+
+/// parseDirectiveDCB
+/// ::= .dcb.{b, l, w} expression, expression
+bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
+ SMLoc NumValuesLoc = Lexer.getLoc();
+ int64_t NumValues;
+ if (checkForValidSection() || parseAbsoluteExpression(NumValues))
+ return true;
+
+ if (NumValues < 0) {
+ Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
+ return false;
+ }
+
+ if (parseToken(AsmToken::Comma,
+ "unexpected token in '" + Twine(IDVal) + "' directive"))
+ return true;
+
+ const MCExpr *Value;
+ SMLoc ExprLoc = getLexer().getLoc();
+ if (parseExpression(Value))
+ return true;
+
+ // Special case constant expressions to match code generator.
+ if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
+ assert(Size <= 8 && "Invalid size");
+ uint64_t IntValue = MCE->getValue();
+ if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
+ return Error(ExprLoc, "literal value out of range for directive");
+ for (uint64_t i = 0, e = NumValues; i != e; ++i)
+ getStreamer().EmitIntValue(IntValue, Size);
+ } else {
+ for (uint64_t i = 0, e = NumValues; i != e; ++i)
+ getStreamer().EmitValue(Value, Size, ExprLoc);
}
if (parseToken(AsmToken::EndOfStatement,
"unexpected token in '" + Twine(IDVal) + "' directive"))
return true;
- // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
- getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
+ return false;
+}
+
+/// parseDirectiveRealDCB
+/// ::= .dcb.{d, s} expression, expression
+bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {
+ SMLoc NumValuesLoc = Lexer.getLoc();
+ int64_t NumValues;
+ if (checkForValidSection() || parseAbsoluteExpression(NumValues))
+ return true;
+
+ if (NumValues < 0) {
+ Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
+ return false;
+ }
+
+ if (parseToken(AsmToken::Comma,
+ "unexpected token in '" + Twine(IDVal) + "' directive"))
+ return true;
+
+ APInt AsInt;
+ if (parseRealValue(Semantics, AsInt))
+ return true;
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '" + Twine(IDVal) + "' directive"))
+ return true;
+
+ for (uint64_t i = 0, e = NumValues; i != e; ++i)
+ getStreamer().EmitIntValue(AsInt.getLimitedValue(),
+ AsInt.getBitWidth() / 8);
+
+ return false;
+}
+
+/// parseDirectiveDS
+/// ::= .ds.{b, d, l, p, s, w, x} expression
+bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {
+
+ SMLoc NumValuesLoc = Lexer.getLoc();
+ int64_t NumValues;
+ if (checkForValidSection() || parseAbsoluteExpression(NumValues))
+ return true;
+
+ if (NumValues < 0) {
+ Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
+ return false;
+ }
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '" + Twine(IDVal) + "' directive"))
+ return true;
+
+ for (uint64_t i = 0, e = NumValues; i != e; ++i)
+ getStreamer().emitFill(Size, 0);
return false;
}
@@ -4030,25 +4311,22 @@ bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
/// parseDirectiveLEB128
/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
bool AsmParser::parseDirectiveLEB128(bool Signed) {
- checkForValidSection();
- const MCExpr *Value;
+ if (checkForValidSection())
+ return true;
- for (;;) {
+ auto parseOp = [&]() -> bool {
+ const MCExpr *Value;
if (parseExpression(Value))
return true;
-
if (Signed)
getStreamer().EmitSLEB128Value(Value);
else
getStreamer().EmitULEB128Value(Value);
+ return false;
+ };
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
-
- if (parseToken(AsmToken::Comma, "unexpected token in directive"))
- return true;
- }
- Lex();
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in directive");
return false;
}
@@ -4056,39 +4334,32 @@ bool AsmParser::parseDirectiveLEB128(bool Signed) {
/// parseDirectiveSymbolAttribute
/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- for (;;) {
- StringRef Name;
- SMLoc Loc = getTok().getLoc();
-
- if (parseIdentifier(Name))
- return Error(Loc, "expected identifier in directive");
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- // Assembler local symbols don't make any sense here. Complain loudly.
- if (Sym->isTemporary())
- return Error(Loc, "non-local symbol required in directive");
-
- if (!getStreamer().EmitSymbolAttribute(Sym, Attr))
- return Error(Loc, "unable to emit symbol attribute");
+ auto parseOp = [&]() -> bool {
+ StringRef Name;
+ SMLoc Loc = getTok().getLoc();
+ if (parseIdentifier(Name))
+ return Error(Loc, "expected identifier");
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
+ // Assembler local symbols don't make any sense here. Complain loudly.
+ if (Sym->isTemporary())
+ return Error(Loc, "non-local symbol required");
- if (parseToken(AsmToken::Comma, "unexpected token in directive"))
- return true;
- }
- }
+ if (!getStreamer().EmitSymbolAttribute(Sym, Attr))
+ return Error(Loc, "unable to emit symbol attribute");
+ return false;
+ };
- Lex();
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in directive");
return false;
}
/// parseDirectiveComm
/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
bool AsmParser::parseDirectiveComm(bool IsLocal) {
- checkForValidSection();
+ if (checkForValidSection())
+ return true;
SMLoc IDLoc = getLexer().getLoc();
StringRef Name;
@@ -4128,10 +4399,9 @@ bool AsmParser::parseDirectiveComm(bool IsLocal) {
}
}
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.comm' or '.lcomm' directive");
-
- Lex();
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.comm' or '.lcomm' directive"))
+ return true;
// NOTE: a size of zero for a .comm should create a undefined symbol
// but a size of .lcomm creates a bss symbol of size zero.
@@ -4171,9 +4441,9 @@ bool AsmParser::parseDirectiveAbort() {
return true;
if (Str.empty())
- Error(Loc, ".abort detected. Assembly stopping.");
+ return Error(Loc, ".abort detected. Assembly stopping.");
else
- Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
+ return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
// FIXME: Actually abort assembly here.
return false;
@@ -4201,20 +4471,43 @@ bool AsmParser::parseDirectiveInclude() {
}
/// parseDirectiveIncbin
-/// ::= .incbin "filename"
+/// ::= .incbin "filename" [ , skip [ , count ] ]
bool AsmParser::parseDirectiveIncbin() {
// Allow the strings to have escaped octal character sequence.
std::string Filename;
SMLoc IncbinLoc = getTok().getLoc();
if (check(getTok().isNot(AsmToken::String),
"expected string in '.incbin' directive") ||
- parseEscapedString(Filename) ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.incbin' directive") ||
- // Attempt to process the included file.
- check(processIncbinFile(Filename), IncbinLoc,
- "Could not find incbin file '" + Filename + "'"))
+ parseEscapedString(Filename))
+ return true;
+
+ int64_t Skip = 0;
+ const MCExpr *Count = nullptr;
+ SMLoc SkipLoc, CountLoc;
+ if (parseOptionalToken(AsmToken::Comma)) {
+ // The skip expression can be omitted while specifying the count, e.g:
+ // .incbin "filename",,4
+ if (getTok().isNot(AsmToken::Comma)) {
+ if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))
+ return true;
+ }
+ if (parseOptionalToken(AsmToken::Comma)) {
+ CountLoc = getTok().getLoc();
+ if (parseExpression(Count))
+ return true;
+ }
+ }
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.incbin' directive"))
+ return true;
+
+ if (check(Skip < 0, SkipLoc, "skip is negative"))
return true;
+
+ // Attempt to process the included file.
+ if (processIncbinFile(Filename, Skip, Count, CountLoc))
+ return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
return false;
}
@@ -4317,11 +4610,8 @@ bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
if (Lexer.isNot(AsmToken::String)) {
if (ExpectEqual)
- TokError("expected string parameter for '.ifeqs' directive");
- else
- TokError("expected string parameter for '.ifnes' directive");
- eatToEndOfStatement();
- return true;
+ return TokError("expected string parameter for '.ifeqs' directive");
+ return TokError("expected string parameter for '.ifnes' directive");
}
StringRef String1 = getTok().getStringContents();
@@ -4329,22 +4619,17 @@ bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
if (Lexer.isNot(AsmToken::Comma)) {
if (ExpectEqual)
- TokError("expected comma after first string for '.ifeqs' directive");
- else
- TokError("expected comma after first string for '.ifnes' directive");
- eatToEndOfStatement();
- return true;
+ return TokError(
+ "expected comma after first string for '.ifeqs' directive");
+ return TokError("expected comma after first string for '.ifnes' directive");
}
Lex();
if (Lexer.isNot(AsmToken::String)) {
if (ExpectEqual)
- TokError("expected string parameter for '.ifeqs' directive");
- else
- TokError("expected string parameter for '.ifnes' directive");
- eatToEndOfStatement();
- return true;
+ return TokError("expected string parameter for '.ifeqs' directive");
+ return TokError("expected string parameter for '.ifnes' directive");
}
StringRef String2 = getTok().getStringContents();
@@ -4389,8 +4674,8 @@ bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
if (TheCondState.TheCond != AsmCond::IfCond &&
TheCondState.TheCond != AsmCond::ElseIfCond)
- Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or "
- " an .elseif");
+ return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
+ " .if or an .elseif");
TheCondState.TheCond = AsmCond::ElseIfCond;
bool LastIgnoreState = false;
@@ -4404,10 +4689,10 @@ bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
if (parseAbsoluteExpression(ExprValue))
return true;
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.elseif' directive");
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.elseif' directive"))
+ return true;
- Lex();
TheCondState.CondMet = ExprValue;
TheCondState.Ignore = !TheCondState.CondMet;
}
@@ -4424,8 +4709,8 @@ bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
if (TheCondState.TheCond != AsmCond::IfCond &&
TheCondState.TheCond != AsmCond::ElseIfCond)
- Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an "
- ".elseif");
+ return Error(DirectiveLoc, "Encountered a .else that doesn't follow "
+ " an .if or an .elseif");
TheCondState.TheCond = AsmCond::ElseCond;
bool LastIgnoreState = false;
if (!TheCondStack.empty())
@@ -4446,7 +4731,7 @@ bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
return true;
while (Lexer.isNot(AsmToken::Eof))
- Lex();
+ Lexer.Lex();
return false;
}
@@ -4467,18 +4752,14 @@ bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
StringRef Message = ".error directive invoked in source file";
if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::String)) {
- TokError(".error argument must be a string");
- eatToEndOfStatement();
- return true;
- }
+ if (Lexer.isNot(AsmToken::String))
+ return TokError(".error argument must be a string");
Message = getTok().getStringContents();
Lex();
}
- Error(L, Message);
- return true;
+ return Error(L, Message);
}
/// parseDirectiveWarning
@@ -4492,19 +4773,19 @@ bool AsmParser::parseDirectiveWarning(SMLoc L) {
}
StringRef Message = ".warning directive invoked in source file";
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::String)) {
- TokError(".warning argument must be a string");
- eatToEndOfStatement();
- return true;
- }
+
+ if (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::String))
+ return TokError(".warning argument must be a string");
Message = getTok().getStringContents();
Lex();
+ if (parseToken(AsmToken::EndOfStatement,
+ "expected end of statement in '.warning' directive"))
+ return true;
}
- Warning(L, Message);
- return false;
+ return Warning(L, Message);
}
/// parseDirectiveEndIf
@@ -4515,8 +4796,8 @@ bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
return true;
if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
- Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or "
- ".else");
+ return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
+ "an .if or .else");
if (!TheCondStack.empty()) {
TheCondState = TheCondStack.back();
TheCondStack.pop_back();
@@ -4610,9 +4891,11 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".loc"] = DK_LOC;
DirectiveKindMap[".stabs"] = DK_STABS;
DirectiveKindMap[".cv_file"] = DK_CV_FILE;
+ DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
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_stringtable"] = DK_CV_STRINGTABLE;
DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
@@ -4649,16 +4932,39 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".error"] = DK_ERROR;
DirectiveKindMap[".warning"] = DK_WARNING;
DirectiveKindMap[".reloc"] = DK_RELOC;
+ DirectiveKindMap[".dc"] = DK_DC;
+ DirectiveKindMap[".dc.a"] = DK_DC_A;
+ DirectiveKindMap[".dc.b"] = DK_DC_B;
+ DirectiveKindMap[".dc.d"] = DK_DC_D;
+ DirectiveKindMap[".dc.l"] = DK_DC_L;
+ DirectiveKindMap[".dc.s"] = DK_DC_S;
+ DirectiveKindMap[".dc.w"] = DK_DC_W;
+ DirectiveKindMap[".dc.x"] = DK_DC_X;
+ DirectiveKindMap[".dcb"] = DK_DCB;
+ DirectiveKindMap[".dcb.b"] = DK_DCB_B;
+ DirectiveKindMap[".dcb.d"] = DK_DCB_D;
+ DirectiveKindMap[".dcb.l"] = DK_DCB_L;
+ DirectiveKindMap[".dcb.s"] = DK_DCB_S;
+ DirectiveKindMap[".dcb.w"] = DK_DCB_W;
+ DirectiveKindMap[".dcb.x"] = DK_DCB_X;
+ DirectiveKindMap[".ds"] = DK_DS;
+ DirectiveKindMap[".ds.b"] = DK_DS_B;
+ DirectiveKindMap[".ds.d"] = DK_DS_D;
+ DirectiveKindMap[".ds.l"] = DK_DS_L;
+ DirectiveKindMap[".ds.p"] = DK_DS_P;
+ DirectiveKindMap[".ds.s"] = DK_DS_S;
+ DirectiveKindMap[".ds.w"] = DK_DS_W;
+ DirectiveKindMap[".ds.x"] = DK_DS_X;
}
MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
AsmToken EndToken, StartToken = getTok();
unsigned NestLevel = 0;
- for (;;) {
+ while (true) {
// Check whether we have reached the end of the file.
if (getLexer().is(AsmToken::Eof)) {
- Error(DirectiveLoc, "no matching '.endr' in definition");
+ printError(DirectiveLoc, "no matching '.endr' in definition");
return nullptr;
}
@@ -4675,7 +4981,8 @@ MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
EndToken = getTok();
Lex();
if (Lexer.isNot(AsmToken::EndOfStatement)) {
- TokError("unexpected token in '.endr' directive");
+ printError(getTok().getLoc(),
+ "unexpected token in '.endr' directive");
return nullptr;
}
break;
@@ -4725,7 +5032,6 @@ bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
int64_t Count;
if (!CountExpr->evaluateAsAbsolute(Count)) {
- eatToEndOfStatement();
return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
}
@@ -4928,11 +5234,16 @@ bool AsmParser::parseMSInlineAsm(
continue;
ParseStatementInfo Info(&AsmStrRewrites);
- if (parseStatement(Info, &SI))
- return true;
+ bool StatementErr = parseStatement(Info, &SI);
- if (Info.ParseError)
+ if (StatementErr || Info.ParseError) {
+ // Emit pending errors if any exist.
+ printPendingErrors();
return true;
+ }
+
+ // No pending error should exist here.
+ assert(!hasPendingError() && "unexpected error from parseStatement");
if (Info.Opcode == ~0U)
continue;
@@ -5158,20 +5469,15 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef,
SMLoc EqualLoc = Parser.getTok().getLoc();
if (Parser.parseExpression(Value)) {
- Parser.TokError("missing expression");
- Parser.eatToEndOfStatement();
- return true;
+ return Parser.TokError("missing expression");
}
// Note: we don't count b as used in "a = b". This is to allow
// a = b
// b = c
- if (Parser.getTok().isNot(AsmToken::EndOfStatement))
- return Parser.TokError("unexpected token in assignment");
-
- // Eat the end of statement marker.
- Parser.Lex();
+ if (Parser.parseToken(AsmToken::EndOfStatement))
+ return true;
// Validate that the LHS is allowed to be a variable (either it has not been
// used as a symbol, or it is an absolute symbol).
@@ -5197,7 +5503,7 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef,
"invalid reassignment of non-absolute variable '" +
Name + "'");
} else if (Name == ".") {
- Parser.getStreamer().emitValueToOffset(Value, 0);
+ Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
return false;
} else
Sym = Parser.getContext().getOrCreateSymbol(Name);
@@ -5207,8 +5513,8 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef,
return false;
}
-} // namespace MCParserUtils
-} // namespace llvm
+} // end namespace MCParserUtils
+} // end namespace llvm
/// \brief Create an MCAsmParser instance.
MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp
index 653627ad8dca..f4114795a92d 100644
--- a/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/lib/MC/MCParser/COFFAsmParser.cpp
@@ -41,7 +41,8 @@ class COFFAsmParser : public MCAsmParserExtension {
COFF::COMDATType Type);
bool ParseSectionName(StringRef &SectionName);
- bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
+ bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
+ unsigned *Flags);
void Initialize(MCAsmParser &Parser) override {
// Call the base implementation.
@@ -155,17 +156,19 @@ static SectionKind computeSectionKind(unsigned Flags) {
return SectionKind::getData();
}
-bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
+bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,
+ StringRef FlagsString, unsigned *Flags) {
enum {
- None = 0,
- Alloc = 1 << 0,
- Code = 1 << 1,
- Load = 1 << 2,
- InitData = 1 << 3,
- Shared = 1 << 4,
- NoLoad = 1 << 5,
- NoRead = 1 << 6,
- NoWrite = 1 << 7
+ None = 0,
+ Alloc = 1 << 0,
+ Code = 1 << 1,
+ Load = 1 << 2,
+ InitData = 1 << 3,
+ Shared = 1 << 4,
+ NoLoad = 1 << 5,
+ NoRead = 1 << 6,
+ NoWrite = 1 << 7,
+ Discardable = 1 << 8,
};
bool ReadOnlyRemoved = false;
@@ -198,6 +201,10 @@ bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
SecFlags &= ~Load;
break;
+ case 'D': // discardable
+ SecFlags |= Discardable;
+ break;
+
case 'r': // read-only
ReadOnlyRemoved = false;
SecFlags |= NoWrite;
@@ -249,6 +256,9 @@ bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
*Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
if (SecFlags & NoLoad)
*Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
+ if ((SecFlags & Discardable) ||
+ MCSectionCOFF::isImplicitlyDiscardable(SectionName))
+ *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
if ((SecFlags & NoRead) == 0)
*Flags |= COFF::IMAGE_SCN_MEM_READ;
if ((SecFlags & NoWrite) == 0)
@@ -326,7 +336,8 @@ bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
// a: Ignored.
// b: BSS section (uninitialized data)
// d: data section (initialized data)
-// n: Discardable section
+// n: "noload" section (removed by linker)
+// D: Discardable section
// r: Readable section
// s: Shared section
// w: Writable section
@@ -353,7 +364,7 @@ bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
StringRef FlagsStr = getTok().getStringContents();
Lex();
- if (ParseSectionFlags(FlagsStr, &Flags))
+ if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
return true;
}
@@ -444,13 +455,26 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
if (getParser().parseIdentifier(SymbolID))
return TokError("expected identifier in directive");
+ int64_t Offset = 0;
+ SMLoc OffsetLoc;
+ if (getLexer().is(AsmToken::Plus)) {
+ OffsetLoc = getLexer().getLoc();
+ if (getParser().parseAbsoluteExpression(Offset))
+ return true;
+ }
+
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in directive");
+ if (Offset < 0 || Offset > UINT32_MAX)
+ return Error(OffsetLoc,
+ "invalid '.secrel32' directive offset, can't be less "
+ "than zero or greater than UINT32_MAX");
+
MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Lex();
- getStreamer().EmitCOFFSecRel32(Symbol);
+ getStreamer().EmitCOFFSecRel32(Symbol, Offset);
return false;
}
@@ -514,8 +538,8 @@ bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
if (parseCOMDATType(Type))
return true;
- const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
- getStreamer().getCurrentSection().first);
+ const MCSectionCOFF *Current =
+ static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
return Error(Loc, "cannot make section associative with .linkonce");
diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp
index 37515d9c074d..94aa70ef0326 100644
--- a/lib/MC/MCParser/DarwinAsmParser.cpp
+++ b/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -37,7 +37,7 @@ class DarwinAsmParser : public MCAsmParserExtension {
getParser().addDirectiveHandler(Directive, Handler);
}
- bool parseSectionSwitch(const char *Segment, const char *Section,
+ bool parseSectionSwitch(StringRef Segment, StringRef Section,
unsigned TAA = 0, unsigned ImplicitAlign = 0,
unsigned StubSize = 0);
@@ -389,8 +389,7 @@ public:
} // end anonymous namespace
-bool DarwinAsmParser::parseSectionSwitch(const char *Segment,
- const char *Section,
+bool DarwinAsmParser::parseSectionSwitch(StringRef Segment, StringRef Section,
unsigned TAA, unsigned Align,
unsigned StubSize) {
if (getLexer().isNot(AsmToken::EndOfStatement))
@@ -469,8 +468,8 @@ bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) {
/// parseDirectiveIndirectSymbol
/// ::= .indirect_symbol identifier
bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) {
- const MCSectionMachO *Current = static_cast<const MCSectionMachO*>(
- getStreamer().getCurrentSection().first);
+ const MCSectionMachO *Current = static_cast<const MCSectionMachO *>(
+ getStreamer().getCurrentSectionOnly());
MachO::SectionType SectionType = Current->getType();
if (SectionType != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
SectionType != MachO::S_LAZY_SYMBOL_POINTERS &&
@@ -615,7 +614,7 @@ bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) {
TAA, TAAParsed, StubSize);
if (!ErrorStr.empty())
- return Error(Loc, ErrorStr.c_str());
+ return Error(Loc, ErrorStr);
// Issue a warning if the target is not powerpc and Section is a *coal* section.
Triple TT = getParser().getContext().getObjectFileInfo()->getTargetTriple();
@@ -700,7 +699,7 @@ bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) {
if (!OS) {
std::error_code EC;
auto NewOS = llvm::make_unique<raw_fd_ostream>(
- SecureLogFile, EC, sys::fs::F_Append | sys::fs::F_Text);
+ StringRef(SecureLogFile), EC, sys::fs::F_Append | sys::fs::F_Text);
if (EC)
return Error(IDLoc, Twine("can't open secure log file: ") +
SecureLogFile + " (" + EC.message() + ")");
diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp
index 47d19a824d19..8d7ba0d03362 100644
--- a/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/lib/MC/MCParser/ELFAsmParser.cpp
@@ -264,6 +264,10 @@ bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {
static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) {
unsigned flags = 0;
+ // If a valid numerical value is set for the section flag, use it verbatim
+ if (!flagsStr.getAsInteger(0, flags))
+ return flags;
+
for (char i : flagsStr) {
switch (i) {
case 'a':
@@ -293,6 +297,9 @@ static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) {
case 'd':
flags |= ELF::XCORE_SHF_DP_SECTION;
break;
+ case 'y':
+ flags |= ELF::SHF_ARM_PURECODE;
+ break;
case 'G':
flags |= ELF::SHF_GROUP;
break;
diff --git a/lib/MC/MCParser/MCAsmLexer.cpp b/lib/MC/MCParser/MCAsmLexer.cpp
index d95cd12accbc..63c0daba09a0 100644
--- a/lib/MC/MCParser/MCAsmLexer.cpp
+++ b/lib/MC/MCParser/MCAsmLexer.cpp
@@ -12,7 +12,9 @@
using namespace llvm;
-MCAsmLexer::MCAsmLexer() : TokStart(nullptr), SkipSpace(true) {
+MCAsmLexer::MCAsmLexer()
+ : TokStart(nullptr), SkipSpace(true), IsAtStartOfStatement(true),
+ CommentConsumer(nullptr) {
CurTok.emplace_back(AsmToken::Space, StringRef());
}
diff --git a/lib/MC/MCParser/MCAsmParser.cpp b/lib/MC/MCParser/MCAsmParser.cpp
index dc7a3f00840f..98f4daf972d6 100644
--- a/lib/MC/MCParser/MCAsmParser.cpp
+++ b/lib/MC/MCParser/MCAsmParser.cpp
@@ -17,8 +17,9 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
-MCAsmParser::MCAsmParser() : TargetParser(nullptr), ShowParsedOperands(0) {
-}
+MCAsmParser::MCAsmParser()
+ : TargetParser(nullptr), ShowParsedOperands(0), HadError(false),
+ PendingErrors() {}
MCAsmParser::~MCAsmParser() {
}
@@ -33,18 +34,109 @@ const AsmToken &MCAsmParser::getTok() const {
return getLexer().getTok();
}
-bool MCAsmParser::TokError(const Twine &Msg, ArrayRef<SMRange> Ranges) {
- Error(getLexer().getLoc(), Msg, Ranges);
+bool MCAsmParser::parseTokenLoc(SMLoc &Loc) {
+ Loc = getTok().getLoc();
+ return false;
+}
+
+bool MCAsmParser::parseEOL(const Twine &Msg) {
+ if (getTok().getKind() == AsmToken::Hash) {
+ StringRef CommentStr = parseStringToEndOfStatement();
+ getLexer().Lex();
+ getLexer().UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
+ }
+ if (getTok().getKind() != AsmToken::EndOfStatement)
+ return Error(getTok().getLoc(), Msg);
+ Lex();
+ return false;
+}
+
+bool MCAsmParser::parseToken(AsmToken::TokenKind T, const Twine &Msg) {
+ if (T == AsmToken::EndOfStatement)
+ return parseEOL(Msg);
+ if (getTok().getKind() != T)
+ return Error(getTok().getLoc(), Msg);
+ Lex();
+ return false;
+}
+
+bool MCAsmParser::parseIntToken(int64_t &V, const Twine &Msg) {
+ if (getTok().getKind() != AsmToken::Integer)
+ return TokError(Msg);
+ V = getTok().getIntVal();
+ Lex();
+ return false;
+}
+
+bool MCAsmParser::parseOptionalToken(AsmToken::TokenKind T) {
+ bool Present = (getTok().getKind() == T);
+ // if token is EOL and current token is # this is an EOL comment.
+ if (getTok().getKind() == AsmToken::Hash && T == AsmToken::EndOfStatement)
+ Present = true;
+ if (Present)
+ parseToken(T);
+ return Present;
+}
+
+bool MCAsmParser::check(bool P, const Twine &Msg) {
+ return check(P, getTok().getLoc(), Msg);
+}
+
+bool MCAsmParser::check(bool P, SMLoc Loc, const Twine &Msg) {
+ if (P)
+ return Error(Loc, Msg);
+ return false;
+}
+
+bool MCAsmParser::TokError(const Twine &Msg, SMRange Range) {
+ return Error(getLexer().getLoc(), Msg, Range);
+}
+
+bool MCAsmParser::Error(SMLoc L, const Twine &Msg, SMRange Range) {
+ HadError = true;
+
+ MCPendingError PErr;
+ PErr.Loc = L;
+ Msg.toVector(PErr.Msg);
+ PErr.Range = Range;
+ PendingErrors.push_back(PErr);
+
+ // If we threw this parsing error after a lexing error, this should
+ // supercede the lexing error and so we remove it from the Lexer
+ // before it can propagate
+ if (getTok().is(AsmToken::Error))
+ getLexer().Lex();
+ return true;
+}
+
+bool MCAsmParser::addErrorSuffix(const Twine &Suffix) {
+ // Make sure lexing errors have propagated to the parser.
+ if (getTok().is(AsmToken::Error))
+ Lex();
+ for (auto &PErr : PendingErrors)
+ Suffix.toVector(PErr.Msg);
return true;
}
+bool MCAsmParser::parseMany(std::function<bool()> parseOne, bool hasComma) {
+ if (parseOptionalToken(AsmToken::EndOfStatement))
+ return false;
+ while (1) {
+ if (parseOne())
+ return true;
+ if (parseOptionalToken(AsmToken::EndOfStatement))
+ return false;
+ if (hasComma && parseToken(AsmToken::Comma))
+ return true;
+ }
+ return false;
+}
+
bool MCAsmParser::parseExpression(const MCExpr *&Res) {
SMLoc L;
return parseExpression(Res, L);
}
LLVM_DUMP_METHOD void MCParsedAsmOperand::dump() const {
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dbgs() << " " << *this;
-#endif
}
diff --git a/lib/MC/MCRegisterInfo.cpp b/lib/MC/MCRegisterInfo.cpp
index c76bb646c126..ea117f3caa85 100644
--- a/lib/MC/MCRegisterInfo.cpp
+++ b/lib/MC/MCRegisterInfo.cpp
@@ -12,6 +12,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -62,6 +64,8 @@ int MCRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
const DwarfLLVMRegPair *M = isEH ? EHL2DwarfRegs : L2DwarfRegs;
unsigned Size = isEH ? EHL2DwarfRegsSize : L2DwarfRegsSize;
+ if (!M)
+ return -1;
DwarfLLVMRegPair Key = { RegNum, 0 };
const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key);
if (I == M+Size || I->FromReg != RegNum)
@@ -73,6 +77,8 @@ int MCRegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const {
const DwarfLLVMRegPair *M = isEH ? EHDwarf2LRegs : Dwarf2LRegs;
unsigned Size = isEH ? EHDwarf2LRegsSize : Dwarf2LRegsSize;
+ if (!M)
+ return -1;
DwarfLLVMRegPair Key = { RegNum, 0 };
const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key);
assert(I != M+Size && I->FromReg == RegNum && "Invalid RegNum");
diff --git a/lib/MC/MCSection.cpp b/lib/MC/MCSection.cpp
index 32e4cce4f68c..9064cdf2f319 100644
--- a/lib/MC/MCSection.cpp
+++ b/lib/MC/MCSection.cpp
@@ -85,7 +85,6 @@ MCSection::getSubsectionInsertionPoint(unsigned Subsection) {
return IP;
}
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MCSection::dump() {
raw_ostream &OS = llvm::errs();
@@ -98,12 +97,3 @@ LLVM_DUMP_METHOD void MCSection::dump() {
}
OS << "]>";
}
-#endif
-
-MCSection::iterator MCSection::begin() { return Fragments.begin(); }
-
-MCSection::iterator MCSection::end() { return Fragments.end(); }
-
-MCSection::reverse_iterator MCSection::rbegin() { return Fragments.rbegin(); }
-
-MCSection::reverse_iterator MCSection::rend() { return Fragments.rend(); }
diff --git a/lib/MC/MCSectionCOFF.cpp b/lib/MC/MCSectionCOFF.cpp
index b8373f40b8be..f2dd47d81b7e 100644
--- a/lib/MC/MCSectionCOFF.cpp
+++ b/lib/MC/MCSectionCOFF.cpp
@@ -64,6 +64,9 @@ void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI,
OS << 'n';
if (getCharacteristics() & COFF::IMAGE_SCN_MEM_SHARED)
OS << 's';
+ if ((getCharacteristics() & COFF::IMAGE_SCN_MEM_DISCARDABLE) &&
+ !isImplicitlyDiscardable(SectionName))
+ OS << 'D';
OS << '"';
if (getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) {
diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp
index 5a0bb7fe986f..587b28f71b7d 100644
--- a/lib/MC/MCSectionELF.cpp
+++ b/lib/MC/MCSectionELF.cpp
@@ -110,6 +110,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
OS << 'c';
if (Flags & ELF::XCORE_SHF_DP_SECTION)
OS << 'd';
+ if (Flags & ELF::SHF_ARM_PURECODE)
+ OS << 'y';
OS << '"';
diff --git a/lib/MC/MCSectionMachO.cpp b/lib/MC/MCSectionMachO.cpp
index 879c6e5ff932..c2a772fdbdac 100644
--- a/lib/MC/MCSectionMachO.cpp
+++ b/lib/MC/MCSectionMachO.cpp
@@ -17,10 +17,10 @@ using namespace llvm;
/// types. This *must* be kept in order with and stay synchronized with the
/// section type list.
static const struct {
- const char *AssemblerName, *EnumName;
+ StringRef AssemblerName, EnumName;
} SectionTypeDescriptors[MachO::LAST_KNOWN_SECTION_TYPE+1] = {
{ "regular", "S_REGULAR" }, // 0x00
- { nullptr, "S_ZEROFILL" }, // 0x01
+ { StringRef(), "S_ZEROFILL" }, // 0x01
{ "cstring_literals", "S_CSTRING_LITERALS" }, // 0x02
{ "4byte_literals", "S_4BYTE_LITERALS" }, // 0x03
{ "8byte_literals", "S_8BYTE_LITERALS" }, // 0x04
@@ -31,11 +31,11 @@ static const struct {
{ "mod_init_funcs", "S_MOD_INIT_FUNC_POINTERS" }, // 0x09
{ "mod_term_funcs", "S_MOD_TERM_FUNC_POINTERS" }, // 0x0A
{ "coalesced", "S_COALESCED" }, // 0x0B
- { nullptr, /*FIXME??*/ "S_GB_ZEROFILL" }, // 0x0C
+ { StringRef(), /*FIXME??*/ "S_GB_ZEROFILL" }, // 0x0C
{ "interposing", "S_INTERPOSING" }, // 0x0D
{ "16byte_literals", "S_16BYTE_LITERALS" }, // 0x0E
- { nullptr, /*FIXME??*/ "S_DTRACE_DOF" }, // 0x0F
- { nullptr, /*FIXME??*/ "S_LAZY_DYLIB_SYMBOL_POINTERS" }, // 0x10
+ { StringRef(), /*FIXME??*/ "S_DTRACE_DOF" }, // 0x0F
+ { StringRef(), /*FIXME??*/ "S_LAZY_DYLIB_SYMBOL_POINTERS" }, // 0x10
{ "thread_local_regular", "S_THREAD_LOCAL_REGULAR" }, // 0x11
{ "thread_local_zerofill", "S_THREAD_LOCAL_ZEROFILL" }, // 0x12
{ "thread_local_variables", "S_THREAD_LOCAL_VARIABLES" }, // 0x13
@@ -51,7 +51,7 @@ static const struct {
/// by attribute, instead it is searched.
static const struct {
unsigned AttrFlag;
- const char *AssemblerName, *EnumName;
+ StringRef AssemblerName, EnumName;
} SectionAttrDescriptors[] = {
#define ENTRY(ASMNAME, ENUM) \
{ MachO::ENUM, ASMNAME, #ENUM },
@@ -62,11 +62,11 @@ ENTRY("no_dead_strip", S_ATTR_NO_DEAD_STRIP)
ENTRY("live_support", S_ATTR_LIVE_SUPPORT)
ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE)
ENTRY("debug", S_ATTR_DEBUG)
-ENTRY(nullptr /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS)
-ENTRY(nullptr /*FIXME*/, S_ATTR_EXT_RELOC)
-ENTRY(nullptr /*FIXME*/, S_ATTR_LOC_RELOC)
+ENTRY(StringRef() /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS)
+ENTRY(StringRef() /*FIXME*/, S_ATTR_EXT_RELOC)
+ENTRY(StringRef() /*FIXME*/, S_ATTR_LOC_RELOC)
#undef ENTRY
- { 0, "none", nullptr }, // used if section has no attributes but has a stub size
+ { 0, "none", StringRef() }, // used if section has no attributes but has a stub size
};
MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section,
@@ -105,7 +105,7 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
assert(SectionType <= MachO::LAST_KNOWN_SECTION_TYPE &&
"Invalid SectionType specified!");
- if (SectionTypeDescriptors[SectionType].AssemblerName) {
+ if (!SectionTypeDescriptors[SectionType].AssemblerName.empty()) {
OS << ',';
OS << SectionTypeDescriptors[SectionType].AssemblerName;
} else {
@@ -138,7 +138,7 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag;
OS << Separator;
- if (SectionAttrDescriptors[i].AssemblerName)
+ if (!SectionAttrDescriptors[i].AssemblerName.empty())
OS << SectionAttrDescriptors[i].AssemblerName;
else
OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>";
@@ -212,8 +212,7 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
auto TypeDescriptor = std::find_if(
std::begin(SectionTypeDescriptors), std::end(SectionTypeDescriptors),
[&](decltype(*SectionTypeDescriptors) &Descriptor) {
- return Descriptor.AssemblerName &&
- SectionType == Descriptor.AssemblerName;
+ return SectionType == Descriptor.AssemblerName;
});
// If we didn't find the section type, reject it.
@@ -241,8 +240,7 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
auto AttrDescriptorI = std::find_if(
std::begin(SectionAttrDescriptors), std::end(SectionAttrDescriptors),
[&](decltype(*SectionAttrDescriptors) &Descriptor) {
- return Descriptor.AssemblerName &&
- SectionAttr.trim() == Descriptor.AssemblerName;
+ return SectionAttr.trim() == Descriptor.AssemblerName;
});
if (AttrDescriptorI == std::end(SectionAttrDescriptors))
return "mach-o section specifier has invalid attribute";
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index 6c8828f71ba2..fb28f856f671 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/lib/MC/MCStreamer.cpp
@@ -12,6 +12,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeView.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
@@ -124,7 +125,23 @@ void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
if (!IsSectionRelative)
EmitValueImpl(MCSymbolRefExpr::create(Sym, getContext()), Size);
else
- EmitCOFFSecRel32(Sym);
+ EmitCOFFSecRel32(Sym, /*Offset=*/0);
+}
+
+void MCStreamer::EmitDTPRel64Value(const MCExpr *Value) {
+ report_fatal_error("unsupported directive in streamer");
+}
+
+void MCStreamer::EmitDTPRel32Value(const MCExpr *Value) {
+ report_fatal_error("unsupported directive in streamer");
+}
+
+void MCStreamer::EmitTPRel64Value(const MCExpr *Value) {
+ report_fatal_error("unsupported directive in streamer");
+}
+
+void MCStreamer::EmitTPRel32Value(const MCExpr *Value) {
+ report_fatal_error("unsupported directive in streamer");
}
void MCStreamer::EmitGPRel64Value(const MCExpr *Value) {
@@ -199,26 +216,58 @@ void MCStreamer::EnsureValidDwarfFrame() {
report_fatal_error("No open frame");
}
-unsigned MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
- return getContext().getCVFile(Filename, FileNo);
+bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
+ return getContext().getCVContext().addFile(FileNo, Filename);
+}
+
+bool MCStreamer::EmitCVFuncIdDirective(unsigned FunctionId) {
+ return getContext().getCVContext().recordFunctionId(FunctionId);
+}
+
+bool MCStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
+ unsigned IAFunc, unsigned IAFile,
+ unsigned IALine, unsigned IACol,
+ SMLoc Loc) {
+ if (getContext().getCVContext().getCVFunctionInfo(IAFunc) == nullptr) {
+ getContext().reportError(Loc, "parent function id not introduced by "
+ ".cv_func_id or .cv_inline_site_id");
+ return true;
+ }
+
+ return getContext().getCVContext().recordInlinedCallSiteId(
+ FunctionId, IAFunc, IAFile, IALine, IACol);
}
void MCStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
unsigned Line, unsigned Column,
bool PrologueEnd, bool IsStmt,
- StringRef FileName) {
- getContext().setCurrentCVLoc(FunctionId, FileNo, Line, Column, PrologueEnd,
- IsStmt);
+ StringRef FileName, SMLoc Loc) {
+ CodeViewContext &CVC = getContext().getCVContext();
+ MCCVFunctionInfo *FI = CVC.getCVFunctionInfo(FunctionId);
+ if (!FI)
+ return getContext().reportError(
+ Loc, "function id not introduced by .cv_func_id or .cv_inline_site_id");
+
+ // Track the section
+ if (FI->Section == nullptr)
+ FI->Section = getCurrentSectionOnly();
+ else if (FI->Section != getCurrentSectionOnly())
+ return getContext().reportError(
+ Loc,
+ "all .cv_loc directives for a function must be in the same section");
+
+ CVC.setCurrentCVLoc(FunctionId, FileNo, Line, Column, PrologueEnd, IsStmt);
}
void MCStreamer::EmitCVLinetableDirective(unsigned FunctionId,
const MCSymbol *Begin,
const MCSymbol *End) {}
-void MCStreamer::EmitCVInlineLinetableDirective(
- unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
- const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
- ArrayRef<unsigned> SecondaryFunctionIds) {}
+void MCStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
+ unsigned SourceFileId,
+ unsigned SourceLineNum,
+ const MCSymbol *FnStartSym,
+ const MCSymbol *FnEndSym) {}
void MCStreamer::EmitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
@@ -243,7 +292,7 @@ void MCStreamer::AssignFragment(MCSymbol *Symbol, MCFragment *Fragment) {
void MCStreamer::EmitLabel(MCSymbol *Symbol) {
assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
- assert(getCurrentSection().first && "Cannot emit before setting section!");
+ assert(getCurrentSectionOnly() && "Cannot emit before setting section!");
assert(!Symbol->getFragment() && "Unexpected fragment on symbol data!");
Symbol->setFragment(&getCurrentSectionOnly()->getDummyFragment());
@@ -292,13 +341,17 @@ void MCStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
Frame.End = (MCSymbol *) 1;
}
-MCSymbol *MCStreamer::EmitCFICommon() {
- EnsureValidDwarfFrame();
- MCSymbol *Label = getContext().createTempSymbol();
+MCSymbol *MCStreamer::EmitCFILabel() {
+ MCSymbol *Label = getContext().createTempSymbol("cfi", true);
EmitLabel(Label);
return Label;
}
+MCSymbol *MCStreamer::EmitCFICommon() {
+ EnsureValidDwarfFrame();
+ return EmitCFILabel();
+}
+
void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
MCSymbol *Label = EmitCFICommon();
MCCFIInstruction Instruction =
@@ -455,8 +508,7 @@ void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) {
if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End)
report_fatal_error("Starting a function before ending the previous one!");
- MCSymbol *StartProc = getContext().createTempSymbol();
- EmitLabel(StartProc);
+ MCSymbol *StartProc = EmitCFILabel();
WinFrameInfos.push_back(new WinEH::FrameInfo(Symbol, StartProc));
CurrentWinFrameInfo = WinFrameInfos.back();
@@ -468,16 +520,14 @@ void MCStreamer::EmitWinCFIEndProc() {
if (CurrentWinFrameInfo->ChainedParent)
report_fatal_error("Not all chained regions terminated!");
- MCSymbol *Label = getContext().createTempSymbol();
- EmitLabel(Label);
+ MCSymbol *Label = EmitCFILabel();
CurrentWinFrameInfo->End = Label;
}
void MCStreamer::EmitWinCFIStartChained() {
EnsureValidWinFrameInfo();
- MCSymbol *StartProc = getContext().createTempSymbol();
- EmitLabel(StartProc);
+ MCSymbol *StartProc = EmitCFILabel();
WinFrameInfos.push_back(new WinEH::FrameInfo(CurrentWinFrameInfo->Function,
StartProc, CurrentWinFrameInfo));
@@ -490,8 +540,7 @@ void MCStreamer::EmitWinCFIEndChained() {
if (!CurrentWinFrameInfo->ChainedParent)
report_fatal_error("End of a chained region outside a chained region!");
- MCSymbol *Label = getContext().createTempSymbol();
- EmitLabel(Label);
+ MCSymbol *Label = EmitCFILabel();
CurrentWinFrameInfo->End = Label;
CurrentWinFrameInfo =
@@ -555,8 +604,7 @@ void MCStreamer::EmitSyntaxDirective() {}
void MCStreamer::EmitWinCFIPushReg(unsigned Register) {
EnsureValidWinFrameInfo();
- MCSymbol *Label = getContext().createTempSymbol();
- EmitLabel(Label);
+ MCSymbol *Label = EmitCFILabel();
WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(Label, Register);
CurrentWinFrameInfo->Instructions.push_back(Inst);
@@ -571,8 +619,7 @@ void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) {
if (Offset > 240)
report_fatal_error("Frame offset must be less than or equal to 240!");
- MCSymbol *Label = getContext().createTempSymbol();
- EmitLabel(Label);
+ MCSymbol *Label = EmitCFILabel();
WinEH::Instruction Inst =
Win64EH::Instruction::SetFPReg(Label, Register, Offset);
@@ -587,8 +634,7 @@ void MCStreamer::EmitWinCFIAllocStack(unsigned Size) {
if (Size & 7)
report_fatal_error("Misaligned stack allocation!");
- MCSymbol *Label = getContext().createTempSymbol();
- EmitLabel(Label);
+ MCSymbol *Label = EmitCFILabel();
WinEH::Instruction Inst = Win64EH::Instruction::Alloc(Label, Size);
CurrentWinFrameInfo->Instructions.push_back(Inst);
@@ -599,8 +645,7 @@ void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) {
if (Offset & 7)
report_fatal_error("Misaligned saved register offset!");
- MCSymbol *Label = getContext().createTempSymbol();
- EmitLabel(Label);
+ MCSymbol *Label = EmitCFILabel();
WinEH::Instruction Inst =
Win64EH::Instruction::SaveNonVol(Label, Register, Offset);
@@ -612,8 +657,7 @@ void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) {
if (Offset & 0x0F)
report_fatal_error("Misaligned saved vector register offset!");
- MCSymbol *Label = getContext().createTempSymbol();
- EmitLabel(Label);
+ MCSymbol *Label = EmitCFILabel();
WinEH::Instruction Inst =
Win64EH::Instruction::SaveXMM(Label, Register, Offset);
@@ -625,8 +669,7 @@ void MCStreamer::EmitWinCFIPushFrame(bool Code) {
if (CurrentWinFrameInfo->Instructions.size() > 0)
report_fatal_error("If present, PushMachFrame must be the first UOP");
- MCSymbol *Label = getContext().createTempSymbol();
- EmitLabel(Label);
+ MCSymbol *Label = EmitCFILabel();
WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(Label, Code);
CurrentWinFrameInfo->Instructions.push_back(Inst);
@@ -635,8 +678,7 @@ void MCStreamer::EmitWinCFIPushFrame(bool Code) {
void MCStreamer::EmitWinCFIEndProlog() {
EnsureValidWinFrameInfo();
- MCSymbol *Label = getContext().createTempSymbol();
- EmitLabel(Label);
+ MCSymbol *Label = EmitCFILabel();
CurrentWinFrameInfo->PrologEnd = Label;
}
@@ -647,8 +689,7 @@ void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
}
-void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {
-}
+void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {}
/// EmitRawText - If this file is backed by an assembly streamer, this dumps
/// the specified string in the output .s file. This capability is
@@ -756,7 +797,7 @@ void MCStreamer::EndCOFFSymbolDef() {}
void MCStreamer::EmitFileDirective(StringRef Filename) {}
void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {}
void MCStreamer::EmitCOFFSymbolType(int Type) {}
-void MCStreamer::emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) {}
+void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
void MCStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {}
void MCStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
@@ -778,7 +819,8 @@ void MCStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
unsigned MaxBytesToEmit) {}
void MCStreamer::EmitCodeAlignment(unsigned ByteAlignment,
unsigned MaxBytesToEmit) {}
-void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value) {}
+void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value,
+ SMLoc Loc) {}
void MCStreamer::EmitBundleAlignMode(unsigned AlignPow2) {}
void MCStreamer::EmitBundleLock(bool AlignToEnd) {}
void MCStreamer::FinishImpl() {}
diff --git a/lib/MC/MCSymbol.cpp b/lib/MC/MCSymbol.cpp
index 2ddece6bddce..20d985df7ea0 100644
--- a/lib/MC/MCSymbol.cpp
+++ b/lib/MC/MCSymbol.cpp
@@ -31,10 +31,9 @@ void *MCSymbol::operator new(size_t s, const StringMapEntry<bool> *Name,
// For safety, ensure that the alignment of a pointer is enough for an
// MCSymbol. This also ensures we don't need padding between the name and
// symbol.
- static_assert((unsigned)AlignOf<MCSymbol>::Alignment <=
- AlignOf<NameEntryStorageTy>::Alignment,
+ static_assert((unsigned)alignof(MCSymbol) <= alignof(NameEntryStorageTy),
"Bad alignment of MCSymbol");
- void *Storage = Ctx.allocate(Size, alignOf<NameEntryStorageTy>());
+ void *Storage = Ctx.allocate(Size, alignof(NameEntryStorageTy));
NameEntryStorageTy *Start = static_cast<NameEntryStorageTy*>(Storage);
NameEntryStorageTy *End = Start + (Name ? 1 : 0);
return End;
@@ -76,6 +75,4 @@ void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
OS << '"';
}
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MCSymbol::dump() const { dbgs() << *this; }
-#endif
diff --git a/lib/MC/MCTargetOptions.cpp b/lib/MC/MCTargetOptions.cpp
index 465622715526..419210537eea 100644
--- a/lib/MC/MCTargetOptions.cpp
+++ b/lib/MC/MCTargetOptions.cpp
@@ -14,10 +14,12 @@ namespace llvm {
MCTargetOptions::MCTargetOptions()
: SanitizeAddress(false), MCRelaxAll(false), MCNoExecStack(false),
- MCFatalWarnings(false), MCNoWarn(false), MCSaveTempLabels(false),
+ MCFatalWarnings(false), MCNoWarn(false), MCNoDeprecatedWarn(false),
+ MCSaveTempLabels(false),
MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false),
- ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
- DwarfVersion(0), ABIName() {}
+ MCPIECopyRelocations(false), ShowMCEncoding(false),
+ ShowMCInst(false), AsmVerbose(false),
+ PreserveAsmComments(true), DwarfVersion(0), ABIName() {}
StringRef MCTargetOptions::getABIName() const {
return ABIName;
diff --git a/lib/MC/MCValue.cpp b/lib/MC/MCValue.cpp
index 32a6adbf224e..c1336d6d1b49 100644
--- a/lib/MC/MCValue.cpp
+++ b/lib/MC/MCValue.cpp
@@ -37,11 +37,9 @@ void MCValue::print(raw_ostream &OS) const {
OS << " + " << getConstant();
}
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MCValue::dump() const {
print(dbgs());
}
-#endif
MCSymbolRefExpr::VariantKind MCValue::getAccessVariant() const {
const MCSymbolRefExpr *B = getSymB();
diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp
index e39271949d94..c4b35f5db9b4 100644
--- a/lib/MC/MachObjectWriter.cpp
+++ b/lib/MC/MachObjectWriter.cpp
@@ -422,7 +422,7 @@ void MachObjectWriter::writeLinkerOptionsLoadCommand(
uint64_t BytesWritten = sizeof(MachO::linker_option_command);
for (const std::string &Option : Options) {
// Write each string, including the null byte.
- writeBytes(Option.c_str(), Option.size() + 1);
+ writeBytes(Option, Option.size() + 1);
BytesWritten += Option.size() + 1;
}
@@ -882,7 +882,7 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
sizeof(MachO::nlist_64) :
sizeof(MachO::nlist));
writeSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
- StringTableOffset, StringTable.data().size());
+ StringTableOffset, StringTable.getSize());
writeDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
FirstExternalSymbol, NumExternalSymbols,
@@ -977,7 +977,7 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
writeNlist(Entry, Layout);
// Write the string table.
- getStream() << StringTable.data();
+ StringTable.write(getStream());
}
}
diff --git a/lib/MC/StringTableBuilder.cpp b/lib/MC/StringTableBuilder.cpp
index 9d95952a6d30..1a501bcafc12 100644
--- a/lib/MC/StringTableBuilder.cpp
+++ b/lib/MC/StringTableBuilder.cpp
@@ -9,15 +9,18 @@
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/raw_ostream.h"
#include <vector>
using namespace llvm;
-StringTableBuilder::StringTableBuilder(Kind K, unsigned Alignment)
- : K(K), Alignment(Alignment) {
+StringTableBuilder::~StringTableBuilder() {}
+
+void StringTableBuilder::initSize() {
// Account for leading bytes in table so that offsets returned from add are
// correct.
switch (K) {
@@ -26,19 +29,46 @@ StringTableBuilder::StringTableBuilder(Kind K, unsigned Alignment)
break;
case MachO:
case ELF:
+ // Start the table with a NUL byte.
Size = 1;
break;
case WinCOFF:
+ // Make room to write the table size later.
Size = 4;
break;
}
}
-typedef std::pair<CachedHash<StringRef>, size_t> StringPair;
+StringTableBuilder::StringTableBuilder(Kind K, unsigned Alignment)
+ : K(K), Alignment(Alignment) {
+ initSize();
+}
+
+void StringTableBuilder::write(raw_ostream &OS) const {
+ assert(isFinalized());
+ SmallString<0> Data;
+ Data.resize(getSize());
+ write((uint8_t *)&Data[0]);
+ OS << Data;
+}
+
+typedef std::pair<CachedHashStringRef, size_t> StringPair;
+
+void StringTableBuilder::write(uint8_t *Buf) const {
+ assert(isFinalized());
+ for (const StringPair &P : StringIndexMap) {
+ StringRef Data = P.first.val();
+ if (!Data.empty())
+ memcpy(Buf + P.second, Data.data(), Data.size());
+ }
+ if (K != WinCOFF)
+ return;
+ support::endian::write32le(Buf, Size);
+}
// Returns the character at Pos from end of a string.
static int charTailAt(StringPair *P, size_t Pos) {
- StringRef S = P->first.Val;
+ StringRef S = P->first.val();
if (Pos >= S.size())
return -1;
return (unsigned char)S[S.size() - Pos - 1];
@@ -86,106 +116,69 @@ void StringTableBuilder::finalizeInOrder() {
}
void StringTableBuilder::finalizeStringTable(bool Optimize) {
- typedef std::pair<CachedHash<StringRef>, size_t> StringOffsetPair;
- std::vector<StringOffsetPair *> Strings;
- Strings.reserve(StringIndexMap.size());
- for (StringOffsetPair &P : StringIndexMap)
- Strings.push_back(&P);
-
- if (!Strings.empty()) {
- // If we're optimizing, sort by name. If not, sort by previously assigned
- // offset.
- if (Optimize) {
- multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 0);
- } else {
- std::sort(Strings.begin(), Strings.end(),
- [](const StringOffsetPair *LHS, const StringOffsetPair *RHS) {
- return LHS->second < RHS->second;
- });
- }
- }
+ Finalized = true;
- switch (K) {
- case RAW:
- break;
- case ELF:
- case MachO:
- // Start the table with a NUL byte.
- StringTable += '\x00';
- break;
- case WinCOFF:
- // Make room to write the table size later.
- StringTable.append(4, '\x00');
- break;
- }
+ if (Optimize) {
+ std::vector<StringPair *> Strings;
+ Strings.reserve(StringIndexMap.size());
+ for (StringPair &P : StringIndexMap)
+ Strings.push_back(&P);
- StringRef Previous;
- for (StringOffsetPair *P : Strings) {
- StringRef S = P->first.Val;
- if (K == WinCOFF)
- assert(S.size() > COFF::NameSize && "Short string in COFF string table!");
-
- if (Optimize && Previous.endswith(S)) {
- size_t Pos = StringTable.size() - S.size() - (K != RAW);
- if (!(Pos & (Alignment - 1))) {
- P->second = Pos;
- continue;
- }
+ if (!Strings.empty()) {
+ // If we're optimizing, sort by name. If not, sort by previously assigned
+ // offset.
+ multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 0);
}
- if (Optimize) {
- size_t Start = alignTo(StringTable.size(), Alignment);
- P->second = Start;
- StringTable.append(Start - StringTable.size(), '\0');
- } else {
- assert(P->second == StringTable.size() &&
- "different strtab offset after finalization");
- }
+ initSize();
+
+ StringRef Previous;
+ for (StringPair *P : Strings) {
+ StringRef S = P->first.val();
+ if (Previous.endswith(S)) {
+ size_t Pos = Size - S.size() - (K != RAW);
+ if (!(Pos & (Alignment - 1))) {
+ P->second = Pos;
+ continue;
+ }
+ }
- StringTable += S;
- if (K != RAW)
- StringTable += '\x00';
- Previous = S;
- }
+ Size = alignTo(Size, Alignment);
+ P->second = Size;
- switch (K) {
- case RAW:
- case ELF:
- break;
- case MachO:
- // Pad to multiple of 4.
- while (StringTable.size() % 4)
- StringTable += '\x00';
- break;
- case WinCOFF:
- // Write the table size in the first word.
- assert(StringTable.size() <= std::numeric_limits<uint32_t>::max());
- uint32_t Size = static_cast<uint32_t>(StringTable.size());
- support::endian::write<uint32_t, support::little, support::unaligned>(
- StringTable.data(), Size);
- break;
+ Size += S.size();
+ if (K != RAW)
+ ++Size;
+ Previous = S;
+ }
}
- Size = StringTable.size();
+ if (K == MachO)
+ Size = alignTo(Size, 4); // Pad to multiple of 4.
}
void StringTableBuilder::clear() {
- StringTable.clear();
+ Finalized = false;
StringIndexMap.clear();
}
-size_t StringTableBuilder::getOffset(StringRef S) const {
+size_t StringTableBuilder::getOffset(CachedHashStringRef S) const {
assert(isFinalized());
auto I = StringIndexMap.find(S);
assert(I != StringIndexMap.end() && "String is not in table!");
return I->second;
}
-size_t StringTableBuilder::add(StringRef S) {
+size_t StringTableBuilder::add(CachedHashStringRef S) {
+ if (K == WinCOFF)
+ assert(S.size() > COFF::NameSize && "Short string in COFF string table!");
+
assert(!isFinalized());
- size_t Start = alignTo(Size, Alignment);
- auto P = StringIndexMap.insert(std::make_pair(S, Start));
- if (P.second)
+ auto P = StringIndexMap.insert(std::make_pair(S, 0));
+ if (P.second) {
+ size_t Start = alignTo(Size, Alignment);
+ P.first->second = Start;
Size = Start + S.size() + (K != RAW);
+ }
return P.first->second;
}
diff --git a/lib/MC/SubtargetFeature.cpp b/lib/MC/SubtargetFeature.cpp
index a97cd1db6932..32f06f8a7d6a 100644
--- a/lib/MC/SubtargetFeature.cpp
+++ b/lib/MC/SubtargetFeature.cpp
@@ -282,13 +282,11 @@ void SubtargetFeatures::print(raw_ostream &OS) const {
OS << "\n";
}
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
/// dump - Dump feature info.
///
LLVM_DUMP_METHOD void SubtargetFeatures::dump() const {
print(dbgs());
}
-#endif
/// Adds the default features for the specified target triple.
///
diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp
index f316a5af387d..afc5c6a14d11 100644
--- a/lib/MC/WinCOFFObjectWriter.cpp
+++ b/lib/MC/WinCOFFObjectWriter.cpp
@@ -34,7 +34,6 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/JamCRC.h"
-#include "llvm/Support/TimeValue.h"
#include <cstdio>
#include <ctime>
@@ -792,7 +791,7 @@ void WinCOFFObjectWriter::recordRelocation(
}
}
- // The fixed value never makes sense for section indicies, ignore it.
+ // The fixed value never makes sense for section indices, ignore it.
if (Fixup.getKind() == FK_SecRel_2)
FixedValue = 0;
@@ -1082,7 +1081,7 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
if (Symbol->getIndex() != -1)
WriteSymbol(*Symbol);
- getStream().write(Strings.data().data(), Strings.data().size());
+ Strings.write(getStream());
}
MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_)
diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp
index 5c6407ef1e5c..6383d8794030 100644
--- a/lib/MC/WinCOFFStreamer.cpp
+++ b/lib/MC/WinCOFFStreamer.cpp
@@ -195,11 +195,20 @@ void MCWinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
DF->getContents().resize(DF->getContents().size() + 2, 0);
}
-void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {
+void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol,
+ uint64_t Offset) {
MCDataFragment *DF = getOrCreateDataFragment();
- const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
- MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_4);
+ // Create Symbol A for the relocation relative reference.
+ const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext());
+ // Add the constant offset, if given.
+ if (Offset)
+ MCE = MCBinaryExpr::createAdd(
+ MCE, MCConstantExpr::create(Offset, getContext()), getContext());
+ // Build the secrel32 relocation.
+ MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4);
+ // Record the relocation.
DF->getFixups().push_back(Fixup);
+ // Emit 4 bytes (zeros) to the object file.
DF->getContents().resize(DF->getContents().size() + 4, 0);
}