summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/MC/MCParser/AsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/MC/MCParser/AsmParser.cpp')
-rw-r--r--contrib/llvm/lib/MC/MCParser/AsmParser.cpp1556
1 files changed, 931 insertions, 625 deletions
diff --git a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp
index 1548aee..da54155 100644
--- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/contrib/llvm/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,
OpenPOWER on IntegriCloud