aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/lib/MC/MCParser
diff options
context:
space:
mode:
authororivej <orivej@yandex-team.ru>2022-02-10 16:45:01 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:01 +0300
commit2d37894b1b037cf24231090eda8589bbb44fb6fc (patch)
treebe835aa92c6248212e705f25388ebafcf84bc7a1 /contrib/libs/llvm12/lib/MC/MCParser
parent718c552901d703c502ccbefdfc3c9028d608b947 (diff)
downloadydb-2d37894b1b037cf24231090eda8589bbb44fb6fc.tar.gz
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/llvm12/lib/MC/MCParser')
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/AsmLexer.cpp1484
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/AsmParser.cpp12236
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/COFFAsmParser.cpp1434
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/COFFMasmParser.cpp686
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/DarwinAsmParser.cpp2416
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/ELFAsmParser.cpp1752
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/MCAsmLexer.cpp258
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/MCAsmParser.cpp282
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/MCAsmParserExtension.cpp124
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/MCTargetAsmParser.cpp58
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/MasmParser.cpp12274
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/WasmAsmParser.cpp468
-rw-r--r--contrib/libs/llvm12/lib/MC/MCParser/ya.make58
13 files changed, 16765 insertions, 16765 deletions
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/AsmLexer.cpp b/contrib/libs/llvm12/lib/MC/MCParser/AsmLexer.cpp
index f075f3cfd4..1fa22ab000 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/AsmLexer.cpp
+++ b/contrib/libs/llvm12/lib/MC/MCParser/AsmLexer.cpp
@@ -1,283 +1,283 @@
-//===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements the lexer for assembly files.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCParser/AsmLexer.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
+//===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements the lexer for assembly files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/AsmLexer.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/SaveAndRestore.h"
-#include <cassert>
-#include <cctype>
-#include <cstdio>
-#include <cstring>
-#include <string>
-#include <tuple>
-#include <utility>
-
-using namespace llvm;
-
-AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) {
- AllowAtInIdentifier = !StringRef(MAI.getCommentString()).startswith("@");
-}
-
-AsmLexer::~AsmLexer() = default;
-
-void AsmLexer::setBuffer(StringRef Buf, const char *ptr,
- bool EndStatementAtEOF) {
- CurBuf = Buf;
-
- if (ptr)
- CurPtr = ptr;
- else
- CurPtr = CurBuf.begin();
-
- TokStart = nullptr;
- this->EndStatementAtEOF = EndStatementAtEOF;
-}
-
-/// ReturnError - Set the error to the specified string at the specified
-/// location. This is defined to always return AsmToken::Error.
-AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
- SetError(SMLoc::getFromPointer(Loc), Msg);
-
- return AsmToken(AsmToken::Error, StringRef(Loc, CurPtr - Loc));
-}
-
-int AsmLexer::getNextChar() {
- if (CurPtr == CurBuf.end())
- return EOF;
- return (unsigned char)*CurPtr++;
-}
-
+#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include <cassert>
+#include <cctype>
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include <tuple>
+#include <utility>
+
+using namespace llvm;
+
+AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) {
+ AllowAtInIdentifier = !StringRef(MAI.getCommentString()).startswith("@");
+}
+
+AsmLexer::~AsmLexer() = default;
+
+void AsmLexer::setBuffer(StringRef Buf, const char *ptr,
+ bool EndStatementAtEOF) {
+ CurBuf = Buf;
+
+ if (ptr)
+ CurPtr = ptr;
+ else
+ CurPtr = CurBuf.begin();
+
+ TokStart = nullptr;
+ this->EndStatementAtEOF = EndStatementAtEOF;
+}
+
+/// ReturnError - Set the error to the specified string at the specified
+/// location. This is defined to always return AsmToken::Error.
+AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
+ SetError(SMLoc::getFromPointer(Loc), Msg);
+
+ return AsmToken(AsmToken::Error, StringRef(Loc, CurPtr - Loc));
+}
+
+int AsmLexer::getNextChar() {
+ if (CurPtr == CurBuf.end())
+ return EOF;
+ return (unsigned char)*CurPtr++;
+}
+
int AsmLexer::peekNextChar() {
if (CurPtr == CurBuf.end())
return EOF;
return (unsigned char)*CurPtr;
}
-/// The leading integral digit sequence and dot should have already been
-/// consumed, some or all of the fractional digit sequence *can* have been
-/// consumed.
-AsmToken AsmLexer::LexFloatLiteral() {
- // Skip the fractional digit sequence.
- while (isDigit(*CurPtr))
- ++CurPtr;
-
- if (*CurPtr == '-' || *CurPtr == '+')
- return ReturnError(CurPtr, "Invalid sign in float literal");
-
- // Check for exponent
- if ((*CurPtr == 'e' || *CurPtr == 'E')) {
- ++CurPtr;
-
- if (*CurPtr == '-' || *CurPtr == '+')
- ++CurPtr;
-
- while (isDigit(*CurPtr))
- ++CurPtr;
- }
-
- return AsmToken(AsmToken::Real,
- StringRef(TokStart, CurPtr - TokStart));
-}
-
-/// LexHexFloatLiteral matches essentially (.[0-9a-fA-F]*)?[pP][+-]?[0-9a-fA-F]+
-/// while making sure there are enough actual digits around for the constant to
-/// be valid.
-///
-/// The leading "0x[0-9a-fA-F]*" (i.e. integer part) has already been consumed
-/// before we get here.
-AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) {
- assert((*CurPtr == 'p' || *CurPtr == 'P' || *CurPtr == '.') &&
- "unexpected parse state in floating hex");
- bool NoFracDigits = true;
-
- // Skip the fractional part if there is one
- if (*CurPtr == '.') {
- ++CurPtr;
-
- const char *FracStart = CurPtr;
- while (isHexDigit(*CurPtr))
- ++CurPtr;
-
- NoFracDigits = CurPtr == FracStart;
- }
-
- if (NoIntDigits && NoFracDigits)
- return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
- "expected at least one significand digit");
-
- // Make sure we do have some kind of proper exponent part
- if (*CurPtr != 'p' && *CurPtr != 'P')
- return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
- "expected exponent part 'p'");
- ++CurPtr;
-
- if (*CurPtr == '+' || *CurPtr == '-')
- ++CurPtr;
-
- // N.b. exponent digits are *not* hex
- const char *ExpStart = CurPtr;
- while (isDigit(*CurPtr))
- ++CurPtr;
-
- if (CurPtr == ExpStart)
- return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
- "expected at least one exponent digit");
-
- return AsmToken(AsmToken::Real, StringRef(TokStart, CurPtr - TokStart));
-}
-
-/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@?]*
-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)) {
- // Disambiguate a .1243foo identifier from a floating literal.
- while (isDigit(*CurPtr))
- ++CurPtr;
-
- if (!IsIdentifierChar(*CurPtr, AllowAtInIdentifier) ||
- *CurPtr == 'e' || *CurPtr == 'E')
- return LexFloatLiteral();
- }
-
- while (IsIdentifierChar(*CurPtr, AllowAtInIdentifier))
- ++CurPtr;
-
- // Handle . as a special case.
- if (CurPtr == TokStart+1 && TokStart[0] == '.')
- return AsmToken(AsmToken::Dot, StringRef(TokStart, 1));
-
- return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart));
-}
-
-/// LexSlash: Slash: /
-/// C-Style Comment: /* ... */
-AsmToken AsmLexer::LexSlash() {
- switch (*CurPtr) {
- case '*':
- IsAtStartOfStatement = false;
- break; // C style comment.
- case '/':
- ++CurPtr;
- return LexLineComment();
- default:
- IsAtStartOfStatement = false;
- return AsmToken(AsmToken::Slash, StringRef(TokStart, 1));
- }
-
- // 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));
- }
- }
- return ReturnError(TokStart, "unterminated comment");
-}
-
-/// LexLineComment: Comment: #[^\n]*
-/// : //[^\n]*
-AsmToken AsmLexer::LexLineComment() {
- // Mark This as an end of statement with a body of the
- // 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 (CurChar == '\r' && CurPtr != CurBuf.end() && *CurPtr == '\n')
- ++CurPtr;
-
- // If we have a CommentConsumer, notify it about the comment.
- if (CommentConsumer) {
- CommentConsumer->HandleComment(
- SMLoc::getFromPointer(CommentTextStart),
- StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
- }
-
- IsAtStartOfLine = true;
- // This is a whole line comment. leave newline
- if (IsAtStartOfStatement)
- return AsmToken(AsmToken::EndOfStatement,
- StringRef(TokStart, CurPtr - TokStart));
- IsAtStartOfStatement = true;
-
- return AsmToken(AsmToken::EndOfStatement,
- StringRef(TokStart, CurPtr - 1 - TokStart));
-}
-
-static void SkipIgnoredIntegerSuffix(const char *&CurPtr) {
- // Skip ULL, UL, U, L and LL suffices.
- if (CurPtr[0] == 'U')
- ++CurPtr;
- if (CurPtr[0] == 'L')
- ++CurPtr;
- if (CurPtr[0] == 'L')
- ++CurPtr;
-}
-
-// Look ahead to search for first non-hex digit, if it's [hH], then we treat the
-// integer as a hexadecimal, possibly with leading zeroes.
-static unsigned doHexLookAhead(const char *&CurPtr, unsigned DefaultRadix,
- bool LexHex) {
- const char *FirstNonDec = nullptr;
- const char *LookAhead = CurPtr;
- while (true) {
- if (isDigit(*LookAhead)) {
- ++LookAhead;
- } else {
- if (!FirstNonDec)
- FirstNonDec = LookAhead;
-
- // Keep going if we are looking for a 'h' suffix.
- if (LexHex && isHexDigit(*LookAhead))
- ++LookAhead;
- else
- break;
- }
- }
- bool isHex = LexHex && (*LookAhead == 'h' || *LookAhead == 'H');
- CurPtr = isHex || !FirstNonDec ? LookAhead : FirstNonDec;
- if (isHex)
- return 16;
- return DefaultRadix;
-}
-
+/// The leading integral digit sequence and dot should have already been
+/// consumed, some or all of the fractional digit sequence *can* have been
+/// consumed.
+AsmToken AsmLexer::LexFloatLiteral() {
+ // Skip the fractional digit sequence.
+ while (isDigit(*CurPtr))
+ ++CurPtr;
+
+ if (*CurPtr == '-' || *CurPtr == '+')
+ return ReturnError(CurPtr, "Invalid sign in float literal");
+
+ // Check for exponent
+ if ((*CurPtr == 'e' || *CurPtr == 'E')) {
+ ++CurPtr;
+
+ if (*CurPtr == '-' || *CurPtr == '+')
+ ++CurPtr;
+
+ while (isDigit(*CurPtr))
+ ++CurPtr;
+ }
+
+ return AsmToken(AsmToken::Real,
+ StringRef(TokStart, CurPtr - TokStart));
+}
+
+/// LexHexFloatLiteral matches essentially (.[0-9a-fA-F]*)?[pP][+-]?[0-9a-fA-F]+
+/// while making sure there are enough actual digits around for the constant to
+/// be valid.
+///
+/// The leading "0x[0-9a-fA-F]*" (i.e. integer part) has already been consumed
+/// before we get here.
+AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) {
+ assert((*CurPtr == 'p' || *CurPtr == 'P' || *CurPtr == '.') &&
+ "unexpected parse state in floating hex");
+ bool NoFracDigits = true;
+
+ // Skip the fractional part if there is one
+ if (*CurPtr == '.') {
+ ++CurPtr;
+
+ const char *FracStart = CurPtr;
+ while (isHexDigit(*CurPtr))
+ ++CurPtr;
+
+ NoFracDigits = CurPtr == FracStart;
+ }
+
+ if (NoIntDigits && NoFracDigits)
+ return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
+ "expected at least one significand digit");
+
+ // Make sure we do have some kind of proper exponent part
+ if (*CurPtr != 'p' && *CurPtr != 'P')
+ return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
+ "expected exponent part 'p'");
+ ++CurPtr;
+
+ if (*CurPtr == '+' || *CurPtr == '-')
+ ++CurPtr;
+
+ // N.b. exponent digits are *not* hex
+ const char *ExpStart = CurPtr;
+ while (isDigit(*CurPtr))
+ ++CurPtr;
+
+ if (CurPtr == ExpStart)
+ return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
+ "expected at least one exponent digit");
+
+ return AsmToken(AsmToken::Real, StringRef(TokStart, CurPtr - TokStart));
+}
+
+/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@?]*
+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)) {
+ // Disambiguate a .1243foo identifier from a floating literal.
+ while (isDigit(*CurPtr))
+ ++CurPtr;
+
+ if (!IsIdentifierChar(*CurPtr, AllowAtInIdentifier) ||
+ *CurPtr == 'e' || *CurPtr == 'E')
+ return LexFloatLiteral();
+ }
+
+ while (IsIdentifierChar(*CurPtr, AllowAtInIdentifier))
+ ++CurPtr;
+
+ // Handle . as a special case.
+ if (CurPtr == TokStart+1 && TokStart[0] == '.')
+ return AsmToken(AsmToken::Dot, StringRef(TokStart, 1));
+
+ return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart));
+}
+
+/// LexSlash: Slash: /
+/// C-Style Comment: /* ... */
+AsmToken AsmLexer::LexSlash() {
+ switch (*CurPtr) {
+ case '*':
+ IsAtStartOfStatement = false;
+ break; // C style comment.
+ case '/':
+ ++CurPtr;
+ return LexLineComment();
+ default:
+ IsAtStartOfStatement = false;
+ return AsmToken(AsmToken::Slash, StringRef(TokStart, 1));
+ }
+
+ // 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));
+ }
+ }
+ return ReturnError(TokStart, "unterminated comment");
+}
+
+/// LexLineComment: Comment: #[^\n]*
+/// : //[^\n]*
+AsmToken AsmLexer::LexLineComment() {
+ // Mark This as an end of statement with a body of the
+ // 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 (CurChar == '\r' && CurPtr != CurBuf.end() && *CurPtr == '\n')
+ ++CurPtr;
+
+ // If we have a CommentConsumer, notify it about the comment.
+ if (CommentConsumer) {
+ CommentConsumer->HandleComment(
+ SMLoc::getFromPointer(CommentTextStart),
+ StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
+ }
+
+ IsAtStartOfLine = true;
+ // This is a whole line comment. leave newline
+ if (IsAtStartOfStatement)
+ return AsmToken(AsmToken::EndOfStatement,
+ StringRef(TokStart, CurPtr - TokStart));
+ IsAtStartOfStatement = true;
+
+ return AsmToken(AsmToken::EndOfStatement,
+ StringRef(TokStart, CurPtr - 1 - TokStart));
+}
+
+static void SkipIgnoredIntegerSuffix(const char *&CurPtr) {
+ // Skip ULL, UL, U, L and LL suffices.
+ if (CurPtr[0] == 'U')
+ ++CurPtr;
+ if (CurPtr[0] == 'L')
+ ++CurPtr;
+ if (CurPtr[0] == 'L')
+ ++CurPtr;
+}
+
+// Look ahead to search for first non-hex digit, if it's [hH], then we treat the
+// integer as a hexadecimal, possibly with leading zeroes.
+static unsigned doHexLookAhead(const char *&CurPtr, unsigned DefaultRadix,
+ bool LexHex) {
+ const char *FirstNonDec = nullptr;
+ const char *LookAhead = CurPtr;
+ while (true) {
+ if (isDigit(*LookAhead)) {
+ ++LookAhead;
+ } else {
+ if (!FirstNonDec)
+ FirstNonDec = LookAhead;
+
+ // Keep going if we are looking for a 'h' suffix.
+ if (LexHex && isHexDigit(*LookAhead))
+ ++LookAhead;
+ else
+ break;
+ }
+ }
+ bool isHex = LexHex && (*LookAhead == 'h' || *LookAhead == 'H');
+ CurPtr = isHex || !FirstNonDec ? LookAhead : FirstNonDec;
+ if (isHex)
+ return 16;
+ return DefaultRadix;
+}
+
static const char *findLastDigit(const char *CurPtr, unsigned DefaultRadix) {
while (hexDigitValue(*CurPtr) < DefaultRadix) {
++CurPtr;
@@ -286,11 +286,11 @@ static const char *findLastDigit(const char *CurPtr, unsigned DefaultRadix) {
}
static AsmToken intToken(StringRef Ref, APInt &Value) {
- if (Value.isIntN(64))
- return AsmToken(AsmToken::Integer, Ref, Value);
- return AsmToken(AsmToken::BigNum, Ref, Value);
-}
-
+ if (Value.isIntN(64))
+ return AsmToken(AsmToken::Integer, Ref, Value);
+ return AsmToken(AsmToken::BigNum, Ref, Value);
+}
+
static std::string radixName(unsigned Radix) {
switch (Radix) {
case 2:
@@ -306,25 +306,25 @@ static std::string radixName(unsigned Radix) {
}
}
-/// LexDigit: First character is [0-9].
-/// Local Label: [0-9][:]
-/// Forward/Backward Label: [0-9][fb]
-/// Binary integer: 0b[01]+
-/// Octal integer: 0[0-7]+
-/// 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() {
+/// LexDigit: First character is [0-9].
+/// Local Label: [0-9][:]
+/// Forward/Backward Label: [0-9][fb]
+/// Binary integer: 0b[01]+
+/// Octal integer: 0[0-7]+
+/// 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]+[yY] (if DefaultRadix < 16, [bByY])
// MASM-flavor octal integer: [0-7]+[oOqQ]
// MASM-flavor decimal integer: [0-9]+[tT] (if DefaultRadix < 16, [dDtT])
- // MASM-flavor hexadecimal integer: [0-9][0-9a-fA-F]*[hH]
- if (LexMasmIntegers && isdigit(CurPtr[-1])) {
+ // MASM-flavor hexadecimal integer: [0-9][0-9a-fA-F]*[hH]
+ if (LexMasmIntegers && isdigit(CurPtr[-1])) {
const char *FirstNonBinary =
(CurPtr[-1] != '0' && CurPtr[-1] != '1') ? CurPtr - 1 : nullptr;
const char *FirstNonDecimal =
(CurPtr[-1] < '0' || CurPtr[-1] > '9') ? CurPtr - 1 : nullptr;
- const char *OldCurPtr = CurPtr;
- while (isHexDigit(*CurPtr)) {
+ const char *OldCurPtr = CurPtr;
+ while (isHexDigit(*CurPtr)) {
switch (*CurPtr) {
default:
if (!FirstNonDecimal) {
@@ -347,25 +347,25 @@ AsmToken AsmLexer::LexDigit() {
case '0':
break;
}
- ++CurPtr;
- }
+ ++CurPtr;
+ }
if (*CurPtr == '.') {
// MASM float literals (other than hex floats) always contain a ".", and
// are always written in decimal.
++CurPtr;
return LexFloatLiteral();
}
-
+
if (LexMasmHexFloats && (*CurPtr == 'r' || *CurPtr == 'R')) {
++CurPtr;
return AsmToken(AsmToken::Real, StringRef(TokStart, CurPtr - TokStart));
}
- unsigned Radix = 0;
- if (*CurPtr == 'h' || *CurPtr == 'H') {
- // hexadecimal number
- ++CurPtr;
- Radix = 16;
+ unsigned Radix = 0;
+ if (*CurPtr == 'h' || *CurPtr == 'H') {
+ // hexadecimal number
+ ++CurPtr;
+ Radix = 16;
} else if (*CurPtr == 't' || *CurPtr == 'T') {
// decimal number
++CurPtr;
@@ -383,29 +383,29 @@ AsmToken AsmLexer::LexDigit() {
DefaultRadix < 14 &&
(*FirstNonDecimal == 'd' || *FirstNonDecimal == 'D')) {
Radix = 10;
- } else if (FirstNonBinary && FirstNonBinary + 1 == CurPtr &&
+ } else if (FirstNonBinary && FirstNonBinary + 1 == CurPtr &&
DefaultRadix < 12 &&
(*FirstNonBinary == 'b' || *FirstNonBinary == 'B')) {
- Radix = 2;
+ Radix = 2;
}
-
+
if (Radix) {
- StringRef Result(TokStart, CurPtr - TokStart);
- APInt Value(128, 0, true);
-
- if (Result.drop_back().getAsInteger(Radix, Value))
+ StringRef Result(TokStart, CurPtr - TokStart);
+ APInt Value(128, 0, true);
+
+ if (Result.drop_back().getAsInteger(Radix, Value))
return ReturnError(TokStart, "invalid " + radixName(Radix) + " number");
-
- // MSVC accepts and ignores type suffices on integer literals.
- SkipIgnoredIntegerSuffix(CurPtr);
-
- return intToken(Result, Value);
+
+ // MSVC accepts and ignores type suffices on integer literals.
+ SkipIgnoredIntegerSuffix(CurPtr);
+
+ return intToken(Result, Value);
}
-
+
// default-radix integers, or floating point numbers, fall through
- CurPtr = OldCurPtr;
- }
-
+ CurPtr = OldCurPtr;
+ }
+
// MASM default-radix integers: [0-9a-fA-F]+
// (All other integer literals have a radix specifier.)
if (LexMasmIntegers && UseMasmDefaultRadix) {
@@ -421,112 +421,112 @@ AsmToken AsmLexer::LexDigit() {
return intToken(Result, Value);
}
- // Decimal integer: [1-9][0-9]*
- if (CurPtr[-1] != '0' || CurPtr[0] == '.') {
- unsigned Radix = doHexLookAhead(CurPtr, 10, LexMasmIntegers);
- bool isHex = Radix == 16;
- // Check for floating point literals.
- if (!isHex && (*CurPtr == '.' || *CurPtr == 'e' || *CurPtr == 'E')) {
- if (*CurPtr == '.')
- ++CurPtr;
- return LexFloatLiteral();
- }
-
- StringRef Result(TokStart, CurPtr - TokStart);
-
- APInt Value(128, 0, true);
+ // Decimal integer: [1-9][0-9]*
+ if (CurPtr[-1] != '0' || CurPtr[0] == '.') {
+ unsigned Radix = doHexLookAhead(CurPtr, 10, LexMasmIntegers);
+ bool isHex = Radix == 16;
+ // Check for floating point literals.
+ if (!isHex && (*CurPtr == '.' || *CurPtr == 'e' || *CurPtr == 'E')) {
+ if (*CurPtr == '.')
+ ++CurPtr;
+ return LexFloatLiteral();
+ }
+
+ StringRef Result(TokStart, CurPtr - TokStart);
+
+ APInt Value(128, 0, true);
if (Result.getAsInteger(Radix, Value)) {
return ReturnError(TokStart, "invalid " + radixName(Radix) + " number");
}
-
- // The darwin/x86 (and x86-64) assembler accepts and ignores type
- // suffices on integer literals.
- SkipIgnoredIntegerSuffix(CurPtr);
-
- return intToken(Result, Value);
- }
-
- if (!LexMasmIntegers && ((*CurPtr == 'b') || (*CurPtr == 'B'))) {
- ++CurPtr;
- // See if we actually have "0b" as part of something like "jmp 0b\n"
- if (!isDigit(CurPtr[0])) {
- --CurPtr;
- StringRef Result(TokStart, CurPtr - TokStart);
- return AsmToken(AsmToken::Integer, Result, 0);
- }
- const char *NumStart = CurPtr;
- while (CurPtr[0] == '0' || CurPtr[0] == '1')
- ++CurPtr;
-
- // Requires at least one binary digit.
- if (CurPtr == NumStart)
- return ReturnError(TokStart, "invalid binary number");
-
- StringRef Result(TokStart, CurPtr - TokStart);
-
- APInt Value(128, 0, true);
- if (Result.substr(2).getAsInteger(2, Value))
- return ReturnError(TokStart, "invalid binary number");
-
- // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
- // suffixes on integer literals.
- SkipIgnoredIntegerSuffix(CurPtr);
-
- return intToken(Result, Value);
- }
-
- if ((*CurPtr == 'x') || (*CurPtr == 'X')) {
- ++CurPtr;
- const char *NumStart = CurPtr;
- while (isHexDigit(CurPtr[0]))
- ++CurPtr;
-
- // "0x.0p0" is valid, and "0x0p0" (but not "0xp0" for example, which will be
- // diagnosed by LexHexFloatLiteral).
- if (CurPtr[0] == '.' || CurPtr[0] == 'p' || CurPtr[0] == 'P')
- return LexHexFloatLiteral(NumStart == CurPtr);
-
- // Otherwise requires at least one hex digit.
- if (CurPtr == NumStart)
- return ReturnError(CurPtr-2, "invalid hexadecimal number");
-
- APInt Result(128, 0);
- if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result))
- return ReturnError(TokStart, "invalid hexadecimal number");
-
- // Consume the optional [hH].
- if (LexMasmIntegers && (*CurPtr == 'h' || *CurPtr == 'H'))
- ++CurPtr;
-
- // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
- // suffixes on integer literals.
- SkipIgnoredIntegerSuffix(CurPtr);
-
- return intToken(StringRef(TokStart, CurPtr - TokStart), Result);
- }
-
- // Either octal or hexadecimal.
- APInt Value(128, 0, true);
- unsigned Radix = doHexLookAhead(CurPtr, 8, LexMasmIntegers);
- StringRef Result(TokStart, CurPtr - TokStart);
- if (Result.getAsInteger(Radix, Value))
+
+ // The darwin/x86 (and x86-64) assembler accepts and ignores type
+ // suffices on integer literals.
+ SkipIgnoredIntegerSuffix(CurPtr);
+
+ return intToken(Result, Value);
+ }
+
+ if (!LexMasmIntegers && ((*CurPtr == 'b') || (*CurPtr == 'B'))) {
+ ++CurPtr;
+ // See if we actually have "0b" as part of something like "jmp 0b\n"
+ if (!isDigit(CurPtr[0])) {
+ --CurPtr;
+ StringRef Result(TokStart, CurPtr - TokStart);
+ return AsmToken(AsmToken::Integer, Result, 0);
+ }
+ const char *NumStart = CurPtr;
+ while (CurPtr[0] == '0' || CurPtr[0] == '1')
+ ++CurPtr;
+
+ // Requires at least one binary digit.
+ if (CurPtr == NumStart)
+ return ReturnError(TokStart, "invalid binary number");
+
+ StringRef Result(TokStart, CurPtr - TokStart);
+
+ APInt Value(128, 0, true);
+ if (Result.substr(2).getAsInteger(2, Value))
+ return ReturnError(TokStart, "invalid binary number");
+
+ // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
+ // suffixes on integer literals.
+ SkipIgnoredIntegerSuffix(CurPtr);
+
+ return intToken(Result, Value);
+ }
+
+ if ((*CurPtr == 'x') || (*CurPtr == 'X')) {
+ ++CurPtr;
+ const char *NumStart = CurPtr;
+ while (isHexDigit(CurPtr[0]))
+ ++CurPtr;
+
+ // "0x.0p0" is valid, and "0x0p0" (but not "0xp0" for example, which will be
+ // diagnosed by LexHexFloatLiteral).
+ if (CurPtr[0] == '.' || CurPtr[0] == 'p' || CurPtr[0] == 'P')
+ return LexHexFloatLiteral(NumStart == CurPtr);
+
+ // Otherwise requires at least one hex digit.
+ if (CurPtr == NumStart)
+ return ReturnError(CurPtr-2, "invalid hexadecimal number");
+
+ APInt Result(128, 0);
+ if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result))
+ return ReturnError(TokStart, "invalid hexadecimal number");
+
+ // Consume the optional [hH].
+ if (LexMasmIntegers && (*CurPtr == 'h' || *CurPtr == 'H'))
+ ++CurPtr;
+
+ // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
+ // suffixes on integer literals.
+ SkipIgnoredIntegerSuffix(CurPtr);
+
+ return intToken(StringRef(TokStart, CurPtr - TokStart), Result);
+ }
+
+ // Either octal or hexadecimal.
+ APInt Value(128, 0, true);
+ unsigned Radix = doHexLookAhead(CurPtr, 8, LexMasmIntegers);
+ StringRef Result(TokStart, CurPtr - TokStart);
+ if (Result.getAsInteger(Radix, Value))
return ReturnError(TokStart, "invalid " + radixName(Radix) + " number");
-
- // Consume the [hH].
- if (Radix == 16)
- ++CurPtr;
-
- // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
- // suffixes on integer literals.
- SkipIgnoredIntegerSuffix(CurPtr);
-
- return intToken(Result, Value);
-}
-
-/// LexSingleQuote: Integer: 'b'
-AsmToken AsmLexer::LexSingleQuote() {
- int CurChar = getNextChar();
-
+
+ // Consume the [hH].
+ if (Radix == 16)
+ ++CurPtr;
+
+ // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
+ // suffixes on integer literals.
+ SkipIgnoredIntegerSuffix(CurPtr);
+
+ return intToken(Result, Value);
+}
+
+/// LexSingleQuote: Integer: 'b'
+AsmToken AsmLexer::LexSingleQuote() {
+ int CurChar = getNextChar();
+
if (LexMasmStrings) {
while (CurChar != EOF) {
if (CurChar != '\'') {
@@ -545,40 +545,40 @@ AsmToken AsmLexer::LexSingleQuote() {
return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart));
}
- if (CurChar == '\\')
- CurChar = getNextChar();
-
- if (CurChar == EOF)
- return ReturnError(TokStart, "unterminated single quote");
-
- CurChar = getNextChar();
-
- if (CurChar != '\'')
- return ReturnError(TokStart, "single quote way too long");
-
- // The idea here being that 'c' is basically just an integral
- // constant.
- StringRef Res = StringRef(TokStart,CurPtr - TokStart);
- long long Value;
-
- if (Res.startswith("\'\\")) {
- char theChar = Res[2];
- switch (theChar) {
- default: Value = theChar; break;
- case '\'': Value = '\''; break;
- case 't': Value = '\t'; break;
- case 'n': Value = '\n'; break;
- case 'b': Value = '\b'; break;
- }
- } else
- Value = TokStart[1];
-
- return AsmToken(AsmToken::Integer, Res, Value);
-}
-
-/// LexQuote: String: "..."
-AsmToken AsmLexer::LexQuote() {
- int CurChar = getNextChar();
+ if (CurChar == '\\')
+ CurChar = getNextChar();
+
+ if (CurChar == EOF)
+ return ReturnError(TokStart, "unterminated single quote");
+
+ CurChar = getNextChar();
+
+ if (CurChar != '\'')
+ return ReturnError(TokStart, "single quote way too long");
+
+ // The idea here being that 'c' is basically just an integral
+ // constant.
+ StringRef Res = StringRef(TokStart,CurPtr - TokStart);
+ long long Value;
+
+ if (Res.startswith("\'\\")) {
+ char theChar = Res[2];
+ switch (theChar) {
+ default: Value = theChar; break;
+ case '\'': Value = '\''; break;
+ case 't': Value = '\t'; break;
+ case 'n': Value = '\n'; break;
+ case 'b': Value = '\b'; break;
+ }
+ } else
+ Value = TokStart[1];
+
+ return AsmToken(AsmToken::Integer, Res, Value);
+}
+
+/// LexQuote: String: "..."
+AsmToken AsmLexer::LexQuote() {
+ int CurChar = getNextChar();
if (LexMasmStrings) {
while (CurChar != EOF) {
if (CurChar != '"') {
@@ -597,296 +597,296 @@ AsmToken AsmLexer::LexQuote() {
return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart));
}
- // TODO: does gas allow multiline string constants?
- while (CurChar != '"') {
- if (CurChar == '\\') {
- // Allow \", etc.
- CurChar = getNextChar();
- }
-
- if (CurChar == EOF)
- return ReturnError(TokStart, "unterminated string constant");
-
- CurChar = getNextChar();
- }
-
- return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart));
-}
-
-StringRef AsmLexer::LexUntilEndOfStatement() {
- TokStart = CurPtr;
-
- while (!isAtStartOfComment(CurPtr) && // Start of line comment.
- !isAtStatementSeparator(CurPtr) && // End of statement marker.
- *CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
- ++CurPtr;
- }
- return StringRef(TokStart, CurPtr-TokStart);
-}
-
-StringRef AsmLexer::LexUntilEndOfLine() {
- TokStart = CurPtr;
-
- while (*CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
- ++CurPtr;
- }
- return StringRef(TokStart, CurPtr-TokStart);
-}
-
-size_t AsmLexer::peekTokens(MutableArrayRef<AsmToken> Buf,
- bool ShouldSkipSpace) {
- 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();
-
- size_t ReadCount;
- for (ReadCount = 0; ReadCount < Buf.size(); ++ReadCount) {
- AsmToken Token = LexToken();
-
- Buf[ReadCount] = Token;
-
- if (Token.is(AsmToken::Eof))
- break;
- }
-
- SetError(SavedErrLoc, SavedErr);
- return ReadCount;
-}
-
-bool AsmLexer::isAtStartOfComment(const char *Ptr) {
- StringRef CommentString = MAI.getCommentString();
-
- if (CommentString.size() == 1)
- return CommentString[0] == Ptr[0];
-
- // Allow # preprocessor commments also be counted as comments for "##" cases
- if (CommentString[1] == '#')
- return CommentString[0] == Ptr[0];
-
- return strncmp(Ptr, CommentString.data(), CommentString.size()) == 0;
-}
-
-bool AsmLexer::isAtStatementSeparator(const char *Ptr) {
- return strncmp(Ptr, MAI.getSeparatorString(),
- strlen(MAI.getSeparatorString())) == 0;
-}
-
-AsmToken AsmLexer::LexToken() {
- TokStart = CurPtr;
- // This always consumes at least one character.
- int CurChar = getNextChar();
-
- if (!IsPeeking && CurChar == '#' && IsAtStartOfStatement) {
- // If this starts with a '#', this may be a cpp
- // hash directive and otherwise a line comment.
- AsmToken TokenBuf[2];
- MutableArrayRef<AsmToken> Buf(TokenBuf, 2);
- size_t num = peekTokens(Buf, true);
- // There cannot be a space preceding this
- if (IsAtStartOfLine && num == 2 && TokenBuf[0].is(AsmToken::Integer) &&
- TokenBuf[1].is(AsmToken::String)) {
- CurPtr = TokStart; // reset curPtr;
- StringRef s = LexUntilEndOfLine();
- UnLex(TokenBuf[1]);
- UnLex(TokenBuf[0]);
- return AsmToken(AsmToken::HashDirective, s);
- }
- return LexLineComment();
- }
-
- if (isAtStartOfComment(TokStart))
- return LexLineComment();
-
- if (isAtStatementSeparator(TokStart)) {
- CurPtr += strlen(MAI.getSeparatorString()) - 1;
- IsAtStartOfLine = true;
- IsAtStartOfStatement = true;
- return AsmToken(AsmToken::EndOfStatement,
- StringRef(TokStart, strlen(MAI.getSeparatorString())));
- }
-
- // If we're missing a newline at EOF, make sure we still get an
- // EndOfStatement token before the Eof token.
- if (CurChar == EOF && !IsAtStartOfStatement && EndStatementAtEOF) {
- IsAtStartOfLine = true;
- IsAtStartOfStatement = true;
+ // TODO: does gas allow multiline string constants?
+ while (CurChar != '"') {
+ if (CurChar == '\\') {
+ // Allow \", etc.
+ CurChar = getNextChar();
+ }
+
+ if (CurChar == EOF)
+ return ReturnError(TokStart, "unterminated string constant");
+
+ CurChar = getNextChar();
+ }
+
+ return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart));
+}
+
+StringRef AsmLexer::LexUntilEndOfStatement() {
+ TokStart = CurPtr;
+
+ while (!isAtStartOfComment(CurPtr) && // Start of line comment.
+ !isAtStatementSeparator(CurPtr) && // End of statement marker.
+ *CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
+ ++CurPtr;
+ }
+ return StringRef(TokStart, CurPtr-TokStart);
+}
+
+StringRef AsmLexer::LexUntilEndOfLine() {
+ TokStart = CurPtr;
+
+ while (*CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
+ ++CurPtr;
+ }
+ return StringRef(TokStart, CurPtr-TokStart);
+}
+
+size_t AsmLexer::peekTokens(MutableArrayRef<AsmToken> Buf,
+ bool ShouldSkipSpace) {
+ 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();
+
+ size_t ReadCount;
+ for (ReadCount = 0; ReadCount < Buf.size(); ++ReadCount) {
+ AsmToken Token = LexToken();
+
+ Buf[ReadCount] = Token;
+
+ if (Token.is(AsmToken::Eof))
+ break;
+ }
+
+ SetError(SavedErrLoc, SavedErr);
+ return ReadCount;
+}
+
+bool AsmLexer::isAtStartOfComment(const char *Ptr) {
+ StringRef CommentString = MAI.getCommentString();
+
+ if (CommentString.size() == 1)
+ return CommentString[0] == Ptr[0];
+
+ // Allow # preprocessor commments also be counted as comments for "##" cases
+ if (CommentString[1] == '#')
+ return CommentString[0] == Ptr[0];
+
+ return strncmp(Ptr, CommentString.data(), CommentString.size()) == 0;
+}
+
+bool AsmLexer::isAtStatementSeparator(const char *Ptr) {
+ return strncmp(Ptr, MAI.getSeparatorString(),
+ strlen(MAI.getSeparatorString())) == 0;
+}
+
+AsmToken AsmLexer::LexToken() {
+ TokStart = CurPtr;
+ // This always consumes at least one character.
+ int CurChar = getNextChar();
+
+ if (!IsPeeking && CurChar == '#' && IsAtStartOfStatement) {
+ // If this starts with a '#', this may be a cpp
+ // hash directive and otherwise a line comment.
+ AsmToken TokenBuf[2];
+ MutableArrayRef<AsmToken> Buf(TokenBuf, 2);
+ size_t num = peekTokens(Buf, true);
+ // There cannot be a space preceding this
+ if (IsAtStartOfLine && num == 2 && TokenBuf[0].is(AsmToken::Integer) &&
+ TokenBuf[1].is(AsmToken::String)) {
+ CurPtr = TokStart; // reset curPtr;
+ StringRef s = LexUntilEndOfLine();
+ UnLex(TokenBuf[1]);
+ UnLex(TokenBuf[0]);
+ return AsmToken(AsmToken::HashDirective, s);
+ }
+ return LexLineComment();
+ }
+
+ if (isAtStartOfComment(TokStart))
+ return LexLineComment();
+
+ if (isAtStatementSeparator(TokStart)) {
+ CurPtr += strlen(MAI.getSeparatorString()) - 1;
+ IsAtStartOfLine = true;
+ IsAtStartOfStatement = true;
+ return AsmToken(AsmToken::EndOfStatement,
+ StringRef(TokStart, strlen(MAI.getSeparatorString())));
+ }
+
+ // If we're missing a newline at EOF, make sure we still get an
+ // EndOfStatement token before the Eof token.
+ if (CurChar == EOF && !IsAtStartOfStatement && EndStatementAtEOF) {
+ IsAtStartOfLine = true;
+ IsAtStartOfStatement = true;
return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 0));
- }
- IsAtStartOfLine = false;
- bool OldIsAtStartOfStatement = IsAtStartOfStatement;
- IsAtStartOfStatement = false;
- switch (CurChar) {
- default:
- if (MAI.doesAllowSymbolAtNameStart()) {
- // Handle Microsoft-style identifier: [a-zA-Z_$.@?][a-zA-Z0-9_$.@?]*
- if (!isDigit(CurChar) &&
- IsIdentifierChar(CurChar, MAI.doesAllowAtInName()))
- return LexIdentifier();
- } else {
- // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
- if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
- return LexIdentifier();
- }
-
- // Unknown character, emit an error.
- return ReturnError(TokStart, "invalid character in input");
- case EOF:
- if (EndStatementAtEOF) {
- IsAtStartOfLine = true;
- IsAtStartOfStatement = true;
- }
- return AsmToken(AsmToken::Eof, StringRef(TokStart, 0));
- case 0:
- case ' ':
- case '\t':
- IsAtStartOfStatement = OldIsAtStartOfStatement;
- while (*CurPtr == ' ' || *CurPtr == '\t')
- CurPtr++;
- if (SkipSpace)
- return LexToken(); // Ignore whitespace.
- else
- return AsmToken(AsmToken::Space, StringRef(TokStart, CurPtr - TokStart));
- case '\r': {
- IsAtStartOfLine = true;
- IsAtStartOfStatement = true;
- // If this is a CR followed by LF, treat that as one token.
- if (CurPtr != CurBuf.end() && *CurPtr == '\n')
- ++CurPtr;
- return AsmToken(AsmToken::EndOfStatement,
- StringRef(TokStart, CurPtr - TokStart));
- }
- case '\n':
- IsAtStartOfLine = true;
- IsAtStartOfStatement = true;
- return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
- case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
- case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
- case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
- case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
- case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
- case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1));
- case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1));
- case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1));
- case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1));
- case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1));
- case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1));
- case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1));
- case '@': return AsmToken(AsmToken::At, StringRef(TokStart, 1));
- case '\\': return AsmToken(AsmToken::BackSlash, StringRef(TokStart, 1));
- case '=':
- if (*CurPtr == '=') {
- ++CurPtr;
- return AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
- }
- return AsmToken(AsmToken::Equal, StringRef(TokStart, 1));
- case '-':
- if (*CurPtr == '>') {
- ++CurPtr;
- return AsmToken(AsmToken::MinusGreater, StringRef(TokStart, 2));
- }
- return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
- case '|':
- if (*CurPtr == '|') {
- ++CurPtr;
- return AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2));
- }
- return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1));
- case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1));
- case '&':
- if (*CurPtr == '&') {
- ++CurPtr;
- return AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2));
- }
- return AsmToken(AsmToken::Amp, StringRef(TokStart, 1));
- case '!':
- if (*CurPtr == '=') {
- ++CurPtr;
- return AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2));
- }
- return AsmToken(AsmToken::Exclaim, 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();
- case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1));
- case '\'': return LexSingleQuote();
- case '"': return LexQuote();
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- return LexDigit();
- case '<':
- switch (*CurPtr) {
- case '<':
- ++CurPtr;
- return AsmToken(AsmToken::LessLess, StringRef(TokStart, 2));
- case '=':
- ++CurPtr;
- return AsmToken(AsmToken::LessEqual, StringRef(TokStart, 2));
- case '>':
- ++CurPtr;
- return AsmToken(AsmToken::LessGreater, StringRef(TokStart, 2));
- default:
- return AsmToken(AsmToken::Less, StringRef(TokStart, 1));
- }
- case '>':
- switch (*CurPtr) {
- case '>':
- ++CurPtr;
- return AsmToken(AsmToken::GreaterGreater, StringRef(TokStart, 2));
- case '=':
- ++CurPtr;
- return AsmToken(AsmToken::GreaterEqual, StringRef(TokStart, 2));
- default:
- return AsmToken(AsmToken::Greater, StringRef(TokStart, 1));
- }
-
- // TODO: Quoted identifiers (objc methods etc)
- // local labels: [0-9][:]
- // Forward/backward labels: [0-9][fb]
- // Integers, fp constants, character constants.
- }
-}
+ }
+ IsAtStartOfLine = false;
+ bool OldIsAtStartOfStatement = IsAtStartOfStatement;
+ IsAtStartOfStatement = false;
+ switch (CurChar) {
+ default:
+ if (MAI.doesAllowSymbolAtNameStart()) {
+ // Handle Microsoft-style identifier: [a-zA-Z_$.@?][a-zA-Z0-9_$.@?]*
+ if (!isDigit(CurChar) &&
+ IsIdentifierChar(CurChar, MAI.doesAllowAtInName()))
+ return LexIdentifier();
+ } else {
+ // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
+ if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
+ return LexIdentifier();
+ }
+
+ // Unknown character, emit an error.
+ return ReturnError(TokStart, "invalid character in input");
+ case EOF:
+ if (EndStatementAtEOF) {
+ IsAtStartOfLine = true;
+ IsAtStartOfStatement = true;
+ }
+ return AsmToken(AsmToken::Eof, StringRef(TokStart, 0));
+ case 0:
+ case ' ':
+ case '\t':
+ IsAtStartOfStatement = OldIsAtStartOfStatement;
+ while (*CurPtr == ' ' || *CurPtr == '\t')
+ CurPtr++;
+ if (SkipSpace)
+ return LexToken(); // Ignore whitespace.
+ else
+ return AsmToken(AsmToken::Space, StringRef(TokStart, CurPtr - TokStart));
+ case '\r': {
+ IsAtStartOfLine = true;
+ IsAtStartOfStatement = true;
+ // If this is a CR followed by LF, treat that as one token.
+ if (CurPtr != CurBuf.end() && *CurPtr == '\n')
+ ++CurPtr;
+ return AsmToken(AsmToken::EndOfStatement,
+ StringRef(TokStart, CurPtr - TokStart));
+ }
+ case '\n':
+ IsAtStartOfLine = true;
+ IsAtStartOfStatement = true;
+ return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
+ case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
+ case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
+ case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
+ case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
+ case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
+ case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1));
+ case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1));
+ case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1));
+ case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1));
+ case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1));
+ case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1));
+ case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1));
+ case '@': return AsmToken(AsmToken::At, StringRef(TokStart, 1));
+ case '\\': return AsmToken(AsmToken::BackSlash, StringRef(TokStart, 1));
+ case '=':
+ if (*CurPtr == '=') {
+ ++CurPtr;
+ return AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
+ }
+ return AsmToken(AsmToken::Equal, StringRef(TokStart, 1));
+ case '-':
+ if (*CurPtr == '>') {
+ ++CurPtr;
+ return AsmToken(AsmToken::MinusGreater, StringRef(TokStart, 2));
+ }
+ return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
+ case '|':
+ if (*CurPtr == '|') {
+ ++CurPtr;
+ return AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2));
+ }
+ return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1));
+ case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1));
+ case '&':
+ if (*CurPtr == '&') {
+ ++CurPtr;
+ return AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2));
+ }
+ return AsmToken(AsmToken::Amp, StringRef(TokStart, 1));
+ case '!':
+ if (*CurPtr == '=') {
+ ++CurPtr;
+ return AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2));
+ }
+ return AsmToken(AsmToken::Exclaim, 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();
+ case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1));
+ case '\'': return LexSingleQuote();
+ case '"': return LexQuote();
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ return LexDigit();
+ case '<':
+ switch (*CurPtr) {
+ case '<':
+ ++CurPtr;
+ return AsmToken(AsmToken::LessLess, StringRef(TokStart, 2));
+ case '=':
+ ++CurPtr;
+ return AsmToken(AsmToken::LessEqual, StringRef(TokStart, 2));
+ case '>':
+ ++CurPtr;
+ return AsmToken(AsmToken::LessGreater, StringRef(TokStart, 2));
+ default:
+ return AsmToken(AsmToken::Less, StringRef(TokStart, 1));
+ }
+ case '>':
+ switch (*CurPtr) {
+ case '>':
+ ++CurPtr;
+ return AsmToken(AsmToken::GreaterGreater, StringRef(TokStart, 2));
+ case '=':
+ ++CurPtr;
+ return AsmToken(AsmToken::GreaterEqual, StringRef(TokStart, 2));
+ default:
+ return AsmToken(AsmToken::Greater, StringRef(TokStart, 1));
+ }
+
+ // TODO: Quoted identifiers (objc methods etc)
+ // local labels: [0-9][:]
+ // Forward/backward labels: [0-9][fb]
+ // Integers, fp constants, character constants.
+ }
+}
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/AsmParser.cpp b/contrib/libs/llvm12/lib/MC/MCParser/AsmParser.cpp
index 99548acb88..c5ff241ead 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/AsmParser.cpp
+++ b/contrib/libs/llvm12/lib/MC/MCParser/AsmParser.cpp
@@ -1,1623 +1,1623 @@
-//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements a parser for assembly files similar to gas syntax.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCCodeView.h"
-#include "llvm/MC/MCContext.h"
-#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/MCAsmParserExtension.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/MCSection.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCTargetOptions.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MD5.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 <climits>
-#include <cstddef>
-#include <cstdint>
-#include <deque>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-using namespace llvm;
-
-MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;
-
-extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
-
-namespace {
-
-/// Helper types for tracking macro definitions.
-typedef std::vector<AsmToken> MCAsmMacroArgument;
-typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
-
-/// Helper class for storing information about an active macro
-/// instantiation.
-struct MacroInstantiation {
- /// The location of the instantiation.
- SMLoc InstantiationLoc;
-
- /// The buffer where parsing should resume upon instantiation completion.
- unsigned ExitBuffer;
-
- /// The location where parsing should resume upon instantiation completion.
- SMLoc ExitLoc;
-
- /// The depth of TheCondStack at the start of the instantiation.
- size_t CondStackDepth;
-};
-
-struct ParseStatementInfo {
- /// The parsed operands from the last parsed statement.
- SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
-
- /// The opcode from the last parsed instruction.
- unsigned Opcode = ~0U;
-
- /// Was there an error parsing the inline assembly?
- bool ParseError = false;
-
- SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
-
- ParseStatementInfo() = delete;
- ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
- : AsmRewrites(rewrites) {}
-};
-
-/// The concrete assembly parser instance.
-class AsmParser : public MCAsmParser {
-private:
- AsmLexer Lexer;
- MCContext &Ctx;
- MCStreamer &Out;
- const MCAsmInfo &MAI;
- SourceMgr &SrcMgr;
- SourceMgr::DiagHandlerTy SavedDiagHandler;
- void *SavedDiagContext;
- std::unique_ptr<MCAsmParserExtension> PlatformParser;
+//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements a parser for assembly files similar to gas syntax.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeView.h"
+#include "llvm/MC/MCContext.h"
+#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/MCAsmParserExtension.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/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MD5.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 <climits>
+#include <cstddef>
+#include <cstdint>
+#include <deque>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;
+
+extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
+
+namespace {
+
+/// Helper types for tracking macro definitions.
+typedef std::vector<AsmToken> MCAsmMacroArgument;
+typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
+
+/// Helper class for storing information about an active macro
+/// instantiation.
+struct MacroInstantiation {
+ /// The location of the instantiation.
+ SMLoc InstantiationLoc;
+
+ /// The buffer where parsing should resume upon instantiation completion.
+ unsigned ExitBuffer;
+
+ /// The location where parsing should resume upon instantiation completion.
+ SMLoc ExitLoc;
+
+ /// The depth of TheCondStack at the start of the instantiation.
+ size_t CondStackDepth;
+};
+
+struct ParseStatementInfo {
+ /// The parsed operands from the last parsed statement.
+ SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
+
+ /// The opcode from the last parsed instruction.
+ unsigned Opcode = ~0U;
+
+ /// Was there an error parsing the inline assembly?
+ bool ParseError = false;
+
+ SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
+
+ ParseStatementInfo() = delete;
+ ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
+ : AsmRewrites(rewrites) {}
+};
+
+/// The concrete assembly parser instance.
+class AsmParser : public MCAsmParser {
+private:
+ AsmLexer Lexer;
+ MCContext &Ctx;
+ MCStreamer &Out;
+ const MCAsmInfo &MAI;
+ SourceMgr &SrcMgr;
+ SourceMgr::DiagHandlerTy SavedDiagHandler;
+ void *SavedDiagContext;
+ std::unique_ptr<MCAsmParserExtension> PlatformParser;
SMLoc StartTokLoc;
-
- /// This is the current buffer index we're lexing from as managed by the
- /// SourceMgr object.
- unsigned CurBuffer;
-
- AsmCond TheCondState;
- std::vector<AsmCond> TheCondStack;
-
- /// maps directive names to handler methods in parser
- /// extensions. Extensions register themselves in this map by calling
- /// addDirectiveHandler.
- StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
-
- /// Stack of active macro instantiations.
- std::vector<MacroInstantiation*> ActiveMacros;
-
- /// List of bodies of anonymous macros.
- std::deque<MCAsmMacro> MacroLikeBodies;
-
- /// Boolean tracking whether macro substitution is enabled.
- unsigned MacrosEnabledFlag : 1;
-
- /// Keeps track of how many .macro's have been instantiated.
- unsigned NumOfMacroInstantiations;
-
- /// The values from the last parsed cpp hash file line comment if any.
- struct CppHashInfoTy {
- StringRef Filename;
- int64_t LineNumber;
- SMLoc Loc;
- unsigned Buf;
- CppHashInfoTy() : Filename(), LineNumber(0), Loc(), Buf(0) {}
- };
- CppHashInfoTy CppHashInfo;
-
- /// The filename from the first cpp hash file line comment, if any.
- StringRef FirstCppHashFilename;
-
- /// List of forward directional labels for diagnosis at the end.
- SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
-
- /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
- unsigned AssemblerDialect = ~0U;
-
- /// is Darwin compatibility enabled?
- bool IsDarwin = false;
-
- /// Are we parsing ms-style inline assembly?
- bool ParsingMSInlineAsm = false;
-
- /// Did we already inform the user about inconsistent MD5 usage?
- bool ReportedInconsistentMD5 = false;
-
- // Is alt macro mode enabled.
- bool AltMacroMode = false;
-
-public:
- AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
- const MCAsmInfo &MAI, unsigned CB);
- AsmParser(const AsmParser &) = delete;
- AsmParser &operator=(const AsmParser &) = delete;
- ~AsmParser() override;
-
- bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
-
- void addDirectiveHandler(StringRef Directive,
- ExtensionDirectiveHandler Handler) override {
- ExtensionDirectiveMap[Directive] = Handler;
- }
-
- void addAliasForDirective(StringRef Directive, StringRef Alias) override {
- DirectiveKindMap[Directive.lower()] = DirectiveKindMap[Alias.lower()];
- }
-
- /// @name MCAsmParser Interface
- /// {
-
- SourceMgr &getSourceManager() override { return SrcMgr; }
- 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();
- else
- return AssemblerDialect;
- }
- void setAssemblerDialect(unsigned i) override {
- AssemblerDialect = i;
- }
-
- 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 setParsingMSInlineAsm(bool V) override {
- ParsingMSInlineAsm = V;
- // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
- // hex integer literals.
- Lexer.setLexMasmIntegers(V);
- }
- bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
-
- bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
- unsigned &NumOutputs, unsigned &NumInputs,
- SmallVectorImpl<std::pair<void *,bool>> &OpDecls,
- SmallVectorImpl<std::string> &Constraints,
- SmallVectorImpl<std::string> &Clobbers,
- const MCInstrInfo *MII, const MCInstPrinter *IP,
- MCAsmParserSemaCallback &SI) override;
-
- bool parseExpression(const MCExpr *&Res);
- bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
+
+ /// This is the current buffer index we're lexing from as managed by the
+ /// SourceMgr object.
+ unsigned CurBuffer;
+
+ AsmCond TheCondState;
+ std::vector<AsmCond> TheCondStack;
+
+ /// maps directive names to handler methods in parser
+ /// extensions. Extensions register themselves in this map by calling
+ /// addDirectiveHandler.
+ StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
+
+ /// Stack of active macro instantiations.
+ std::vector<MacroInstantiation*> ActiveMacros;
+
+ /// List of bodies of anonymous macros.
+ std::deque<MCAsmMacro> MacroLikeBodies;
+
+ /// Boolean tracking whether macro substitution is enabled.
+ unsigned MacrosEnabledFlag : 1;
+
+ /// Keeps track of how many .macro's have been instantiated.
+ unsigned NumOfMacroInstantiations;
+
+ /// The values from the last parsed cpp hash file line comment if any.
+ struct CppHashInfoTy {
+ StringRef Filename;
+ int64_t LineNumber;
+ SMLoc Loc;
+ unsigned Buf;
+ CppHashInfoTy() : Filename(), LineNumber(0), Loc(), Buf(0) {}
+ };
+ CppHashInfoTy CppHashInfo;
+
+ /// The filename from the first cpp hash file line comment, if any.
+ StringRef FirstCppHashFilename;
+
+ /// List of forward directional labels for diagnosis at the end.
+ SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
+
+ /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
+ unsigned AssemblerDialect = ~0U;
+
+ /// is Darwin compatibility enabled?
+ bool IsDarwin = false;
+
+ /// Are we parsing ms-style inline assembly?
+ bool ParsingMSInlineAsm = false;
+
+ /// Did we already inform the user about inconsistent MD5 usage?
+ bool ReportedInconsistentMD5 = false;
+
+ // Is alt macro mode enabled.
+ bool AltMacroMode = false;
+
+public:
+ AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
+ const MCAsmInfo &MAI, unsigned CB);
+ AsmParser(const AsmParser &) = delete;
+ AsmParser &operator=(const AsmParser &) = delete;
+ ~AsmParser() override;
+
+ bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
+
+ void addDirectiveHandler(StringRef Directive,
+ ExtensionDirectiveHandler Handler) override {
+ ExtensionDirectiveMap[Directive] = Handler;
+ }
+
+ void addAliasForDirective(StringRef Directive, StringRef Alias) override {
+ DirectiveKindMap[Directive.lower()] = DirectiveKindMap[Alias.lower()];
+ }
+
+ /// @name MCAsmParser Interface
+ /// {
+
+ SourceMgr &getSourceManager() override { return SrcMgr; }
+ 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();
+ else
+ return AssemblerDialect;
+ }
+ void setAssemblerDialect(unsigned i) override {
+ AssemblerDialect = i;
+ }
+
+ 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 setParsingMSInlineAsm(bool V) override {
+ ParsingMSInlineAsm = V;
+ // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
+ // hex integer literals.
+ Lexer.setLexMasmIntegers(V);
+ }
+ bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
+
+ bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
+ unsigned &NumOutputs, unsigned &NumInputs,
+ SmallVectorImpl<std::pair<void *,bool>> &OpDecls,
+ SmallVectorImpl<std::string> &Constraints,
+ SmallVectorImpl<std::string> &Clobbers,
+ const MCInstrInfo *MII, const MCInstPrinter *IP,
+ MCAsmParserSemaCallback &SI) override;
+
+ bool parseExpression(const MCExpr *&Res);
+ bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
AsmTypeInfo *TypeInfo) override;
- bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
- bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
- SMLoc &EndLoc) override;
- bool parseAbsoluteExpression(int64_t &Res) override;
-
- /// Parse a floating point expression using the float \p Semantics
- /// and set \p Res to the value.
- bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
-
- /// 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;
-
- bool checkForValidSection() override;
-
- /// }
-
-private:
- bool parseStatement(ParseStatementInfo &Info,
- MCAsmParserSemaCallback *SI);
- bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
- bool parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo = true);
-
- void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
- ArrayRef<MCAsmMacroParameter> Parameters);
- bool expandMacro(raw_svector_ostream &OS, StringRef Body,
- ArrayRef<MCAsmMacroParameter> Parameters,
- ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable,
- SMLoc L);
-
- /// Are macros enabled in the parser?
- bool areMacrosEnabled() {return MacrosEnabledFlag;}
-
- /// Control a flag in the parser that enables or disables macros.
- void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
-
- /// Are we inside a macro instantiation?
- bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
-
- /// Handle entry to macro instantiation.
- ///
- /// \param M The macro.
- /// \param NameLoc Instantiation location.
- bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
-
- /// Handle exit from macro instantiation.
- void handleMacroExit();
-
- /// Extract AsmTokens for a macro argument.
- bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
-
- /// Parse all macro arguments for a given macro.
- bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
-
- void printMacroInstantiations();
- void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
- SMRange Range = None) const {
- ArrayRef<SMRange> Ranges(Range);
- SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
- }
- static void DiagHandler(const SMDiagnostic &Diag, void *Context);
-
- /// Should we emit DWARF describing this assembler source? (Returns false if
- /// the source has .file directives, which means we don't want to generate
- /// info describing the assembler source itself.)
- bool enabledGenDwarfForAssembly();
-
- /// Enter the specified file. This returns true on failure.
- bool enterIncludeFile(const std::string &Filename);
-
- /// Process the specified file for the .incbin directive.
- /// This returns true on failure.
- bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,
- const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());
-
- /// Reset the current lexer position to that given by \p Loc. The
- /// current token is not set; clients should ensure Lex() is called
- /// subsequently.
- ///
- /// \param InBuffer If not 0, should be the known buffer id that contains the
- /// location.
- void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);
-
- /// Parse up to the end of statement and a return the contents from the
- /// current token until the end of the statement; the current token on exit
- /// will be either the EndOfStatement or EOF.
- StringRef parseStringToEndOfStatement() override;
-
- /// Parse until the end of a statement or a comma is encountered,
- /// return the contents from the current token up to the end or comma.
- StringRef parseStringToComma();
-
- bool parseAssignment(StringRef Name, bool allow_redef,
- bool NoDeadStrip = false);
-
- unsigned getBinOpPrecedence(AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind);
-
- bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
- bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
- bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
-
- 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,
- DK_ZERO,
- DK_EXTERN,
- DK_GLOBL,
- DK_GLOBAL,
- DK_LAZY_REFERENCE,
- DK_NO_DEAD_STRIP,
- DK_SYMBOL_RESOLVER,
- DK_PRIVATE_EXTERN,
- DK_REFERENCE,
- DK_WEAK_DEFINITION,
- DK_WEAK_REFERENCE,
- DK_WEAK_DEF_CAN_BE_HIDDEN,
- DK_COLD,
- DK_COMM,
- DK_COMMON,
- DK_LCOMM,
- DK_ABORT,
- DK_INCLUDE,
- DK_INCBIN,
- DK_CODE16,
- DK_CODE16GCC,
- DK_REPT,
- DK_IRP,
- DK_IRPC,
- DK_IF,
- DK_IFEQ,
- DK_IFGE,
- DK_IFGT,
- DK_IFLE,
- DK_IFLT,
- DK_IFNE,
- DK_IFB,
- DK_IFNB,
- DK_IFC,
- DK_IFEQS,
- DK_IFNC,
- DK_IFNES,
- DK_IFDEF,
- DK_IFNDEF,
- DK_IFNOTDEF,
- DK_ELSEIF,
- DK_ELSE,
- DK_ENDIF,
- DK_SPACE,
- DK_SKIP,
- DK_FILE,
- DK_LINE,
- DK_LOC,
- DK_STABS,
- DK_CV_FILE,
- DK_CV_FUNC_ID,
- DK_CV_INLINE_SITE_ID,
- DK_CV_LOC,
- DK_CV_LINETABLE,
- DK_CV_INLINE_LINETABLE,
- DK_CV_DEF_RANGE,
- DK_CV_STRINGTABLE,
- DK_CV_STRING,
- DK_CV_FILECHECKSUMS,
- DK_CV_FILECHECKSUM_OFFSET,
- DK_CV_FPO_DATA,
- DK_CFI_SECTIONS,
- DK_CFI_STARTPROC,
- DK_CFI_ENDPROC,
- DK_CFI_DEF_CFA,
- DK_CFI_DEF_CFA_OFFSET,
- DK_CFI_ADJUST_CFA_OFFSET,
- DK_CFI_DEF_CFA_REGISTER,
- DK_CFI_OFFSET,
- DK_CFI_REL_OFFSET,
- DK_CFI_PERSONALITY,
- DK_CFI_LSDA,
- DK_CFI_REMEMBER_STATE,
- DK_CFI_RESTORE_STATE,
- DK_CFI_SAME_VALUE,
- DK_CFI_RESTORE,
- DK_CFI_ESCAPE,
- DK_CFI_RETURN_COLUMN,
- DK_CFI_SIGNAL_FRAME,
- DK_CFI_UNDEFINED,
- DK_CFI_REGISTER,
- DK_CFI_WINDOW_SAVE,
- DK_CFI_B_KEY_FRAME,
- DK_MACROS_ON,
- DK_MACROS_OFF,
- DK_ALTMACRO,
- DK_NOALTMACRO,
- DK_MACRO,
- DK_EXITM,
- DK_ENDM,
- DK_ENDMACRO,
- DK_PURGEM,
- DK_SLEB128,
- DK_ULEB128,
- DK_ERR,
- DK_ERROR,
- DK_WARNING,
- DK_PRINT,
- DK_ADDRSIG,
- DK_ADDRSIG_SYM,
+ bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
+ bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
+ SMLoc &EndLoc) override;
+ bool parseAbsoluteExpression(int64_t &Res) override;
+
+ /// Parse a floating point expression using the float \p Semantics
+ /// and set \p Res to the value.
+ bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
+
+ /// 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;
+
+ bool checkForValidSection() override;
+
+ /// }
+
+private:
+ bool parseStatement(ParseStatementInfo &Info,
+ MCAsmParserSemaCallback *SI);
+ bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
+ bool parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo = true);
+
+ void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
+ ArrayRef<MCAsmMacroParameter> Parameters);
+ bool expandMacro(raw_svector_ostream &OS, StringRef Body,
+ ArrayRef<MCAsmMacroParameter> Parameters,
+ ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable,
+ SMLoc L);
+
+ /// Are macros enabled in the parser?
+ bool areMacrosEnabled() {return MacrosEnabledFlag;}
+
+ /// Control a flag in the parser that enables or disables macros.
+ void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
+
+ /// Are we inside a macro instantiation?
+ bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
+
+ /// Handle entry to macro instantiation.
+ ///
+ /// \param M The macro.
+ /// \param NameLoc Instantiation location.
+ bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
+
+ /// Handle exit from macro instantiation.
+ void handleMacroExit();
+
+ /// Extract AsmTokens for a macro argument.
+ bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
+
+ /// Parse all macro arguments for a given macro.
+ bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
+
+ void printMacroInstantiations();
+ void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
+ SMRange Range = None) const {
+ ArrayRef<SMRange> Ranges(Range);
+ SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
+ }
+ static void DiagHandler(const SMDiagnostic &Diag, void *Context);
+
+ /// Should we emit DWARF describing this assembler source? (Returns false if
+ /// the source has .file directives, which means we don't want to generate
+ /// info describing the assembler source itself.)
+ bool enabledGenDwarfForAssembly();
+
+ /// Enter the specified file. This returns true on failure.
+ bool enterIncludeFile(const std::string &Filename);
+
+ /// Process the specified file for the .incbin directive.
+ /// This returns true on failure.
+ bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,
+ const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());
+
+ /// Reset the current lexer position to that given by \p Loc. The
+ /// current token is not set; clients should ensure Lex() is called
+ /// subsequently.
+ ///
+ /// \param InBuffer If not 0, should be the known buffer id that contains the
+ /// location.
+ void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);
+
+ /// Parse up to the end of statement and a return the contents from the
+ /// current token until the end of the statement; the current token on exit
+ /// will be either the EndOfStatement or EOF.
+ StringRef parseStringToEndOfStatement() override;
+
+ /// Parse until the end of a statement or a comma is encountered,
+ /// return the contents from the current token up to the end or comma.
+ StringRef parseStringToComma();
+
+ bool parseAssignment(StringRef Name, bool allow_redef,
+ bool NoDeadStrip = false);
+
+ unsigned getBinOpPrecedence(AsmToken::TokenKind K,
+ MCBinaryExpr::Opcode &Kind);
+
+ bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
+ bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
+ bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
+
+ 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,
+ DK_ZERO,
+ DK_EXTERN,
+ DK_GLOBL,
+ DK_GLOBAL,
+ DK_LAZY_REFERENCE,
+ DK_NO_DEAD_STRIP,
+ DK_SYMBOL_RESOLVER,
+ DK_PRIVATE_EXTERN,
+ DK_REFERENCE,
+ DK_WEAK_DEFINITION,
+ DK_WEAK_REFERENCE,
+ DK_WEAK_DEF_CAN_BE_HIDDEN,
+ DK_COLD,
+ DK_COMM,
+ DK_COMMON,
+ DK_LCOMM,
+ DK_ABORT,
+ DK_INCLUDE,
+ DK_INCBIN,
+ DK_CODE16,
+ DK_CODE16GCC,
+ DK_REPT,
+ DK_IRP,
+ DK_IRPC,
+ DK_IF,
+ DK_IFEQ,
+ DK_IFGE,
+ DK_IFGT,
+ DK_IFLE,
+ DK_IFLT,
+ DK_IFNE,
+ DK_IFB,
+ DK_IFNB,
+ DK_IFC,
+ DK_IFEQS,
+ DK_IFNC,
+ DK_IFNES,
+ DK_IFDEF,
+ DK_IFNDEF,
+ DK_IFNOTDEF,
+ DK_ELSEIF,
+ DK_ELSE,
+ DK_ENDIF,
+ DK_SPACE,
+ DK_SKIP,
+ DK_FILE,
+ DK_LINE,
+ DK_LOC,
+ DK_STABS,
+ DK_CV_FILE,
+ DK_CV_FUNC_ID,
+ DK_CV_INLINE_SITE_ID,
+ DK_CV_LOC,
+ DK_CV_LINETABLE,
+ DK_CV_INLINE_LINETABLE,
+ DK_CV_DEF_RANGE,
+ DK_CV_STRINGTABLE,
+ DK_CV_STRING,
+ DK_CV_FILECHECKSUMS,
+ DK_CV_FILECHECKSUM_OFFSET,
+ DK_CV_FPO_DATA,
+ DK_CFI_SECTIONS,
+ DK_CFI_STARTPROC,
+ DK_CFI_ENDPROC,
+ DK_CFI_DEF_CFA,
+ DK_CFI_DEF_CFA_OFFSET,
+ DK_CFI_ADJUST_CFA_OFFSET,
+ DK_CFI_DEF_CFA_REGISTER,
+ DK_CFI_OFFSET,
+ DK_CFI_REL_OFFSET,
+ DK_CFI_PERSONALITY,
+ DK_CFI_LSDA,
+ DK_CFI_REMEMBER_STATE,
+ DK_CFI_RESTORE_STATE,
+ DK_CFI_SAME_VALUE,
+ DK_CFI_RESTORE,
+ DK_CFI_ESCAPE,
+ DK_CFI_RETURN_COLUMN,
+ DK_CFI_SIGNAL_FRAME,
+ DK_CFI_UNDEFINED,
+ DK_CFI_REGISTER,
+ DK_CFI_WINDOW_SAVE,
+ DK_CFI_B_KEY_FRAME,
+ DK_MACROS_ON,
+ DK_MACROS_OFF,
+ DK_ALTMACRO,
+ DK_NOALTMACRO,
+ DK_MACRO,
+ DK_EXITM,
+ DK_ENDM,
+ DK_ENDMACRO,
+ DK_PURGEM,
+ DK_SLEB128,
+ DK_ULEB128,
+ DK_ERR,
+ DK_ERROR,
+ DK_WARNING,
+ DK_PRINT,
+ DK_ADDRSIG,
+ DK_ADDRSIG_SYM,
DK_PSEUDO_PROBE,
- DK_END
- };
-
- /// Maps directive name --> DirectiveKind enum, for
- /// directives parsed by this class.
- StringMap<DirectiveKind> DirectiveKindMap;
-
- // Codeview def_range type parsing.
- enum CVDefRangeType {
- CVDR_DEFRANGE = 0, // Placeholder
- CVDR_DEFRANGE_REGISTER,
- CVDR_DEFRANGE_FRAMEPOINTER_REL,
- CVDR_DEFRANGE_SUBFIELD_REGISTER,
- CVDR_DEFRANGE_REGISTER_REL
- };
-
- /// Maps Codeview def_range types --> CVDefRangeType enum, for
- /// Codeview def_range types parsed by this class.
- StringMap<CVDefRangeType> CVDefRangeTypeMap;
-
- // ".ascii", ".asciz", ".string"
- bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
- bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
- 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"
- bool parseDirectiveSet(StringRef IDVal, bool allow_redef);
- bool parseDirectiveOrg(); // ".org"
- // ".align{,32}", ".p2align{,w,l}"
- bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);
-
- // ".file", ".line", ".loc", ".stabs"
- bool parseDirectiveFile(SMLoc DirectiveLoc);
- bool parseDirectiveLine();
- bool parseDirectiveLoc();
- bool parseDirectiveStabs();
-
- // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
- // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
- bool parseDirectiveCVFile();
- bool parseDirectiveCVFuncId();
- bool parseDirectiveCVInlineSiteId();
- bool parseDirectiveCVLoc();
- bool parseDirectiveCVLinetable();
- bool parseDirectiveCVInlineLinetable();
- bool parseDirectiveCVDefRange();
- bool parseDirectiveCVString();
- bool parseDirectiveCVStringTable();
- bool parseDirectiveCVFileChecksums();
- bool parseDirectiveCVFileChecksumOffset();
- bool parseDirectiveCVFPOData();
-
- // .cfi directives
- bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
- bool parseDirectiveCFIWindowSave();
- bool parseDirectiveCFISections();
- bool parseDirectiveCFIStartProc();
- bool parseDirectiveCFIEndProc();
- bool parseDirectiveCFIDefCfaOffset();
- bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
- bool parseDirectiveCFIAdjustCfaOffset();
- bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
- bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
- bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
- bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
- bool parseDirectiveCFIRememberState();
- bool parseDirectiveCFIRestoreState();
- bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
- bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
- bool parseDirectiveCFIEscape();
- bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
- bool parseDirectiveCFISignalFrame();
- bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
-
- // macro directives
- bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
- bool parseDirectiveExitMacro(StringRef Directive);
- bool parseDirectiveEndMacro(StringRef Directive);
- bool parseDirectiveMacro(SMLoc DirectiveLoc);
- bool parseDirectiveMacrosOnOff(StringRef Directive);
- // alternate macro mode directives
- bool parseDirectiveAltmacro(StringRef Directive);
- // ".bundle_align_mode"
- bool parseDirectiveBundleAlignMode();
- // ".bundle_lock"
- bool parseDirectiveBundleLock();
- // ".bundle_unlock"
- bool parseDirectiveBundleUnlock();
-
- // ".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);
-
- /// Parse a directive like ".globl" which
- /// accepts a single symbol (which should be a label or an external).
- bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
-
- bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
-
- bool parseDirectiveAbort(); // ".abort"
- bool parseDirectiveInclude(); // ".include"
- bool parseDirectiveIncbin(); // ".incbin"
-
- // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"
- bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
- // ".ifb" or ".ifnb", depending on ExpectBlank.
- bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
- // ".ifc" or ".ifnc", depending on ExpectEqual.
- bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
- // ".ifeqs" or ".ifnes", depending on ExpectEqual.
- bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);
- // ".ifdef" or ".ifndef", depending on expect_defined
- bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
- bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
- bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
- bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
- bool parseEscapedString(std::string &Data) override;
- bool parseAngleBracketString(std::string &Data) override;
-
- const MCExpr *applyModifierToExpr(const MCExpr *E,
- MCSymbolRefExpr::VariantKind Variant);
-
- // Macro-like directives
- MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
- void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
- raw_svector_ostream &OS);
- bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);
- bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
- bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
- bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
-
- // "_emit" or "__emit"
- bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
- size_t Len);
-
- // "align"
- bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
-
- // "end"
- bool parseDirectiveEnd(SMLoc DirectiveLoc);
-
- // ".err" or ".error"
- bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
-
- // ".warning"
- bool parseDirectiveWarning(SMLoc DirectiveLoc);
-
- // .print <double-quotes-string>
- bool parseDirectivePrint(SMLoc DirectiveLoc);
-
+ DK_END
+ };
+
+ /// Maps directive name --> DirectiveKind enum, for
+ /// directives parsed by this class.
+ StringMap<DirectiveKind> DirectiveKindMap;
+
+ // Codeview def_range type parsing.
+ enum CVDefRangeType {
+ CVDR_DEFRANGE = 0, // Placeholder
+ CVDR_DEFRANGE_REGISTER,
+ CVDR_DEFRANGE_FRAMEPOINTER_REL,
+ CVDR_DEFRANGE_SUBFIELD_REGISTER,
+ CVDR_DEFRANGE_REGISTER_REL
+ };
+
+ /// Maps Codeview def_range types --> CVDefRangeType enum, for
+ /// Codeview def_range types parsed by this class.
+ StringMap<CVDefRangeType> CVDefRangeTypeMap;
+
+ // ".ascii", ".asciz", ".string"
+ bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
+ bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
+ 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"
+ bool parseDirectiveSet(StringRef IDVal, bool allow_redef);
+ bool parseDirectiveOrg(); // ".org"
+ // ".align{,32}", ".p2align{,w,l}"
+ bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);
+
+ // ".file", ".line", ".loc", ".stabs"
+ bool parseDirectiveFile(SMLoc DirectiveLoc);
+ bool parseDirectiveLine();
+ bool parseDirectiveLoc();
+ bool parseDirectiveStabs();
+
+ // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
+ // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
+ bool parseDirectiveCVFile();
+ bool parseDirectiveCVFuncId();
+ bool parseDirectiveCVInlineSiteId();
+ bool parseDirectiveCVLoc();
+ bool parseDirectiveCVLinetable();
+ bool parseDirectiveCVInlineLinetable();
+ bool parseDirectiveCVDefRange();
+ bool parseDirectiveCVString();
+ bool parseDirectiveCVStringTable();
+ bool parseDirectiveCVFileChecksums();
+ bool parseDirectiveCVFileChecksumOffset();
+ bool parseDirectiveCVFPOData();
+
+ // .cfi directives
+ bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIWindowSave();
+ bool parseDirectiveCFISections();
+ bool parseDirectiveCFIStartProc();
+ bool parseDirectiveCFIEndProc();
+ bool parseDirectiveCFIDefCfaOffset();
+ bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIAdjustCfaOffset();
+ bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
+ bool parseDirectiveCFIRememberState();
+ bool parseDirectiveCFIRestoreState();
+ bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIEscape();
+ bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
+ bool parseDirectiveCFISignalFrame();
+ bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
+
+ // macro directives
+ bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
+ bool parseDirectiveExitMacro(StringRef Directive);
+ bool parseDirectiveEndMacro(StringRef Directive);
+ bool parseDirectiveMacro(SMLoc DirectiveLoc);
+ bool parseDirectiveMacrosOnOff(StringRef Directive);
+ // alternate macro mode directives
+ bool parseDirectiveAltmacro(StringRef Directive);
+ // ".bundle_align_mode"
+ bool parseDirectiveBundleAlignMode();
+ // ".bundle_lock"
+ bool parseDirectiveBundleLock();
+ // ".bundle_unlock"
+ bool parseDirectiveBundleUnlock();
+
+ // ".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);
+
+ /// Parse a directive like ".globl" which
+ /// accepts a single symbol (which should be a label or an external).
+ bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
+
+ bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
+
+ bool parseDirectiveAbort(); // ".abort"
+ bool parseDirectiveInclude(); // ".include"
+ bool parseDirectiveIncbin(); // ".incbin"
+
+ // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"
+ bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
+ // ".ifb" or ".ifnb", depending on ExpectBlank.
+ bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
+ // ".ifc" or ".ifnc", depending on ExpectEqual.
+ bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
+ // ".ifeqs" or ".ifnes", depending on ExpectEqual.
+ bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);
+ // ".ifdef" or ".ifndef", depending on expect_defined
+ bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
+ bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
+ bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
+ bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
+ bool parseEscapedString(std::string &Data) override;
+ bool parseAngleBracketString(std::string &Data) override;
+
+ const MCExpr *applyModifierToExpr(const MCExpr *E,
+ MCSymbolRefExpr::VariantKind Variant);
+
+ // Macro-like directives
+ MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
+ void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
+ raw_svector_ostream &OS);
+ bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);
+ bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
+ bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
+ bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
+
+ // "_emit" or "__emit"
+ bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
+ size_t Len);
+
+ // "align"
+ bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
+
+ // "end"
+ bool parseDirectiveEnd(SMLoc DirectiveLoc);
+
+ // ".err" or ".error"
+ bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
+
+ // ".warning"
+ bool parseDirectiveWarning(SMLoc DirectiveLoc);
+
+ // .print <double-quotes-string>
+ bool parseDirectivePrint(SMLoc DirectiveLoc);
+
// .pseudoprobe
bool parseDirectivePseudoProbe();
- // Directives to support address-significance tables.
- bool parseDirectiveAddrsig();
- bool parseDirectiveAddrsigSym();
-
- void initializeDirectiveKindMap();
- void initializeCVDefRangeTypeMap();
-};
-
-} // end anonymous namespace
-
-namespace llvm {
-
-extern MCAsmParserExtension *createDarwinAsmParser();
-extern MCAsmParserExtension *createELFAsmParser();
-extern MCAsmParserExtension *createCOFFAsmParser();
-extern MCAsmParserExtension *createWasmAsmParser();
-
-} // end namespace llvm
-
-enum { DEFAULT_ADDRSPACE = 0 };
-
-AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
- const MCAsmInfo &MAI, unsigned CB = 0)
- : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
- CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {
- HadError = false;
- // Save the old handler.
- SavedDiagHandler = SrcMgr.getDiagHandler();
- SavedDiagContext = SrcMgr.getDiagContext();
- // Set our own handler which calls the saved handler.
- SrcMgr.setDiagHandler(DiagHandler, this);
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
+ // Directives to support address-significance tables.
+ bool parseDirectiveAddrsig();
+ bool parseDirectiveAddrsigSym();
+
+ void initializeDirectiveKindMap();
+ void initializeCVDefRangeTypeMap();
+};
+
+} // end anonymous namespace
+
+namespace llvm {
+
+extern MCAsmParserExtension *createDarwinAsmParser();
+extern MCAsmParserExtension *createELFAsmParser();
+extern MCAsmParserExtension *createCOFFAsmParser();
+extern MCAsmParserExtension *createWasmAsmParser();
+
+} // end namespace llvm
+
+enum { DEFAULT_ADDRSPACE = 0 };
+
+AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
+ const MCAsmInfo &MAI, unsigned CB = 0)
+ : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
+ CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {
+ HadError = false;
+ // Save the old handler.
+ SavedDiagHandler = SrcMgr.getDiagHandler();
+ SavedDiagContext = SrcMgr.getDiagContext();
+ // Set our own handler which calls the saved handler.
+ SrcMgr.setDiagHandler(DiagHandler, this);
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
// Make MCStreamer aware of the StartTokLoc for locations in diagnostics.
Out.setStartTokLocPtr(&StartTokLoc);
-
- // Initialize the platform / file format parser.
- switch (Ctx.getObjectFileInfo()->getObjectFileType()) {
- case MCObjectFileInfo::IsCOFF:
- PlatformParser.reset(createCOFFAsmParser());
- break;
- case MCObjectFileInfo::IsMachO:
- PlatformParser.reset(createDarwinAsmParser());
- IsDarwin = true;
- break;
- case MCObjectFileInfo::IsELF:
- PlatformParser.reset(createELFAsmParser());
- break;
- case MCObjectFileInfo::IsWasm:
- PlatformParser.reset(createWasmAsmParser());
- break;
- case MCObjectFileInfo::IsXCOFF:
- report_fatal_error(
- "Need to implement createXCOFFAsmParser for XCOFF format.");
- break;
- }
-
- PlatformParser->Initialize(*this);
- initializeDirectiveKindMap();
- initializeCVDefRangeTypeMap();
-
- NumOfMacroInstantiations = 0;
-}
-
-AsmParser::~AsmParser() {
- assert((HadError || ActiveMacros.empty()) &&
- "Unexpected active macro instantiation!");
-
+
+ // Initialize the platform / file format parser.
+ switch (Ctx.getObjectFileInfo()->getObjectFileType()) {
+ case MCObjectFileInfo::IsCOFF:
+ PlatformParser.reset(createCOFFAsmParser());
+ break;
+ case MCObjectFileInfo::IsMachO:
+ PlatformParser.reset(createDarwinAsmParser());
+ IsDarwin = true;
+ break;
+ case MCObjectFileInfo::IsELF:
+ PlatformParser.reset(createELFAsmParser());
+ break;
+ case MCObjectFileInfo::IsWasm:
+ PlatformParser.reset(createWasmAsmParser());
+ break;
+ case MCObjectFileInfo::IsXCOFF:
+ report_fatal_error(
+ "Need to implement createXCOFFAsmParser for XCOFF format.");
+ break;
+ }
+
+ PlatformParser->Initialize(*this);
+ initializeDirectiveKindMap();
+ initializeCVDefRangeTypeMap();
+
+ NumOfMacroInstantiations = 0;
+}
+
+AsmParser::~AsmParser() {
+ assert((HadError || ActiveMacros.empty()) &&
+ "Unexpected active macro instantiation!");
+
// Remove MCStreamer's reference to the parser SMLoc.
Out.setStartTokLocPtr(nullptr);
- // Restore the saved diagnostics handler and context for use during
- // finalization.
- SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
-}
-
-void AsmParser::printMacroInstantiations() {
- // Print the active macro instantiation stack.
- for (std::vector<MacroInstantiation *>::const_reverse_iterator
- it = ActiveMacros.rbegin(),
- ie = ActiveMacros.rend();
- it != ie; ++it)
- printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
- "while in macro instantiation");
-}
-
-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, SMRange Range) {
- if(getTargetParser().getTargetOptions().MCNoWarn)
- return false;
- if (getTargetParser().getTargetOptions().MCFatalWarnings)
- return Error(L, Msg, Range);
- printMessage(L, SourceMgr::DK_Warning, Msg, Range);
- printMacroInstantiations();
- return false;
-}
-
-bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
- HadError = true;
- printMessage(L, SourceMgr::DK_Error, Msg, Range);
- printMacroInstantiations();
- return true;
-}
-
-bool AsmParser::enterIncludeFile(const std::string &Filename) {
- std::string IncludedFile;
- unsigned NewBuf =
- SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
- if (!NewBuf)
- return true;
-
- CurBuffer = NewBuf;
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
- return false;
-}
-
-/// 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, int64_t Skip,
- const MCExpr *Count, SMLoc Loc) {
- std::string IncludedFile;
- unsigned NewBuf =
- SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
- if (!NewBuf)
- return true;
-
- // Pick up the bytes from the file and emit them.
- StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();
- Bytes = Bytes.drop_front(Skip);
- if (Count) {
- int64_t Res;
- if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
- 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;
-}
-
-void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
- CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
- Loc.getPointer());
-}
-
-const AsmToken &AsmParser::Lex() {
- if (Lexer.getTok().is(AsmToken::Error))
- Error(Lexer.getErrLoc(), Lexer.getErr());
-
- // if it's a end of statement with a comment in it
- if (getTok().is(AsmToken::EndOfStatement)) {
- // if this is a line comment output it.
- if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
- getTok().getString().front() != '\r' && MAI.preserveAsmComments())
- Out.addExplicitComment(Twine(getTok().getString()));
- }
-
- const AsmToken *tok = &Lexer.Lex();
-
- // Parse comments here to be deferred until end of next statement.
- while (tok->is(AsmToken::Comment)) {
- if (MAI.preserveAsmComments())
- Out.addExplicitComment(Twine(tok->getString()));
- tok = &Lexer.Lex();
- }
-
- if (tok->is(AsmToken::Eof)) {
- // If this is the end of an included file, pop the parent file off the
- // include stack.
- SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
- if (ParentIncludeLoc != SMLoc()) {
- jumpToLoc(ParentIncludeLoc);
- return Lex();
- }
- }
-
- return *tok;
-}
-
-bool AsmParser::enabledGenDwarfForAssembly() {
- // Check whether the user specified -g.
- if (!getContext().getGenDwarfForAssembly())
- return false;
- // If we haven't encountered any .file directives (which would imply that
- // the assembler source was produced with debug info already) then emit one
- // describing the assembler source file itself.
- if (getContext().getGenDwarfFileNumber() == 0) {
- // Use the first #line directive for this, if any. It's preprocessed, so
- // there is no checksum, and of course no source directive.
- if (!FirstCppHashFilename.empty())
- getContext().setMCLineTableRootFile(/*CUID=*/0,
- getContext().getCompilationDir(),
- FirstCppHashFilename,
- /*Cksum=*/None, /*Source=*/None);
- const MCDwarfFile &RootFile =
- getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
- getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
- /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
- RootFile.Checksum, RootFile.Source));
- }
- return true;
-}
-
-bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
- // Create the initial section, if requested.
- if (!NoInitialTextSection)
- Out.InitSections(false);
-
- // Prime the lexer.
- Lex();
-
- HadError = false;
- AsmCond StartingCondState = TheCondState;
- SmallVector<AsmRewrite, 4> AsmStrRewrites;
-
- // If we are generating dwarf for assembly source files save the initial text
- // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't
- // emitting any actual debug info yet and haven't had a chance to parse any
- // embedded .file directives.)
- if (getContext().getGenDwarfForAssembly()) {
- MCSection *Sec = getStreamer().getCurrentSectionOnly();
- if (!Sec->getBeginSymbol()) {
- MCSymbol *SectionStartSym = getContext().createTempSymbol();
- getStreamer().emitLabel(SectionStartSym);
- Sec->setBeginSymbol(SectionStartSym);
- }
- bool InsertResult = getContext().addGenDwarfSection(Sec);
- assert(InsertResult && ".text section should not have debug info yet");
- (void)InsertResult;
- }
-
- // While we have input, parse each statement.
- while (Lexer.isNot(AsmToken::Eof)) {
- ParseStatementInfo Info(&AsmStrRewrites);
- bool Parsed = parseStatement(Info, nullptr);
-
- // 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 (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
- Lex();
- }
-
- // parseStatement returned true so may need to emit an error.
- printPendingErrors();
-
- // Skipping to the next line if needed.
- if (Parsed && !getLexer().isAtStartOfStatement())
- eatToEndOfStatement();
- }
-
- getTargetParser().onEndOfFile();
- printPendingErrors();
-
- // All errors should have been emitted.
- assert(!hasPendingError() && "unexpected error from parseStatement");
-
- getTargetParser().flushPendingInstructions(getStreamer());
-
- if (TheCondState.TheCond != StartingCondState.TheCond ||
- TheCondState.Ignore != StartingCondState.Ignore)
- 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)
- printError(getTok().getLoc(), "unassigned file number: " +
- Twine(Index) +
- " for .file directives");
- ++Index;
- }
- }
-
- // Check to see that all assembler local symbols were actually defined.
- // Targets that don't do subsections via symbols may not want this, though,
- // so conservatively exclude them. Only do this if we're finalizing, though,
- // as otherwise we won't necessarilly have seen everything yet.
- if (!NoFinalize) {
- if (MAI.hasSubsectionsViaSymbols()) {
- for (const auto &TableEntry : getContext().getSymbols()) {
- MCSymbol *Sym = TableEntry.getValue();
- // Variable symbols may not be marked as defined, so check those
- // explicitly. If we know it's a variable, we have a definition for
- // the purposes of this check.
- if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
- // 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.
- printError(getTok().getLoc(), "assembler local symbol '" +
- Sym->getName() + "' not defined");
- }
- }
-
- // Temporary symbols like the ones for directional jumps don't go in the
- // symbol table. They also need to be diagnosed in all (final) cases.
- for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
- if (std::get<2>(LocSym)->isUndefined()) {
- // 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);
- printError(std::get<0>(LocSym), "directional label undefined");
- }
- }
- }
-
- // Finalize the output stream if there are no errors and if the client wants
- // us to.
- if (!HadError && !NoFinalize)
+ // Restore the saved diagnostics handler and context for use during
+ // finalization.
+ SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
+}
+
+void AsmParser::printMacroInstantiations() {
+ // Print the active macro instantiation stack.
+ for (std::vector<MacroInstantiation *>::const_reverse_iterator
+ it = ActiveMacros.rbegin(),
+ ie = ActiveMacros.rend();
+ it != ie; ++it)
+ printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
+ "while in macro instantiation");
+}
+
+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, SMRange Range) {
+ if(getTargetParser().getTargetOptions().MCNoWarn)
+ return false;
+ if (getTargetParser().getTargetOptions().MCFatalWarnings)
+ return Error(L, Msg, Range);
+ printMessage(L, SourceMgr::DK_Warning, Msg, Range);
+ printMacroInstantiations();
+ return false;
+}
+
+bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
+ HadError = true;
+ printMessage(L, SourceMgr::DK_Error, Msg, Range);
+ printMacroInstantiations();
+ return true;
+}
+
+bool AsmParser::enterIncludeFile(const std::string &Filename) {
+ std::string IncludedFile;
+ unsigned NewBuf =
+ SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
+ if (!NewBuf)
+ return true;
+
+ CurBuffer = NewBuf;
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
+ return false;
+}
+
+/// 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, int64_t Skip,
+ const MCExpr *Count, SMLoc Loc) {
+ std::string IncludedFile;
+ unsigned NewBuf =
+ SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
+ if (!NewBuf)
+ return true;
+
+ // Pick up the bytes from the file and emit them.
+ StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();
+ Bytes = Bytes.drop_front(Skip);
+ if (Count) {
+ int64_t Res;
+ if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
+ 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;
+}
+
+void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
+ CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
+ Loc.getPointer());
+}
+
+const AsmToken &AsmParser::Lex() {
+ if (Lexer.getTok().is(AsmToken::Error))
+ Error(Lexer.getErrLoc(), Lexer.getErr());
+
+ // if it's a end of statement with a comment in it
+ if (getTok().is(AsmToken::EndOfStatement)) {
+ // if this is a line comment output it.
+ if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
+ getTok().getString().front() != '\r' && MAI.preserveAsmComments())
+ Out.addExplicitComment(Twine(getTok().getString()));
+ }
+
+ const AsmToken *tok = &Lexer.Lex();
+
+ // Parse comments here to be deferred until end of next statement.
+ while (tok->is(AsmToken::Comment)) {
+ if (MAI.preserveAsmComments())
+ Out.addExplicitComment(Twine(tok->getString()));
+ tok = &Lexer.Lex();
+ }
+
+ if (tok->is(AsmToken::Eof)) {
+ // If this is the end of an included file, pop the parent file off the
+ // include stack.
+ SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
+ if (ParentIncludeLoc != SMLoc()) {
+ jumpToLoc(ParentIncludeLoc);
+ return Lex();
+ }
+ }
+
+ return *tok;
+}
+
+bool AsmParser::enabledGenDwarfForAssembly() {
+ // Check whether the user specified -g.
+ if (!getContext().getGenDwarfForAssembly())
+ return false;
+ // If we haven't encountered any .file directives (which would imply that
+ // the assembler source was produced with debug info already) then emit one
+ // describing the assembler source file itself.
+ if (getContext().getGenDwarfFileNumber() == 0) {
+ // Use the first #line directive for this, if any. It's preprocessed, so
+ // there is no checksum, and of course no source directive.
+ if (!FirstCppHashFilename.empty())
+ getContext().setMCLineTableRootFile(/*CUID=*/0,
+ getContext().getCompilationDir(),
+ FirstCppHashFilename,
+ /*Cksum=*/None, /*Source=*/None);
+ const MCDwarfFile &RootFile =
+ getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
+ getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
+ /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
+ RootFile.Checksum, RootFile.Source));
+ }
+ return true;
+}
+
+bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
+ // Create the initial section, if requested.
+ if (!NoInitialTextSection)
+ Out.InitSections(false);
+
+ // Prime the lexer.
+ Lex();
+
+ HadError = false;
+ AsmCond StartingCondState = TheCondState;
+ SmallVector<AsmRewrite, 4> AsmStrRewrites;
+
+ // If we are generating dwarf for assembly source files save the initial text
+ // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't
+ // emitting any actual debug info yet and haven't had a chance to parse any
+ // embedded .file directives.)
+ if (getContext().getGenDwarfForAssembly()) {
+ MCSection *Sec = getStreamer().getCurrentSectionOnly();
+ if (!Sec->getBeginSymbol()) {
+ MCSymbol *SectionStartSym = getContext().createTempSymbol();
+ getStreamer().emitLabel(SectionStartSym);
+ Sec->setBeginSymbol(SectionStartSym);
+ }
+ bool InsertResult = getContext().addGenDwarfSection(Sec);
+ assert(InsertResult && ".text section should not have debug info yet");
+ (void)InsertResult;
+ }
+
+ // While we have input, parse each statement.
+ while (Lexer.isNot(AsmToken::Eof)) {
+ ParseStatementInfo Info(&AsmStrRewrites);
+ bool Parsed = parseStatement(Info, nullptr);
+
+ // 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 (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
+ Lex();
+ }
+
+ // parseStatement returned true so may need to emit an error.
+ printPendingErrors();
+
+ // Skipping to the next line if needed.
+ if (Parsed && !getLexer().isAtStartOfStatement())
+ eatToEndOfStatement();
+ }
+
+ getTargetParser().onEndOfFile();
+ printPendingErrors();
+
+ // All errors should have been emitted.
+ assert(!hasPendingError() && "unexpected error from parseStatement");
+
+ getTargetParser().flushPendingInstructions(getStreamer());
+
+ if (TheCondState.TheCond != StartingCondState.TheCond ||
+ TheCondState.Ignore != StartingCondState.Ignore)
+ 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)
+ printError(getTok().getLoc(), "unassigned file number: " +
+ Twine(Index) +
+ " for .file directives");
+ ++Index;
+ }
+ }
+
+ // Check to see that all assembler local symbols were actually defined.
+ // Targets that don't do subsections via symbols may not want this, though,
+ // so conservatively exclude them. Only do this if we're finalizing, though,
+ // as otherwise we won't necessarilly have seen everything yet.
+ if (!NoFinalize) {
+ if (MAI.hasSubsectionsViaSymbols()) {
+ for (const auto &TableEntry : getContext().getSymbols()) {
+ MCSymbol *Sym = TableEntry.getValue();
+ // Variable symbols may not be marked as defined, so check those
+ // explicitly. If we know it's a variable, we have a definition for
+ // the purposes of this check.
+ if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
+ // 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.
+ printError(getTok().getLoc(), "assembler local symbol '" +
+ Sym->getName() + "' not defined");
+ }
+ }
+
+ // Temporary symbols like the ones for directional jumps don't go in the
+ // symbol table. They also need to be diagnosed in all (final) cases.
+ for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
+ if (std::get<2>(LocSym)->isUndefined()) {
+ // 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);
+ printError(std::get<0>(LocSym), "directional label undefined");
+ }
+ }
+ }
+
+ // Finalize the output stream if there are no errors and if the client wants
+ // us to.
+ if (!HadError && !NoFinalize)
Out.Finish(Lexer.getLoc());
-
- return HadError || getContext().hadError();
-}
-
-bool AsmParser::checkForValidSection() {
- if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
- Out.InitSections(false);
- return Error(getTok().getLoc(),
- "expected section directive before assembly directive");
- }
- return false;
-}
-
-/// Throw away the rest of the line for testing purposes.
-void AsmParser::eatToEndOfStatement() {
- while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
- Lexer.Lex();
-
- // Eat EOL.
- if (Lexer.is(AsmToken::EndOfStatement))
- Lexer.Lex();
-}
-
-StringRef AsmParser::parseStringToEndOfStatement() {
- const char *Start = getTok().getLoc().getPointer();
-
- while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
- Lexer.Lex();
-
- const char *End = getTok().getLoc().getPointer();
- return StringRef(Start, End - Start);
-}
-
-StringRef AsmParser::parseStringToComma() {
- const char *Start = getTok().getLoc().getPointer();
-
- while (Lexer.isNot(AsmToken::EndOfStatement) &&
- Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof))
- Lexer.Lex();
-
- const char *End = getTok().getLoc().getPointer();
- return StringRef(Start, End - Start);
-}
-
-/// Parse a paren expression and return it.
-/// NOTE: This assumes the leading '(' has already been consumed.
-///
-/// parenexpr ::= expr)
-///
-bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- if (parseExpression(Res))
- return true;
- if (Lexer.isNot(AsmToken::RParen))
- return TokError("expected ')' in parentheses expression");
- EndLoc = Lexer.getTok().getEndLoc();
- Lex();
- return false;
-}
-
-/// Parse a bracket expression and return it.
-/// NOTE: This assumes the leading '[' has already been consumed.
-///
-/// bracketexpr ::= expr]
-///
-bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- if (parseExpression(Res))
- return true;
- EndLoc = getTok().getEndLoc();
- if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
- return true;
- return false;
-}
-
-/// Parse a primary expression and return it.
-/// primaryexpr ::= (parenexpr
-/// primaryexpr ::= symbol
-/// primaryexpr ::= number
-/// primaryexpr ::= '.'
-/// primaryexpr ::= ~,+,- primaryexpr
+
+ return HadError || getContext().hadError();
+}
+
+bool AsmParser::checkForValidSection() {
+ if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
+ Out.InitSections(false);
+ return Error(getTok().getLoc(),
+ "expected section directive before assembly directive");
+ }
+ return false;
+}
+
+/// Throw away the rest of the line for testing purposes.
+void AsmParser::eatToEndOfStatement() {
+ while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
+ Lexer.Lex();
+
+ // Eat EOL.
+ if (Lexer.is(AsmToken::EndOfStatement))
+ Lexer.Lex();
+}
+
+StringRef AsmParser::parseStringToEndOfStatement() {
+ const char *Start = getTok().getLoc().getPointer();
+
+ while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
+ Lexer.Lex();
+
+ const char *End = getTok().getLoc().getPointer();
+ return StringRef(Start, End - Start);
+}
+
+StringRef AsmParser::parseStringToComma() {
+ const char *Start = getTok().getLoc().getPointer();
+
+ while (Lexer.isNot(AsmToken::EndOfStatement) &&
+ Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof))
+ Lexer.Lex();
+
+ const char *End = getTok().getLoc().getPointer();
+ return StringRef(Start, End - Start);
+}
+
+/// Parse a paren expression and return it.
+/// NOTE: This assumes the leading '(' has already been consumed.
+///
+/// parenexpr ::= expr)
+///
+bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+ if (parseExpression(Res))
+ return true;
+ if (Lexer.isNot(AsmToken::RParen))
+ return TokError("expected ')' in parentheses expression");
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex();
+ return false;
+}
+
+/// Parse a bracket expression and return it.
+/// NOTE: This assumes the leading '[' has already been consumed.
+///
+/// bracketexpr ::= expr]
+///
+bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+ if (parseExpression(Res))
+ return true;
+ EndLoc = getTok().getEndLoc();
+ if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
+ return true;
+ return false;
+}
+
+/// Parse a primary expression and return it.
+/// primaryexpr ::= (parenexpr
+/// primaryexpr ::= symbol
+/// primaryexpr ::= number
+/// primaryexpr ::= '.'
+/// primaryexpr ::= ~,+,- primaryexpr
bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
AsmTypeInfo *TypeInfo) {
- SMLoc FirstTokenLoc = getLexer().getLoc();
- AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
- switch (FirstTokenKind) {
- default:
- return TokError("unknown token in expression");
- // If we have an error assume that we've already handled it.
- case AsmToken::Error:
- return true;
- case AsmToken::Exclaim:
- Lex(); // Eat the operator.
+ SMLoc FirstTokenLoc = getLexer().getLoc();
+ AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
+ switch (FirstTokenKind) {
+ default:
+ return TokError("unknown token in expression");
+ // If we have an error assume that we've already handled it.
+ case AsmToken::Error:
+ return true;
+ case AsmToken::Exclaim:
+ Lex(); // Eat the operator.
if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
- return true;
- Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
- return false;
- case AsmToken::Dollar:
- case AsmToken::At:
- case AsmToken::String:
- case AsmToken::Identifier: {
- StringRef Identifier;
- if (parseIdentifier(Identifier)) {
- // 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();
- Out.emitLabel(Sym);
- Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
- getContext());
- EndLoc = FirstTokenLoc;
- return false;
- }
- return Error(FirstTokenLoc, "invalid token in expression");
- }
- }
- // Parse symbol variant
- std::pair<StringRef, StringRef> Split;
- if (!MAI.useParensForSymbolVariant()) {
- if (FirstTokenKind == AsmToken::String) {
- if (Lexer.is(AsmToken::At)) {
- Lex(); // eat @
- SMLoc AtLoc = getLexer().getLoc();
- StringRef VName;
- if (parseIdentifier(VName))
- return Error(AtLoc, "expected symbol variant after '@'");
-
- Split = std::make_pair(Identifier, VName);
- }
- } else {
- Split = Identifier.split('@');
- }
- } else if (Lexer.is(AsmToken::LParen)) {
- Lex(); // eat '('.
- StringRef VName;
- parseIdentifier(VName);
- // eat ')'.
- if (parseToken(AsmToken::RParen,
- "unexpected token in variant, expected ')'"))
- return true;
- Split = std::make_pair(Identifier, VName);
- }
-
- EndLoc = SMLoc::getFromPointer(Identifier.end());
-
- // This is a symbol reference.
- StringRef SymbolName = Identifier;
- if (SymbolName.empty())
- return Error(getLexer().getLoc(), "expected a symbol reference");
-
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
-
- // Lookup the symbol variant if used.
- if (!Split.second.empty()) {
- Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
- if (Variant != MCSymbolRefExpr::VK_Invalid) {
- SymbolName = Split.first;
- } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
- Variant = MCSymbolRefExpr::VK_None;
- } else {
- return Error(SMLoc::getFromPointer(Split.second.begin()),
- "invalid variant '" + Split.second + "'");
- }
- }
-
- MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
- if (!Sym)
- Sym = getContext().getOrCreateSymbol(SymbolName);
-
- // If this is an absolute variable reference, substitute it now to preserve
- // semantics in the face of reassignment.
- if (Sym->isVariable()) {
- auto V = Sym->getVariableValue(/*SetUsed*/ false);
- bool DoInline = isa<MCConstantExpr>(V) && !Variant;
- if (auto TV = dyn_cast<MCTargetExpr>(V))
- DoInline = TV->inlineAssignedExpr();
- if (DoInline) {
- if (Variant)
- return Error(EndLoc, "unexpected modifier on variable reference");
- Res = Sym->getVariableValue(/*SetUsed*/ false);
- return false;
- }
- }
-
- // Otherwise create a symbol ref.
- Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
- return false;
- }
- case AsmToken::BigNum:
- return TokError("literal value out of range for directive");
- case AsmToken::Integer: {
- SMLoc Loc = getTok().getLoc();
- int64_t IntVal = getTok().getIntVal();
- Res = MCConstantExpr::create(IntVal, getContext());
- EndLoc = Lexer.getTok().getEndLoc();
- Lex(); // Eat token.
- // Look for 'b' or 'f' following an Integer as a directional label
- if (Lexer.getKind() == AsmToken::Identifier) {
- StringRef IDVal = getTok().getString();
- // Lookup the symbol variant if used.
- std::pair<StringRef, StringRef> Split = IDVal.split('@');
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
- if (Split.first.size() != IDVal.size()) {
- Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
- if (Variant == MCSymbolRefExpr::VK_Invalid)
- return TokError("invalid variant '" + Split.second + "'");
- IDVal = Split.first;
- }
- if (IDVal == "f" || IDVal == "b") {
- MCSymbol *Sym =
- Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
- Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
- if (IDVal == "b" && Sym->isUndefined())
- return Error(Loc, "directional label undefined");
- DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
- EndLoc = Lexer.getTok().getEndLoc();
- Lex(); // Eat identifier.
- }
- }
- return false;
- }
- case AsmToken::Real: {
- APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
- uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
- Res = MCConstantExpr::create(IntVal, getContext());
- EndLoc = Lexer.getTok().getEndLoc();
- Lex(); // Eat token.
- return false;
- }
- case AsmToken::Dot: {
- // This is a '.' reference, which references the current PC. Emit a
- // temporary label to the streamer and refer to it.
- MCSymbol *Sym = Ctx.createTempSymbol();
- Out.emitLabel(Sym);
- Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
- EndLoc = Lexer.getTok().getEndLoc();
- Lex(); // Eat identifier.
- return false;
- }
- case AsmToken::LParen:
- Lex(); // Eat the '('.
- return parseParenExpr(Res, EndLoc);
- case AsmToken::LBrac:
- if (!PlatformParser->HasBracketExpressions())
- return TokError("brackets expression not supported on this target");
- Lex(); // Eat the '['.
- return parseBracketExpr(Res, EndLoc);
- case AsmToken::Minus:
- Lex(); // Eat the operator.
+ return true;
+ Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
+ return false;
+ case AsmToken::Dollar:
+ case AsmToken::At:
+ case AsmToken::String:
+ case AsmToken::Identifier: {
+ StringRef Identifier;
+ if (parseIdentifier(Identifier)) {
+ // 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();
+ Out.emitLabel(Sym);
+ Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
+ getContext());
+ EndLoc = FirstTokenLoc;
+ return false;
+ }
+ return Error(FirstTokenLoc, "invalid token in expression");
+ }
+ }
+ // Parse symbol variant
+ std::pair<StringRef, StringRef> Split;
+ if (!MAI.useParensForSymbolVariant()) {
+ if (FirstTokenKind == AsmToken::String) {
+ if (Lexer.is(AsmToken::At)) {
+ Lex(); // eat @
+ SMLoc AtLoc = getLexer().getLoc();
+ StringRef VName;
+ if (parseIdentifier(VName))
+ return Error(AtLoc, "expected symbol variant after '@'");
+
+ Split = std::make_pair(Identifier, VName);
+ }
+ } else {
+ Split = Identifier.split('@');
+ }
+ } else if (Lexer.is(AsmToken::LParen)) {
+ Lex(); // eat '('.
+ StringRef VName;
+ parseIdentifier(VName);
+ // eat ')'.
+ if (parseToken(AsmToken::RParen,
+ "unexpected token in variant, expected ')'"))
+ return true;
+ Split = std::make_pair(Identifier, VName);
+ }
+
+ EndLoc = SMLoc::getFromPointer(Identifier.end());
+
+ // This is a symbol reference.
+ StringRef SymbolName = Identifier;
+ if (SymbolName.empty())
+ return Error(getLexer().getLoc(), "expected a symbol reference");
+
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+
+ // Lookup the symbol variant if used.
+ if (!Split.second.empty()) {
+ Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
+ if (Variant != MCSymbolRefExpr::VK_Invalid) {
+ SymbolName = Split.first;
+ } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
+ Variant = MCSymbolRefExpr::VK_None;
+ } else {
+ return Error(SMLoc::getFromPointer(Split.second.begin()),
+ "invalid variant '" + Split.second + "'");
+ }
+ }
+
+ MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
+ if (!Sym)
+ Sym = getContext().getOrCreateSymbol(SymbolName);
+
+ // If this is an absolute variable reference, substitute it now to preserve
+ // semantics in the face of reassignment.
+ if (Sym->isVariable()) {
+ auto V = Sym->getVariableValue(/*SetUsed*/ false);
+ bool DoInline = isa<MCConstantExpr>(V) && !Variant;
+ if (auto TV = dyn_cast<MCTargetExpr>(V))
+ DoInline = TV->inlineAssignedExpr();
+ if (DoInline) {
+ if (Variant)
+ return Error(EndLoc, "unexpected modifier on variable reference");
+ Res = Sym->getVariableValue(/*SetUsed*/ false);
+ return false;
+ }
+ }
+
+ // Otherwise create a symbol ref.
+ Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
+ return false;
+ }
+ case AsmToken::BigNum:
+ return TokError("literal value out of range for directive");
+ case AsmToken::Integer: {
+ SMLoc Loc = getTok().getLoc();
+ int64_t IntVal = getTok().getIntVal();
+ Res = MCConstantExpr::create(IntVal, getContext());
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex(); // Eat token.
+ // Look for 'b' or 'f' following an Integer as a directional label
+ if (Lexer.getKind() == AsmToken::Identifier) {
+ StringRef IDVal = getTok().getString();
+ // Lookup the symbol variant if used.
+ std::pair<StringRef, StringRef> Split = IDVal.split('@');
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+ if (Split.first.size() != IDVal.size()) {
+ Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
+ if (Variant == MCSymbolRefExpr::VK_Invalid)
+ return TokError("invalid variant '" + Split.second + "'");
+ IDVal = Split.first;
+ }
+ if (IDVal == "f" || IDVal == "b") {
+ MCSymbol *Sym =
+ Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
+ Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
+ if (IDVal == "b" && Sym->isUndefined())
+ return Error(Loc, "directional label undefined");
+ DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex(); // Eat identifier.
+ }
+ }
+ return false;
+ }
+ case AsmToken::Real: {
+ APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
+ uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
+ Res = MCConstantExpr::create(IntVal, getContext());
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex(); // Eat token.
+ return false;
+ }
+ case AsmToken::Dot: {
+ // This is a '.' reference, which references the current PC. Emit a
+ // temporary label to the streamer and refer to it.
+ MCSymbol *Sym = Ctx.createTempSymbol();
+ Out.emitLabel(Sym);
+ Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex(); // Eat identifier.
+ return false;
+ }
+ case AsmToken::LParen:
+ Lex(); // Eat the '('.
+ return parseParenExpr(Res, EndLoc);
+ case AsmToken::LBrac:
+ if (!PlatformParser->HasBracketExpressions())
+ return TokError("brackets expression not supported on this target");
+ Lex(); // Eat the '['.
+ return parseBracketExpr(Res, EndLoc);
+ case AsmToken::Minus:
+ Lex(); // Eat the operator.
if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
- return true;
- Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
- return false;
- case AsmToken::Plus:
- Lex(); // Eat the operator.
+ return true;
+ Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
+ return false;
+ case AsmToken::Plus:
+ Lex(); // Eat the operator.
if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
- return true;
- Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
- return false;
- case AsmToken::Tilde:
- Lex(); // Eat the operator.
+ return true;
+ Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
+ return false;
+ case AsmToken::Tilde:
+ Lex(); // Eat the operator.
if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
- return true;
- Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
- 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;
- }
-}
-
-bool AsmParser::parseExpression(const MCExpr *&Res) {
- SMLoc EndLoc;
- return parseExpression(Res, EndLoc);
-}
-
-const MCExpr *
-AsmParser::applyModifierToExpr(const MCExpr *E,
- MCSymbolRefExpr::VariantKind Variant) {
- // Ask the target implementation about this expression first.
- const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx);
- if (NewE)
- return NewE;
- // Recurse over the given expression, rebuilding it to apply the given variant
- // if there is exactly one symbol.
- switch (E->getKind()) {
- case MCExpr::Target:
- case MCExpr::Constant:
- return nullptr;
-
- case MCExpr::SymbolRef: {
- const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
-
- if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
- TokError("invalid variant on expression '" + getTok().getIdentifier() +
- "' (already modified)");
- return E;
- }
-
- return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext());
- }
-
- case MCExpr::Unary: {
- const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
- const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant);
- if (!Sub)
- return nullptr;
- return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext());
- }
-
- case MCExpr::Binary: {
- const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
- const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant);
- const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant);
-
- if (!LHS && !RHS)
- return nullptr;
-
- if (!LHS)
- LHS = BE->getLHS();
- if (!RHS)
- RHS = BE->getRHS();
-
- return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext());
- }
- }
-
- llvm_unreachable("Invalid expression kind!");
-}
-
-/// This function checks if the next token is <string> type or arithmetic.
-/// string that begin with character '<' must end with character '>'.
-/// otherwise it is arithmetics.
-/// If the function returns a 'true' value,
-/// the End argument will be filled with the last location pointed to the '>'
-/// character.
-
-/// There is a gap between the AltMacro's documentation and the single quote
-/// implementation. GCC does not fully support this feature and so we will not
-/// support it.
-/// TODO: Adding single quote as a string.
-static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
- assert((StrLoc.getPointer() != nullptr) &&
- "Argument to the function cannot be a NULL value");
- const char *CharPtr = StrLoc.getPointer();
- while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
- (*CharPtr != '\0')) {
- if (*CharPtr == '!')
- CharPtr++;
- CharPtr++;
- }
- if (*CharPtr == '>') {
- EndLoc = StrLoc.getFromPointer(CharPtr + 1);
- return true;
- }
- return false;
-}
-
-/// creating a string without the escape characters '!'.
-static std::string angleBracketString(StringRef AltMacroStr) {
- std::string Res;
- for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
- if (AltMacroStr[Pos] == '!')
- Pos++;
- Res += AltMacroStr[Pos];
- }
- return Res;
-}
-
-/// Parse an expression and return it.
-///
-/// expr ::= expr &&,|| expr -> lowest.
-/// expr ::= expr |,^,&,! expr
-/// expr ::= expr ==,!=,<>,<,<=,>,>= expr
-/// expr ::= expr <<,>> expr
-/// expr ::= expr +,- expr
-/// expr ::= expr *,/,% expr -> highest.
-/// expr ::= primaryexpr
-///
-bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
- // Parse the expression.
- Res = nullptr;
- if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
- parseBinOpRHS(1, Res, EndLoc))
- return true;
-
- // As a special case, we support 'a op b @ modifier' by rewriting the
- // expression to include the modifier. This is inefficient, but in general we
- // expect users to use 'a@modifier op b'.
- if (Lexer.getKind() == AsmToken::At) {
- Lex();
-
- if (Lexer.isNot(AsmToken::Identifier))
- return TokError("unexpected symbol modifier following '@'");
-
- MCSymbolRefExpr::VariantKind Variant =
- MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
- if (Variant == MCSymbolRefExpr::VK_Invalid)
- return TokError("invalid variant '" + getTok().getIdentifier() + "'");
-
- const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant);
- if (!ModifiedRes) {
- return TokError("invalid modifier '" + getTok().getIdentifier() +
- "' (no symbols present)");
- }
-
- Res = ModifiedRes;
- Lex();
- }
-
- // Try to constant fold it up front, if possible. Do not exploit
- // assembler here.
- int64_t Value;
- if (Res->evaluateAsAbsolute(Value))
- Res = MCConstantExpr::create(Value, getContext());
-
- return false;
-}
-
-bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
- Res = nullptr;
- return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
-}
-
-bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
- SMLoc &EndLoc) {
- if (parseParenExpr(Res, EndLoc))
- return true;
-
- for (; ParenDepth > 0; --ParenDepth) {
- if (parseBinOpRHS(1, Res, EndLoc))
- return true;
-
- // We don't Lex() the last RParen.
- // This is the same behavior as parseParenExpression().
- if (ParenDepth - 1 > 0) {
- EndLoc = getTok().getEndLoc();
- if (parseToken(AsmToken::RParen,
- "expected ')' in parentheses expression"))
- return true;
- }
- }
- return false;
-}
-
-bool AsmParser::parseAbsoluteExpression(int64_t &Res) {
- const MCExpr *Expr;
-
- SMLoc StartLoc = Lexer.getLoc();
- if (parseExpression(Expr))
- return true;
-
- if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
- return Error(StartLoc, "expected absolute expression");
-
- return false;
-}
-
-static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind,
- bool ShouldUseLogicalShr) {
- switch (K) {
- default:
- return 0; // not a binop.
-
- // Lowest Precedence: &&, ||
- case AsmToken::AmpAmp:
- Kind = MCBinaryExpr::LAnd;
- return 1;
- case AsmToken::PipePipe:
- Kind = MCBinaryExpr::LOr;
- return 1;
-
- // Low Precedence: |, &, ^
- case AsmToken::Pipe:
- Kind = MCBinaryExpr::Or;
- return 2;
- case AsmToken::Caret:
- Kind = MCBinaryExpr::Xor;
- return 2;
- case AsmToken::Amp:
- Kind = MCBinaryExpr::And;
- return 2;
-
- // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
- case AsmToken::EqualEqual:
- Kind = MCBinaryExpr::EQ;
- return 3;
- case AsmToken::ExclaimEqual:
- case AsmToken::LessGreater:
- Kind = MCBinaryExpr::NE;
- return 3;
- case AsmToken::Less:
- Kind = MCBinaryExpr::LT;
- return 3;
- case AsmToken::LessEqual:
- Kind = MCBinaryExpr::LTE;
- return 3;
- case AsmToken::Greater:
- Kind = MCBinaryExpr::GT;
- return 3;
- case AsmToken::GreaterEqual:
- Kind = MCBinaryExpr::GTE;
- return 3;
-
- // Intermediate Precedence: <<, >>
- case AsmToken::LessLess:
- Kind = MCBinaryExpr::Shl;
- return 4;
- case AsmToken::GreaterGreater:
- Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
- return 4;
-
- // High Intermediate Precedence: +, -
- case AsmToken::Plus:
- Kind = MCBinaryExpr::Add;
- return 5;
- case AsmToken::Minus:
- Kind = MCBinaryExpr::Sub;
- return 5;
-
- // Highest Precedence: *, /, %
- case AsmToken::Star:
- Kind = MCBinaryExpr::Mul;
- return 6;
- case AsmToken::Slash:
- Kind = MCBinaryExpr::Div;
- return 6;
- case AsmToken::Percent:
- Kind = MCBinaryExpr::Mod;
- return 6;
- }
-}
-
+ return true;
+ Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
+ 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;
+ }
+}
+
+bool AsmParser::parseExpression(const MCExpr *&Res) {
+ SMLoc EndLoc;
+ return parseExpression(Res, EndLoc);
+}
+
+const MCExpr *
+AsmParser::applyModifierToExpr(const MCExpr *E,
+ MCSymbolRefExpr::VariantKind Variant) {
+ // Ask the target implementation about this expression first.
+ const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx);
+ if (NewE)
+ return NewE;
+ // Recurse over the given expression, rebuilding it to apply the given variant
+ // if there is exactly one symbol.
+ switch (E->getKind()) {
+ case MCExpr::Target:
+ case MCExpr::Constant:
+ return nullptr;
+
+ case MCExpr::SymbolRef: {
+ const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
+
+ if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
+ TokError("invalid variant on expression '" + getTok().getIdentifier() +
+ "' (already modified)");
+ return E;
+ }
+
+ return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext());
+ }
+
+ case MCExpr::Unary: {
+ const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
+ const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant);
+ if (!Sub)
+ return nullptr;
+ return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext());
+ }
+
+ case MCExpr::Binary: {
+ const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
+ const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant);
+ const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant);
+
+ if (!LHS && !RHS)
+ return nullptr;
+
+ if (!LHS)
+ LHS = BE->getLHS();
+ if (!RHS)
+ RHS = BE->getRHS();
+
+ return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext());
+ }
+ }
+
+ llvm_unreachable("Invalid expression kind!");
+}
+
+/// This function checks if the next token is <string> type or arithmetic.
+/// string that begin with character '<' must end with character '>'.
+/// otherwise it is arithmetics.
+/// If the function returns a 'true' value,
+/// the End argument will be filled with the last location pointed to the '>'
+/// character.
+
+/// There is a gap between the AltMacro's documentation and the single quote
+/// implementation. GCC does not fully support this feature and so we will not
+/// support it.
+/// TODO: Adding single quote as a string.
+static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
+ assert((StrLoc.getPointer() != nullptr) &&
+ "Argument to the function cannot be a NULL value");
+ const char *CharPtr = StrLoc.getPointer();
+ while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
+ (*CharPtr != '\0')) {
+ if (*CharPtr == '!')
+ CharPtr++;
+ CharPtr++;
+ }
+ if (*CharPtr == '>') {
+ EndLoc = StrLoc.getFromPointer(CharPtr + 1);
+ return true;
+ }
+ return false;
+}
+
+/// creating a string without the escape characters '!'.
+static std::string angleBracketString(StringRef AltMacroStr) {
+ std::string Res;
+ for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
+ if (AltMacroStr[Pos] == '!')
+ Pos++;
+ Res += AltMacroStr[Pos];
+ }
+ return Res;
+}
+
+/// Parse an expression and return it.
+///
+/// expr ::= expr &&,|| expr -> lowest.
+/// expr ::= expr |,^,&,! expr
+/// expr ::= expr ==,!=,<>,<,<=,>,>= expr
+/// expr ::= expr <<,>> expr
+/// expr ::= expr +,- expr
+/// expr ::= expr *,/,% expr -> highest.
+/// expr ::= primaryexpr
+///
+bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
+ // Parse the expression.
+ Res = nullptr;
+ if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
+ parseBinOpRHS(1, Res, EndLoc))
+ return true;
+
+ // As a special case, we support 'a op b @ modifier' by rewriting the
+ // expression to include the modifier. This is inefficient, but in general we
+ // expect users to use 'a@modifier op b'.
+ if (Lexer.getKind() == AsmToken::At) {
+ Lex();
+
+ if (Lexer.isNot(AsmToken::Identifier))
+ return TokError("unexpected symbol modifier following '@'");
+
+ MCSymbolRefExpr::VariantKind Variant =
+ MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
+ if (Variant == MCSymbolRefExpr::VK_Invalid)
+ return TokError("invalid variant '" + getTok().getIdentifier() + "'");
+
+ const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant);
+ if (!ModifiedRes) {
+ return TokError("invalid modifier '" + getTok().getIdentifier() +
+ "' (no symbols present)");
+ }
+
+ Res = ModifiedRes;
+ Lex();
+ }
+
+ // Try to constant fold it up front, if possible. Do not exploit
+ // assembler here.
+ int64_t Value;
+ if (Res->evaluateAsAbsolute(Value))
+ Res = MCConstantExpr::create(Value, getContext());
+
+ return false;
+}
+
+bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
+ Res = nullptr;
+ return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
+}
+
+bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
+ SMLoc &EndLoc) {
+ if (parseParenExpr(Res, EndLoc))
+ return true;
+
+ for (; ParenDepth > 0; --ParenDepth) {
+ if (parseBinOpRHS(1, Res, EndLoc))
+ return true;
+
+ // We don't Lex() the last RParen.
+ // This is the same behavior as parseParenExpression().
+ if (ParenDepth - 1 > 0) {
+ EndLoc = getTok().getEndLoc();
+ if (parseToken(AsmToken::RParen,
+ "expected ')' in parentheses expression"))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool AsmParser::parseAbsoluteExpression(int64_t &Res) {
+ const MCExpr *Expr;
+
+ SMLoc StartLoc = Lexer.getLoc();
+ if (parseExpression(Expr))
+ return true;
+
+ if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
+ return Error(StartLoc, "expected absolute expression");
+
+ return false;
+}
+
+static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K,
+ MCBinaryExpr::Opcode &Kind,
+ bool ShouldUseLogicalShr) {
+ switch (K) {
+ default:
+ return 0; // not a binop.
+
+ // Lowest Precedence: &&, ||
+ case AsmToken::AmpAmp:
+ Kind = MCBinaryExpr::LAnd;
+ return 1;
+ case AsmToken::PipePipe:
+ Kind = MCBinaryExpr::LOr;
+ return 1;
+
+ // Low Precedence: |, &, ^
+ case AsmToken::Pipe:
+ Kind = MCBinaryExpr::Or;
+ return 2;
+ case AsmToken::Caret:
+ Kind = MCBinaryExpr::Xor;
+ return 2;
+ case AsmToken::Amp:
+ Kind = MCBinaryExpr::And;
+ return 2;
+
+ // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
+ case AsmToken::EqualEqual:
+ Kind = MCBinaryExpr::EQ;
+ return 3;
+ case AsmToken::ExclaimEqual:
+ case AsmToken::LessGreater:
+ Kind = MCBinaryExpr::NE;
+ return 3;
+ case AsmToken::Less:
+ Kind = MCBinaryExpr::LT;
+ return 3;
+ case AsmToken::LessEqual:
+ Kind = MCBinaryExpr::LTE;
+ return 3;
+ case AsmToken::Greater:
+ Kind = MCBinaryExpr::GT;
+ return 3;
+ case AsmToken::GreaterEqual:
+ Kind = MCBinaryExpr::GTE;
+ return 3;
+
+ // Intermediate Precedence: <<, >>
+ case AsmToken::LessLess:
+ Kind = MCBinaryExpr::Shl;
+ return 4;
+ case AsmToken::GreaterGreater:
+ Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
+ return 4;
+
+ // High Intermediate Precedence: +, -
+ case AsmToken::Plus:
+ Kind = MCBinaryExpr::Add;
+ return 5;
+ case AsmToken::Minus:
+ Kind = MCBinaryExpr::Sub;
+ return 5;
+
+ // Highest Precedence: *, /, %
+ case AsmToken::Star:
+ Kind = MCBinaryExpr::Mul;
+ return 6;
+ case AsmToken::Slash:
+ Kind = MCBinaryExpr::Div;
+ return 6;
+ case AsmToken::Percent:
+ Kind = MCBinaryExpr::Mod;
+ return 6;
+ }
+}
+
static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI,
AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind,
- bool ShouldUseLogicalShr) {
- switch (K) {
- default:
- return 0; // not a binop.
-
- // Lowest Precedence: &&, ||
- case AsmToken::AmpAmp:
- Kind = MCBinaryExpr::LAnd;
- return 2;
- case AsmToken::PipePipe:
- Kind = MCBinaryExpr::LOr;
- return 1;
-
- // Low Precedence: ==, !=, <>, <, <=, >, >=
- case AsmToken::EqualEqual:
- Kind = MCBinaryExpr::EQ;
- return 3;
- case AsmToken::ExclaimEqual:
- case AsmToken::LessGreater:
- Kind = MCBinaryExpr::NE;
- return 3;
- case AsmToken::Less:
- Kind = MCBinaryExpr::LT;
- return 3;
- case AsmToken::LessEqual:
- Kind = MCBinaryExpr::LTE;
- return 3;
- case AsmToken::Greater:
- Kind = MCBinaryExpr::GT;
- return 3;
- case AsmToken::GreaterEqual:
- Kind = MCBinaryExpr::GTE;
- return 3;
-
- // Low Intermediate Precedence: +, -
- case AsmToken::Plus:
- Kind = MCBinaryExpr::Add;
- return 4;
- case AsmToken::Minus:
- Kind = MCBinaryExpr::Sub;
- return 4;
-
+ MCBinaryExpr::Opcode &Kind,
+ bool ShouldUseLogicalShr) {
+ switch (K) {
+ default:
+ return 0; // not a binop.
+
+ // Lowest Precedence: &&, ||
+ case AsmToken::AmpAmp:
+ Kind = MCBinaryExpr::LAnd;
+ return 2;
+ case AsmToken::PipePipe:
+ Kind = MCBinaryExpr::LOr;
+ return 1;
+
+ // Low Precedence: ==, !=, <>, <, <=, >, >=
+ case AsmToken::EqualEqual:
+ Kind = MCBinaryExpr::EQ;
+ return 3;
+ case AsmToken::ExclaimEqual:
+ case AsmToken::LessGreater:
+ Kind = MCBinaryExpr::NE;
+ return 3;
+ case AsmToken::Less:
+ Kind = MCBinaryExpr::LT;
+ return 3;
+ case AsmToken::LessEqual:
+ Kind = MCBinaryExpr::LTE;
+ return 3;
+ case AsmToken::Greater:
+ Kind = MCBinaryExpr::GT;
+ return 3;
+ case AsmToken::GreaterEqual:
+ Kind = MCBinaryExpr::GTE;
+ return 3;
+
+ // Low Intermediate Precedence: +, -
+ case AsmToken::Plus:
+ Kind = MCBinaryExpr::Add;
+ return 4;
+ case AsmToken::Minus:
+ Kind = MCBinaryExpr::Sub;
+ return 4;
+
// High Intermediate Precedence: |, !, &, ^
- //
- case AsmToken::Pipe:
- Kind = MCBinaryExpr::Or;
- return 5;
+ //
+ case AsmToken::Pipe:
+ Kind = MCBinaryExpr::Or;
+ return 5;
case AsmToken::Exclaim:
// Hack to support ARM compatible aliases (implied 'sp' operand in 'srs*'
// instructions like 'srsda #31!') and not parse ! as an infix operator.
@@ -1625,1396 +1625,1396 @@ static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI,
return 0;
Kind = MCBinaryExpr::OrNot;
return 5;
- case AsmToken::Caret:
- Kind = MCBinaryExpr::Xor;
- return 5;
- case AsmToken::Amp:
- Kind = MCBinaryExpr::And;
- return 5;
-
- // Highest Precedence: *, /, %, <<, >>
- case AsmToken::Star:
- Kind = MCBinaryExpr::Mul;
- return 6;
- case AsmToken::Slash:
- Kind = MCBinaryExpr::Div;
- return 6;
- case AsmToken::Percent:
- Kind = MCBinaryExpr::Mod;
- return 6;
- case AsmToken::LessLess:
- Kind = MCBinaryExpr::Shl;
- return 6;
- case AsmToken::GreaterGreater:
- Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
- return 6;
- }
-}
-
-unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind) {
- bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
- return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)
+ case AsmToken::Caret:
+ Kind = MCBinaryExpr::Xor;
+ return 5;
+ case AsmToken::Amp:
+ Kind = MCBinaryExpr::And;
+ return 5;
+
+ // Highest Precedence: *, /, %, <<, >>
+ case AsmToken::Star:
+ Kind = MCBinaryExpr::Mul;
+ return 6;
+ case AsmToken::Slash:
+ Kind = MCBinaryExpr::Div;
+ return 6;
+ case AsmToken::Percent:
+ Kind = MCBinaryExpr::Mod;
+ return 6;
+ case AsmToken::LessLess:
+ Kind = MCBinaryExpr::Shl;
+ return 6;
+ case AsmToken::GreaterGreater:
+ Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
+ return 6;
+ }
+}
+
+unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
+ MCBinaryExpr::Opcode &Kind) {
+ bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
+ return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)
: getGNUBinOpPrecedence(MAI, K, Kind, ShouldUseLogicalShr);
-}
-
-/// Parse all binary operators with precedence >= 'Precedence'.
-/// Res contains the LHS of the expression on input.
-bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
- SMLoc &EndLoc) {
- SMLoc StartLoc = Lexer.getLoc();
- while (true) {
- MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
- unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
-
- // If the next token is lower precedence than we are allowed to eat, return
- // successfully with what we ate already.
- if (TokPrec < Precedence)
- return false;
-
- Lex();
-
- // Eat the next primary expression.
- const MCExpr *RHS;
- if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
- return true;
-
- // If BinOp binds less tightly with RHS than the operator after RHS, let
- // the pending operator take RHS as its LHS.
- MCBinaryExpr::Opcode Dummy;
- unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
- if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
- return true;
-
- // Merge LHS and RHS according to operator.
- Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
- }
-}
-
-/// ParseStatement:
-/// ::= EndOfStatement
-/// ::= Label* Directive ...Operands... EndOfStatement
-/// ::= 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();
- if (Lexer.is(AsmToken::EndOfStatement)) {
- // if this is a line comment we can drop it safely
- if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
- getTok().getString().front() == '\n')
- Out.AddBlankLine();
- Lex();
- return false;
- }
- // Statements always start with an identifier.
- AsmToken ID = getTok();
- SMLoc IDLoc = ID.getLoc();
- StringRef IDVal;
- int64_t LocalLabelVal = -1;
+}
+
+/// Parse all binary operators with precedence >= 'Precedence'.
+/// Res contains the LHS of the expression on input.
+bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
+ SMLoc &EndLoc) {
+ SMLoc StartLoc = Lexer.getLoc();
+ while (true) {
+ MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
+ unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
+
+ // If the next token is lower precedence than we are allowed to eat, return
+ // successfully with what we ate already.
+ if (TokPrec < Precedence)
+ return false;
+
+ Lex();
+
+ // Eat the next primary expression.
+ const MCExpr *RHS;
+ if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
+ return true;
+
+ // If BinOp binds less tightly with RHS than the operator after RHS, let
+ // the pending operator take RHS as its LHS.
+ MCBinaryExpr::Opcode Dummy;
+ unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
+ if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
+ return true;
+
+ // Merge LHS and RHS according to operator.
+ Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
+ }
+}
+
+/// ParseStatement:
+/// ::= EndOfStatement
+/// ::= Label* Directive ...Operands... EndOfStatement
+/// ::= 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();
+ if (Lexer.is(AsmToken::EndOfStatement)) {
+ // if this is a line comment we can drop it safely
+ if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
+ getTok().getString().front() == '\n')
+ Out.AddBlankLine();
+ Lex();
+ return false;
+ }
+ // Statements always start with an identifier.
+ AsmToken ID = getTok();
+ SMLoc IDLoc = ID.getLoc();
+ StringRef IDVal;
+ int64_t LocalLabelVal = -1;
StartTokLoc = ID.getLoc();
- if (Lexer.is(AsmToken::HashDirective))
- return parseCppHashLineFilenameComment(IDLoc,
- !isInsideMacroInstantiation());
-
- // Allow an integer followed by a ':' as a directional local label.
- if (Lexer.is(AsmToken::Integer)) {
- LocalLabelVal = getTok().getIntVal();
- if (LocalLabelVal < 0) {
- 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) {
- Lex(); // always eat a token
- return Error(IDLoc, "unexpected token at start of statement");
- }
- }
- }
- } else if (Lexer.is(AsmToken::Dot)) {
- // Treat '.' as a valid identifier in this context.
- Lex();
- IDVal = ".";
- } else if (Lexer.is(AsmToken::LCurly)) {
- // Treat '{' as a valid identifier in this context.
- Lex();
- IDVal = "{";
-
- } else if (Lexer.is(AsmToken::RCurly)) {
- // Treat '}' as a valid identifier in this context.
- Lex();
- IDVal = "}";
- } else if (Lexer.is(AsmToken::Star) &&
- getTargetParser().starIsStartOfStatement()) {
- // Accept '*' as a valid start of statement.
- Lex();
- IDVal = "*";
- } else if (parseIdentifier(IDVal)) {
- if (!TheCondState.Ignore) {
- Lex(); // always eat a token
- return Error(IDLoc, "unexpected token at start of statement");
- }
- IDVal = "";
- }
-
- // Handle conditional assembly here before checking for skipping. We
- // have to do this so that .endif isn't skipped in a ".if 0" block for
- // example.
- StringMap<DirectiveKind>::const_iterator DirKindIt =
- DirectiveKindMap.find(IDVal.lower());
- DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
-
- ? DK_NO_DIRECTIVE
- : DirKindIt->getValue();
- switch (DirKind) {
- default:
- break;
- case DK_IF:
- case DK_IFEQ:
- case DK_IFGE:
- case DK_IFGT:
- case DK_IFLE:
- case DK_IFLT:
- case DK_IFNE:
- return parseDirectiveIf(IDLoc, DirKind);
- case DK_IFB:
- return parseDirectiveIfb(IDLoc, true);
- case DK_IFNB:
- return parseDirectiveIfb(IDLoc, false);
- case DK_IFC:
- return parseDirectiveIfc(IDLoc, true);
- case DK_IFEQS:
- return parseDirectiveIfeqs(IDLoc, true);
- case DK_IFNC:
- return parseDirectiveIfc(IDLoc, false);
- case DK_IFNES:
- return parseDirectiveIfeqs(IDLoc, false);
- case DK_IFDEF:
- return parseDirectiveIfdef(IDLoc, true);
- case DK_IFNDEF:
- case DK_IFNOTDEF:
- return parseDirectiveIfdef(IDLoc, false);
- case DK_ELSEIF:
- return parseDirectiveElseIf(IDLoc);
- case DK_ELSE:
- return parseDirectiveElse(IDLoc);
- case DK_ENDIF:
- return parseDirectiveEndIf(IDLoc);
- }
-
- // Ignore the statement if in the middle of inactive conditional
- // (e.g. ".if 0").
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- return false;
- }
-
- // FIXME: Recurse on local labels?
-
- // See what kind of statement we have.
- switch (Lexer.getKind()) {
- case AsmToken::Colon: {
- if (!getTargetParser().isLabel(ID))
- break;
- if (checkForValidSection())
- return true;
-
- // identifier ':' -> Label.
- Lex();
-
- // Diagnose attempt to use '.' as a label.
- if (IDVal == ".")
- return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
-
- // Diagnose attempt to use a variable as a label.
- //
- // FIXME: Diagnostics. Note the location of the definition as a label.
- // FIXME: This doesn't diagnose assignment to a symbol which has been
- // implicitly marked as external.
- MCSymbol *Sym;
- if (LocalLabelVal == -1) {
- if (ParsingMSInlineAsm && SI) {
- StringRef RewrittenLabel =
- SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
- assert(!RewrittenLabel.empty() &&
- "We should have an internal name here.");
- Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
- RewrittenLabel);
- IDVal = RewrittenLabel;
- }
- Sym = getContext().getOrCreateSymbol(IDVal);
- } else
- Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
- // 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)) {
- Lex();
- }
-
- getTargetParser().doBeforeLabelEmit(Sym);
-
- // Emit the label.
- if (!getTargetParser().isParsingMSInlineAsm())
- Out.emitLabel(Sym, IDLoc);
-
- // If we are generating dwarf for assembly source files then gather the
- // info to make a dwarf label entry for this label if needed.
- if (enabledGenDwarfForAssembly())
- MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
- IDLoc);
-
- getTargetParser().onLabelParsed(Sym);
-
- return false;
- }
-
- case AsmToken::Equal:
- if (!getTargetParser().equalIsAsmAssignment())
- break;
- // identifier '=' ... -> assignment statement
- Lex();
-
- return parseAssignment(IDVal, true);
-
- default: // Normal instruction or directive.
- break;
- }
-
- // If macros are enabled, check to see if this is a macro instantiation.
- if (areMacrosEnabled())
- if (const MCAsmMacro *M = getContext().lookupMacro(IDVal)) {
- return handleMacroEntry(M, IDLoc);
- }
-
- // Otherwise, we have a normal instruction or directive.
-
- // Directives start with "."
- if (IDVal.startswith(".") && IDVal != ".") {
- // There are several entities interested in parsing directives:
- //
- // 1. The target-specific assembly parser. Some directives are target
- // specific or may potentially behave differently on certain targets.
- // 2. Asm parser extensions. For example, platform-specific parsers
- // (like the ELF parser) register themselves as extensions.
- // 3. The generic directive parser implemented by this class. These are
- // all the directives that behave in a target and platform independent
- // manner, or at least have a default behavior that's shared between
- // all targets and platforms.
-
- 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
- // registered itself to parse this directive.
- std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
- ExtensionDirectiveMap.lookup(IDVal);
- if (Handler.first)
- return (*Handler.second)(Handler.first, IDVal, IDLoc);
-
- // Finally, if no one else is interested in this directive, it must be
- // generic and familiar to this class.
- switch (DirKind) {
- default:
- break;
- case DK_SET:
- case DK_EQU:
- return parseDirectiveSet(IDVal, true);
- case DK_EQUIV:
- return parseDirectiveSet(IDVal, false);
- case DK_ASCII:
- return parseDirectiveAscii(IDVal, false);
- case DK_ASCIZ:
- case DK_STRING:
- return parseDirectiveAscii(IDVal, true);
- case DK_BYTE:
- 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(IDVal, 2);
- case DK_LONG:
- case DK_INT:
- case DK_4BYTE:
- case DK_DC_L:
- return parseDirectiveValue(IDVal, 4);
- case DK_QUAD:
- case DK_8BYTE:
- return parseDirectiveValue(IDVal, 8);
- case DK_DC_A:
- return parseDirectiveValue(
- IDVal, getContext().getAsmInfo()->getCodePointerSize());
- case DK_OCTA:
- return parseDirectiveOctaValue(IDVal);
- case DK_SINGLE:
- case DK_FLOAT:
- case DK_DC_S:
- return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());
- case DK_DOUBLE:
- case DK_DC_D:
- return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());
- case DK_ALIGN: {
- bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
- return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);
- }
- case DK_ALIGN32: {
- bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
- return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);
- }
- case DK_BALIGN:
- return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
- case DK_BALIGNW:
- return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
- case DK_BALIGNL:
- return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
- case DK_P2ALIGN:
- return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
- case DK_P2ALIGNW:
- return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
- case DK_P2ALIGNL:
- return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
- case DK_ORG:
- return parseDirectiveOrg();
- case DK_FILL:
- return parseDirectiveFill();
- case DK_ZERO:
- return parseDirectiveZero();
- case DK_EXTERN:
- eatToEndOfStatement(); // .extern is the default, ignore it.
- return false;
- case DK_GLOBL:
- case DK_GLOBAL:
- return parseDirectiveSymbolAttribute(MCSA_Global);
- case DK_LAZY_REFERENCE:
- return parseDirectiveSymbolAttribute(MCSA_LazyReference);
- case DK_NO_DEAD_STRIP:
- return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
- case DK_SYMBOL_RESOLVER:
- return parseDirectiveSymbolAttribute(MCSA_SymbolResolver);
- case DK_PRIVATE_EXTERN:
- return parseDirectiveSymbolAttribute(MCSA_PrivateExtern);
- case DK_REFERENCE:
- return parseDirectiveSymbolAttribute(MCSA_Reference);
- case DK_WEAK_DEFINITION:
- return parseDirectiveSymbolAttribute(MCSA_WeakDefinition);
- case DK_WEAK_REFERENCE:
- return parseDirectiveSymbolAttribute(MCSA_WeakReference);
- case DK_WEAK_DEF_CAN_BE_HIDDEN:
- return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
- case DK_COLD:
- return parseDirectiveSymbolAttribute(MCSA_Cold);
- case DK_COMM:
- case DK_COMMON:
- return parseDirectiveComm(/*IsLocal=*/false);
- case DK_LCOMM:
- return parseDirectiveComm(/*IsLocal=*/true);
- case DK_ABORT:
- return parseDirectiveAbort();
- case DK_INCLUDE:
- return parseDirectiveInclude();
- case DK_INCBIN:
- return parseDirectiveIncbin();
- case DK_CODE16:
- case DK_CODE16GCC:
- return TokError(Twine(IDVal) +
- " not currently supported for this target");
- case DK_REPT:
- return parseDirectiveRept(IDLoc, IDVal);
- case DK_IRP:
- return parseDirectiveIrp(IDLoc);
- case DK_IRPC:
- return parseDirectiveIrpc(IDLoc);
- case DK_ENDR:
- return parseDirectiveEndr(IDLoc);
- case DK_BUNDLE_ALIGN_MODE:
- return parseDirectiveBundleAlignMode();
- case DK_BUNDLE_LOCK:
- return parseDirectiveBundleLock();
- case DK_BUNDLE_UNLOCK:
- return parseDirectiveBundleUnlock();
- case DK_SLEB128:
- return parseDirectiveLEB128(true);
- case DK_ULEB128:
- return parseDirectiveLEB128(false);
- case DK_SPACE:
- case DK_SKIP:
- return parseDirectiveSpace(IDVal);
- case DK_FILE:
- return parseDirectiveFile(IDLoc);
- case DK_LINE:
- return parseDirectiveLine();
- case DK_LOC:
- return parseDirectiveLoc();
- case DK_STABS:
- 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:
- return parseDirectiveCVLinetable();
- case DK_CV_INLINE_LINETABLE:
- return parseDirectiveCVInlineLinetable();
- case DK_CV_DEF_RANGE:
- return parseDirectiveCVDefRange();
- case DK_CV_STRING:
- return parseDirectiveCVString();
- case DK_CV_STRINGTABLE:
- return parseDirectiveCVStringTable();
- case DK_CV_FILECHECKSUMS:
- return parseDirectiveCVFileChecksums();
- case DK_CV_FILECHECKSUM_OFFSET:
- return parseDirectiveCVFileChecksumOffset();
- case DK_CV_FPO_DATA:
- return parseDirectiveCVFPOData();
- case DK_CFI_SECTIONS:
- return parseDirectiveCFISections();
- case DK_CFI_STARTPROC:
- return parseDirectiveCFIStartProc();
- case DK_CFI_ENDPROC:
- return parseDirectiveCFIEndProc();
- case DK_CFI_DEF_CFA:
- return parseDirectiveCFIDefCfa(IDLoc);
- case DK_CFI_DEF_CFA_OFFSET:
- return parseDirectiveCFIDefCfaOffset();
- case DK_CFI_ADJUST_CFA_OFFSET:
- return parseDirectiveCFIAdjustCfaOffset();
- case DK_CFI_DEF_CFA_REGISTER:
- return parseDirectiveCFIDefCfaRegister(IDLoc);
- case DK_CFI_OFFSET:
- return parseDirectiveCFIOffset(IDLoc);
- case DK_CFI_REL_OFFSET:
- return parseDirectiveCFIRelOffset(IDLoc);
- case DK_CFI_PERSONALITY:
- return parseDirectiveCFIPersonalityOrLsda(true);
- case DK_CFI_LSDA:
- return parseDirectiveCFIPersonalityOrLsda(false);
- case DK_CFI_REMEMBER_STATE:
- return parseDirectiveCFIRememberState();
- case DK_CFI_RESTORE_STATE:
- return parseDirectiveCFIRestoreState();
- case DK_CFI_SAME_VALUE:
- return parseDirectiveCFISameValue(IDLoc);
- case DK_CFI_RESTORE:
- return parseDirectiveCFIRestore(IDLoc);
- case DK_CFI_ESCAPE:
- return parseDirectiveCFIEscape();
- case DK_CFI_RETURN_COLUMN:
- return parseDirectiveCFIReturnColumn(IDLoc);
- case DK_CFI_SIGNAL_FRAME:
- return parseDirectiveCFISignalFrame();
- case DK_CFI_UNDEFINED:
- return parseDirectiveCFIUndefined(IDLoc);
- case DK_CFI_REGISTER:
- return parseDirectiveCFIRegister(IDLoc);
- case DK_CFI_WINDOW_SAVE:
- return parseDirectiveCFIWindowSave();
- case DK_MACROS_ON:
- case DK_MACROS_OFF:
- return parseDirectiveMacrosOnOff(IDVal);
- case DK_MACRO:
- return parseDirectiveMacro(IDLoc);
- case DK_ALTMACRO:
- case DK_NOALTMACRO:
- return parseDirectiveAltmacro(IDVal);
- case DK_EXITM:
- return parseDirectiveExitMacro(IDVal);
- case DK_ENDM:
- case DK_ENDMACRO:
- return parseDirectiveEndMacro(IDVal);
- case DK_PURGEM:
- return parseDirectivePurgeMacro(IDLoc);
- case DK_END:
- return parseDirectiveEnd(IDLoc);
- case DK_ERR:
- return parseDirectiveError(IDLoc, false);
- case DK_ERROR:
- return parseDirectiveError(IDLoc, true);
- case DK_WARNING:
- 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);
- case DK_PRINT:
- return parseDirectivePrint(IDLoc);
- case DK_ADDRSIG:
- return parseDirectiveAddrsig();
- case DK_ADDRSIG_SYM:
- return parseDirectiveAddrsigSym();
+ if (Lexer.is(AsmToken::HashDirective))
+ return parseCppHashLineFilenameComment(IDLoc,
+ !isInsideMacroInstantiation());
+
+ // Allow an integer followed by a ':' as a directional local label.
+ if (Lexer.is(AsmToken::Integer)) {
+ LocalLabelVal = getTok().getIntVal();
+ if (LocalLabelVal < 0) {
+ 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) {
+ Lex(); // always eat a token
+ return Error(IDLoc, "unexpected token at start of statement");
+ }
+ }
+ }
+ } else if (Lexer.is(AsmToken::Dot)) {
+ // Treat '.' as a valid identifier in this context.
+ Lex();
+ IDVal = ".";
+ } else if (Lexer.is(AsmToken::LCurly)) {
+ // Treat '{' as a valid identifier in this context.
+ Lex();
+ IDVal = "{";
+
+ } else if (Lexer.is(AsmToken::RCurly)) {
+ // Treat '}' as a valid identifier in this context.
+ Lex();
+ IDVal = "}";
+ } else if (Lexer.is(AsmToken::Star) &&
+ getTargetParser().starIsStartOfStatement()) {
+ // Accept '*' as a valid start of statement.
+ Lex();
+ IDVal = "*";
+ } else if (parseIdentifier(IDVal)) {
+ if (!TheCondState.Ignore) {
+ Lex(); // always eat a token
+ return Error(IDLoc, "unexpected token at start of statement");
+ }
+ IDVal = "";
+ }
+
+ // Handle conditional assembly here before checking for skipping. We
+ // have to do this so that .endif isn't skipped in a ".if 0" block for
+ // example.
+ StringMap<DirectiveKind>::const_iterator DirKindIt =
+ DirectiveKindMap.find(IDVal.lower());
+ DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
+
+ ? DK_NO_DIRECTIVE
+ : DirKindIt->getValue();
+ switch (DirKind) {
+ default:
+ break;
+ case DK_IF:
+ case DK_IFEQ:
+ case DK_IFGE:
+ case DK_IFGT:
+ case DK_IFLE:
+ case DK_IFLT:
+ case DK_IFNE:
+ return parseDirectiveIf(IDLoc, DirKind);
+ case DK_IFB:
+ return parseDirectiveIfb(IDLoc, true);
+ case DK_IFNB:
+ return parseDirectiveIfb(IDLoc, false);
+ case DK_IFC:
+ return parseDirectiveIfc(IDLoc, true);
+ case DK_IFEQS:
+ return parseDirectiveIfeqs(IDLoc, true);
+ case DK_IFNC:
+ return parseDirectiveIfc(IDLoc, false);
+ case DK_IFNES:
+ return parseDirectiveIfeqs(IDLoc, false);
+ case DK_IFDEF:
+ return parseDirectiveIfdef(IDLoc, true);
+ case DK_IFNDEF:
+ case DK_IFNOTDEF:
+ return parseDirectiveIfdef(IDLoc, false);
+ case DK_ELSEIF:
+ return parseDirectiveElseIf(IDLoc);
+ case DK_ELSE:
+ return parseDirectiveElse(IDLoc);
+ case DK_ENDIF:
+ return parseDirectiveEndIf(IDLoc);
+ }
+
+ // Ignore the statement if in the middle of inactive conditional
+ // (e.g. ".if 0").
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+
+ // FIXME: Recurse on local labels?
+
+ // See what kind of statement we have.
+ switch (Lexer.getKind()) {
+ case AsmToken::Colon: {
+ if (!getTargetParser().isLabel(ID))
+ break;
+ if (checkForValidSection())
+ return true;
+
+ // identifier ':' -> Label.
+ Lex();
+
+ // Diagnose attempt to use '.' as a label.
+ if (IDVal == ".")
+ return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
+
+ // Diagnose attempt to use a variable as a label.
+ //
+ // FIXME: Diagnostics. Note the location of the definition as a label.
+ // FIXME: This doesn't diagnose assignment to a symbol which has been
+ // implicitly marked as external.
+ MCSymbol *Sym;
+ if (LocalLabelVal == -1) {
+ if (ParsingMSInlineAsm && SI) {
+ StringRef RewrittenLabel =
+ SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
+ assert(!RewrittenLabel.empty() &&
+ "We should have an internal name here.");
+ Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
+ RewrittenLabel);
+ IDVal = RewrittenLabel;
+ }
+ Sym = getContext().getOrCreateSymbol(IDVal);
+ } else
+ Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
+ // 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)) {
+ Lex();
+ }
+
+ getTargetParser().doBeforeLabelEmit(Sym);
+
+ // Emit the label.
+ if (!getTargetParser().isParsingMSInlineAsm())
+ Out.emitLabel(Sym, IDLoc);
+
+ // If we are generating dwarf for assembly source files then gather the
+ // info to make a dwarf label entry for this label if needed.
+ if (enabledGenDwarfForAssembly())
+ MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
+ IDLoc);
+
+ getTargetParser().onLabelParsed(Sym);
+
+ return false;
+ }
+
+ case AsmToken::Equal:
+ if (!getTargetParser().equalIsAsmAssignment())
+ break;
+ // identifier '=' ... -> assignment statement
+ Lex();
+
+ return parseAssignment(IDVal, true);
+
+ default: // Normal instruction or directive.
+ break;
+ }
+
+ // If macros are enabled, check to see if this is a macro instantiation.
+ if (areMacrosEnabled())
+ if (const MCAsmMacro *M = getContext().lookupMacro(IDVal)) {
+ return handleMacroEntry(M, IDLoc);
+ }
+
+ // Otherwise, we have a normal instruction or directive.
+
+ // Directives start with "."
+ if (IDVal.startswith(".") && IDVal != ".") {
+ // There are several entities interested in parsing directives:
+ //
+ // 1. The target-specific assembly parser. Some directives are target
+ // specific or may potentially behave differently on certain targets.
+ // 2. Asm parser extensions. For example, platform-specific parsers
+ // (like the ELF parser) register themselves as extensions.
+ // 3. The generic directive parser implemented by this class. These are
+ // all the directives that behave in a target and platform independent
+ // manner, or at least have a default behavior that's shared between
+ // all targets and platforms.
+
+ 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
+ // registered itself to parse this directive.
+ std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
+ ExtensionDirectiveMap.lookup(IDVal);
+ if (Handler.first)
+ return (*Handler.second)(Handler.first, IDVal, IDLoc);
+
+ // Finally, if no one else is interested in this directive, it must be
+ // generic and familiar to this class.
+ switch (DirKind) {
+ default:
+ break;
+ case DK_SET:
+ case DK_EQU:
+ return parseDirectiveSet(IDVal, true);
+ case DK_EQUIV:
+ return parseDirectiveSet(IDVal, false);
+ case DK_ASCII:
+ return parseDirectiveAscii(IDVal, false);
+ case DK_ASCIZ:
+ case DK_STRING:
+ return parseDirectiveAscii(IDVal, true);
+ case DK_BYTE:
+ 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(IDVal, 2);
+ case DK_LONG:
+ case DK_INT:
+ case DK_4BYTE:
+ case DK_DC_L:
+ return parseDirectiveValue(IDVal, 4);
+ case DK_QUAD:
+ case DK_8BYTE:
+ return parseDirectiveValue(IDVal, 8);
+ case DK_DC_A:
+ return parseDirectiveValue(
+ IDVal, getContext().getAsmInfo()->getCodePointerSize());
+ case DK_OCTA:
+ return parseDirectiveOctaValue(IDVal);
+ case DK_SINGLE:
+ case DK_FLOAT:
+ case DK_DC_S:
+ return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());
+ case DK_DOUBLE:
+ case DK_DC_D:
+ return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());
+ case DK_ALIGN: {
+ bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
+ return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);
+ }
+ case DK_ALIGN32: {
+ bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
+ return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);
+ }
+ case DK_BALIGN:
+ return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
+ case DK_BALIGNW:
+ return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
+ case DK_BALIGNL:
+ return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
+ case DK_P2ALIGN:
+ return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
+ case DK_P2ALIGNW:
+ return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
+ case DK_P2ALIGNL:
+ return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
+ case DK_ORG:
+ return parseDirectiveOrg();
+ case DK_FILL:
+ return parseDirectiveFill();
+ case DK_ZERO:
+ return parseDirectiveZero();
+ case DK_EXTERN:
+ eatToEndOfStatement(); // .extern is the default, ignore it.
+ return false;
+ case DK_GLOBL:
+ case DK_GLOBAL:
+ return parseDirectiveSymbolAttribute(MCSA_Global);
+ case DK_LAZY_REFERENCE:
+ return parseDirectiveSymbolAttribute(MCSA_LazyReference);
+ case DK_NO_DEAD_STRIP:
+ return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
+ case DK_SYMBOL_RESOLVER:
+ return parseDirectiveSymbolAttribute(MCSA_SymbolResolver);
+ case DK_PRIVATE_EXTERN:
+ return parseDirectiveSymbolAttribute(MCSA_PrivateExtern);
+ case DK_REFERENCE:
+ return parseDirectiveSymbolAttribute(MCSA_Reference);
+ case DK_WEAK_DEFINITION:
+ return parseDirectiveSymbolAttribute(MCSA_WeakDefinition);
+ case DK_WEAK_REFERENCE:
+ return parseDirectiveSymbolAttribute(MCSA_WeakReference);
+ case DK_WEAK_DEF_CAN_BE_HIDDEN:
+ return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
+ case DK_COLD:
+ return parseDirectiveSymbolAttribute(MCSA_Cold);
+ case DK_COMM:
+ case DK_COMMON:
+ return parseDirectiveComm(/*IsLocal=*/false);
+ case DK_LCOMM:
+ return parseDirectiveComm(/*IsLocal=*/true);
+ case DK_ABORT:
+ return parseDirectiveAbort();
+ case DK_INCLUDE:
+ return parseDirectiveInclude();
+ case DK_INCBIN:
+ return parseDirectiveIncbin();
+ case DK_CODE16:
+ case DK_CODE16GCC:
+ return TokError(Twine(IDVal) +
+ " not currently supported for this target");
+ case DK_REPT:
+ return parseDirectiveRept(IDLoc, IDVal);
+ case DK_IRP:
+ return parseDirectiveIrp(IDLoc);
+ case DK_IRPC:
+ return parseDirectiveIrpc(IDLoc);
+ case DK_ENDR:
+ return parseDirectiveEndr(IDLoc);
+ case DK_BUNDLE_ALIGN_MODE:
+ return parseDirectiveBundleAlignMode();
+ case DK_BUNDLE_LOCK:
+ return parseDirectiveBundleLock();
+ case DK_BUNDLE_UNLOCK:
+ return parseDirectiveBundleUnlock();
+ case DK_SLEB128:
+ return parseDirectiveLEB128(true);
+ case DK_ULEB128:
+ return parseDirectiveLEB128(false);
+ case DK_SPACE:
+ case DK_SKIP:
+ return parseDirectiveSpace(IDVal);
+ case DK_FILE:
+ return parseDirectiveFile(IDLoc);
+ case DK_LINE:
+ return parseDirectiveLine();
+ case DK_LOC:
+ return parseDirectiveLoc();
+ case DK_STABS:
+ 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:
+ return parseDirectiveCVLinetable();
+ case DK_CV_INLINE_LINETABLE:
+ return parseDirectiveCVInlineLinetable();
+ case DK_CV_DEF_RANGE:
+ return parseDirectiveCVDefRange();
+ case DK_CV_STRING:
+ return parseDirectiveCVString();
+ case DK_CV_STRINGTABLE:
+ return parseDirectiveCVStringTable();
+ case DK_CV_FILECHECKSUMS:
+ return parseDirectiveCVFileChecksums();
+ case DK_CV_FILECHECKSUM_OFFSET:
+ return parseDirectiveCVFileChecksumOffset();
+ case DK_CV_FPO_DATA:
+ return parseDirectiveCVFPOData();
+ case DK_CFI_SECTIONS:
+ return parseDirectiveCFISections();
+ case DK_CFI_STARTPROC:
+ return parseDirectiveCFIStartProc();
+ case DK_CFI_ENDPROC:
+ return parseDirectiveCFIEndProc();
+ case DK_CFI_DEF_CFA:
+ return parseDirectiveCFIDefCfa(IDLoc);
+ case DK_CFI_DEF_CFA_OFFSET:
+ return parseDirectiveCFIDefCfaOffset();
+ case DK_CFI_ADJUST_CFA_OFFSET:
+ return parseDirectiveCFIAdjustCfaOffset();
+ case DK_CFI_DEF_CFA_REGISTER:
+ return parseDirectiveCFIDefCfaRegister(IDLoc);
+ case DK_CFI_OFFSET:
+ return parseDirectiveCFIOffset(IDLoc);
+ case DK_CFI_REL_OFFSET:
+ return parseDirectiveCFIRelOffset(IDLoc);
+ case DK_CFI_PERSONALITY:
+ return parseDirectiveCFIPersonalityOrLsda(true);
+ case DK_CFI_LSDA:
+ return parseDirectiveCFIPersonalityOrLsda(false);
+ case DK_CFI_REMEMBER_STATE:
+ return parseDirectiveCFIRememberState();
+ case DK_CFI_RESTORE_STATE:
+ return parseDirectiveCFIRestoreState();
+ case DK_CFI_SAME_VALUE:
+ return parseDirectiveCFISameValue(IDLoc);
+ case DK_CFI_RESTORE:
+ return parseDirectiveCFIRestore(IDLoc);
+ case DK_CFI_ESCAPE:
+ return parseDirectiveCFIEscape();
+ case DK_CFI_RETURN_COLUMN:
+ return parseDirectiveCFIReturnColumn(IDLoc);
+ case DK_CFI_SIGNAL_FRAME:
+ return parseDirectiveCFISignalFrame();
+ case DK_CFI_UNDEFINED:
+ return parseDirectiveCFIUndefined(IDLoc);
+ case DK_CFI_REGISTER:
+ return parseDirectiveCFIRegister(IDLoc);
+ case DK_CFI_WINDOW_SAVE:
+ return parseDirectiveCFIWindowSave();
+ case DK_MACROS_ON:
+ case DK_MACROS_OFF:
+ return parseDirectiveMacrosOnOff(IDVal);
+ case DK_MACRO:
+ return parseDirectiveMacro(IDLoc);
+ case DK_ALTMACRO:
+ case DK_NOALTMACRO:
+ return parseDirectiveAltmacro(IDVal);
+ case DK_EXITM:
+ return parseDirectiveExitMacro(IDVal);
+ case DK_ENDM:
+ case DK_ENDMACRO:
+ return parseDirectiveEndMacro(IDVal);
+ case DK_PURGEM:
+ return parseDirectivePurgeMacro(IDLoc);
+ case DK_END:
+ return parseDirectiveEnd(IDLoc);
+ case DK_ERR:
+ return parseDirectiveError(IDLoc, false);
+ case DK_ERROR:
+ return parseDirectiveError(IDLoc, true);
+ case DK_WARNING:
+ 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);
+ case DK_PRINT:
+ return parseDirectivePrint(IDLoc);
+ case DK_ADDRSIG:
+ return parseDirectiveAddrsig();
+ case DK_ADDRSIG_SYM:
+ return parseDirectiveAddrsigSym();
case DK_PSEUDO_PROBE:
return parseDirectivePseudoProbe();
- }
-
- return Error(IDLoc, "unknown directive");
- }
-
- // __asm _emit or __asm __emit
- if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
- IDVal == "_EMIT" || IDVal == "__EMIT"))
- return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
-
- // __asm align
- if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
- return parseDirectiveMSAlign(IDLoc, Info);
-
- if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
- Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
- if (checkForValidSection())
- return true;
-
- // Canonicalize the opcode to lower case.
- std::string OpcodeStr = IDVal.lower();
- ParseInstructionInfo IInfo(Info.AsmRewrites);
- bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
- Info.ParsedOperands);
- Info.ParseError = ParseHadError;
-
- // Dump the parsed representation, if requested.
- if (getShowParsedOperands()) {
- SmallString<256> Str;
- raw_svector_ostream OS(Str);
- OS << "parsed instruction: [";
- for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
- if (i != 0)
- OS << ", ";
- Info.ParsedOperands[i]->print(OS);
- }
- OS << "]";
-
- 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 (!ParseHadError && enabledGenDwarfForAssembly() &&
- getContext().getGenDwarfSectionSyms().count(
- getStreamer().getCurrentSectionOnly())) {
- unsigned Line;
- if (ActiveMacros.empty())
- Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
- else
- Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
- ActiveMacros.front()->ExitBuffer);
-
- // If we previously parsed a cpp hash file line comment then make sure the
- // current Dwarf File is for the CppHashFilename if not then emit the
- // Dwarf File table for it and adjust the line number for the .loc.
- if (!CppHashInfo.Filename.empty()) {
- unsigned FileNumber = getStreamer().emitDwarfFileDirective(
- 0, StringRef(), CppHashInfo.Filename);
- getContext().setGenDwarfFileNumber(FileNumber);
-
- unsigned CppHashLocLineNo =
- SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
- Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
- }
-
- getStreamer().emitDwarfLocDirective(
- getContext().getGenDwarfFileNumber(), Line, 0,
- DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
- StringRef());
- }
-
- // If parsing succeeded, match the instruction.
- if (!ParseHadError) {
- uint64_t ErrorInfo;
- if (getTargetParser().MatchAndEmitInstruction(
- IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
- getTargetParser().isParsingMSInlineAsm()))
- return true;
- }
- return false;
-}
-
-// Parse and erase curly braces marking block start/end
-bool
-AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
- // Identify curly brace marking block start/end
- if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
- return false;
-
- SMLoc StartLoc = Lexer.getLoc();
- Lex(); // Eat the brace
- if (Lexer.is(AsmToken::EndOfStatement))
- Lex(); // Eat EndOfStatement following the brace
-
- // Erase the block start/end brace from the output asm string
- AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
- StartLoc.getPointer());
- return true;
-}
-
-/// parseCppHashLineFilenameComment as this:
-/// ::= # number "filename"
-bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) {
- Lex(); // Eat the hash token.
- // Lexer only ever emits HashDirective if it fully formed if it's
- // done the checking already so this is an internal error.
- assert(getTok().is(AsmToken::Integer) &&
- "Lexing Cpp line comment: Expected Integer");
- int64_t LineNumber = getTok().getIntVal();
- Lex();
- assert(getTok().is(AsmToken::String) &&
- "Lexing Cpp line comment: Expected String");
- StringRef Filename = getTok().getString();
- Lex();
-
- if (!SaveLocInfo)
- return false;
-
- // Get rid of the enclosing quotes.
- Filename = Filename.substr(1, Filename.size() - 2);
-
- // Save the SMLoc, Filename and LineNumber for later use by diagnostics
- // and possibly DWARF file info.
- CppHashInfo.Loc = L;
- CppHashInfo.Filename = Filename;
- CppHashInfo.LineNumber = LineNumber;
- CppHashInfo.Buf = CurBuffer;
- if (FirstCppHashFilename.empty())
- FirstCppHashFilename = Filename;
- return false;
-}
-
-/// will use the last parsed cpp hash line filename comment
-/// for the Filename and LineNo if any in the diagnostic.
-void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
- const AsmParser *Parser = static_cast<const AsmParser *>(Context);
- raw_ostream &OS = errs();
-
- const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
- SMLoc DiagLoc = Diag.getLoc();
- unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
- unsigned CppHashBuf =
- Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
-
- // Like SourceMgr::printMessage() we need to print the include stack if any
- // before printing the message.
- unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
- if (!Parser->SavedDiagHandler && DiagCurBuffer &&
- DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
- SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
- DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
- }
-
- // If we have not parsed a cpp hash line filename comment or the source
- // manager changed or buffer changed (like in a nested include) then just
- // print the normal diagnostic using its Filename and LineNo.
- if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
- DiagBuf != CppHashBuf) {
- if (Parser->SavedDiagHandler)
- Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
- else
- Diag.print(nullptr, OS);
- return;
- }
-
- // Use the CppHashFilename and calculate a line number based on the
- // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
- // for the diagnostic.
- const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
-
- int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
- int CppHashLocLineNo =
- Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
- int LineNo =
- Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
-
- SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
- Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
- Diag.getLineContents(), Diag.getRanges());
-
- if (Parser->SavedDiagHandler)
- Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
- else
- NewDiag.print(nullptr, OS);
-}
-
-// FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The
-// difference being that that function accepts '@' as part of identifiers and
-// we can't do that. AsmLexer.cpp should probably be changed to handle
-// '@' as a special case when needed.
-static bool isIdentifierChar(char c) {
- return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||
- c == '.';
-}
-
-bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
- ArrayRef<MCAsmMacroParameter> Parameters,
- ArrayRef<MCAsmMacroArgument> A,
- bool EnableAtPseudoVariable, SMLoc L) {
- unsigned NParameters = Parameters.size();
- bool HasVararg = NParameters ? Parameters.back().Vararg : false;
- if ((!IsDarwin || NParameters != 0) && NParameters != A.size())
- return Error(L, "Wrong number of arguments");
-
- // A macro without parameters is handled differently on Darwin:
- // gas accepts no arguments and does no substitutions
- while (!Body.empty()) {
- // Scan for the next substitution.
- std::size_t End = Body.size(), Pos = 0;
- for (; Pos != End; ++Pos) {
- // Check for a substitution or escape.
- if (IsDarwin && !NParameters) {
- // This macro has no parameters, look for $0, $1, etc.
- if (Body[Pos] != '$' || Pos + 1 == End)
- continue;
-
- char Next = Body[Pos + 1];
- if (Next == '$' || Next == 'n' ||
- isdigit(static_cast<unsigned char>(Next)))
- break;
- } else {
- // This macro has parameters, look for \foo, \bar, etc.
- if (Body[Pos] == '\\' && Pos + 1 != End)
- break;
- }
- }
-
- // Add the prefix.
- OS << Body.slice(0, Pos);
-
- // Check if we reached the end.
- if (Pos == End)
- break;
-
- if (IsDarwin && !NParameters) {
- switch (Body[Pos + 1]) {
- // $$ => $
- case '$':
- OS << '$';
- break;
-
- // $n => number of arguments
- case 'n':
- OS << A.size();
- break;
-
- // $[0-9] => argument
- default: {
- // Missing arguments are ignored.
- unsigned Index = Body[Pos + 1] - '0';
- if (Index >= A.size())
- break;
-
- // Otherwise substitute with the token values, with spaces eliminated.
- for (const AsmToken &Token : A[Index])
- OS << Token.getString();
- break;
- }
- }
- Pos += 2;
- } else {
- unsigned I = Pos + 1;
-
- // Check for the \@ pseudo-variable.
- if (EnableAtPseudoVariable && Body[I] == '@' && I + 1 != End)
- ++I;
- else
- while (isIdentifierChar(Body[I]) && I + 1 != End)
- ++I;
-
- const char *Begin = Body.data() + Pos + 1;
- StringRef Argument(Begin, I - (Pos + 1));
- unsigned Index = 0;
-
- if (Argument == "@") {
- OS << NumOfMacroInstantiations;
- Pos += 2;
- } else {
- for (; Index < NParameters; ++Index)
- if (Parameters[Index].Name == Argument)
- break;
-
- if (Index == NParameters) {
- if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
- Pos += 3;
- else {
- OS << '\\' << Argument;
- Pos = I;
- }
- } else {
- bool VarargParameter = HasVararg && Index == (NParameters - 1);
- for (const AsmToken &Token : A[Index])
- // For altmacro mode, you can write '%expr'.
- // The prefix '%' evaluates the expression 'expr'
- // and uses the result as a string (e.g. replace %(1+2) with the
- // string "3").
- // Here, we identify the integer token which is the result of the
- // absolute expression evaluation and replace it with its string
- // representation.
- if (AltMacroMode && Token.getString().front() == '%' &&
- Token.is(AsmToken::Integer))
- // Emit an integer value to the buffer.
- OS << Token.getIntVal();
- // Only Token that was validated as a string and begins with '<'
- // is considered altMacroString!!!
- else if (AltMacroMode && Token.getString().front() == '<' &&
- Token.is(AsmToken::String)) {
- OS << angleBracketString(Token.getStringContents());
- }
- // We expect no quotes around the string's contents when
- // parsing for varargs.
- else if (Token.isNot(AsmToken::String) || VarargParameter)
- OS << Token.getString();
- else
- OS << Token.getStringContents();
-
- Pos += 1 + Argument.size();
- }
- }
- }
- // Update the scan point.
- Body = Body.substr(Pos);
- }
-
- return false;
-}
-
-static bool isOperator(AsmToken::TokenKind kind) {
- switch (kind) {
- default:
- return false;
- case AsmToken::Plus:
- case AsmToken::Minus:
- case AsmToken::Tilde:
- case AsmToken::Slash:
- case AsmToken::Star:
- case AsmToken::Dot:
- case AsmToken::Equal:
- case AsmToken::EqualEqual:
- case AsmToken::Pipe:
- case AsmToken::PipePipe:
- case AsmToken::Caret:
- case AsmToken::Amp:
- case AsmToken::AmpAmp:
- case AsmToken::Exclaim:
- case AsmToken::ExclaimEqual:
- case AsmToken::Less:
- case AsmToken::LessEqual:
- case AsmToken::LessLess:
- case AsmToken::LessGreater:
- case AsmToken::Greater:
- case AsmToken::GreaterEqual:
- case AsmToken::GreaterGreater:
- return true;
- }
-}
-
-namespace {
-
-class AsmLexerSkipSpaceRAII {
-public:
- AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
- Lexer.setSkipSpace(SkipSpace);
- }
-
- ~AsmLexerSkipSpaceRAII() {
- Lexer.setSkipSpace(true);
- }
-
-private:
- AsmLexer &Lexer;
-};
-
-} // end anonymous namespace
-
-bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
-
- if (Vararg) {
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- StringRef Str = parseStringToEndOfStatement();
- MA.emplace_back(AsmToken::String, Str);
- }
- return false;
- }
-
- unsigned ParenLevel = 0;
-
- // Darwin doesn't use spaces to delmit arguments.
- AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
-
- bool SpaceEaten;
-
- while (true) {
- SpaceEaten = false;
- if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
- return TokError("unexpected token in macro instantiation");
-
- if (ParenLevel == 0) {
-
- if (Lexer.is(AsmToken::Comma))
- break;
-
- if (Lexer.is(AsmToken::Space)) {
- SpaceEaten = true;
- Lexer.Lex(); // Eat spaces
- }
-
- // Spaces can delimit parameters, but could also be part an expression.
- // If the token after a space is an operator, add the token and the next
- // one into this argument
- if (!IsDarwin) {
- if (isOperator(Lexer.getKind())) {
- MA.push_back(getTok());
- Lexer.Lex();
-
- // Whitespace after an operator can be ignored.
- if (Lexer.is(AsmToken::Space))
- Lexer.Lex();
-
- continue;
- }
- }
- if (SpaceEaten)
- break;
- }
-
- // handleMacroEntry relies on not advancing the lexer here
- // to be able to fill in the remaining default parameter values
- if (Lexer.is(AsmToken::EndOfStatement))
- break;
-
- // Adjust the current parentheses level.
- if (Lexer.is(AsmToken::LParen))
- ++ParenLevel;
- else if (Lexer.is(AsmToken::RParen) && ParenLevel)
- --ParenLevel;
-
- // Append the token to the current argument list.
- MA.push_back(getTok());
- Lexer.Lex();
- }
-
- if (ParenLevel != 0)
- return TokError("unbalanced parentheses in macro argument");
- return false;
-}
-
-// Parse the macro instantiation arguments.
-bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
- MCAsmMacroArguments &A) {
- const unsigned NParameters = M ? M->Parameters.size() : 0;
- bool NamedParametersFound = false;
- SmallVector<SMLoc, 4> FALocs;
-
- A.resize(NParameters);
- FALocs.resize(NParameters);
-
- // Parse two kinds of macro invocations:
- // - macros defined without any parameters accept an arbitrary number of them
- // - macros defined with parameters accept at most that many of them
- bool HasVararg = NParameters ? M->Parameters.back().Vararg : false;
- for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
- ++Parameter) {
- SMLoc IDLoc = Lexer.getLoc();
- MCAsmMacroParameter FA;
-
- if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
- 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");
-
- Lex();
-
- NamedParametersFound = true;
- }
- bool Vararg = HasVararg && Parameter == (NParameters - 1);
-
- if (NamedParametersFound && FA.Name.empty())
- return Error(IDLoc, "cannot mix positional and keyword arguments");
-
- SMLoc StrLoc = Lexer.getLoc();
- SMLoc EndLoc;
- if (AltMacroMode && Lexer.is(AsmToken::Percent)) {
- const MCExpr *AbsoluteExp;
- int64_t Value;
- /// Eat '%'
- Lex();
- if (parseExpression(AbsoluteExp, EndLoc))
- return false;
- if (!AbsoluteExp->evaluateAsAbsolute(Value,
- getStreamer().getAssemblerPtr()))
- return Error(StrLoc, "expected absolute expression");
- const char *StrChar = StrLoc.getPointer();
- const char *EndChar = EndLoc.getPointer();
- AsmToken newToken(AsmToken::Integer,
- StringRef(StrChar, EndChar - StrChar), Value);
- FA.Value.push_back(newToken);
- } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
- isAngleBracketString(StrLoc, EndLoc)) {
- const char *StrChar = StrLoc.getPointer();
- const char *EndChar = EndLoc.getPointer();
- jumpToLoc(EndLoc, CurBuffer);
- /// Eat from '<' to '>'
- Lex();
- AsmToken newToken(AsmToken::String,
- StringRef(StrChar, EndChar - StrChar));
- FA.Value.push_back(newToken);
- } else if(parseMacroArgument(FA.Value, Vararg))
- return true;
-
- unsigned PI = Parameter;
- if (!FA.Name.empty()) {
- unsigned FAI = 0;
- for (FAI = 0; FAI < NParameters; ++FAI)
- if (M->Parameters[FAI].Name == FA.Name)
- break;
-
- if (FAI >= NParameters) {
- assert(M && "expected macro to be defined");
- return Error(IDLoc, "parameter named '" + FA.Name +
- "' does not exist for macro '" + M->Name + "'");
- }
- PI = FAI;
- }
-
- if (!FA.Value.empty()) {
- if (A.size() <= PI)
- A.resize(PI + 1);
- A[PI] = FA.Value;
-
- if (FALocs.size() <= PI)
- FALocs.resize(PI + 1);
-
- FALocs[PI] = Lexer.getLoc();
- }
-
- // At the end of the statement, fill in remaining arguments that have
- // default values. If there aren't any, then the next argument is
- // required but missing
- if (Lexer.is(AsmToken::EndOfStatement)) {
- bool Failure = false;
- for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
- if (A[FAI].empty()) {
- if (M->Parameters[FAI].Required) {
- Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
- "missing value for required parameter "
- "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
- Failure = true;
- }
-
- if (!M->Parameters[FAI].Value.empty())
- A[FAI] = M->Parameters[FAI].Value;
- }
- }
- return Failure;
- }
-
- if (Lexer.is(AsmToken::Comma))
- Lex();
- }
-
- return TokError("too many positional arguments");
-}
-
-bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
- // 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))
- return true;
-
- // Macro instantiation is lexical, unfortunately. We construct a new buffer
- // to hold the macro body with substitutions.
- SmallString<256> Buf;
- StringRef Body = M->Body;
- raw_svector_ostream OS(Buf);
-
- if (expandMacro(OS, Body, M->Parameters, A, true, getTok().getLoc()))
- return true;
-
- // We include the .endmacro in the buffer as our cue to exit the macro
- // instantiation.
- OS << ".endmacro\n";
-
- std::unique_ptr<MemoryBuffer> Instantiation =
- MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
-
- // Create the macro instantiation object and add to the current macro
- // instantiation stack.
- MacroInstantiation *MI = new MacroInstantiation{
- NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
- ActiveMacros.push_back(MI);
-
- ++NumOfMacroInstantiations;
-
- // Jump to the macro instantiation and prime the lexer.
- CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
- Lex();
-
- return false;
-}
-
-void AsmParser::handleMacroExit() {
- // Jump to the EndOfStatement we should return to, and consume it.
- jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
- Lex();
-
- // Pop the instantiation entry.
- delete ActiveMacros.back();
- ActiveMacros.pop_back();
-}
-
-bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
- bool NoDeadStrip) {
- MCSymbol *Sym;
- const MCExpr *Value;
- if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym,
- Value))
- return true;
-
- if (!Sym) {
- // In the case where we parse an expression starting with a '.', we will
- // not generate an error, nor will we create a symbol. In this case we
- // should just return out.
- return false;
- }
-
- // Do the assignment.
- Out.emitAssignment(Sym, Value);
- if (NoDeadStrip)
- Out.emitSymbolAttribute(Sym, MCSA_NoDeadStrip);
-
- return false;
-}
-
-/// parseIdentifier:
-/// ::= identifier
-/// ::= string
-bool AsmParser::parseIdentifier(StringRef &Res) {
- // The assembler has relaxed rules for accepting identifiers, in particular we
- // allow things like '.globl $foo' and '.def @feat.00', which would normally be
- // separate tokens. At this level, we have already lexed so we cannot (currently)
- // handle this as a context dependent token, instead we detect adjacent tokens
- // and return the combined identifier.
- if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
- SMLoc PrefixLoc = getLexer().getLoc();
-
- // Consume the prefix character, and check for a following identifier.
-
- AsmToken Buf[1];
- Lexer.peekTokens(Buf, false);
-
- if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer))
- return true;
-
- // We have a '$' or '@' followed by an identifier or integer token, make
- // sure they are adjacent.
- 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().getString().size() + 1);
- Lex(); // Parser Lex to maintain invariants.
- return false;
- }
-
- if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
- return true;
-
- Res = getTok().getIdentifier();
-
- Lex(); // Consume the identifier token.
-
- return false;
-}
-
-/// parseDirectiveSet:
-/// ::= .equ identifier ',' expression
-/// ::= .equiv identifier ',' expression
-/// ::= .set identifier ',' expression
-bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) {
- StringRef Name;
- 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) {
- if (check(getTok().isNot(AsmToken::String), "expected string"))
- return true;
-
- Data = "";
- StringRef Str = getTok().getStringContents();
- for (unsigned i = 0, e = Str.size(); i != e; ++i) {
- if (Str[i] != '\\') {
- Data += Str[i];
- continue;
- }
-
- // Recognize escaped characters. Note that this escape semantics currently
- // loosely follows Darwin 'as'.
- ++i;
- if (i == e)
- return TokError("unexpected backslash at end of string");
-
- // Recognize hex sequences similarly to GNU 'as'.
- if (Str[i] == 'x' || Str[i] == 'X') {
- size_t length = Str.size();
- if (i + 1 >= length || !isHexDigit(Str[i + 1]))
- return TokError("invalid hexadecimal escape sequence");
-
- // Consume hex characters. GNU 'as' reads all hexadecimal characters and
- // then truncates to the lower 16 bits. Seems reasonable.
- unsigned Value = 0;
- while (i + 1 < length && isHexDigit(Str[i + 1]))
- Value = Value * 16 + hexDigitValue(Str[++i]);
-
- Data += (unsigned char)(Value & 0xFF);
- continue;
- }
-
- // Recognize octal sequences.
- if ((unsigned)(Str[i] - '0') <= 7) {
- // Consume up to three octal characters.
- unsigned Value = Str[i] - '0';
-
- if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
- ++i;
- Value = Value * 8 + (Str[i] - '0');
-
- if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
- ++i;
- Value = Value * 8 + (Str[i] - '0');
- }
- }
-
- if (Value > 255)
- return TokError("invalid octal escape sequence (out of range)");
-
- Data += (unsigned char)Value;
- continue;
- }
-
- // Otherwise recognize individual escapes.
- switch (Str[i]) {
- default:
- // Just reject invalid escape sequences for now.
- return TokError("invalid escape sequence (unrecognized character)");
-
- case 'b': Data += '\b'; break;
- case 'f': Data += '\f'; break;
- case 'n': Data += '\n'; break;
- case 'r': Data += '\r'; break;
- case 't': Data += '\t'; break;
- case '"': Data += '"'; break;
- case '\\': Data += '\\'; break;
- }
- }
-
- Lex();
- return false;
-}
-
-bool AsmParser::parseAngleBracketString(std::string &Data) {
- SMLoc EndLoc, StartLoc = getTok().getLoc();
- if (isAngleBracketString(StartLoc, EndLoc)) {
- const char *StartChar = StartLoc.getPointer() + 1;
- const char *EndChar = EndLoc.getPointer() - 1;
- jumpToLoc(EndLoc, CurBuffer);
- /// Eat from '<' to '>'
- Lex();
-
- Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
- return false;
- }
- return true;
-}
-
-/// parseDirectiveAscii:
+ }
+
+ return Error(IDLoc, "unknown directive");
+ }
+
+ // __asm _emit or __asm __emit
+ if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
+ IDVal == "_EMIT" || IDVal == "__EMIT"))
+ return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
+
+ // __asm align
+ if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
+ return parseDirectiveMSAlign(IDLoc, Info);
+
+ if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
+ Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
+ if (checkForValidSection())
+ return true;
+
+ // Canonicalize the opcode to lower case.
+ std::string OpcodeStr = IDVal.lower();
+ ParseInstructionInfo IInfo(Info.AsmRewrites);
+ bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
+ Info.ParsedOperands);
+ Info.ParseError = ParseHadError;
+
+ // Dump the parsed representation, if requested.
+ if (getShowParsedOperands()) {
+ SmallString<256> Str;
+ raw_svector_ostream OS(Str);
+ OS << "parsed instruction: [";
+ for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
+ if (i != 0)
+ OS << ", ";
+ Info.ParsedOperands[i]->print(OS);
+ }
+ OS << "]";
+
+ 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 (!ParseHadError && enabledGenDwarfForAssembly() &&
+ getContext().getGenDwarfSectionSyms().count(
+ getStreamer().getCurrentSectionOnly())) {
+ unsigned Line;
+ if (ActiveMacros.empty())
+ Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
+ else
+ Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
+ ActiveMacros.front()->ExitBuffer);
+
+ // If we previously parsed a cpp hash file line comment then make sure the
+ // current Dwarf File is for the CppHashFilename if not then emit the
+ // Dwarf File table for it and adjust the line number for the .loc.
+ if (!CppHashInfo.Filename.empty()) {
+ unsigned FileNumber = getStreamer().emitDwarfFileDirective(
+ 0, StringRef(), CppHashInfo.Filename);
+ getContext().setGenDwarfFileNumber(FileNumber);
+
+ unsigned CppHashLocLineNo =
+ SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
+ Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
+ }
+
+ getStreamer().emitDwarfLocDirective(
+ getContext().getGenDwarfFileNumber(), Line, 0,
+ DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
+ StringRef());
+ }
+
+ // If parsing succeeded, match the instruction.
+ if (!ParseHadError) {
+ uint64_t ErrorInfo;
+ if (getTargetParser().MatchAndEmitInstruction(
+ IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
+ getTargetParser().isParsingMSInlineAsm()))
+ return true;
+ }
+ return false;
+}
+
+// Parse and erase curly braces marking block start/end
+bool
+AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
+ // Identify curly brace marking block start/end
+ if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
+ return false;
+
+ SMLoc StartLoc = Lexer.getLoc();
+ Lex(); // Eat the brace
+ if (Lexer.is(AsmToken::EndOfStatement))
+ Lex(); // Eat EndOfStatement following the brace
+
+ // Erase the block start/end brace from the output asm string
+ AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
+ StartLoc.getPointer());
+ return true;
+}
+
+/// parseCppHashLineFilenameComment as this:
+/// ::= # number "filename"
+bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) {
+ Lex(); // Eat the hash token.
+ // Lexer only ever emits HashDirective if it fully formed if it's
+ // done the checking already so this is an internal error.
+ assert(getTok().is(AsmToken::Integer) &&
+ "Lexing Cpp line comment: Expected Integer");
+ int64_t LineNumber = getTok().getIntVal();
+ Lex();
+ assert(getTok().is(AsmToken::String) &&
+ "Lexing Cpp line comment: Expected String");
+ StringRef Filename = getTok().getString();
+ Lex();
+
+ if (!SaveLocInfo)
+ return false;
+
+ // Get rid of the enclosing quotes.
+ Filename = Filename.substr(1, Filename.size() - 2);
+
+ // Save the SMLoc, Filename and LineNumber for later use by diagnostics
+ // and possibly DWARF file info.
+ CppHashInfo.Loc = L;
+ CppHashInfo.Filename = Filename;
+ CppHashInfo.LineNumber = LineNumber;
+ CppHashInfo.Buf = CurBuffer;
+ if (FirstCppHashFilename.empty())
+ FirstCppHashFilename = Filename;
+ return false;
+}
+
+/// will use the last parsed cpp hash line filename comment
+/// for the Filename and LineNo if any in the diagnostic.
+void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
+ const AsmParser *Parser = static_cast<const AsmParser *>(Context);
+ raw_ostream &OS = errs();
+
+ const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
+ SMLoc DiagLoc = Diag.getLoc();
+ unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
+ unsigned CppHashBuf =
+ Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
+
+ // Like SourceMgr::printMessage() we need to print the include stack if any
+ // before printing the message.
+ unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
+ if (!Parser->SavedDiagHandler && DiagCurBuffer &&
+ DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
+ SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
+ DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
+ }
+
+ // If we have not parsed a cpp hash line filename comment or the source
+ // manager changed or buffer changed (like in a nested include) then just
+ // print the normal diagnostic using its Filename and LineNo.
+ if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
+ DiagBuf != CppHashBuf) {
+ if (Parser->SavedDiagHandler)
+ Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
+ else
+ Diag.print(nullptr, OS);
+ return;
+ }
+
+ // Use the CppHashFilename and calculate a line number based on the
+ // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
+ // for the diagnostic.
+ const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
+
+ int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
+ int CppHashLocLineNo =
+ Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
+ int LineNo =
+ Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
+
+ SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
+ Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
+ Diag.getLineContents(), Diag.getRanges());
+
+ if (Parser->SavedDiagHandler)
+ Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
+ else
+ NewDiag.print(nullptr, OS);
+}
+
+// FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The
+// difference being that that function accepts '@' as part of identifiers and
+// we can't do that. AsmLexer.cpp should probably be changed to handle
+// '@' as a special case when needed.
+static bool isIdentifierChar(char c) {
+ return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||
+ c == '.';
+}
+
+bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
+ ArrayRef<MCAsmMacroParameter> Parameters,
+ ArrayRef<MCAsmMacroArgument> A,
+ bool EnableAtPseudoVariable, SMLoc L) {
+ unsigned NParameters = Parameters.size();
+ bool HasVararg = NParameters ? Parameters.back().Vararg : false;
+ if ((!IsDarwin || NParameters != 0) && NParameters != A.size())
+ return Error(L, "Wrong number of arguments");
+
+ // A macro without parameters is handled differently on Darwin:
+ // gas accepts no arguments and does no substitutions
+ while (!Body.empty()) {
+ // Scan for the next substitution.
+ std::size_t End = Body.size(), Pos = 0;
+ for (; Pos != End; ++Pos) {
+ // Check for a substitution or escape.
+ if (IsDarwin && !NParameters) {
+ // This macro has no parameters, look for $0, $1, etc.
+ if (Body[Pos] != '$' || Pos + 1 == End)
+ continue;
+
+ char Next = Body[Pos + 1];
+ if (Next == '$' || Next == 'n' ||
+ isdigit(static_cast<unsigned char>(Next)))
+ break;
+ } else {
+ // This macro has parameters, look for \foo, \bar, etc.
+ if (Body[Pos] == '\\' && Pos + 1 != End)
+ break;
+ }
+ }
+
+ // Add the prefix.
+ OS << Body.slice(0, Pos);
+
+ // Check if we reached the end.
+ if (Pos == End)
+ break;
+
+ if (IsDarwin && !NParameters) {
+ switch (Body[Pos + 1]) {
+ // $$ => $
+ case '$':
+ OS << '$';
+ break;
+
+ // $n => number of arguments
+ case 'n':
+ OS << A.size();
+ break;
+
+ // $[0-9] => argument
+ default: {
+ // Missing arguments are ignored.
+ unsigned Index = Body[Pos + 1] - '0';
+ if (Index >= A.size())
+ break;
+
+ // Otherwise substitute with the token values, with spaces eliminated.
+ for (const AsmToken &Token : A[Index])
+ OS << Token.getString();
+ break;
+ }
+ }
+ Pos += 2;
+ } else {
+ unsigned I = Pos + 1;
+
+ // Check for the \@ pseudo-variable.
+ if (EnableAtPseudoVariable && Body[I] == '@' && I + 1 != End)
+ ++I;
+ else
+ while (isIdentifierChar(Body[I]) && I + 1 != End)
+ ++I;
+
+ const char *Begin = Body.data() + Pos + 1;
+ StringRef Argument(Begin, I - (Pos + 1));
+ unsigned Index = 0;
+
+ if (Argument == "@") {
+ OS << NumOfMacroInstantiations;
+ Pos += 2;
+ } else {
+ for (; Index < NParameters; ++Index)
+ if (Parameters[Index].Name == Argument)
+ break;
+
+ if (Index == NParameters) {
+ if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
+ Pos += 3;
+ else {
+ OS << '\\' << Argument;
+ Pos = I;
+ }
+ } else {
+ bool VarargParameter = HasVararg && Index == (NParameters - 1);
+ for (const AsmToken &Token : A[Index])
+ // For altmacro mode, you can write '%expr'.
+ // The prefix '%' evaluates the expression 'expr'
+ // and uses the result as a string (e.g. replace %(1+2) with the
+ // string "3").
+ // Here, we identify the integer token which is the result of the
+ // absolute expression evaluation and replace it with its string
+ // representation.
+ if (AltMacroMode && Token.getString().front() == '%' &&
+ Token.is(AsmToken::Integer))
+ // Emit an integer value to the buffer.
+ OS << Token.getIntVal();
+ // Only Token that was validated as a string and begins with '<'
+ // is considered altMacroString!!!
+ else if (AltMacroMode && Token.getString().front() == '<' &&
+ Token.is(AsmToken::String)) {
+ OS << angleBracketString(Token.getStringContents());
+ }
+ // We expect no quotes around the string's contents when
+ // parsing for varargs.
+ else if (Token.isNot(AsmToken::String) || VarargParameter)
+ OS << Token.getString();
+ else
+ OS << Token.getStringContents();
+
+ Pos += 1 + Argument.size();
+ }
+ }
+ }
+ // Update the scan point.
+ Body = Body.substr(Pos);
+ }
+
+ return false;
+}
+
+static bool isOperator(AsmToken::TokenKind kind) {
+ switch (kind) {
+ default:
+ return false;
+ case AsmToken::Plus:
+ case AsmToken::Minus:
+ case AsmToken::Tilde:
+ case AsmToken::Slash:
+ case AsmToken::Star:
+ case AsmToken::Dot:
+ case AsmToken::Equal:
+ case AsmToken::EqualEqual:
+ case AsmToken::Pipe:
+ case AsmToken::PipePipe:
+ case AsmToken::Caret:
+ case AsmToken::Amp:
+ case AsmToken::AmpAmp:
+ case AsmToken::Exclaim:
+ case AsmToken::ExclaimEqual:
+ case AsmToken::Less:
+ case AsmToken::LessEqual:
+ case AsmToken::LessLess:
+ case AsmToken::LessGreater:
+ case AsmToken::Greater:
+ case AsmToken::GreaterEqual:
+ case AsmToken::GreaterGreater:
+ return true;
+ }
+}
+
+namespace {
+
+class AsmLexerSkipSpaceRAII {
+public:
+ AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
+ Lexer.setSkipSpace(SkipSpace);
+ }
+
+ ~AsmLexerSkipSpaceRAII() {
+ Lexer.setSkipSpace(true);
+ }
+
+private:
+ AsmLexer &Lexer;
+};
+
+} // end anonymous namespace
+
+bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
+
+ if (Vararg) {
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ StringRef Str = parseStringToEndOfStatement();
+ MA.emplace_back(AsmToken::String, Str);
+ }
+ return false;
+ }
+
+ unsigned ParenLevel = 0;
+
+ // Darwin doesn't use spaces to delmit arguments.
+ AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
+
+ bool SpaceEaten;
+
+ while (true) {
+ SpaceEaten = false;
+ if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
+ return TokError("unexpected token in macro instantiation");
+
+ if (ParenLevel == 0) {
+
+ if (Lexer.is(AsmToken::Comma))
+ break;
+
+ if (Lexer.is(AsmToken::Space)) {
+ SpaceEaten = true;
+ Lexer.Lex(); // Eat spaces
+ }
+
+ // Spaces can delimit parameters, but could also be part an expression.
+ // If the token after a space is an operator, add the token and the next
+ // one into this argument
+ if (!IsDarwin) {
+ if (isOperator(Lexer.getKind())) {
+ MA.push_back(getTok());
+ Lexer.Lex();
+
+ // Whitespace after an operator can be ignored.
+ if (Lexer.is(AsmToken::Space))
+ Lexer.Lex();
+
+ continue;
+ }
+ }
+ if (SpaceEaten)
+ break;
+ }
+
+ // handleMacroEntry relies on not advancing the lexer here
+ // to be able to fill in the remaining default parameter values
+ if (Lexer.is(AsmToken::EndOfStatement))
+ break;
+
+ // Adjust the current parentheses level.
+ if (Lexer.is(AsmToken::LParen))
+ ++ParenLevel;
+ else if (Lexer.is(AsmToken::RParen) && ParenLevel)
+ --ParenLevel;
+
+ // Append the token to the current argument list.
+ MA.push_back(getTok());
+ Lexer.Lex();
+ }
+
+ if (ParenLevel != 0)
+ return TokError("unbalanced parentheses in macro argument");
+ return false;
+}
+
+// Parse the macro instantiation arguments.
+bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
+ MCAsmMacroArguments &A) {
+ const unsigned NParameters = M ? M->Parameters.size() : 0;
+ bool NamedParametersFound = false;
+ SmallVector<SMLoc, 4> FALocs;
+
+ A.resize(NParameters);
+ FALocs.resize(NParameters);
+
+ // Parse two kinds of macro invocations:
+ // - macros defined without any parameters accept an arbitrary number of them
+ // - macros defined with parameters accept at most that many of them
+ bool HasVararg = NParameters ? M->Parameters.back().Vararg : false;
+ for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
+ ++Parameter) {
+ SMLoc IDLoc = Lexer.getLoc();
+ MCAsmMacroParameter FA;
+
+ if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
+ 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");
+
+ Lex();
+
+ NamedParametersFound = true;
+ }
+ bool Vararg = HasVararg && Parameter == (NParameters - 1);
+
+ if (NamedParametersFound && FA.Name.empty())
+ return Error(IDLoc, "cannot mix positional and keyword arguments");
+
+ SMLoc StrLoc = Lexer.getLoc();
+ SMLoc EndLoc;
+ if (AltMacroMode && Lexer.is(AsmToken::Percent)) {
+ const MCExpr *AbsoluteExp;
+ int64_t Value;
+ /// Eat '%'
+ Lex();
+ if (parseExpression(AbsoluteExp, EndLoc))
+ return false;
+ if (!AbsoluteExp->evaluateAsAbsolute(Value,
+ getStreamer().getAssemblerPtr()))
+ return Error(StrLoc, "expected absolute expression");
+ const char *StrChar = StrLoc.getPointer();
+ const char *EndChar = EndLoc.getPointer();
+ AsmToken newToken(AsmToken::Integer,
+ StringRef(StrChar, EndChar - StrChar), Value);
+ FA.Value.push_back(newToken);
+ } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
+ isAngleBracketString(StrLoc, EndLoc)) {
+ const char *StrChar = StrLoc.getPointer();
+ const char *EndChar = EndLoc.getPointer();
+ jumpToLoc(EndLoc, CurBuffer);
+ /// Eat from '<' to '>'
+ Lex();
+ AsmToken newToken(AsmToken::String,
+ StringRef(StrChar, EndChar - StrChar));
+ FA.Value.push_back(newToken);
+ } else if(parseMacroArgument(FA.Value, Vararg))
+ return true;
+
+ unsigned PI = Parameter;
+ if (!FA.Name.empty()) {
+ unsigned FAI = 0;
+ for (FAI = 0; FAI < NParameters; ++FAI)
+ if (M->Parameters[FAI].Name == FA.Name)
+ break;
+
+ if (FAI >= NParameters) {
+ assert(M && "expected macro to be defined");
+ return Error(IDLoc, "parameter named '" + FA.Name +
+ "' does not exist for macro '" + M->Name + "'");
+ }
+ PI = FAI;
+ }
+
+ if (!FA.Value.empty()) {
+ if (A.size() <= PI)
+ A.resize(PI + 1);
+ A[PI] = FA.Value;
+
+ if (FALocs.size() <= PI)
+ FALocs.resize(PI + 1);
+
+ FALocs[PI] = Lexer.getLoc();
+ }
+
+ // At the end of the statement, fill in remaining arguments that have
+ // default values. If there aren't any, then the next argument is
+ // required but missing
+ if (Lexer.is(AsmToken::EndOfStatement)) {
+ bool Failure = false;
+ for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
+ if (A[FAI].empty()) {
+ if (M->Parameters[FAI].Required) {
+ Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
+ "missing value for required parameter "
+ "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
+ Failure = true;
+ }
+
+ if (!M->Parameters[FAI].Value.empty())
+ A[FAI] = M->Parameters[FAI].Value;
+ }
+ }
+ return Failure;
+ }
+
+ if (Lexer.is(AsmToken::Comma))
+ Lex();
+ }
+
+ return TokError("too many positional arguments");
+}
+
+bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
+ // 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))
+ return true;
+
+ // Macro instantiation is lexical, unfortunately. We construct a new buffer
+ // to hold the macro body with substitutions.
+ SmallString<256> Buf;
+ StringRef Body = M->Body;
+ raw_svector_ostream OS(Buf);
+
+ if (expandMacro(OS, Body, M->Parameters, A, true, getTok().getLoc()))
+ return true;
+
+ // We include the .endmacro in the buffer as our cue to exit the macro
+ // instantiation.
+ OS << ".endmacro\n";
+
+ std::unique_ptr<MemoryBuffer> Instantiation =
+ MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
+
+ // Create the macro instantiation object and add to the current macro
+ // instantiation stack.
+ MacroInstantiation *MI = new MacroInstantiation{
+ NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
+ ActiveMacros.push_back(MI);
+
+ ++NumOfMacroInstantiations;
+
+ // Jump to the macro instantiation and prime the lexer.
+ CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
+ Lex();
+
+ return false;
+}
+
+void AsmParser::handleMacroExit() {
+ // Jump to the EndOfStatement we should return to, and consume it.
+ jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
+ Lex();
+
+ // Pop the instantiation entry.
+ delete ActiveMacros.back();
+ ActiveMacros.pop_back();
+}
+
+bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
+ bool NoDeadStrip) {
+ MCSymbol *Sym;
+ const MCExpr *Value;
+ if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym,
+ Value))
+ return true;
+
+ if (!Sym) {
+ // In the case where we parse an expression starting with a '.', we will
+ // not generate an error, nor will we create a symbol. In this case we
+ // should just return out.
+ return false;
+ }
+
+ // Do the assignment.
+ Out.emitAssignment(Sym, Value);
+ if (NoDeadStrip)
+ Out.emitSymbolAttribute(Sym, MCSA_NoDeadStrip);
+
+ return false;
+}
+
+/// parseIdentifier:
+/// ::= identifier
+/// ::= string
+bool AsmParser::parseIdentifier(StringRef &Res) {
+ // The assembler has relaxed rules for accepting identifiers, in particular we
+ // allow things like '.globl $foo' and '.def @feat.00', which would normally be
+ // separate tokens. At this level, we have already lexed so we cannot (currently)
+ // handle this as a context dependent token, instead we detect adjacent tokens
+ // and return the combined identifier.
+ if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
+ SMLoc PrefixLoc = getLexer().getLoc();
+
+ // Consume the prefix character, and check for a following identifier.
+
+ AsmToken Buf[1];
+ Lexer.peekTokens(Buf, false);
+
+ if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer))
+ return true;
+
+ // We have a '$' or '@' followed by an identifier or integer token, make
+ // sure they are adjacent.
+ 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().getString().size() + 1);
+ Lex(); // Parser Lex to maintain invariants.
+ return false;
+ }
+
+ if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
+ return true;
+
+ Res = getTok().getIdentifier();
+
+ Lex(); // Consume the identifier token.
+
+ return false;
+}
+
+/// parseDirectiveSet:
+/// ::= .equ identifier ',' expression
+/// ::= .equiv identifier ',' expression
+/// ::= .set identifier ',' expression
+bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) {
+ StringRef Name;
+ 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) {
+ if (check(getTok().isNot(AsmToken::String), "expected string"))
+ return true;
+
+ Data = "";
+ StringRef Str = getTok().getStringContents();
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ if (Str[i] != '\\') {
+ Data += Str[i];
+ continue;
+ }
+
+ // Recognize escaped characters. Note that this escape semantics currently
+ // loosely follows Darwin 'as'.
+ ++i;
+ if (i == e)
+ return TokError("unexpected backslash at end of string");
+
+ // Recognize hex sequences similarly to GNU 'as'.
+ if (Str[i] == 'x' || Str[i] == 'X') {
+ size_t length = Str.size();
+ if (i + 1 >= length || !isHexDigit(Str[i + 1]))
+ return TokError("invalid hexadecimal escape sequence");
+
+ // Consume hex characters. GNU 'as' reads all hexadecimal characters and
+ // then truncates to the lower 16 bits. Seems reasonable.
+ unsigned Value = 0;
+ while (i + 1 < length && isHexDigit(Str[i + 1]))
+ Value = Value * 16 + hexDigitValue(Str[++i]);
+
+ Data += (unsigned char)(Value & 0xFF);
+ continue;
+ }
+
+ // Recognize octal sequences.
+ if ((unsigned)(Str[i] - '0') <= 7) {
+ // Consume up to three octal characters.
+ unsigned Value = Str[i] - '0';
+
+ if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
+ ++i;
+ Value = Value * 8 + (Str[i] - '0');
+
+ if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
+ ++i;
+ Value = Value * 8 + (Str[i] - '0');
+ }
+ }
+
+ if (Value > 255)
+ return TokError("invalid octal escape sequence (out of range)");
+
+ Data += (unsigned char)Value;
+ continue;
+ }
+
+ // Otherwise recognize individual escapes.
+ switch (Str[i]) {
+ default:
+ // Just reject invalid escape sequences for now.
+ return TokError("invalid escape sequence (unrecognized character)");
+
+ case 'b': Data += '\b'; break;
+ case 'f': Data += '\f'; break;
+ case 'n': Data += '\n'; break;
+ case 'r': Data += '\r'; break;
+ case 't': Data += '\t'; break;
+ case '"': Data += '"'; break;
+ case '\\': Data += '\\'; break;
+ }
+ }
+
+ Lex();
+ return false;
+}
+
+bool AsmParser::parseAngleBracketString(std::string &Data) {
+ SMLoc EndLoc, StartLoc = getTok().getLoc();
+ if (isAngleBracketString(StartLoc, EndLoc)) {
+ const char *StartChar = StartLoc.getPointer() + 1;
+ const char *EndChar = EndLoc.getPointer() - 1;
+ jumpToLoc(EndLoc, CurBuffer);
+ /// Eat from '<' to '>'
+ Lex();
+
+ Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
+ return false;
+ }
+ return true;
+}
+
+/// parseDirectiveAscii:
// ::= .ascii [ "string"+ ( , "string"+ )* ]
/// ::= ( .asciz | .string ) [ "string" ( , "string" )* ]
-bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
- auto parseOp = [&]() -> bool {
- std::string Data;
+bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
+ auto parseOp = [&]() -> bool {
+ std::string Data;
if (checkForValidSection())
- return true;
+ return true;
// Only support spaces as separators for .ascii directive for now. See the
// discusssion at https://reviews.llvm.org/D91460 for more details.
do {
@@ -3022,2775 +3022,2775 @@ bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
return true;
getStreamer().emitBytes(Data);
} while (!ZeroTerminated && getTok().is(AsmToken::String));
- if (ZeroTerminated)
- getStreamer().emitBytes(StringRef("\0", 1));
- return false;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- return false;
-}
-
-/// parseDirectiveReloc
-/// ::= .reloc expression , identifier [ , expression ]
-bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
- const MCExpr *Offset;
- const MCExpr *Expr = nullptr;
- SMLoc OffsetLoc = Lexer.getTok().getLoc();
-
- if (parseExpression(Offset))
- return true;
- if (parseToken(AsmToken::Comma, "expected comma") ||
- check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
- return true;
-
- SMLoc NameLoc = Lexer.getTok().getLoc();
- StringRef Name = Lexer.getTok().getIdentifier();
- Lex();
-
- if (Lexer.is(AsmToken::Comma)) {
- Lex();
- SMLoc ExprLoc = Lexer.getLoc();
- if (parseExpression(Expr))
- return true;
-
- MCValue Value;
- if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr))
- return Error(ExprLoc, "expression must be relocatable");
- }
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in .reloc directive"))
- return true;
-
- const MCTargetAsmParser &MCT = getTargetParser();
- const MCSubtargetInfo &STI = MCT.getSTI();
- if (Optional<std::pair<bool, std::string>> Err =
- getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc,
- STI))
- return Error(Err->first ? NameLoc : OffsetLoc, Err->second);
-
- return false;
-}
-
-/// parseDirectiveValue
-/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
-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;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- return false;
-}
-
-static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {
- if (Asm.getTok().isNot(AsmToken::Integer) &&
- Asm.getTok().isNot(AsmToken::BigNum))
- return Asm.TokError("unknown token in expression");
- SMLoc ExprLoc = Asm.getTok().getLoc();
- APInt IntValue = Asm.getTok().getAPIntVal();
- Asm.Lex();
- if (!IntValue.isIntN(128))
- return Asm.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();
- }
- return false;
-}
-
-/// ParseDirectiveOctaValue
-/// ::= .octa [ hexconstant (, hexconstant)* ]
-
-bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
- auto parseOp = [&]() -> bool {
- if (checkForValidSection())
- return true;
- uint64_t hi, lo;
- if (parseHexOcta(*this, hi, lo))
- return true;
- if (MAI.isLittleEndian()) {
- getStreamer().emitInt64(lo);
- getStreamer().emitInt64(hi);
- } else {
- getStreamer().emitInt64(hi);
- getStreamer().emitInt64(lo);
- }
- return false;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- return false;
-}
-
-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();
-
- 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 (errorToBool(
- Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
- .takeError()))
- 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(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;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- return false;
-}
-
-/// parseDirectiveZero
-/// ::= .zero expression
-bool AsmParser::parseDirectiveZero() {
- SMLoc NumBytesLoc = Lexer.getLoc();
- const MCExpr *NumBytes;
- if (checkForValidSection() || parseExpression(NumBytes))
- return true;
-
- int64_t Val = 0;
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
- if (parseAbsoluteExpression(Val))
- return true;
- }
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.zero' directive"))
- return true;
- getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);
-
- return false;
-}
-
-/// parseDirectiveFill
-/// ::= .fill expression [ , expression [ , expression ] ]
-bool AsmParser::parseDirectiveFill() {
- SMLoc NumValuesLoc = Lexer.getLoc();
- const MCExpr *NumValues;
- if (checkForValidSection() || parseExpression(NumValues))
- return true;
-
- int64_t FillSize = 1;
- int64_t FillExpr = 0;
-
- SMLoc SizeLoc, ExprLoc;
-
- if (parseOptionalToken(AsmToken::Comma)) {
- SizeLoc = getTok().getLoc();
- if (parseAbsoluteExpression(FillSize))
- return true;
- 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");
- return false;
- }
- if (FillSize > 8) {
- Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
- FillSize = 8;
- }
-
- if (!isUInt<32>(FillExpr) && FillSize > 4)
- Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
-
- getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);
-
- return false;
-}
-
-/// parseDirectiveOrg
-/// ::= .org expression [ , expression ]
-bool AsmParser::parseDirectiveOrg() {
- const MCExpr *Offset;
- SMLoc OffsetLoc = Lexer.getLoc();
- if (checkForValidSection() || parseExpression(Offset))
- return true;
-
- // Parse optional fill expression.
- int64_t FillExpr = 0;
- if (parseOptionalToken(AsmToken::Comma))
- if (parseAbsoluteExpression(FillExpr))
- return addErrorSuffix(" in '.org' directive");
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in '.org' directive");
-
- getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
- return false;
-}
-
-/// parseDirectiveAlign
-/// ::= {.align, ...} expression [ , expression [ , expression ]]
-bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
- SMLoc AlignmentLoc = getLexer().getLoc();
- int64_t Alignment;
- SMLoc MaxBytesLoc;
- bool HasFillExpr = false;
- int64_t FillExpr = 0;
- int64_t MaxBytesToFill = 0;
-
- auto parseAlign = [&]() -> bool {
- if (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 (checkForValidSection())
- return addErrorSuffix(" in directive");
- // Ignore empty '.p2align' directives for GNU-as compatibility
- if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
- Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
- return parseToken(AsmToken::EndOfStatement);
- }
- if (parseAlign())
- return addErrorSuffix(" in directive");
-
- // 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) {
- ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
- Alignment = 31;
- }
-
- Alignment = 1ULL << Alignment;
- } else {
- // Reject alignments that aren't either a power of two or zero,
- // for gas compatibility. Alignment of zero is silently rounded
- // up to one.
- if (Alignment == 0)
- Alignment = 1;
- if (!isPowerOf2_64(Alignment))
- ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
+ if (ZeroTerminated)
+ getStreamer().emitBytes(StringRef("\0", 1));
+ return false;
+ };
+
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ return false;
+}
+
+/// parseDirectiveReloc
+/// ::= .reloc expression , identifier [ , expression ]
+bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
+ const MCExpr *Offset;
+ const MCExpr *Expr = nullptr;
+ SMLoc OffsetLoc = Lexer.getTok().getLoc();
+
+ if (parseExpression(Offset))
+ return true;
+ if (parseToken(AsmToken::Comma, "expected comma") ||
+ check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
+ return true;
+
+ SMLoc NameLoc = Lexer.getTok().getLoc();
+ StringRef Name = Lexer.getTok().getIdentifier();
+ Lex();
+
+ if (Lexer.is(AsmToken::Comma)) {
+ Lex();
+ SMLoc ExprLoc = Lexer.getLoc();
+ if (parseExpression(Expr))
+ return true;
+
+ MCValue Value;
+ if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr))
+ return Error(ExprLoc, "expression must be relocatable");
+ }
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in .reloc directive"))
+ return true;
+
+ const MCTargetAsmParser &MCT = getTargetParser();
+ const MCSubtargetInfo &STI = MCT.getSTI();
+ if (Optional<std::pair<bool, std::string>> Err =
+ getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc,
+ STI))
+ return Error(Err->first ? NameLoc : OffsetLoc, Err->second);
+
+ return false;
+}
+
+/// parseDirectiveValue
+/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
+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;
+ };
+
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ return false;
+}
+
+static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {
+ if (Asm.getTok().isNot(AsmToken::Integer) &&
+ Asm.getTok().isNot(AsmToken::BigNum))
+ return Asm.TokError("unknown token in expression");
+ SMLoc ExprLoc = Asm.getTok().getLoc();
+ APInt IntValue = Asm.getTok().getAPIntVal();
+ Asm.Lex();
+ if (!IntValue.isIntN(128))
+ return Asm.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();
+ }
+ return false;
+}
+
+/// ParseDirectiveOctaValue
+/// ::= .octa [ hexconstant (, hexconstant)* ]
+
+bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
+ auto parseOp = [&]() -> bool {
+ if (checkForValidSection())
+ return true;
+ uint64_t hi, lo;
+ if (parseHexOcta(*this, hi, lo))
+ return true;
+ if (MAI.isLittleEndian()) {
+ getStreamer().emitInt64(lo);
+ getStreamer().emitInt64(hi);
+ } else {
+ getStreamer().emitInt64(hi);
+ getStreamer().emitInt64(lo);
+ }
+ return false;
+ };
+
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ return false;
+}
+
+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();
+
+ 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 (errorToBool(
+ Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
+ .takeError()))
+ 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(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;
+ };
+
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ return false;
+}
+
+/// parseDirectiveZero
+/// ::= .zero expression
+bool AsmParser::parseDirectiveZero() {
+ SMLoc NumBytesLoc = Lexer.getLoc();
+ const MCExpr *NumBytes;
+ if (checkForValidSection() || parseExpression(NumBytes))
+ return true;
+
+ int64_t Val = 0;
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+ if (parseAbsoluteExpression(Val))
+ return true;
+ }
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.zero' directive"))
+ return true;
+ getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);
+
+ return false;
+}
+
+/// parseDirectiveFill
+/// ::= .fill expression [ , expression [ , expression ] ]
+bool AsmParser::parseDirectiveFill() {
+ SMLoc NumValuesLoc = Lexer.getLoc();
+ const MCExpr *NumValues;
+ if (checkForValidSection() || parseExpression(NumValues))
+ return true;
+
+ int64_t FillSize = 1;
+ int64_t FillExpr = 0;
+
+ SMLoc SizeLoc, ExprLoc;
+
+ if (parseOptionalToken(AsmToken::Comma)) {
+ SizeLoc = getTok().getLoc();
+ if (parseAbsoluteExpression(FillSize))
+ return true;
+ 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");
+ return false;
+ }
+ if (FillSize > 8) {
+ Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
+ FillSize = 8;
+ }
+
+ if (!isUInt<32>(FillExpr) && FillSize > 4)
+ Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
+
+ getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);
+
+ return false;
+}
+
+/// parseDirectiveOrg
+/// ::= .org expression [ , expression ]
+bool AsmParser::parseDirectiveOrg() {
+ const MCExpr *Offset;
+ SMLoc OffsetLoc = Lexer.getLoc();
+ if (checkForValidSection() || parseExpression(Offset))
+ return true;
+
+ // Parse optional fill expression.
+ int64_t FillExpr = 0;
+ if (parseOptionalToken(AsmToken::Comma))
+ if (parseAbsoluteExpression(FillExpr))
+ return addErrorSuffix(" in '.org' directive");
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '.org' directive");
+
+ getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
+ return false;
+}
+
+/// parseDirectiveAlign
+/// ::= {.align, ...} expression [ , expression [ , expression ]]
+bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
+ SMLoc AlignmentLoc = getLexer().getLoc();
+ int64_t Alignment;
+ SMLoc MaxBytesLoc;
+ bool HasFillExpr = false;
+ int64_t FillExpr = 0;
+ int64_t MaxBytesToFill = 0;
+
+ auto parseAlign = [&]() -> bool {
+ if (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 (checkForValidSection())
+ return addErrorSuffix(" in directive");
+ // Ignore empty '.p2align' directives for GNU-as compatibility
+ if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
+ Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
+ return parseToken(AsmToken::EndOfStatement);
+ }
+ if (parseAlign())
+ return addErrorSuffix(" in directive");
+
+ // 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) {
+ ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
+ Alignment = 31;
+ }
+
+ Alignment = 1ULL << Alignment;
+ } else {
+ // Reject alignments that aren't either a power of two or zero,
+ // for gas compatibility. Alignment of zero is silently rounded
+ // up to one.
+ if (Alignment == 0)
+ Alignment = 1;
+ if (!isPowerOf2_64(Alignment))
+ ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
if (!isUInt<32>(Alignment))
ReturnVal |= Error(AlignmentLoc, "alignment must be smaller than 2**32");
- }
-
- // Diagnose non-sensical max bytes to align.
- if (MaxBytesLoc.isValid()) {
- if (MaxBytesToFill < 1) {
- ReturnVal |= Error(MaxBytesLoc,
- "alignment directive can never be satisfied in this "
- "many bytes, ignoring maximum bytes expression");
- MaxBytesToFill = 0;
- }
-
- if (MaxBytesToFill >= Alignment) {
- Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
- "has no effect");
- MaxBytesToFill = 0;
- }
- }
-
- // Check whether we should use optimal code alignment for this .align
- // directive.
- const MCSection *Section = getStreamer().getCurrentSectionOnly();
- assert(Section && "must have section to emit alignment");
- bool UseCodeAlign = Section->UseCodeAlign();
- if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
- ValueSize == 1 && UseCodeAlign) {
- getStreamer().emitCodeAlignment(Alignment, MaxBytesToFill);
- } else {
- // FIXME: Target specific behavior about how the "extra" bytes are filled.
- getStreamer().emitValueToAlignment(Alignment, FillExpr, ValueSize,
- MaxBytesToFill);
- }
-
- return ReturnVal;
-}
-
-/// parseDirectiveFile
-/// ::= .file filename
-/// ::= .file number [directory] filename [md5 checksum] [source source-text]
-bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
- // FIXME: I'm not sure what this is.
- int64_t FileNumber = -1;
- if (getLexer().is(AsmToken::Integer)) {
- FileNumber = getTok().getIntVal();
- Lex();
-
- if (FileNumber < 0)
- return TokError("negative file number");
- }
-
- std::string Path;
-
- // Usually the directory and filename together, otherwise just the directory.
- // Allow the strings to have escaped octal character sequence.
- if (check(getTok().isNot(AsmToken::String),
- "unexpected token in '.file' directive") ||
- parseEscapedString(Path))
- return true;
-
- StringRef Directory;
- StringRef Filename;
- std::string FilenameData;
- if (getLexer().is(AsmToken::String)) {
- if (check(FileNumber == -1,
- "explicit path specified, but no file number") ||
- parseEscapedString(FilenameData))
- return true;
- Filename = FilenameData;
- Directory = Path;
- } else {
- Filename = Path;
- }
-
- uint64_t MD5Hi, MD5Lo;
- bool HasMD5 = false;
-
- Optional<StringRef> Source;
- bool HasSource = false;
- std::string SourceString;
-
- while (!parseOptionalToken(AsmToken::EndOfStatement)) {
- StringRef Keyword;
- if (check(getTok().isNot(AsmToken::Identifier),
- "unexpected token in '.file' directive") ||
- parseIdentifier(Keyword))
- return true;
- if (Keyword == "md5") {
- HasMD5 = true;
- if (check(FileNumber == -1,
- "MD5 checksum specified, but no file number") ||
- parseHexOcta(*this, MD5Hi, MD5Lo))
- return true;
- } else if (Keyword == "source") {
- HasSource = true;
- if (check(FileNumber == -1,
- "source specified, but no file number") ||
- check(getTok().isNot(AsmToken::String),
- "unexpected token in '.file' directive") ||
- parseEscapedString(SourceString))
- return true;
- } else {
- return TokError("unexpected token in '.file' directive");
- }
- }
-
- if (FileNumber == -1) {
- // Ignore the directive if there is no number and the target doesn't support
- // numberless .file directives. This allows some portability of assembler
- // between different object file formats.
- if (getContext().getAsmInfo()->hasSingleParameterDotFile())
- getStreamer().emitFileDirective(Filename);
- } else {
- // In case there is a -g option as well as debug info from directive .file,
- // we turn off the -g option, directly use the existing debug info instead.
- // Throw away any implicit file table for the assembler source.
- if (Ctx.getGenDwarfForAssembly()) {
- Ctx.getMCDwarfLineTable(0).resetFileTable();
- Ctx.setGenDwarfForAssembly(false);
- }
-
- Optional<MD5::MD5Result> CKMem;
- if (HasMD5) {
- MD5::MD5Result Sum;
- for (unsigned i = 0; i != 8; ++i) {
- Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
- Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
- }
- CKMem = Sum;
- }
- if (HasSource) {
- char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
- memcpy(SourceBuf, SourceString.data(), SourceString.size());
- Source = StringRef(SourceBuf, SourceString.size());
- }
- if (FileNumber == 0) {
- if (Ctx.getDwarfVersion() < 5)
- return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5");
- getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
- } else {
- Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
- FileNumber, Directory, Filename, CKMem, Source);
- if (!FileNumOrErr)
- return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
- }
- // Alert the user if there are some .file directives with MD5 and some not.
- // But only do that once.
- if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
- ReportedInconsistentMD5 = true;
- return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
- }
- }
-
- return false;
-}
-
-/// parseDirectiveLine
-/// ::= .line [number]
-bool AsmParser::parseDirectiveLine() {
- int64_t LineNumber;
- if (getLexer().is(AsmToken::Integer)) {
- if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
- return true;
- (void)LineNumber;
- // FIXME: Do something with the .line.
- }
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.line' directive"))
- return true;
-
- return false;
-}
-
-/// parseDirectiveLoc
-/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
-/// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
-/// The first number is a file number, must have been previously assigned with
-/// a .file directive, the second number is the line number and optionally the
-/// third number is a column position (zero if not specified). The remaining
-/// optional items are .loc sub-directives.
-bool AsmParser::parseDirectiveLoc() {
- int64_t FileNumber = 0, LineNumber = 0;
- SMLoc Loc = getTok().getLoc();
- if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
- check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
- "file number less than one in '.loc' directive") ||
- check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
- "unassigned file number in '.loc' directive"))
- return true;
-
- // optional
- if (getLexer().is(AsmToken::Integer)) {
- LineNumber = getTok().getIntVal();
- if (LineNumber < 0)
- return TokError("line number less than zero in '.loc' directive");
- Lex();
- }
-
- int64_t ColumnPos = 0;
- if (getLexer().is(AsmToken::Integer)) {
- ColumnPos = getTok().getIntVal();
- if (ColumnPos < 0)
- return TokError("column position less than zero in '.loc' directive");
- Lex();
- }
-
- auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
- unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
- unsigned Isa = 0;
- int64_t Discriminator = 0;
-
- 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, "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;
- } else {
- return Error(Loc, "unknown sub-directive in '.loc' directive");
- }
- return false;
- };
-
- if (parseMany(parseLocOp, false /*hasComma*/))
- return true;
-
- getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
- Isa, Discriminator, StringRef());
-
- return false;
-}
-
-/// parseDirectiveStabs
-/// ::= .stabs string, number, number, number
-bool AsmParser::parseDirectiveStabs() {
- return TokError("unsupported directive '.stabs'");
-}
-
-/// parseDirectiveCVFile
-/// ::= .cv_file number filename [checksum] [checksumkind]
-bool AsmParser::parseDirectiveCVFile() {
- SMLoc FileNumberLoc = getTok().getLoc();
- int64_t FileNumber;
- std::string Filename;
- std::string Checksum;
- int64_t ChecksumKind = 0;
-
- if (parseIntToken(FileNumber,
- "expected file number in '.cv_file' directive") ||
- check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
- check(getTok().isNot(AsmToken::String),
- "unexpected token in '.cv_file' directive") ||
- parseEscapedString(Filename))
- return true;
- if (!parseOptionalToken(AsmToken::EndOfStatement)) {
- if (check(getTok().isNot(AsmToken::String),
- "unexpected token in '.cv_file' directive") ||
- parseEscapedString(Checksum) ||
- parseIntToken(ChecksumKind,
- "expected checksum kind in '.cv_file' directive") ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.cv_file' directive"))
- return true;
- }
-
- Checksum = fromHex(Checksum);
- void *CKMem = Ctx.allocate(Checksum.size(), 1);
- memcpy(CKMem, Checksum.data(), Checksum.size());
- ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
- Checksum.size());
-
- if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
- static_cast<uint8_t>(ChecksumKind)))
- return Error(FileNumberLoc, "file number already allocated");
-
- return false;
-}
-
-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;
-}
-
-/// parseDirectiveCVLoc
-/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
-/// [is_stmt VALUE]
-/// The first number is a file number, must have been previously assigned with
-/// a .file directive, the second number is the line number and optionally the
-/// 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();
- int64_t FunctionId, FileNumber;
- if (parseCVFunctionId(FunctionId, ".cv_loc") ||
- parseCVFileId(FileNumber, ".cv_loc"))
- return true;
-
- int64_t LineNumber = 0;
- if (getLexer().is(AsmToken::Integer)) {
- LineNumber = getTok().getIntVal();
- if (LineNumber < 0)
- return TokError("line number less than zero in '.cv_loc' directive");
- Lex();
- }
-
- int64_t ColumnPos = 0;
- if (getLexer().is(AsmToken::Integer)) {
- ColumnPos = getTok().getIntVal();
- if (ColumnPos < 0)
- return TokError("column position less than zero in '.cv_loc' directive");
- Lex();
- }
-
- bool PrologueEnd = false;
- uint64_t IsStmt = 0;
-
- 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") {
- Loc = getTok().getLoc();
- const MCExpr *Value;
- if (parseExpression(Value))
- return true;
- // The expression must be the constant 0 or 1.
- IsStmt = ~0ULL;
- if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
- IsStmt = MCE->getValue();
-
- if (IsStmt > 1)
- return Error(Loc, "is_stmt value not 0 or 1");
- } else {
- return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
- }
- return false;
- };
-
- if (parseMany(parseOp, false /*hasComma*/))
- return true;
-
- getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
- ColumnPos, PrologueEnd, IsStmt, StringRef(),
- DirectiveLoc);
- return false;
-}
-
-/// parseDirectiveCVLinetable
-/// ::= .cv_linetable FunctionId, FnStart, FnEnd
-bool AsmParser::parseDirectiveCVLinetable() {
- int64_t FunctionId;
- StringRef FnStartName, FnEndName;
- SMLoc Loc = getTok().getLoc();
- if (parseCVFunctionId(FunctionId, ".cv_linetable") ||
- parseToken(AsmToken::Comma,
- "unexpected token in '.cv_linetable' directive") ||
- parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
- "expected identifier in directive") ||
- parseToken(AsmToken::Comma,
- "unexpected token in '.cv_linetable' directive") ||
- parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
- "expected identifier in directive"))
- return true;
-
- MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
- MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
-
- getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
- return false;
-}
-
-/// parseDirectiveCVInlineLinetable
-/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
-bool AsmParser::parseDirectiveCVInlineLinetable() {
- int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
- StringRef FnStartName, FnEndName;
- SMLoc Loc = getTok().getLoc();
- 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") ||
- 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") ||
- parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
- "expected identifier in directive") ||
- parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
- "expected identifier in directive"))
- return true;
-
- if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
- return true;
-
- MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
- MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
- getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
- SourceLineNum, FnStartSym,
- FnEndSym);
- return false;
-}
-
-void AsmParser::initializeCVDefRangeTypeMap() {
- CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
- CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
- CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
- CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
-}
-
-/// parseDirectiveCVDefRange
-/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
-bool AsmParser::parseDirectiveCVDefRange() {
- SMLoc Loc;
- std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
- while (getLexer().is(AsmToken::Identifier)) {
- Loc = getLexer().getLoc();
- StringRef GapStartName;
- if (parseIdentifier(GapStartName))
- return Error(Loc, "expected identifier in directive");
- MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
-
- Loc = getLexer().getLoc();
- StringRef GapEndName;
- if (parseIdentifier(GapEndName))
- return Error(Loc, "expected identifier in directive");
- MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
-
- Ranges.push_back({GapStartSym, GapEndSym});
- }
-
- StringRef CVDefRangeTypeStr;
- if (parseToken(
- AsmToken::Comma,
- "expected comma before def_range type in .cv_def_range directive") ||
- parseIdentifier(CVDefRangeTypeStr))
- return Error(Loc, "expected def_range type in directive");
-
- StringMap<CVDefRangeType>::const_iterator CVTypeIt =
- CVDefRangeTypeMap.find(CVDefRangeTypeStr);
- CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
- ? CVDR_DEFRANGE
- : CVTypeIt->getValue();
- switch (CVDRType) {
- case CVDR_DEFRANGE_REGISTER: {
- int64_t DRRegister;
- if (parseToken(AsmToken::Comma, "expected comma before register number in "
- ".cv_def_range directive") ||
- parseAbsoluteExpression(DRRegister))
- return Error(Loc, "expected register number");
-
- codeview::DefRangeRegisterHeader DRHdr;
- DRHdr.Register = DRRegister;
- DRHdr.MayHaveNoName = 0;
- getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
- break;
- }
- case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
- int64_t DROffset;
- if (parseToken(AsmToken::Comma,
- "expected comma before offset in .cv_def_range directive") ||
- parseAbsoluteExpression(DROffset))
- return Error(Loc, "expected offset value");
-
- codeview::DefRangeFramePointerRelHeader DRHdr;
- DRHdr.Offset = DROffset;
- getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
- break;
- }
- case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
- int64_t DRRegister;
- int64_t DROffsetInParent;
- if (parseToken(AsmToken::Comma, "expected comma before register number in "
- ".cv_def_range directive") ||
- parseAbsoluteExpression(DRRegister))
- return Error(Loc, "expected register number");
- if (parseToken(AsmToken::Comma,
- "expected comma before offset in .cv_def_range directive") ||
- parseAbsoluteExpression(DROffsetInParent))
- return Error(Loc, "expected offset value");
-
- codeview::DefRangeSubfieldRegisterHeader DRHdr;
- DRHdr.Register = DRRegister;
- DRHdr.MayHaveNoName = 0;
- DRHdr.OffsetInParent = DROffsetInParent;
- getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
- break;
- }
- case CVDR_DEFRANGE_REGISTER_REL: {
- int64_t DRRegister;
- int64_t DRFlags;
- int64_t DRBasePointerOffset;
- if (parseToken(AsmToken::Comma, "expected comma before register number in "
- ".cv_def_range directive") ||
- parseAbsoluteExpression(DRRegister))
- return Error(Loc, "expected register value");
- if (parseToken(
- AsmToken::Comma,
- "expected comma before flag value in .cv_def_range directive") ||
- parseAbsoluteExpression(DRFlags))
- return Error(Loc, "expected flag value");
- if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
- "in .cv_def_range directive") ||
- parseAbsoluteExpression(DRBasePointerOffset))
- return Error(Loc, "expected base pointer offset value");
-
- codeview::DefRangeRegisterRelHeader DRHdr;
- DRHdr.Register = DRRegister;
- DRHdr.Flags = DRFlags;
- DRHdr.BasePointerOffset = DRBasePointerOffset;
- getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
- break;
- }
- default:
- return Error(Loc, "unexpected def_range type in .cv_def_range directive");
- }
- return true;
-}
-
-/// parseDirectiveCVString
-/// ::= .cv_stringtable "string"
-bool AsmParser::parseDirectiveCVString() {
- std::string Data;
- if (checkForValidSection() || parseEscapedString(Data))
- return addErrorSuffix(" in '.cv_string' directive");
-
- // Put the string in the table and emit the offset.
- std::pair<StringRef, unsigned> Insertion =
- getCVContext().addToStringTable(Data);
- getStreamer().emitInt32(Insertion.second);
- return false;
-}
-
-/// parseDirectiveCVStringTable
-/// ::= .cv_stringtable
-bool AsmParser::parseDirectiveCVStringTable() {
- getStreamer().emitCVStringTableDirective();
- return false;
-}
-
-/// parseDirectiveCVFileChecksums
-/// ::= .cv_filechecksums
-bool AsmParser::parseDirectiveCVFileChecksums() {
- getStreamer().emitCVFileChecksumsDirective();
- return false;
-}
-
-/// parseDirectiveCVFileChecksumOffset
-/// ::= .cv_filechecksumoffset fileno
-bool AsmParser::parseDirectiveCVFileChecksumOffset() {
- int64_t FileNo;
- if (parseIntToken(FileNo, "expected identifier in directive"))
- return true;
- if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
- return true;
- getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
- return false;
-}
-
-/// parseDirectiveCVFPOData
-/// ::= .cv_fpo_data procsym
-bool AsmParser::parseDirectiveCVFPOData() {
- SMLoc DirLoc = getLexer().getLoc();
- StringRef ProcName;
- if (parseIdentifier(ProcName))
- return TokError("expected symbol name");
- if (parseEOL("unexpected tokens"))
- return addErrorSuffix(" in '.cv_fpo_data' directive");
- MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
- getStreamer().EmitCVFPOData(ProcSym, DirLoc);
- return false;
-}
-
-/// parseDirectiveCFISections
-/// ::= .cfi_sections section [, section]
-bool AsmParser::parseDirectiveCFISections() {
- StringRef Name;
- bool EH = false;
- bool Debug = false;
-
- if (parseIdentifier(Name))
- return TokError("Expected an identifier");
-
- if (Name == ".eh_frame")
- EH = true;
- else if (Name == ".debug_frame")
- Debug = true;
-
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
-
- if (parseIdentifier(Name))
- return TokError("Expected an identifier");
-
- if (Name == ".eh_frame")
- EH = true;
- else if (Name == ".debug_frame")
- Debug = true;
- }
-
+ }
+
+ // Diagnose non-sensical max bytes to align.
+ if (MaxBytesLoc.isValid()) {
+ if (MaxBytesToFill < 1) {
+ ReturnVal |= Error(MaxBytesLoc,
+ "alignment directive can never be satisfied in this "
+ "many bytes, ignoring maximum bytes expression");
+ MaxBytesToFill = 0;
+ }
+
+ if (MaxBytesToFill >= Alignment) {
+ Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
+ "has no effect");
+ MaxBytesToFill = 0;
+ }
+ }
+
+ // Check whether we should use optimal code alignment for this .align
+ // directive.
+ const MCSection *Section = getStreamer().getCurrentSectionOnly();
+ assert(Section && "must have section to emit alignment");
+ bool UseCodeAlign = Section->UseCodeAlign();
+ if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
+ ValueSize == 1 && UseCodeAlign) {
+ getStreamer().emitCodeAlignment(Alignment, MaxBytesToFill);
+ } else {
+ // FIXME: Target specific behavior about how the "extra" bytes are filled.
+ getStreamer().emitValueToAlignment(Alignment, FillExpr, ValueSize,
+ MaxBytesToFill);
+ }
+
+ return ReturnVal;
+}
+
+/// parseDirectiveFile
+/// ::= .file filename
+/// ::= .file number [directory] filename [md5 checksum] [source source-text]
+bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
+ // FIXME: I'm not sure what this is.
+ int64_t FileNumber = -1;
+ if (getLexer().is(AsmToken::Integer)) {
+ FileNumber = getTok().getIntVal();
+ Lex();
+
+ if (FileNumber < 0)
+ return TokError("negative file number");
+ }
+
+ std::string Path;
+
+ // Usually the directory and filename together, otherwise just the directory.
+ // Allow the strings to have escaped octal character sequence.
+ if (check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.file' directive") ||
+ parseEscapedString(Path))
+ return true;
+
+ StringRef Directory;
+ StringRef Filename;
+ std::string FilenameData;
+ if (getLexer().is(AsmToken::String)) {
+ if (check(FileNumber == -1,
+ "explicit path specified, but no file number") ||
+ parseEscapedString(FilenameData))
+ return true;
+ Filename = FilenameData;
+ Directory = Path;
+ } else {
+ Filename = Path;
+ }
+
+ uint64_t MD5Hi, MD5Lo;
+ bool HasMD5 = false;
+
+ Optional<StringRef> Source;
+ bool HasSource = false;
+ std::string SourceString;
+
+ while (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ StringRef Keyword;
+ if (check(getTok().isNot(AsmToken::Identifier),
+ "unexpected token in '.file' directive") ||
+ parseIdentifier(Keyword))
+ return true;
+ if (Keyword == "md5") {
+ HasMD5 = true;
+ if (check(FileNumber == -1,
+ "MD5 checksum specified, but no file number") ||
+ parseHexOcta(*this, MD5Hi, MD5Lo))
+ return true;
+ } else if (Keyword == "source") {
+ HasSource = true;
+ if (check(FileNumber == -1,
+ "source specified, but no file number") ||
+ check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.file' directive") ||
+ parseEscapedString(SourceString))
+ return true;
+ } else {
+ return TokError("unexpected token in '.file' directive");
+ }
+ }
+
+ if (FileNumber == -1) {
+ // Ignore the directive if there is no number and the target doesn't support
+ // numberless .file directives. This allows some portability of assembler
+ // between different object file formats.
+ if (getContext().getAsmInfo()->hasSingleParameterDotFile())
+ getStreamer().emitFileDirective(Filename);
+ } else {
+ // In case there is a -g option as well as debug info from directive .file,
+ // we turn off the -g option, directly use the existing debug info instead.
+ // Throw away any implicit file table for the assembler source.
+ if (Ctx.getGenDwarfForAssembly()) {
+ Ctx.getMCDwarfLineTable(0).resetFileTable();
+ Ctx.setGenDwarfForAssembly(false);
+ }
+
+ Optional<MD5::MD5Result> CKMem;
+ if (HasMD5) {
+ MD5::MD5Result Sum;
+ for (unsigned i = 0; i != 8; ++i) {
+ Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
+ Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
+ }
+ CKMem = Sum;
+ }
+ if (HasSource) {
+ char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
+ memcpy(SourceBuf, SourceString.data(), SourceString.size());
+ Source = StringRef(SourceBuf, SourceString.size());
+ }
+ if (FileNumber == 0) {
+ if (Ctx.getDwarfVersion() < 5)
+ return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5");
+ getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
+ } else {
+ Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
+ FileNumber, Directory, Filename, CKMem, Source);
+ if (!FileNumOrErr)
+ return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
+ }
+ // Alert the user if there are some .file directives with MD5 and some not.
+ // But only do that once.
+ if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
+ ReportedInconsistentMD5 = true;
+ return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
+ }
+ }
+
+ return false;
+}
+
+/// parseDirectiveLine
+/// ::= .line [number]
+bool AsmParser::parseDirectiveLine() {
+ int64_t LineNumber;
+ if (getLexer().is(AsmToken::Integer)) {
+ if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
+ return true;
+ (void)LineNumber;
+ // FIXME: Do something with the .line.
+ }
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.line' directive"))
+ return true;
+
+ return false;
+}
+
+/// parseDirectiveLoc
+/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
+/// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
+/// The first number is a file number, must have been previously assigned with
+/// a .file directive, the second number is the line number and optionally the
+/// third number is a column position (zero if not specified). The remaining
+/// optional items are .loc sub-directives.
+bool AsmParser::parseDirectiveLoc() {
+ int64_t FileNumber = 0, LineNumber = 0;
+ SMLoc Loc = getTok().getLoc();
+ if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
+ check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
+ "file number less than one in '.loc' directive") ||
+ check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
+ "unassigned file number in '.loc' directive"))
+ return true;
+
+ // optional
+ if (getLexer().is(AsmToken::Integer)) {
+ LineNumber = getTok().getIntVal();
+ if (LineNumber < 0)
+ return TokError("line number less than zero in '.loc' directive");
+ Lex();
+ }
+
+ int64_t ColumnPos = 0;
+ if (getLexer().is(AsmToken::Integer)) {
+ ColumnPos = getTok().getIntVal();
+ if (ColumnPos < 0)
+ return TokError("column position less than zero in '.loc' directive");
+ Lex();
+ }
+
+ auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
+ unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
+ unsigned Isa = 0;
+ int64_t Discriminator = 0;
+
+ 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, "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;
+ } else {
+ return Error(Loc, "unknown sub-directive in '.loc' directive");
+ }
+ return false;
+ };
+
+ if (parseMany(parseLocOp, false /*hasComma*/))
+ return true;
+
+ getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
+ Isa, Discriminator, StringRef());
+
+ return false;
+}
+
+/// parseDirectiveStabs
+/// ::= .stabs string, number, number, number
+bool AsmParser::parseDirectiveStabs() {
+ return TokError("unsupported directive '.stabs'");
+}
+
+/// parseDirectiveCVFile
+/// ::= .cv_file number filename [checksum] [checksumkind]
+bool AsmParser::parseDirectiveCVFile() {
+ SMLoc FileNumberLoc = getTok().getLoc();
+ int64_t FileNumber;
+ std::string Filename;
+ std::string Checksum;
+ int64_t ChecksumKind = 0;
+
+ if (parseIntToken(FileNumber,
+ "expected file number in '.cv_file' directive") ||
+ check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
+ check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.cv_file' directive") ||
+ parseEscapedString(Filename))
+ return true;
+ if (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ if (check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.cv_file' directive") ||
+ parseEscapedString(Checksum) ||
+ parseIntToken(ChecksumKind,
+ "expected checksum kind in '.cv_file' directive") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cv_file' directive"))
+ return true;
+ }
+
+ Checksum = fromHex(Checksum);
+ void *CKMem = Ctx.allocate(Checksum.size(), 1);
+ memcpy(CKMem, Checksum.data(), Checksum.size());
+ ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
+ Checksum.size());
+
+ if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
+ static_cast<uint8_t>(ChecksumKind)))
+ return Error(FileNumberLoc, "file number already allocated");
+
+ return false;
+}
+
+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;
+}
+
+/// parseDirectiveCVLoc
+/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
+/// [is_stmt VALUE]
+/// The first number is a file number, must have been previously assigned with
+/// a .file directive, the second number is the line number and optionally the
+/// 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();
+ int64_t FunctionId, FileNumber;
+ if (parseCVFunctionId(FunctionId, ".cv_loc") ||
+ parseCVFileId(FileNumber, ".cv_loc"))
+ return true;
+
+ int64_t LineNumber = 0;
+ if (getLexer().is(AsmToken::Integer)) {
+ LineNumber = getTok().getIntVal();
+ if (LineNumber < 0)
+ return TokError("line number less than zero in '.cv_loc' directive");
+ Lex();
+ }
+
+ int64_t ColumnPos = 0;
+ if (getLexer().is(AsmToken::Integer)) {
+ ColumnPos = getTok().getIntVal();
+ if (ColumnPos < 0)
+ return TokError("column position less than zero in '.cv_loc' directive");
+ Lex();
+ }
+
+ bool PrologueEnd = false;
+ uint64_t IsStmt = 0;
+
+ 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") {
+ Loc = getTok().getLoc();
+ const MCExpr *Value;
+ if (parseExpression(Value))
+ return true;
+ // The expression must be the constant 0 or 1.
+ IsStmt = ~0ULL;
+ if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
+ IsStmt = MCE->getValue();
+
+ if (IsStmt > 1)
+ return Error(Loc, "is_stmt value not 0 or 1");
+ } else {
+ return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
+ }
+ return false;
+ };
+
+ if (parseMany(parseOp, false /*hasComma*/))
+ return true;
+
+ getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
+ ColumnPos, PrologueEnd, IsStmt, StringRef(),
+ DirectiveLoc);
+ return false;
+}
+
+/// parseDirectiveCVLinetable
+/// ::= .cv_linetable FunctionId, FnStart, FnEnd
+bool AsmParser::parseDirectiveCVLinetable() {
+ int64_t FunctionId;
+ StringRef FnStartName, FnEndName;
+ SMLoc Loc = getTok().getLoc();
+ if (parseCVFunctionId(FunctionId, ".cv_linetable") ||
+ parseToken(AsmToken::Comma,
+ "unexpected token in '.cv_linetable' directive") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
+ "expected identifier in directive") ||
+ parseToken(AsmToken::Comma,
+ "unexpected token in '.cv_linetable' directive") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
+ "expected identifier in directive"))
+ return true;
+
+ MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
+ MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
+
+ getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
+ return false;
+}
+
+/// parseDirectiveCVInlineLinetable
+/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
+bool AsmParser::parseDirectiveCVInlineLinetable() {
+ int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
+ StringRef FnStartName, FnEndName;
+ SMLoc Loc = getTok().getLoc();
+ 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") ||
+ 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") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
+ "expected identifier in directive") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
+ "expected identifier in directive"))
+ return true;
+
+ if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
+ return true;
+
+ MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
+ MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
+ getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
+ SourceLineNum, FnStartSym,
+ FnEndSym);
+ return false;
+}
+
+void AsmParser::initializeCVDefRangeTypeMap() {
+ CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
+ CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
+ CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
+ CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
+}
+
+/// parseDirectiveCVDefRange
+/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
+bool AsmParser::parseDirectiveCVDefRange() {
+ SMLoc Loc;
+ std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
+ while (getLexer().is(AsmToken::Identifier)) {
+ Loc = getLexer().getLoc();
+ StringRef GapStartName;
+ if (parseIdentifier(GapStartName))
+ return Error(Loc, "expected identifier in directive");
+ MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
+
+ Loc = getLexer().getLoc();
+ StringRef GapEndName;
+ if (parseIdentifier(GapEndName))
+ return Error(Loc, "expected identifier in directive");
+ MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
+
+ Ranges.push_back({GapStartSym, GapEndSym});
+ }
+
+ StringRef CVDefRangeTypeStr;
+ if (parseToken(
+ AsmToken::Comma,
+ "expected comma before def_range type in .cv_def_range directive") ||
+ parseIdentifier(CVDefRangeTypeStr))
+ return Error(Loc, "expected def_range type in directive");
+
+ StringMap<CVDefRangeType>::const_iterator CVTypeIt =
+ CVDefRangeTypeMap.find(CVDefRangeTypeStr);
+ CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
+ ? CVDR_DEFRANGE
+ : CVTypeIt->getValue();
+ switch (CVDRType) {
+ case CVDR_DEFRANGE_REGISTER: {
+ int64_t DRRegister;
+ if (parseToken(AsmToken::Comma, "expected comma before register number in "
+ ".cv_def_range directive") ||
+ parseAbsoluteExpression(DRRegister))
+ return Error(Loc, "expected register number");
+
+ codeview::DefRangeRegisterHeader DRHdr;
+ DRHdr.Register = DRRegister;
+ DRHdr.MayHaveNoName = 0;
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
+ int64_t DROffset;
+ if (parseToken(AsmToken::Comma,
+ "expected comma before offset in .cv_def_range directive") ||
+ parseAbsoluteExpression(DROffset))
+ return Error(Loc, "expected offset value");
+
+ codeview::DefRangeFramePointerRelHeader DRHdr;
+ DRHdr.Offset = DROffset;
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
+ int64_t DRRegister;
+ int64_t DROffsetInParent;
+ if (parseToken(AsmToken::Comma, "expected comma before register number in "
+ ".cv_def_range directive") ||
+ parseAbsoluteExpression(DRRegister))
+ return Error(Loc, "expected register number");
+ if (parseToken(AsmToken::Comma,
+ "expected comma before offset in .cv_def_range directive") ||
+ parseAbsoluteExpression(DROffsetInParent))
+ return Error(Loc, "expected offset value");
+
+ codeview::DefRangeSubfieldRegisterHeader DRHdr;
+ DRHdr.Register = DRRegister;
+ DRHdr.MayHaveNoName = 0;
+ DRHdr.OffsetInParent = DROffsetInParent;
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ case CVDR_DEFRANGE_REGISTER_REL: {
+ int64_t DRRegister;
+ int64_t DRFlags;
+ int64_t DRBasePointerOffset;
+ if (parseToken(AsmToken::Comma, "expected comma before register number in "
+ ".cv_def_range directive") ||
+ parseAbsoluteExpression(DRRegister))
+ return Error(Loc, "expected register value");
+ if (parseToken(
+ AsmToken::Comma,
+ "expected comma before flag value in .cv_def_range directive") ||
+ parseAbsoluteExpression(DRFlags))
+ return Error(Loc, "expected flag value");
+ if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
+ "in .cv_def_range directive") ||
+ parseAbsoluteExpression(DRBasePointerOffset))
+ return Error(Loc, "expected base pointer offset value");
+
+ codeview::DefRangeRegisterRelHeader DRHdr;
+ DRHdr.Register = DRRegister;
+ DRHdr.Flags = DRFlags;
+ DRHdr.BasePointerOffset = DRBasePointerOffset;
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ default:
+ return Error(Loc, "unexpected def_range type in .cv_def_range directive");
+ }
+ return true;
+}
+
+/// parseDirectiveCVString
+/// ::= .cv_stringtable "string"
+bool AsmParser::parseDirectiveCVString() {
+ std::string Data;
+ if (checkForValidSection() || parseEscapedString(Data))
+ return addErrorSuffix(" in '.cv_string' directive");
+
+ // Put the string in the table and emit the offset.
+ std::pair<StringRef, unsigned> Insertion =
+ getCVContext().addToStringTable(Data);
+ getStreamer().emitInt32(Insertion.second);
+ return false;
+}
+
+/// parseDirectiveCVStringTable
+/// ::= .cv_stringtable
+bool AsmParser::parseDirectiveCVStringTable() {
+ getStreamer().emitCVStringTableDirective();
+ return false;
+}
+
+/// parseDirectiveCVFileChecksums
+/// ::= .cv_filechecksums
+bool AsmParser::parseDirectiveCVFileChecksums() {
+ getStreamer().emitCVFileChecksumsDirective();
+ return false;
+}
+
+/// parseDirectiveCVFileChecksumOffset
+/// ::= .cv_filechecksumoffset fileno
+bool AsmParser::parseDirectiveCVFileChecksumOffset() {
+ int64_t FileNo;
+ if (parseIntToken(FileNo, "expected identifier in directive"))
+ return true;
+ if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
+ return true;
+ getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
+ return false;
+}
+
+/// parseDirectiveCVFPOData
+/// ::= .cv_fpo_data procsym
+bool AsmParser::parseDirectiveCVFPOData() {
+ SMLoc DirLoc = getLexer().getLoc();
+ StringRef ProcName;
+ if (parseIdentifier(ProcName))
+ return TokError("expected symbol name");
+ if (parseEOL("unexpected tokens"))
+ return addErrorSuffix(" in '.cv_fpo_data' directive");
+ MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
+ getStreamer().EmitCVFPOData(ProcSym, DirLoc);
+ return false;
+}
+
+/// parseDirectiveCFISections
+/// ::= .cfi_sections section [, section]
+bool AsmParser::parseDirectiveCFISections() {
+ StringRef Name;
+ bool EH = false;
+ bool Debug = false;
+
+ if (parseIdentifier(Name))
+ return TokError("Expected an identifier");
+
+ if (Name == ".eh_frame")
+ EH = true;
+ else if (Name == ".debug_frame")
+ Debug = true;
+
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+
+ if (parseIdentifier(Name))
+ return TokError("Expected an identifier");
+
+ if (Name == ".eh_frame")
+ EH = true;
+ else if (Name == ".debug_frame")
+ Debug = true;
+ }
+
if (parseToken(AsmToken::EndOfStatement))
return addErrorSuffix(" in '.cfi_sections' directive");
- getStreamer().emitCFISections(EH, Debug);
- return false;
-}
-
-/// parseDirectiveCFIStartProc
-/// ::= .cfi_startproc [simple]
-bool AsmParser::parseDirectiveCFIStartProc() {
- StringRef Simple;
- if (!parseOptionalToken(AsmToken::EndOfStatement)) {
- if (check(parseIdentifier(Simple) || Simple != "simple",
- "unexpected token") ||
- parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in '.cfi_startproc' directive");
- }
-
- // TODO(kristina): Deal with a corner case of incorrect diagnostic context
- // being produced if this directive is emitted as part of preprocessor macro
- // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
- // Tools like llvm-mc on the other hand are not affected by it, and report
- // correct context information.
- getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
- return false;
-}
-
-/// parseDirectiveCFIEndProc
-/// ::= .cfi_endproc
-bool AsmParser::parseDirectiveCFIEndProc() {
+ getStreamer().emitCFISections(EH, Debug);
+ return false;
+}
+
+/// parseDirectiveCFIStartProc
+/// ::= .cfi_startproc [simple]
+bool AsmParser::parseDirectiveCFIStartProc() {
+ StringRef Simple;
+ if (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ if (check(parseIdentifier(Simple) || Simple != "simple",
+ "unexpected token") ||
+ parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '.cfi_startproc' directive");
+ }
+
+ // TODO(kristina): Deal with a corner case of incorrect diagnostic context
+ // being produced if this directive is emitted as part of preprocessor macro
+ // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
+ // Tools like llvm-mc on the other hand are not affected by it, and report
+ // correct context information.
+ getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
+ return false;
+}
+
+/// parseDirectiveCFIEndProc
+/// ::= .cfi_endproc
+bool AsmParser::parseDirectiveCFIEndProc() {
if (parseToken(AsmToken::EndOfStatement))
return addErrorSuffix(" in '.cfi_endproc' directive");
- getStreamer().emitCFIEndProc();
- return false;
-}
-
-/// parse register name or number.
-bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
- SMLoc DirectiveLoc) {
- unsigned RegNo;
-
- if (getLexer().isNot(AsmToken::Integer)) {
- if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc))
- return true;
- Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
- } else
- return parseAbsoluteExpression(Register);
-
- return false;
-}
-
-/// parseDirectiveCFIDefCfa
-/// ::= .cfi_def_cfa register, offset
-bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
- int64_t Register = 0, Offset = 0;
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseAbsoluteExpression(Offset))
- return true;
-
- getStreamer().emitCFIDefCfa(Register, Offset);
- return false;
-}
-
-/// parseDirectiveCFIDefCfaOffset
-/// ::= .cfi_def_cfa_offset offset
-bool AsmParser::parseDirectiveCFIDefCfaOffset() {
- int64_t Offset = 0;
- if (parseAbsoluteExpression(Offset))
- return true;
-
- getStreamer().emitCFIDefCfaOffset(Offset);
- return false;
-}
-
-/// parseDirectiveCFIRegister
-/// ::= .cfi_register register, register
-bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
- int64_t Register1 = 0, Register2 = 0;
- if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseRegisterOrRegisterNumber(Register2, DirectiveLoc))
- return true;
-
- getStreamer().emitCFIRegister(Register1, Register2);
- return false;
-}
-
-/// parseDirectiveCFIWindowSave
-/// ::= .cfi_window_save
-bool AsmParser::parseDirectiveCFIWindowSave() {
- getStreamer().emitCFIWindowSave();
- return false;
-}
-
-/// parseDirectiveCFIAdjustCfaOffset
-/// ::= .cfi_adjust_cfa_offset adjustment
-bool AsmParser::parseDirectiveCFIAdjustCfaOffset() {
- int64_t Adjustment = 0;
- if (parseAbsoluteExpression(Adjustment))
- return true;
-
- getStreamer().emitCFIAdjustCfaOffset(Adjustment);
- return false;
-}
-
-/// parseDirectiveCFIDefCfaRegister
-/// ::= .cfi_def_cfa_register register
-bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
- int64_t Register = 0;
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
-
- getStreamer().emitCFIDefCfaRegister(Register);
- return false;
-}
-
-/// parseDirectiveCFIOffset
-/// ::= .cfi_offset register, offset
-bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
- int64_t Register = 0;
- int64_t Offset = 0;
-
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseAbsoluteExpression(Offset))
- return true;
-
- getStreamer().emitCFIOffset(Register, Offset);
- return false;
-}
-
-/// parseDirectiveCFIRelOffset
-/// ::= .cfi_rel_offset register, offset
-bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
- int64_t Register = 0, Offset = 0;
-
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseAbsoluteExpression(Offset))
- return true;
-
- getStreamer().emitCFIRelOffset(Register, Offset);
- return false;
-}
-
-static bool isValidEncoding(int64_t Encoding) {
- if (Encoding & ~0xff)
- return false;
-
- if (Encoding == dwarf::DW_EH_PE_omit)
- return true;
-
- const unsigned Format = Encoding & 0xf;
- if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
- Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
- Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
- Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
- return false;
-
- const unsigned Application = Encoding & 0x70;
- if (Application != dwarf::DW_EH_PE_absptr &&
- Application != dwarf::DW_EH_PE_pcrel)
- return false;
-
- return true;
-}
-
-/// parseDirectiveCFIPersonalityOrLsda
-/// IsPersonality true for cfi_personality, false for cfi_lsda
-/// ::= .cfi_personality encoding, [symbol_name]
-/// ::= .cfi_lsda encoding, [symbol_name]
-bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
- int64_t Encoding = 0;
- if (parseAbsoluteExpression(Encoding))
- return true;
- if (Encoding == dwarf::DW_EH_PE_omit)
- return false;
-
- StringRef Name;
- if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- check(parseIdentifier(Name), "expected identifier in directive"))
- return true;
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (IsPersonality)
- getStreamer().emitCFIPersonality(Sym, Encoding);
- else
- getStreamer().emitCFILsda(Sym, Encoding);
- return false;
-}
-
-/// parseDirectiveCFIRememberState
-/// ::= .cfi_remember_state
-bool AsmParser::parseDirectiveCFIRememberState() {
- getStreamer().emitCFIRememberState();
- return false;
-}
-
-/// parseDirectiveCFIRestoreState
-/// ::= .cfi_remember_state
-bool AsmParser::parseDirectiveCFIRestoreState() {
- getStreamer().emitCFIRestoreState();
- return false;
-}
-
-/// parseDirectiveCFISameValue
-/// ::= .cfi_same_value register
-bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
- int64_t Register = 0;
-
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
-
- getStreamer().emitCFISameValue(Register);
- return false;
-}
-
-/// parseDirectiveCFIRestore
-/// ::= .cfi_restore register
-bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
- int64_t Register = 0;
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
-
- getStreamer().emitCFIRestore(Register);
- return false;
-}
-
-/// parseDirectiveCFIEscape
-/// ::= .cfi_escape expression[,...]
-bool AsmParser::parseDirectiveCFIEscape() {
- std::string Values;
- int64_t CurrValue;
- if (parseAbsoluteExpression(CurrValue))
- return true;
-
- Values.push_back((uint8_t)CurrValue);
-
- while (getLexer().is(AsmToken::Comma)) {
- Lex();
-
- if (parseAbsoluteExpression(CurrValue))
- return true;
-
- Values.push_back((uint8_t)CurrValue);
- }
-
- getStreamer().emitCFIEscape(Values);
- return false;
-}
-
-/// parseDirectiveCFIReturnColumn
-/// ::= .cfi_return_column register
-bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
- int64_t Register = 0;
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
- getStreamer().emitCFIReturnColumn(Register);
- return false;
-}
-
-/// parseDirectiveCFISignalFrame
-/// ::= .cfi_signal_frame
-bool AsmParser::parseDirectiveCFISignalFrame() {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.cfi_signal_frame'"))
- return true;
-
- getStreamer().emitCFISignalFrame();
- return false;
-}
-
-/// parseDirectiveCFIUndefined
-/// ::= .cfi_undefined register
-bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
- int64_t Register = 0;
-
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
-
- getStreamer().emitCFIUndefined(Register);
- return false;
-}
-
-/// parseDirectiveAltmacro
-/// ::= .altmacro
-/// ::= .noaltmacro
-bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '" + Directive + "' directive");
- AltMacroMode = (Directive == ".altmacro");
- return false;
-}
-
-/// parseDirectiveMacrosOnOff
-/// ::= .macros_on
-/// ::= .macros_off
-bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '" + Directive + "' directive"))
- return true;
-
- setMacrosEnabled(Directive == ".macros_on");
- return false;
-}
-
-/// parseDirectiveMacro
-/// ::= .macro name[,] [parameters]
-bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
- StringRef Name;
- if (parseIdentifier(Name))
- return TokError("expected identifier in '.macro' directive");
-
- if (getLexer().is(AsmToken::Comma))
- Lex();
-
- MCAsmMacroParameters Parameters;
- while (getLexer().isNot(AsmToken::EndOfStatement)) {
-
- if (!Parameters.empty() && Parameters.back().Vararg)
- return Error(Lexer.getLoc(), "vararg parameter '" +
- Parameters.back().Name +
- "' should be the last parameter");
-
- MCAsmMacroParameter Parameter;
- if (parseIdentifier(Parameter.Name))
- return TokError("expected identifier in '.macro' directive");
-
- // Emit an error if two (or more) named parameters share the same name
- for (const MCAsmMacroParameter& CurrParam : Parameters)
- if (CurrParam.Name.equals(Parameter.Name))
- return TokError("macro '" + Name + "' has multiple parameters"
- " named '" + Parameter.Name + "'");
-
- if (Lexer.is(AsmToken::Colon)) {
- Lex(); // consume ':'
-
- SMLoc QualLoc;
- StringRef Qualifier;
-
- QualLoc = Lexer.getLoc();
- if (parseIdentifier(Qualifier))
- return Error(QualLoc, "missing parameter qualifier for "
- "'" + Parameter.Name + "' in macro '" + Name + "'");
-
- if (Qualifier == "req")
- Parameter.Required = true;
- else if (Qualifier == "vararg")
- Parameter.Vararg = true;
- else
- return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
- "for '" + Parameter.Name + "' in macro '" + Name + "'");
- }
-
- if (getLexer().is(AsmToken::Equal)) {
- Lex();
-
- SMLoc ParamLoc;
-
- ParamLoc = Lexer.getLoc();
- if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
- return true;
-
- if (Parameter.Required)
- Warning(ParamLoc, "pointless default value for required parameter "
- "'" + Parameter.Name + "' in macro '" + Name + "'");
- }
-
- Parameters.push_back(std::move(Parameter));
-
- if (getLexer().is(AsmToken::Comma))
- Lex();
- }
-
- // Eat just the end of statement.
- Lexer.Lex();
-
- // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors
- AsmToken EndToken, StartToken = getTok();
- unsigned MacroDepth = 0;
- // Lex the macro definition.
- while (true) {
- // Ignore Lexing errors in macros.
- while (Lexer.is(AsmToken::Error)) {
- Lexer.Lex();
- }
-
- // Check whether we have reached the end of the file.
- if (getLexer().is(AsmToken::Eof))
- return Error(DirectiveLoc, "no matching '.endmacro' in definition");
-
- // Otherwise, check whether we have reach the .endmacro or the start of a
- // preprocessor line marker.
- if (getLexer().is(AsmToken::Identifier)) {
- if (getTok().getIdentifier() == ".endm" ||
- getTok().getIdentifier() == ".endmacro") {
- if (MacroDepth == 0) { // Outermost macro.
- EndToken = getTok();
- Lexer.Lex();
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '" + EndToken.getIdentifier() +
- "' directive");
- break;
- } else {
- // Otherwise we just found the end of an inner macro.
- --MacroDepth;
- }
- } else if (getTok().getIdentifier() == ".macro") {
- // We allow nested macros. Those aren't instantiated until the outermost
- // macro is expanded so just ignore them for now.
- ++MacroDepth;
- }
- } else if (Lexer.is(AsmToken::HashDirective)) {
- (void)parseCppHashLineFilenameComment(getLexer().getLoc());
- }
-
- // Otherwise, scan til the end of the statement.
- eatToEndOfStatement();
- }
-
- if (getContext().lookupMacro(Name)) {
- return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
- }
-
- const char *BodyStart = StartToken.getLoc().getPointer();
- const char *BodyEnd = EndToken.getLoc().getPointer();
- StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
- checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
- MCAsmMacro Macro(Name, Body, std::move(Parameters));
- DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
- Macro.dump());
- getContext().defineMacro(Name, std::move(Macro));
- return false;
-}
-
-/// checkForBadMacro
-///
-/// With the support added for named parameters there may be code out there that
-/// is transitioning from positional parameters. In versions of gas that did
-/// not support named parameters they would be ignored on the macro definition.
-/// But to support both styles of parameters this is not possible so if a macro
-/// definition has named parameters but does not use them and has what appears
-/// to be positional parameters, strings like $1, $2, ... and $n, then issue a
-/// warning that the positional parameter found in body which have no effect.
-/// Hoping the developer will either remove the named parameters from the macro
-/// definition so the positional parameters get used if that was what was
-/// intended or change the macro to use the named parameters. It is possible
-/// this warning will trigger when the none of the named parameters are used
-/// and the strings like $1 are infact to simply to be passed trough unchanged.
-void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
- StringRef Body,
- ArrayRef<MCAsmMacroParameter> Parameters) {
- // If this macro is not defined with named parameters the warning we are
- // checking for here doesn't apply.
- unsigned NParameters = Parameters.size();
- if (NParameters == 0)
- return;
-
- bool NamedParametersFound = false;
- bool PositionalParametersFound = false;
-
- // Look at the body of the macro for use of both the named parameters and what
- // are likely to be positional parameters. This is what expandMacro() is
- // doing when it finds the parameters in the body.
- while (!Body.empty()) {
- // Scan for the next possible parameter.
- std::size_t End = Body.size(), Pos = 0;
- for (; Pos != End; ++Pos) {
- // Check for a substitution or escape.
- // This macro is defined with parameters, look for \foo, \bar, etc.
- if (Body[Pos] == '\\' && Pos + 1 != End)
- break;
-
- // This macro should have parameters, but look for $0, $1, ..., $n too.
- if (Body[Pos] != '$' || Pos + 1 == End)
- continue;
- char Next = Body[Pos + 1];
- if (Next == '$' || Next == 'n' ||
- isdigit(static_cast<unsigned char>(Next)))
- break;
- }
-
- // Check if we reached the end.
- if (Pos == End)
- break;
-
- if (Body[Pos] == '$') {
- switch (Body[Pos + 1]) {
- // $$ => $
- case '$':
- break;
-
- // $n => number of arguments
- case 'n':
- PositionalParametersFound = true;
- break;
-
- // $[0-9] => argument
- default: {
- PositionalParametersFound = true;
- break;
- }
- }
- Pos += 2;
- } else {
- unsigned I = Pos + 1;
- while (isIdentifierChar(Body[I]) && I + 1 != End)
- ++I;
-
- const char *Begin = Body.data() + Pos + 1;
- StringRef Argument(Begin, I - (Pos + 1));
- unsigned Index = 0;
- for (; Index < NParameters; ++Index)
- if (Parameters[Index].Name == Argument)
- break;
-
- if (Index == NParameters) {
- if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
- Pos += 3;
- else {
- Pos = I;
- }
- } else {
- NamedParametersFound = true;
- Pos += 1 + Argument.size();
- }
- }
- // Update the scan point.
- Body = Body.substr(Pos);
- }
-
- if (!NamedParametersFound && PositionalParametersFound)
- Warning(DirectiveLoc, "macro defined with named parameters which are not "
- "used in macro body, possible positional parameter "
- "found in body which will have no effect");
-}
-
-/// parseDirectiveExitMacro
-/// ::= .exitm
-bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '" + Directive + "' directive"))
- return true;
-
- if (!isInsideMacroInstantiation())
- return TokError("unexpected '" + Directive + "' in file, "
- "no current macro definition");
-
- // Exit all conditionals that are active in the current macro.
- while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
- TheCondState = TheCondStack.back();
- TheCondStack.pop_back();
- }
-
- handleMacroExit();
- return false;
-}
-
-/// parseDirectiveEndMacro
-/// ::= .endm
-/// ::= .endmacro
-bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '" + Directive + "' directive");
-
- // If we are inside a macro instantiation, terminate the current
- // instantiation.
- if (isInsideMacroInstantiation()) {
- handleMacroExit();
- return false;
- }
-
- // Otherwise, this .endmacro is a stray entry in the file; well formed
- // .endmacro directives are handled during the macro definition parsing.
- return TokError("unexpected '" + Directive + "' in file, "
- "no current macro definition");
-}
-
-/// parseDirectivePurgeMacro
-/// ::= .purgem
-bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
- StringRef Name;
- SMLoc Loc;
- if (parseTokenLoc(Loc) ||
- check(parseIdentifier(Name), Loc,
- "expected identifier in '.purgem' directive") ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.purgem' directive"))
- return true;
-
- if (!getContext().lookupMacro(Name))
- return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
-
- getContext().undefineMacro(Name);
- DEBUG_WITH_TYPE("asm-macros", dbgs()
- << "Un-defining macro: " << Name << "\n");
- return false;
-}
-
-/// parseDirectiveBundleAlignMode
-/// ::= {.bundle_align_mode} expression
-bool AsmParser::parseDirectiveBundleAlignMode() {
- // 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 (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||
- parseToken(AsmToken::EndOfStatement, "unexpected token after expression "
- "in '.bundle_align_mode' "
- "directive") ||
- check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc,
- "invalid bundle alignment size (expected between 0 and 30)"))
- return true;
-
- // Because of AlignSizePow2's verified range we can safely truncate it to
- // unsigned.
- getStreamer().emitBundleAlignMode(static_cast<unsigned>(AlignSizePow2));
- return false;
-}
-
-/// parseDirectiveBundleLock
-/// ::= {.bundle_lock} [align_to_end]
-bool AsmParser::parseDirectiveBundleLock() {
- if (checkForValidSection())
- return true;
- bool AlignToEnd = false;
-
- 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) ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token after '.bundle_lock' directive option"))
- return true;
- AlignToEnd = true;
- }
-
- getStreamer().emitBundleLock(AlignToEnd);
- return false;
-}
-
-/// parseDirectiveBundleLock
-/// ::= {.bundle_lock}
-bool AsmParser::parseDirectiveBundleUnlock() {
- if (checkForValidSection() ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.bundle_unlock' directive"))
- return true;
-
- getStreamer().emitBundleUnlock();
- return false;
-}
-
-/// parseDirectiveSpace
-/// ::= (.skip | .space) expression [ , expression ]
-bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
- SMLoc NumBytesLoc = Lexer.getLoc();
- const MCExpr *NumBytes;
- if (checkForValidSection() || parseExpression(NumBytes))
- return true;
-
- int64_t FillExpr = 0;
- if (parseOptionalToken(AsmToken::Comma))
- if (parseAbsoluteExpression(FillExpr))
- return addErrorSuffix("in '" + Twine(IDVal) + "' directive");
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix("in '" + Twine(IDVal) + "' directive");
-
- // 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;
-
- 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;
-}
-
-/// parseDirectiveLEB128
-/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
-bool AsmParser::parseDirectiveLEB128(bool Signed) {
- if (checkForValidSection())
- return true;
-
- auto parseOp = [&]() -> bool {
- const MCExpr *Value;
- if (parseExpression(Value))
- return true;
- if (Signed)
- getStreamer().emitSLEB128Value(Value);
- else
- getStreamer().emitULEB128Value(Value);
- return false;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in directive");
-
- return false;
-}
-
-/// parseDirectiveSymbolAttribute
-/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
-bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
- auto parseOp = [&]() -> bool {
- StringRef Name;
- SMLoc Loc = getTok().getLoc();
- if (parseIdentifier(Name))
- return Error(Loc, "expected identifier");
- 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");
-
- if (!getStreamer().emitSymbolAttribute(Sym, Attr))
- return Error(Loc, "unable to emit symbol attribute");
- return false;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in directive");
- return false;
-}
-
-/// parseDirectiveComm
-/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
-bool AsmParser::parseDirectiveComm(bool IsLocal) {
- if (checkForValidSection())
- return true;
-
- SMLoc IDLoc = getLexer().getLoc();
- StringRef Name;
- if (parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- int64_t Size;
- SMLoc SizeLoc = getLexer().getLoc();
- if (parseAbsoluteExpression(Size))
- return true;
-
- int64_t Pow2Alignment = 0;
- SMLoc Pow2AlignmentLoc;
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
- Pow2AlignmentLoc = getLexer().getLoc();
- if (parseAbsoluteExpression(Pow2Alignment))
- return true;
-
- LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
- if (IsLocal && LCOMM == LCOMM::NoAlignment)
- return Error(Pow2AlignmentLoc, "alignment not supported on this target");
-
- // If this target takes alignments in bytes (not log) validate and convert.
- if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
- (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
- if (!isPowerOf2_64(Pow2Alignment))
- return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
- Pow2Alignment = Log2_64(Pow2Alignment);
- }
- }
-
- 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.
- if (Size < 0)
- return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
- "be less than zero");
-
- // NOTE: The alignment in the directive is a power of 2 value, the assembler
- // may internally end up wanting an alignment in bytes.
- // FIXME: Diagnose overflow.
- if (Pow2Alignment < 0)
- return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
- "alignment, can't be less than zero");
-
- Sym->redefineIfPossible();
- if (!Sym->isUndefined())
- return Error(IDLoc, "invalid symbol redefinition");
-
- // Create the Symbol as a common or local common with Size and Pow2Alignment
- if (IsLocal) {
- getStreamer().emitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
- return false;
- }
-
- getStreamer().emitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
- return false;
-}
-
-/// parseDirectiveAbort
-/// ::= .abort [... message ...]
-bool AsmParser::parseDirectiveAbort() {
- // FIXME: Use loc from directive.
- SMLoc Loc = getLexer().getLoc();
-
- StringRef Str = parseStringToEndOfStatement();
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.abort' directive"))
- return true;
-
- if (Str.empty())
- return Error(Loc, ".abort detected. Assembly stopping.");
- else
- return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
- // FIXME: Actually abort assembly here.
-
- return false;
-}
-
-/// parseDirectiveInclude
-/// ::= .include "filename"
-bool AsmParser::parseDirectiveInclude() {
- // Allow the strings to have escaped octal character sequence.
- std::string Filename;
- SMLoc IncludeLoc = getTok().getLoc();
-
- if (check(getTok().isNot(AsmToken::String),
- "expected string in '.include' directive") ||
- parseEscapedString(Filename) ||
- check(getTok().isNot(AsmToken::EndOfStatement),
- "unexpected token in '.include' directive") ||
- // Attempt to switch the lexer to the included file before consuming the
- // end of statement to avoid losing it when we switch.
- check(enterIncludeFile(Filename), IncludeLoc,
- "Could not find include file '" + Filename + "'"))
- return true;
-
- return false;
-}
-
-/// parseDirectiveIncbin
-/// ::= .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))
- 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;
-}
-
-/// parseDirectiveIf
-/// ::= .if{,eq,ge,gt,le,lt,ne} expression
-bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- } else {
- int64_t ExprValue;
- if (parseAbsoluteExpression(ExprValue) ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.if' directive"))
- return true;
-
- switch (DirKind) {
- default:
- llvm_unreachable("unsupported directive");
- case DK_IF:
- case DK_IFNE:
- break;
- case DK_IFEQ:
- ExprValue = ExprValue == 0;
- break;
- case DK_IFGE:
- ExprValue = ExprValue >= 0;
- break;
- case DK_IFGT:
- ExprValue = ExprValue > 0;
- break;
- case DK_IFLE:
- ExprValue = ExprValue <= 0;
- break;
- case DK_IFLT:
- ExprValue = ExprValue < 0;
- break;
- }
-
- TheCondState.CondMet = ExprValue;
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveIfb
-/// ::= .ifb string
-bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
-
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- } else {
- StringRef Str = parseStringToEndOfStatement();
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.ifb' directive"))
- return true;
-
- TheCondState.CondMet = ExpectBlank == Str.empty();
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveIfc
-/// ::= .ifc string1, string2
-/// ::= .ifnc string1, string2
-bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
-
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- } else {
- StringRef Str1 = parseStringToComma();
-
- if (parseToken(AsmToken::Comma, "unexpected token in '.ifc' directive"))
- return true;
-
- StringRef Str2 = parseStringToEndOfStatement();
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.ifc' directive"))
- return true;
-
- TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveIfeqs
-/// ::= .ifeqs string1, string2
-bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
- if (Lexer.isNot(AsmToken::String)) {
- if (ExpectEqual)
- return TokError("expected string parameter for '.ifeqs' directive");
- return TokError("expected string parameter for '.ifnes' directive");
- }
-
- StringRef String1 = getTok().getStringContents();
- Lex();
-
- if (Lexer.isNot(AsmToken::Comma)) {
- if (ExpectEqual)
- 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)
- return TokError("expected string parameter for '.ifeqs' directive");
- return TokError("expected string parameter for '.ifnes' directive");
- }
-
- StringRef String2 = getTok().getStringContents();
- Lex();
-
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
- TheCondState.CondMet = ExpectEqual == (String1 == String2);
- TheCondState.Ignore = !TheCondState.CondMet;
-
- return false;
-}
-
-/// parseDirectiveIfdef
-/// ::= .ifdef symbol
-bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
- StringRef Name;
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
-
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- } else {
- if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
- parseToken(AsmToken::EndOfStatement, "unexpected token in '.ifdef'"))
- return true;
-
- MCSymbol *Sym = getContext().lookupSymbol(Name);
-
- if (expect_defined)
- TheCondState.CondMet = (Sym && !Sym->isUndefined(false));
- else
- TheCondState.CondMet = (!Sym || Sym->isUndefined(false));
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveElseIf
-/// ::= .elseif expression
-bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
- if (TheCondState.TheCond != AsmCond::IfCond &&
- TheCondState.TheCond != AsmCond::ElseIfCond)
- return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
- " .if or an .elseif");
- TheCondState.TheCond = AsmCond::ElseIfCond;
-
- bool LastIgnoreState = false;
- if (!TheCondStack.empty())
- LastIgnoreState = TheCondStack.back().Ignore;
- if (LastIgnoreState || TheCondState.CondMet) {
- TheCondState.Ignore = true;
- eatToEndOfStatement();
- } else {
- int64_t ExprValue;
- if (parseAbsoluteExpression(ExprValue))
- return true;
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.elseif' directive"))
- return true;
-
- TheCondState.CondMet = ExprValue;
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveElse
-/// ::= .else
-bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.else' directive"))
- return true;
-
- if (TheCondState.TheCond != AsmCond::IfCond &&
- TheCondState.TheCond != AsmCond::ElseIfCond)
- 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())
- LastIgnoreState = TheCondStack.back().Ignore;
- if (LastIgnoreState || TheCondState.CondMet)
- TheCondState.Ignore = true;
- else
- TheCondState.Ignore = false;
-
- return false;
-}
-
-/// parseDirectiveEnd
-/// ::= .end
-bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.end' directive"))
- return true;
-
- while (Lexer.isNot(AsmToken::Eof))
- Lexer.Lex();
-
- return false;
-}
-
-/// parseDirectiveError
-/// ::= .err
-/// ::= .error [string]
-bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
- if (!TheCondStack.empty()) {
- if (TheCondStack.back().Ignore) {
- eatToEndOfStatement();
- return false;
- }
- }
-
- if (!WithMessage)
- return Error(L, ".err encountered");
-
- StringRef Message = ".error directive invoked in source file";
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::String))
- return TokError(".error argument must be a string");
-
- Message = getTok().getStringContents();
- Lex();
- }
-
- return Error(L, Message);
-}
-
-/// parseDirectiveWarning
-/// ::= .warning [string]
-bool AsmParser::parseDirectiveWarning(SMLoc L) {
- if (!TheCondStack.empty()) {
- if (TheCondStack.back().Ignore) {
- eatToEndOfStatement();
- return false;
- }
- }
-
- StringRef Message = ".warning directive invoked in source file";
-
- 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;
- }
-
- return Warning(L, Message);
-}
-
-/// parseDirectiveEndIf
-/// ::= .endif
-bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.endif' directive"))
- return true;
-
- if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
- return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
- "an .if or .else");
- if (!TheCondStack.empty()) {
- TheCondState = TheCondStack.back();
- TheCondStack.pop_back();
- }
-
- return false;
-}
-
-void AsmParser::initializeDirectiveKindMap() {
- /* Lookup will be done with the directive
- * converted to lower case, so all these
- * keys should be lower case.
- * (target specific directives are handled
- * elsewhere)
- */
- DirectiveKindMap[".set"] = DK_SET;
- DirectiveKindMap[".equ"] = DK_EQU;
- DirectiveKindMap[".equiv"] = DK_EQUIV;
- DirectiveKindMap[".ascii"] = DK_ASCII;
- DirectiveKindMap[".asciz"] = DK_ASCIZ;
- DirectiveKindMap[".string"] = DK_STRING;
- DirectiveKindMap[".byte"] = DK_BYTE;
- DirectiveKindMap[".short"] = DK_SHORT;
- DirectiveKindMap[".value"] = DK_VALUE;
- DirectiveKindMap[".2byte"] = DK_2BYTE;
- DirectiveKindMap[".long"] = DK_LONG;
- DirectiveKindMap[".int"] = DK_INT;
- DirectiveKindMap[".4byte"] = DK_4BYTE;
- DirectiveKindMap[".quad"] = DK_QUAD;
- DirectiveKindMap[".8byte"] = DK_8BYTE;
- DirectiveKindMap[".octa"] = DK_OCTA;
- DirectiveKindMap[".single"] = DK_SINGLE;
- DirectiveKindMap[".float"] = DK_FLOAT;
- DirectiveKindMap[".double"] = DK_DOUBLE;
- DirectiveKindMap[".align"] = DK_ALIGN;
- DirectiveKindMap[".align32"] = DK_ALIGN32;
- DirectiveKindMap[".balign"] = DK_BALIGN;
- DirectiveKindMap[".balignw"] = DK_BALIGNW;
- DirectiveKindMap[".balignl"] = DK_BALIGNL;
- DirectiveKindMap[".p2align"] = DK_P2ALIGN;
- DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
- DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
- DirectiveKindMap[".org"] = DK_ORG;
- DirectiveKindMap[".fill"] = DK_FILL;
- DirectiveKindMap[".zero"] = DK_ZERO;
- DirectiveKindMap[".extern"] = DK_EXTERN;
- DirectiveKindMap[".globl"] = DK_GLOBL;
- DirectiveKindMap[".global"] = DK_GLOBAL;
- DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
- DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
- DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
- DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
- DirectiveKindMap[".reference"] = DK_REFERENCE;
- DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
- DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
- DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
- DirectiveKindMap[".cold"] = DK_COLD;
- DirectiveKindMap[".comm"] = DK_COMM;
- DirectiveKindMap[".common"] = DK_COMMON;
- DirectiveKindMap[".lcomm"] = DK_LCOMM;
- DirectiveKindMap[".abort"] = DK_ABORT;
- DirectiveKindMap[".include"] = DK_INCLUDE;
- DirectiveKindMap[".incbin"] = DK_INCBIN;
- DirectiveKindMap[".code16"] = DK_CODE16;
- DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
- DirectiveKindMap[".rept"] = DK_REPT;
- DirectiveKindMap[".rep"] = DK_REPT;
- DirectiveKindMap[".irp"] = DK_IRP;
- DirectiveKindMap[".irpc"] = DK_IRPC;
- DirectiveKindMap[".endr"] = DK_ENDR;
- DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE;
- DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK;
- DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK;
- DirectiveKindMap[".if"] = DK_IF;
- DirectiveKindMap[".ifeq"] = DK_IFEQ;
- DirectiveKindMap[".ifge"] = DK_IFGE;
- DirectiveKindMap[".ifgt"] = DK_IFGT;
- DirectiveKindMap[".ifle"] = DK_IFLE;
- DirectiveKindMap[".iflt"] = DK_IFLT;
- DirectiveKindMap[".ifne"] = DK_IFNE;
- DirectiveKindMap[".ifb"] = DK_IFB;
- DirectiveKindMap[".ifnb"] = DK_IFNB;
- DirectiveKindMap[".ifc"] = DK_IFC;
- DirectiveKindMap[".ifeqs"] = DK_IFEQS;
- DirectiveKindMap[".ifnc"] = DK_IFNC;
- DirectiveKindMap[".ifnes"] = DK_IFNES;
- DirectiveKindMap[".ifdef"] = DK_IFDEF;
- DirectiveKindMap[".ifndef"] = DK_IFNDEF;
- DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
- DirectiveKindMap[".elseif"] = DK_ELSEIF;
- DirectiveKindMap[".else"] = DK_ELSE;
- DirectiveKindMap[".end"] = DK_END;
- DirectiveKindMap[".endif"] = DK_ENDIF;
- DirectiveKindMap[".skip"] = DK_SKIP;
- DirectiveKindMap[".space"] = DK_SPACE;
- DirectiveKindMap[".file"] = DK_FILE;
- DirectiveKindMap[".line"] = DK_LINE;
- 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_string"] = DK_CV_STRING;
- DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
- DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
- DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
- DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
- DirectiveKindMap[".sleb128"] = DK_SLEB128;
- DirectiveKindMap[".uleb128"] = DK_ULEB128;
- DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
- DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
- DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
- DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
- DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
- DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
- DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
- DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
- DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
- DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
- DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
- DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
- DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
- DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
- DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
- DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
- DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
- DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
- DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
- DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
- DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
- DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
- DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
- DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
- DirectiveKindMap[".macro"] = DK_MACRO;
- DirectiveKindMap[".exitm"] = DK_EXITM;
- DirectiveKindMap[".endm"] = DK_ENDM;
- DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
- DirectiveKindMap[".purgem"] = DK_PURGEM;
- DirectiveKindMap[".err"] = DK_ERR;
- DirectiveKindMap[".error"] = DK_ERROR;
- DirectiveKindMap[".warning"] = DK_WARNING;
- DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
- DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
- 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;
- DirectiveKindMap[".print"] = DK_PRINT;
- DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
- DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
+ getStreamer().emitCFIEndProc();
+ return false;
+}
+
+/// parse register name or number.
+bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
+ SMLoc DirectiveLoc) {
+ unsigned RegNo;
+
+ if (getLexer().isNot(AsmToken::Integer)) {
+ if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc))
+ return true;
+ Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
+ } else
+ return parseAbsoluteExpression(Register);
+
+ return false;
+}
+
+/// parseDirectiveCFIDefCfa
+/// ::= .cfi_def_cfa register, offset
+bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
+ int64_t Register = 0, Offset = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ parseAbsoluteExpression(Offset))
+ return true;
+
+ getStreamer().emitCFIDefCfa(Register, Offset);
+ return false;
+}
+
+/// parseDirectiveCFIDefCfaOffset
+/// ::= .cfi_def_cfa_offset offset
+bool AsmParser::parseDirectiveCFIDefCfaOffset() {
+ int64_t Offset = 0;
+ if (parseAbsoluteExpression(Offset))
+ return true;
+
+ getStreamer().emitCFIDefCfaOffset(Offset);
+ return false;
+}
+
+/// parseDirectiveCFIRegister
+/// ::= .cfi_register register, register
+bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
+ int64_t Register1 = 0, Register2 = 0;
+ if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ parseRegisterOrRegisterNumber(Register2, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFIRegister(Register1, Register2);
+ return false;
+}
+
+/// parseDirectiveCFIWindowSave
+/// ::= .cfi_window_save
+bool AsmParser::parseDirectiveCFIWindowSave() {
+ getStreamer().emitCFIWindowSave();
+ return false;
+}
+
+/// parseDirectiveCFIAdjustCfaOffset
+/// ::= .cfi_adjust_cfa_offset adjustment
+bool AsmParser::parseDirectiveCFIAdjustCfaOffset() {
+ int64_t Adjustment = 0;
+ if (parseAbsoluteExpression(Adjustment))
+ return true;
+
+ getStreamer().emitCFIAdjustCfaOffset(Adjustment);
+ return false;
+}
+
+/// parseDirectiveCFIDefCfaRegister
+/// ::= .cfi_def_cfa_register register
+bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFIDefCfaRegister(Register);
+ return false;
+}
+
+/// parseDirectiveCFIOffset
+/// ::= .cfi_offset register, offset
+bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ int64_t Offset = 0;
+
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ parseAbsoluteExpression(Offset))
+ return true;
+
+ getStreamer().emitCFIOffset(Register, Offset);
+ return false;
+}
+
+/// parseDirectiveCFIRelOffset
+/// ::= .cfi_rel_offset register, offset
+bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
+ int64_t Register = 0, Offset = 0;
+
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ parseAbsoluteExpression(Offset))
+ return true;
+
+ getStreamer().emitCFIRelOffset(Register, Offset);
+ return false;
+}
+
+static bool isValidEncoding(int64_t Encoding) {
+ if (Encoding & ~0xff)
+ return false;
+
+ if (Encoding == dwarf::DW_EH_PE_omit)
+ return true;
+
+ const unsigned Format = Encoding & 0xf;
+ if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
+ Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
+ Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
+ Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
+ return false;
+
+ const unsigned Application = Encoding & 0x70;
+ if (Application != dwarf::DW_EH_PE_absptr &&
+ Application != dwarf::DW_EH_PE_pcrel)
+ return false;
+
+ return true;
+}
+
+/// parseDirectiveCFIPersonalityOrLsda
+/// IsPersonality true for cfi_personality, false for cfi_lsda
+/// ::= .cfi_personality encoding, [symbol_name]
+/// ::= .cfi_lsda encoding, [symbol_name]
+bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
+ int64_t Encoding = 0;
+ if (parseAbsoluteExpression(Encoding))
+ return true;
+ if (Encoding == dwarf::DW_EH_PE_omit)
+ return false;
+
+ StringRef Name;
+ if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ check(parseIdentifier(Name), "expected identifier in directive"))
+ return true;
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ if (IsPersonality)
+ getStreamer().emitCFIPersonality(Sym, Encoding);
+ else
+ getStreamer().emitCFILsda(Sym, Encoding);
+ return false;
+}
+
+/// parseDirectiveCFIRememberState
+/// ::= .cfi_remember_state
+bool AsmParser::parseDirectiveCFIRememberState() {
+ getStreamer().emitCFIRememberState();
+ return false;
+}
+
+/// parseDirectiveCFIRestoreState
+/// ::= .cfi_remember_state
+bool AsmParser::parseDirectiveCFIRestoreState() {
+ getStreamer().emitCFIRestoreState();
+ return false;
+}
+
+/// parseDirectiveCFISameValue
+/// ::= .cfi_same_value register
+bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFISameValue(Register);
+ return false;
+}
+
+/// parseDirectiveCFIRestore
+/// ::= .cfi_restore register
+bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFIRestore(Register);
+ return false;
+}
+
+/// parseDirectiveCFIEscape
+/// ::= .cfi_escape expression[,...]
+bool AsmParser::parseDirectiveCFIEscape() {
+ std::string Values;
+ int64_t CurrValue;
+ if (parseAbsoluteExpression(CurrValue))
+ return true;
+
+ Values.push_back((uint8_t)CurrValue);
+
+ while (getLexer().is(AsmToken::Comma)) {
+ Lex();
+
+ if (parseAbsoluteExpression(CurrValue))
+ return true;
+
+ Values.push_back((uint8_t)CurrValue);
+ }
+
+ getStreamer().emitCFIEscape(Values);
+ return false;
+}
+
+/// parseDirectiveCFIReturnColumn
+/// ::= .cfi_return_column register
+bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+ getStreamer().emitCFIReturnColumn(Register);
+ return false;
+}
+
+/// parseDirectiveCFISignalFrame
+/// ::= .cfi_signal_frame
+bool AsmParser::parseDirectiveCFISignalFrame() {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cfi_signal_frame'"))
+ return true;
+
+ getStreamer().emitCFISignalFrame();
+ return false;
+}
+
+/// parseDirectiveCFIUndefined
+/// ::= .cfi_undefined register
+bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFIUndefined(Register);
+ return false;
+}
+
+/// parseDirectiveAltmacro
+/// ::= .altmacro
+/// ::= .noaltmacro
+bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '" + Directive + "' directive");
+ AltMacroMode = (Directive == ".altmacro");
+ return false;
+}
+
+/// parseDirectiveMacrosOnOff
+/// ::= .macros_on
+/// ::= .macros_off
+bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '" + Directive + "' directive"))
+ return true;
+
+ setMacrosEnabled(Directive == ".macros_on");
+ return false;
+}
+
+/// parseDirectiveMacro
+/// ::= .macro name[,] [parameters]
+bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
+ StringRef Name;
+ if (parseIdentifier(Name))
+ return TokError("expected identifier in '.macro' directive");
+
+ if (getLexer().is(AsmToken::Comma))
+ Lex();
+
+ MCAsmMacroParameters Parameters;
+ while (getLexer().isNot(AsmToken::EndOfStatement)) {
+
+ if (!Parameters.empty() && Parameters.back().Vararg)
+ return Error(Lexer.getLoc(), "vararg parameter '" +
+ Parameters.back().Name +
+ "' should be the last parameter");
+
+ MCAsmMacroParameter Parameter;
+ if (parseIdentifier(Parameter.Name))
+ return TokError("expected identifier in '.macro' directive");
+
+ // Emit an error if two (or more) named parameters share the same name
+ for (const MCAsmMacroParameter& CurrParam : Parameters)
+ if (CurrParam.Name.equals(Parameter.Name))
+ return TokError("macro '" + Name + "' has multiple parameters"
+ " named '" + Parameter.Name + "'");
+
+ if (Lexer.is(AsmToken::Colon)) {
+ Lex(); // consume ':'
+
+ SMLoc QualLoc;
+ StringRef Qualifier;
+
+ QualLoc = Lexer.getLoc();
+ if (parseIdentifier(Qualifier))
+ return Error(QualLoc, "missing parameter qualifier for "
+ "'" + Parameter.Name + "' in macro '" + Name + "'");
+
+ if (Qualifier == "req")
+ Parameter.Required = true;
+ else if (Qualifier == "vararg")
+ Parameter.Vararg = true;
+ else
+ return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
+ "for '" + Parameter.Name + "' in macro '" + Name + "'");
+ }
+
+ if (getLexer().is(AsmToken::Equal)) {
+ Lex();
+
+ SMLoc ParamLoc;
+
+ ParamLoc = Lexer.getLoc();
+ if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
+ return true;
+
+ if (Parameter.Required)
+ Warning(ParamLoc, "pointless default value for required parameter "
+ "'" + Parameter.Name + "' in macro '" + Name + "'");
+ }
+
+ Parameters.push_back(std::move(Parameter));
+
+ if (getLexer().is(AsmToken::Comma))
+ Lex();
+ }
+
+ // Eat just the end of statement.
+ Lexer.Lex();
+
+ // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors
+ AsmToken EndToken, StartToken = getTok();
+ unsigned MacroDepth = 0;
+ // Lex the macro definition.
+ while (true) {
+ // Ignore Lexing errors in macros.
+ while (Lexer.is(AsmToken::Error)) {
+ Lexer.Lex();
+ }
+
+ // Check whether we have reached the end of the file.
+ if (getLexer().is(AsmToken::Eof))
+ return Error(DirectiveLoc, "no matching '.endmacro' in definition");
+
+ // Otherwise, check whether we have reach the .endmacro or the start of a
+ // preprocessor line marker.
+ if (getLexer().is(AsmToken::Identifier)) {
+ if (getTok().getIdentifier() == ".endm" ||
+ getTok().getIdentifier() == ".endmacro") {
+ if (MacroDepth == 0) { // Outermost macro.
+ EndToken = getTok();
+ Lexer.Lex();
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '" + EndToken.getIdentifier() +
+ "' directive");
+ break;
+ } else {
+ // Otherwise we just found the end of an inner macro.
+ --MacroDepth;
+ }
+ } else if (getTok().getIdentifier() == ".macro") {
+ // We allow nested macros. Those aren't instantiated until the outermost
+ // macro is expanded so just ignore them for now.
+ ++MacroDepth;
+ }
+ } else if (Lexer.is(AsmToken::HashDirective)) {
+ (void)parseCppHashLineFilenameComment(getLexer().getLoc());
+ }
+
+ // Otherwise, scan til the end of the statement.
+ eatToEndOfStatement();
+ }
+
+ if (getContext().lookupMacro(Name)) {
+ return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
+ }
+
+ const char *BodyStart = StartToken.getLoc().getPointer();
+ const char *BodyEnd = EndToken.getLoc().getPointer();
+ StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
+ checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
+ MCAsmMacro Macro(Name, Body, std::move(Parameters));
+ DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
+ Macro.dump());
+ getContext().defineMacro(Name, std::move(Macro));
+ return false;
+}
+
+/// checkForBadMacro
+///
+/// With the support added for named parameters there may be code out there that
+/// is transitioning from positional parameters. In versions of gas that did
+/// not support named parameters they would be ignored on the macro definition.
+/// But to support both styles of parameters this is not possible so if a macro
+/// definition has named parameters but does not use them and has what appears
+/// to be positional parameters, strings like $1, $2, ... and $n, then issue a
+/// warning that the positional parameter found in body which have no effect.
+/// Hoping the developer will either remove the named parameters from the macro
+/// definition so the positional parameters get used if that was what was
+/// intended or change the macro to use the named parameters. It is possible
+/// this warning will trigger when the none of the named parameters are used
+/// and the strings like $1 are infact to simply to be passed trough unchanged.
+void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
+ StringRef Body,
+ ArrayRef<MCAsmMacroParameter> Parameters) {
+ // If this macro is not defined with named parameters the warning we are
+ // checking for here doesn't apply.
+ unsigned NParameters = Parameters.size();
+ if (NParameters == 0)
+ return;
+
+ bool NamedParametersFound = false;
+ bool PositionalParametersFound = false;
+
+ // Look at the body of the macro for use of both the named parameters and what
+ // are likely to be positional parameters. This is what expandMacro() is
+ // doing when it finds the parameters in the body.
+ while (!Body.empty()) {
+ // Scan for the next possible parameter.
+ std::size_t End = Body.size(), Pos = 0;
+ for (; Pos != End; ++Pos) {
+ // Check for a substitution or escape.
+ // This macro is defined with parameters, look for \foo, \bar, etc.
+ if (Body[Pos] == '\\' && Pos + 1 != End)
+ break;
+
+ // This macro should have parameters, but look for $0, $1, ..., $n too.
+ if (Body[Pos] != '$' || Pos + 1 == End)
+ continue;
+ char Next = Body[Pos + 1];
+ if (Next == '$' || Next == 'n' ||
+ isdigit(static_cast<unsigned char>(Next)))
+ break;
+ }
+
+ // Check if we reached the end.
+ if (Pos == End)
+ break;
+
+ if (Body[Pos] == '$') {
+ switch (Body[Pos + 1]) {
+ // $$ => $
+ case '$':
+ break;
+
+ // $n => number of arguments
+ case 'n':
+ PositionalParametersFound = true;
+ break;
+
+ // $[0-9] => argument
+ default: {
+ PositionalParametersFound = true;
+ break;
+ }
+ }
+ Pos += 2;
+ } else {
+ unsigned I = Pos + 1;
+ while (isIdentifierChar(Body[I]) && I + 1 != End)
+ ++I;
+
+ const char *Begin = Body.data() + Pos + 1;
+ StringRef Argument(Begin, I - (Pos + 1));
+ unsigned Index = 0;
+ for (; Index < NParameters; ++Index)
+ if (Parameters[Index].Name == Argument)
+ break;
+
+ if (Index == NParameters) {
+ if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
+ Pos += 3;
+ else {
+ Pos = I;
+ }
+ } else {
+ NamedParametersFound = true;
+ Pos += 1 + Argument.size();
+ }
+ }
+ // Update the scan point.
+ Body = Body.substr(Pos);
+ }
+
+ if (!NamedParametersFound && PositionalParametersFound)
+ Warning(DirectiveLoc, "macro defined with named parameters which are not "
+ "used in macro body, possible positional parameter "
+ "found in body which will have no effect");
+}
+
+/// parseDirectiveExitMacro
+/// ::= .exitm
+bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '" + Directive + "' directive"))
+ return true;
+
+ if (!isInsideMacroInstantiation())
+ return TokError("unexpected '" + Directive + "' in file, "
+ "no current macro definition");
+
+ // Exit all conditionals that are active in the current macro.
+ while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
+ TheCondState = TheCondStack.back();
+ TheCondStack.pop_back();
+ }
+
+ handleMacroExit();
+ return false;
+}
+
+/// parseDirectiveEndMacro
+/// ::= .endm
+/// ::= .endmacro
+bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '" + Directive + "' directive");
+
+ // If we are inside a macro instantiation, terminate the current
+ // instantiation.
+ if (isInsideMacroInstantiation()) {
+ handleMacroExit();
+ return false;
+ }
+
+ // Otherwise, this .endmacro is a stray entry in the file; well formed
+ // .endmacro directives are handled during the macro definition parsing.
+ return TokError("unexpected '" + Directive + "' in file, "
+ "no current macro definition");
+}
+
+/// parseDirectivePurgeMacro
+/// ::= .purgem
+bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
+ StringRef Name;
+ SMLoc Loc;
+ if (parseTokenLoc(Loc) ||
+ check(parseIdentifier(Name), Loc,
+ "expected identifier in '.purgem' directive") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.purgem' directive"))
+ return true;
+
+ if (!getContext().lookupMacro(Name))
+ return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
+
+ getContext().undefineMacro(Name);
+ DEBUG_WITH_TYPE("asm-macros", dbgs()
+ << "Un-defining macro: " << Name << "\n");
+ return false;
+}
+
+/// parseDirectiveBundleAlignMode
+/// ::= {.bundle_align_mode} expression
+bool AsmParser::parseDirectiveBundleAlignMode() {
+ // 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 (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||
+ parseToken(AsmToken::EndOfStatement, "unexpected token after expression "
+ "in '.bundle_align_mode' "
+ "directive") ||
+ check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc,
+ "invalid bundle alignment size (expected between 0 and 30)"))
+ return true;
+
+ // Because of AlignSizePow2's verified range we can safely truncate it to
+ // unsigned.
+ getStreamer().emitBundleAlignMode(static_cast<unsigned>(AlignSizePow2));
+ return false;
+}
+
+/// parseDirectiveBundleLock
+/// ::= {.bundle_lock} [align_to_end]
+bool AsmParser::parseDirectiveBundleLock() {
+ if (checkForValidSection())
+ return true;
+ bool AlignToEnd = false;
+
+ 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) ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token after '.bundle_lock' directive option"))
+ return true;
+ AlignToEnd = true;
+ }
+
+ getStreamer().emitBundleLock(AlignToEnd);
+ return false;
+}
+
+/// parseDirectiveBundleLock
+/// ::= {.bundle_lock}
+bool AsmParser::parseDirectiveBundleUnlock() {
+ if (checkForValidSection() ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.bundle_unlock' directive"))
+ return true;
+
+ getStreamer().emitBundleUnlock();
+ return false;
+}
+
+/// parseDirectiveSpace
+/// ::= (.skip | .space) expression [ , expression ]
+bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
+ SMLoc NumBytesLoc = Lexer.getLoc();
+ const MCExpr *NumBytes;
+ if (checkForValidSection() || parseExpression(NumBytes))
+ return true;
+
+ int64_t FillExpr = 0;
+ if (parseOptionalToken(AsmToken::Comma))
+ if (parseAbsoluteExpression(FillExpr))
+ return addErrorSuffix("in '" + Twine(IDVal) + "' directive");
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix("in '" + Twine(IDVal) + "' directive");
+
+ // 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;
+
+ 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;
+}
+
+/// parseDirectiveLEB128
+/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
+bool AsmParser::parseDirectiveLEB128(bool Signed) {
+ if (checkForValidSection())
+ return true;
+
+ auto parseOp = [&]() -> bool {
+ const MCExpr *Value;
+ if (parseExpression(Value))
+ return true;
+ if (Signed)
+ getStreamer().emitSLEB128Value(Value);
+ else
+ getStreamer().emitULEB128Value(Value);
+ return false;
+ };
+
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in directive");
+
+ return false;
+}
+
+/// parseDirectiveSymbolAttribute
+/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
+bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
+ auto parseOp = [&]() -> bool {
+ StringRef Name;
+ SMLoc Loc = getTok().getLoc();
+ if (parseIdentifier(Name))
+ return Error(Loc, "expected identifier");
+ 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");
+
+ if (!getStreamer().emitSymbolAttribute(Sym, Attr))
+ return Error(Loc, "unable to emit symbol attribute");
+ return false;
+ };
+
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in directive");
+ return false;
+}
+
+/// parseDirectiveComm
+/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
+bool AsmParser::parseDirectiveComm(bool IsLocal) {
+ if (checkForValidSection())
+ return true;
+
+ SMLoc IDLoc = getLexer().getLoc();
+ StringRef Name;
+ if (parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ int64_t Size;
+ SMLoc SizeLoc = getLexer().getLoc();
+ if (parseAbsoluteExpression(Size))
+ return true;
+
+ int64_t Pow2Alignment = 0;
+ SMLoc Pow2AlignmentLoc;
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+ Pow2AlignmentLoc = getLexer().getLoc();
+ if (parseAbsoluteExpression(Pow2Alignment))
+ return true;
+
+ LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
+ if (IsLocal && LCOMM == LCOMM::NoAlignment)
+ return Error(Pow2AlignmentLoc, "alignment not supported on this target");
+
+ // If this target takes alignments in bytes (not log) validate and convert.
+ if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
+ (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
+ if (!isPowerOf2_64(Pow2Alignment))
+ return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
+ Pow2Alignment = Log2_64(Pow2Alignment);
+ }
+ }
+
+ 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.
+ if (Size < 0)
+ return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
+ "be less than zero");
+
+ // NOTE: The alignment in the directive is a power of 2 value, the assembler
+ // may internally end up wanting an alignment in bytes.
+ // FIXME: Diagnose overflow.
+ if (Pow2Alignment < 0)
+ return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
+ "alignment, can't be less than zero");
+
+ Sym->redefineIfPossible();
+ if (!Sym->isUndefined())
+ return Error(IDLoc, "invalid symbol redefinition");
+
+ // Create the Symbol as a common or local common with Size and Pow2Alignment
+ if (IsLocal) {
+ getStreamer().emitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
+ return false;
+ }
+
+ getStreamer().emitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
+ return false;
+}
+
+/// parseDirectiveAbort
+/// ::= .abort [... message ...]
+bool AsmParser::parseDirectiveAbort() {
+ // FIXME: Use loc from directive.
+ SMLoc Loc = getLexer().getLoc();
+
+ StringRef Str = parseStringToEndOfStatement();
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.abort' directive"))
+ return true;
+
+ if (Str.empty())
+ return Error(Loc, ".abort detected. Assembly stopping.");
+ else
+ return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
+ // FIXME: Actually abort assembly here.
+
+ return false;
+}
+
+/// parseDirectiveInclude
+/// ::= .include "filename"
+bool AsmParser::parseDirectiveInclude() {
+ // Allow the strings to have escaped octal character sequence.
+ std::string Filename;
+ SMLoc IncludeLoc = getTok().getLoc();
+
+ if (check(getTok().isNot(AsmToken::String),
+ "expected string in '.include' directive") ||
+ parseEscapedString(Filename) ||
+ check(getTok().isNot(AsmToken::EndOfStatement),
+ "unexpected token in '.include' directive") ||
+ // Attempt to switch the lexer to the included file before consuming the
+ // end of statement to avoid losing it when we switch.
+ check(enterIncludeFile(Filename), IncludeLoc,
+ "Could not find include file '" + Filename + "'"))
+ return true;
+
+ return false;
+}
+
+/// parseDirectiveIncbin
+/// ::= .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))
+ 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;
+}
+
+/// parseDirectiveIf
+/// ::= .if{,eq,ge,gt,le,lt,ne} expression
+bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ } else {
+ int64_t ExprValue;
+ if (parseAbsoluteExpression(ExprValue) ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.if' directive"))
+ return true;
+
+ switch (DirKind) {
+ default:
+ llvm_unreachable("unsupported directive");
+ case DK_IF:
+ case DK_IFNE:
+ break;
+ case DK_IFEQ:
+ ExprValue = ExprValue == 0;
+ break;
+ case DK_IFGE:
+ ExprValue = ExprValue >= 0;
+ break;
+ case DK_IFGT:
+ ExprValue = ExprValue > 0;
+ break;
+ case DK_IFLE:
+ ExprValue = ExprValue <= 0;
+ break;
+ case DK_IFLT:
+ ExprValue = ExprValue < 0;
+ break;
+ }
+
+ TheCondState.CondMet = ExprValue;
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveIfb
+/// ::= .ifb string
+bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ } else {
+ StringRef Str = parseStringToEndOfStatement();
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.ifb' directive"))
+ return true;
+
+ TheCondState.CondMet = ExpectBlank == Str.empty();
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveIfc
+/// ::= .ifc string1, string2
+/// ::= .ifnc string1, string2
+bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ } else {
+ StringRef Str1 = parseStringToComma();
+
+ if (parseToken(AsmToken::Comma, "unexpected token in '.ifc' directive"))
+ return true;
+
+ StringRef Str2 = parseStringToEndOfStatement();
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.ifc' directive"))
+ return true;
+
+ TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveIfeqs
+/// ::= .ifeqs string1, string2
+bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
+ if (Lexer.isNot(AsmToken::String)) {
+ if (ExpectEqual)
+ return TokError("expected string parameter for '.ifeqs' directive");
+ return TokError("expected string parameter for '.ifnes' directive");
+ }
+
+ StringRef String1 = getTok().getStringContents();
+ Lex();
+
+ if (Lexer.isNot(AsmToken::Comma)) {
+ if (ExpectEqual)
+ 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)
+ return TokError("expected string parameter for '.ifeqs' directive");
+ return TokError("expected string parameter for '.ifnes' directive");
+ }
+
+ StringRef String2 = getTok().getStringContents();
+ Lex();
+
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+ TheCondState.CondMet = ExpectEqual == (String1 == String2);
+ TheCondState.Ignore = !TheCondState.CondMet;
+
+ return false;
+}
+
+/// parseDirectiveIfdef
+/// ::= .ifdef symbol
+bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
+ StringRef Name;
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ } else {
+ if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
+ parseToken(AsmToken::EndOfStatement, "unexpected token in '.ifdef'"))
+ return true;
+
+ MCSymbol *Sym = getContext().lookupSymbol(Name);
+
+ if (expect_defined)
+ TheCondState.CondMet = (Sym && !Sym->isUndefined(false));
+ else
+ TheCondState.CondMet = (!Sym || Sym->isUndefined(false));
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveElseIf
+/// ::= .elseif expression
+bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
+ " .if or an .elseif");
+ TheCondState.TheCond = AsmCond::ElseIfCond;
+
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet) {
+ TheCondState.Ignore = true;
+ eatToEndOfStatement();
+ } else {
+ int64_t ExprValue;
+ if (parseAbsoluteExpression(ExprValue))
+ return true;
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.elseif' directive"))
+ return true;
+
+ TheCondState.CondMet = ExprValue;
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveElse
+/// ::= .else
+bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.else' directive"))
+ return true;
+
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ 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())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet)
+ TheCondState.Ignore = true;
+ else
+ TheCondState.Ignore = false;
+
+ return false;
+}
+
+/// parseDirectiveEnd
+/// ::= .end
+bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.end' directive"))
+ return true;
+
+ while (Lexer.isNot(AsmToken::Eof))
+ Lexer.Lex();
+
+ return false;
+}
+
+/// parseDirectiveError
+/// ::= .err
+/// ::= .error [string]
+bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+ }
+
+ if (!WithMessage)
+ return Error(L, ".err encountered");
+
+ StringRef Message = ".error directive invoked in source file";
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::String))
+ return TokError(".error argument must be a string");
+
+ Message = getTok().getStringContents();
+ Lex();
+ }
+
+ return Error(L, Message);
+}
+
+/// parseDirectiveWarning
+/// ::= .warning [string]
+bool AsmParser::parseDirectiveWarning(SMLoc L) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+ }
+
+ StringRef Message = ".warning directive invoked in source file";
+
+ 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;
+ }
+
+ return Warning(L, Message);
+}
+
+/// parseDirectiveEndIf
+/// ::= .endif
+bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.endif' directive"))
+ return true;
+
+ if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
+ return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
+ "an .if or .else");
+ if (!TheCondStack.empty()) {
+ TheCondState = TheCondStack.back();
+ TheCondStack.pop_back();
+ }
+
+ return false;
+}
+
+void AsmParser::initializeDirectiveKindMap() {
+ /* Lookup will be done with the directive
+ * converted to lower case, so all these
+ * keys should be lower case.
+ * (target specific directives are handled
+ * elsewhere)
+ */
+ DirectiveKindMap[".set"] = DK_SET;
+ DirectiveKindMap[".equ"] = DK_EQU;
+ DirectiveKindMap[".equiv"] = DK_EQUIV;
+ DirectiveKindMap[".ascii"] = DK_ASCII;
+ DirectiveKindMap[".asciz"] = DK_ASCIZ;
+ DirectiveKindMap[".string"] = DK_STRING;
+ DirectiveKindMap[".byte"] = DK_BYTE;
+ DirectiveKindMap[".short"] = DK_SHORT;
+ DirectiveKindMap[".value"] = DK_VALUE;
+ DirectiveKindMap[".2byte"] = DK_2BYTE;
+ DirectiveKindMap[".long"] = DK_LONG;
+ DirectiveKindMap[".int"] = DK_INT;
+ DirectiveKindMap[".4byte"] = DK_4BYTE;
+ DirectiveKindMap[".quad"] = DK_QUAD;
+ DirectiveKindMap[".8byte"] = DK_8BYTE;
+ DirectiveKindMap[".octa"] = DK_OCTA;
+ DirectiveKindMap[".single"] = DK_SINGLE;
+ DirectiveKindMap[".float"] = DK_FLOAT;
+ DirectiveKindMap[".double"] = DK_DOUBLE;
+ DirectiveKindMap[".align"] = DK_ALIGN;
+ DirectiveKindMap[".align32"] = DK_ALIGN32;
+ DirectiveKindMap[".balign"] = DK_BALIGN;
+ DirectiveKindMap[".balignw"] = DK_BALIGNW;
+ DirectiveKindMap[".balignl"] = DK_BALIGNL;
+ DirectiveKindMap[".p2align"] = DK_P2ALIGN;
+ DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
+ DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
+ DirectiveKindMap[".org"] = DK_ORG;
+ DirectiveKindMap[".fill"] = DK_FILL;
+ DirectiveKindMap[".zero"] = DK_ZERO;
+ DirectiveKindMap[".extern"] = DK_EXTERN;
+ DirectiveKindMap[".globl"] = DK_GLOBL;
+ DirectiveKindMap[".global"] = DK_GLOBAL;
+ DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
+ DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
+ DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
+ DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
+ DirectiveKindMap[".reference"] = DK_REFERENCE;
+ DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
+ DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
+ DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
+ DirectiveKindMap[".cold"] = DK_COLD;
+ DirectiveKindMap[".comm"] = DK_COMM;
+ DirectiveKindMap[".common"] = DK_COMMON;
+ DirectiveKindMap[".lcomm"] = DK_LCOMM;
+ DirectiveKindMap[".abort"] = DK_ABORT;
+ DirectiveKindMap[".include"] = DK_INCLUDE;
+ DirectiveKindMap[".incbin"] = DK_INCBIN;
+ DirectiveKindMap[".code16"] = DK_CODE16;
+ DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
+ DirectiveKindMap[".rept"] = DK_REPT;
+ DirectiveKindMap[".rep"] = DK_REPT;
+ DirectiveKindMap[".irp"] = DK_IRP;
+ DirectiveKindMap[".irpc"] = DK_IRPC;
+ DirectiveKindMap[".endr"] = DK_ENDR;
+ DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE;
+ DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK;
+ DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK;
+ DirectiveKindMap[".if"] = DK_IF;
+ DirectiveKindMap[".ifeq"] = DK_IFEQ;
+ DirectiveKindMap[".ifge"] = DK_IFGE;
+ DirectiveKindMap[".ifgt"] = DK_IFGT;
+ DirectiveKindMap[".ifle"] = DK_IFLE;
+ DirectiveKindMap[".iflt"] = DK_IFLT;
+ DirectiveKindMap[".ifne"] = DK_IFNE;
+ DirectiveKindMap[".ifb"] = DK_IFB;
+ DirectiveKindMap[".ifnb"] = DK_IFNB;
+ DirectiveKindMap[".ifc"] = DK_IFC;
+ DirectiveKindMap[".ifeqs"] = DK_IFEQS;
+ DirectiveKindMap[".ifnc"] = DK_IFNC;
+ DirectiveKindMap[".ifnes"] = DK_IFNES;
+ DirectiveKindMap[".ifdef"] = DK_IFDEF;
+ DirectiveKindMap[".ifndef"] = DK_IFNDEF;
+ DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
+ DirectiveKindMap[".elseif"] = DK_ELSEIF;
+ DirectiveKindMap[".else"] = DK_ELSE;
+ DirectiveKindMap[".end"] = DK_END;
+ DirectiveKindMap[".endif"] = DK_ENDIF;
+ DirectiveKindMap[".skip"] = DK_SKIP;
+ DirectiveKindMap[".space"] = DK_SPACE;
+ DirectiveKindMap[".file"] = DK_FILE;
+ DirectiveKindMap[".line"] = DK_LINE;
+ 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_string"] = DK_CV_STRING;
+ DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
+ DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
+ DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
+ DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
+ DirectiveKindMap[".sleb128"] = DK_SLEB128;
+ DirectiveKindMap[".uleb128"] = DK_ULEB128;
+ DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
+ DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
+ DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
+ DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
+ DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
+ DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
+ DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
+ DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
+ DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
+ DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
+ DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
+ DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
+ DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
+ DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
+ DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
+ DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
+ DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
+ DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
+ DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
+ DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
+ DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
+ DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
+ DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
+ DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
+ DirectiveKindMap[".macro"] = DK_MACRO;
+ DirectiveKindMap[".exitm"] = DK_EXITM;
+ DirectiveKindMap[".endm"] = DK_ENDM;
+ DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
+ DirectiveKindMap[".purgem"] = DK_PURGEM;
+ DirectiveKindMap[".err"] = DK_ERR;
+ DirectiveKindMap[".error"] = DK_ERROR;
+ DirectiveKindMap[".warning"] = DK_WARNING;
+ DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
+ DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
+ 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;
+ DirectiveKindMap[".print"] = DK_PRINT;
+ DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
+ DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE;
-}
-
-MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
- AsmToken EndToken, StartToken = getTok();
-
- unsigned NestLevel = 0;
- while (true) {
- // Check whether we have reached the end of the file.
- if (getLexer().is(AsmToken::Eof)) {
- printError(DirectiveLoc, "no matching '.endr' in definition");
- return nullptr;
- }
-
- if (Lexer.is(AsmToken::Identifier) &&
- (getTok().getIdentifier() == ".rep" ||
- getTok().getIdentifier() == ".rept" ||
- getTok().getIdentifier() == ".irp" ||
- getTok().getIdentifier() == ".irpc")) {
- ++NestLevel;
- }
-
- // Otherwise, check whether we have reached the .endr.
- if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") {
- if (NestLevel == 0) {
- EndToken = getTok();
- Lex();
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- printError(getTok().getLoc(),
- "unexpected token in '.endr' directive");
- return nullptr;
- }
- break;
- }
- --NestLevel;
- }
-
- // Otherwise, scan till the end of the statement.
- eatToEndOfStatement();
- }
-
- const char *BodyStart = StartToken.getLoc().getPointer();
- const char *BodyEnd = EndToken.getLoc().getPointer();
- StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
-
- // We Are Anonymous.
- MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
- return &MacroLikeBodies.back();
-}
-
-void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
- raw_svector_ostream &OS) {
- OS << ".endr\n";
-
- std::unique_ptr<MemoryBuffer> Instantiation =
- MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
-
- // Create the macro instantiation object and add to the current macro
- // instantiation stack.
- MacroInstantiation *MI = new MacroInstantiation{
- DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
- ActiveMacros.push_back(MI);
-
- // Jump to the macro instantiation and prime the lexer.
- CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
- Lex();
-}
-
-/// parseDirectiveRept
-/// ::= .rep | .rept count
-bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
- const MCExpr *CountExpr;
- SMLoc CountLoc = getTok().getLoc();
- if (parseExpression(CountExpr))
- return true;
-
- int64_t Count;
- if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
- return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
- }
-
- if (check(Count < 0, CountLoc, "Count is negative") ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '" + Dir + "' directive"))
- return true;
-
- // Lex the rept definition.
- MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
- if (!M)
- return true;
-
- // Macro instantiation is lexical, unfortunately. We construct a new buffer
- // to hold the macro body with substitutions.
- SmallString<256> Buf;
- raw_svector_ostream OS(Buf);
- while (Count--) {
- // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
- if (expandMacro(OS, M->Body, None, None, false, getTok().getLoc()))
- return true;
- }
- instantiateMacroLikeBody(M, DirectiveLoc, OS);
-
- return false;
-}
-
-/// parseDirectiveIrp
-/// ::= .irp symbol,values
-bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
- MCAsmMacroParameter Parameter;
- MCAsmMacroArguments A;
- if (check(parseIdentifier(Parameter.Name),
- "expected identifier in '.irp' directive") ||
- parseToken(AsmToken::Comma, "expected comma in '.irp' directive") ||
- parseMacroArguments(nullptr, A) ||
- parseToken(AsmToken::EndOfStatement, "expected End of Statement"))
- return true;
-
- // Lex the irp definition.
- MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
- if (!M)
- return true;
-
- // Macro instantiation is lexical, unfortunately. We construct a new buffer
- // to hold the macro body with substitutions.
- SmallString<256> Buf;
- raw_svector_ostream OS(Buf);
-
- for (const MCAsmMacroArgument &Arg : A) {
- // Note that the AtPseudoVariable is enabled for instantiations of .irp.
- // This is undocumented, but GAS seems to support it.
- if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
- return true;
- }
-
- instantiateMacroLikeBody(M, DirectiveLoc, OS);
-
- return false;
-}
-
-/// parseDirectiveIrpc
-/// ::= .irpc symbol,values
-bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
- MCAsmMacroParameter Parameter;
- MCAsmMacroArguments A;
-
- if (check(parseIdentifier(Parameter.Name),
- "expected identifier in '.irpc' directive") ||
- parseToken(AsmToken::Comma, "expected comma in '.irpc' directive") ||
- parseMacroArguments(nullptr, A))
- return true;
-
- if (A.size() != 1 || A.front().size() != 1)
- return TokError("unexpected token in '.irpc' directive");
-
- // Eat the end of statement.
- if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
- return true;
-
- // Lex the irpc definition.
- MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
- if (!M)
- return true;
-
- // Macro instantiation is lexical, unfortunately. We construct a new buffer
- // to hold the macro body with substitutions.
- SmallString<256> Buf;
- raw_svector_ostream OS(Buf);
-
- StringRef Values = A.front().front().getString();
- for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
- MCAsmMacroArgument Arg;
- Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
-
- // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
- // This is undocumented, but GAS seems to support it.
- if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
- return true;
- }
-
- instantiateMacroLikeBody(M, DirectiveLoc, OS);
-
- return false;
-}
-
-bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
- if (ActiveMacros.empty())
- return TokError("unmatched '.endr' directive");
-
- // The only .repl that should get here are the ones created by
- // instantiateMacroLikeBody.
- assert(getLexer().is(AsmToken::EndOfStatement));
-
- handleMacroExit();
- return false;
-}
-
-bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
- size_t Len) {
- const MCExpr *Value;
- SMLoc ExprLoc = getLexer().getLoc();
- if (parseExpression(Value))
- return true;
- const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
- if (!MCE)
- return Error(ExprLoc, "unexpected expression in _emit");
- uint64_t IntValue = MCE->getValue();
- if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
- return Error(ExprLoc, "literal value out of range for directive");
-
- Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
- return false;
-}
-
-bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
- const MCExpr *Value;
- SMLoc ExprLoc = getLexer().getLoc();
- if (parseExpression(Value))
- return true;
- const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
- if (!MCE)
- return Error(ExprLoc, "unexpected expression in align");
- uint64_t IntValue = MCE->getValue();
- if (!isPowerOf2_64(IntValue))
- return Error(ExprLoc, "literal value not a power of two greater then zero");
-
- Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
- return false;
-}
-
-bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
- const AsmToken StrTok = getTok();
- Lex();
- if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
- return Error(DirectiveLoc, "expected double quoted string after .print");
- if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
- return true;
- llvm::outs() << StrTok.getStringContents() << '\n';
- return false;
-}
-
-bool AsmParser::parseDirectiveAddrsig() {
- getStreamer().emitAddrsig();
- return false;
-}
-
-bool AsmParser::parseDirectiveAddrsigSym() {
- StringRef Name;
- if (check(parseIdentifier(Name),
- "expected identifier in '.addrsig_sym' directive"))
- return true;
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().emitAddrsigSym(Sym);
- return false;
-}
-
+}
+
+MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
+ AsmToken EndToken, StartToken = getTok();
+
+ unsigned NestLevel = 0;
+ while (true) {
+ // Check whether we have reached the end of the file.
+ if (getLexer().is(AsmToken::Eof)) {
+ printError(DirectiveLoc, "no matching '.endr' in definition");
+ return nullptr;
+ }
+
+ if (Lexer.is(AsmToken::Identifier) &&
+ (getTok().getIdentifier() == ".rep" ||
+ getTok().getIdentifier() == ".rept" ||
+ getTok().getIdentifier() == ".irp" ||
+ getTok().getIdentifier() == ".irpc")) {
+ ++NestLevel;
+ }
+
+ // Otherwise, check whether we have reached the .endr.
+ if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") {
+ if (NestLevel == 0) {
+ EndToken = getTok();
+ Lex();
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ printError(getTok().getLoc(),
+ "unexpected token in '.endr' directive");
+ return nullptr;
+ }
+ break;
+ }
+ --NestLevel;
+ }
+
+ // Otherwise, scan till the end of the statement.
+ eatToEndOfStatement();
+ }
+
+ const char *BodyStart = StartToken.getLoc().getPointer();
+ const char *BodyEnd = EndToken.getLoc().getPointer();
+ StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
+
+ // We Are Anonymous.
+ MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
+ return &MacroLikeBodies.back();
+}
+
+void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
+ raw_svector_ostream &OS) {
+ OS << ".endr\n";
+
+ std::unique_ptr<MemoryBuffer> Instantiation =
+ MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
+
+ // Create the macro instantiation object and add to the current macro
+ // instantiation stack.
+ MacroInstantiation *MI = new MacroInstantiation{
+ DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
+ ActiveMacros.push_back(MI);
+
+ // Jump to the macro instantiation and prime the lexer.
+ CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
+ Lex();
+}
+
+/// parseDirectiveRept
+/// ::= .rep | .rept count
+bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
+ const MCExpr *CountExpr;
+ SMLoc CountLoc = getTok().getLoc();
+ if (parseExpression(CountExpr))
+ return true;
+
+ int64_t Count;
+ if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
+ return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
+ }
+
+ if (check(Count < 0, CountLoc, "Count is negative") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '" + Dir + "' directive"))
+ return true;
+
+ // Lex the rept definition.
+ MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
+ if (!M)
+ return true;
+
+ // Macro instantiation is lexical, unfortunately. We construct a new buffer
+ // to hold the macro body with substitutions.
+ SmallString<256> Buf;
+ raw_svector_ostream OS(Buf);
+ while (Count--) {
+ // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
+ if (expandMacro(OS, M->Body, None, None, false, getTok().getLoc()))
+ return true;
+ }
+ instantiateMacroLikeBody(M, DirectiveLoc, OS);
+
+ return false;
+}
+
+/// parseDirectiveIrp
+/// ::= .irp symbol,values
+bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
+ MCAsmMacroParameter Parameter;
+ MCAsmMacroArguments A;
+ if (check(parseIdentifier(Parameter.Name),
+ "expected identifier in '.irp' directive") ||
+ parseToken(AsmToken::Comma, "expected comma in '.irp' directive") ||
+ parseMacroArguments(nullptr, A) ||
+ parseToken(AsmToken::EndOfStatement, "expected End of Statement"))
+ return true;
+
+ // Lex the irp definition.
+ MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
+ if (!M)
+ return true;
+
+ // Macro instantiation is lexical, unfortunately. We construct a new buffer
+ // to hold the macro body with substitutions.
+ SmallString<256> Buf;
+ raw_svector_ostream OS(Buf);
+
+ for (const MCAsmMacroArgument &Arg : A) {
+ // Note that the AtPseudoVariable is enabled for instantiations of .irp.
+ // This is undocumented, but GAS seems to support it.
+ if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
+ return true;
+ }
+
+ instantiateMacroLikeBody(M, DirectiveLoc, OS);
+
+ return false;
+}
+
+/// parseDirectiveIrpc
+/// ::= .irpc symbol,values
+bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
+ MCAsmMacroParameter Parameter;
+ MCAsmMacroArguments A;
+
+ if (check(parseIdentifier(Parameter.Name),
+ "expected identifier in '.irpc' directive") ||
+ parseToken(AsmToken::Comma, "expected comma in '.irpc' directive") ||
+ parseMacroArguments(nullptr, A))
+ return true;
+
+ if (A.size() != 1 || A.front().size() != 1)
+ return TokError("unexpected token in '.irpc' directive");
+
+ // Eat the end of statement.
+ if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
+ return true;
+
+ // Lex the irpc definition.
+ MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
+ if (!M)
+ return true;
+
+ // Macro instantiation is lexical, unfortunately. We construct a new buffer
+ // to hold the macro body with substitutions.
+ SmallString<256> Buf;
+ raw_svector_ostream OS(Buf);
+
+ StringRef Values = A.front().front().getString();
+ for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
+ MCAsmMacroArgument Arg;
+ Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
+
+ // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
+ // This is undocumented, but GAS seems to support it.
+ if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
+ return true;
+ }
+
+ instantiateMacroLikeBody(M, DirectiveLoc, OS);
+
+ return false;
+}
+
+bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
+ if (ActiveMacros.empty())
+ return TokError("unmatched '.endr' directive");
+
+ // The only .repl that should get here are the ones created by
+ // instantiateMacroLikeBody.
+ assert(getLexer().is(AsmToken::EndOfStatement));
+
+ handleMacroExit();
+ return false;
+}
+
+bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
+ size_t Len) {
+ const MCExpr *Value;
+ SMLoc ExprLoc = getLexer().getLoc();
+ if (parseExpression(Value))
+ return true;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
+ if (!MCE)
+ return Error(ExprLoc, "unexpected expression in _emit");
+ uint64_t IntValue = MCE->getValue();
+ if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
+ return Error(ExprLoc, "literal value out of range for directive");
+
+ Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
+ return false;
+}
+
+bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
+ const MCExpr *Value;
+ SMLoc ExprLoc = getLexer().getLoc();
+ if (parseExpression(Value))
+ return true;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
+ if (!MCE)
+ return Error(ExprLoc, "unexpected expression in align");
+ uint64_t IntValue = MCE->getValue();
+ if (!isPowerOf2_64(IntValue))
+ return Error(ExprLoc, "literal value not a power of two greater then zero");
+
+ Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
+ return false;
+}
+
+bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
+ const AsmToken StrTok = getTok();
+ Lex();
+ if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
+ return Error(DirectiveLoc, "expected double quoted string after .print");
+ if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
+ return true;
+ llvm::outs() << StrTok.getStringContents() << '\n';
+ return false;
+}
+
+bool AsmParser::parseDirectiveAddrsig() {
+ getStreamer().emitAddrsig();
+ return false;
+}
+
+bool AsmParser::parseDirectiveAddrsigSym() {
+ StringRef Name;
+ if (check(parseIdentifier(Name),
+ "expected identifier in '.addrsig_sym' directive"))
+ return true;
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ getStreamer().emitAddrsigSym(Sym);
+ return false;
+}
+
bool AsmParser::parseDirectivePseudoProbe() {
int64_t Guid;
int64_t Index;
@@ -5854,379 +5854,379 @@ bool AsmParser::parseDirectivePseudoProbe() {
return false;
}
-// We are comparing pointers, but the pointers are relative to a single string.
-// Thus, this should always be deterministic.
-static int rewritesSort(const AsmRewrite *AsmRewriteA,
- const AsmRewrite *AsmRewriteB) {
- if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
- return -1;
- if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
- return 1;
-
- // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
- // rewrite to the same location. Make sure the SizeDirective rewrite is
- // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
- // ensures the sort algorithm is stable.
- if (AsmRewritePrecedence[AsmRewriteA->Kind] >
- AsmRewritePrecedence[AsmRewriteB->Kind])
- return -1;
-
- if (AsmRewritePrecedence[AsmRewriteA->Kind] <
- AsmRewritePrecedence[AsmRewriteB->Kind])
- return 1;
- llvm_unreachable("Unstable rewrite sort.");
-}
-
-bool AsmParser::parseMSInlineAsm(
- void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
- unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
- SmallVectorImpl<std::string> &Constraints,
- SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
- const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
- SmallVector<void *, 4> InputDecls;
- SmallVector<void *, 4> OutputDecls;
- SmallVector<bool, 4> InputDeclsAddressOf;
- SmallVector<bool, 4> OutputDeclsAddressOf;
- SmallVector<std::string, 4> InputConstraints;
- SmallVector<std::string, 4> OutputConstraints;
- SmallVector<unsigned, 4> ClobberRegs;
-
- SmallVector<AsmRewrite, 4> AsmStrRewrites;
-
- // Prime the lexer.
- Lex();
-
- // While we have input, parse each statement.
- unsigned InputIdx = 0;
- unsigned OutputIdx = 0;
- while (getLexer().isNot(AsmToken::Eof)) {
- // Parse curly braces marking block start/end
- if (parseCurlyBlockScope(AsmStrRewrites))
- continue;
-
- ParseStatementInfo Info(&AsmStrRewrites);
- bool StatementErr = parseStatement(Info, &SI);
-
- 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;
-
- const MCInstrDesc &Desc = MII->get(Info.Opcode);
-
- // Build the list of clobbers, outputs and inputs.
- for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
- MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
-
- // Register operand.
- if (Operand.isReg() && !Operand.needAddressOf() &&
- !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
- unsigned NumDefs = Desc.getNumDefs();
- // Clobber.
- if (NumDefs && Operand.getMCOperandNum() < NumDefs)
- ClobberRegs.push_back(Operand.getReg());
- continue;
- }
-
- // Expr/Input or Output.
- StringRef SymName = Operand.getSymName();
- if (SymName.empty())
- continue;
-
- void *OpDecl = Operand.getOpDecl();
- if (!OpDecl)
- continue;
-
- StringRef Constraint = Operand.getConstraint();
- if (Operand.isImm()) {
- // Offset as immediate
- if (Operand.isOffsetOfLocal())
- Constraint = "r";
- else
- Constraint = "i";
- }
-
- bool isOutput = (i == 1) && Desc.mayStore();
- SMLoc Start = SMLoc::getFromPointer(SymName.data());
- if (isOutput) {
- ++InputIdx;
- OutputDecls.push_back(OpDecl);
- OutputDeclsAddressOf.push_back(Operand.needAddressOf());
- OutputConstraints.push_back(("=" + Constraint).str());
- AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
- } else {
- InputDecls.push_back(OpDecl);
- InputDeclsAddressOf.push_back(Operand.needAddressOf());
- InputConstraints.push_back(Constraint.str());
- if (Desc.OpInfo[i - 1].isBranchTarget())
- AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
- else
- AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
- }
- }
-
- // Consider implicit defs to be clobbers. Think of cpuid and push.
- ArrayRef<MCPhysReg> ImpDefs(Desc.getImplicitDefs(),
- Desc.getNumImplicitDefs());
+// We are comparing pointers, but the pointers are relative to a single string.
+// Thus, this should always be deterministic.
+static int rewritesSort(const AsmRewrite *AsmRewriteA,
+ const AsmRewrite *AsmRewriteB) {
+ if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
+ return -1;
+ if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
+ return 1;
+
+ // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
+ // rewrite to the same location. Make sure the SizeDirective rewrite is
+ // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
+ // ensures the sort algorithm is stable.
+ if (AsmRewritePrecedence[AsmRewriteA->Kind] >
+ AsmRewritePrecedence[AsmRewriteB->Kind])
+ return -1;
+
+ if (AsmRewritePrecedence[AsmRewriteA->Kind] <
+ AsmRewritePrecedence[AsmRewriteB->Kind])
+ return 1;
+ llvm_unreachable("Unstable rewrite sort.");
+}
+
+bool AsmParser::parseMSInlineAsm(
+ void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
+ unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
+ SmallVectorImpl<std::string> &Constraints,
+ SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
+ const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
+ SmallVector<void *, 4> InputDecls;
+ SmallVector<void *, 4> OutputDecls;
+ SmallVector<bool, 4> InputDeclsAddressOf;
+ SmallVector<bool, 4> OutputDeclsAddressOf;
+ SmallVector<std::string, 4> InputConstraints;
+ SmallVector<std::string, 4> OutputConstraints;
+ SmallVector<unsigned, 4> ClobberRegs;
+
+ SmallVector<AsmRewrite, 4> AsmStrRewrites;
+
+ // Prime the lexer.
+ Lex();
+
+ // While we have input, parse each statement.
+ unsigned InputIdx = 0;
+ unsigned OutputIdx = 0;
+ while (getLexer().isNot(AsmToken::Eof)) {
+ // Parse curly braces marking block start/end
+ if (parseCurlyBlockScope(AsmStrRewrites))
+ continue;
+
+ ParseStatementInfo Info(&AsmStrRewrites);
+ bool StatementErr = parseStatement(Info, &SI);
+
+ 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;
+
+ const MCInstrDesc &Desc = MII->get(Info.Opcode);
+
+ // Build the list of clobbers, outputs and inputs.
+ for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
+ MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
+
+ // Register operand.
+ if (Operand.isReg() && !Operand.needAddressOf() &&
+ !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
+ unsigned NumDefs = Desc.getNumDefs();
+ // Clobber.
+ if (NumDefs && Operand.getMCOperandNum() < NumDefs)
+ ClobberRegs.push_back(Operand.getReg());
+ continue;
+ }
+
+ // Expr/Input or Output.
+ StringRef SymName = Operand.getSymName();
+ if (SymName.empty())
+ continue;
+
+ void *OpDecl = Operand.getOpDecl();
+ if (!OpDecl)
+ continue;
+
+ StringRef Constraint = Operand.getConstraint();
+ if (Operand.isImm()) {
+ // Offset as immediate
+ if (Operand.isOffsetOfLocal())
+ Constraint = "r";
+ else
+ Constraint = "i";
+ }
+
+ bool isOutput = (i == 1) && Desc.mayStore();
+ SMLoc Start = SMLoc::getFromPointer(SymName.data());
+ if (isOutput) {
+ ++InputIdx;
+ OutputDecls.push_back(OpDecl);
+ OutputDeclsAddressOf.push_back(Operand.needAddressOf());
+ OutputConstraints.push_back(("=" + Constraint).str());
+ AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
+ } else {
+ InputDecls.push_back(OpDecl);
+ InputDeclsAddressOf.push_back(Operand.needAddressOf());
+ InputConstraints.push_back(Constraint.str());
+ if (Desc.OpInfo[i - 1].isBranchTarget())
+ AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
+ else
+ AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
+ }
+ }
+
+ // Consider implicit defs to be clobbers. Think of cpuid and push.
+ ArrayRef<MCPhysReg> ImpDefs(Desc.getImplicitDefs(),
+ Desc.getNumImplicitDefs());
llvm::append_range(ClobberRegs, ImpDefs);
- }
-
- // Set the number of Outputs and Inputs.
- NumOutputs = OutputDecls.size();
- NumInputs = InputDecls.size();
-
- // Set the unique clobbers.
- array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
- ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
- ClobberRegs.end());
- Clobbers.assign(ClobberRegs.size(), std::string());
- for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
- raw_string_ostream OS(Clobbers[I]);
- IP->printRegName(OS, ClobberRegs[I]);
- }
-
- // Merge the various outputs and inputs. Output are expected first.
- if (NumOutputs || NumInputs) {
- unsigned NumExprs = NumOutputs + NumInputs;
- OpDecls.resize(NumExprs);
- Constraints.resize(NumExprs);
- for (unsigned i = 0; i < NumOutputs; ++i) {
- OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
- Constraints[i] = OutputConstraints[i];
- }
- for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
- OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
- Constraints[j] = InputConstraints[i];
- }
- }
-
- // Build the IR assembly string.
- std::string AsmStringIR;
- raw_string_ostream OS(AsmStringIR);
- StringRef ASMString =
- SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
- const char *AsmStart = ASMString.begin();
- const char *AsmEnd = ASMString.end();
- array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
- for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) {
- const AsmRewrite &AR = *it;
- // Check if this has already been covered by another rewrite...
- if (AR.Done)
- continue;
- AsmRewriteKind Kind = AR.Kind;
-
- const char *Loc = AR.Loc.getPointer();
- assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
-
- // Emit everything up to the immediate/expression.
- if (unsigned Len = Loc - AsmStart)
- OS << StringRef(AsmStart, Len);
-
- // Skip the original expression.
- if (Kind == AOK_Skip) {
- AsmStart = Loc + AR.Len;
- continue;
- }
-
- unsigned AdditionalSkip = 0;
- // Rewrite expressions in $N notation.
- switch (Kind) {
- default:
- break;
- case AOK_IntelExpr:
- assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
- if (AR.IntelExp.NeedBracs)
- OS << "[";
- if (AR.IntelExp.hasBaseReg())
- OS << AR.IntelExp.BaseReg;
- if (AR.IntelExp.hasIndexReg())
- OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
- << AR.IntelExp.IndexReg;
- if (AR.IntelExp.Scale > 1)
- OS << " * $$" << AR.IntelExp.Scale;
- if (AR.IntelExp.hasOffset()) {
- if (AR.IntelExp.hasRegs())
- OS << " + ";
- // Fuse this rewrite with a rewrite of the offset name, if present.
- StringRef OffsetName = AR.IntelExp.OffsetName;
- SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
- size_t OffsetLen = OffsetName.size();
- auto rewrite_it = std::find_if(
- it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
- return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
- (FusingAR.Kind == AOK_Input ||
- FusingAR.Kind == AOK_CallInput);
- });
- if (rewrite_it == AsmStrRewrites.end()) {
- OS << "offset " << OffsetName;
- } else if (rewrite_it->Kind == AOK_CallInput) {
- OS << "${" << InputIdx++ << ":P}";
- rewrite_it->Done = true;
- } else {
- OS << '$' << InputIdx++;
- rewrite_it->Done = true;
- }
- }
- if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
- OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
- if (AR.IntelExp.NeedBracs)
- OS << "]";
- break;
- case AOK_Label:
- OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
- break;
- case AOK_Input:
- OS << '$' << InputIdx++;
- break;
- case AOK_CallInput:
- OS << "${" << InputIdx++ << ":P}";
- break;
- case AOK_Output:
- OS << '$' << OutputIdx++;
- break;
- case AOK_SizeDirective:
- switch (AR.Val) {
- default: break;
- case 8: OS << "byte ptr "; break;
- case 16: OS << "word ptr "; break;
- case 32: OS << "dword ptr "; break;
- case 64: OS << "qword ptr "; break;
- case 80: OS << "xword ptr "; break;
- case 128: OS << "xmmword ptr "; break;
- case 256: OS << "ymmword ptr "; break;
- }
- break;
- case AOK_Emit:
- OS << ".byte";
- break;
- case AOK_Align: {
- // MS alignment directives are measured in bytes. If the native assembler
- // measures alignment in bytes, we can pass it straight through.
- OS << ".align";
- if (getContext().getAsmInfo()->getAlignmentIsInBytes())
- break;
-
- // Alignment is in log2 form, so print that instead and skip the original
- // immediate.
- unsigned Val = AR.Val;
- OS << ' ' << Val;
- assert(Val < 10 && "Expected alignment less then 2^10.");
- AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
- break;
- }
- case AOK_EVEN:
- OS << ".even";
- break;
- case AOK_EndOfStatement:
- OS << "\n\t";
- break;
- }
-
- // Skip the original expression.
- AsmStart = Loc + AR.Len + AdditionalSkip;
- }
-
- // Emit the remainder of the asm string.
- if (AsmStart != AsmEnd)
- OS << StringRef(AsmStart, AsmEnd - AsmStart);
-
- AsmString = OS.str();
- return false;
-}
-
-namespace llvm {
-namespace MCParserUtils {
-
-/// Returns whether the given symbol is used anywhere in the given expression,
-/// or subexpressions.
-static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
- switch (Value->getKind()) {
- case MCExpr::Binary: {
- const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
- return isSymbolUsedInExpression(Sym, BE->getLHS()) ||
- isSymbolUsedInExpression(Sym, BE->getRHS());
- }
- case MCExpr::Target:
- case MCExpr::Constant:
- return false;
- case MCExpr::SymbolRef: {
- const MCSymbol &S =
- static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
- if (S.isVariable())
- return isSymbolUsedInExpression(Sym, S.getVariableValue());
- return &S == Sym;
- }
- case MCExpr::Unary:
- return isSymbolUsedInExpression(
- Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
- }
-
- llvm_unreachable("Unknown expr kind!");
-}
-
-bool parseAssignmentExpression(StringRef Name, bool allow_redef,
- MCAsmParser &Parser, MCSymbol *&Sym,
- const MCExpr *&Value) {
-
- // FIXME: Use better location, we should use proper tokens.
- SMLoc EqualLoc = Parser.getTok().getLoc();
- if (Parser.parseExpression(Value))
- return Parser.TokError("missing expression");
-
- // Note: we don't count b as used in "a = b". This is to allow
- // a = b
- // b = c
-
- 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).
- Sym = Parser.getContext().lookupSymbol(Name);
- if (Sym) {
- // Diagnose assignment to a label.
- //
- // FIXME: Diagnostics. Note the location of the definition as a label.
- // FIXME: Diagnose assignment to protected identifier (e.g., register name).
- if (isSymbolUsedInExpression(Sym, Value))
- return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'");
- else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() &&
- !Sym->isVariable())
- ; // Allow redefinitions of undefined symbols only used in directives.
- else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
- ; // Allow redefinitions of variables that haven't yet been used.
- else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
- return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
- else if (!Sym->isVariable())
- return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'");
- else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
- return Parser.Error(EqualLoc,
- "invalid reassignment of non-absolute variable '" +
- Name + "'");
- } else if (Name == ".") {
- Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
- return false;
- } else
- Sym = Parser.getContext().getOrCreateSymbol(Name);
-
- Sym->setRedefinable(allow_redef);
-
- return false;
-}
-
-} // end namespace MCParserUtils
-} // end namespace llvm
-
-/// Create an MCAsmParser instance.
-MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
- MCStreamer &Out, const MCAsmInfo &MAI,
- unsigned CB) {
- return new AsmParser(SM, C, Out, MAI, CB);
-}
+ }
+
+ // Set the number of Outputs and Inputs.
+ NumOutputs = OutputDecls.size();
+ NumInputs = InputDecls.size();
+
+ // Set the unique clobbers.
+ array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
+ ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
+ ClobberRegs.end());
+ Clobbers.assign(ClobberRegs.size(), std::string());
+ for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
+ raw_string_ostream OS(Clobbers[I]);
+ IP->printRegName(OS, ClobberRegs[I]);
+ }
+
+ // Merge the various outputs and inputs. Output are expected first.
+ if (NumOutputs || NumInputs) {
+ unsigned NumExprs = NumOutputs + NumInputs;
+ OpDecls.resize(NumExprs);
+ Constraints.resize(NumExprs);
+ for (unsigned i = 0; i < NumOutputs; ++i) {
+ OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
+ Constraints[i] = OutputConstraints[i];
+ }
+ for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
+ OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
+ Constraints[j] = InputConstraints[i];
+ }
+ }
+
+ // Build the IR assembly string.
+ std::string AsmStringIR;
+ raw_string_ostream OS(AsmStringIR);
+ StringRef ASMString =
+ SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
+ const char *AsmStart = ASMString.begin();
+ const char *AsmEnd = ASMString.end();
+ array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
+ for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) {
+ const AsmRewrite &AR = *it;
+ // Check if this has already been covered by another rewrite...
+ if (AR.Done)
+ continue;
+ AsmRewriteKind Kind = AR.Kind;
+
+ const char *Loc = AR.Loc.getPointer();
+ assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
+
+ // Emit everything up to the immediate/expression.
+ if (unsigned Len = Loc - AsmStart)
+ OS << StringRef(AsmStart, Len);
+
+ // Skip the original expression.
+ if (Kind == AOK_Skip) {
+ AsmStart = Loc + AR.Len;
+ continue;
+ }
+
+ unsigned AdditionalSkip = 0;
+ // Rewrite expressions in $N notation.
+ switch (Kind) {
+ default:
+ break;
+ case AOK_IntelExpr:
+ assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
+ if (AR.IntelExp.NeedBracs)
+ OS << "[";
+ if (AR.IntelExp.hasBaseReg())
+ OS << AR.IntelExp.BaseReg;
+ if (AR.IntelExp.hasIndexReg())
+ OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
+ << AR.IntelExp.IndexReg;
+ if (AR.IntelExp.Scale > 1)
+ OS << " * $$" << AR.IntelExp.Scale;
+ if (AR.IntelExp.hasOffset()) {
+ if (AR.IntelExp.hasRegs())
+ OS << " + ";
+ // Fuse this rewrite with a rewrite of the offset name, if present.
+ StringRef OffsetName = AR.IntelExp.OffsetName;
+ SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
+ size_t OffsetLen = OffsetName.size();
+ auto rewrite_it = std::find_if(
+ it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
+ return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
+ (FusingAR.Kind == AOK_Input ||
+ FusingAR.Kind == AOK_CallInput);
+ });
+ if (rewrite_it == AsmStrRewrites.end()) {
+ OS << "offset " << OffsetName;
+ } else if (rewrite_it->Kind == AOK_CallInput) {
+ OS << "${" << InputIdx++ << ":P}";
+ rewrite_it->Done = true;
+ } else {
+ OS << '$' << InputIdx++;
+ rewrite_it->Done = true;
+ }
+ }
+ if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
+ OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
+ if (AR.IntelExp.NeedBracs)
+ OS << "]";
+ break;
+ case AOK_Label:
+ OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
+ break;
+ case AOK_Input:
+ OS << '$' << InputIdx++;
+ break;
+ case AOK_CallInput:
+ OS << "${" << InputIdx++ << ":P}";
+ break;
+ case AOK_Output:
+ OS << '$' << OutputIdx++;
+ break;
+ case AOK_SizeDirective:
+ switch (AR.Val) {
+ default: break;
+ case 8: OS << "byte ptr "; break;
+ case 16: OS << "word ptr "; break;
+ case 32: OS << "dword ptr "; break;
+ case 64: OS << "qword ptr "; break;
+ case 80: OS << "xword ptr "; break;
+ case 128: OS << "xmmword ptr "; break;
+ case 256: OS << "ymmword ptr "; break;
+ }
+ break;
+ case AOK_Emit:
+ OS << ".byte";
+ break;
+ case AOK_Align: {
+ // MS alignment directives are measured in bytes. If the native assembler
+ // measures alignment in bytes, we can pass it straight through.
+ OS << ".align";
+ if (getContext().getAsmInfo()->getAlignmentIsInBytes())
+ break;
+
+ // Alignment is in log2 form, so print that instead and skip the original
+ // immediate.
+ unsigned Val = AR.Val;
+ OS << ' ' << Val;
+ assert(Val < 10 && "Expected alignment less then 2^10.");
+ AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
+ break;
+ }
+ case AOK_EVEN:
+ OS << ".even";
+ break;
+ case AOK_EndOfStatement:
+ OS << "\n\t";
+ break;
+ }
+
+ // Skip the original expression.
+ AsmStart = Loc + AR.Len + AdditionalSkip;
+ }
+
+ // Emit the remainder of the asm string.
+ if (AsmStart != AsmEnd)
+ OS << StringRef(AsmStart, AsmEnd - AsmStart);
+
+ AsmString = OS.str();
+ return false;
+}
+
+namespace llvm {
+namespace MCParserUtils {
+
+/// Returns whether the given symbol is used anywhere in the given expression,
+/// or subexpressions.
+static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
+ switch (Value->getKind()) {
+ case MCExpr::Binary: {
+ const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
+ return isSymbolUsedInExpression(Sym, BE->getLHS()) ||
+ isSymbolUsedInExpression(Sym, BE->getRHS());
+ }
+ case MCExpr::Target:
+ case MCExpr::Constant:
+ return false;
+ case MCExpr::SymbolRef: {
+ const MCSymbol &S =
+ static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
+ if (S.isVariable())
+ return isSymbolUsedInExpression(Sym, S.getVariableValue());
+ return &S == Sym;
+ }
+ case MCExpr::Unary:
+ return isSymbolUsedInExpression(
+ Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
+ }
+
+ llvm_unreachable("Unknown expr kind!");
+}
+
+bool parseAssignmentExpression(StringRef Name, bool allow_redef,
+ MCAsmParser &Parser, MCSymbol *&Sym,
+ const MCExpr *&Value) {
+
+ // FIXME: Use better location, we should use proper tokens.
+ SMLoc EqualLoc = Parser.getTok().getLoc();
+ if (Parser.parseExpression(Value))
+ return Parser.TokError("missing expression");
+
+ // Note: we don't count b as used in "a = b". This is to allow
+ // a = b
+ // b = c
+
+ 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).
+ Sym = Parser.getContext().lookupSymbol(Name);
+ if (Sym) {
+ // Diagnose assignment to a label.
+ //
+ // FIXME: Diagnostics. Note the location of the definition as a label.
+ // FIXME: Diagnose assignment to protected identifier (e.g., register name).
+ if (isSymbolUsedInExpression(Sym, Value))
+ return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'");
+ else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() &&
+ !Sym->isVariable())
+ ; // Allow redefinitions of undefined symbols only used in directives.
+ else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
+ ; // Allow redefinitions of variables that haven't yet been used.
+ else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
+ return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
+ else if (!Sym->isVariable())
+ return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'");
+ else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
+ return Parser.Error(EqualLoc,
+ "invalid reassignment of non-absolute variable '" +
+ Name + "'");
+ } else if (Name == ".") {
+ Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
+ return false;
+ } else
+ Sym = Parser.getContext().getOrCreateSymbol(Name);
+
+ Sym->setRedefinable(allow_redef);
+
+ return false;
+}
+
+} // end namespace MCParserUtils
+} // end namespace llvm
+
+/// Create an MCAsmParser instance.
+MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
+ MCStreamer &Out, const MCAsmInfo &MAI,
+ unsigned CB) {
+ return new AsmParser(SM, C, Out, MAI, CB);
+}
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/COFFAsmParser.cpp b/contrib/libs/llvm12/lib/MC/MCParser/COFFAsmParser.cpp
index a859bf2ab2..3ac6a88341 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/contrib/libs/llvm12/lib/MC/MCParser/COFFAsmParser.cpp
@@ -1,726 +1,726 @@
-//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-#include "llvm/MC/MCParser/MCTargetAsmParser.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/SectionKind.h"
-#include "llvm/Support/SMLoc.h"
-#include <cassert>
-#include <cstdint>
-#include <limits>
-#include <utility>
-
-using namespace llvm;
-
-namespace {
-
-class COFFAsmParser : public MCAsmParserExtension {
- template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
- void addDirectiveHandler(StringRef Directive) {
- MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
- this, HandleDirective<COFFAsmParser, HandlerMethod>);
- getParser().addDirectiveHandler(Directive, Handler);
- }
-
- bool ParseSectionSwitch(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind);
-
- bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
- SectionKind Kind, StringRef COMDATSymName,
- COFF::COMDATType Type);
-
- bool ParseSectionName(StringRef &SectionName);
- bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
- unsigned *Flags);
-
- void Initialize(MCAsmParser &Parser) override {
- // Call the base implementation.
- MCAsmParserExtension::Initialize(Parser);
-
- addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
- addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
- addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
-
- // Win64 EH directives.
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
- ".seh_proc");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
- ".seh_endproc");
+//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSectionCOFF.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/SectionKind.h"
+#include "llvm/Support/SMLoc.h"
+#include <cassert>
+#include <cstdint>
+#include <limits>
+#include <utility>
+
+using namespace llvm;
+
+namespace {
+
+class COFFAsmParser : public MCAsmParserExtension {
+ template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
+ void addDirectiveHandler(StringRef Directive) {
+ MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
+ this, HandleDirective<COFFAsmParser, HandlerMethod>);
+ getParser().addDirectiveHandler(Directive, Handler);
+ }
+
+ bool ParseSectionSwitch(StringRef Section,
+ unsigned Characteristics,
+ SectionKind Kind);
+
+ bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
+ SectionKind Kind, StringRef COMDATSymName,
+ COFF::COMDATType Type);
+
+ bool ParseSectionName(StringRef &SectionName);
+ bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
+ unsigned *Flags);
+
+ void Initialize(MCAsmParser &Parser) override {
+ // Call the base implementation.
+ MCAsmParserExtension::Initialize(Parser);
+
+ addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
+ addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
+ addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
+
+ // Win64 EH directives.
+ addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
+ ".seh_proc");
+ addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
+ ".seh_endproc");
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc>(
".seh_endfunclet");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
- ".seh_startchained");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
- ".seh_endchained");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
- ".seh_handler");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
- ".seh_handlerdata");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
- ".seh_stackalloc");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
- ".seh_endprologue");
- }
-
- bool ParseSectionDirectiveText(StringRef, SMLoc) {
- return ParseSectionSwitch(".text",
- COFF::IMAGE_SCN_CNT_CODE
- | COFF::IMAGE_SCN_MEM_EXECUTE
- | COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getText());
- }
-
- bool ParseSectionDirectiveData(StringRef, SMLoc) {
- return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ |
- COFF::IMAGE_SCN_MEM_WRITE,
- SectionKind::getData());
- }
-
- bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
- return ParseSectionSwitch(".bss",
- COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
- | COFF::IMAGE_SCN_MEM_READ
- | COFF::IMAGE_SCN_MEM_WRITE,
- SectionKind::getBSS());
- }
-
- bool ParseDirectiveSection(StringRef, SMLoc);
- bool ParseDirectiveDef(StringRef, SMLoc);
- bool ParseDirectiveScl(StringRef, SMLoc);
- bool ParseDirectiveType(StringRef, SMLoc);
- bool ParseDirectiveEndef(StringRef, SMLoc);
- bool ParseDirectiveSecRel32(StringRef, SMLoc);
- bool ParseDirectiveSecIdx(StringRef, SMLoc);
- bool ParseDirectiveSafeSEH(StringRef, SMLoc);
- bool ParseDirectiveSymIdx(StringRef, SMLoc);
- bool parseCOMDATType(COFF::COMDATType &Type);
- bool ParseDirectiveLinkOnce(StringRef, SMLoc);
- bool ParseDirectiveRVA(StringRef, SMLoc);
- bool ParseDirectiveCGProfile(StringRef, SMLoc);
-
- // Win64 EH directives.
- bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
- bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
+ addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
+ ".seh_startchained");
+ addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
+ ".seh_endchained");
+ addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
+ ".seh_handler");
+ addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
+ ".seh_handlerdata");
+ addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
+ ".seh_stackalloc");
+ addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
+ ".seh_endprologue");
+ }
+
+ bool ParseSectionDirectiveText(StringRef, SMLoc) {
+ return ParseSectionSwitch(".text",
+ COFF::IMAGE_SCN_CNT_CODE
+ | COFF::IMAGE_SCN_MEM_EXECUTE
+ | COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getText());
+ }
+
+ bool ParseSectionDirectiveData(StringRef, SMLoc) {
+ return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ |
+ COFF::IMAGE_SCN_MEM_WRITE,
+ SectionKind::getData());
+ }
+
+ bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
+ return ParseSectionSwitch(".bss",
+ COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
+ | COFF::IMAGE_SCN_MEM_READ
+ | COFF::IMAGE_SCN_MEM_WRITE,
+ SectionKind::getBSS());
+ }
+
+ bool ParseDirectiveSection(StringRef, SMLoc);
+ bool ParseDirectiveDef(StringRef, SMLoc);
+ bool ParseDirectiveScl(StringRef, SMLoc);
+ bool ParseDirectiveType(StringRef, SMLoc);
+ bool ParseDirectiveEndef(StringRef, SMLoc);
+ bool ParseDirectiveSecRel32(StringRef, SMLoc);
+ bool ParseDirectiveSecIdx(StringRef, SMLoc);
+ bool ParseDirectiveSafeSEH(StringRef, SMLoc);
+ bool ParseDirectiveSymIdx(StringRef, SMLoc);
+ bool parseCOMDATType(COFF::COMDATType &Type);
+ bool ParseDirectiveLinkOnce(StringRef, SMLoc);
+ bool ParseDirectiveRVA(StringRef, SMLoc);
+ bool ParseDirectiveCGProfile(StringRef, SMLoc);
+
+ // Win64 EH directives.
+ bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
+ bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
bool ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc);
- bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
- bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
- bool ParseSEHDirectiveHandler(StringRef, SMLoc);
- bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
- bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
- bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
-
- bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
- bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
-
-public:
- COFFAsmParser() = default;
-};
-
-} // end anonymous namespace.
-
-static SectionKind computeSectionKind(unsigned Flags) {
- if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
- return SectionKind::getText();
- if (Flags & COFF::IMAGE_SCN_MEM_READ &&
- (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
- return SectionKind::getReadOnly();
- return SectionKind::getData();
-}
-
-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,
- Discardable = 1 << 8,
- };
-
- bool ReadOnlyRemoved = false;
- unsigned SecFlags = None;
-
- for (char FlagChar : FlagsString) {
- switch (FlagChar) {
- case 'a':
- // Ignored.
- break;
-
- case 'b': // bss section
- SecFlags |= Alloc;
- if (SecFlags & InitData)
- return TokError("conflicting section flags 'b' and 'd'.");
- SecFlags &= ~Load;
- break;
-
- case 'd': // data section
- SecFlags |= InitData;
- if (SecFlags & Alloc)
- return TokError("conflicting section flags 'b' and 'd'.");
- SecFlags &= ~NoWrite;
- if ((SecFlags & NoLoad) == 0)
- SecFlags |= Load;
- break;
-
- case 'n': // section is not loaded
- SecFlags |= NoLoad;
- SecFlags &= ~Load;
- break;
-
- case 'D': // discardable
- SecFlags |= Discardable;
- break;
-
- case 'r': // read-only
- ReadOnlyRemoved = false;
- SecFlags |= NoWrite;
- if ((SecFlags & Code) == 0)
- SecFlags |= InitData;
- if ((SecFlags & NoLoad) == 0)
- SecFlags |= Load;
- break;
-
- case 's': // shared section
- SecFlags |= Shared | InitData;
- SecFlags &= ~NoWrite;
- if ((SecFlags & NoLoad) == 0)
- SecFlags |= Load;
- break;
-
- case 'w': // writable
- SecFlags &= ~NoWrite;
- ReadOnlyRemoved = true;
- break;
-
- case 'x': // executable section
- SecFlags |= Code;
- if ((SecFlags & NoLoad) == 0)
- SecFlags |= Load;
- if (!ReadOnlyRemoved)
- SecFlags |= NoWrite;
- break;
-
- case 'y': // not readable
- SecFlags |= NoRead | NoWrite;
- break;
-
- default:
- return TokError("unknown flag");
- }
- }
-
- *Flags = 0;
-
- if (SecFlags == None)
- SecFlags = InitData;
-
- if (SecFlags & Code)
- *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
- if (SecFlags & InitData)
- *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
- if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
- *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)
- *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
- if (SecFlags & Shared)
- *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
-
- return false;
-}
-
-/// ParseDirectiveSymbolAttribute
-/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
-bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
- MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
- .Case(".weak", MCSA_Weak)
- .Default(MCSA_Invalid);
- assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- while (true) {
- StringRef Name;
-
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- getStreamer().emitSymbolAttribute(Sym, Attr);
-
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
- }
- }
-
- Lex();
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
- return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
-}
-
-bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind) {
- return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
-}
-
-bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind,
- StringRef COMDATSymName,
- COFF::COMDATType Type) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in section switching directive");
- Lex();
-
- getStreamer().SwitchSection(getContext().getCOFFSection(
- Section, Characteristics, Kind, COMDATSymName, Type));
-
- return false;
-}
-
-bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
- if (!getLexer().is(AsmToken::Identifier) && !getLexer().is(AsmToken::String))
- return true;
-
- SectionName = getTok().getIdentifier();
- Lex();
- return false;
-}
-
-// .section name [, "flags"] [, identifier [ identifier ], identifier]
-//
-// Supported flags:
-// a: Ignored.
-// b: BSS section (uninitialized data)
-// d: data section (initialized data)
-// n: "noload" section (removed by linker)
-// D: Discardable section
-// r: Readable section
-// s: Shared section
-// w: Writable section
-// x: Executable section
-// y: Not-readable section (clears 'r')
-//
-// Subsections are not supported.
-bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
- StringRef SectionName;
-
- if (ParseSectionName(SectionName))
- return TokError("expected identifier in directive");
-
- unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ |
- COFF::IMAGE_SCN_MEM_WRITE;
-
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
-
- if (getLexer().isNot(AsmToken::String))
- return TokError("expected string in directive");
-
- StringRef FlagsStr = getTok().getStringContents();
- Lex();
-
- if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
- return true;
- }
-
- COFF::COMDATType Type = (COFF::COMDATType)0;
- StringRef COMDATSymName;
- if (getLexer().is(AsmToken::Comma)) {
- Type = COFF::IMAGE_COMDAT_SELECT_ANY;
- Lex();
-
- Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
-
- if (!getLexer().is(AsmToken::Identifier))
- return TokError("expected comdat type such as 'discard' or 'largest' "
- "after protection bits");
-
- if (parseCOMDATType(Type))
- return true;
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected comma in directive");
- Lex();
-
- if (getParser().parseIdentifier(COMDATSymName))
- return TokError("expected identifier in directive");
- }
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- SectionKind Kind = computeSectionKind(Flags);
- if (Kind.isText()) {
- const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
- if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
- Flags |= COFF::IMAGE_SCN_MEM_16BIT;
- }
- ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
- StringRef SymbolName;
-
- if (getParser().parseIdentifier(SymbolName))
- return TokError("expected identifier in directive");
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
-
- getStreamer().BeginCOFFSymbolDef(Sym);
-
- Lex();
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
- int64_t SymbolStorageClass;
- if (getParser().parseAbsoluteExpression(SymbolStorageClass))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
- int64_t Type;
- if (getParser().parseAbsoluteExpression(Type))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- getStreamer().EmitCOFFSymbolType(Type);
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
- Lex();
- getStreamer().EndCOFFSymbolDef();
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
- StringRef SymbolID;
- 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 > std::numeric_limits<uint32_t>::max())
- return Error(
- OffsetLoc,
- "invalid '.secrel32' directive offset, can't be less "
- "than zero or greater than std::numeric_limits<uint32_t>::max()");
-
- MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
-
- Lex();
- getStreamer().EmitCOFFSecRel32(Symbol, Offset);
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {
- auto parseOp = [&]() -> bool {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return TokError("expected identifier in directive");
-
- int64_t Offset = 0;
- SMLoc OffsetLoc;
- if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
- OffsetLoc = getLexer().getLoc();
- if (getParser().parseAbsoluteExpression(Offset))
- return true;
- }
-
- if (Offset < std::numeric_limits<int32_t>::min() ||
- Offset > std::numeric_limits<int32_t>::max())
- return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
- "than -2147483648 or greater than "
- "2147483647");
-
- MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
-
- getStreamer().EmitCOFFImgRel32(Symbol, Offset);
- return false;
- };
-
- if (getParser().parseMany(parseOp))
- return addErrorSuffix(" in directive");
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
-
- Lex();
- getStreamer().EmitCOFFSafeSEH(Symbol);
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
-
- Lex();
- getStreamer().EmitCOFFSectionIndex(Symbol);
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
-
- Lex();
- getStreamer().EmitCOFFSymbolIndex(Symbol);
- return false;
-}
-
-/// ::= [ identifier ]
-bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
- StringRef TypeId = getTok().getIdentifier();
-
- Type = StringSwitch<COFF::COMDATType>(TypeId)
- .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
- .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
- .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
- .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
- .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
- .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
- .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
- .Default((COFF::COMDATType)0);
-
- if (Type == 0)
- return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
-
- Lex();
-
- return false;
-}
-
-/// ParseDirectiveLinkOnce
-/// ::= .linkonce [ identifier ]
-bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
- COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
- if (getLexer().is(AsmToken::Identifier))
- if (parseCOMDATType(Type))
- return true;
-
- 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");
-
- if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
- return Error(Loc, Twine("section '") + Current->getName() +
- "' is already linkonce");
-
- Current->setSelection(Type);
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
-
- Lex();
- getStreamer().EmitWinCFIStartProc(Symbol, Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
- Lex();
- getStreamer().EmitWinCFIEndProc(Loc);
- return false;
-}
-
+ bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
+ bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
+ bool ParseSEHDirectiveHandler(StringRef, SMLoc);
+ bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
+ bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
+ bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
+
+ bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
+ bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
+
+public:
+ COFFAsmParser() = default;
+};
+
+} // end anonymous namespace.
+
+static SectionKind computeSectionKind(unsigned Flags) {
+ if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
+ return SectionKind::getText();
+ if (Flags & COFF::IMAGE_SCN_MEM_READ &&
+ (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
+ return SectionKind::getReadOnly();
+ return SectionKind::getData();
+}
+
+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,
+ Discardable = 1 << 8,
+ };
+
+ bool ReadOnlyRemoved = false;
+ unsigned SecFlags = None;
+
+ for (char FlagChar : FlagsString) {
+ switch (FlagChar) {
+ case 'a':
+ // Ignored.
+ break;
+
+ case 'b': // bss section
+ SecFlags |= Alloc;
+ if (SecFlags & InitData)
+ return TokError("conflicting section flags 'b' and 'd'.");
+ SecFlags &= ~Load;
+ break;
+
+ case 'd': // data section
+ SecFlags |= InitData;
+ if (SecFlags & Alloc)
+ return TokError("conflicting section flags 'b' and 'd'.");
+ SecFlags &= ~NoWrite;
+ if ((SecFlags & NoLoad) == 0)
+ SecFlags |= Load;
+ break;
+
+ case 'n': // section is not loaded
+ SecFlags |= NoLoad;
+ SecFlags &= ~Load;
+ break;
+
+ case 'D': // discardable
+ SecFlags |= Discardable;
+ break;
+
+ case 'r': // read-only
+ ReadOnlyRemoved = false;
+ SecFlags |= NoWrite;
+ if ((SecFlags & Code) == 0)
+ SecFlags |= InitData;
+ if ((SecFlags & NoLoad) == 0)
+ SecFlags |= Load;
+ break;
+
+ case 's': // shared section
+ SecFlags |= Shared | InitData;
+ SecFlags &= ~NoWrite;
+ if ((SecFlags & NoLoad) == 0)
+ SecFlags |= Load;
+ break;
+
+ case 'w': // writable
+ SecFlags &= ~NoWrite;
+ ReadOnlyRemoved = true;
+ break;
+
+ case 'x': // executable section
+ SecFlags |= Code;
+ if ((SecFlags & NoLoad) == 0)
+ SecFlags |= Load;
+ if (!ReadOnlyRemoved)
+ SecFlags |= NoWrite;
+ break;
+
+ case 'y': // not readable
+ SecFlags |= NoRead | NoWrite;
+ break;
+
+ default:
+ return TokError("unknown flag");
+ }
+ }
+
+ *Flags = 0;
+
+ if (SecFlags == None)
+ SecFlags = InitData;
+
+ if (SecFlags & Code)
+ *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
+ if (SecFlags & InitData)
+ *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
+ if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
+ *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)
+ *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
+ if (SecFlags & Shared)
+ *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
+
+ return false;
+}
+
+/// ParseDirectiveSymbolAttribute
+/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
+bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
+ MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
+ .Case(".weak", MCSA_Weak)
+ .Default(MCSA_Invalid);
+ assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ while (true) {
+ StringRef Name;
+
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ getStreamer().emitSymbolAttribute(Sym, Attr);
+
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+ }
+ }
+
+ Lex();
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
+ return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
+}
+
+bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
+ unsigned Characteristics,
+ SectionKind Kind) {
+ return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
+}
+
+bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
+ unsigned Characteristics,
+ SectionKind Kind,
+ StringRef COMDATSymName,
+ COFF::COMDATType Type) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in section switching directive");
+ Lex();
+
+ getStreamer().SwitchSection(getContext().getCOFFSection(
+ Section, Characteristics, Kind, COMDATSymName, Type));
+
+ return false;
+}
+
+bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
+ if (!getLexer().is(AsmToken::Identifier) && !getLexer().is(AsmToken::String))
+ return true;
+
+ SectionName = getTok().getIdentifier();
+ Lex();
+ return false;
+}
+
+// .section name [, "flags"] [, identifier [ identifier ], identifier]
+//
+// Supported flags:
+// a: Ignored.
+// b: BSS section (uninitialized data)
+// d: data section (initialized data)
+// n: "noload" section (removed by linker)
+// D: Discardable section
+// r: Readable section
+// s: Shared section
+// w: Writable section
+// x: Executable section
+// y: Not-readable section (clears 'r')
+//
+// Subsections are not supported.
+bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
+ StringRef SectionName;
+
+ if (ParseSectionName(SectionName))
+ return TokError("expected identifier in directive");
+
+ unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ |
+ COFF::IMAGE_SCN_MEM_WRITE;
+
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+
+ if (getLexer().isNot(AsmToken::String))
+ return TokError("expected string in directive");
+
+ StringRef FlagsStr = getTok().getStringContents();
+ Lex();
+
+ if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
+ return true;
+ }
+
+ COFF::COMDATType Type = (COFF::COMDATType)0;
+ StringRef COMDATSymName;
+ if (getLexer().is(AsmToken::Comma)) {
+ Type = COFF::IMAGE_COMDAT_SELECT_ANY;
+ Lex();
+
+ Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
+
+ if (!getLexer().is(AsmToken::Identifier))
+ return TokError("expected comdat type such as 'discard' or 'largest' "
+ "after protection bits");
+
+ if (parseCOMDATType(Type))
+ return true;
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected comma in directive");
+ Lex();
+
+ if (getParser().parseIdentifier(COMDATSymName))
+ return TokError("expected identifier in directive");
+ }
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ SectionKind Kind = computeSectionKind(Flags);
+ if (Kind.isText()) {
+ const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
+ if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
+ Flags |= COFF::IMAGE_SCN_MEM_16BIT;
+ }
+ ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
+ StringRef SymbolName;
+
+ if (getParser().parseIdentifier(SymbolName))
+ return TokError("expected identifier in directive");
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
+
+ getStreamer().BeginCOFFSymbolDef(Sym);
+
+ Lex();
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
+ int64_t SymbolStorageClass;
+ if (getParser().parseAbsoluteExpression(SymbolStorageClass))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ Lex();
+ getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
+ int64_t Type;
+ if (getParser().parseAbsoluteExpression(Type))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ Lex();
+ getStreamer().EmitCOFFSymbolType(Type);
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
+ Lex();
+ getStreamer().EndCOFFSymbolDef();
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
+ StringRef SymbolID;
+ 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 > std::numeric_limits<uint32_t>::max())
+ return Error(
+ OffsetLoc,
+ "invalid '.secrel32' directive offset, can't be less "
+ "than zero or greater than std::numeric_limits<uint32_t>::max()");
+
+ MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
+
+ Lex();
+ getStreamer().EmitCOFFSecRel32(Symbol, Offset);
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {
+ auto parseOp = [&]() -> bool {
+ StringRef SymbolID;
+ if (getParser().parseIdentifier(SymbolID))
+ return TokError("expected identifier in directive");
+
+ int64_t Offset = 0;
+ SMLoc OffsetLoc;
+ if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
+ OffsetLoc = getLexer().getLoc();
+ if (getParser().parseAbsoluteExpression(Offset))
+ return true;
+ }
+
+ if (Offset < std::numeric_limits<int32_t>::min() ||
+ Offset > std::numeric_limits<int32_t>::max())
+ return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
+ "than -2147483648 or greater than "
+ "2147483647");
+
+ MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
+
+ getStreamer().EmitCOFFImgRel32(Symbol, Offset);
+ return false;
+ };
+
+ if (getParser().parseMany(parseOp))
+ return addErrorSuffix(" in directive");
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
+ StringRef SymbolID;
+ if (getParser().parseIdentifier(SymbolID))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
+
+ Lex();
+ getStreamer().EmitCOFFSafeSEH(Symbol);
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
+ StringRef SymbolID;
+ if (getParser().parseIdentifier(SymbolID))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
+
+ Lex();
+ getStreamer().EmitCOFFSectionIndex(Symbol);
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
+ StringRef SymbolID;
+ if (getParser().parseIdentifier(SymbolID))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
+
+ Lex();
+ getStreamer().EmitCOFFSymbolIndex(Symbol);
+ return false;
+}
+
+/// ::= [ identifier ]
+bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
+ StringRef TypeId = getTok().getIdentifier();
+
+ Type = StringSwitch<COFF::COMDATType>(TypeId)
+ .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
+ .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
+ .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
+ .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
+ .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
+ .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
+ .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
+ .Default((COFF::COMDATType)0);
+
+ if (Type == 0)
+ return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
+
+ Lex();
+
+ return false;
+}
+
+/// ParseDirectiveLinkOnce
+/// ::= .linkonce [ identifier ]
+bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
+ COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
+ if (getLexer().is(AsmToken::Identifier))
+ if (parseCOMDATType(Type))
+ return true;
+
+ 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");
+
+ if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
+ return Error(Loc, Twine("section '") + Current->getName() +
+ "' is already linkonce");
+
+ Current->setSelection(Type);
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
+ StringRef SymbolID;
+ if (getParser().parseIdentifier(SymbolID))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
+
+ Lex();
+ getStreamer().EmitWinCFIStartProc(Symbol, Loc);
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
+ Lex();
+ getStreamer().EmitWinCFIEndProc(Loc);
+ return false;
+}
+
bool COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc Loc) {
Lex();
getStreamer().EmitWinCFIFuncletOrFuncEnd(Loc);
return false;
}
-bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
- Lex();
- getStreamer().EmitWinCFIStartChained(Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
- Lex();
- getStreamer().EmitWinCFIEndChained(Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return true;
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("you must specify one or both of @unwind or @except");
- Lex();
- bool unwind = false, except = false;
- if (ParseAtUnwindOrAtExcept(unwind, except))
- return true;
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
- if (ParseAtUnwindOrAtExcept(unwind, except))
- return true;
- }
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
-
- Lex();
- getStreamer().EmitWinEHHandler(handler, unwind, except, Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
- Lex();
- getStreamer().EmitWinEHHandlerData();
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
- int64_t Size;
- if (getParser().parseAbsoluteExpression(Size))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- getStreamer().EmitWinCFIAllocStack(Size, Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
- Lex();
- getStreamer().EmitWinCFIEndProlog(Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
- StringRef identifier;
- if (getLexer().isNot(AsmToken::At))
- return TokError("a handler attribute must begin with '@'");
- SMLoc startLoc = getLexer().getLoc();
- Lex();
- if (getParser().parseIdentifier(identifier))
- return Error(startLoc, "expected @unwind or @except");
- if (identifier == "unwind")
- unwind = true;
- else if (identifier == "except")
- except = true;
- else
- return Error(startLoc, "expected @unwind or @except");
- return false;
-}
-
-namespace llvm {
-
-MCAsmParserExtension *createCOFFAsmParser() {
- return new COFFAsmParser;
-}
-
-} // end namespace llvm
+bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
+ Lex();
+ getStreamer().EmitWinCFIStartChained(Loc);
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
+ Lex();
+ getStreamer().EmitWinCFIEndChained(Loc);
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
+ StringRef SymbolID;
+ if (getParser().parseIdentifier(SymbolID))
+ return true;
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("you must specify one or both of @unwind or @except");
+ Lex();
+ bool unwind = false, except = false;
+ if (ParseAtUnwindOrAtExcept(unwind, except))
+ return true;
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+ if (ParseAtUnwindOrAtExcept(unwind, except))
+ return true;
+ }
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
+
+ Lex();
+ getStreamer().EmitWinEHHandler(handler, unwind, except, Loc);
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
+ Lex();
+ getStreamer().EmitWinEHHandlerData();
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
+ int64_t Size;
+ if (getParser().parseAbsoluteExpression(Size))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ Lex();
+ getStreamer().EmitWinCFIAllocStack(Size, Loc);
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
+ Lex();
+ getStreamer().EmitWinCFIEndProlog(Loc);
+ return false;
+}
+
+bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
+ StringRef identifier;
+ if (getLexer().isNot(AsmToken::At))
+ return TokError("a handler attribute must begin with '@'");
+ SMLoc startLoc = getLexer().getLoc();
+ Lex();
+ if (getParser().parseIdentifier(identifier))
+ return Error(startLoc, "expected @unwind or @except");
+ if (identifier == "unwind")
+ unwind = true;
+ else if (identifier == "except")
+ except = true;
+ else
+ return Error(startLoc, "expected @unwind or @except");
+ return false;
+}
+
+namespace llvm {
+
+MCAsmParserExtension *createCOFFAsmParser() {
+ return new COFFAsmParser;
+}
+
+} // end namespace llvm
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/COFFMasmParser.cpp b/contrib/libs/llvm12/lib/MC/MCParser/COFFMasmParser.cpp
index 2930e7b89a..95128cf7d1 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/COFFMasmParser.cpp
+++ b/contrib/libs/llvm12/lib/MC/MCParser/COFFMasmParser.cpp
@@ -1,343 +1,343 @@
-//===- COFFMasmParser.cpp - COFF MASM Assembly Parser ---------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-#include "llvm/MC/MCParser/MCAsmParserUtils.h"
-#include "llvm/MC/MCParser/MCTargetAsmParser.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/MC/MCStreamer.h"
+//===- COFFMasmParser.cpp - COFF MASM Assembly Parser ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCParser/MCAsmParserUtils.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSectionCOFF.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbolCOFF.h"
-#include "llvm/MC/SectionKind.h"
-#include "llvm/Support/SMLoc.h"
-#include <cassert>
-#include <cstdint>
-#include <limits>
-#include <utility>
-
-using namespace llvm;
-
-namespace {
-
-class COFFMasmParser : public MCAsmParserExtension {
- template <bool (COFFMasmParser::*HandlerMethod)(StringRef, SMLoc)>
- void addDirectiveHandler(StringRef Directive) {
- MCAsmParser::ExtensionDirectiveHandler Handler =
- std::make_pair(this, HandleDirective<COFFMasmParser, HandlerMethod>);
- getParser().addDirectiveHandler(Directive, Handler);
- }
-
- bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
- SectionKind Kind);
-
- bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
- SectionKind Kind, StringRef COMDATSymName,
- COFF::COMDATType Type);
-
- bool ParseDirectiveProc(StringRef, SMLoc);
- bool ParseDirectiveEndProc(StringRef, SMLoc);
- bool ParseDirectiveSegment(StringRef, SMLoc);
- bool ParseDirectiveSegmentEnd(StringRef, SMLoc);
- bool ParseDirectiveIncludelib(StringRef, SMLoc);
-
+#include "llvm/MC/SectionKind.h"
+#include "llvm/Support/SMLoc.h"
+#include <cassert>
+#include <cstdint>
+#include <limits>
+#include <utility>
+
+using namespace llvm;
+
+namespace {
+
+class COFFMasmParser : public MCAsmParserExtension {
+ template <bool (COFFMasmParser::*HandlerMethod)(StringRef, SMLoc)>
+ void addDirectiveHandler(StringRef Directive) {
+ MCAsmParser::ExtensionDirectiveHandler Handler =
+ std::make_pair(this, HandleDirective<COFFMasmParser, HandlerMethod>);
+ getParser().addDirectiveHandler(Directive, Handler);
+ }
+
+ bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
+ SectionKind Kind);
+
+ bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
+ SectionKind Kind, StringRef COMDATSymName,
+ COFF::COMDATType Type);
+
+ bool ParseDirectiveProc(StringRef, SMLoc);
+ bool ParseDirectiveEndProc(StringRef, SMLoc);
+ bool ParseDirectiveSegment(StringRef, SMLoc);
+ bool ParseDirectiveSegmentEnd(StringRef, SMLoc);
+ bool ParseDirectiveIncludelib(StringRef, SMLoc);
+
bool ParseDirectiveAlias(StringRef, SMLoc);
bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
- bool IgnoreDirective(StringRef, SMLoc) {
- while (!getLexer().is(AsmToken::EndOfStatement)) {
- Lex();
- }
- return false;
- }
-
- void Initialize(MCAsmParser &Parser) override {
- // Call the base implementation.
- MCAsmParserExtension::Initialize(Parser);
-
- // x64 directives
+ bool IgnoreDirective(StringRef, SMLoc) {
+ while (!getLexer().is(AsmToken::EndOfStatement)) {
+ Lex();
+ }
+ return false;
+ }
+
+ void Initialize(MCAsmParser &Parser) override {
+ // Call the base implementation.
+ MCAsmParserExtension::Initialize(Parser);
+
+ // x64 directives
addDirectiveHandler<&COFFMasmParser::ParseSEHDirectiveAllocStack>(
".allocstack");
addDirectiveHandler<&COFFMasmParser::ParseSEHDirectiveEndProlog>(
".endprolog");
-
- // Code label directives
- // label
- // org
-
- // Conditional control flow directives
- // .break
- // .continue
- // .else
- // .elseif
- // .endif
- // .endw
- // .if
- // .repeat
- // .until
- // .untilcxz
- // .while
-
- // Data allocation directives
- // align
- // even
+
+ // Code label directives
+ // label
+ // org
+
+ // Conditional control flow directives
+ // .break
+ // .continue
+ // .else
+ // .elseif
+ // .endif
+ // .endw
+ // .if
+ // .repeat
+ // .until
+ // .untilcxz
+ // .while
+
+ // Data allocation directives
+ // align
+ // even
// mmword
- // tbyte
+ // tbyte
// xmmword
// ymmword
-
- // Listing control directives
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".list");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listall");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listif");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacro");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacroall");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nocref");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolist");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistif");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistmacro");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("page");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("subtitle");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".tfcond");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("title");
-
- // Macro directives
- // goto
-
- // Miscellaneous directives
+
+ // Listing control directives
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".list");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listall");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listif");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacro");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacroall");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nocref");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolist");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistif");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistmacro");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("page");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("subtitle");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".tfcond");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("title");
+
+ // Macro directives
+ // goto
+
+ // Miscellaneous directives
addDirectiveHandler<&COFFMasmParser::ParseDirectiveAlias>("alias");
- // assume
- // .fpo
- addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>(
- "includelib");
- // option
- // popcontext
- // pushcontext
- // .safeseh
-
- // Procedure directives
- addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp");
- // invoke (32-bit only)
- addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc");
- // proto
-
+ // assume
+ // .fpo
+ addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>(
+ "includelib");
+ // option
+ // popcontext
+ // pushcontext
+ // .safeseh
+
+ // Procedure directives
+ addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp");
+ // invoke (32-bit only)
+ addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc");
+ // proto
+
// Processor directives; all ignored
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386P");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486P");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586P");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686P");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".k3d");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".mmx");
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".xmm");
-
- // Scope directives
- // comm
- // externdef
-
- // Segment directives
- // .alpha (32-bit only, order segments alphabetically)
- // .dosseg (32-bit only, order segments in DOS convention)
- // .seq (32-bit only, order segments sequentially)
- addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegmentEnd>("ends");
- // group (32-bit only)
- addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegment>("segment");
-
- // Simplified segment directives
- addDirectiveHandler<&COFFMasmParser::ParseSectionDirectiveCode>(".code");
- // .const
- addDirectiveHandler<
- &COFFMasmParser::ParseSectionDirectiveInitializedData>(".data");
- addDirectiveHandler<
- &COFFMasmParser::ParseSectionDirectiveUninitializedData>(".data?");
- // .exit
- // .fardata
- // .fardata?
- addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".model");
- // .stack
- // .startup
-
- // String directives, written <name> <directive> <params>
- // catstr (equivalent to <name> TEXTEQU <params>)
- // instr (equivalent to <name> = @InStr(<params>))
- // sizestr (equivalent to <name> = @SizeStr(<params>))
- // substr (equivalent to <name> TEXTEQU @SubStr(<params>))
-
- // Structure and record directives
- // record
- // typedef
- }
-
- bool ParseSectionDirectiveCode(StringRef, SMLoc) {
- return ParseSectionSwitch(".text",
- COFF::IMAGE_SCN_CNT_CODE
- | COFF::IMAGE_SCN_MEM_EXECUTE
- | COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getText());
- }
-
- bool ParseSectionDirectiveInitializedData(StringRef, SMLoc) {
- return ParseSectionSwitch(".data",
- COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
- | COFF::IMAGE_SCN_MEM_READ
- | COFF::IMAGE_SCN_MEM_WRITE,
- SectionKind::getData());
- }
-
- bool ParseSectionDirectiveUninitializedData(StringRef, SMLoc) {
- return ParseSectionSwitch(".bss",
- COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
- | COFF::IMAGE_SCN_MEM_READ
- | COFF::IMAGE_SCN_MEM_WRITE,
- SectionKind::getBSS());
- }
-
- StringRef CurrentProcedure;
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386P");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486P");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586P");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686P");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".k3d");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".mmx");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".xmm");
+
+ // Scope directives
+ // comm
+ // externdef
+
+ // Segment directives
+ // .alpha (32-bit only, order segments alphabetically)
+ // .dosseg (32-bit only, order segments in DOS convention)
+ // .seq (32-bit only, order segments sequentially)
+ addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegmentEnd>("ends");
+ // group (32-bit only)
+ addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegment>("segment");
+
+ // Simplified segment directives
+ addDirectiveHandler<&COFFMasmParser::ParseSectionDirectiveCode>(".code");
+ // .const
+ addDirectiveHandler<
+ &COFFMasmParser::ParseSectionDirectiveInitializedData>(".data");
+ addDirectiveHandler<
+ &COFFMasmParser::ParseSectionDirectiveUninitializedData>(".data?");
+ // .exit
+ // .fardata
+ // .fardata?
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".model");
+ // .stack
+ // .startup
+
+ // String directives, written <name> <directive> <params>
+ // catstr (equivalent to <name> TEXTEQU <params>)
+ // instr (equivalent to <name> = @InStr(<params>))
+ // sizestr (equivalent to <name> = @SizeStr(<params>))
+ // substr (equivalent to <name> TEXTEQU @SubStr(<params>))
+
+ // Structure and record directives
+ // record
+ // typedef
+ }
+
+ bool ParseSectionDirectiveCode(StringRef, SMLoc) {
+ return ParseSectionSwitch(".text",
+ COFF::IMAGE_SCN_CNT_CODE
+ | COFF::IMAGE_SCN_MEM_EXECUTE
+ | COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getText());
+ }
+
+ bool ParseSectionDirectiveInitializedData(StringRef, SMLoc) {
+ return ParseSectionSwitch(".data",
+ COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
+ | COFF::IMAGE_SCN_MEM_READ
+ | COFF::IMAGE_SCN_MEM_WRITE,
+ SectionKind::getData());
+ }
+
+ bool ParseSectionDirectiveUninitializedData(StringRef, SMLoc) {
+ return ParseSectionSwitch(".bss",
+ COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
+ | COFF::IMAGE_SCN_MEM_READ
+ | COFF::IMAGE_SCN_MEM_WRITE,
+ SectionKind::getBSS());
+ }
+
+ StringRef CurrentProcedure;
bool CurrentProcedureFramed;
-
-public:
- COFFMasmParser() = default;
-};
-
-} // end anonymous namespace.
-
-static SectionKind computeSectionKind(unsigned Flags) {
- if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
- return SectionKind::getText();
- if (Flags & COFF::IMAGE_SCN_MEM_READ &&
- (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
- return SectionKind::getReadOnly();
- return SectionKind::getData();
-}
-
-bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind) {
- return ParseSectionSwitch(Section, Characteristics, Kind, "",
- (COFF::COMDATType)0);
-}
-
-bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind,
- StringRef COMDATSymName,
- COFF::COMDATType Type) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in section switching directive");
- Lex();
-
- getStreamer().SwitchSection(getContext().getCOFFSection(
- Section, Characteristics, Kind, COMDATSymName, Type));
-
- return false;
-}
-
-bool COFFMasmParser::ParseDirectiveSegment(StringRef Directive, SMLoc Loc) {
- StringRef SegmentName;
- if (!getLexer().is(AsmToken::Identifier))
- return TokError("expected identifier in directive");
- SegmentName = getTok().getIdentifier();
- Lex();
-
- StringRef SectionName = SegmentName;
- SmallVector<char, 247> SectionNameVector;
- unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE;
- if (SegmentName == "_TEXT" || SegmentName.startswith("_TEXT$")) {
- if (SegmentName.size() == 5) {
- SectionName = ".text";
- } else {
- SectionName =
- (".text$" + SegmentName.substr(6)).toStringRef(SectionNameVector);
- }
- Flags = COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE |
- COFF::IMAGE_SCN_MEM_READ;
- }
- SectionKind Kind = computeSectionKind(Flags);
- getStreamer().SwitchSection(getContext().getCOFFSection(
- SectionName, Flags, Kind, "", (COFF::COMDATType)(0)));
- return false;
-}
-
-/// ParseDirectiveSegmentEnd
-/// ::= identifier "ends"
-bool COFFMasmParser::ParseDirectiveSegmentEnd(StringRef Directive, SMLoc Loc) {
- StringRef SegmentName;
- if (!getLexer().is(AsmToken::Identifier))
- return TokError("expected identifier in directive");
- SegmentName = getTok().getIdentifier();
-
- // Ignore; no action necessary.
- Lex();
- return false;
-}
-
-/// ParseDirectiveIncludelib
-/// ::= "includelib" identifier
-bool COFFMasmParser::ParseDirectiveIncludelib(StringRef Directive, SMLoc Loc) {
- StringRef Lib;
- if (getParser().parseIdentifier(Lib))
- return TokError("expected identifier in includelib directive");
-
- unsigned Flags = COFF::IMAGE_SCN_MEM_PRELOAD | COFF::IMAGE_SCN_MEM_16BIT;
- SectionKind Kind = computeSectionKind(Flags);
- getStreamer().PushSection();
- getStreamer().SwitchSection(getContext().getCOFFSection(
- ".drectve", Flags, Kind, "", (COFF::COMDATType)(0)));
- getStreamer().emitBytes("/DEFAULTLIB:");
- getStreamer().emitBytes(Lib);
- getStreamer().emitBytes(" ");
- getStreamer().PopSection();
- return false;
-}
-
-/// ParseDirectiveProc
-/// TODO(epastor): Implement parameters and other attributes.
-/// ::= label "proc" [[distance]]
-/// statements
-/// label "endproc"
-bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) {
- StringRef Label;
- if (getParser().parseIdentifier(Label))
- return Error(Loc, "expected identifier for procedure");
- if (getLexer().is(AsmToken::Identifier)) {
- StringRef nextVal = getTok().getString();
- SMLoc nextLoc = getTok().getLoc();
- if (nextVal.equals_lower("far")) {
- // TODO(epastor): Handle far procedure definitions.
- Lex();
- return Error(nextLoc, "far procedure definitions not yet supported");
- } else if (nextVal.equals_lower("near")) {
- Lex();
- nextVal = getTok().getString();
- nextLoc = getTok().getLoc();
- }
- }
+
+public:
+ COFFMasmParser() = default;
+};
+
+} // end anonymous namespace.
+
+static SectionKind computeSectionKind(unsigned Flags) {
+ if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
+ return SectionKind::getText();
+ if (Flags & COFF::IMAGE_SCN_MEM_READ &&
+ (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
+ return SectionKind::getReadOnly();
+ return SectionKind::getData();
+}
+
+bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
+ unsigned Characteristics,
+ SectionKind Kind) {
+ return ParseSectionSwitch(Section, Characteristics, Kind, "",
+ (COFF::COMDATType)0);
+}
+
+bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
+ unsigned Characteristics,
+ SectionKind Kind,
+ StringRef COMDATSymName,
+ COFF::COMDATType Type) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in section switching directive");
+ Lex();
+
+ getStreamer().SwitchSection(getContext().getCOFFSection(
+ Section, Characteristics, Kind, COMDATSymName, Type));
+
+ return false;
+}
+
+bool COFFMasmParser::ParseDirectiveSegment(StringRef Directive, SMLoc Loc) {
+ StringRef SegmentName;
+ if (!getLexer().is(AsmToken::Identifier))
+ return TokError("expected identifier in directive");
+ SegmentName = getTok().getIdentifier();
+ Lex();
+
+ StringRef SectionName = SegmentName;
+ SmallVector<char, 247> SectionNameVector;
+ unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE;
+ if (SegmentName == "_TEXT" || SegmentName.startswith("_TEXT$")) {
+ if (SegmentName.size() == 5) {
+ SectionName = ".text";
+ } else {
+ SectionName =
+ (".text$" + SegmentName.substr(6)).toStringRef(SectionNameVector);
+ }
+ Flags = COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE |
+ COFF::IMAGE_SCN_MEM_READ;
+ }
+ SectionKind Kind = computeSectionKind(Flags);
+ getStreamer().SwitchSection(getContext().getCOFFSection(
+ SectionName, Flags, Kind, "", (COFF::COMDATType)(0)));
+ return false;
+}
+
+/// ParseDirectiveSegmentEnd
+/// ::= identifier "ends"
+bool COFFMasmParser::ParseDirectiveSegmentEnd(StringRef Directive, SMLoc Loc) {
+ StringRef SegmentName;
+ if (!getLexer().is(AsmToken::Identifier))
+ return TokError("expected identifier in directive");
+ SegmentName = getTok().getIdentifier();
+
+ // Ignore; no action necessary.
+ Lex();
+ return false;
+}
+
+/// ParseDirectiveIncludelib
+/// ::= "includelib" identifier
+bool COFFMasmParser::ParseDirectiveIncludelib(StringRef Directive, SMLoc Loc) {
+ StringRef Lib;
+ if (getParser().parseIdentifier(Lib))
+ return TokError("expected identifier in includelib directive");
+
+ unsigned Flags = COFF::IMAGE_SCN_MEM_PRELOAD | COFF::IMAGE_SCN_MEM_16BIT;
+ SectionKind Kind = computeSectionKind(Flags);
+ getStreamer().PushSection();
+ getStreamer().SwitchSection(getContext().getCOFFSection(
+ ".drectve", Flags, Kind, "", (COFF::COMDATType)(0)));
+ getStreamer().emitBytes("/DEFAULTLIB:");
+ getStreamer().emitBytes(Lib);
+ getStreamer().emitBytes(" ");
+ getStreamer().PopSection();
+ return false;
+}
+
+/// ParseDirectiveProc
+/// TODO(epastor): Implement parameters and other attributes.
+/// ::= label "proc" [[distance]]
+/// statements
+/// label "endproc"
+bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) {
+ StringRef Label;
+ if (getParser().parseIdentifier(Label))
+ return Error(Loc, "expected identifier for procedure");
+ if (getLexer().is(AsmToken::Identifier)) {
+ StringRef nextVal = getTok().getString();
+ SMLoc nextLoc = getTok().getLoc();
+ if (nextVal.equals_lower("far")) {
+ // TODO(epastor): Handle far procedure definitions.
+ Lex();
+ return Error(nextLoc, "far procedure definitions not yet supported");
+ } else if (nextVal.equals_lower("near")) {
+ Lex();
+ nextVal = getTok().getString();
+ nextLoc = getTok().getLoc();
+ }
+ }
MCSymbolCOFF *Sym = cast<MCSymbolCOFF>(getContext().getOrCreateSymbol(Label));
-
+
// Define symbol as simple external function
Sym->setExternal(true);
Sym->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT);
-
+
bool Framed = false;
if (getLexer().is(AsmToken::Identifier) &&
getTok().getString().equals_lower("frame")) {
@@ -345,32 +345,32 @@ bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) {
Framed = true;
getStreamer().EmitWinCFIStartProc(Sym, Loc);
}
- getStreamer().emitLabel(Sym, Loc);
+ getStreamer().emitLabel(Sym, Loc);
- CurrentProcedure = Label;
+ CurrentProcedure = Label;
CurrentProcedureFramed = Framed;
- return false;
-}
-bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) {
- StringRef Label;
- SMLoc LabelLoc = getTok().getLoc();
- if (getParser().parseIdentifier(Label))
- return Error(LabelLoc, "expected identifier for procedure end");
-
- if (CurrentProcedure.empty())
- return Error(Loc, "endp outside of procedure block");
- else if (CurrentProcedure != Label)
- return Error(LabelLoc, "endp does not match current procedure '" +
- CurrentProcedure + "'");
+ return false;
+}
+bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) {
+ StringRef Label;
+ SMLoc LabelLoc = getTok().getLoc();
+ if (getParser().parseIdentifier(Label))
+ return Error(LabelLoc, "expected identifier for procedure end");
+
+ if (CurrentProcedure.empty())
+ return Error(Loc, "endp outside of procedure block");
+ else if (CurrentProcedure != Label)
+ return Error(LabelLoc, "endp does not match current procedure '" +
+ CurrentProcedure + "'");
if (CurrentProcedureFramed) {
getStreamer().EmitWinCFIEndProc(Loc);
}
CurrentProcedure = "";
CurrentProcedureFramed = false;
- return false;
-}
-
+ return false;
+}
+
bool COFFMasmParser::ParseDirectiveAlias(StringRef Directive, SMLoc Loc) {
std::string AliasName, ActualName;
if (getTok().isNot(AsmToken::Less) ||
@@ -408,8 +408,8 @@ bool COFFMasmParser::ParseSEHDirectiveEndProlog(StringRef Directive,
return false;
}
-namespace llvm {
-
-MCAsmParserExtension *createCOFFMasmParser() { return new COFFMasmParser; }
-
-} // end namespace llvm
+namespace llvm {
+
+MCAsmParserExtension *createCOFFMasmParser() { return new COFFMasmParser; }
+
+} // end namespace llvm
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/DarwinAsmParser.cpp b/contrib/libs/llvm12/lib/MC/MCParser/DarwinAsmParser.cpp
index 36e0d25660..9264834512 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/DarwinAsmParser.cpp
+++ b/contrib/libs/llvm12/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -1,1209 +1,1209 @@
-//===- DarwinAsmParser.cpp - Darwin (Mach-O) Assembly Parser --------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/SectionKind.h"
-#include "llvm/Support/FileSystem.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 <cstddef>
-#include <cstdint>
-#include <string>
-#include <system_error>
-#include <utility>
-
-using namespace llvm;
-
-namespace {
-
-/// Implementation of directive handling which is shared across all
-/// Darwin targets.
-class DarwinAsmParser : public MCAsmParserExtension {
- template<bool (DarwinAsmParser::*HandlerMethod)(StringRef, SMLoc)>
- void addDirectiveHandler(StringRef Directive) {
- MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
- this, HandleDirective<DarwinAsmParser, HandlerMethod>);
- getParser().addDirectiveHandler(Directive, Handler);
- }
-
- bool parseSectionSwitch(StringRef Segment, StringRef Section,
- unsigned TAA = 0, unsigned ImplicitAlign = 0,
- unsigned StubSize = 0);
-
- SMLoc LastVersionDirective;
-
-public:
- DarwinAsmParser() = default;
-
- void Initialize(MCAsmParser &Parser) override {
- // Call the base implementation.
- this->MCAsmParserExtension::Initialize(Parser);
-
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveAltEntry>(".alt_entry");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveDesc>(".desc");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveIndirectSymbol>(
- ".indirect_symbol");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveLsym>(".lsym");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveSubsectionsViaSymbols>(
- ".subsections_via_symbols");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".dump");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".load");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveSection>(".section");
- addDirectiveHandler<&DarwinAsmParser::parseDirectivePushSection>(
- ".pushsection");
- addDirectiveHandler<&DarwinAsmParser::parseDirectivePopSection>(
- ".popsection");
- addDirectiveHandler<&DarwinAsmParser::parseDirectivePrevious>(".previous");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogUnique>(
- ".secure_log_unique");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogReset>(
- ".secure_log_reset");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveTBSS>(".tbss");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveZerofill>(".zerofill");
-
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegion>(
- ".data_region");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegionEnd>(
- ".end_data_region");
-
- // Special section directives.
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveBss>(".bss");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConst>(".const");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstData>(
- ".const_data");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstructor>(
- ".constructor");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveCString>(
- ".cstring");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveData>(".data");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDestructor>(
- ".destructor");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDyld>(".dyld");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit0>(
- ".fvmlib_init0");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit1>(
- ".fvmlib_init1");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveLazySymbolPointers>(
- ".lazy_symbol_pointer");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveLinkerOption>(
- ".linker_option");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral16>(
- ".literal16");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral4>(
- ".literal4");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral8>(
- ".literal8");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModInitFunc>(
- ".mod_init_func");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModTermFunc>(
- ".mod_term_func");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveNonLazySymbolPointers>(
- ".non_lazy_symbol_pointer");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveThreadLocalVariablePointers>(
- ".thread_local_variable_pointer");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatClsMeth>(
- ".objc_cat_cls_meth");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatInstMeth>(
- ".objc_cat_inst_meth");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCategory>(
- ".objc_category");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClass>(
- ".objc_class");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassNames>(
- ".objc_class_names");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassVars>(
- ".objc_class_vars");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsMeth>(
- ".objc_cls_meth");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsRefs>(
- ".objc_cls_refs");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCInstMeth>(
- ".objc_inst_meth");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveObjCInstanceVars>(
- ".objc_instance_vars");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMessageRefs>(
- ".objc_message_refs");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMetaClass>(
- ".objc_meta_class");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveObjCMethVarNames>(
- ".objc_meth_var_names");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveObjCMethVarTypes>(
- ".objc_meth_var_types");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCModuleInfo>(
- ".objc_module_info");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCProtocol>(
- ".objc_protocol");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveObjCSelectorStrs>(
- ".objc_selector_strs");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveObjCStringObject>(
- ".objc_string_object");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCSymbols>(
- ".objc_symbols");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectivePICSymbolStub>(
- ".picsymbol_stub");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticConst>(
- ".static_const");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticData>(
- ".static_data");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveSymbolStub>(
- ".symbol_stub");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTData>(".tdata");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveText>(".text");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveThreadInitFunc>(
- ".thread_init_func");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(".tlv");
-
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(".ident");
- addDirectiveHandler<&DarwinAsmParser::parseWatchOSVersionMin>(
- ".watchos_version_min");
- addDirectiveHandler<&DarwinAsmParser::parseTvOSVersionMin>(
- ".tvos_version_min");
- addDirectiveHandler<&DarwinAsmParser::parseIOSVersionMin>(
- ".ios_version_min");
- addDirectiveHandler<&DarwinAsmParser::parseMacOSXVersionMin>(
- ".macosx_version_min");
- addDirectiveHandler<&DarwinAsmParser::parseBuildVersion>(".build_version");
-
- LastVersionDirective = SMLoc();
- }
-
- bool parseDirectiveAltEntry(StringRef, SMLoc);
- bool parseDirectiveDesc(StringRef, SMLoc);
- bool parseDirectiveIndirectSymbol(StringRef, SMLoc);
- bool parseDirectiveDumpOrLoad(StringRef, SMLoc);
- bool parseDirectiveLsym(StringRef, SMLoc);
- bool parseDirectiveLinkerOption(StringRef, SMLoc);
- bool parseDirectiveSection(StringRef, SMLoc);
- bool parseDirectivePushSection(StringRef, SMLoc);
- bool parseDirectivePopSection(StringRef, SMLoc);
- bool parseDirectivePrevious(StringRef, SMLoc);
- bool parseDirectiveSecureLogReset(StringRef, SMLoc);
- bool parseDirectiveSecureLogUnique(StringRef, SMLoc);
- bool parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc);
- bool parseDirectiveTBSS(StringRef, SMLoc);
- bool parseDirectiveZerofill(StringRef, SMLoc);
- bool parseDirectiveDataRegion(StringRef, SMLoc);
- bool parseDirectiveDataRegionEnd(StringRef, SMLoc);
-
- // Named Section Directive
- bool parseSectionDirectiveBss(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__bss");
- }
-
- bool parseSectionDirectiveConst(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__const");
- }
-
- bool parseSectionDirectiveStaticConst(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__static_const");
- }
-
- bool parseSectionDirectiveCString(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__cstring",
- MachO::S_CSTRING_LITERALS);
- }
-
- bool parseSectionDirectiveLiteral4(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__literal4",
- MachO::S_4BYTE_LITERALS, 4);
- }
-
- bool parseSectionDirectiveLiteral8(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__literal8",
- MachO::S_8BYTE_LITERALS, 8);
- }
-
- bool parseSectionDirectiveLiteral16(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__literal16",
- MachO::S_16BYTE_LITERALS, 16);
- }
-
- bool parseSectionDirectiveConstructor(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__constructor");
- }
-
- bool parseSectionDirectiveDestructor(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__destructor");
- }
-
- bool parseSectionDirectiveFVMLibInit0(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__fvmlib_init0");
- }
-
- bool parseSectionDirectiveFVMLibInit1(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__fvmlib_init1");
- }
-
- bool parseSectionDirectiveSymbolStub(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__symbol_stub",
- MachO::S_SYMBOL_STUBS |
- MachO::S_ATTR_PURE_INSTRUCTIONS,
- // FIXME: Different on PPC and ARM.
- 0, 16);
- }
-
- bool parseSectionDirectivePICSymbolStub(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__picsymbol_stub",
- MachO::S_SYMBOL_STUBS |
- MachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26);
- }
-
- bool parseSectionDirectiveData(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__data");
- }
-
- bool parseSectionDirectiveStaticData(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__static_data");
- }
-
- bool parseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__nl_symbol_ptr",
- MachO::S_NON_LAZY_SYMBOL_POINTERS, 4);
- }
-
- bool parseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__la_symbol_ptr",
- MachO::S_LAZY_SYMBOL_POINTERS, 4);
- }
-
- bool parseSectionDirectiveThreadLocalVariablePointers(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__thread_ptr",
- MachO::S_THREAD_LOCAL_VARIABLE_POINTERS, 4);
- }
-
- bool parseSectionDirectiveDyld(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__dyld");
- }
-
- bool parseSectionDirectiveModInitFunc(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__mod_init_func",
- MachO::S_MOD_INIT_FUNC_POINTERS, 4);
- }
-
- bool parseSectionDirectiveModTermFunc(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__mod_term_func",
- MachO::S_MOD_TERM_FUNC_POINTERS, 4);
- }
-
- bool parseSectionDirectiveConstData(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__const");
- }
-
- bool parseSectionDirectiveObjCClass(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__class",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCMetaClass(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__meta_class",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__cat_cls_meth",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__cat_inst_meth",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCProtocol(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__protocol",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCStringObject(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__string_object",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCClsMeth(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__cls_meth",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCInstMeth(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__inst_meth",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCClsRefs(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__cls_refs",
- MachO::S_ATTR_NO_DEAD_STRIP |
- MachO::S_LITERAL_POINTERS, 4);
- }
-
- bool parseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__message_refs",
- MachO::S_ATTR_NO_DEAD_STRIP |
- MachO::S_LITERAL_POINTERS, 4);
- }
-
- bool parseSectionDirectiveObjCSymbols(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__symbols",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCCategory(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__category",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCClassVars(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__class_vars",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__instance_vars",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__module_info",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCClassNames(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__cstring",
- MachO::S_CSTRING_LITERALS);
- }
-
- bool parseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__cstring",
- MachO::S_CSTRING_LITERALS);
- }
-
- bool parseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__cstring",
- MachO::S_CSTRING_LITERALS);
- }
-
- bool parseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__selector_strs",
- MachO::S_CSTRING_LITERALS);
- }
-
- bool parseSectionDirectiveTData(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__thread_data",
- MachO::S_THREAD_LOCAL_REGULAR);
- }
-
- bool parseSectionDirectiveText(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__text",
- MachO::S_ATTR_PURE_INSTRUCTIONS);
- }
-
- bool parseSectionDirectiveTLV(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__thread_vars",
- MachO::S_THREAD_LOCAL_VARIABLES);
- }
-
- bool parseSectionDirectiveIdent(StringRef, SMLoc) {
- // Darwin silently ignores the .ident directive.
- getParser().eatToEndOfStatement();
- return false;
- }
-
- bool parseSectionDirectiveThreadInitFunc(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__thread_init",
- MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
- }
-
- bool parseWatchOSVersionMin(StringRef Directive, SMLoc Loc) {
- return parseVersionMin(Directive, Loc, MCVM_WatchOSVersionMin);
- }
- bool parseTvOSVersionMin(StringRef Directive, SMLoc Loc) {
- return parseVersionMin(Directive, Loc, MCVM_TvOSVersionMin);
- }
- bool parseIOSVersionMin(StringRef Directive, SMLoc Loc) {
- return parseVersionMin(Directive, Loc, MCVM_IOSVersionMin);
- }
- bool parseMacOSXVersionMin(StringRef Directive, SMLoc Loc) {
- return parseVersionMin(Directive, Loc, MCVM_OSXVersionMin);
- }
-
- bool parseBuildVersion(StringRef Directive, SMLoc Loc);
- bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type);
- bool parseMajorMinorVersionComponent(unsigned *Major, unsigned *Minor,
- const char *VersionName);
- bool parseOptionalTrailingVersionComponent(unsigned *Component,
- const char *ComponentName);
- bool parseVersion(unsigned *Major, unsigned *Minor, unsigned *Update);
- bool parseSDKVersion(VersionTuple &SDKVersion);
- void checkVersion(StringRef Directive, StringRef Arg, SMLoc Loc,
- Triple::OSType ExpectedOS);
-};
-
-} // end anonymous namespace
-
-bool DarwinAsmParser::parseSectionSwitch(StringRef Segment, StringRef Section,
- unsigned TAA, unsigned Align,
- unsigned StubSize) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in section switching directive");
- Lex();
-
- // FIXME: Arch specific.
- bool isText = TAA & MachO::S_ATTR_PURE_INSTRUCTIONS;
- getStreamer().SwitchSection(getContext().getMachOSection(
- Segment, Section, TAA, StubSize,
- isText ? SectionKind::getText() : SectionKind::getData()));
-
- // Set the implicit alignment, if any.
- //
- // FIXME: This isn't really what 'as' does; I think it just uses the implicit
- // alignment on the section (e.g., if one manually inserts bytes into the
- // section, then just issuing the section switch directive will not realign
- // the section. However, this is arguably more reasonable behavior, and there
- // is no good reason for someone to intentionally emit incorrectly sized
- // values into the implicitly aligned sections.
- if (Align)
- getStreamer().emitValueToAlignment(Align);
-
- return false;
-}
-
-/// parseDirectiveAltEntry
-/// ::= .alt_entry identifier
-bool DarwinAsmParser::parseDirectiveAltEntry(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Look up symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (Sym->isDefined())
- return TokError(".alt_entry must preceed symbol definition");
-
- if (!getStreamer().emitSymbolAttribute(Sym, MCSA_AltEntry))
- return TokError("unable to emit symbol attribute");
-
- Lex();
- return false;
-}
-
-/// parseDirectiveDesc
-/// ::= .desc identifier , expression
-bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in '.desc' directive");
- Lex();
-
- int64_t DescValue;
- if (getParser().parseAbsoluteExpression(DescValue))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.desc' directive");
-
- Lex();
-
- // Set the n_desc field of this Symbol to this DescValue
- getStreamer().emitSymbolDesc(Sym, DescValue);
-
- return false;
-}
-
-/// parseDirectiveIndirectSymbol
-/// ::= .indirect_symbol identifier
-bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) {
- 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 &&
- SectionType != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS &&
- SectionType != MachO::S_SYMBOL_STUBS)
- return Error(Loc, "indirect symbol not in a symbol pointer or stub "
- "section");
-
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in .indirect_symbol directive");
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- // Assembler local symbols don't make any sense here. Complain loudly.
- if (Sym->isTemporary())
- return TokError("non-local symbol required in directive");
-
- if (!getStreamer().emitSymbolAttribute(Sym, MCSA_IndirectSymbol))
- return TokError("unable to emit indirect symbol attribute for: " + Name);
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.indirect_symbol' directive");
-
- Lex();
-
- return false;
-}
-
-/// parseDirectiveDumpOrLoad
-/// ::= ( .dump | .load ) "filename"
-bool DarwinAsmParser::parseDirectiveDumpOrLoad(StringRef Directive,
- SMLoc IDLoc) {
- bool IsDump = Directive == ".dump";
- if (getLexer().isNot(AsmToken::String))
- return TokError("expected string in '.dump' or '.load' directive");
-
- Lex();
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.dump' or '.load' directive");
-
- Lex();
-
- // FIXME: If/when .dump and .load are implemented they will be done in the
- // the assembly parser and not have any need for an MCStreamer API.
- if (IsDump)
- return Warning(IDLoc, "ignoring directive .dump for now");
- else
- return Warning(IDLoc, "ignoring directive .load for now");
-}
-
-/// ParseDirectiveLinkerOption
-/// ::= .linker_option "string" ( , "string" )*
-bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) {
- SmallVector<std::string, 4> Args;
- while (true) {
- if (getLexer().isNot(AsmToken::String))
- return TokError("expected string in '" + Twine(IDVal) + "' directive");
-
- std::string Data;
- if (getParser().parseEscapedString(Data))
- return true;
-
- Args.push_back(Data);
-
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
- Lex();
- }
-
- getStreamer().emitLinkerOptions(Args);
- return false;
-}
-
-/// parseDirectiveLsym
-/// ::= .lsym identifier , expression
-bool DarwinAsmParser::parseDirectiveLsym(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in '.lsym' directive");
- Lex();
-
- const MCExpr *Value;
- if (getParser().parseExpression(Value))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.lsym' directive");
-
- Lex();
-
- // We don't currently support this directive.
- //
- // FIXME: Diagnostic location!
- (void) Sym;
- return TokError("directive '.lsym' is unsupported");
-}
-
-/// parseDirectiveSection:
-/// ::= .section identifier (',' identifier)*
-bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) {
- SMLoc Loc = getLexer().getLoc();
-
- StringRef SectionName;
- if (getParser().parseIdentifier(SectionName))
- return Error(Loc, "expected identifier after '.section' directive");
-
- // Verify there is a following comma.
- if (!getLexer().is(AsmToken::Comma))
- return TokError("unexpected token in '.section' directive");
-
- std::string SectionSpec = std::string(SectionName);
- SectionSpec += ",";
-
- // Add all the tokens until the end of the line, ParseSectionSpecifier will
- // handle this.
- StringRef EOL = getLexer().LexUntilEndOfStatement();
- SectionSpec.append(EOL.begin(), EOL.end());
-
- Lex();
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.section' directive");
- Lex();
-
- StringRef Segment, Section;
- unsigned StubSize;
- unsigned TAA;
- bool TAAParsed;
- std::string ErrorStr =
- MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section,
- TAA, TAAParsed, StubSize);
-
- if (!ErrorStr.empty())
- 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();
- Triple::ArchType ArchTy = TT.getArch();
-
- if (ArchTy != Triple::ppc && ArchTy != Triple::ppc64) {
- StringRef NonCoalSection = StringSwitch<StringRef>(Section)
- .Case("__textcoal_nt", "__text")
- .Case("__const_coal", "__const")
- .Case("__datacoal_nt", "__data")
- .Default(Section);
-
- if (!Section.equals(NonCoalSection)) {
- StringRef SectionVal(Loc.getPointer());
- size_t B = SectionVal.find(',') + 1, E = SectionVal.find(',', B);
- SMLoc BLoc = SMLoc::getFromPointer(SectionVal.data() + B);
- SMLoc ELoc = SMLoc::getFromPointer(SectionVal.data() + E);
- getParser().Warning(Loc, "section \"" + Section + "\" is deprecated",
- SMRange(BLoc, ELoc));
- getParser().Note(Loc, "change section name to \"" + NonCoalSection +
- "\"", SMRange(BLoc, ELoc));
- }
- }
-
- // FIXME: Arch specific.
- bool isText = Segment == "__TEXT"; // FIXME: Hack.
- getStreamer().SwitchSection(getContext().getMachOSection(
- Segment, Section, TAA, StubSize,
- isText ? SectionKind::getText() : SectionKind::getData()));
- return false;
-}
-
-/// ParseDirectivePushSection:
-/// ::= .pushsection identifier (',' identifier)*
-bool DarwinAsmParser::parseDirectivePushSection(StringRef S, SMLoc Loc) {
- getStreamer().PushSection();
-
- if (parseDirectiveSection(S, Loc)) {
- getStreamer().PopSection();
- return true;
- }
-
- return false;
-}
-
-/// ParseDirectivePopSection:
-/// ::= .popsection
-bool DarwinAsmParser::parseDirectivePopSection(StringRef, SMLoc) {
- if (!getStreamer().PopSection())
- return TokError(".popsection without corresponding .pushsection");
- return false;
-}
-
-/// ParseDirectivePrevious:
-/// ::= .previous
-bool DarwinAsmParser::parseDirectivePrevious(StringRef DirName, SMLoc) {
- MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
- if (!PreviousSection.first)
- return TokError(".previous without corresponding .section");
- getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second);
- return false;
-}
-
-/// ParseDirectiveSecureLogUnique
-/// ::= .secure_log_unique ... message ...
-bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) {
- StringRef LogMessage = getParser().parseStringToEndOfStatement();
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.secure_log_unique' directive");
-
- if (getContext().getSecureLogUsed())
- return Error(IDLoc, ".secure_log_unique specified multiple times");
-
- // Get the secure log path.
- const char *SecureLogFile = getContext().getSecureLogFile();
- if (!SecureLogFile)
- return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE "
- "environment variable unset.");
-
- // Open the secure log file if we haven't already.
- raw_fd_ostream *OS = getContext().getSecureLog();
- if (!OS) {
- std::error_code EC;
- auto NewOS = std::make_unique<raw_fd_ostream>(
- StringRef(SecureLogFile), EC, sys::fs::OF_Append | sys::fs::OF_Text);
- if (EC)
- return Error(IDLoc, Twine("can't open secure log file: ") +
- SecureLogFile + " (" + EC.message() + ")");
- OS = NewOS.get();
- getContext().setSecureLog(std::move(NewOS));
- }
-
- // Write the message.
- unsigned CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc);
- *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier()
- << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":"
- << LogMessage + "\n";
-
- getContext().setSecureLogUsed(true);
-
- return false;
-}
-
-/// ParseDirectiveSecureLogReset
-/// ::= .secure_log_reset
-bool DarwinAsmParser::parseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.secure_log_reset' directive");
-
- Lex();
-
- getContext().setSecureLogUsed(false);
-
- return false;
-}
-
-/// parseDirectiveSubsectionsViaSymbols
-/// ::= .subsections_via_symbols
-bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.subsections_via_symbols' directive");
-
- Lex();
-
- getStreamer().emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
-
- return false;
-}
-
-/// ParseDirectiveTBSS
-/// ::= .tbss identifier, size, align
-bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) {
- SMLoc IDLoc = getLexer().getLoc();
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- int64_t Size;
- SMLoc SizeLoc = getLexer().getLoc();
- if (getParser().parseAbsoluteExpression(Size))
- return true;
-
- int64_t Pow2Alignment = 0;
- SMLoc Pow2AlignmentLoc;
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
- Pow2AlignmentLoc = getLexer().getLoc();
- if (getParser().parseAbsoluteExpression(Pow2Alignment))
- return true;
- }
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.tbss' directive");
-
- Lex();
-
- if (Size < 0)
- return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than"
- "zero");
-
- // FIXME: Diagnose overflow.
- if (Pow2Alignment < 0)
- return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less"
- "than zero");
-
- if (!Sym->isUndefined())
- return Error(IDLoc, "invalid symbol redefinition");
-
- getStreamer().emitTBSSSymbol(
- getContext().getMachOSection("__DATA", "__thread_bss",
- MachO::S_THREAD_LOCAL_ZEROFILL, 0,
- SectionKind::getThreadBSS()),
- Sym, Size, 1 << Pow2Alignment);
-
- return false;
-}
-
-/// ParseDirectiveZerofill
-/// ::= .zerofill segname , sectname [, identifier , size_expression [
-/// , align_expression ]]
-bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {
- StringRef Segment;
- if (getParser().parseIdentifier(Segment))
- return TokError("expected segment name after '.zerofill' directive");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- StringRef Section;
- SMLoc SectionLoc = getLexer().getLoc();
- if (getParser().parseIdentifier(Section))
- return TokError("expected section name after comma in '.zerofill' "
- "directive");
-
- // If this is the end of the line all that was wanted was to create the
- // the section but with no symbol.
- if (getLexer().is(AsmToken::EndOfStatement)) {
- // Create the zerofill section but no symbol
- getStreamer().emitZerofill(
- getContext().getMachOSection(Segment, Section, MachO::S_ZEROFILL, 0,
- SectionKind::getBSS()),
- /*Symbol=*/nullptr, /*Size=*/0, /*ByteAlignment=*/0, SectionLoc);
- return false;
- }
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- SMLoc IDLoc = getLexer().getLoc();
- StringRef IDStr;
- if (getParser().parseIdentifier(IDStr))
- return TokError("expected identifier in directive");
-
- // handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(IDStr);
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- int64_t Size;
- SMLoc SizeLoc = getLexer().getLoc();
- if (getParser().parseAbsoluteExpression(Size))
- return true;
-
- int64_t Pow2Alignment = 0;
- SMLoc Pow2AlignmentLoc;
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
- Pow2AlignmentLoc = getLexer().getLoc();
- if (getParser().parseAbsoluteExpression(Pow2Alignment))
- return true;
- }
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.zerofill' directive");
-
- Lex();
-
- if (Size < 0)
- return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
- "than zero");
-
- // NOTE: The alignment in the directive is a power of 2 value, the assembler
- // may internally end up wanting an alignment in bytes.
- // FIXME: Diagnose overflow.
- if (Pow2Alignment < 0)
- return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
- "can't be less than zero");
-
- if (!Sym->isUndefined())
- return Error(IDLoc, "invalid symbol redefinition");
-
- // Create the zerofill Symbol with Size and Pow2Alignment
- //
- // FIXME: Arch specific.
- getStreamer().emitZerofill(getContext().getMachOSection(
- Segment, Section, MachO::S_ZEROFILL,
- 0, SectionKind::getBSS()),
- Sym, Size, 1 << Pow2Alignment, SectionLoc);
-
- return false;
-}
-
-/// ParseDirectiveDataRegion
-/// ::= .data_region [ ( jt8 | jt16 | jt32 ) ]
-bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) {
- if (getLexer().is(AsmToken::EndOfStatement)) {
- Lex();
- getStreamer().emitDataRegion(MCDR_DataRegion);
- return false;
- }
- StringRef RegionType;
- SMLoc Loc = getParser().getTok().getLoc();
- if (getParser().parseIdentifier(RegionType))
- return TokError("expected region type after '.data_region' directive");
- int Kind = StringSwitch<int>(RegionType)
- .Case("jt8", MCDR_DataRegionJT8)
- .Case("jt16", MCDR_DataRegionJT16)
- .Case("jt32", MCDR_DataRegionJT32)
- .Default(-1);
- if (Kind == -1)
- return Error(Loc, "unknown region type in '.data_region' directive");
- Lex();
-
- getStreamer().emitDataRegion((MCDataRegionType)Kind);
- return false;
-}
-
-/// ParseDirectiveDataRegionEnd
-/// ::= .end_data_region
-bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.end_data_region' directive");
-
- Lex();
- getStreamer().emitDataRegion(MCDR_DataRegionEnd);
- return false;
-}
-
-static bool isSDKVersionToken(const AsmToken &Tok) {
- return Tok.is(AsmToken::Identifier) && Tok.getIdentifier() == "sdk_version";
-}
-
-/// parseMajorMinorVersionComponent ::= major, minor
-bool DarwinAsmParser::parseMajorMinorVersionComponent(unsigned *Major,
- unsigned *Minor,
- const char *VersionName) {
- // Get the major version number.
- if (getLexer().isNot(AsmToken::Integer))
- return TokError(Twine("invalid ") + VersionName +
- " major version number, integer expected");
- int64_t MajorVal = getLexer().getTok().getIntVal();
- if (MajorVal > 65535 || MajorVal <= 0)
- return TokError(Twine("invalid ") + VersionName + " major version number");
- *Major = (unsigned)MajorVal;
- Lex();
- if (getLexer().isNot(AsmToken::Comma))
- return TokError(Twine(VersionName) +
- " minor version number required, comma expected");
- Lex();
- // Get the minor version number.
- if (getLexer().isNot(AsmToken::Integer))
- return TokError(Twine("invalid ") + VersionName +
- " minor version number, integer expected");
- int64_t MinorVal = getLexer().getTok().getIntVal();
- if (MinorVal > 255 || MinorVal < 0)
- return TokError(Twine("invalid ") + VersionName + " minor version number");
- *Minor = MinorVal;
- Lex();
- return false;
-}
-
-/// parseOptionalTrailingVersionComponent ::= , version_number
-bool DarwinAsmParser::parseOptionalTrailingVersionComponent(
- unsigned *Component, const char *ComponentName) {
- assert(getLexer().is(AsmToken::Comma) && "comma expected");
- Lex();
- if (getLexer().isNot(AsmToken::Integer))
- return TokError(Twine("invalid ") + ComponentName +
- " version number, integer expected");
- int64_t Val = getLexer().getTok().getIntVal();
- if (Val > 255 || Val < 0)
- return TokError(Twine("invalid ") + ComponentName + " version number");
- *Component = Val;
- Lex();
- return false;
-}
-
-/// parseVersion ::= parseMajorMinorVersionComponent
-/// parseOptionalTrailingVersionComponent
-bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor,
- unsigned *Update) {
- if (parseMajorMinorVersionComponent(Major, Minor, "OS"))
- return true;
-
- // Get the update level, if specified
- *Update = 0;
- if (getLexer().is(AsmToken::EndOfStatement) ||
- isSDKVersionToken(getLexer().getTok()))
- return false;
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("invalid OS update specifier, comma expected");
- if (parseOptionalTrailingVersionComponent(Update, "OS update"))
- return true;
- return false;
-}
-
-bool DarwinAsmParser::parseSDKVersion(VersionTuple &SDKVersion) {
- assert(isSDKVersionToken(getLexer().getTok()) && "expected sdk_version");
- Lex();
- unsigned Major, Minor;
- if (parseMajorMinorVersionComponent(&Major, &Minor, "SDK"))
- return true;
- SDKVersion = VersionTuple(Major, Minor);
-
- // Get the subminor version, if specified.
- if (getLexer().is(AsmToken::Comma)) {
- unsigned Subminor;
- if (parseOptionalTrailingVersionComponent(&Subminor, "SDK subminor"))
- return true;
- SDKVersion = VersionTuple(Major, Minor, Subminor);
- }
- return false;
-}
-
-void DarwinAsmParser::checkVersion(StringRef Directive, StringRef Arg,
- SMLoc Loc, Triple::OSType ExpectedOS) {
- const Triple &Target = getContext().getObjectFileInfo()->getTargetTriple();
- if (Target.getOS() != ExpectedOS)
- Warning(Loc, Twine(Directive) +
- (Arg.empty() ? Twine() : Twine(' ') + Arg) +
- " used while targeting " + Target.getOSName());
-
- if (LastVersionDirective.isValid()) {
- Warning(Loc, "overriding previous version directive");
- Note(LastVersionDirective, "previous definition is here");
- }
- LastVersionDirective = Loc;
-}
-
-static Triple::OSType getOSTypeFromMCVM(MCVersionMinType Type) {
- switch (Type) {
- case MCVM_WatchOSVersionMin: return Triple::WatchOS;
- case MCVM_TvOSVersionMin: return Triple::TvOS;
- case MCVM_IOSVersionMin: return Triple::IOS;
- case MCVM_OSXVersionMin: return Triple::MacOSX;
- }
- llvm_unreachable("Invalid mc version min type");
-}
-
-/// parseVersionMin
-/// ::= .ios_version_min parseVersion parseSDKVersion
-/// | .macosx_version_min parseVersion parseSDKVersion
-/// | .tvos_version_min parseVersion parseSDKVersion
-/// | .watchos_version_min parseVersion parseSDKVersion
-bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc,
- MCVersionMinType Type) {
- unsigned Major;
- unsigned Minor;
- unsigned Update;
- if (parseVersion(&Major, &Minor, &Update))
- return true;
-
- VersionTuple SDKVersion;
- if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion))
- return true;
-
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(Twine(" in '") + Directive + "' directive");
-
- Triple::OSType ExpectedOS = getOSTypeFromMCVM(Type);
- checkVersion(Directive, StringRef(), Loc, ExpectedOS);
- getStreamer().emitVersionMin(Type, Major, Minor, Update, SDKVersion);
- return false;
-}
-
-static Triple::OSType getOSTypeFromPlatform(MachO::PlatformType Type) {
- switch (Type) {
- case MachO::PLATFORM_MACOS: return Triple::MacOSX;
- case MachO::PLATFORM_IOS: return Triple::IOS;
- case MachO::PLATFORM_TVOS: return Triple::TvOS;
- case MachO::PLATFORM_WATCHOS: return Triple::WatchOS;
- case MachO::PLATFORM_BRIDGEOS: /* silence warning */ break;
- case MachO::PLATFORM_MACCATALYST: return Triple::IOS;
- case MachO::PLATFORM_IOSSIMULATOR: /* silence warning */ break;
- case MachO::PLATFORM_TVOSSIMULATOR: /* silence warning */ break;
- case MachO::PLATFORM_WATCHOSSIMULATOR: /* silence warning */ break;
+//===- DarwinAsmParser.cpp - Darwin (Mach-O) Assembly Parser --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/SectionKind.h"
+#include "llvm/Support/FileSystem.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 <cstddef>
+#include <cstdint>
+#include <string>
+#include <system_error>
+#include <utility>
+
+using namespace llvm;
+
+namespace {
+
+/// Implementation of directive handling which is shared across all
+/// Darwin targets.
+class DarwinAsmParser : public MCAsmParserExtension {
+ template<bool (DarwinAsmParser::*HandlerMethod)(StringRef, SMLoc)>
+ void addDirectiveHandler(StringRef Directive) {
+ MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
+ this, HandleDirective<DarwinAsmParser, HandlerMethod>);
+ getParser().addDirectiveHandler(Directive, Handler);
+ }
+
+ bool parseSectionSwitch(StringRef Segment, StringRef Section,
+ unsigned TAA = 0, unsigned ImplicitAlign = 0,
+ unsigned StubSize = 0);
+
+ SMLoc LastVersionDirective;
+
+public:
+ DarwinAsmParser() = default;
+
+ void Initialize(MCAsmParser &Parser) override {
+ // Call the base implementation.
+ this->MCAsmParserExtension::Initialize(Parser);
+
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveAltEntry>(".alt_entry");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveDesc>(".desc");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveIndirectSymbol>(
+ ".indirect_symbol");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveLsym>(".lsym");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveSubsectionsViaSymbols>(
+ ".subsections_via_symbols");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".dump");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".load");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveSection>(".section");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectivePushSection>(
+ ".pushsection");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectivePopSection>(
+ ".popsection");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectivePrevious>(".previous");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogUnique>(
+ ".secure_log_unique");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogReset>(
+ ".secure_log_reset");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveTBSS>(".tbss");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveZerofill>(".zerofill");
+
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegion>(
+ ".data_region");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegionEnd>(
+ ".end_data_region");
+
+ // Special section directives.
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveBss>(".bss");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConst>(".const");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstData>(
+ ".const_data");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstructor>(
+ ".constructor");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveCString>(
+ ".cstring");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveData>(".data");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDestructor>(
+ ".destructor");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDyld>(".dyld");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit0>(
+ ".fvmlib_init0");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit1>(
+ ".fvmlib_init1");
+ addDirectiveHandler<
+ &DarwinAsmParser::parseSectionDirectiveLazySymbolPointers>(
+ ".lazy_symbol_pointer");
+ addDirectiveHandler<&DarwinAsmParser::parseDirectiveLinkerOption>(
+ ".linker_option");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral16>(
+ ".literal16");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral4>(
+ ".literal4");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral8>(
+ ".literal8");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModInitFunc>(
+ ".mod_init_func");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModTermFunc>(
+ ".mod_term_func");
+ addDirectiveHandler<
+ &DarwinAsmParser::parseSectionDirectiveNonLazySymbolPointers>(
+ ".non_lazy_symbol_pointer");
+ addDirectiveHandler<
+ &DarwinAsmParser::parseSectionDirectiveThreadLocalVariablePointers>(
+ ".thread_local_variable_pointer");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatClsMeth>(
+ ".objc_cat_cls_meth");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatInstMeth>(
+ ".objc_cat_inst_meth");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCategory>(
+ ".objc_category");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClass>(
+ ".objc_class");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassNames>(
+ ".objc_class_names");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassVars>(
+ ".objc_class_vars");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsMeth>(
+ ".objc_cls_meth");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsRefs>(
+ ".objc_cls_refs");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCInstMeth>(
+ ".objc_inst_meth");
+ addDirectiveHandler<
+ &DarwinAsmParser::parseSectionDirectiveObjCInstanceVars>(
+ ".objc_instance_vars");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMessageRefs>(
+ ".objc_message_refs");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMetaClass>(
+ ".objc_meta_class");
+ addDirectiveHandler<
+ &DarwinAsmParser::parseSectionDirectiveObjCMethVarNames>(
+ ".objc_meth_var_names");
+ addDirectiveHandler<
+ &DarwinAsmParser::parseSectionDirectiveObjCMethVarTypes>(
+ ".objc_meth_var_types");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCModuleInfo>(
+ ".objc_module_info");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCProtocol>(
+ ".objc_protocol");
+ addDirectiveHandler<
+ &DarwinAsmParser::parseSectionDirectiveObjCSelectorStrs>(
+ ".objc_selector_strs");
+ addDirectiveHandler<
+ &DarwinAsmParser::parseSectionDirectiveObjCStringObject>(
+ ".objc_string_object");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCSymbols>(
+ ".objc_symbols");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectivePICSymbolStub>(
+ ".picsymbol_stub");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticConst>(
+ ".static_const");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticData>(
+ ".static_data");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveSymbolStub>(
+ ".symbol_stub");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTData>(".tdata");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveText>(".text");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveThreadInitFunc>(
+ ".thread_init_func");
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(".tlv");
+
+ addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(".ident");
+ addDirectiveHandler<&DarwinAsmParser::parseWatchOSVersionMin>(
+ ".watchos_version_min");
+ addDirectiveHandler<&DarwinAsmParser::parseTvOSVersionMin>(
+ ".tvos_version_min");
+ addDirectiveHandler<&DarwinAsmParser::parseIOSVersionMin>(
+ ".ios_version_min");
+ addDirectiveHandler<&DarwinAsmParser::parseMacOSXVersionMin>(
+ ".macosx_version_min");
+ addDirectiveHandler<&DarwinAsmParser::parseBuildVersion>(".build_version");
+
+ LastVersionDirective = SMLoc();
+ }
+
+ bool parseDirectiveAltEntry(StringRef, SMLoc);
+ bool parseDirectiveDesc(StringRef, SMLoc);
+ bool parseDirectiveIndirectSymbol(StringRef, SMLoc);
+ bool parseDirectiveDumpOrLoad(StringRef, SMLoc);
+ bool parseDirectiveLsym(StringRef, SMLoc);
+ bool parseDirectiveLinkerOption(StringRef, SMLoc);
+ bool parseDirectiveSection(StringRef, SMLoc);
+ bool parseDirectivePushSection(StringRef, SMLoc);
+ bool parseDirectivePopSection(StringRef, SMLoc);
+ bool parseDirectivePrevious(StringRef, SMLoc);
+ bool parseDirectiveSecureLogReset(StringRef, SMLoc);
+ bool parseDirectiveSecureLogUnique(StringRef, SMLoc);
+ bool parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc);
+ bool parseDirectiveTBSS(StringRef, SMLoc);
+ bool parseDirectiveZerofill(StringRef, SMLoc);
+ bool parseDirectiveDataRegion(StringRef, SMLoc);
+ bool parseDirectiveDataRegionEnd(StringRef, SMLoc);
+
+ // Named Section Directive
+ bool parseSectionDirectiveBss(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__bss");
+ }
+
+ bool parseSectionDirectiveConst(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT", "__const");
+ }
+
+ bool parseSectionDirectiveStaticConst(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT", "__static_const");
+ }
+
+ bool parseSectionDirectiveCString(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT","__cstring",
+ MachO::S_CSTRING_LITERALS);
+ }
+
+ bool parseSectionDirectiveLiteral4(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT", "__literal4",
+ MachO::S_4BYTE_LITERALS, 4);
+ }
+
+ bool parseSectionDirectiveLiteral8(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT", "__literal8",
+ MachO::S_8BYTE_LITERALS, 8);
+ }
+
+ bool parseSectionDirectiveLiteral16(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT","__literal16",
+ MachO::S_16BYTE_LITERALS, 16);
+ }
+
+ bool parseSectionDirectiveConstructor(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT","__constructor");
+ }
+
+ bool parseSectionDirectiveDestructor(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT","__destructor");
+ }
+
+ bool parseSectionDirectiveFVMLibInit0(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT","__fvmlib_init0");
+ }
+
+ bool parseSectionDirectiveFVMLibInit1(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT","__fvmlib_init1");
+ }
+
+ bool parseSectionDirectiveSymbolStub(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT","__symbol_stub",
+ MachO::S_SYMBOL_STUBS |
+ MachO::S_ATTR_PURE_INSTRUCTIONS,
+ // FIXME: Different on PPC and ARM.
+ 0, 16);
+ }
+
+ bool parseSectionDirectivePICSymbolStub(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT","__picsymbol_stub",
+ MachO::S_SYMBOL_STUBS |
+ MachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26);
+ }
+
+ bool parseSectionDirectiveData(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__data");
+ }
+
+ bool parseSectionDirectiveStaticData(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__static_data");
+ }
+
+ bool parseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__nl_symbol_ptr",
+ MachO::S_NON_LAZY_SYMBOL_POINTERS, 4);
+ }
+
+ bool parseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__la_symbol_ptr",
+ MachO::S_LAZY_SYMBOL_POINTERS, 4);
+ }
+
+ bool parseSectionDirectiveThreadLocalVariablePointers(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__thread_ptr",
+ MachO::S_THREAD_LOCAL_VARIABLE_POINTERS, 4);
+ }
+
+ bool parseSectionDirectiveDyld(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__dyld");
+ }
+
+ bool parseSectionDirectiveModInitFunc(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__mod_init_func",
+ MachO::S_MOD_INIT_FUNC_POINTERS, 4);
+ }
+
+ bool parseSectionDirectiveModTermFunc(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__mod_term_func",
+ MachO::S_MOD_TERM_FUNC_POINTERS, 4);
+ }
+
+ bool parseSectionDirectiveConstData(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__const");
+ }
+
+ bool parseSectionDirectiveObjCClass(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__class",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCMetaClass(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__meta_class",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__cat_cls_meth",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__cat_inst_meth",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCProtocol(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__protocol",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCStringObject(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__string_object",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCClsMeth(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__cls_meth",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCInstMeth(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__inst_meth",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCClsRefs(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__cls_refs",
+ MachO::S_ATTR_NO_DEAD_STRIP |
+ MachO::S_LITERAL_POINTERS, 4);
+ }
+
+ bool parseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__message_refs",
+ MachO::S_ATTR_NO_DEAD_STRIP |
+ MachO::S_LITERAL_POINTERS, 4);
+ }
+
+ bool parseSectionDirectiveObjCSymbols(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__symbols",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCCategory(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__category",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCClassVars(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__class_vars",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__instance_vars",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__module_info",
+ MachO::S_ATTR_NO_DEAD_STRIP);
+ }
+
+ bool parseSectionDirectiveObjCClassNames(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT", "__cstring",
+ MachO::S_CSTRING_LITERALS);
+ }
+
+ bool parseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT", "__cstring",
+ MachO::S_CSTRING_LITERALS);
+ }
+
+ bool parseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT", "__cstring",
+ MachO::S_CSTRING_LITERALS);
+ }
+
+ bool parseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) {
+ return parseSectionSwitch("__OBJC", "__selector_strs",
+ MachO::S_CSTRING_LITERALS);
+ }
+
+ bool parseSectionDirectiveTData(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__thread_data",
+ MachO::S_THREAD_LOCAL_REGULAR);
+ }
+
+ bool parseSectionDirectiveText(StringRef, SMLoc) {
+ return parseSectionSwitch("__TEXT", "__text",
+ MachO::S_ATTR_PURE_INSTRUCTIONS);
+ }
+
+ bool parseSectionDirectiveTLV(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__thread_vars",
+ MachO::S_THREAD_LOCAL_VARIABLES);
+ }
+
+ bool parseSectionDirectiveIdent(StringRef, SMLoc) {
+ // Darwin silently ignores the .ident directive.
+ getParser().eatToEndOfStatement();
+ return false;
+ }
+
+ bool parseSectionDirectiveThreadInitFunc(StringRef, SMLoc) {
+ return parseSectionSwitch("__DATA", "__thread_init",
+ MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
+ }
+
+ bool parseWatchOSVersionMin(StringRef Directive, SMLoc Loc) {
+ return parseVersionMin(Directive, Loc, MCVM_WatchOSVersionMin);
+ }
+ bool parseTvOSVersionMin(StringRef Directive, SMLoc Loc) {
+ return parseVersionMin(Directive, Loc, MCVM_TvOSVersionMin);
+ }
+ bool parseIOSVersionMin(StringRef Directive, SMLoc Loc) {
+ return parseVersionMin(Directive, Loc, MCVM_IOSVersionMin);
+ }
+ bool parseMacOSXVersionMin(StringRef Directive, SMLoc Loc) {
+ return parseVersionMin(Directive, Loc, MCVM_OSXVersionMin);
+ }
+
+ bool parseBuildVersion(StringRef Directive, SMLoc Loc);
+ bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type);
+ bool parseMajorMinorVersionComponent(unsigned *Major, unsigned *Minor,
+ const char *VersionName);
+ bool parseOptionalTrailingVersionComponent(unsigned *Component,
+ const char *ComponentName);
+ bool parseVersion(unsigned *Major, unsigned *Minor, unsigned *Update);
+ bool parseSDKVersion(VersionTuple &SDKVersion);
+ void checkVersion(StringRef Directive, StringRef Arg, SMLoc Loc,
+ Triple::OSType ExpectedOS);
+};
+
+} // end anonymous namespace
+
+bool DarwinAsmParser::parseSectionSwitch(StringRef Segment, StringRef Section,
+ unsigned TAA, unsigned Align,
+ unsigned StubSize) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in section switching directive");
+ Lex();
+
+ // FIXME: Arch specific.
+ bool isText = TAA & MachO::S_ATTR_PURE_INSTRUCTIONS;
+ getStreamer().SwitchSection(getContext().getMachOSection(
+ Segment, Section, TAA, StubSize,
+ isText ? SectionKind::getText() : SectionKind::getData()));
+
+ // Set the implicit alignment, if any.
+ //
+ // FIXME: This isn't really what 'as' does; I think it just uses the implicit
+ // alignment on the section (e.g., if one manually inserts bytes into the
+ // section, then just issuing the section switch directive will not realign
+ // the section. However, this is arguably more reasonable behavior, and there
+ // is no good reason for someone to intentionally emit incorrectly sized
+ // values into the implicitly aligned sections.
+ if (Align)
+ getStreamer().emitValueToAlignment(Align);
+
+ return false;
+}
+
+/// parseDirectiveAltEntry
+/// ::= .alt_entry identifier
+bool DarwinAsmParser::parseDirectiveAltEntry(StringRef, SMLoc) {
+ StringRef Name;
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Look up symbol.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ if (Sym->isDefined())
+ return TokError(".alt_entry must preceed symbol definition");
+
+ if (!getStreamer().emitSymbolAttribute(Sym, MCSA_AltEntry))
+ return TokError("unable to emit symbol attribute");
+
+ Lex();
+ return false;
+}
+
+/// parseDirectiveDesc
+/// ::= .desc identifier , expression
+bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) {
+ StringRef Name;
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.desc' directive");
+ Lex();
+
+ int64_t DescValue;
+ if (getParser().parseAbsoluteExpression(DescValue))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.desc' directive");
+
+ Lex();
+
+ // Set the n_desc field of this Symbol to this DescValue
+ getStreamer().emitSymbolDesc(Sym, DescValue);
+
+ return false;
+}
+
+/// parseDirectiveIndirectSymbol
+/// ::= .indirect_symbol identifier
+bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) {
+ 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 &&
+ SectionType != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS &&
+ SectionType != MachO::S_SYMBOL_STUBS)
+ return Error(Loc, "indirect symbol not in a symbol pointer or stub "
+ "section");
+
+ StringRef Name;
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in .indirect_symbol directive");
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ // Assembler local symbols don't make any sense here. Complain loudly.
+ if (Sym->isTemporary())
+ return TokError("non-local symbol required in directive");
+
+ if (!getStreamer().emitSymbolAttribute(Sym, MCSA_IndirectSymbol))
+ return TokError("unable to emit indirect symbol attribute for: " + Name);
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.indirect_symbol' directive");
+
+ Lex();
+
+ return false;
+}
+
+/// parseDirectiveDumpOrLoad
+/// ::= ( .dump | .load ) "filename"
+bool DarwinAsmParser::parseDirectiveDumpOrLoad(StringRef Directive,
+ SMLoc IDLoc) {
+ bool IsDump = Directive == ".dump";
+ if (getLexer().isNot(AsmToken::String))
+ return TokError("expected string in '.dump' or '.load' directive");
+
+ Lex();
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.dump' or '.load' directive");
+
+ Lex();
+
+ // FIXME: If/when .dump and .load are implemented they will be done in the
+ // the assembly parser and not have any need for an MCStreamer API.
+ if (IsDump)
+ return Warning(IDLoc, "ignoring directive .dump for now");
+ else
+ return Warning(IDLoc, "ignoring directive .load for now");
+}
+
+/// ParseDirectiveLinkerOption
+/// ::= .linker_option "string" ( , "string" )*
+bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) {
+ SmallVector<std::string, 4> Args;
+ while (true) {
+ if (getLexer().isNot(AsmToken::String))
+ return TokError("expected string in '" + Twine(IDVal) + "' directive");
+
+ std::string Data;
+ if (getParser().parseEscapedString(Data))
+ return true;
+
+ Args.push_back(Data);
+
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
+ Lex();
+ }
+
+ getStreamer().emitLinkerOptions(Args);
+ return false;
+}
+
+/// parseDirectiveLsym
+/// ::= .lsym identifier , expression
+bool DarwinAsmParser::parseDirectiveLsym(StringRef, SMLoc) {
+ StringRef Name;
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.lsym' directive");
+ Lex();
+
+ const MCExpr *Value;
+ if (getParser().parseExpression(Value))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.lsym' directive");
+
+ Lex();
+
+ // We don't currently support this directive.
+ //
+ // FIXME: Diagnostic location!
+ (void) Sym;
+ return TokError("directive '.lsym' is unsupported");
+}
+
+/// parseDirectiveSection:
+/// ::= .section identifier (',' identifier)*
+bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) {
+ SMLoc Loc = getLexer().getLoc();
+
+ StringRef SectionName;
+ if (getParser().parseIdentifier(SectionName))
+ return Error(Loc, "expected identifier after '.section' directive");
+
+ // Verify there is a following comma.
+ if (!getLexer().is(AsmToken::Comma))
+ return TokError("unexpected token in '.section' directive");
+
+ std::string SectionSpec = std::string(SectionName);
+ SectionSpec += ",";
+
+ // Add all the tokens until the end of the line, ParseSectionSpecifier will
+ // handle this.
+ StringRef EOL = getLexer().LexUntilEndOfStatement();
+ SectionSpec.append(EOL.begin(), EOL.end());
+
+ Lex();
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.section' directive");
+ Lex();
+
+ StringRef Segment, Section;
+ unsigned StubSize;
+ unsigned TAA;
+ bool TAAParsed;
+ std::string ErrorStr =
+ MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section,
+ TAA, TAAParsed, StubSize);
+
+ if (!ErrorStr.empty())
+ 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();
+ Triple::ArchType ArchTy = TT.getArch();
+
+ if (ArchTy != Triple::ppc && ArchTy != Triple::ppc64) {
+ StringRef NonCoalSection = StringSwitch<StringRef>(Section)
+ .Case("__textcoal_nt", "__text")
+ .Case("__const_coal", "__const")
+ .Case("__datacoal_nt", "__data")
+ .Default(Section);
+
+ if (!Section.equals(NonCoalSection)) {
+ StringRef SectionVal(Loc.getPointer());
+ size_t B = SectionVal.find(',') + 1, E = SectionVal.find(',', B);
+ SMLoc BLoc = SMLoc::getFromPointer(SectionVal.data() + B);
+ SMLoc ELoc = SMLoc::getFromPointer(SectionVal.data() + E);
+ getParser().Warning(Loc, "section \"" + Section + "\" is deprecated",
+ SMRange(BLoc, ELoc));
+ getParser().Note(Loc, "change section name to \"" + NonCoalSection +
+ "\"", SMRange(BLoc, ELoc));
+ }
+ }
+
+ // FIXME: Arch specific.
+ bool isText = Segment == "__TEXT"; // FIXME: Hack.
+ getStreamer().SwitchSection(getContext().getMachOSection(
+ Segment, Section, TAA, StubSize,
+ isText ? SectionKind::getText() : SectionKind::getData()));
+ return false;
+}
+
+/// ParseDirectivePushSection:
+/// ::= .pushsection identifier (',' identifier)*
+bool DarwinAsmParser::parseDirectivePushSection(StringRef S, SMLoc Loc) {
+ getStreamer().PushSection();
+
+ if (parseDirectiveSection(S, Loc)) {
+ getStreamer().PopSection();
+ return true;
+ }
+
+ return false;
+}
+
+/// ParseDirectivePopSection:
+/// ::= .popsection
+bool DarwinAsmParser::parseDirectivePopSection(StringRef, SMLoc) {
+ if (!getStreamer().PopSection())
+ return TokError(".popsection without corresponding .pushsection");
+ return false;
+}
+
+/// ParseDirectivePrevious:
+/// ::= .previous
+bool DarwinAsmParser::parseDirectivePrevious(StringRef DirName, SMLoc) {
+ MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
+ if (!PreviousSection.first)
+ return TokError(".previous without corresponding .section");
+ getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second);
+ return false;
+}
+
+/// ParseDirectiveSecureLogUnique
+/// ::= .secure_log_unique ... message ...
+bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) {
+ StringRef LogMessage = getParser().parseStringToEndOfStatement();
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.secure_log_unique' directive");
+
+ if (getContext().getSecureLogUsed())
+ return Error(IDLoc, ".secure_log_unique specified multiple times");
+
+ // Get the secure log path.
+ const char *SecureLogFile = getContext().getSecureLogFile();
+ if (!SecureLogFile)
+ return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE "
+ "environment variable unset.");
+
+ // Open the secure log file if we haven't already.
+ raw_fd_ostream *OS = getContext().getSecureLog();
+ if (!OS) {
+ std::error_code EC;
+ auto NewOS = std::make_unique<raw_fd_ostream>(
+ StringRef(SecureLogFile), EC, sys::fs::OF_Append | sys::fs::OF_Text);
+ if (EC)
+ return Error(IDLoc, Twine("can't open secure log file: ") +
+ SecureLogFile + " (" + EC.message() + ")");
+ OS = NewOS.get();
+ getContext().setSecureLog(std::move(NewOS));
+ }
+
+ // Write the message.
+ unsigned CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc);
+ *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier()
+ << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":"
+ << LogMessage + "\n";
+
+ getContext().setSecureLogUsed(true);
+
+ return false;
+}
+
+/// ParseDirectiveSecureLogReset
+/// ::= .secure_log_reset
+bool DarwinAsmParser::parseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.secure_log_reset' directive");
+
+ Lex();
+
+ getContext().setSecureLogUsed(false);
+
+ return false;
+}
+
+/// parseDirectiveSubsectionsViaSymbols
+/// ::= .subsections_via_symbols
+bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.subsections_via_symbols' directive");
+
+ Lex();
+
+ getStreamer().emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
+
+ return false;
+}
+
+/// ParseDirectiveTBSS
+/// ::= .tbss identifier, size, align
+bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) {
+ SMLoc IDLoc = getLexer().getLoc();
+ StringRef Name;
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ int64_t Size;
+ SMLoc SizeLoc = getLexer().getLoc();
+ if (getParser().parseAbsoluteExpression(Size))
+ return true;
+
+ int64_t Pow2Alignment = 0;
+ SMLoc Pow2AlignmentLoc;
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+ Pow2AlignmentLoc = getLexer().getLoc();
+ if (getParser().parseAbsoluteExpression(Pow2Alignment))
+ return true;
+ }
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.tbss' directive");
+
+ Lex();
+
+ if (Size < 0)
+ return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than"
+ "zero");
+
+ // FIXME: Diagnose overflow.
+ if (Pow2Alignment < 0)
+ return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less"
+ "than zero");
+
+ if (!Sym->isUndefined())
+ return Error(IDLoc, "invalid symbol redefinition");
+
+ getStreamer().emitTBSSSymbol(
+ getContext().getMachOSection("__DATA", "__thread_bss",
+ MachO::S_THREAD_LOCAL_ZEROFILL, 0,
+ SectionKind::getThreadBSS()),
+ Sym, Size, 1 << Pow2Alignment);
+
+ return false;
+}
+
+/// ParseDirectiveZerofill
+/// ::= .zerofill segname , sectname [, identifier , size_expression [
+/// , align_expression ]]
+bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {
+ StringRef Segment;
+ if (getParser().parseIdentifier(Segment))
+ return TokError("expected segment name after '.zerofill' directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ StringRef Section;
+ SMLoc SectionLoc = getLexer().getLoc();
+ if (getParser().parseIdentifier(Section))
+ return TokError("expected section name after comma in '.zerofill' "
+ "directive");
+
+ // If this is the end of the line all that was wanted was to create the
+ // the section but with no symbol.
+ if (getLexer().is(AsmToken::EndOfStatement)) {
+ // Create the zerofill section but no symbol
+ getStreamer().emitZerofill(
+ getContext().getMachOSection(Segment, Section, MachO::S_ZEROFILL, 0,
+ SectionKind::getBSS()),
+ /*Symbol=*/nullptr, /*Size=*/0, /*ByteAlignment=*/0, SectionLoc);
+ return false;
+ }
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ SMLoc IDLoc = getLexer().getLoc();
+ StringRef IDStr;
+ if (getParser().parseIdentifier(IDStr))
+ return TokError("expected identifier in directive");
+
+ // handle the identifier as the key symbol.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(IDStr);
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ int64_t Size;
+ SMLoc SizeLoc = getLexer().getLoc();
+ if (getParser().parseAbsoluteExpression(Size))
+ return true;
+
+ int64_t Pow2Alignment = 0;
+ SMLoc Pow2AlignmentLoc;
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+ Pow2AlignmentLoc = getLexer().getLoc();
+ if (getParser().parseAbsoluteExpression(Pow2Alignment))
+ return true;
+ }
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.zerofill' directive");
+
+ Lex();
+
+ if (Size < 0)
+ return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
+ "than zero");
+
+ // NOTE: The alignment in the directive is a power of 2 value, the assembler
+ // may internally end up wanting an alignment in bytes.
+ // FIXME: Diagnose overflow.
+ if (Pow2Alignment < 0)
+ return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
+ "can't be less than zero");
+
+ if (!Sym->isUndefined())
+ return Error(IDLoc, "invalid symbol redefinition");
+
+ // Create the zerofill Symbol with Size and Pow2Alignment
+ //
+ // FIXME: Arch specific.
+ getStreamer().emitZerofill(getContext().getMachOSection(
+ Segment, Section, MachO::S_ZEROFILL,
+ 0, SectionKind::getBSS()),
+ Sym, Size, 1 << Pow2Alignment, SectionLoc);
+
+ return false;
+}
+
+/// ParseDirectiveDataRegion
+/// ::= .data_region [ ( jt8 | jt16 | jt32 ) ]
+bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) {
+ if (getLexer().is(AsmToken::EndOfStatement)) {
+ Lex();
+ getStreamer().emitDataRegion(MCDR_DataRegion);
+ return false;
+ }
+ StringRef RegionType;
+ SMLoc Loc = getParser().getTok().getLoc();
+ if (getParser().parseIdentifier(RegionType))
+ return TokError("expected region type after '.data_region' directive");
+ int Kind = StringSwitch<int>(RegionType)
+ .Case("jt8", MCDR_DataRegionJT8)
+ .Case("jt16", MCDR_DataRegionJT16)
+ .Case("jt32", MCDR_DataRegionJT32)
+ .Default(-1);
+ if (Kind == -1)
+ return Error(Loc, "unknown region type in '.data_region' directive");
+ Lex();
+
+ getStreamer().emitDataRegion((MCDataRegionType)Kind);
+ return false;
+}
+
+/// ParseDirectiveDataRegionEnd
+/// ::= .end_data_region
+bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.end_data_region' directive");
+
+ Lex();
+ getStreamer().emitDataRegion(MCDR_DataRegionEnd);
+ return false;
+}
+
+static bool isSDKVersionToken(const AsmToken &Tok) {
+ return Tok.is(AsmToken::Identifier) && Tok.getIdentifier() == "sdk_version";
+}
+
+/// parseMajorMinorVersionComponent ::= major, minor
+bool DarwinAsmParser::parseMajorMinorVersionComponent(unsigned *Major,
+ unsigned *Minor,
+ const char *VersionName) {
+ // Get the major version number.
+ if (getLexer().isNot(AsmToken::Integer))
+ return TokError(Twine("invalid ") + VersionName +
+ " major version number, integer expected");
+ int64_t MajorVal = getLexer().getTok().getIntVal();
+ if (MajorVal > 65535 || MajorVal <= 0)
+ return TokError(Twine("invalid ") + VersionName + " major version number");
+ *Major = (unsigned)MajorVal;
+ Lex();
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError(Twine(VersionName) +
+ " minor version number required, comma expected");
+ Lex();
+ // Get the minor version number.
+ if (getLexer().isNot(AsmToken::Integer))
+ return TokError(Twine("invalid ") + VersionName +
+ " minor version number, integer expected");
+ int64_t MinorVal = getLexer().getTok().getIntVal();
+ if (MinorVal > 255 || MinorVal < 0)
+ return TokError(Twine("invalid ") + VersionName + " minor version number");
+ *Minor = MinorVal;
+ Lex();
+ return false;
+}
+
+/// parseOptionalTrailingVersionComponent ::= , version_number
+bool DarwinAsmParser::parseOptionalTrailingVersionComponent(
+ unsigned *Component, const char *ComponentName) {
+ assert(getLexer().is(AsmToken::Comma) && "comma expected");
+ Lex();
+ if (getLexer().isNot(AsmToken::Integer))
+ return TokError(Twine("invalid ") + ComponentName +
+ " version number, integer expected");
+ int64_t Val = getLexer().getTok().getIntVal();
+ if (Val > 255 || Val < 0)
+ return TokError(Twine("invalid ") + ComponentName + " version number");
+ *Component = Val;
+ Lex();
+ return false;
+}
+
+/// parseVersion ::= parseMajorMinorVersionComponent
+/// parseOptionalTrailingVersionComponent
+bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor,
+ unsigned *Update) {
+ if (parseMajorMinorVersionComponent(Major, Minor, "OS"))
+ return true;
+
+ // Get the update level, if specified
+ *Update = 0;
+ if (getLexer().is(AsmToken::EndOfStatement) ||
+ isSDKVersionToken(getLexer().getTok()))
+ return false;
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("invalid OS update specifier, comma expected");
+ if (parseOptionalTrailingVersionComponent(Update, "OS update"))
+ return true;
+ return false;
+}
+
+bool DarwinAsmParser::parseSDKVersion(VersionTuple &SDKVersion) {
+ assert(isSDKVersionToken(getLexer().getTok()) && "expected sdk_version");
+ Lex();
+ unsigned Major, Minor;
+ if (parseMajorMinorVersionComponent(&Major, &Minor, "SDK"))
+ return true;
+ SDKVersion = VersionTuple(Major, Minor);
+
+ // Get the subminor version, if specified.
+ if (getLexer().is(AsmToken::Comma)) {
+ unsigned Subminor;
+ if (parseOptionalTrailingVersionComponent(&Subminor, "SDK subminor"))
+ return true;
+ SDKVersion = VersionTuple(Major, Minor, Subminor);
+ }
+ return false;
+}
+
+void DarwinAsmParser::checkVersion(StringRef Directive, StringRef Arg,
+ SMLoc Loc, Triple::OSType ExpectedOS) {
+ const Triple &Target = getContext().getObjectFileInfo()->getTargetTriple();
+ if (Target.getOS() != ExpectedOS)
+ Warning(Loc, Twine(Directive) +
+ (Arg.empty() ? Twine() : Twine(' ') + Arg) +
+ " used while targeting " + Target.getOSName());
+
+ if (LastVersionDirective.isValid()) {
+ Warning(Loc, "overriding previous version directive");
+ Note(LastVersionDirective, "previous definition is here");
+ }
+ LastVersionDirective = Loc;
+}
+
+static Triple::OSType getOSTypeFromMCVM(MCVersionMinType Type) {
+ switch (Type) {
+ case MCVM_WatchOSVersionMin: return Triple::WatchOS;
+ case MCVM_TvOSVersionMin: return Triple::TvOS;
+ case MCVM_IOSVersionMin: return Triple::IOS;
+ case MCVM_OSXVersionMin: return Triple::MacOSX;
+ }
+ llvm_unreachable("Invalid mc version min type");
+}
+
+/// parseVersionMin
+/// ::= .ios_version_min parseVersion parseSDKVersion
+/// | .macosx_version_min parseVersion parseSDKVersion
+/// | .tvos_version_min parseVersion parseSDKVersion
+/// | .watchos_version_min parseVersion parseSDKVersion
+bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc,
+ MCVersionMinType Type) {
+ unsigned Major;
+ unsigned Minor;
+ unsigned Update;
+ if (parseVersion(&Major, &Minor, &Update))
+ return true;
+
+ VersionTuple SDKVersion;
+ if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion))
+ return true;
+
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(Twine(" in '") + Directive + "' directive");
+
+ Triple::OSType ExpectedOS = getOSTypeFromMCVM(Type);
+ checkVersion(Directive, StringRef(), Loc, ExpectedOS);
+ getStreamer().emitVersionMin(Type, Major, Minor, Update, SDKVersion);
+ return false;
+}
+
+static Triple::OSType getOSTypeFromPlatform(MachO::PlatformType Type) {
+ switch (Type) {
+ case MachO::PLATFORM_MACOS: return Triple::MacOSX;
+ case MachO::PLATFORM_IOS: return Triple::IOS;
+ case MachO::PLATFORM_TVOS: return Triple::TvOS;
+ case MachO::PLATFORM_WATCHOS: return Triple::WatchOS;
+ case MachO::PLATFORM_BRIDGEOS: /* silence warning */ break;
+ case MachO::PLATFORM_MACCATALYST: return Triple::IOS;
+ case MachO::PLATFORM_IOSSIMULATOR: /* silence warning */ break;
+ case MachO::PLATFORM_TVOSSIMULATOR: /* silence warning */ break;
+ case MachO::PLATFORM_WATCHOSSIMULATOR: /* silence warning */ break;
case MachO::PLATFORM_DRIVERKIT: /* silence warning */ break;
- }
- llvm_unreachable("Invalid mach-o platform type");
-}
-
-/// parseBuildVersion
-/// ::= .build_version (macos|ios|tvos|watchos), parseVersion parseSDKVersion
-bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) {
- StringRef PlatformName;
- SMLoc PlatformLoc = getTok().getLoc();
- if (getParser().parseIdentifier(PlatformName))
- return TokError("platform name expected");
-
- unsigned Platform = StringSwitch<unsigned>(PlatformName)
- .Case("macos", MachO::PLATFORM_MACOS)
- .Case("ios", MachO::PLATFORM_IOS)
- .Case("tvos", MachO::PLATFORM_TVOS)
- .Case("watchos", MachO::PLATFORM_WATCHOS)
- .Case("macCatalyst", MachO::PLATFORM_MACCATALYST)
- .Default(0);
- if (Platform == 0)
- return Error(PlatformLoc, "unknown platform name");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("version number required, comma expected");
- Lex();
-
- unsigned Major;
- unsigned Minor;
- unsigned Update;
- if (parseVersion(&Major, &Minor, &Update))
- return true;
-
- VersionTuple SDKVersion;
- if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion))
- return true;
-
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in '.build_version' directive");
-
- Triple::OSType ExpectedOS
- = getOSTypeFromPlatform((MachO::PlatformType)Platform);
- checkVersion(Directive, PlatformName, Loc, ExpectedOS);
- getStreamer().emitBuildVersion(Platform, Major, Minor, Update, SDKVersion);
- return false;
-}
-
-
-namespace llvm {
-
-MCAsmParserExtension *createDarwinAsmParser() {
- return new DarwinAsmParser;
-}
-
-} // end llvm namespace
+ }
+ llvm_unreachable("Invalid mach-o platform type");
+}
+
+/// parseBuildVersion
+/// ::= .build_version (macos|ios|tvos|watchos), parseVersion parseSDKVersion
+bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) {
+ StringRef PlatformName;
+ SMLoc PlatformLoc = getTok().getLoc();
+ if (getParser().parseIdentifier(PlatformName))
+ return TokError("platform name expected");
+
+ unsigned Platform = StringSwitch<unsigned>(PlatformName)
+ .Case("macos", MachO::PLATFORM_MACOS)
+ .Case("ios", MachO::PLATFORM_IOS)
+ .Case("tvos", MachO::PLATFORM_TVOS)
+ .Case("watchos", MachO::PLATFORM_WATCHOS)
+ .Case("macCatalyst", MachO::PLATFORM_MACCATALYST)
+ .Default(0);
+ if (Platform == 0)
+ return Error(PlatformLoc, "unknown platform name");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("version number required, comma expected");
+ Lex();
+
+ unsigned Major;
+ unsigned Minor;
+ unsigned Update;
+ if (parseVersion(&Major, &Minor, &Update))
+ return true;
+
+ VersionTuple SDKVersion;
+ if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion))
+ return true;
+
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '.build_version' directive");
+
+ Triple::OSType ExpectedOS
+ = getOSTypeFromPlatform((MachO::PlatformType)Platform);
+ checkVersion(Directive, PlatformName, Loc, ExpectedOS);
+ getStreamer().emitBuildVersion(Platform, Major, Minor, Update, SDKVersion);
+ return false;
+}
+
+
+namespace llvm {
+
+MCAsmParserExtension *createDarwinAsmParser() {
+ return new DarwinAsmParser;
+}
+
+} // end llvm namespace
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/libs/llvm12/lib/MC/MCParser/ELFAsmParser.cpp
index 243cdc2e3e..65ac1d6b5b 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/contrib/libs/llvm12/lib/MC/MCParser/ELFAsmParser.cpp
@@ -1,888 +1,888 @@
-//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSectionELF.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/MC/SectionKind.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/SMLoc.h"
-#include <cassert>
-#include <cstdint>
-#include <utility>
-
-using namespace llvm;
-
-namespace {
-
-class ELFAsmParser : public MCAsmParserExtension {
- template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
- void addDirectiveHandler(StringRef Directive) {
- MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
- this, HandleDirective<ELFAsmParser, HandlerMethod>);
-
- getParser().addDirectiveHandler(Directive, Handler);
- }
-
- bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags,
- SectionKind Kind);
-
-public:
- ELFAsmParser() { BracketExpressionsSupported = true; }
-
- void Initialize(MCAsmParser &Parser) override {
- // Call the base implementation.
- this->MCAsmParserExtension::Initialize(Parser);
-
- addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data");
- addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text");
- addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss");
- addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata");
- addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata");
- addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss");
- addDirectiveHandler<
- &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel");
- addDirectiveHandler<
- &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro");
- addDirectiveHandler<
- &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section");
- addDirectiveHandler<
- &ELFAsmParser::ParseDirectivePushSection>(".pushsection");
- addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size");
- addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local");
- addDirectiveHandler<
- &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected");
- addDirectiveHandler<
- &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal");
- addDirectiveHandler<
- &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
- }
-
- // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
- // the best way for us to get access to it?
- bool ParseSectionDirectiveData(StringRef, SMLoc) {
- return ParseSectionSwitch(".data", ELF::SHT_PROGBITS,
- ELF::SHF_WRITE | ELF::SHF_ALLOC,
- SectionKind::getData());
- }
- bool ParseSectionDirectiveText(StringRef, SMLoc) {
- return ParseSectionSwitch(".text", ELF::SHT_PROGBITS,
- ELF::SHF_EXECINSTR |
- ELF::SHF_ALLOC, SectionKind::getText());
- }
- bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
- return ParseSectionSwitch(".bss", ELF::SHT_NOBITS,
- ELF::SHF_WRITE |
- ELF::SHF_ALLOC, SectionKind::getBSS());
- }
- bool ParseSectionDirectiveRoData(StringRef, SMLoc) {
- return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC,
- SectionKind::getReadOnly());
- }
- bool ParseSectionDirectiveTData(StringRef, SMLoc) {
- return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC |
- ELF::SHF_TLS | ELF::SHF_WRITE,
- SectionKind::getThreadData());
- }
- bool ParseSectionDirectiveTBSS(StringRef, SMLoc) {
- return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS,
- ELF::SHF_ALLOC |
- ELF::SHF_TLS | ELF::SHF_WRITE,
- SectionKind::getThreadBSS());
- }
- bool ParseSectionDirectiveDataRel(StringRef, SMLoc) {
- return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHF_WRITE,
- SectionKind::getData());
- }
- bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) {
- return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC |
- ELF::SHF_WRITE,
- SectionKind::getReadOnlyWithRel());
- }
- bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) {
- return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHF_WRITE,
- SectionKind::getData());
- }
- bool ParseDirectivePushSection(StringRef, SMLoc);
- bool ParseDirectivePopSection(StringRef, SMLoc);
- bool ParseDirectiveSection(StringRef, SMLoc);
- bool ParseDirectiveSize(StringRef, SMLoc);
- bool ParseDirectivePrevious(StringRef, SMLoc);
- bool ParseDirectiveType(StringRef, SMLoc);
- bool ParseDirectiveIdent(StringRef, SMLoc);
- bool ParseDirectiveSymver(StringRef, SMLoc);
- bool ParseDirectiveVersion(StringRef, SMLoc);
- bool ParseDirectiveWeakref(StringRef, SMLoc);
- bool ParseDirectiveSymbolAttribute(StringRef, SMLoc);
- bool ParseDirectiveSubsection(StringRef, SMLoc);
- bool ParseDirectiveCGProfile(StringRef, SMLoc);
-
-private:
- bool ParseSectionName(StringRef &SectionName);
- bool ParseSectionArguments(bool IsPush, SMLoc loc);
- unsigned parseSunStyleSectionFlags();
- bool maybeParseSectionType(StringRef &TypeName);
- bool parseMergeSize(int64_t &Size);
- bool parseGroup(StringRef &GroupName);
- bool parseLinkedToSym(MCSymbolELF *&LinkedToSym);
- bool maybeParseUniqueID(int64_t &UniqueID);
-};
-
-} // end anonymous namespace
-
-/// ParseDirectiveSymbolAttribute
-/// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]
-bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
- MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
- .Case(".weak", MCSA_Weak)
- .Case(".local", MCSA_Local)
- .Case(".hidden", MCSA_Hidden)
- .Case(".internal", MCSA_Internal)
- .Case(".protected", MCSA_Protected)
- .Default(MCSA_Invalid);
- assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- while (true) {
- StringRef Name;
-
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- getStreamer().emitSymbolAttribute(Sym, Attr);
-
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
- }
- }
-
- Lex();
- return false;
-}
-
-bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,
- unsigned Flags, SectionKind Kind) {
- const MCExpr *Subsection = nullptr;
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- if (getParser().parseExpression(Subsection))
- return true;
- }
- Lex();
-
- getStreamer().SwitchSection(getContext().getELFSection(Section, Type, Flags),
- Subsection);
-
- return false;
-}
-
-bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
- MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name));
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- const MCExpr *Expr;
- if (getParser().parseExpression(Expr))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
- Lex();
-
- getStreamer().emitELFSize(Sym, Expr);
- return false;
-}
-
-bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {
- // A section name can contain -, so we cannot just use
- // parseIdentifier.
- SMLoc FirstLoc = getLexer().getLoc();
- unsigned Size = 0;
-
- if (getLexer().is(AsmToken::String)) {
- SectionName = getTok().getIdentifier();
- Lex();
- return false;
- }
-
- while (!getParser().hasPendingError()) {
- SMLoc PrevLoc = getLexer().getLoc();
- if (getLexer().is(AsmToken::Comma) ||
- getLexer().is(AsmToken::EndOfStatement))
- break;
-
- unsigned CurSize;
- if (getLexer().is(AsmToken::String)) {
- CurSize = getTok().getIdentifier().size() + 2;
- Lex();
- } else if (getLexer().is(AsmToken::Identifier)) {
- CurSize = getTok().getIdentifier().size();
- Lex();
- } else {
- CurSize = getTok().getString().size();
- Lex();
- }
- Size += CurSize;
- SectionName = StringRef(FirstLoc.getPointer(), Size);
-
- // Make sure the following token is adjacent.
- if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer())
- break;
- }
- if (Size == 0)
- return true;
-
- return false;
-}
-
-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':
- flags |= ELF::SHF_ALLOC;
- break;
- case 'e':
- flags |= ELF::SHF_EXCLUDE;
- break;
- case 'x':
- flags |= ELF::SHF_EXECINSTR;
- break;
- case 'w':
- flags |= ELF::SHF_WRITE;
- break;
- case 'o':
- flags |= ELF::SHF_LINK_ORDER;
- break;
- case 'M':
- flags |= ELF::SHF_MERGE;
- break;
- case 'S':
- flags |= ELF::SHF_STRINGS;
- break;
- case 'T':
- flags |= ELF::SHF_TLS;
- break;
- case 'c':
- flags |= ELF::XCORE_SHF_CP_SECTION;
- break;
- case 'd':
- flags |= ELF::XCORE_SHF_DP_SECTION;
- break;
- case 'y':
- flags |= ELF::SHF_ARM_PURECODE;
- break;
- case 's':
- flags |= ELF::SHF_HEX_GPREL;
- break;
- case 'G':
- flags |= ELF::SHF_GROUP;
- break;
- case '?':
- *UseLastGroup = true;
- break;
- default:
- return -1U;
- }
- }
-
- return flags;
-}
-
-unsigned ELFAsmParser::parseSunStyleSectionFlags() {
- unsigned flags = 0;
- while (getLexer().is(AsmToken::Hash)) {
- Lex(); // Eat the #.
-
- if (!getLexer().is(AsmToken::Identifier))
- return -1U;
-
- StringRef flagId = getTok().getIdentifier();
- if (flagId == "alloc")
- flags |= ELF::SHF_ALLOC;
- else if (flagId == "execinstr")
- flags |= ELF::SHF_EXECINSTR;
- else if (flagId == "write")
- flags |= ELF::SHF_WRITE;
- else if (flagId == "tls")
- flags |= ELF::SHF_TLS;
- else
- return -1U;
-
- Lex(); // Eat the flag.
-
- if (!getLexer().is(AsmToken::Comma))
- break;
- Lex(); // Eat the comma.
- }
- return flags;
-}
-
-
-bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {
- getStreamer().PushSection();
-
- if (ParseSectionArguments(/*IsPush=*/true, loc)) {
- getStreamer().PopSection();
- return true;
- }
-
- return false;
-}
-
-bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
- if (!getStreamer().PopSection())
- return TokError(".popsection without corresponding .pushsection");
- return false;
-}
-
-bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) {
- return ParseSectionArguments(/*IsPush=*/false, loc);
-}
-
-bool ELFAsmParser::maybeParseSectionType(StringRef &TypeName) {
- MCAsmLexer &L = getLexer();
- if (L.isNot(AsmToken::Comma))
- return false;
- Lex();
- if (L.isNot(AsmToken::At) && L.isNot(AsmToken::Percent) &&
- L.isNot(AsmToken::String)) {
- if (L.getAllowAtInIdentifier())
- return TokError("expected '@<type>', '%<type>' or \"<type>\"");
- else
- return TokError("expected '%<type>' or \"<type>\"");
- }
- if (!L.is(AsmToken::String))
- Lex();
- if (L.is(AsmToken::Integer)) {
- TypeName = getTok().getString();
- Lex();
- } else if (getParser().parseIdentifier(TypeName))
- return TokError("expected identifier in directive");
- return false;
-}
-
-bool ELFAsmParser::parseMergeSize(int64_t &Size) {
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected the entry size");
- Lex();
- if (getParser().parseAbsoluteExpression(Size))
- return true;
- if (Size <= 0)
- return TokError("entry size must be positive");
- return false;
-}
-
-bool ELFAsmParser::parseGroup(StringRef &GroupName) {
- MCAsmLexer &L = getLexer();
- if (L.isNot(AsmToken::Comma))
- return TokError("expected group name");
- Lex();
- if (L.is(AsmToken::Integer)) {
- GroupName = getTok().getString();
- Lex();
- } else if (getParser().parseIdentifier(GroupName)) {
- return TokError("invalid group name");
- }
- if (L.is(AsmToken::Comma)) {
- Lex();
- StringRef Linkage;
- if (getParser().parseIdentifier(Linkage))
- return TokError("invalid linkage");
- if (Linkage != "comdat")
- return TokError("Linkage must be 'comdat'");
- }
- return false;
-}
-
-bool ELFAsmParser::parseLinkedToSym(MCSymbolELF *&LinkedToSym) {
- MCAsmLexer &L = getLexer();
- if (L.isNot(AsmToken::Comma))
- return TokError("expected linked-to symbol");
- Lex();
- StringRef Name;
- SMLoc StartLoc = L.getLoc();
+//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/MC/SectionKind.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/SMLoc.h"
+#include <cassert>
+#include <cstdint>
+#include <utility>
+
+using namespace llvm;
+
+namespace {
+
+class ELFAsmParser : public MCAsmParserExtension {
+ template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
+ void addDirectiveHandler(StringRef Directive) {
+ MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
+ this, HandleDirective<ELFAsmParser, HandlerMethod>);
+
+ getParser().addDirectiveHandler(Directive, Handler);
+ }
+
+ bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags,
+ SectionKind Kind);
+
+public:
+ ELFAsmParser() { BracketExpressionsSupported = true; }
+
+ void Initialize(MCAsmParser &Parser) override {
+ // Call the base implementation.
+ this->MCAsmParserExtension::Initialize(Parser);
+
+ addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data");
+ addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text");
+ addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss");
+ addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata");
+ addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata");
+ addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss");
+ addDirectiveHandler<
+ &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel");
+ addDirectiveHandler<
+ &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro");
+ addDirectiveHandler<
+ &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section");
+ addDirectiveHandler<
+ &ELFAsmParser::ParseDirectivePushSection>(".pushsection");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local");
+ addDirectiveHandler<
+ &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected");
+ addDirectiveHandler<
+ &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal");
+ addDirectiveHandler<
+ &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
+ }
+
+ // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
+ // the best way for us to get access to it?
+ bool ParseSectionDirectiveData(StringRef, SMLoc) {
+ return ParseSectionSwitch(".data", ELF::SHT_PROGBITS,
+ ELF::SHF_WRITE | ELF::SHF_ALLOC,
+ SectionKind::getData());
+ }
+ bool ParseSectionDirectiveText(StringRef, SMLoc) {
+ return ParseSectionSwitch(".text", ELF::SHT_PROGBITS,
+ ELF::SHF_EXECINSTR |
+ ELF::SHF_ALLOC, SectionKind::getText());
+ }
+ bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
+ return ParseSectionSwitch(".bss", ELF::SHT_NOBITS,
+ ELF::SHF_WRITE |
+ ELF::SHF_ALLOC, SectionKind::getBSS());
+ }
+ bool ParseSectionDirectiveRoData(StringRef, SMLoc) {
+ return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS,
+ ELF::SHF_ALLOC,
+ SectionKind::getReadOnly());
+ }
+ bool ParseSectionDirectiveTData(StringRef, SMLoc) {
+ return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS,
+ ELF::SHF_ALLOC |
+ ELF::SHF_TLS | ELF::SHF_WRITE,
+ SectionKind::getThreadData());
+ }
+ bool ParseSectionDirectiveTBSS(StringRef, SMLoc) {
+ return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS,
+ ELF::SHF_ALLOC |
+ ELF::SHF_TLS | ELF::SHF_WRITE,
+ SectionKind::getThreadBSS());
+ }
+ bool ParseSectionDirectiveDataRel(StringRef, SMLoc) {
+ return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS,
+ ELF::SHF_ALLOC | ELF::SHF_WRITE,
+ SectionKind::getData());
+ }
+ bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) {
+ return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS,
+ ELF::SHF_ALLOC |
+ ELF::SHF_WRITE,
+ SectionKind::getReadOnlyWithRel());
+ }
+ bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) {
+ return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS,
+ ELF::SHF_ALLOC | ELF::SHF_WRITE,
+ SectionKind::getData());
+ }
+ bool ParseDirectivePushSection(StringRef, SMLoc);
+ bool ParseDirectivePopSection(StringRef, SMLoc);
+ bool ParseDirectiveSection(StringRef, SMLoc);
+ bool ParseDirectiveSize(StringRef, SMLoc);
+ bool ParseDirectivePrevious(StringRef, SMLoc);
+ bool ParseDirectiveType(StringRef, SMLoc);
+ bool ParseDirectiveIdent(StringRef, SMLoc);
+ bool ParseDirectiveSymver(StringRef, SMLoc);
+ bool ParseDirectiveVersion(StringRef, SMLoc);
+ bool ParseDirectiveWeakref(StringRef, SMLoc);
+ bool ParseDirectiveSymbolAttribute(StringRef, SMLoc);
+ bool ParseDirectiveSubsection(StringRef, SMLoc);
+ bool ParseDirectiveCGProfile(StringRef, SMLoc);
+
+private:
+ bool ParseSectionName(StringRef &SectionName);
+ bool ParseSectionArguments(bool IsPush, SMLoc loc);
+ unsigned parseSunStyleSectionFlags();
+ bool maybeParseSectionType(StringRef &TypeName);
+ bool parseMergeSize(int64_t &Size);
+ bool parseGroup(StringRef &GroupName);
+ bool parseLinkedToSym(MCSymbolELF *&LinkedToSym);
+ bool maybeParseUniqueID(int64_t &UniqueID);
+};
+
+} // end anonymous namespace
+
+/// ParseDirectiveSymbolAttribute
+/// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]
+bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
+ MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
+ .Case(".weak", MCSA_Weak)
+ .Case(".local", MCSA_Local)
+ .Case(".hidden", MCSA_Hidden)
+ .Case(".internal", MCSA_Internal)
+ .Case(".protected", MCSA_Protected)
+ .Default(MCSA_Invalid);
+ assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ while (true) {
+ StringRef Name;
+
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ getStreamer().emitSymbolAttribute(Sym, Attr);
+
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+ }
+ }
+
+ Lex();
+ return false;
+}
+
+bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,
+ unsigned Flags, SectionKind Kind) {
+ const MCExpr *Subsection = nullptr;
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ if (getParser().parseExpression(Subsection))
+ return true;
+ }
+ Lex();
+
+ getStreamer().SwitchSection(getContext().getELFSection(Section, Type, Flags),
+ Subsection);
+
+ return false;
+}
+
+bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) {
+ StringRef Name;
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+ MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name));
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ const MCExpr *Expr;
+ if (getParser().parseExpression(Expr))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ getStreamer().emitELFSize(Sym, Expr);
+ return false;
+}
+
+bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {
+ // A section name can contain -, so we cannot just use
+ // parseIdentifier.
+ SMLoc FirstLoc = getLexer().getLoc();
+ unsigned Size = 0;
+
+ if (getLexer().is(AsmToken::String)) {
+ SectionName = getTok().getIdentifier();
+ Lex();
+ return false;
+ }
+
+ while (!getParser().hasPendingError()) {
+ SMLoc PrevLoc = getLexer().getLoc();
+ if (getLexer().is(AsmToken::Comma) ||
+ getLexer().is(AsmToken::EndOfStatement))
+ break;
+
+ unsigned CurSize;
+ if (getLexer().is(AsmToken::String)) {
+ CurSize = getTok().getIdentifier().size() + 2;
+ Lex();
+ } else if (getLexer().is(AsmToken::Identifier)) {
+ CurSize = getTok().getIdentifier().size();
+ Lex();
+ } else {
+ CurSize = getTok().getString().size();
+ Lex();
+ }
+ Size += CurSize;
+ SectionName = StringRef(FirstLoc.getPointer(), Size);
+
+ // Make sure the following token is adjacent.
+ if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer())
+ break;
+ }
+ if (Size == 0)
+ return true;
+
+ return false;
+}
+
+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':
+ flags |= ELF::SHF_ALLOC;
+ break;
+ case 'e':
+ flags |= ELF::SHF_EXCLUDE;
+ break;
+ case 'x':
+ flags |= ELF::SHF_EXECINSTR;
+ break;
+ case 'w':
+ flags |= ELF::SHF_WRITE;
+ break;
+ case 'o':
+ flags |= ELF::SHF_LINK_ORDER;
+ break;
+ case 'M':
+ flags |= ELF::SHF_MERGE;
+ break;
+ case 'S':
+ flags |= ELF::SHF_STRINGS;
+ break;
+ case 'T':
+ flags |= ELF::SHF_TLS;
+ break;
+ case 'c':
+ flags |= ELF::XCORE_SHF_CP_SECTION;
+ break;
+ case 'd':
+ flags |= ELF::XCORE_SHF_DP_SECTION;
+ break;
+ case 'y':
+ flags |= ELF::SHF_ARM_PURECODE;
+ break;
+ case 's':
+ flags |= ELF::SHF_HEX_GPREL;
+ break;
+ case 'G':
+ flags |= ELF::SHF_GROUP;
+ break;
+ case '?':
+ *UseLastGroup = true;
+ break;
+ default:
+ return -1U;
+ }
+ }
+
+ return flags;
+}
+
+unsigned ELFAsmParser::parseSunStyleSectionFlags() {
+ unsigned flags = 0;
+ while (getLexer().is(AsmToken::Hash)) {
+ Lex(); // Eat the #.
+
+ if (!getLexer().is(AsmToken::Identifier))
+ return -1U;
+
+ StringRef flagId = getTok().getIdentifier();
+ if (flagId == "alloc")
+ flags |= ELF::SHF_ALLOC;
+ else if (flagId == "execinstr")
+ flags |= ELF::SHF_EXECINSTR;
+ else if (flagId == "write")
+ flags |= ELF::SHF_WRITE;
+ else if (flagId == "tls")
+ flags |= ELF::SHF_TLS;
+ else
+ return -1U;
+
+ Lex(); // Eat the flag.
+
+ if (!getLexer().is(AsmToken::Comma))
+ break;
+ Lex(); // Eat the comma.
+ }
+ return flags;
+}
+
+
+bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {
+ getStreamer().PushSection();
+
+ if (ParseSectionArguments(/*IsPush=*/true, loc)) {
+ getStreamer().PopSection();
+ return true;
+ }
+
+ return false;
+}
+
+bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
+ if (!getStreamer().PopSection())
+ return TokError(".popsection without corresponding .pushsection");
+ return false;
+}
+
+bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) {
+ return ParseSectionArguments(/*IsPush=*/false, loc);
+}
+
+bool ELFAsmParser::maybeParseSectionType(StringRef &TypeName) {
+ MCAsmLexer &L = getLexer();
+ if (L.isNot(AsmToken::Comma))
+ return false;
+ Lex();
+ if (L.isNot(AsmToken::At) && L.isNot(AsmToken::Percent) &&
+ L.isNot(AsmToken::String)) {
+ if (L.getAllowAtInIdentifier())
+ return TokError("expected '@<type>', '%<type>' or \"<type>\"");
+ else
+ return TokError("expected '%<type>' or \"<type>\"");
+ }
+ if (!L.is(AsmToken::String))
+ Lex();
+ if (L.is(AsmToken::Integer)) {
+ TypeName = getTok().getString();
+ Lex();
+ } else if (getParser().parseIdentifier(TypeName))
+ return TokError("expected identifier in directive");
+ return false;
+}
+
+bool ELFAsmParser::parseMergeSize(int64_t &Size) {
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected the entry size");
+ Lex();
+ if (getParser().parseAbsoluteExpression(Size))
+ return true;
+ if (Size <= 0)
+ return TokError("entry size must be positive");
+ return false;
+}
+
+bool ELFAsmParser::parseGroup(StringRef &GroupName) {
+ MCAsmLexer &L = getLexer();
+ if (L.isNot(AsmToken::Comma))
+ return TokError("expected group name");
+ Lex();
+ if (L.is(AsmToken::Integer)) {
+ GroupName = getTok().getString();
+ Lex();
+ } else if (getParser().parseIdentifier(GroupName)) {
+ return TokError("invalid group name");
+ }
+ if (L.is(AsmToken::Comma)) {
+ Lex();
+ StringRef Linkage;
+ if (getParser().parseIdentifier(Linkage))
+ return TokError("invalid linkage");
+ if (Linkage != "comdat")
+ return TokError("Linkage must be 'comdat'");
+ }
+ return false;
+}
+
+bool ELFAsmParser::parseLinkedToSym(MCSymbolELF *&LinkedToSym) {
+ MCAsmLexer &L = getLexer();
+ if (L.isNot(AsmToken::Comma))
+ return TokError("expected linked-to symbol");
+ Lex();
+ StringRef Name;
+ SMLoc StartLoc = L.getLoc();
if (getParser().parseIdentifier(Name)) {
if (getParser().getTok().getString() == "0") {
getParser().Lex();
LinkedToSym = nullptr;
return false;
}
- return TokError("invalid linked-to symbol");
+ return TokError("invalid linked-to symbol");
}
- LinkedToSym = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name));
- if (!LinkedToSym || !LinkedToSym->isInSection())
- return Error(StartLoc, "linked-to symbol is not in a section: " + Name);
- return false;
-}
-
-bool ELFAsmParser::maybeParseUniqueID(int64_t &UniqueID) {
- MCAsmLexer &L = getLexer();
- if (L.isNot(AsmToken::Comma))
- return false;
- Lex();
- StringRef UniqueStr;
- if (getParser().parseIdentifier(UniqueStr))
- return TokError("expected identifier in directive");
- if (UniqueStr != "unique")
- return TokError("expected 'unique'");
- if (L.isNot(AsmToken::Comma))
- return TokError("expected commma");
- Lex();
- if (getParser().parseAbsoluteExpression(UniqueID))
- return true;
- if (UniqueID < 0)
- return TokError("unique id must be positive");
- if (!isUInt<32>(UniqueID) || UniqueID == ~0U)
- return TokError("unique id is too large");
- return false;
-}
-
-static bool hasPrefix(StringRef SectionName, StringRef Prefix) {
- return SectionName.startswith(Prefix) || SectionName == Prefix.drop_back();
-}
-
-bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
- StringRef SectionName;
-
- if (ParseSectionName(SectionName))
- return TokError("expected identifier in directive");
-
- StringRef TypeName;
- int64_t Size = 0;
- StringRef GroupName;
- unsigned Flags = 0;
- const MCExpr *Subsection = nullptr;
- bool UseLastGroup = false;
- MCSymbolELF *LinkedToSym = nullptr;
- int64_t UniqueID = ~0;
-
- // Set the defaults first.
- if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1")
- Flags |= ELF::SHF_ALLOC;
- else if (SectionName == ".fini" || SectionName == ".init" ||
- hasPrefix(SectionName, ".text."))
- Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;
- else if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" ||
- hasPrefix(SectionName, ".bss.") ||
- hasPrefix(SectionName, ".init_array.") ||
- hasPrefix(SectionName, ".fini_array.") ||
- hasPrefix(SectionName, ".preinit_array."))
- Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE;
- else if (hasPrefix(SectionName, ".tdata.") ||
- hasPrefix(SectionName, ".tbss."))
- Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS;
-
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
-
- if (IsPush && getLexer().isNot(AsmToken::String)) {
- if (getParser().parseExpression(Subsection))
- return true;
- if (getLexer().isNot(AsmToken::Comma))
- goto EndStmt;
- Lex();
- }
-
- unsigned extraFlags;
-
- if (getLexer().isNot(AsmToken::String)) {
- if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax()
- || getLexer().isNot(AsmToken::Hash))
- return TokError("expected string in directive");
- extraFlags = parseSunStyleSectionFlags();
- } else {
- StringRef FlagsStr = getTok().getStringContents();
- Lex();
- extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup);
- }
-
- if (extraFlags == -1U)
- return TokError("unknown flag");
- Flags |= extraFlags;
-
- bool Mergeable = Flags & ELF::SHF_MERGE;
- bool Group = Flags & ELF::SHF_GROUP;
- if (Group && UseLastGroup)
- return TokError("Section cannot specifiy a group name while also acting "
- "as a member of the last group");
-
- if (maybeParseSectionType(TypeName))
- return true;
-
- MCAsmLexer &L = getLexer();
- if (TypeName.empty()) {
- if (Mergeable)
- return TokError("Mergeable section must specify the type");
- if (Group)
- return TokError("Group section must specify the type");
- if (L.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
- }
-
- if (Mergeable)
- if (parseMergeSize(Size))
- return true;
- if (Group)
- if (parseGroup(GroupName))
- return true;
- if (Flags & ELF::SHF_LINK_ORDER)
- if (parseLinkedToSym(LinkedToSym))
- return true;
- if (maybeParseUniqueID(UniqueID))
- return true;
- }
-
-EndStmt:
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
- Lex();
-
- unsigned Type = ELF::SHT_PROGBITS;
-
- if (TypeName.empty()) {
- if (SectionName.startswith(".note"))
- Type = ELF::SHT_NOTE;
- else if (hasPrefix(SectionName, ".init_array."))
- Type = ELF::SHT_INIT_ARRAY;
- else if (hasPrefix(SectionName, ".bss."))
- Type = ELF::SHT_NOBITS;
- else if (hasPrefix(SectionName, ".tbss."))
- Type = ELF::SHT_NOBITS;
- else if (hasPrefix(SectionName, ".fini_array."))
- Type = ELF::SHT_FINI_ARRAY;
- else if (hasPrefix(SectionName, ".preinit_array."))
- Type = ELF::SHT_PREINIT_ARRAY;
- } else {
- if (TypeName == "init_array")
- Type = ELF::SHT_INIT_ARRAY;
- else if (TypeName == "fini_array")
- Type = ELF::SHT_FINI_ARRAY;
- else if (TypeName == "preinit_array")
- Type = ELF::SHT_PREINIT_ARRAY;
- else if (TypeName == "nobits")
- Type = ELF::SHT_NOBITS;
- else if (TypeName == "progbits")
- Type = ELF::SHT_PROGBITS;
- else if (TypeName == "note")
- Type = ELF::SHT_NOTE;
- else if (TypeName == "unwind")
- Type = ELF::SHT_X86_64_UNWIND;
- else if (TypeName == "llvm_odrtab")
- Type = ELF::SHT_LLVM_ODRTAB;
- else if (TypeName == "llvm_linker_options")
- Type = ELF::SHT_LLVM_LINKER_OPTIONS;
- else if (TypeName == "llvm_call_graph_profile")
- Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
- else if (TypeName == "llvm_dependent_libraries")
- Type = ELF::SHT_LLVM_DEPENDENT_LIBRARIES;
- else if (TypeName == "llvm_sympart")
- Type = ELF::SHT_LLVM_SYMPART;
+ LinkedToSym = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name));
+ if (!LinkedToSym || !LinkedToSym->isInSection())
+ return Error(StartLoc, "linked-to symbol is not in a section: " + Name);
+ return false;
+}
+
+bool ELFAsmParser::maybeParseUniqueID(int64_t &UniqueID) {
+ MCAsmLexer &L = getLexer();
+ if (L.isNot(AsmToken::Comma))
+ return false;
+ Lex();
+ StringRef UniqueStr;
+ if (getParser().parseIdentifier(UniqueStr))
+ return TokError("expected identifier in directive");
+ if (UniqueStr != "unique")
+ return TokError("expected 'unique'");
+ if (L.isNot(AsmToken::Comma))
+ return TokError("expected commma");
+ Lex();
+ if (getParser().parseAbsoluteExpression(UniqueID))
+ return true;
+ if (UniqueID < 0)
+ return TokError("unique id must be positive");
+ if (!isUInt<32>(UniqueID) || UniqueID == ~0U)
+ return TokError("unique id is too large");
+ return false;
+}
+
+static bool hasPrefix(StringRef SectionName, StringRef Prefix) {
+ return SectionName.startswith(Prefix) || SectionName == Prefix.drop_back();
+}
+
+bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
+ StringRef SectionName;
+
+ if (ParseSectionName(SectionName))
+ return TokError("expected identifier in directive");
+
+ StringRef TypeName;
+ int64_t Size = 0;
+ StringRef GroupName;
+ unsigned Flags = 0;
+ const MCExpr *Subsection = nullptr;
+ bool UseLastGroup = false;
+ MCSymbolELF *LinkedToSym = nullptr;
+ int64_t UniqueID = ~0;
+
+ // Set the defaults first.
+ if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1")
+ Flags |= ELF::SHF_ALLOC;
+ else if (SectionName == ".fini" || SectionName == ".init" ||
+ hasPrefix(SectionName, ".text."))
+ Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;
+ else if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" ||
+ hasPrefix(SectionName, ".bss.") ||
+ hasPrefix(SectionName, ".init_array.") ||
+ hasPrefix(SectionName, ".fini_array.") ||
+ hasPrefix(SectionName, ".preinit_array."))
+ Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE;
+ else if (hasPrefix(SectionName, ".tdata.") ||
+ hasPrefix(SectionName, ".tbss."))
+ Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS;
+
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+
+ if (IsPush && getLexer().isNot(AsmToken::String)) {
+ if (getParser().parseExpression(Subsection))
+ return true;
+ if (getLexer().isNot(AsmToken::Comma))
+ goto EndStmt;
+ Lex();
+ }
+
+ unsigned extraFlags;
+
+ if (getLexer().isNot(AsmToken::String)) {
+ if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax()
+ || getLexer().isNot(AsmToken::Hash))
+ return TokError("expected string in directive");
+ extraFlags = parseSunStyleSectionFlags();
+ } else {
+ StringRef FlagsStr = getTok().getStringContents();
+ Lex();
+ extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup);
+ }
+
+ if (extraFlags == -1U)
+ return TokError("unknown flag");
+ Flags |= extraFlags;
+
+ bool Mergeable = Flags & ELF::SHF_MERGE;
+ bool Group = Flags & ELF::SHF_GROUP;
+ if (Group && UseLastGroup)
+ return TokError("Section cannot specifiy a group name while also acting "
+ "as a member of the last group");
+
+ if (maybeParseSectionType(TypeName))
+ return true;
+
+ MCAsmLexer &L = getLexer();
+ if (TypeName.empty()) {
+ if (Mergeable)
+ return TokError("Mergeable section must specify the type");
+ if (Group)
+ return TokError("Group section must specify the type");
+ if (L.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+ }
+
+ if (Mergeable)
+ if (parseMergeSize(Size))
+ return true;
+ if (Group)
+ if (parseGroup(GroupName))
+ return true;
+ if (Flags & ELF::SHF_LINK_ORDER)
+ if (parseLinkedToSym(LinkedToSym))
+ return true;
+ if (maybeParseUniqueID(UniqueID))
+ return true;
+ }
+
+EndStmt:
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ unsigned Type = ELF::SHT_PROGBITS;
+
+ if (TypeName.empty()) {
+ if (SectionName.startswith(".note"))
+ Type = ELF::SHT_NOTE;
+ else if (hasPrefix(SectionName, ".init_array."))
+ Type = ELF::SHT_INIT_ARRAY;
+ else if (hasPrefix(SectionName, ".bss."))
+ Type = ELF::SHT_NOBITS;
+ else if (hasPrefix(SectionName, ".tbss."))
+ Type = ELF::SHT_NOBITS;
+ else if (hasPrefix(SectionName, ".fini_array."))
+ Type = ELF::SHT_FINI_ARRAY;
+ else if (hasPrefix(SectionName, ".preinit_array."))
+ Type = ELF::SHT_PREINIT_ARRAY;
+ } else {
+ if (TypeName == "init_array")
+ Type = ELF::SHT_INIT_ARRAY;
+ else if (TypeName == "fini_array")
+ Type = ELF::SHT_FINI_ARRAY;
+ else if (TypeName == "preinit_array")
+ Type = ELF::SHT_PREINIT_ARRAY;
+ else if (TypeName == "nobits")
+ Type = ELF::SHT_NOBITS;
+ else if (TypeName == "progbits")
+ Type = ELF::SHT_PROGBITS;
+ else if (TypeName == "note")
+ Type = ELF::SHT_NOTE;
+ else if (TypeName == "unwind")
+ Type = ELF::SHT_X86_64_UNWIND;
+ else if (TypeName == "llvm_odrtab")
+ Type = ELF::SHT_LLVM_ODRTAB;
+ else if (TypeName == "llvm_linker_options")
+ Type = ELF::SHT_LLVM_LINKER_OPTIONS;
+ else if (TypeName == "llvm_call_graph_profile")
+ Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
+ else if (TypeName == "llvm_dependent_libraries")
+ Type = ELF::SHT_LLVM_DEPENDENT_LIBRARIES;
+ else if (TypeName == "llvm_sympart")
+ Type = ELF::SHT_LLVM_SYMPART;
else if (TypeName == "llvm_bb_addr_map")
Type = ELF::SHT_LLVM_BB_ADDR_MAP;
- else if (TypeName.getAsInteger(0, Type))
- return TokError("unknown section type");
- }
-
- if (UseLastGroup) {
- MCSectionSubPair CurrentSection = getStreamer().getCurrentSection();
- if (const MCSectionELF *Section =
- cast_or_null<MCSectionELF>(CurrentSection.first))
- if (const MCSymbol *Group = Section->getGroup()) {
- GroupName = Group->getName();
- Flags |= ELF::SHF_GROUP;
- }
- }
-
- MCSectionELF *Section = getContext().getELFSection(
- SectionName, Type, Flags, Size, GroupName, UniqueID, LinkedToSym);
- getStreamer().SwitchSection(Section, Subsection);
- // x86-64 psABI names SHT_X86_64_UNWIND as the canonical type for .eh_frame,
- // but GNU as emits SHT_PROGBITS .eh_frame for .cfi_* directives. Don't error
- // for SHT_PROGBITS .eh_frame
- if (Section->getType() != Type &&
- !(SectionName == ".eh_frame" && Type == ELF::SHT_PROGBITS))
- Error(loc, "changed section type for " + SectionName + ", expected: 0x" +
- utohexstr(Section->getType()));
- // Check that flags are used consistently. However, the GNU assembler permits
- // to leave out in subsequent uses of the same sections; for compatibility,
- // do likewise.
- if ((Flags || Size || !TypeName.empty()) && Section->getFlags() != Flags)
- Error(loc, "changed section flags for " + SectionName + ", expected: 0x" +
- utohexstr(Section->getFlags()));
- if ((Flags || Size || !TypeName.empty()) && Section->getEntrySize() != Size)
- Error(loc, "changed section entsize for " + SectionName +
- ", expected: " + Twine(Section->getEntrySize()));
-
+ else if (TypeName.getAsInteger(0, Type))
+ return TokError("unknown section type");
+ }
+
+ if (UseLastGroup) {
+ MCSectionSubPair CurrentSection = getStreamer().getCurrentSection();
+ if (const MCSectionELF *Section =
+ cast_or_null<MCSectionELF>(CurrentSection.first))
+ if (const MCSymbol *Group = Section->getGroup()) {
+ GroupName = Group->getName();
+ Flags |= ELF::SHF_GROUP;
+ }
+ }
+
+ MCSectionELF *Section = getContext().getELFSection(
+ SectionName, Type, Flags, Size, GroupName, UniqueID, LinkedToSym);
+ getStreamer().SwitchSection(Section, Subsection);
+ // x86-64 psABI names SHT_X86_64_UNWIND as the canonical type for .eh_frame,
+ // but GNU as emits SHT_PROGBITS .eh_frame for .cfi_* directives. Don't error
+ // for SHT_PROGBITS .eh_frame
+ if (Section->getType() != Type &&
+ !(SectionName == ".eh_frame" && Type == ELF::SHT_PROGBITS))
+ Error(loc, "changed section type for " + SectionName + ", expected: 0x" +
+ utohexstr(Section->getType()));
+ // Check that flags are used consistently. However, the GNU assembler permits
+ // to leave out in subsequent uses of the same sections; for compatibility,
+ // do likewise.
+ if ((Flags || Size || !TypeName.empty()) && Section->getFlags() != Flags)
+ Error(loc, "changed section flags for " + SectionName + ", expected: 0x" +
+ utohexstr(Section->getFlags()));
+ if ((Flags || Size || !TypeName.empty()) && Section->getEntrySize() != Size)
+ Error(loc, "changed section entsize for " + SectionName +
+ ", expected: " + Twine(Section->getEntrySize()));
+
if (getContext().getGenDwarfForAssembly() &&
(Section->getFlags() & ELF::SHF_ALLOC) &&
(Section->getFlags() & ELF::SHF_EXECINSTR)) {
- bool InsertResult = getContext().addGenDwarfSection(Section);
- if (InsertResult) {
- if (getContext().getDwarfVersion() <= 2)
- Warning(loc, "DWARF2 only supports one section per compilation unit");
-
- if (!Section->getBeginSymbol()) {
- MCSymbol *SectionStartSymbol = getContext().createTempSymbol();
- getStreamer().emitLabel(SectionStartSymbol);
- Section->setBeginSymbol(SectionStartSymbol);
- }
- }
- }
-
- return false;
-}
-
-bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {
- MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
- if (PreviousSection.first == nullptr)
- return TokError(".previous without corresponding .section");
- getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second);
-
- return false;
-}
-
-static MCSymbolAttr MCAttrForString(StringRef Type) {
- return StringSwitch<MCSymbolAttr>(Type)
- .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction)
- .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject)
- .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS)
- .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon)
- .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType)
- .Cases("STT_GNU_IFUNC", "gnu_indirect_function",
- MCSA_ELF_TypeIndFunction)
- .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)
- .Default(MCSA_Invalid);
-}
-
-/// ParseDirectiveELFType
-/// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE>
-/// ::= .type identifier , #attribute
-/// ::= .type identifier , @attribute
-/// ::= .type identifier , %attribute
-/// ::= .type identifier , "attribute"
-bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- // NOTE the comma is optional in all cases. It is only documented as being
- // optional in the first case, however, GAS will silently treat the comma as
- // optional in all cases. Furthermore, although the documentation states that
- // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS
- // accepts both the upper case name as well as the lower case aliases.
- if (getLexer().is(AsmToken::Comma))
- Lex();
-
- if (getLexer().isNot(AsmToken::Identifier) &&
- getLexer().isNot(AsmToken::Hash) &&
- getLexer().isNot(AsmToken::Percent) &&
- getLexer().isNot(AsmToken::String)) {
- if (!getLexer().getAllowAtInIdentifier())
- return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', "
- "'%<type>' or \"<type>\"");
- else if (getLexer().isNot(AsmToken::At))
- return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', "
- "'%<type>' or \"<type>\"");
- }
-
- if (getLexer().isNot(AsmToken::String) &&
- getLexer().isNot(AsmToken::Identifier))
- Lex();
-
- SMLoc TypeLoc = getLexer().getLoc();
-
- StringRef Type;
- if (getParser().parseIdentifier(Type))
- return TokError("expected symbol type in directive");
-
- MCSymbolAttr Attr = MCAttrForString(Type);
- if (Attr == MCSA_Invalid)
- return Error(TypeLoc, "unsupported attribute in '.type' directive");
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.type' directive");
- Lex();
-
- getStreamer().emitSymbolAttribute(Sym, Attr);
-
- return false;
-}
-
-/// ParseDirectiveIdent
-/// ::= .ident string
-bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
- if (getLexer().isNot(AsmToken::String))
- return TokError("unexpected token in '.ident' directive");
-
- StringRef Data = getTok().getIdentifier();
-
- Lex();
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.ident' directive");
- Lex();
-
- getStreamer().emitIdent(Data);
- return false;
-}
-
-/// ParseDirectiveSymver
-/// ::= .symver foo, bar2@zed
-bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected a comma");
-
- // ARM assembly uses @ for a comment...
- // except when parsing the second parameter of the .symver directive.
- // Force the next symbol to allow @ in the identifier, which is
- // required for this directive and then reset it to its initial state.
- const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier();
- getLexer().setAllowAtInIdentifier(true);
- Lex();
- getLexer().setAllowAtInIdentifier(AllowAtInIdentifier);
-
- StringRef AliasName;
- if (getParser().parseIdentifier(AliasName))
- return TokError("expected identifier in directive");
-
- if (AliasName.find('@') == StringRef::npos)
- return TokError("expected a '@' in the name");
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().emitELFSymverDirective(AliasName, Sym);
- return false;
-}
-
-/// ParseDirectiveVersion
-/// ::= .version string
-bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) {
- if (getLexer().isNot(AsmToken::String))
- return TokError("unexpected token in '.version' directive");
-
- StringRef Data = getTok().getIdentifier();
-
- Lex();
-
- MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0);
-
- getStreamer().PushSection();
- getStreamer().SwitchSection(Note);
- getStreamer().emitInt32(Data.size() + 1); // namesz
- getStreamer().emitInt32(0); // descsz = 0 (no description).
- getStreamer().emitInt32(1); // type = NT_VERSION
- getStreamer().emitBytes(Data); // name
- getStreamer().emitInt8(0); // NUL
- getStreamer().emitValueToAlignment(4);
- getStreamer().PopSection();
- return false;
-}
-
-/// ParseDirectiveWeakref
-/// ::= .weakref foo, bar
-bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) {
- // FIXME: Share code with the other alias building directives.
-
- StringRef AliasName;
- if (getParser().parseIdentifier(AliasName))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected a comma");
-
- Lex();
-
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- getStreamer().emitWeakReference(Alias, Sym);
- return false;
-}
-
-bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) {
- const MCExpr *Subsection = nullptr;
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- if (getParser().parseExpression(Subsection))
- return true;
- }
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
-
- getStreamer().SubSection(Subsection);
- return false;
-}
-
-bool ELFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
- return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
-}
-
-namespace llvm {
-
-MCAsmParserExtension *createELFAsmParser() {
- return new ELFAsmParser;
-}
-
-} // end namespace llvm
+ bool InsertResult = getContext().addGenDwarfSection(Section);
+ if (InsertResult) {
+ if (getContext().getDwarfVersion() <= 2)
+ Warning(loc, "DWARF2 only supports one section per compilation unit");
+
+ if (!Section->getBeginSymbol()) {
+ MCSymbol *SectionStartSymbol = getContext().createTempSymbol();
+ getStreamer().emitLabel(SectionStartSymbol);
+ Section->setBeginSymbol(SectionStartSymbol);
+ }
+ }
+ }
+
+ return false;
+}
+
+bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {
+ MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
+ if (PreviousSection.first == nullptr)
+ return TokError(".previous without corresponding .section");
+ getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second);
+
+ return false;
+}
+
+static MCSymbolAttr MCAttrForString(StringRef Type) {
+ return StringSwitch<MCSymbolAttr>(Type)
+ .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction)
+ .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject)
+ .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS)
+ .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon)
+ .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType)
+ .Cases("STT_GNU_IFUNC", "gnu_indirect_function",
+ MCSA_ELF_TypeIndFunction)
+ .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)
+ .Default(MCSA_Invalid);
+}
+
+/// ParseDirectiveELFType
+/// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE>
+/// ::= .type identifier , #attribute
+/// ::= .type identifier , @attribute
+/// ::= .type identifier , %attribute
+/// ::= .type identifier , "attribute"
+bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
+ StringRef Name;
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ // NOTE the comma is optional in all cases. It is only documented as being
+ // optional in the first case, however, GAS will silently treat the comma as
+ // optional in all cases. Furthermore, although the documentation states that
+ // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS
+ // accepts both the upper case name as well as the lower case aliases.
+ if (getLexer().is(AsmToken::Comma))
+ Lex();
+
+ if (getLexer().isNot(AsmToken::Identifier) &&
+ getLexer().isNot(AsmToken::Hash) &&
+ getLexer().isNot(AsmToken::Percent) &&
+ getLexer().isNot(AsmToken::String)) {
+ if (!getLexer().getAllowAtInIdentifier())
+ return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', "
+ "'%<type>' or \"<type>\"");
+ else if (getLexer().isNot(AsmToken::At))
+ return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', "
+ "'%<type>' or \"<type>\"");
+ }
+
+ if (getLexer().isNot(AsmToken::String) &&
+ getLexer().isNot(AsmToken::Identifier))
+ Lex();
+
+ SMLoc TypeLoc = getLexer().getLoc();
+
+ StringRef Type;
+ if (getParser().parseIdentifier(Type))
+ return TokError("expected symbol type in directive");
+
+ MCSymbolAttr Attr = MCAttrForString(Type);
+ if (Attr == MCSA_Invalid)
+ return Error(TypeLoc, "unsupported attribute in '.type' directive");
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.type' directive");
+ Lex();
+
+ getStreamer().emitSymbolAttribute(Sym, Attr);
+
+ return false;
+}
+
+/// ParseDirectiveIdent
+/// ::= .ident string
+bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
+ if (getLexer().isNot(AsmToken::String))
+ return TokError("unexpected token in '.ident' directive");
+
+ StringRef Data = getTok().getIdentifier();
+
+ Lex();
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.ident' directive");
+ Lex();
+
+ getStreamer().emitIdent(Data);
+ return false;
+}
+
+/// ParseDirectiveSymver
+/// ::= .symver foo, bar2@zed
+bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {
+ StringRef Name;
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected a comma");
+
+ // ARM assembly uses @ for a comment...
+ // except when parsing the second parameter of the .symver directive.
+ // Force the next symbol to allow @ in the identifier, which is
+ // required for this directive and then reset it to its initial state.
+ const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier();
+ getLexer().setAllowAtInIdentifier(true);
+ Lex();
+ getLexer().setAllowAtInIdentifier(AllowAtInIdentifier);
+
+ StringRef AliasName;
+ if (getParser().parseIdentifier(AliasName))
+ return TokError("expected identifier in directive");
+
+ if (AliasName.find('@') == StringRef::npos)
+ return TokError("expected a '@' in the name");
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ getStreamer().emitELFSymverDirective(AliasName, Sym);
+ return false;
+}
+
+/// ParseDirectiveVersion
+/// ::= .version string
+bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) {
+ if (getLexer().isNot(AsmToken::String))
+ return TokError("unexpected token in '.version' directive");
+
+ StringRef Data = getTok().getIdentifier();
+
+ Lex();
+
+ MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0);
+
+ getStreamer().PushSection();
+ getStreamer().SwitchSection(Note);
+ getStreamer().emitInt32(Data.size() + 1); // namesz
+ getStreamer().emitInt32(0); // descsz = 0 (no description).
+ getStreamer().emitInt32(1); // type = NT_VERSION
+ getStreamer().emitBytes(Data); // name
+ getStreamer().emitInt8(0); // NUL
+ getStreamer().emitValueToAlignment(4);
+ getStreamer().PopSection();
+ return false;
+}
+
+/// ParseDirectiveWeakref
+/// ::= .weakref foo, bar
+bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) {
+ // FIXME: Share code with the other alias building directives.
+
+ StringRef AliasName;
+ if (getParser().parseIdentifier(AliasName))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected a comma");
+
+ Lex();
+
+ StringRef Name;
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ getStreamer().emitWeakReference(Alias, Sym);
+ return false;
+}
+
+bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) {
+ const MCExpr *Subsection = nullptr;
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ if (getParser().parseExpression(Subsection))
+ return true;
+ }
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ Lex();
+
+ getStreamer().SubSection(Subsection);
+ return false;
+}
+
+bool ELFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
+ return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
+}
+
+namespace llvm {
+
+MCAsmParserExtension *createELFAsmParser() {
+ return new ELFAsmParser;
+}
+
+} // end namespace llvm
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/MCAsmLexer.cpp b/contrib/libs/llvm12/lib/MC/MCParser/MCAsmLexer.cpp
index 8907716438..497055bc17 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/MCAsmLexer.cpp
+++ b/contrib/libs/llvm12/lib/MC/MCParser/MCAsmLexer.cpp
@@ -1,129 +1,129 @@
-//===- MCAsmLexer.cpp - Abstract Asm Lexer Interface ----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-MCAsmLexer::MCAsmLexer() {
- CurTok.emplace_back(AsmToken::Space, StringRef());
-}
-
-MCAsmLexer::~MCAsmLexer() = default;
-
-SMLoc MCAsmLexer::getLoc() const {
- return SMLoc::getFromPointer(TokStart);
-}
-
-SMLoc AsmToken::getLoc() const {
- return SMLoc::getFromPointer(Str.data());
-}
-
-SMLoc AsmToken::getEndLoc() const {
- return SMLoc::getFromPointer(Str.data() + Str.size());
-}
-
-SMRange AsmToken::getLocRange() const {
- return SMRange(getLoc(), getEndLoc());
-}
-
-void AsmToken::dump(raw_ostream &OS) const {
- switch (Kind) {
- case AsmToken::Error:
- OS << "error";
- break;
- case AsmToken::Identifier:
- OS << "identifier: " << getString();
- break;
- case AsmToken::Integer:
- OS << "int: " << getString();
- break;
- case AsmToken::Real:
- OS << "real: " << getString();
- break;
- case AsmToken::String:
- OS << "string: " << getString();
- break;
-
- case AsmToken::Amp: OS << "Amp"; break;
- case AsmToken::AmpAmp: OS << "AmpAmp"; break;
- case AsmToken::At: OS << "At"; break;
- case AsmToken::BackSlash: OS << "BackSlash"; break;
- case AsmToken::BigNum: OS << "BigNum"; break;
- case AsmToken::Caret: OS << "Caret"; break;
- case AsmToken::Colon: OS << "Colon"; break;
- case AsmToken::Comma: OS << "Comma"; break;
- case AsmToken::Comment: OS << "Comment"; break;
- case AsmToken::Dollar: OS << "Dollar"; break;
- case AsmToken::Dot: OS << "Dot"; break;
- case AsmToken::EndOfStatement: OS << "EndOfStatement"; break;
- case AsmToken::Eof: OS << "Eof"; break;
- case AsmToken::Equal: OS << "Equal"; break;
- case AsmToken::EqualEqual: OS << "EqualEqual"; break;
- case AsmToken::Exclaim: OS << "Exclaim"; break;
- case AsmToken::ExclaimEqual: OS << "ExclaimEqual"; break;
- case AsmToken::Greater: OS << "Greater"; break;
- case AsmToken::GreaterEqual: OS << "GreaterEqual"; break;
- case AsmToken::GreaterGreater: OS << "GreaterGreater"; break;
- case AsmToken::Hash: OS << "Hash"; break;
- case AsmToken::HashDirective: OS << "HashDirective"; break;
- case AsmToken::LBrac: OS << "LBrac"; break;
- case AsmToken::LCurly: OS << "LCurly"; break;
- case AsmToken::LParen: OS << "LParen"; break;
- case AsmToken::Less: OS << "Less"; break;
- case AsmToken::LessEqual: OS << "LessEqual"; break;
- case AsmToken::LessGreater: OS << "LessGreater"; break;
- case AsmToken::LessLess: OS << "LessLess"; break;
- case AsmToken::Minus: OS << "Minus"; break;
- case AsmToken::MinusGreater: OS << "MinusGreater"; break;
- case AsmToken::Percent: OS << "Percent"; break;
- case AsmToken::Pipe: OS << "Pipe"; break;
- case AsmToken::PipePipe: OS << "PipePipe"; break;
- case AsmToken::Plus: OS << "Plus"; break;
- case AsmToken::RBrac: OS << "RBrac"; break;
- case AsmToken::RCurly: OS << "RCurly"; break;
- case AsmToken::RParen: OS << "RParen"; break;
- case AsmToken::Slash: OS << "Slash"; break;
- case AsmToken::Space: OS << "Space"; break;
- case AsmToken::Star: OS << "Star"; break;
- case AsmToken::Tilde: OS << "Tilde"; break;
- case AsmToken::PercentCall16: OS << "PercentCall16"; break;
- case AsmToken::PercentCall_Hi: OS << "PercentCall_Hi"; break;
- case AsmToken::PercentCall_Lo: OS << "PercentCall_Lo"; break;
- case AsmToken::PercentDtprel_Hi: OS << "PercentDtprel_Hi"; break;
- case AsmToken::PercentDtprel_Lo: OS << "PercentDtprel_Lo"; break;
- case AsmToken::PercentGot: OS << "PercentGot"; break;
- case AsmToken::PercentGot_Disp: OS << "PercentGot_Disp"; break;
- case AsmToken::PercentGot_Hi: OS << "PercentGot_Hi"; break;
- case AsmToken::PercentGot_Lo: OS << "PercentGot_Lo"; break;
- case AsmToken::PercentGot_Ofst: OS << "PercentGot_Ofst"; break;
- case AsmToken::PercentGot_Page: OS << "PercentGot_Page"; break;
- case AsmToken::PercentGottprel: OS << "PercentGottprel"; break;
- case AsmToken::PercentGp_Rel: OS << "PercentGp_Rel"; break;
- case AsmToken::PercentHi: OS << "PercentHi"; break;
- case AsmToken::PercentHigher: OS << "PercentHigher"; break;
- case AsmToken::PercentHighest: OS << "PercentHighest"; break;
- case AsmToken::PercentLo: OS << "PercentLo"; break;
- case AsmToken::PercentNeg: OS << "PercentNeg"; break;
- case AsmToken::PercentPcrel_Hi: OS << "PercentPcrel_Hi"; break;
- case AsmToken::PercentPcrel_Lo: OS << "PercentPcrel_Lo"; break;
- case AsmToken::PercentTlsgd: OS << "PercentTlsgd"; break;
- case AsmToken::PercentTlsldm: OS << "PercentTlsldm"; break;
- case AsmToken::PercentTprel_Hi: OS << "PercentTprel_Hi"; break;
- case AsmToken::PercentTprel_Lo: OS << "PercentTprel_Lo"; break;
- }
-
- // Print the token string.
- OS << " (\"";
- OS.write_escaped(getString());
- OS << "\")";
-}
+//===- MCAsmLexer.cpp - Abstract Asm Lexer Interface ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+MCAsmLexer::MCAsmLexer() {
+ CurTok.emplace_back(AsmToken::Space, StringRef());
+}
+
+MCAsmLexer::~MCAsmLexer() = default;
+
+SMLoc MCAsmLexer::getLoc() const {
+ return SMLoc::getFromPointer(TokStart);
+}
+
+SMLoc AsmToken::getLoc() const {
+ return SMLoc::getFromPointer(Str.data());
+}
+
+SMLoc AsmToken::getEndLoc() const {
+ return SMLoc::getFromPointer(Str.data() + Str.size());
+}
+
+SMRange AsmToken::getLocRange() const {
+ return SMRange(getLoc(), getEndLoc());
+}
+
+void AsmToken::dump(raw_ostream &OS) const {
+ switch (Kind) {
+ case AsmToken::Error:
+ OS << "error";
+ break;
+ case AsmToken::Identifier:
+ OS << "identifier: " << getString();
+ break;
+ case AsmToken::Integer:
+ OS << "int: " << getString();
+ break;
+ case AsmToken::Real:
+ OS << "real: " << getString();
+ break;
+ case AsmToken::String:
+ OS << "string: " << getString();
+ break;
+
+ case AsmToken::Amp: OS << "Amp"; break;
+ case AsmToken::AmpAmp: OS << "AmpAmp"; break;
+ case AsmToken::At: OS << "At"; break;
+ case AsmToken::BackSlash: OS << "BackSlash"; break;
+ case AsmToken::BigNum: OS << "BigNum"; break;
+ case AsmToken::Caret: OS << "Caret"; break;
+ case AsmToken::Colon: OS << "Colon"; break;
+ case AsmToken::Comma: OS << "Comma"; break;
+ case AsmToken::Comment: OS << "Comment"; break;
+ case AsmToken::Dollar: OS << "Dollar"; break;
+ case AsmToken::Dot: OS << "Dot"; break;
+ case AsmToken::EndOfStatement: OS << "EndOfStatement"; break;
+ case AsmToken::Eof: OS << "Eof"; break;
+ case AsmToken::Equal: OS << "Equal"; break;
+ case AsmToken::EqualEqual: OS << "EqualEqual"; break;
+ case AsmToken::Exclaim: OS << "Exclaim"; break;
+ case AsmToken::ExclaimEqual: OS << "ExclaimEqual"; break;
+ case AsmToken::Greater: OS << "Greater"; break;
+ case AsmToken::GreaterEqual: OS << "GreaterEqual"; break;
+ case AsmToken::GreaterGreater: OS << "GreaterGreater"; break;
+ case AsmToken::Hash: OS << "Hash"; break;
+ case AsmToken::HashDirective: OS << "HashDirective"; break;
+ case AsmToken::LBrac: OS << "LBrac"; break;
+ case AsmToken::LCurly: OS << "LCurly"; break;
+ case AsmToken::LParen: OS << "LParen"; break;
+ case AsmToken::Less: OS << "Less"; break;
+ case AsmToken::LessEqual: OS << "LessEqual"; break;
+ case AsmToken::LessGreater: OS << "LessGreater"; break;
+ case AsmToken::LessLess: OS << "LessLess"; break;
+ case AsmToken::Minus: OS << "Minus"; break;
+ case AsmToken::MinusGreater: OS << "MinusGreater"; break;
+ case AsmToken::Percent: OS << "Percent"; break;
+ case AsmToken::Pipe: OS << "Pipe"; break;
+ case AsmToken::PipePipe: OS << "PipePipe"; break;
+ case AsmToken::Plus: OS << "Plus"; break;
+ case AsmToken::RBrac: OS << "RBrac"; break;
+ case AsmToken::RCurly: OS << "RCurly"; break;
+ case AsmToken::RParen: OS << "RParen"; break;
+ case AsmToken::Slash: OS << "Slash"; break;
+ case AsmToken::Space: OS << "Space"; break;
+ case AsmToken::Star: OS << "Star"; break;
+ case AsmToken::Tilde: OS << "Tilde"; break;
+ case AsmToken::PercentCall16: OS << "PercentCall16"; break;
+ case AsmToken::PercentCall_Hi: OS << "PercentCall_Hi"; break;
+ case AsmToken::PercentCall_Lo: OS << "PercentCall_Lo"; break;
+ case AsmToken::PercentDtprel_Hi: OS << "PercentDtprel_Hi"; break;
+ case AsmToken::PercentDtprel_Lo: OS << "PercentDtprel_Lo"; break;
+ case AsmToken::PercentGot: OS << "PercentGot"; break;
+ case AsmToken::PercentGot_Disp: OS << "PercentGot_Disp"; break;
+ case AsmToken::PercentGot_Hi: OS << "PercentGot_Hi"; break;
+ case AsmToken::PercentGot_Lo: OS << "PercentGot_Lo"; break;
+ case AsmToken::PercentGot_Ofst: OS << "PercentGot_Ofst"; break;
+ case AsmToken::PercentGot_Page: OS << "PercentGot_Page"; break;
+ case AsmToken::PercentGottprel: OS << "PercentGottprel"; break;
+ case AsmToken::PercentGp_Rel: OS << "PercentGp_Rel"; break;
+ case AsmToken::PercentHi: OS << "PercentHi"; break;
+ case AsmToken::PercentHigher: OS << "PercentHigher"; break;
+ case AsmToken::PercentHighest: OS << "PercentHighest"; break;
+ case AsmToken::PercentLo: OS << "PercentLo"; break;
+ case AsmToken::PercentNeg: OS << "PercentNeg"; break;
+ case AsmToken::PercentPcrel_Hi: OS << "PercentPcrel_Hi"; break;
+ case AsmToken::PercentPcrel_Lo: OS << "PercentPcrel_Lo"; break;
+ case AsmToken::PercentTlsgd: OS << "PercentTlsgd"; break;
+ case AsmToken::PercentTlsldm: OS << "PercentTlsldm"; break;
+ case AsmToken::PercentTprel_Hi: OS << "PercentTprel_Hi"; break;
+ case AsmToken::PercentTprel_Lo: OS << "PercentTprel_Lo"; break;
+ }
+
+ // Print the token string.
+ OS << " (\"";
+ OS.write_escaped(getString());
+ OS << "\")";
+}
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/MCAsmParser.cpp b/contrib/libs/llvm12/lib/MC/MCParser/MCAsmParser.cpp
index 0bf21343a1..c2fa7be56a 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/MCAsmParser.cpp
+++ b/contrib/libs/llvm12/lib/MC/MCParser/MCAsmParser.cpp
@@ -1,141 +1,141 @@
-//===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
-#include "llvm/MC/MCParser/MCTargetAsmParser.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-
-using namespace llvm;
-
-cl::opt<unsigned> AsmMacroMaxNestingDepth(
- "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,
- cl::desc("The maximum nesting depth allowed for assembly macros."));
-
-MCAsmParser::MCAsmParser() {}
-
-MCAsmParser::~MCAsmParser() = default;
-
-void MCAsmParser::setTargetParser(MCTargetAsmParser &P) {
- assert(!TargetParser && "Target parser is already initialized!");
- TargetParser = &P;
- TargetParser->Initialize(*this);
-}
-
-const AsmToken &MCAsmParser::getTok() const {
- return getLexer().getTok();
-}
-
-bool MCAsmParser::parseTokenLoc(SMLoc &Loc) {
- Loc = getTok().getLoc();
- return false;
-}
-
-bool MCAsmParser::parseEOL(const Twine &Msg) {
- 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 (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) {
-
- 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(function_ref<bool()> parseOne, bool hasComma) {
- if (parseOptionalToken(AsmToken::EndOfStatement))
- return false;
- while (true) {
- 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);
-}
-
-void MCParsedAsmOperand::dump() const {
- // Cannot completely remove virtual function even in release mode.
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- dbgs() << " " << *this;
-#endif
-}
+//===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+
+using namespace llvm;
+
+cl::opt<unsigned> AsmMacroMaxNestingDepth(
+ "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,
+ cl::desc("The maximum nesting depth allowed for assembly macros."));
+
+MCAsmParser::MCAsmParser() {}
+
+MCAsmParser::~MCAsmParser() = default;
+
+void MCAsmParser::setTargetParser(MCTargetAsmParser &P) {
+ assert(!TargetParser && "Target parser is already initialized!");
+ TargetParser = &P;
+ TargetParser->Initialize(*this);
+}
+
+const AsmToken &MCAsmParser::getTok() const {
+ return getLexer().getTok();
+}
+
+bool MCAsmParser::parseTokenLoc(SMLoc &Loc) {
+ Loc = getTok().getLoc();
+ return false;
+}
+
+bool MCAsmParser::parseEOL(const Twine &Msg) {
+ 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 (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) {
+
+ 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(function_ref<bool()> parseOne, bool hasComma) {
+ if (parseOptionalToken(AsmToken::EndOfStatement))
+ return false;
+ while (true) {
+ 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);
+}
+
+void MCParsedAsmOperand::dump() const {
+ // Cannot completely remove virtual function even in release mode.
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ dbgs() << " " << *this;
+#endif
+}
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/MCAsmParserExtension.cpp b/contrib/libs/llvm12/lib/MC/MCParser/MCAsmParserExtension.cpp
index 5dbc65645b..0b5046cd8f 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/MCAsmParserExtension.cpp
+++ b/contrib/libs/llvm12/lib/MC/MCParser/MCAsmParserExtension.cpp
@@ -1,62 +1,62 @@
-//===- MCAsmParserExtension.cpp - Asm Parser Hooks ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCStreamer.h"
-
-using namespace llvm;
-
-MCAsmParserExtension::MCAsmParserExtension() = default;
-
-MCAsmParserExtension::~MCAsmParserExtension() = default;
-
-void MCAsmParserExtension::Initialize(MCAsmParser &Parser) {
- this->Parser = &Parser;
-}
-
-/// ParseDirectiveCGProfile
-/// ::= .cg_profile identifier, identifier, <number>
-bool MCAsmParserExtension::ParseDirectiveCGProfile(StringRef, SMLoc) {
- StringRef From;
- SMLoc FromLoc = getLexer().getLoc();
- if (getParser().parseIdentifier(From))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected a comma");
- Lex();
-
- StringRef To;
- SMLoc ToLoc = getLexer().getLoc();
- if (getParser().parseIdentifier(To))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected a comma");
- Lex();
-
- int64_t Count;
- if (getParser().parseIntToken(
- Count, "expected integer count in '.cg_profile' directive"))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *FromSym = getContext().getOrCreateSymbol(From);
- MCSymbol *ToSym = getContext().getOrCreateSymbol(To);
-
- getStreamer().emitCGProfileEntry(
- MCSymbolRefExpr::create(FromSym, MCSymbolRefExpr::VK_None, getContext(),
- FromLoc),
- MCSymbolRefExpr::create(ToSym, MCSymbolRefExpr::VK_None, getContext(),
- ToLoc),
- Count);
- return false;
-}
+//===- MCAsmParserExtension.cpp - Asm Parser Hooks ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCStreamer.h"
+
+using namespace llvm;
+
+MCAsmParserExtension::MCAsmParserExtension() = default;
+
+MCAsmParserExtension::~MCAsmParserExtension() = default;
+
+void MCAsmParserExtension::Initialize(MCAsmParser &Parser) {
+ this->Parser = &Parser;
+}
+
+/// ParseDirectiveCGProfile
+/// ::= .cg_profile identifier, identifier, <number>
+bool MCAsmParserExtension::ParseDirectiveCGProfile(StringRef, SMLoc) {
+ StringRef From;
+ SMLoc FromLoc = getLexer().getLoc();
+ if (getParser().parseIdentifier(From))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected a comma");
+ Lex();
+
+ StringRef To;
+ SMLoc ToLoc = getLexer().getLoc();
+ if (getParser().parseIdentifier(To))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected a comma");
+ Lex();
+
+ int64_t Count;
+ if (getParser().parseIntToken(
+ Count, "expected integer count in '.cg_profile' directive"))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ MCSymbol *FromSym = getContext().getOrCreateSymbol(From);
+ MCSymbol *ToSym = getContext().getOrCreateSymbol(To);
+
+ getStreamer().emitCGProfileEntry(
+ MCSymbolRefExpr::create(FromSym, MCSymbolRefExpr::VK_None, getContext(),
+ FromLoc),
+ MCSymbolRefExpr::create(ToSym, MCSymbolRefExpr::VK_None, getContext(),
+ ToLoc),
+ Count);
+ return false;
+}
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/MCTargetAsmParser.cpp b/contrib/libs/llvm12/lib/MC/MCParser/MCTargetAsmParser.cpp
index c10418e48b..940f26d475 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/MCTargetAsmParser.cpp
+++ b/contrib/libs/llvm12/lib/MC/MCParser/MCTargetAsmParser.cpp
@@ -1,29 +1,29 @@
-//===-- MCTargetAsmParser.cpp - Target Assembly Parser --------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCParser/MCTargetAsmParser.h"
-#include "llvm/MC/MCContext.h"
-
-using namespace llvm;
-
-MCTargetAsmParser::MCTargetAsmParser(MCTargetOptions const &MCOptions,
- const MCSubtargetInfo &STI,
- const MCInstrInfo &MII)
- : MCOptions(MCOptions), STI(&STI), MII(MII) {}
-
-MCTargetAsmParser::~MCTargetAsmParser() = default;
-
-MCSubtargetInfo &MCTargetAsmParser::copySTI() {
- MCSubtargetInfo &STICopy = getContext().getSubtargetCopy(getSTI());
- STI = &STICopy;
- return STICopy;
-}
-
-const MCSubtargetInfo &MCTargetAsmParser::getSTI() const {
- return *STI;
-}
+//===-- MCTargetAsmParser.cpp - Target Assembly Parser --------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCContext.h"
+
+using namespace llvm;
+
+MCTargetAsmParser::MCTargetAsmParser(MCTargetOptions const &MCOptions,
+ const MCSubtargetInfo &STI,
+ const MCInstrInfo &MII)
+ : MCOptions(MCOptions), STI(&STI), MII(MII) {}
+
+MCTargetAsmParser::~MCTargetAsmParser() = default;
+
+MCSubtargetInfo &MCTargetAsmParser::copySTI() {
+ MCSubtargetInfo &STICopy = getContext().getSubtargetCopy(getSTI());
+ STI = &STICopy;
+ return STICopy;
+}
+
+const MCSubtargetInfo &MCTargetAsmParser::getSTI() const {
+ return *STI;
+}
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/MasmParser.cpp b/contrib/libs/llvm12/lib/MC/MCParser/MasmParser.cpp
index 958d4e0489..4957ee7a03 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/MasmParser.cpp
+++ b/contrib/libs/llvm12/lib/MC/MCParser/MasmParser.cpp
@@ -1,616 +1,616 @@
-//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements the parser for assembly files.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/None.h"
+//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements the parser for assembly files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCCodeView.h"
-#include "llvm/MC/MCContext.h"
-#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/MCAsmParserExtension.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/MCSection.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCTargetOptions.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ErrorHandling.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeView.h"
+#include "llvm/MC/MCContext.h"
+#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/MCAsmParserExtension.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/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
-#include "llvm/Support/MD5.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 <climits>
-#include <cstddef>
-#include <cstdint>
-#include <deque>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-using namespace llvm;
-
-extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
-
-namespace {
-
-/// Helper types for tracking macro definitions.
-typedef std::vector<AsmToken> MCAsmMacroArgument;
-typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
-
-/// Helper class for storing information about an active macro instantiation.
-struct MacroInstantiation {
- /// The location of the instantiation.
- SMLoc InstantiationLoc;
-
- /// The buffer where parsing should resume upon instantiation completion.
- unsigned ExitBuffer;
-
- /// The location where parsing should resume upon instantiation completion.
- SMLoc ExitLoc;
-
- /// The depth of TheCondStack at the start of the instantiation.
- size_t CondStackDepth;
-};
-
-struct ParseStatementInfo {
- /// The parsed operands from the last parsed statement.
- SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
-
- /// The opcode from the last parsed instruction.
- unsigned Opcode = ~0U;
-
- /// Was there an error parsing the inline assembly?
- bool ParseError = false;
-
+#include "llvm/Support/MD5.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 <climits>
+#include <cstddef>
+#include <cstdint>
+#include <deque>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
+
+namespace {
+
+/// Helper types for tracking macro definitions.
+typedef std::vector<AsmToken> MCAsmMacroArgument;
+typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
+
+/// Helper class for storing information about an active macro instantiation.
+struct MacroInstantiation {
+ /// The location of the instantiation.
+ SMLoc InstantiationLoc;
+
+ /// The buffer where parsing should resume upon instantiation completion.
+ unsigned ExitBuffer;
+
+ /// The location where parsing should resume upon instantiation completion.
+ SMLoc ExitLoc;
+
+ /// The depth of TheCondStack at the start of the instantiation.
+ size_t CondStackDepth;
+};
+
+struct ParseStatementInfo {
+ /// The parsed operands from the last parsed statement.
+ SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
+
+ /// The opcode from the last parsed instruction.
+ unsigned Opcode = ~0U;
+
+ /// Was there an error parsing the inline assembly?
+ bool ParseError = false;
+
/// The value associated with a macro exit.
Optional<std::string> ExitValue;
- SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
-
- ParseStatementInfo() = delete;
- ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
- : AsmRewrites(rewrites) {}
-};
-
-enum FieldType {
- FT_INTEGRAL, // Initializer: integer expression, stored as an MCExpr.
- FT_REAL, // Initializer: real number, stored as an APInt.
- FT_STRUCT // Initializer: struct initializer, stored recursively.
-};
-
-struct FieldInfo;
-struct StructInfo {
- StringRef Name;
- bool IsUnion = false;
+ SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
+
+ ParseStatementInfo() = delete;
+ ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
+ : AsmRewrites(rewrites) {}
+};
+
+enum FieldType {
+ FT_INTEGRAL, // Initializer: integer expression, stored as an MCExpr.
+ FT_REAL, // Initializer: real number, stored as an APInt.
+ FT_STRUCT // Initializer: struct initializer, stored recursively.
+};
+
+struct FieldInfo;
+struct StructInfo {
+ StringRef Name;
+ bool IsUnion = false;
unsigned Alignment = 0;
unsigned Size = 0;
unsigned AlignmentSize = 0;
- std::vector<FieldInfo> Fields;
- StringMap<size_t> FieldsByName;
-
+ std::vector<FieldInfo> Fields;
+ StringMap<size_t> FieldsByName;
+
FieldInfo &addField(StringRef FieldName, FieldType FT,
unsigned FieldAlignmentSize);
-
- StructInfo() = default;
-
- StructInfo(StringRef StructName, bool Union, unsigned AlignmentValue)
- : Name(StructName), IsUnion(Union), Alignment(AlignmentValue) {}
-};
-
-// FIXME: This should probably use a class hierarchy, raw pointers between the
-// objects, and dynamic type resolution instead of a union. On the other hand,
-// ownership then becomes much more complicated; the obvious thing would be to
-// use BumpPtrAllocator, but the lack of a destructor makes that messy.
-
-struct StructInitializer;
-struct IntFieldInfo {
- SmallVector<const MCExpr *, 1> Values;
-
- IntFieldInfo() = default;
- IntFieldInfo(const SmallVector<const MCExpr *, 1> &V) { Values = V; }
- IntFieldInfo(SmallVector<const MCExpr *, 1> &&V) { Values = V; }
-};
-struct RealFieldInfo {
- SmallVector<APInt, 1> AsIntValues;
-
- RealFieldInfo() = default;
- RealFieldInfo(const SmallVector<APInt, 1> &V) { AsIntValues = V; }
- RealFieldInfo(SmallVector<APInt, 1> &&V) { AsIntValues = V; }
-};
-struct StructFieldInfo {
- std::vector<StructInitializer> Initializers;
- StructInfo Structure;
-
- StructFieldInfo() = default;
- StructFieldInfo(const std::vector<StructInitializer> &V, StructInfo S) {
- Initializers = V;
- Structure = S;
- }
- StructFieldInfo(std::vector<StructInitializer> &&V, StructInfo S) {
- Initializers = V;
- Structure = S;
- }
-};
-
-class FieldInitializer {
-public:
- FieldType FT;
- union {
- IntFieldInfo IntInfo;
- RealFieldInfo RealInfo;
- StructFieldInfo StructInfo;
- };
-
- ~FieldInitializer() {
- switch (FT) {
- case FT_INTEGRAL:
- IntInfo.~IntFieldInfo();
- break;
- case FT_REAL:
- RealInfo.~RealFieldInfo();
- break;
- case FT_STRUCT:
- StructInfo.~StructFieldInfo();
- break;
- }
- }
-
- FieldInitializer(FieldType FT) : FT(FT) {
- switch (FT) {
- case FT_INTEGRAL:
- new (&IntInfo) IntFieldInfo();
- break;
- case FT_REAL:
- new (&RealInfo) RealFieldInfo();
- break;
- case FT_STRUCT:
- new (&StructInfo) StructFieldInfo();
- break;
- }
- }
-
- FieldInitializer(SmallVector<const MCExpr *, 1> &&Values) : FT(FT_INTEGRAL) {
- new (&IntInfo) IntFieldInfo(Values);
- }
-
- FieldInitializer(SmallVector<APInt, 1> &&AsIntValues) : FT(FT_REAL) {
- new (&RealInfo) RealFieldInfo(AsIntValues);
- }
-
- FieldInitializer(std::vector<StructInitializer> &&Initializers,
- struct StructInfo Structure)
- : FT(FT_STRUCT) {
- new (&StructInfo) StructFieldInfo(Initializers, Structure);
- }
-
- FieldInitializer(const FieldInitializer &Initializer) : FT(Initializer.FT) {
- switch (FT) {
- case FT_INTEGRAL:
- new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
- break;
- case FT_REAL:
- new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
- break;
- case FT_STRUCT:
- new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
- break;
- }
- }
-
- FieldInitializer(FieldInitializer &&Initializer) : FT(Initializer.FT) {
- switch (FT) {
- case FT_INTEGRAL:
- new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
- break;
- case FT_REAL:
- new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
- break;
- case FT_STRUCT:
- new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
- break;
- }
- }
-
- FieldInitializer &operator=(const FieldInitializer &Initializer) {
- if (FT != Initializer.FT) {
- switch (FT) {
- case FT_INTEGRAL:
- IntInfo.~IntFieldInfo();
- break;
- case FT_REAL:
- RealInfo.~RealFieldInfo();
- break;
- case FT_STRUCT:
- StructInfo.~StructFieldInfo();
- break;
- }
- }
- FT = Initializer.FT;
- switch (FT) {
- case FT_INTEGRAL:
- IntInfo = Initializer.IntInfo;
- break;
- case FT_REAL:
- RealInfo = Initializer.RealInfo;
- break;
- case FT_STRUCT:
- StructInfo = Initializer.StructInfo;
- break;
- }
- return *this;
- }
-
- FieldInitializer &operator=(FieldInitializer &&Initializer) {
- if (FT != Initializer.FT) {
- switch (FT) {
- case FT_INTEGRAL:
- IntInfo.~IntFieldInfo();
- break;
- case FT_REAL:
- RealInfo.~RealFieldInfo();
- break;
- case FT_STRUCT:
- StructInfo.~StructFieldInfo();
- break;
- }
- }
- FT = Initializer.FT;
- switch (FT) {
- case FT_INTEGRAL:
- IntInfo = Initializer.IntInfo;
- break;
- case FT_REAL:
- RealInfo = Initializer.RealInfo;
- break;
- case FT_STRUCT:
- StructInfo = Initializer.StructInfo;
- break;
- }
- return *this;
- }
-};
-
-struct StructInitializer {
- std::vector<FieldInitializer> FieldInitializers;
-};
-
-struct FieldInfo {
- // Offset of the field within the containing STRUCT.
- size_t Offset = 0;
-
- // Total size of the field (= LengthOf * Type).
+
+ StructInfo() = default;
+
+ StructInfo(StringRef StructName, bool Union, unsigned AlignmentValue)
+ : Name(StructName), IsUnion(Union), Alignment(AlignmentValue) {}
+};
+
+// FIXME: This should probably use a class hierarchy, raw pointers between the
+// objects, and dynamic type resolution instead of a union. On the other hand,
+// ownership then becomes much more complicated; the obvious thing would be to
+// use BumpPtrAllocator, but the lack of a destructor makes that messy.
+
+struct StructInitializer;
+struct IntFieldInfo {
+ SmallVector<const MCExpr *, 1> Values;
+
+ IntFieldInfo() = default;
+ IntFieldInfo(const SmallVector<const MCExpr *, 1> &V) { Values = V; }
+ IntFieldInfo(SmallVector<const MCExpr *, 1> &&V) { Values = V; }
+};
+struct RealFieldInfo {
+ SmallVector<APInt, 1> AsIntValues;
+
+ RealFieldInfo() = default;
+ RealFieldInfo(const SmallVector<APInt, 1> &V) { AsIntValues = V; }
+ RealFieldInfo(SmallVector<APInt, 1> &&V) { AsIntValues = V; }
+};
+struct StructFieldInfo {
+ std::vector<StructInitializer> Initializers;
+ StructInfo Structure;
+
+ StructFieldInfo() = default;
+ StructFieldInfo(const std::vector<StructInitializer> &V, StructInfo S) {
+ Initializers = V;
+ Structure = S;
+ }
+ StructFieldInfo(std::vector<StructInitializer> &&V, StructInfo S) {
+ Initializers = V;
+ Structure = S;
+ }
+};
+
+class FieldInitializer {
+public:
+ FieldType FT;
+ union {
+ IntFieldInfo IntInfo;
+ RealFieldInfo RealInfo;
+ StructFieldInfo StructInfo;
+ };
+
+ ~FieldInitializer() {
+ switch (FT) {
+ case FT_INTEGRAL:
+ IntInfo.~IntFieldInfo();
+ break;
+ case FT_REAL:
+ RealInfo.~RealFieldInfo();
+ break;
+ case FT_STRUCT:
+ StructInfo.~StructFieldInfo();
+ break;
+ }
+ }
+
+ FieldInitializer(FieldType FT) : FT(FT) {
+ switch (FT) {
+ case FT_INTEGRAL:
+ new (&IntInfo) IntFieldInfo();
+ break;
+ case FT_REAL:
+ new (&RealInfo) RealFieldInfo();
+ break;
+ case FT_STRUCT:
+ new (&StructInfo) StructFieldInfo();
+ break;
+ }
+ }
+
+ FieldInitializer(SmallVector<const MCExpr *, 1> &&Values) : FT(FT_INTEGRAL) {
+ new (&IntInfo) IntFieldInfo(Values);
+ }
+
+ FieldInitializer(SmallVector<APInt, 1> &&AsIntValues) : FT(FT_REAL) {
+ new (&RealInfo) RealFieldInfo(AsIntValues);
+ }
+
+ FieldInitializer(std::vector<StructInitializer> &&Initializers,
+ struct StructInfo Structure)
+ : FT(FT_STRUCT) {
+ new (&StructInfo) StructFieldInfo(Initializers, Structure);
+ }
+
+ FieldInitializer(const FieldInitializer &Initializer) : FT(Initializer.FT) {
+ switch (FT) {
+ case FT_INTEGRAL:
+ new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
+ break;
+ case FT_REAL:
+ new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
+ break;
+ case FT_STRUCT:
+ new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
+ break;
+ }
+ }
+
+ FieldInitializer(FieldInitializer &&Initializer) : FT(Initializer.FT) {
+ switch (FT) {
+ case FT_INTEGRAL:
+ new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
+ break;
+ case FT_REAL:
+ new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
+ break;
+ case FT_STRUCT:
+ new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
+ break;
+ }
+ }
+
+ FieldInitializer &operator=(const FieldInitializer &Initializer) {
+ if (FT != Initializer.FT) {
+ switch (FT) {
+ case FT_INTEGRAL:
+ IntInfo.~IntFieldInfo();
+ break;
+ case FT_REAL:
+ RealInfo.~RealFieldInfo();
+ break;
+ case FT_STRUCT:
+ StructInfo.~StructFieldInfo();
+ break;
+ }
+ }
+ FT = Initializer.FT;
+ switch (FT) {
+ case FT_INTEGRAL:
+ IntInfo = Initializer.IntInfo;
+ break;
+ case FT_REAL:
+ RealInfo = Initializer.RealInfo;
+ break;
+ case FT_STRUCT:
+ StructInfo = Initializer.StructInfo;
+ break;
+ }
+ return *this;
+ }
+
+ FieldInitializer &operator=(FieldInitializer &&Initializer) {
+ if (FT != Initializer.FT) {
+ switch (FT) {
+ case FT_INTEGRAL:
+ IntInfo.~IntFieldInfo();
+ break;
+ case FT_REAL:
+ RealInfo.~RealFieldInfo();
+ break;
+ case FT_STRUCT:
+ StructInfo.~StructFieldInfo();
+ break;
+ }
+ }
+ FT = Initializer.FT;
+ switch (FT) {
+ case FT_INTEGRAL:
+ IntInfo = Initializer.IntInfo;
+ break;
+ case FT_REAL:
+ RealInfo = Initializer.RealInfo;
+ break;
+ case FT_STRUCT:
+ StructInfo = Initializer.StructInfo;
+ break;
+ }
+ return *this;
+ }
+};
+
+struct StructInitializer {
+ std::vector<FieldInitializer> FieldInitializers;
+};
+
+struct FieldInfo {
+ // Offset of the field within the containing STRUCT.
+ size_t Offset = 0;
+
+ // Total size of the field (= LengthOf * Type).
unsigned SizeOf = 0;
-
- // Number of elements in the field (1 if scalar, >1 if an array).
+
+ // Number of elements in the field (1 if scalar, >1 if an array).
unsigned LengthOf = 0;
-
- // Size of a single entry in this field, in bytes ("type" in MASM standards).
+
+ // Size of a single entry in this field, in bytes ("type" in MASM standards).
unsigned Type = 0;
-
- FieldInitializer Contents;
-
- FieldInfo(FieldType FT) : Contents(FT) {}
-};
-
+
+ FieldInitializer Contents;
+
+ FieldInfo(FieldType FT) : Contents(FT) {}
+};
+
FieldInfo &StructInfo::addField(StringRef FieldName, FieldType FT,
unsigned FieldAlignmentSize) {
- if (!FieldName.empty())
+ if (!FieldName.empty())
FieldsByName[FieldName.lower()] = Fields.size();
- Fields.emplace_back(FT);
- FieldInfo &Field = Fields.back();
- if (IsUnion) {
- Field.Offset = 0;
- } else {
+ Fields.emplace_back(FT);
+ FieldInfo &Field = Fields.back();
+ if (IsUnion) {
+ Field.Offset = 0;
+ } else {
Size = llvm::alignTo(Size, std::min(Alignment, FieldAlignmentSize));
- Field.Offset = Size;
- }
+ Field.Offset = Size;
+ }
AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize);
- return Field;
-}
-
-/// The concrete assembly parser instance.
-// Note that this is a full MCAsmParser, not an MCAsmParserExtension!
-// It's a peer of AsmParser, not of COFFAsmParser, WasmAsmParser, etc.
-class MasmParser : public MCAsmParser {
-private:
- AsmLexer Lexer;
- MCContext &Ctx;
- MCStreamer &Out;
- const MCAsmInfo &MAI;
- SourceMgr &SrcMgr;
- SourceMgr::DiagHandlerTy SavedDiagHandler;
- void *SavedDiagContext;
- std::unique_ptr<MCAsmParserExtension> PlatformParser;
-
- /// This is the current buffer index we're lexing from as managed by the
- /// SourceMgr object.
- unsigned CurBuffer;
+ return Field;
+}
+
+/// The concrete assembly parser instance.
+// Note that this is a full MCAsmParser, not an MCAsmParserExtension!
+// It's a peer of AsmParser, not of COFFAsmParser, WasmAsmParser, etc.
+class MasmParser : public MCAsmParser {
+private:
+ AsmLexer Lexer;
+ MCContext &Ctx;
+ MCStreamer &Out;
+ const MCAsmInfo &MAI;
+ SourceMgr &SrcMgr;
+ SourceMgr::DiagHandlerTy SavedDiagHandler;
+ void *SavedDiagContext;
+ std::unique_ptr<MCAsmParserExtension> PlatformParser;
+
+ /// This is the current buffer index we're lexing from as managed by the
+ /// SourceMgr object.
+ unsigned CurBuffer;
std::vector<bool> EndStatementAtEOFStack;
-
- AsmCond TheCondState;
- std::vector<AsmCond> TheCondStack;
-
- /// maps directive names to handler methods in parser
- /// extensions. Extensions register themselves in this map by calling
- /// addDirectiveHandler.
- StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
-
- /// maps assembly-time variable names to variables.
- struct Variable {
- StringRef Name;
- bool Redefinable = true;
- bool IsText = false;
- int64_t NumericValue = 0;
- std::string TextValue;
- };
- StringMap<Variable> Variables;
-
- /// Stack of active struct definitions.
- SmallVector<StructInfo, 1> StructInProgress;
-
- /// Maps struct tags to struct definitions.
- StringMap<StructInfo> Structs;
-
+
+ AsmCond TheCondState;
+ std::vector<AsmCond> TheCondStack;
+
+ /// maps directive names to handler methods in parser
+ /// extensions. Extensions register themselves in this map by calling
+ /// addDirectiveHandler.
+ StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
+
+ /// maps assembly-time variable names to variables.
+ struct Variable {
+ StringRef Name;
+ bool Redefinable = true;
+ bool IsText = false;
+ int64_t NumericValue = 0;
+ std::string TextValue;
+ };
+ StringMap<Variable> Variables;
+
+ /// Stack of active struct definitions.
+ SmallVector<StructInfo, 1> StructInProgress;
+
+ /// Maps struct tags to struct definitions.
+ StringMap<StructInfo> Structs;
+
/// Maps data location names to types.
StringMap<AsmTypeInfo> KnownType;
-
- /// Stack of active macro instantiations.
- std::vector<MacroInstantiation*> ActiveMacros;
-
- /// List of bodies of anonymous macros.
- std::deque<MCAsmMacro> MacroLikeBodies;
-
- /// Keeps track of how many .macro's have been instantiated.
- unsigned NumOfMacroInstantiations;
-
- /// The values from the last parsed cpp hash file line comment if any.
- struct CppHashInfoTy {
- StringRef Filename;
- int64_t LineNumber;
- SMLoc Loc;
- unsigned Buf;
- CppHashInfoTy() : Filename(), LineNumber(0), Loc(), Buf(0) {}
- };
- CppHashInfoTy CppHashInfo;
-
- /// The filename from the first cpp hash file line comment, if any.
- StringRef FirstCppHashFilename;
-
- /// List of forward directional labels for diagnosis at the end.
- SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
-
- /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
- /// Defaults to 1U, meaning Intel.
- unsigned AssemblerDialect = 1U;
-
- /// is Darwin compatibility enabled?
- bool IsDarwin = false;
-
- /// Are we parsing ms-style inline assembly?
- bool ParsingMSInlineAsm = false;
-
- /// Did we already inform the user about inconsistent MD5 usage?
- bool ReportedInconsistentMD5 = false;
-
- // Current <...> expression depth.
- unsigned AngleBracketDepth = 0U;
-
+
+ /// Stack of active macro instantiations.
+ std::vector<MacroInstantiation*> ActiveMacros;
+
+ /// List of bodies of anonymous macros.
+ std::deque<MCAsmMacro> MacroLikeBodies;
+
+ /// Keeps track of how many .macro's have been instantiated.
+ unsigned NumOfMacroInstantiations;
+
+ /// The values from the last parsed cpp hash file line comment if any.
+ struct CppHashInfoTy {
+ StringRef Filename;
+ int64_t LineNumber;
+ SMLoc Loc;
+ unsigned Buf;
+ CppHashInfoTy() : Filename(), LineNumber(0), Loc(), Buf(0) {}
+ };
+ CppHashInfoTy CppHashInfo;
+
+ /// The filename from the first cpp hash file line comment, if any.
+ StringRef FirstCppHashFilename;
+
+ /// List of forward directional labels for diagnosis at the end.
+ SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
+
+ /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
+ /// Defaults to 1U, meaning Intel.
+ unsigned AssemblerDialect = 1U;
+
+ /// is Darwin compatibility enabled?
+ bool IsDarwin = false;
+
+ /// Are we parsing ms-style inline assembly?
+ bool ParsingMSInlineAsm = false;
+
+ /// Did we already inform the user about inconsistent MD5 usage?
+ bool ReportedInconsistentMD5 = false;
+
+ // Current <...> expression depth.
+ unsigned AngleBracketDepth = 0U;
+
// Number of locals defined.
uint16_t LocalCounter = 0;
-public:
- MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
- const MCAsmInfo &MAI, unsigned CB);
- MasmParser(const MasmParser &) = delete;
- MasmParser &operator=(const MasmParser &) = delete;
- ~MasmParser() override;
-
- bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
-
- void addDirectiveHandler(StringRef Directive,
- ExtensionDirectiveHandler Handler) override {
- ExtensionDirectiveMap[Directive] = Handler;
- if (DirectiveKindMap.find(Directive) == DirectiveKindMap.end()) {
- DirectiveKindMap[Directive] = DK_HANDLER_DIRECTIVE;
- }
- }
-
- void addAliasForDirective(StringRef Directive, StringRef Alias) override {
- DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
- }
-
- /// @name MCAsmParser Interface
- /// {
-
- SourceMgr &getSourceManager() override { return SrcMgr; }
- 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();
- else
- return AssemblerDialect;
- }
- void setAssemblerDialect(unsigned i) override {
- AssemblerDialect = i;
- }
-
- 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 setParsingMSInlineAsm(bool V) override {
- ParsingMSInlineAsm = V;
- // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
- // hex integer literals.
- Lexer.setLexMasmIntegers(V);
- }
- bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
-
- bool isParsingMasm() const override { return true; }
-
+public:
+ MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
+ const MCAsmInfo &MAI, unsigned CB);
+ MasmParser(const MasmParser &) = delete;
+ MasmParser &operator=(const MasmParser &) = delete;
+ ~MasmParser() override;
+
+ bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
+
+ void addDirectiveHandler(StringRef Directive,
+ ExtensionDirectiveHandler Handler) override {
+ ExtensionDirectiveMap[Directive] = Handler;
+ if (DirectiveKindMap.find(Directive) == DirectiveKindMap.end()) {
+ DirectiveKindMap[Directive] = DK_HANDLER_DIRECTIVE;
+ }
+ }
+
+ void addAliasForDirective(StringRef Directive, StringRef Alias) override {
+ DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
+ }
+
+ /// @name MCAsmParser Interface
+ /// {
+
+ SourceMgr &getSourceManager() override { return SrcMgr; }
+ 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();
+ else
+ return AssemblerDialect;
+ }
+ void setAssemblerDialect(unsigned i) override {
+ AssemblerDialect = i;
+ }
+
+ 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 setParsingMSInlineAsm(bool V) override {
+ ParsingMSInlineAsm = V;
+ // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
+ // hex integer literals.
+ Lexer.setLexMasmIntegers(V);
+ }
+ bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
+
+ bool isParsingMasm() const override { return true; }
+
bool defineMacro(StringRef Name, StringRef Value) override;
-
+
bool lookUpField(StringRef Name, AsmFieldInfo &Info) const override;
bool lookUpField(StringRef Base, StringRef Member,
AsmFieldInfo &Info) const override;
bool lookUpType(StringRef Name, AsmTypeInfo &Info) const override;
- bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
- unsigned &NumOutputs, unsigned &NumInputs,
- SmallVectorImpl<std::pair<void *,bool>> &OpDecls,
- SmallVectorImpl<std::string> &Constraints,
- SmallVectorImpl<std::string> &Clobbers,
- const MCInstrInfo *MII, const MCInstPrinter *IP,
- MCAsmParserSemaCallback &SI) override;
-
- bool parseExpression(const MCExpr *&Res);
- bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
+ bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
+ unsigned &NumOutputs, unsigned &NumInputs,
+ SmallVectorImpl<std::pair<void *,bool>> &OpDecls,
+ SmallVectorImpl<std::string> &Constraints,
+ SmallVectorImpl<std::string> &Clobbers,
+ const MCInstrInfo *MII, const MCInstPrinter *IP,
+ MCAsmParserSemaCallback &SI) override;
+
+ bool parseExpression(const MCExpr *&Res);
+ bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
AsmTypeInfo *TypeInfo) override;
- bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
- bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
- SMLoc &EndLoc) override;
- bool parseAbsoluteExpression(int64_t &Res) override;
-
- /// Parse a floating point expression using the float \p Semantics
- /// and set \p Res to the value.
- bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
-
- /// 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;
-
- bool checkForValidSection() override;
-
- /// }
-
-private:
- bool parseStatement(ParseStatementInfo &Info,
- MCAsmParserSemaCallback *SI);
- bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
- bool parseCppHashLineFilenameComment(SMLoc L);
-
- bool expandMacro(raw_svector_ostream &OS, StringRef Body,
- ArrayRef<MCAsmMacroParameter> Parameters,
+ bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
+ bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
+ SMLoc &EndLoc) override;
+ bool parseAbsoluteExpression(int64_t &Res) override;
+
+ /// Parse a floating point expression using the float \p Semantics
+ /// and set \p Res to the value.
+ bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
+
+ /// 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;
+
+ bool checkForValidSection() override;
+
+ /// }
+
+private:
+ bool parseStatement(ParseStatementInfo &Info,
+ MCAsmParserSemaCallback *SI);
+ bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
+ bool parseCppHashLineFilenameComment(SMLoc L);
+
+ bool expandMacro(raw_svector_ostream &OS, StringRef Body,
+ ArrayRef<MCAsmMacroParameter> Parameters,
ArrayRef<MCAsmMacroArgument> A,
const std::vector<std::string> &Locals, SMLoc L);
-
- /// Are we inside a macro instantiation?
- bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
-
- /// Handle entry to macro instantiation.
- ///
- /// \param M The macro.
- /// \param NameLoc Instantiation location.
+
+ /// Are we inside a macro instantiation?
+ bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
+
+ /// Handle entry to macro instantiation.
+ ///
+ /// \param M The macro.
+ /// \param NameLoc Instantiation location.
bool handleMacroEntry(
const MCAsmMacro *M, SMLoc NameLoc,
AsmToken::TokenKind ArgumentEndTok = AsmToken::EndOfStatement);
-
+
/// Handle invocation of macro function.
///
/// \param M The macro.
/// \param NameLoc Invocation location.
bool handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc);
- /// Handle exit from macro instantiation.
- void handleMacroExit();
-
- /// Extract AsmTokens for a macro argument.
+ /// Handle exit from macro instantiation.
+ void handleMacroExit();
+
+ /// Extract AsmTokens for a macro argument.
bool
parseMacroArgument(const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA,
AsmToken::TokenKind EndTok = AsmToken::EndOfStatement);
-
- /// Parse all macro arguments for a given macro.
+
+ /// Parse all macro arguments for a given macro.
bool
parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A,
AsmToken::TokenKind EndTok = AsmToken::EndOfStatement);
-
- void printMacroInstantiations();
+
+ void printMacroInstantiations();
bool expandStatement(SMLoc Loc);
- void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
- SMRange Range = None) const {
- ArrayRef<SMRange> Ranges(Range);
- SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
- }
- static void DiagHandler(const SMDiagnostic &Diag, void *Context);
-
- bool lookUpField(const StructInfo &Structure, StringRef Member,
+ void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
+ SMRange Range = None) const {
+ ArrayRef<SMRange> Ranges(Range);
+ SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
+ }
+ static void DiagHandler(const SMDiagnostic &Diag, void *Context);
+
+ bool lookUpField(const StructInfo &Structure, StringRef Member,
AsmFieldInfo &Info) const;
-
- /// Should we emit DWARF describing this assembler source? (Returns false if
- /// the source has .file directives, which means we don't want to generate
- /// info describing the assembler source itself.)
- bool enabledGenDwarfForAssembly();
-
- /// Enter the specified file. This returns true on failure.
- bool enterIncludeFile(const std::string &Filename);
-
- /// Reset the current lexer position to that given by \p Loc. The
- /// current token is not set; clients should ensure Lex() is called
- /// subsequently.
- ///
- /// \param InBuffer If not 0, should be the known buffer id that contains the
- /// location.
+
+ /// Should we emit DWARF describing this assembler source? (Returns false if
+ /// the source has .file directives, which means we don't want to generate
+ /// info describing the assembler source itself.)
+ bool enabledGenDwarfForAssembly();
+
+ /// Enter the specified file. This returns true on failure.
+ bool enterIncludeFile(const std::string &Filename);
+
+ /// Reset the current lexer position to that given by \p Loc. The
+ /// current token is not set; clients should ensure Lex() is called
+ /// subsequently.
+ ///
+ /// \param InBuffer If not 0, should be the known buffer id that contains the
+ /// location.
void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0,
bool EndStatementAtEOF = true);
-
+
/// Parse up to a token of kind \p EndTok and return the contents from the
/// current token up to (but not including) this token; the current token on
/// exit will be either this kind or EOF. Reads through instantiated macro
@@ -621,140 +621,140 @@ private:
/// Parse up to the end of statement and return the contents from the current
/// token until the end of the statement; the current token on exit will be
/// either the EndOfStatement or EOF.
- StringRef parseStringToEndOfStatement() override;
-
- bool parseTextItem(std::string &Data);
-
- unsigned getBinOpPrecedence(AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind);
-
- bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
- bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
- bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
-
- 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_HANDLER_DIRECTIVE,
- DK_ASSIGN,
- DK_EQU,
- DK_TEXTEQU,
- DK_ASCII,
- DK_ASCIZ,
- DK_STRING,
- DK_BYTE,
- DK_SBYTE,
- DK_WORD,
- DK_SWORD,
- DK_DWORD,
- DK_SDWORD,
- DK_FWORD,
- DK_QWORD,
- DK_SQWORD,
- DK_DB,
- DK_DD,
+ StringRef parseStringToEndOfStatement() override;
+
+ bool parseTextItem(std::string &Data);
+
+ unsigned getBinOpPrecedence(AsmToken::TokenKind K,
+ MCBinaryExpr::Opcode &Kind);
+
+ bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
+ bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
+ bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
+
+ 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_HANDLER_DIRECTIVE,
+ DK_ASSIGN,
+ DK_EQU,
+ DK_TEXTEQU,
+ DK_ASCII,
+ DK_ASCIZ,
+ DK_STRING,
+ DK_BYTE,
+ DK_SBYTE,
+ DK_WORD,
+ DK_SWORD,
+ DK_DWORD,
+ DK_SDWORD,
+ DK_FWORD,
+ DK_QWORD,
+ DK_SQWORD,
+ DK_DB,
+ DK_DD,
DK_DF,
- DK_DQ,
- DK_DW,
- DK_REAL4,
- DK_REAL8,
+ DK_DQ,
+ DK_DW,
+ DK_REAL4,
+ DK_REAL8,
DK_REAL10,
- DK_ALIGN,
- DK_ORG,
- DK_ENDR,
- DK_EXTERN,
- DK_PUBLIC,
- DK_COMM,
- DK_COMMENT,
- DK_INCLUDE,
+ DK_ALIGN,
+ DK_ORG,
+ DK_ENDR,
+ DK_EXTERN,
+ DK_PUBLIC,
+ DK_COMM,
+ DK_COMMENT,
+ DK_INCLUDE,
DK_REPEAT,
DK_WHILE,
DK_FOR,
DK_FORC,
- DK_IF,
- DK_IFE,
- DK_IFB,
- DK_IFNB,
- DK_IFDEF,
- DK_IFNDEF,
- DK_IFDIF,
- DK_IFDIFI,
- DK_IFIDN,
- DK_IFIDNI,
- DK_ELSEIF,
- DK_ELSEIFE,
- DK_ELSEIFB,
- DK_ELSEIFNB,
- DK_ELSEIFDEF,
- DK_ELSEIFNDEF,
- DK_ELSEIFDIF,
- DK_ELSEIFDIFI,
- DK_ELSEIFIDN,
- DK_ELSEIFIDNI,
- DK_ELSE,
- DK_ENDIF,
- DK_FILE,
- DK_LINE,
- DK_LOC,
- DK_STABS,
- DK_CV_FILE,
- DK_CV_FUNC_ID,
- DK_CV_INLINE_SITE_ID,
- DK_CV_LOC,
- DK_CV_LINETABLE,
- DK_CV_INLINE_LINETABLE,
- DK_CV_DEF_RANGE,
- DK_CV_STRINGTABLE,
- DK_CV_STRING,
- DK_CV_FILECHECKSUMS,
- DK_CV_FILECHECKSUM_OFFSET,
- DK_CV_FPO_DATA,
- DK_CFI_SECTIONS,
- DK_CFI_STARTPROC,
- DK_CFI_ENDPROC,
- DK_CFI_DEF_CFA,
- DK_CFI_DEF_CFA_OFFSET,
- DK_CFI_ADJUST_CFA_OFFSET,
- DK_CFI_DEF_CFA_REGISTER,
- DK_CFI_OFFSET,
- DK_CFI_REL_OFFSET,
- DK_CFI_PERSONALITY,
- DK_CFI_LSDA,
- DK_CFI_REMEMBER_STATE,
- DK_CFI_RESTORE_STATE,
- DK_CFI_SAME_VALUE,
- DK_CFI_RESTORE,
- DK_CFI_ESCAPE,
- DK_CFI_RETURN_COLUMN,
- DK_CFI_SIGNAL_FRAME,
- DK_CFI_UNDEFINED,
- DK_CFI_REGISTER,
- DK_CFI_WINDOW_SAVE,
- DK_CFI_B_KEY_FRAME,
- DK_MACRO,
- DK_EXITM,
- DK_ENDM,
+ DK_IF,
+ DK_IFE,
+ DK_IFB,
+ DK_IFNB,
+ DK_IFDEF,
+ DK_IFNDEF,
+ DK_IFDIF,
+ DK_IFDIFI,
+ DK_IFIDN,
+ DK_IFIDNI,
+ DK_ELSEIF,
+ DK_ELSEIFE,
+ DK_ELSEIFB,
+ DK_ELSEIFNB,
+ DK_ELSEIFDEF,
+ DK_ELSEIFNDEF,
+ DK_ELSEIFDIF,
+ DK_ELSEIFDIFI,
+ DK_ELSEIFIDN,
+ DK_ELSEIFIDNI,
+ DK_ELSE,
+ DK_ENDIF,
+ DK_FILE,
+ DK_LINE,
+ DK_LOC,
+ DK_STABS,
+ DK_CV_FILE,
+ DK_CV_FUNC_ID,
+ DK_CV_INLINE_SITE_ID,
+ DK_CV_LOC,
+ DK_CV_LINETABLE,
+ DK_CV_INLINE_LINETABLE,
+ DK_CV_DEF_RANGE,
+ DK_CV_STRINGTABLE,
+ DK_CV_STRING,
+ DK_CV_FILECHECKSUMS,
+ DK_CV_FILECHECKSUM_OFFSET,
+ DK_CV_FPO_DATA,
+ DK_CFI_SECTIONS,
+ DK_CFI_STARTPROC,
+ DK_CFI_ENDPROC,
+ DK_CFI_DEF_CFA,
+ DK_CFI_DEF_CFA_OFFSET,
+ DK_CFI_ADJUST_CFA_OFFSET,
+ DK_CFI_DEF_CFA_REGISTER,
+ DK_CFI_OFFSET,
+ DK_CFI_REL_OFFSET,
+ DK_CFI_PERSONALITY,
+ DK_CFI_LSDA,
+ DK_CFI_REMEMBER_STATE,
+ DK_CFI_RESTORE_STATE,
+ DK_CFI_SAME_VALUE,
+ DK_CFI_RESTORE,
+ DK_CFI_ESCAPE,
+ DK_CFI_RETURN_COLUMN,
+ DK_CFI_SIGNAL_FRAME,
+ DK_CFI_UNDEFINED,
+ DK_CFI_REGISTER,
+ DK_CFI_WINDOW_SAVE,
+ DK_CFI_B_KEY_FRAME,
+ DK_MACRO,
+ DK_EXITM,
+ DK_ENDM,
DK_PURGE,
- DK_ERR,
- DK_ERRB,
- DK_ERRNB,
- DK_ERRDEF,
- DK_ERRNDEF,
- DK_ERRDIF,
- DK_ERRDIFI,
- DK_ERRIDN,
- DK_ERRIDNI,
- DK_ERRE,
- DK_ERRNZ,
- DK_ECHO,
- DK_STRUCT,
- DK_UNION,
- DK_ENDS,
+ DK_ERR,
+ DK_ERRB,
+ DK_ERRNB,
+ DK_ERRDEF,
+ DK_ERRNDEF,
+ DK_ERRDIF,
+ DK_ERRDIFI,
+ DK_ERRIDN,
+ DK_ERRIDNI,
+ DK_ERRE,
+ DK_ERRNZ,
+ DK_ECHO,
+ DK_STRUCT,
+ DK_UNION,
+ DK_ENDS,
DK_END,
DK_PUSHFRAME,
DK_PUSHREG,
@@ -762,382 +762,382 @@ private:
DK_SAVEXMM128,
DK_SETFRAME,
DK_RADIX,
- };
-
- /// Maps directive name --> DirectiveKind enum, for directives parsed by this
- /// class.
- StringMap<DirectiveKind> DirectiveKindMap;
-
+ };
+
+ /// Maps directive name --> DirectiveKind enum, for directives parsed by this
+ /// class.
+ StringMap<DirectiveKind> DirectiveKindMap;
+
bool isMacroLikeDirective();
- // Codeview def_range type parsing.
- enum CVDefRangeType {
- CVDR_DEFRANGE = 0, // Placeholder
- CVDR_DEFRANGE_REGISTER,
- CVDR_DEFRANGE_FRAMEPOINTER_REL,
- CVDR_DEFRANGE_SUBFIELD_REGISTER,
- CVDR_DEFRANGE_REGISTER_REL
- };
-
- /// Maps Codeview def_range types --> CVDefRangeType enum, for Codeview
- /// def_range types parsed by this class.
- StringMap<CVDefRangeType> CVDefRangeTypeMap;
-
- // ".ascii", ".asciz", ".string"
- bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
-
- // "byte", "word", ...
- bool emitIntValue(const MCExpr *Value, unsigned Size);
- bool parseScalarInitializer(unsigned Size,
- SmallVectorImpl<const MCExpr *> &Values,
- unsigned StringPadLength = 0);
- bool parseScalarInstList(
- unsigned Size, SmallVectorImpl<const MCExpr *> &Values,
- const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
+ // Codeview def_range type parsing.
+ enum CVDefRangeType {
+ CVDR_DEFRANGE = 0, // Placeholder
+ CVDR_DEFRANGE_REGISTER,
+ CVDR_DEFRANGE_FRAMEPOINTER_REL,
+ CVDR_DEFRANGE_SUBFIELD_REGISTER,
+ CVDR_DEFRANGE_REGISTER_REL
+ };
+
+ /// Maps Codeview def_range types --> CVDefRangeType enum, for Codeview
+ /// def_range types parsed by this class.
+ StringMap<CVDefRangeType> CVDefRangeTypeMap;
+
+ // ".ascii", ".asciz", ".string"
+ bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
+
+ // "byte", "word", ...
+ bool emitIntValue(const MCExpr *Value, unsigned Size);
+ bool parseScalarInitializer(unsigned Size,
+ SmallVectorImpl<const MCExpr *> &Values,
+ unsigned StringPadLength = 0);
+ bool parseScalarInstList(
+ unsigned Size, SmallVectorImpl<const MCExpr *> &Values,
+ const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
bool emitIntegralValues(unsigned Size, unsigned *Count = nullptr);
- bool addIntegralField(StringRef Name, unsigned Size);
- bool parseDirectiveValue(StringRef IDVal, unsigned Size);
+ bool addIntegralField(StringRef Name, unsigned Size);
+ bool parseDirectiveValue(StringRef IDVal, unsigned Size);
bool parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
StringRef Name, SMLoc NameLoc);
-
+
// "real4", "real8", "real10"
bool emitRealValues(const fltSemantics &Semantics, unsigned *Count = nullptr);
bool addRealField(StringRef Name, const fltSemantics &Semantics, size_t Size);
bool parseDirectiveRealValue(StringRef IDVal, const fltSemantics &Semantics,
size_t Size);
- bool parseRealInstList(
- const fltSemantics &Semantics, SmallVectorImpl<APInt> &Values,
- const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
+ bool parseRealInstList(
+ const fltSemantics &Semantics, SmallVectorImpl<APInt> &Values,
+ const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
bool parseDirectiveNamedRealValue(StringRef TypeName,
- const fltSemantics &Semantics,
+ const fltSemantics &Semantics,
unsigned Size, StringRef Name,
SMLoc NameLoc);
-
- bool parseOptionalAngleBracketOpen();
- bool parseAngleBracketClose(const Twine &Msg = "expected '>'");
-
- bool parseFieldInitializer(const FieldInfo &Field,
- FieldInitializer &Initializer);
- bool parseFieldInitializer(const FieldInfo &Field,
- const IntFieldInfo &Contents,
- FieldInitializer &Initializer);
- bool parseFieldInitializer(const FieldInfo &Field,
- const RealFieldInfo &Contents,
- FieldInitializer &Initializer);
- bool parseFieldInitializer(const FieldInfo &Field,
- const StructFieldInfo &Contents,
- FieldInitializer &Initializer);
-
- bool parseStructInitializer(const StructInfo &Structure,
- StructInitializer &Initializer);
- bool parseStructInstList(
- const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
- const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
-
- bool emitFieldValue(const FieldInfo &Field);
- bool emitFieldValue(const FieldInfo &Field, const IntFieldInfo &Contents);
- bool emitFieldValue(const FieldInfo &Field, const RealFieldInfo &Contents);
- bool emitFieldValue(const FieldInfo &Field, const StructFieldInfo &Contents);
-
- bool emitFieldInitializer(const FieldInfo &Field,
- const FieldInitializer &Initializer);
- bool emitFieldInitializer(const FieldInfo &Field,
- const IntFieldInfo &Contents,
- const IntFieldInfo &Initializer);
- bool emitFieldInitializer(const FieldInfo &Field,
- const RealFieldInfo &Contents,
- const RealFieldInfo &Initializer);
- bool emitFieldInitializer(const FieldInfo &Field,
- const StructFieldInfo &Contents,
- const StructFieldInfo &Initializer);
-
- bool emitStructInitializer(const StructInfo &Structure,
- const StructInitializer &Initializer);
-
- // User-defined types (structs, unions):
+
+ bool parseOptionalAngleBracketOpen();
+ bool parseAngleBracketClose(const Twine &Msg = "expected '>'");
+
+ bool parseFieldInitializer(const FieldInfo &Field,
+ FieldInitializer &Initializer);
+ bool parseFieldInitializer(const FieldInfo &Field,
+ const IntFieldInfo &Contents,
+ FieldInitializer &Initializer);
+ bool parseFieldInitializer(const FieldInfo &Field,
+ const RealFieldInfo &Contents,
+ FieldInitializer &Initializer);
+ bool parseFieldInitializer(const FieldInfo &Field,
+ const StructFieldInfo &Contents,
+ FieldInitializer &Initializer);
+
+ bool parseStructInitializer(const StructInfo &Structure,
+ StructInitializer &Initializer);
+ bool parseStructInstList(
+ const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
+ const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
+
+ bool emitFieldValue(const FieldInfo &Field);
+ bool emitFieldValue(const FieldInfo &Field, const IntFieldInfo &Contents);
+ bool emitFieldValue(const FieldInfo &Field, const RealFieldInfo &Contents);
+ bool emitFieldValue(const FieldInfo &Field, const StructFieldInfo &Contents);
+
+ bool emitFieldInitializer(const FieldInfo &Field,
+ const FieldInitializer &Initializer);
+ bool emitFieldInitializer(const FieldInfo &Field,
+ const IntFieldInfo &Contents,
+ const IntFieldInfo &Initializer);
+ bool emitFieldInitializer(const FieldInfo &Field,
+ const RealFieldInfo &Contents,
+ const RealFieldInfo &Initializer);
+ bool emitFieldInitializer(const FieldInfo &Field,
+ const StructFieldInfo &Contents,
+ const StructFieldInfo &Initializer);
+
+ bool emitStructInitializer(const StructInfo &Structure,
+ const StructInitializer &Initializer);
+
+ // User-defined types (structs, unions):
bool emitStructValues(const StructInfo &Structure, unsigned *Count = nullptr);
- bool addStructField(StringRef Name, const StructInfo &Structure);
- bool parseDirectiveStructValue(const StructInfo &Structure,
- StringRef Directive, SMLoc DirLoc);
- bool parseDirectiveNamedStructValue(const StructInfo &Structure,
- StringRef Directive, SMLoc DirLoc,
- StringRef Name);
-
- // "=", "equ", "textequ"
- bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
- DirectiveKind DirKind);
-
- bool parseDirectiveOrg(); // ".org"
- bool parseDirectiveAlign(); // "align"
-
- // ".file", ".line", ".loc", ".stabs"
- bool parseDirectiveFile(SMLoc DirectiveLoc);
- bool parseDirectiveLine();
- bool parseDirectiveLoc();
- bool parseDirectiveStabs();
-
- // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
- // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
- bool parseDirectiveCVFile();
- bool parseDirectiveCVFuncId();
- bool parseDirectiveCVInlineSiteId();
- bool parseDirectiveCVLoc();
- bool parseDirectiveCVLinetable();
- bool parseDirectiveCVInlineLinetable();
- bool parseDirectiveCVDefRange();
- bool parseDirectiveCVString();
- bool parseDirectiveCVStringTable();
- bool parseDirectiveCVFileChecksums();
- bool parseDirectiveCVFileChecksumOffset();
- bool parseDirectiveCVFPOData();
-
- // .cfi directives
- bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
- bool parseDirectiveCFIWindowSave();
- bool parseDirectiveCFISections();
- bool parseDirectiveCFIStartProc();
- bool parseDirectiveCFIEndProc();
- bool parseDirectiveCFIDefCfaOffset();
- bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
- bool parseDirectiveCFIAdjustCfaOffset();
- bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
- bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
- bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
- bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
- bool parseDirectiveCFIRememberState();
- bool parseDirectiveCFIRestoreState();
- bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
- bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
- bool parseDirectiveCFIEscape();
- bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
- bool parseDirectiveCFISignalFrame();
- bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
-
- // macro directives
- bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
+ bool addStructField(StringRef Name, const StructInfo &Structure);
+ bool parseDirectiveStructValue(const StructInfo &Structure,
+ StringRef Directive, SMLoc DirLoc);
+ bool parseDirectiveNamedStructValue(const StructInfo &Structure,
+ StringRef Directive, SMLoc DirLoc,
+ StringRef Name);
+
+ // "=", "equ", "textequ"
+ bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
+ DirectiveKind DirKind);
+
+ bool parseDirectiveOrg(); // ".org"
+ bool parseDirectiveAlign(); // "align"
+
+ // ".file", ".line", ".loc", ".stabs"
+ bool parseDirectiveFile(SMLoc DirectiveLoc);
+ bool parseDirectiveLine();
+ bool parseDirectiveLoc();
+ bool parseDirectiveStabs();
+
+ // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
+ // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
+ bool parseDirectiveCVFile();
+ bool parseDirectiveCVFuncId();
+ bool parseDirectiveCVInlineSiteId();
+ bool parseDirectiveCVLoc();
+ bool parseDirectiveCVLinetable();
+ bool parseDirectiveCVInlineLinetable();
+ bool parseDirectiveCVDefRange();
+ bool parseDirectiveCVString();
+ bool parseDirectiveCVStringTable();
+ bool parseDirectiveCVFileChecksums();
+ bool parseDirectiveCVFileChecksumOffset();
+ bool parseDirectiveCVFPOData();
+
+ // .cfi directives
+ bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIWindowSave();
+ bool parseDirectiveCFISections();
+ bool parseDirectiveCFIStartProc();
+ bool parseDirectiveCFIEndProc();
+ bool parseDirectiveCFIDefCfaOffset();
+ bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIAdjustCfaOffset();
+ bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
+ bool parseDirectiveCFIRememberState();
+ bool parseDirectiveCFIRestoreState();
+ bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIEscape();
+ bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
+ bool parseDirectiveCFISignalFrame();
+ bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
+
+ // macro directives
+ bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
std::string &Value);
- bool parseDirectiveEndMacro(StringRef Directive);
+ bool parseDirectiveEndMacro(StringRef Directive);
bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
-
- bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
- StringRef Name, SMLoc NameLoc);
- bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
- bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
- bool parseDirectiveNestedEnds();
-
- /// Parse a directive like ".globl" which accepts a single symbol (which
- /// should be a label or an external).
- bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
-
- bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
-
- bool parseDirectiveComment(SMLoc DirectiveLoc); // "comment"
-
- bool parseDirectiveInclude(); // "include"
-
- // "if" or "ife"
- bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
- // "ifb" or "ifnb", depending on ExpectBlank.
- bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
- // "ifidn", "ifdif", "ifidni", or "ifdifi", depending on ExpectEqual and
- // CaseInsensitive.
- bool parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
- bool CaseInsensitive);
- // "ifdef" or "ifndef", depending on expect_defined
- bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
- // "elseif" or "elseife"
- bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
- // "elseifb" or "elseifnb", depending on ExpectBlank.
- bool parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank);
- // ".elseifdef" or ".elseifndef", depending on expect_defined
- bool parseDirectiveElseIfdef(SMLoc DirectiveLoc, bool expect_defined);
- // "elseifidn", "elseifdif", "elseifidni", or "elseifdifi", depending on
- // ExpectEqual and CaseInsensitive.
- bool parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
- bool CaseInsensitive);
- bool parseDirectiveElse(SMLoc DirectiveLoc); // "else"
- bool parseDirectiveEndIf(SMLoc DirectiveLoc); // "endif"
- bool parseEscapedString(std::string &Data) override;
- bool parseAngleBracketString(std::string &Data) override;
-
- // Macro-like directives
- MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
- void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
- raw_svector_ostream &OS);
+
+ bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
+ StringRef Name, SMLoc NameLoc);
+ bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
+ bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
+ bool parseDirectiveNestedEnds();
+
+ /// Parse a directive like ".globl" which accepts a single symbol (which
+ /// should be a label or an external).
+ bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
+
+ bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
+
+ bool parseDirectiveComment(SMLoc DirectiveLoc); // "comment"
+
+ bool parseDirectiveInclude(); // "include"
+
+ // "if" or "ife"
+ bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
+ // "ifb" or "ifnb", depending on ExpectBlank.
+ bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
+ // "ifidn", "ifdif", "ifidni", or "ifdifi", depending on ExpectEqual and
+ // CaseInsensitive.
+ bool parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+ bool CaseInsensitive);
+ // "ifdef" or "ifndef", depending on expect_defined
+ bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
+ // "elseif" or "elseife"
+ bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
+ // "elseifb" or "elseifnb", depending on ExpectBlank.
+ bool parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank);
+ // ".elseifdef" or ".elseifndef", depending on expect_defined
+ bool parseDirectiveElseIfdef(SMLoc DirectiveLoc, bool expect_defined);
+ // "elseifidn", "elseifdif", "elseifidni", or "elseifdifi", depending on
+ // ExpectEqual and CaseInsensitive.
+ bool parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+ bool CaseInsensitive);
+ bool parseDirectiveElse(SMLoc DirectiveLoc); // "else"
+ bool parseDirectiveEndIf(SMLoc DirectiveLoc); // "endif"
+ bool parseEscapedString(std::string &Data) override;
+ bool parseAngleBracketString(std::string &Data) override;
+
+ // Macro-like directives
+ MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
+ void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
+ raw_svector_ostream &OS);
void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
SMLoc ExitLoc, raw_svector_ostream &OS);
bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
bool parseDirectiveWhile(SMLoc DirectiveLoc);
-
- // "_emit" or "__emit"
- bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
- size_t Len);
-
- // "align"
- bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
-
- // "end"
- bool parseDirectiveEnd(SMLoc DirectiveLoc);
-
- // ".err"
- bool parseDirectiveError(SMLoc DirectiveLoc);
- // ".errb" or ".errnb", depending on ExpectBlank.
- bool parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank);
- // ".errdef" or ".errndef", depending on ExpectBlank.
- bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc, bool ExpectDefined);
- // ".erridn", ".errdif", ".erridni", or ".errdifi", depending on ExpectEqual
- // and CaseInsensitive.
- bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
- bool CaseInsensitive);
- // ".erre" or ".errnz", depending on ExpectZero.
- bool parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero);
-
+
+ // "_emit" or "__emit"
+ bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
+ size_t Len);
+
+ // "align"
+ bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
+
+ // "end"
+ bool parseDirectiveEnd(SMLoc DirectiveLoc);
+
+ // ".err"
+ bool parseDirectiveError(SMLoc DirectiveLoc);
+ // ".errb" or ".errnb", depending on ExpectBlank.
+ bool parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank);
+ // ".errdef" or ".errndef", depending on ExpectBlank.
+ bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc, bool ExpectDefined);
+ // ".erridn", ".errdif", ".erridni", or ".errdifi", depending on ExpectEqual
+ // and CaseInsensitive.
+ bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+ bool CaseInsensitive);
+ // ".erre" or ".errnz", depending on ExpectZero.
+ bool parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero);
+
// ".radix"
bool parseDirectiveRadix(SMLoc DirectiveLoc);
- // "echo"
- bool parseDirectiveEcho();
-
- void initializeDirectiveKindMap();
- void initializeCVDefRangeTypeMap();
-};
-
-} // end anonymous namespace
-
-namespace llvm {
-
-extern MCAsmParserExtension *createCOFFMasmParser();
-
-} // end namespace llvm
-
-enum { DEFAULT_ADDRSPACE = 0 };
-
-MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
- const MCAsmInfo &MAI, unsigned CB = 0)
- : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
- CurBuffer(CB ? CB : SM.getMainFileID()) {
- HadError = false;
- // Save the old handler.
- SavedDiagHandler = SrcMgr.getDiagHandler();
- SavedDiagContext = SrcMgr.getDiagContext();
- // Set our own handler which calls the saved handler.
- SrcMgr.setDiagHandler(DiagHandler, this);
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
+ // "echo"
+ bool parseDirectiveEcho();
+
+ void initializeDirectiveKindMap();
+ void initializeCVDefRangeTypeMap();
+};
+
+} // end anonymous namespace
+
+namespace llvm {
+
+extern MCAsmParserExtension *createCOFFMasmParser();
+
+} // end namespace llvm
+
+enum { DEFAULT_ADDRSPACE = 0 };
+
+MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
+ const MCAsmInfo &MAI, unsigned CB = 0)
+ : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
+ CurBuffer(CB ? CB : SM.getMainFileID()) {
+ HadError = false;
+ // Save the old handler.
+ SavedDiagHandler = SrcMgr.getDiagHandler();
+ SavedDiagContext = SrcMgr.getDiagContext();
+ // Set our own handler which calls the saved handler.
+ SrcMgr.setDiagHandler(DiagHandler, this);
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
EndStatementAtEOFStack.push_back(true);
-
- // Initialize the platform / file format parser.
- switch (Ctx.getObjectFileInfo()->getObjectFileType()) {
- case MCObjectFileInfo::IsCOFF:
- PlatformParser.reset(createCOFFMasmParser());
- break;
- default:
- report_fatal_error("llvm-ml currently supports only COFF output.");
- break;
- }
-
- initializeDirectiveKindMap();
- PlatformParser->Initialize(*this);
- initializeCVDefRangeTypeMap();
-
- NumOfMacroInstantiations = 0;
-}
-
-MasmParser::~MasmParser() {
- assert((HadError || ActiveMacros.empty()) &&
- "Unexpected active macro instantiation!");
-
- // Restore the saved diagnostics handler and context for use during
- // finalization.
- SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
-}
-
-void MasmParser::printMacroInstantiations() {
- // Print the active macro instantiation stack.
- for (std::vector<MacroInstantiation *>::const_reverse_iterator
- it = ActiveMacros.rbegin(),
- ie = ActiveMacros.rend();
- it != ie; ++it)
- printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
- "while in macro instantiation");
-}
-
-void MasmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
- printPendingErrors();
- printMessage(L, SourceMgr::DK_Note, Msg, Range);
- printMacroInstantiations();
-}
-
-bool MasmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
- if (getTargetParser().getTargetOptions().MCNoWarn)
- return false;
- if (getTargetParser().getTargetOptions().MCFatalWarnings)
- return Error(L, Msg, Range);
- printMessage(L, SourceMgr::DK_Warning, Msg, Range);
- printMacroInstantiations();
- return false;
-}
-
-bool MasmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
- HadError = true;
- printMessage(L, SourceMgr::DK_Error, Msg, Range);
- printMacroInstantiations();
- return true;
-}
-
-bool MasmParser::enterIncludeFile(const std::string &Filename) {
- std::string IncludedFile;
- unsigned NewBuf =
- SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
- if (!NewBuf)
- return true;
-
- CurBuffer = NewBuf;
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
+
+ // Initialize the platform / file format parser.
+ switch (Ctx.getObjectFileInfo()->getObjectFileType()) {
+ case MCObjectFileInfo::IsCOFF:
+ PlatformParser.reset(createCOFFMasmParser());
+ break;
+ default:
+ report_fatal_error("llvm-ml currently supports only COFF output.");
+ break;
+ }
+
+ initializeDirectiveKindMap();
+ PlatformParser->Initialize(*this);
+ initializeCVDefRangeTypeMap();
+
+ NumOfMacroInstantiations = 0;
+}
+
+MasmParser::~MasmParser() {
+ assert((HadError || ActiveMacros.empty()) &&
+ "Unexpected active macro instantiation!");
+
+ // Restore the saved diagnostics handler and context for use during
+ // finalization.
+ SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
+}
+
+void MasmParser::printMacroInstantiations() {
+ // Print the active macro instantiation stack.
+ for (std::vector<MacroInstantiation *>::const_reverse_iterator
+ it = ActiveMacros.rbegin(),
+ ie = ActiveMacros.rend();
+ it != ie; ++it)
+ printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
+ "while in macro instantiation");
+}
+
+void MasmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
+ printPendingErrors();
+ printMessage(L, SourceMgr::DK_Note, Msg, Range);
+ printMacroInstantiations();
+}
+
+bool MasmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
+ if (getTargetParser().getTargetOptions().MCNoWarn)
+ return false;
+ if (getTargetParser().getTargetOptions().MCFatalWarnings)
+ return Error(L, Msg, Range);
+ printMessage(L, SourceMgr::DK_Warning, Msg, Range);
+ printMacroInstantiations();
+ return false;
+}
+
+bool MasmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
+ HadError = true;
+ printMessage(L, SourceMgr::DK_Error, Msg, Range);
+ printMacroInstantiations();
+ return true;
+}
+
+bool MasmParser::enterIncludeFile(const std::string &Filename) {
+ std::string IncludedFile;
+ unsigned NewBuf =
+ SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
+ if (!NewBuf)
+ return true;
+
+ CurBuffer = NewBuf;
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
EndStatementAtEOFStack.push_back(true);
- return false;
-}
-
+ return false;
+}
+
void MasmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer,
bool EndStatementAtEOF) {
- CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
+ CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
Loc.getPointer(), EndStatementAtEOF);
-}
-
-const AsmToken &MasmParser::Lex() {
- if (Lexer.getTok().is(AsmToken::Error))
- Error(Lexer.getErrLoc(), Lexer.getErr());
-
- // if it's a end of statement with a comment in it
- if (getTok().is(AsmToken::EndOfStatement)) {
- // if this is a line comment output it.
- if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
- getTok().getString().front() != '\r' && MAI.preserveAsmComments())
- Out.addExplicitComment(Twine(getTok().getString()));
- }
-
- const AsmToken *tok = &Lexer.Lex();
-
- while (tok->is(AsmToken::Identifier)) {
+}
+
+const AsmToken &MasmParser::Lex() {
+ if (Lexer.getTok().is(AsmToken::Error))
+ Error(Lexer.getErrLoc(), Lexer.getErr());
+
+ // if it's a end of statement with a comment in it
+ if (getTok().is(AsmToken::EndOfStatement)) {
+ // if this is a line comment output it.
+ if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
+ getTok().getString().front() != '\r' && MAI.preserveAsmComments())
+ Out.addExplicitComment(Twine(getTok().getString()));
+ }
+
+ const AsmToken *tok = &Lexer.Lex();
+
+ while (tok->is(AsmToken::Identifier)) {
auto it = Variables.find(tok->getIdentifier().lower());
const llvm::MCAsmMacro *M =
getContext().lookupMacro(tok->getIdentifier().lower());
- if (it != Variables.end() && it->second.IsText) {
+ if (it != Variables.end() && it->second.IsText) {
// This is a textmacro; expand it in place.
- std::unique_ptr<MemoryBuffer> Instantiation =
- MemoryBuffer::getMemBufferCopy(it->second.TextValue,
- "<instantiation>");
-
- // Jump to the macro instantiation and prime the lexer.
- CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation),
- getTok().getEndLoc());
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr,
- /*EndStatementAtEOF=*/false);
+ std::unique_ptr<MemoryBuffer> Instantiation =
+ MemoryBuffer::getMemBufferCopy(it->second.TextValue,
+ "<instantiation>");
+
+ // Jump to the macro instantiation and prime the lexer.
+ CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation),
+ getTok().getEndLoc());
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr,
+ /*EndStatementAtEOF=*/false);
EndStatementAtEOFStack.push_back(false);
- tok = &Lexer.Lex();
+ tok = &Lexer.Lex();
} else if (M && M->IsFunction && Lexer.peekTok().is(AsmToken::LParen)) {
// This is a macro function invocation; expand it in place.
const AsmToken MacroTok = *tok;
@@ -1147,18 +1147,18 @@ const AsmToken &MasmParser::Lex() {
tok = &Lexer.Lex();
}
continue;
- } else {
- break;
- }
- }
-
- // Parse comments here to be deferred until end of next statement.
- while (tok->is(AsmToken::Comment)) {
- if (MAI.preserveAsmComments())
- Out.addExplicitComment(Twine(tok->getString()));
- tok = &Lexer.Lex();
- }
-
+ } else {
+ break;
+ }
+ }
+
+ // Parse comments here to be deferred until end of next statement.
+ while (tok->is(AsmToken::Comment)) {
+ if (MAI.preserveAsmComments())
+ Out.addExplicitComment(Twine(tok->getString()));
+ tok = &Lexer.Lex();
+ }
+
// Recognize and bypass line continuations.
while (tok->is(AsmToken::BackSlash) &&
Lexer.peekTok().is(AsmToken::EndOfStatement)) {
@@ -1167,174 +1167,174 @@ const AsmToken &MasmParser::Lex() {
tok = &Lexer.Lex();
}
- if (tok->is(AsmToken::Eof)) {
- // If this is the end of an included file, pop the parent file off the
- // include stack.
- SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
- if (ParentIncludeLoc != SMLoc()) {
+ if (tok->is(AsmToken::Eof)) {
+ // If this is the end of an included file, pop the parent file off the
+ // include stack.
+ SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
+ if (ParentIncludeLoc != SMLoc()) {
EndStatementAtEOFStack.pop_back();
jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
- return Lex();
- }
+ return Lex();
+ }
EndStatementAtEOFStack.pop_back();
assert(EndStatementAtEOFStack.empty());
- }
-
- return *tok;
-}
-
-bool MasmParser::enabledGenDwarfForAssembly() {
- // Check whether the user specified -g.
- if (!getContext().getGenDwarfForAssembly())
- return false;
- // If we haven't encountered any .file directives (which would imply that
- // the assembler source was produced with debug info already) then emit one
- // describing the assembler source file itself.
- if (getContext().getGenDwarfFileNumber() == 0) {
- // Use the first #line directive for this, if any. It's preprocessed, so
- // there is no checksum, and of course no source directive.
- if (!FirstCppHashFilename.empty())
- getContext().setMCLineTableRootFile(/*CUID=*/0,
- getContext().getCompilationDir(),
- FirstCppHashFilename,
- /*Cksum=*/None, /*Source=*/None);
- const MCDwarfFile &RootFile =
- getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
- getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
- /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
- RootFile.Checksum, RootFile.Source));
- }
- return true;
-}
-
-bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
- // Create the initial section, if requested.
- if (!NoInitialTextSection)
- Out.InitSections(false);
-
- // Prime the lexer.
- Lex();
-
- HadError = false;
- AsmCond StartingCondState = TheCondState;
- SmallVector<AsmRewrite, 4> AsmStrRewrites;
-
- // If we are generating dwarf for assembly source files save the initial text
- // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't
- // emitting any actual debug info yet and haven't had a chance to parse any
- // embedded .file directives.)
- if (getContext().getGenDwarfForAssembly()) {
- MCSection *Sec = getStreamer().getCurrentSectionOnly();
- if (!Sec->getBeginSymbol()) {
- MCSymbol *SectionStartSym = getContext().createTempSymbol();
- getStreamer().emitLabel(SectionStartSym);
- Sec->setBeginSymbol(SectionStartSym);
- }
- bool InsertResult = getContext().addGenDwarfSection(Sec);
- assert(InsertResult && ".text section should not have debug info yet");
- (void)InsertResult;
- }
-
- // While we have input, parse each statement.
+ }
+
+ return *tok;
+}
+
+bool MasmParser::enabledGenDwarfForAssembly() {
+ // Check whether the user specified -g.
+ if (!getContext().getGenDwarfForAssembly())
+ return false;
+ // If we haven't encountered any .file directives (which would imply that
+ // the assembler source was produced with debug info already) then emit one
+ // describing the assembler source file itself.
+ if (getContext().getGenDwarfFileNumber() == 0) {
+ // Use the first #line directive for this, if any. It's preprocessed, so
+ // there is no checksum, and of course no source directive.
+ if (!FirstCppHashFilename.empty())
+ getContext().setMCLineTableRootFile(/*CUID=*/0,
+ getContext().getCompilationDir(),
+ FirstCppHashFilename,
+ /*Cksum=*/None, /*Source=*/None);
+ const MCDwarfFile &RootFile =
+ getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
+ getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
+ /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
+ RootFile.Checksum, RootFile.Source));
+ }
+ return true;
+}
+
+bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
+ // Create the initial section, if requested.
+ if (!NoInitialTextSection)
+ Out.InitSections(false);
+
+ // Prime the lexer.
+ Lex();
+
+ HadError = false;
+ AsmCond StartingCondState = TheCondState;
+ SmallVector<AsmRewrite, 4> AsmStrRewrites;
+
+ // If we are generating dwarf for assembly source files save the initial text
+ // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't
+ // emitting any actual debug info yet and haven't had a chance to parse any
+ // embedded .file directives.)
+ if (getContext().getGenDwarfForAssembly()) {
+ MCSection *Sec = getStreamer().getCurrentSectionOnly();
+ if (!Sec->getBeginSymbol()) {
+ MCSymbol *SectionStartSym = getContext().createTempSymbol();
+ getStreamer().emitLabel(SectionStartSym);
+ Sec->setBeginSymbol(SectionStartSym);
+ }
+ bool InsertResult = getContext().addGenDwarfSection(Sec);
+ assert(InsertResult && ".text section should not have debug info yet");
+ (void)InsertResult;
+ }
+
+ // While we have input, parse each statement.
while (Lexer.isNot(AsmToken::Eof) ||
SrcMgr.getParentIncludeLoc(CurBuffer) != SMLoc()) {
// Skip through the EOF at the end of an inclusion.
if (Lexer.is(AsmToken::Eof))
Lex();
- ParseStatementInfo Info(&AsmStrRewrites);
- bool Parsed = parseStatement(Info, nullptr);
-
- // 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 (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
- Lex();
- }
-
- // parseStatement returned true so may need to emit an error.
- printPendingErrors();
-
- // Skipping to the next line if needed.
- if (Parsed && !getLexer().isAtStartOfStatement())
- eatToEndOfStatement();
- }
-
- getTargetParser().onEndOfFile();
- printPendingErrors();
-
- // All errors should have been emitted.
- assert(!hasPendingError() && "unexpected error from parseStatement");
-
- getTargetParser().flushPendingInstructions(getStreamer());
-
- if (TheCondState.TheCond != StartingCondState.TheCond ||
- TheCondState.Ignore != StartingCondState.Ignore)
- 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)
- printError(getTok().getLoc(), "unassigned file number: " +
- Twine(Index) +
- " for .file directives");
- ++Index;
- }
- }
-
- // Check to see that all assembler local symbols were actually defined.
- // Targets that don't do subsections via symbols may not want this, though,
- // so conservatively exclude them. Only do this if we're finalizing, though,
- // as otherwise we won't necessarilly have seen everything yet.
- if (!NoFinalize) {
- if (MAI.hasSubsectionsViaSymbols()) {
- for (const auto &TableEntry : getContext().getSymbols()) {
- MCSymbol *Sym = TableEntry.getValue();
- // Variable symbols may not be marked as defined, so check those
- // explicitly. If we know it's a variable, we have a definition for
- // the purposes of this check.
- if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
- // 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.
- printError(getTok().getLoc(), "assembler local symbol '" +
- Sym->getName() + "' not defined");
- }
- }
-
- // Temporary symbols like the ones for directional jumps don't go in the
- // symbol table. They also need to be diagnosed in all (final) cases.
- for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
- if (std::get<2>(LocSym)->isUndefined()) {
- // 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);
- printError(std::get<0>(LocSym), "directional label undefined");
- }
- }
- }
-
- // Finalize the output stream if there are no errors and if the client wants
- // us to.
- if (!HadError && !NoFinalize)
+ ParseStatementInfo Info(&AsmStrRewrites);
+ bool Parsed = parseStatement(Info, nullptr);
+
+ // 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 (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
+ Lex();
+ }
+
+ // parseStatement returned true so may need to emit an error.
+ printPendingErrors();
+
+ // Skipping to the next line if needed.
+ if (Parsed && !getLexer().isAtStartOfStatement())
+ eatToEndOfStatement();
+ }
+
+ getTargetParser().onEndOfFile();
+ printPendingErrors();
+
+ // All errors should have been emitted.
+ assert(!hasPendingError() && "unexpected error from parseStatement");
+
+ getTargetParser().flushPendingInstructions(getStreamer());
+
+ if (TheCondState.TheCond != StartingCondState.TheCond ||
+ TheCondState.Ignore != StartingCondState.Ignore)
+ 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)
+ printError(getTok().getLoc(), "unassigned file number: " +
+ Twine(Index) +
+ " for .file directives");
+ ++Index;
+ }
+ }
+
+ // Check to see that all assembler local symbols were actually defined.
+ // Targets that don't do subsections via symbols may not want this, though,
+ // so conservatively exclude them. Only do this if we're finalizing, though,
+ // as otherwise we won't necessarilly have seen everything yet.
+ if (!NoFinalize) {
+ if (MAI.hasSubsectionsViaSymbols()) {
+ for (const auto &TableEntry : getContext().getSymbols()) {
+ MCSymbol *Sym = TableEntry.getValue();
+ // Variable symbols may not be marked as defined, so check those
+ // explicitly. If we know it's a variable, we have a definition for
+ // the purposes of this check.
+ if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
+ // 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.
+ printError(getTok().getLoc(), "assembler local symbol '" +
+ Sym->getName() + "' not defined");
+ }
+ }
+
+ // Temporary symbols like the ones for directional jumps don't go in the
+ // symbol table. They also need to be diagnosed in all (final) cases.
+ for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
+ if (std::get<2>(LocSym)->isUndefined()) {
+ // 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);
+ printError(std::get<0>(LocSym), "directional label undefined");
+ }
+ }
+ }
+
+ // Finalize the output stream if there are no errors and if the client wants
+ // us to.
+ if (!HadError && !NoFinalize)
Out.Finish(Lexer.getLoc());
-
- return HadError || getContext().hadError();
-}
-
-bool MasmParser::checkForValidSection() {
- if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
- Out.InitSections(false);
- return Error(getTok().getLoc(),
- "expected section directive before assembly directive");
- }
- return false;
-}
-
-/// Throw away the rest of the line for testing purposes.
-void MasmParser::eatToEndOfStatement() {
+
+ return HadError || getContext().hadError();
+}
+
+bool MasmParser::checkForValidSection() {
+ if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
+ Out.InitSections(false);
+ return Error(getTok().getLoc(),
+ "expected section directive before assembly directive");
+ }
+ return false;
+}
+
+/// Throw away the rest of the line for testing purposes.
+void MasmParser::eatToEndOfStatement() {
while (Lexer.isNot(AsmToken::EndOfStatement)) {
if (Lexer.is(AsmToken::Eof)) {
SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
@@ -1346,14 +1346,14 @@ void MasmParser::eatToEndOfStatement() {
jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
}
- Lexer.Lex();
+ Lexer.Lex();
}
-
- // Eat EOL.
- if (Lexer.is(AsmToken::EndOfStatement))
- Lexer.Lex();
-}
-
+
+ // Eat EOL.
+ if (Lexer.is(AsmToken::EndOfStatement))
+ Lexer.Lex();
+}
+
SmallVector<StringRef, 1>
MasmParser::parseStringRefsTo(AsmToken::TokenKind EndTok) {
SmallVector<StringRef, 1> Refs;
@@ -1387,90 +1387,90 @@ std::string MasmParser::parseStringTo(AsmToken::TokenKind EndTok) {
return Str;
}
-StringRef MasmParser::parseStringToEndOfStatement() {
- const char *Start = getTok().getLoc().getPointer();
-
- while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
- Lexer.Lex();
-
- const char *End = getTok().getLoc().getPointer();
- return StringRef(Start, End - Start);
-}
-
-/// Parse a paren expression and return it.
-/// NOTE: This assumes the leading '(' has already been consumed.
-///
-/// parenexpr ::= expr)
-///
-bool MasmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- if (parseExpression(Res))
- return true;
- if (Lexer.isNot(AsmToken::RParen))
- return TokError("expected ')' in parentheses expression");
- EndLoc = Lexer.getTok().getEndLoc();
- Lex();
- return false;
-}
-
-/// Parse a bracket expression and return it.
-/// NOTE: This assumes the leading '[' has already been consumed.
-///
-/// bracketexpr ::= expr]
-///
-bool MasmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- if (parseExpression(Res))
- return true;
- EndLoc = getTok().getEndLoc();
- if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
- return true;
- return false;
-}
-
-/// Parse a primary expression and return it.
-/// primaryexpr ::= (parenexpr
-/// primaryexpr ::= symbol
-/// primaryexpr ::= number
-/// primaryexpr ::= '.'
+StringRef MasmParser::parseStringToEndOfStatement() {
+ const char *Start = getTok().getLoc().getPointer();
+
+ while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
+ Lexer.Lex();
+
+ const char *End = getTok().getLoc().getPointer();
+ return StringRef(Start, End - Start);
+}
+
+/// Parse a paren expression and return it.
+/// NOTE: This assumes the leading '(' has already been consumed.
+///
+/// parenexpr ::= expr)
+///
+bool MasmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+ if (parseExpression(Res))
+ return true;
+ if (Lexer.isNot(AsmToken::RParen))
+ return TokError("expected ')' in parentheses expression");
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex();
+ return false;
+}
+
+/// Parse a bracket expression and return it.
+/// NOTE: This assumes the leading '[' has already been consumed.
+///
+/// bracketexpr ::= expr]
+///
+bool MasmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+ if (parseExpression(Res))
+ return true;
+ EndLoc = getTok().getEndLoc();
+ if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
+ return true;
+ return false;
+}
+
+/// Parse a primary expression and return it.
+/// primaryexpr ::= (parenexpr
+/// primaryexpr ::= symbol
+/// primaryexpr ::= number
+/// primaryexpr ::= '.'
/// primaryexpr ::= ~,+,-,'not' primaryexpr
/// primaryexpr ::= string
/// (a string is interpreted as a 64-bit number in big-endian base-256)
bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
AsmTypeInfo *TypeInfo) {
- SMLoc FirstTokenLoc = getLexer().getLoc();
- AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
- switch (FirstTokenKind) {
- default:
- return TokError("unknown token in expression");
- // If we have an error assume that we've already handled it.
- case AsmToken::Error:
- return true;
- case AsmToken::Exclaim:
- Lex(); // Eat the operator.
+ SMLoc FirstTokenLoc = getLexer().getLoc();
+ AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
+ switch (FirstTokenKind) {
+ default:
+ return TokError("unknown token in expression");
+ // If we have an error assume that we've already handled it.
+ case AsmToken::Error:
+ return true;
+ case AsmToken::Exclaim:
+ Lex(); // Eat the operator.
if (parsePrimaryExpr(Res, EndLoc, nullptr))
- return true;
- Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
- return false;
- case AsmToken::Dollar:
- case AsmToken::At:
- case AsmToken::Identifier: {
- StringRef Identifier;
- if (parseIdentifier(Identifier)) {
- // 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();
- Out.emitLabel(Sym);
- Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
- getContext());
- EndLoc = FirstTokenLoc;
- return false;
- }
- return Error(FirstTokenLoc, "invalid token in expression");
- }
- }
+ return true;
+ Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
+ return false;
+ case AsmToken::Dollar:
+ case AsmToken::At:
+ case AsmToken::Identifier: {
+ StringRef Identifier;
+ if (parseIdentifier(Identifier)) {
+ // 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();
+ Out.emitLabel(Sym);
+ Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
+ getContext());
+ EndLoc = FirstTokenLoc;
+ return false;
+ }
+ return Error(FirstTokenLoc, "invalid token in expression");
+ }
+ }
// Parse named bitwise negation.
if (Identifier.equals_lower("not")) {
if (parsePrimaryExpr(Res, EndLoc, nullptr))
@@ -1478,101 +1478,101 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
return false;
}
- // Parse symbol variant.
- std::pair<StringRef, StringRef> Split;
- if (!MAI.useParensForSymbolVariant()) {
- if (FirstTokenKind == AsmToken::String) {
- if (Lexer.is(AsmToken::At)) {
- Lex(); // eat @
- SMLoc AtLoc = getLexer().getLoc();
- StringRef VName;
- if (parseIdentifier(VName))
- return Error(AtLoc, "expected symbol variant after '@'");
-
- Split = std::make_pair(Identifier, VName);
- }
- } else {
- Split = Identifier.split('@');
- }
- } else if (Lexer.is(AsmToken::LParen)) {
- Lex(); // eat '('.
- StringRef VName;
- parseIdentifier(VName);
- // eat ')'.
- if (parseToken(AsmToken::RParen,
- "unexpected token in variant, expected ')'"))
- return true;
- Split = std::make_pair(Identifier, VName);
- }
-
- EndLoc = SMLoc::getFromPointer(Identifier.end());
-
- // This is a symbol reference.
- StringRef SymbolName = Identifier;
- if (SymbolName.empty())
- return Error(getLexer().getLoc(), "expected a symbol reference");
-
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
-
- // Look up the symbol variant if used.
- if (!Split.second.empty()) {
- Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
- if (Variant != MCSymbolRefExpr::VK_Invalid) {
- SymbolName = Split.first;
- } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
- Variant = MCSymbolRefExpr::VK_None;
- } else {
- return Error(SMLoc::getFromPointer(Split.second.begin()),
- "invalid variant '" + Split.second + "'");
- }
- }
-
- // Find the field offset if used.
+ // Parse symbol variant.
+ std::pair<StringRef, StringRef> Split;
+ if (!MAI.useParensForSymbolVariant()) {
+ if (FirstTokenKind == AsmToken::String) {
+ if (Lexer.is(AsmToken::At)) {
+ Lex(); // eat @
+ SMLoc AtLoc = getLexer().getLoc();
+ StringRef VName;
+ if (parseIdentifier(VName))
+ return Error(AtLoc, "expected symbol variant after '@'");
+
+ Split = std::make_pair(Identifier, VName);
+ }
+ } else {
+ Split = Identifier.split('@');
+ }
+ } else if (Lexer.is(AsmToken::LParen)) {
+ Lex(); // eat '('.
+ StringRef VName;
+ parseIdentifier(VName);
+ // eat ')'.
+ if (parseToken(AsmToken::RParen,
+ "unexpected token in variant, expected ')'"))
+ return true;
+ Split = std::make_pair(Identifier, VName);
+ }
+
+ EndLoc = SMLoc::getFromPointer(Identifier.end());
+
+ // This is a symbol reference.
+ StringRef SymbolName = Identifier;
+ if (SymbolName.empty())
+ return Error(getLexer().getLoc(), "expected a symbol reference");
+
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+
+ // Look up the symbol variant if used.
+ if (!Split.second.empty()) {
+ Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
+ if (Variant != MCSymbolRefExpr::VK_Invalid) {
+ SymbolName = Split.first;
+ } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
+ Variant = MCSymbolRefExpr::VK_None;
+ } else {
+ return Error(SMLoc::getFromPointer(Split.second.begin()),
+ "invalid variant '" + Split.second + "'");
+ }
+ }
+
+ // Find the field offset if used.
AsmFieldInfo Info;
- Split = SymbolName.split('.');
+ Split = SymbolName.split('.');
if (Split.second.empty()) {
} else {
- SymbolName = Split.first;
+ SymbolName = Split.first;
if (lookUpField(SymbolName, Split.second, Info)) {
std::pair<StringRef, StringRef> BaseMember = Split.second.split('.');
StringRef Base = BaseMember.first, Member = BaseMember.second;
lookUpField(Base, Member, Info);
} else if (Structs.count(SymbolName.lower())) {
- // This is actually a reference to a field offset.
+ // This is actually a reference to a field offset.
Res = MCConstantExpr::create(Info.Offset, getContext());
- return false;
- }
- }
-
- MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
- if (!Sym)
- Sym = getContext().getOrCreateSymbol(SymbolName);
-
- // If this is an absolute variable reference, substitute it now to preserve
- // semantics in the face of reassignment.
- if (Sym->isVariable()) {
- auto V = Sym->getVariableValue(/*SetUsed*/ false);
- bool DoInline = isa<MCConstantExpr>(V) && !Variant;
- if (auto TV = dyn_cast<MCTargetExpr>(V))
- DoInline = TV->inlineAssignedExpr();
- if (DoInline) {
- if (Variant)
- return Error(EndLoc, "unexpected modifier on variable reference");
- Res = Sym->getVariableValue(/*SetUsed*/ false);
- return false;
- }
- }
-
- // Otherwise create a symbol ref.
- const MCExpr *SymRef =
- MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
+ return false;
+ }
+ }
+
+ MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
+ if (!Sym)
+ Sym = getContext().getOrCreateSymbol(SymbolName);
+
+ // If this is an absolute variable reference, substitute it now to preserve
+ // semantics in the face of reassignment.
+ if (Sym->isVariable()) {
+ auto V = Sym->getVariableValue(/*SetUsed*/ false);
+ bool DoInline = isa<MCConstantExpr>(V) && !Variant;
+ if (auto TV = dyn_cast<MCTargetExpr>(V))
+ DoInline = TV->inlineAssignedExpr();
+ if (DoInline) {
+ if (Variant)
+ return Error(EndLoc, "unexpected modifier on variable reference");
+ Res = Sym->getVariableValue(/*SetUsed*/ false);
+ return false;
+ }
+ }
+
+ // Otherwise create a symbol ref.
+ const MCExpr *SymRef =
+ MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
if (Info.Offset) {
Res = MCBinaryExpr::create(
MCBinaryExpr::Add, SymRef,
MCConstantExpr::create(Info.Offset, getContext()), getContext());
- } else {
- Res = SymRef;
- }
+ } else {
+ Res = SymRef;
+ }
if (TypeInfo) {
if (Info.Type.Name.empty()) {
auto TypeIt = KnownType.find(Identifier.lower());
@@ -1583,41 +1583,41 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
*TypeInfo = Info.Type;
}
- return false;
- }
- case AsmToken::BigNum:
- return TokError("literal value out of range for directive");
- case AsmToken::Integer: {
- SMLoc Loc = getTok().getLoc();
- int64_t IntVal = getTok().getIntVal();
- Res = MCConstantExpr::create(IntVal, getContext());
- EndLoc = Lexer.getTok().getEndLoc();
- Lex(); // Eat token.
- // Look for 'b' or 'f' following an Integer as a directional label.
- if (Lexer.getKind() == AsmToken::Identifier) {
- StringRef IDVal = getTok().getString();
- // Look up the symbol variant if used.
- std::pair<StringRef, StringRef> Split = IDVal.split('@');
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
- if (Split.first.size() != IDVal.size()) {
- Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
- if (Variant == MCSymbolRefExpr::VK_Invalid)
- return TokError("invalid variant '" + Split.second + "'");
- IDVal = Split.first;
- }
- if (IDVal == "f" || IDVal == "b") {
- MCSymbol *Sym =
- Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
- Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
- if (IDVal == "b" && Sym->isUndefined())
- return Error(Loc, "directional label undefined");
- DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
- EndLoc = Lexer.getTok().getEndLoc();
- Lex(); // Eat identifier.
- }
- }
- return false;
- }
+ return false;
+ }
+ case AsmToken::BigNum:
+ return TokError("literal value out of range for directive");
+ case AsmToken::Integer: {
+ SMLoc Loc = getTok().getLoc();
+ int64_t IntVal = getTok().getIntVal();
+ Res = MCConstantExpr::create(IntVal, getContext());
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex(); // Eat token.
+ // Look for 'b' or 'f' following an Integer as a directional label.
+ if (Lexer.getKind() == AsmToken::Identifier) {
+ StringRef IDVal = getTok().getString();
+ // Look up the symbol variant if used.
+ std::pair<StringRef, StringRef> Split = IDVal.split('@');
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+ if (Split.first.size() != IDVal.size()) {
+ Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
+ if (Variant == MCSymbolRefExpr::VK_Invalid)
+ return TokError("invalid variant '" + Split.second + "'");
+ IDVal = Split.first;
+ }
+ if (IDVal == "f" || IDVal == "b") {
+ MCSymbol *Sym =
+ Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
+ Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
+ if (IDVal == "b" && Sym->isUndefined())
+ return Error(Loc, "directional label undefined");
+ DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex(); // Eat identifier.
+ }
+ }
+ return false;
+ }
case AsmToken::String: {
// MASM strings (used as constants) are interpreted as big-endian base-256.
SMLoc ValueLoc = getTok().getLoc();
@@ -1632,286 +1632,286 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
Res = MCConstantExpr::create(IntValue, getContext());
return false;
}
- case AsmToken::Real: {
- APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
- uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
- Res = MCConstantExpr::create(IntVal, getContext());
- EndLoc = Lexer.getTok().getEndLoc();
- Lex(); // Eat token.
- return false;
- }
- case AsmToken::Dot: {
- // This is a '.' reference, which references the current PC. Emit a
- // temporary label to the streamer and refer to it.
- MCSymbol *Sym = Ctx.createTempSymbol();
- Out.emitLabel(Sym);
- Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
- EndLoc = Lexer.getTok().getEndLoc();
- Lex(); // Eat identifier.
- return false;
- }
- case AsmToken::LParen:
- Lex(); // Eat the '('.
- return parseParenExpr(Res, EndLoc);
- case AsmToken::LBrac:
- if (!PlatformParser->HasBracketExpressions())
- return TokError("brackets expression not supported on this target");
- Lex(); // Eat the '['.
- return parseBracketExpr(Res, EndLoc);
- case AsmToken::Minus:
- Lex(); // Eat the operator.
+ case AsmToken::Real: {
+ APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
+ uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
+ Res = MCConstantExpr::create(IntVal, getContext());
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex(); // Eat token.
+ return false;
+ }
+ case AsmToken::Dot: {
+ // This is a '.' reference, which references the current PC. Emit a
+ // temporary label to the streamer and refer to it.
+ MCSymbol *Sym = Ctx.createTempSymbol();
+ Out.emitLabel(Sym);
+ Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex(); // Eat identifier.
+ return false;
+ }
+ case AsmToken::LParen:
+ Lex(); // Eat the '('.
+ return parseParenExpr(Res, EndLoc);
+ case AsmToken::LBrac:
+ if (!PlatformParser->HasBracketExpressions())
+ return TokError("brackets expression not supported on this target");
+ Lex(); // Eat the '['.
+ return parseBracketExpr(Res, EndLoc);
+ case AsmToken::Minus:
+ Lex(); // Eat the operator.
if (parsePrimaryExpr(Res, EndLoc, nullptr))
- return true;
- Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
- return false;
- case AsmToken::Plus:
- Lex(); // Eat the operator.
+ return true;
+ Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
+ return false;
+ case AsmToken::Plus:
+ Lex(); // Eat the operator.
if (parsePrimaryExpr(Res, EndLoc, nullptr))
- return true;
- Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
- return false;
- case AsmToken::Tilde:
- Lex(); // Eat the operator.
+ return true;
+ Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
+ return false;
+ case AsmToken::Tilde:
+ Lex(); // Eat the operator.
if (parsePrimaryExpr(Res, EndLoc, nullptr))
- return true;
- Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
- 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;
- }
-}
-
-bool MasmParser::parseExpression(const MCExpr *&Res) {
- SMLoc EndLoc;
- return parseExpression(Res, EndLoc);
-}
-
-/// This function checks if the next token is <string> type or arithmetic.
-/// string that begin with character '<' must end with character '>'.
-/// otherwise it is arithmetics.
-/// If the function returns a 'true' value,
-/// the End argument will be filled with the last location pointed to the '>'
-/// character.
-static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
- assert((StrLoc.getPointer() != nullptr) &&
- "Argument to the function cannot be a NULL value");
- const char *CharPtr = StrLoc.getPointer();
- while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
- (*CharPtr != '\0')) {
- if (*CharPtr == '!')
- CharPtr++;
- CharPtr++;
- }
- if (*CharPtr == '>') {
- EndLoc = StrLoc.getFromPointer(CharPtr + 1);
- return true;
- }
- return false;
-}
-
-/// creating a string without the escape characters '!'.
+ return true;
+ Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
+ 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;
+ }
+}
+
+bool MasmParser::parseExpression(const MCExpr *&Res) {
+ SMLoc EndLoc;
+ return parseExpression(Res, EndLoc);
+}
+
+/// This function checks if the next token is <string> type or arithmetic.
+/// string that begin with character '<' must end with character '>'.
+/// otherwise it is arithmetics.
+/// If the function returns a 'true' value,
+/// the End argument will be filled with the last location pointed to the '>'
+/// character.
+static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
+ assert((StrLoc.getPointer() != nullptr) &&
+ "Argument to the function cannot be a NULL value");
+ const char *CharPtr = StrLoc.getPointer();
+ while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
+ (*CharPtr != '\0')) {
+ if (*CharPtr == '!')
+ CharPtr++;
+ CharPtr++;
+ }
+ if (*CharPtr == '>') {
+ EndLoc = StrLoc.getFromPointer(CharPtr + 1);
+ return true;
+ }
+ return false;
+}
+
+/// creating a string without the escape characters '!'.
static std::string angleBracketString(StringRef BracketContents) {
- std::string Res;
+ std::string Res;
for (size_t Pos = 0; Pos < BracketContents.size(); Pos++) {
if (BracketContents[Pos] == '!')
- Pos++;
+ Pos++;
Res += BracketContents[Pos];
- }
- return Res;
-}
-
-/// Parse an expression and return it.
-///
-/// expr ::= expr &&,|| expr -> lowest.
-/// expr ::= expr |,^,&,! expr
-/// expr ::= expr ==,!=,<>,<,<=,>,>= expr
-/// expr ::= expr <<,>> expr
-/// expr ::= expr +,- expr
-/// expr ::= expr *,/,% expr -> highest.
-/// expr ::= primaryexpr
-///
-bool MasmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
- // Parse the expression.
- Res = nullptr;
- if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
- parseBinOpRHS(1, Res, EndLoc))
- return true;
-
- // Try to constant fold it up front, if possible. Do not exploit
- // assembler here.
- int64_t Value;
- if (Res->evaluateAsAbsolute(Value))
- Res = MCConstantExpr::create(Value, getContext());
-
- return false;
-}
-
-bool MasmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
- Res = nullptr;
- return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
-}
-
-bool MasmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
- SMLoc &EndLoc) {
- if (parseParenExpr(Res, EndLoc))
- return true;
-
- for (; ParenDepth > 0; --ParenDepth) {
- if (parseBinOpRHS(1, Res, EndLoc))
- return true;
-
- // We don't Lex() the last RParen.
- // This is the same behavior as parseParenExpression().
- if (ParenDepth - 1 > 0) {
- EndLoc = getTok().getEndLoc();
- if (parseToken(AsmToken::RParen,
- "expected ')' in parentheses expression"))
- return true;
- }
- }
- return false;
-}
-
-bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
- const MCExpr *Expr;
-
- SMLoc StartLoc = Lexer.getLoc();
- if (parseExpression(Expr))
- return true;
-
- if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
- return Error(StartLoc, "expected absolute expression");
-
- return false;
-}
-
-static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind,
- bool ShouldUseLogicalShr,
- bool EndExpressionAtGreater) {
- switch (K) {
- default:
- return 0; // not a binop.
-
- // Lowest Precedence: &&, ||
- case AsmToken::AmpAmp:
- Kind = MCBinaryExpr::LAnd;
- return 2;
- case AsmToken::PipePipe:
- Kind = MCBinaryExpr::LOr;
- return 1;
-
- // Low Precedence: ==, !=, <>, <, <=, >, >=
- case AsmToken::EqualEqual:
- Kind = MCBinaryExpr::EQ;
- return 3;
- case AsmToken::ExclaimEqual:
- case AsmToken::LessGreater:
- Kind = MCBinaryExpr::NE;
- return 3;
- case AsmToken::Less:
- Kind = MCBinaryExpr::LT;
- return 3;
- case AsmToken::LessEqual:
- Kind = MCBinaryExpr::LTE;
- return 3;
- case AsmToken::Greater:
- if (EndExpressionAtGreater)
- return 0;
- Kind = MCBinaryExpr::GT;
- return 3;
- case AsmToken::GreaterEqual:
- Kind = MCBinaryExpr::GTE;
- return 3;
-
- // Low Intermediate Precedence: +, -
- case AsmToken::Plus:
- Kind = MCBinaryExpr::Add;
- return 4;
- case AsmToken::Minus:
- Kind = MCBinaryExpr::Sub;
- return 4;
-
- // High Intermediate Precedence: |, &, ^
- case AsmToken::Pipe:
- Kind = MCBinaryExpr::Or;
- return 5;
- case AsmToken::Caret:
- Kind = MCBinaryExpr::Xor;
- return 5;
- case AsmToken::Amp:
- Kind = MCBinaryExpr::And;
- return 5;
-
- // Highest Precedence: *, /, %, <<, >>
- case AsmToken::Star:
- Kind = MCBinaryExpr::Mul;
- return 6;
- case AsmToken::Slash:
- Kind = MCBinaryExpr::Div;
- return 6;
- case AsmToken::Percent:
- Kind = MCBinaryExpr::Mod;
- return 6;
- case AsmToken::LessLess:
- Kind = MCBinaryExpr::Shl;
- return 6;
- case AsmToken::GreaterGreater:
- if (EndExpressionAtGreater)
- return 0;
- Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
- return 6;
- }
-}
-
-unsigned MasmParser::getBinOpPrecedence(AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind) {
- bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
- return getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr,
- AngleBracketDepth > 0);
-}
-
-/// Parse all binary operators with precedence >= 'Precedence'.
-/// Res contains the LHS of the expression on input.
-bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
- SMLoc &EndLoc) {
- SMLoc StartLoc = Lexer.getLoc();
- while (true) {
+ }
+ return Res;
+}
+
+/// Parse an expression and return it.
+///
+/// expr ::= expr &&,|| expr -> lowest.
+/// expr ::= expr |,^,&,! expr
+/// expr ::= expr ==,!=,<>,<,<=,>,>= expr
+/// expr ::= expr <<,>> expr
+/// expr ::= expr +,- expr
+/// expr ::= expr *,/,% expr -> highest.
+/// expr ::= primaryexpr
+///
+bool MasmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
+ // Parse the expression.
+ Res = nullptr;
+ if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
+ parseBinOpRHS(1, Res, EndLoc))
+ return true;
+
+ // Try to constant fold it up front, if possible. Do not exploit
+ // assembler here.
+ int64_t Value;
+ if (Res->evaluateAsAbsolute(Value))
+ Res = MCConstantExpr::create(Value, getContext());
+
+ return false;
+}
+
+bool MasmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
+ Res = nullptr;
+ return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
+}
+
+bool MasmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
+ SMLoc &EndLoc) {
+ if (parseParenExpr(Res, EndLoc))
+ return true;
+
+ for (; ParenDepth > 0; --ParenDepth) {
+ if (parseBinOpRHS(1, Res, EndLoc))
+ return true;
+
+ // We don't Lex() the last RParen.
+ // This is the same behavior as parseParenExpression().
+ if (ParenDepth - 1 > 0) {
+ EndLoc = getTok().getEndLoc();
+ if (parseToken(AsmToken::RParen,
+ "expected ')' in parentheses expression"))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
+ const MCExpr *Expr;
+
+ SMLoc StartLoc = Lexer.getLoc();
+ if (parseExpression(Expr))
+ return true;
+
+ if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
+ return Error(StartLoc, "expected absolute expression");
+
+ return false;
+}
+
+static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K,
+ MCBinaryExpr::Opcode &Kind,
+ bool ShouldUseLogicalShr,
+ bool EndExpressionAtGreater) {
+ switch (K) {
+ default:
+ return 0; // not a binop.
+
+ // Lowest Precedence: &&, ||
+ case AsmToken::AmpAmp:
+ Kind = MCBinaryExpr::LAnd;
+ return 2;
+ case AsmToken::PipePipe:
+ Kind = MCBinaryExpr::LOr;
+ return 1;
+
+ // Low Precedence: ==, !=, <>, <, <=, >, >=
+ case AsmToken::EqualEqual:
+ Kind = MCBinaryExpr::EQ;
+ return 3;
+ case AsmToken::ExclaimEqual:
+ case AsmToken::LessGreater:
+ Kind = MCBinaryExpr::NE;
+ return 3;
+ case AsmToken::Less:
+ Kind = MCBinaryExpr::LT;
+ return 3;
+ case AsmToken::LessEqual:
+ Kind = MCBinaryExpr::LTE;
+ return 3;
+ case AsmToken::Greater:
+ if (EndExpressionAtGreater)
+ return 0;
+ Kind = MCBinaryExpr::GT;
+ return 3;
+ case AsmToken::GreaterEqual:
+ Kind = MCBinaryExpr::GTE;
+ return 3;
+
+ // Low Intermediate Precedence: +, -
+ case AsmToken::Plus:
+ Kind = MCBinaryExpr::Add;
+ return 4;
+ case AsmToken::Minus:
+ Kind = MCBinaryExpr::Sub;
+ return 4;
+
+ // High Intermediate Precedence: |, &, ^
+ case AsmToken::Pipe:
+ Kind = MCBinaryExpr::Or;
+ return 5;
+ case AsmToken::Caret:
+ Kind = MCBinaryExpr::Xor;
+ return 5;
+ case AsmToken::Amp:
+ Kind = MCBinaryExpr::And;
+ return 5;
+
+ // Highest Precedence: *, /, %, <<, >>
+ case AsmToken::Star:
+ Kind = MCBinaryExpr::Mul;
+ return 6;
+ case AsmToken::Slash:
+ Kind = MCBinaryExpr::Div;
+ return 6;
+ case AsmToken::Percent:
+ Kind = MCBinaryExpr::Mod;
+ return 6;
+ case AsmToken::LessLess:
+ Kind = MCBinaryExpr::Shl;
+ return 6;
+ case AsmToken::GreaterGreater:
+ if (EndExpressionAtGreater)
+ return 0;
+ Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
+ return 6;
+ }
+}
+
+unsigned MasmParser::getBinOpPrecedence(AsmToken::TokenKind K,
+ MCBinaryExpr::Opcode &Kind) {
+ bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
+ return getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr,
+ AngleBracketDepth > 0);
+}
+
+/// Parse all binary operators with precedence >= 'Precedence'.
+/// Res contains the LHS of the expression on input.
+bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
+ SMLoc &EndLoc) {
+ SMLoc StartLoc = Lexer.getLoc();
+ while (true) {
AsmToken::TokenKind TokKind = Lexer.getKind();
if (Lexer.getKind() == AsmToken::Identifier) {
TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
@@ -1926,52 +1926,52 @@ bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
.CaseLower("ge", AsmToken::GreaterEqual)
.Default(TokKind);
}
- MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
+ MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
-
- // If the next token is lower precedence than we are allowed to eat, return
- // successfully with what we ate already.
- if (TokPrec < Precedence)
- return false;
-
- Lex();
-
- // Eat the next primary expression.
- const MCExpr *RHS;
- if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
- return true;
-
- // If BinOp binds less tightly with RHS than the operator after RHS, let
- // the pending operator take RHS as its LHS.
- MCBinaryExpr::Opcode Dummy;
- unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
- if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
- return true;
-
- // Merge LHS and RHS according to operator.
- Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
- }
-}
-
-/// ParseStatement:
+
+ // If the next token is lower precedence than we are allowed to eat, return
+ // successfully with what we ate already.
+ if (TokPrec < Precedence)
+ return false;
+
+ Lex();
+
+ // Eat the next primary expression.
+ const MCExpr *RHS;
+ if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
+ return true;
+
+ // If BinOp binds less tightly with RHS than the operator after RHS, let
+ // the pending operator take RHS as its LHS.
+ MCBinaryExpr::Opcode Dummy;
+ unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
+ if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
+ return true;
+
+ // Merge LHS and RHS according to operator.
+ Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
+ }
+}
+
+/// ParseStatement:
/// ::= % statement
-/// ::= EndOfStatement
-/// ::= Label* Directive ...Operands... EndOfStatement
-/// ::= Label* Identifier OperandList* EndOfStatement
-bool MasmParser::parseStatement(ParseStatementInfo &Info,
- MCAsmParserSemaCallback *SI) {
- assert(!hasPendingError() && "parseStatement started with pending error");
- // Eat initial spaces and comments.
- while (Lexer.is(AsmToken::Space))
- Lex();
- if (Lexer.is(AsmToken::EndOfStatement)) {
- // If this is a line comment we can drop it safely.
- if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
- getTok().getString().front() == '\n')
- Out.AddBlankLine();
- Lex();
- return false;
- }
+/// ::= EndOfStatement
+/// ::= Label* Directive ...Operands... EndOfStatement
+/// ::= Label* Identifier OperandList* EndOfStatement
+bool MasmParser::parseStatement(ParseStatementInfo &Info,
+ MCAsmParserSemaCallback *SI) {
+ assert(!hasPendingError() && "parseStatement started with pending error");
+ // Eat initial spaces and comments.
+ while (Lexer.is(AsmToken::Space))
+ Lex();
+ if (Lexer.is(AsmToken::EndOfStatement)) {
+ // If this is a line comment we can drop it safely.
+ if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
+ getTok().getString().front() == '\n')
+ Out.AddBlankLine();
+ Lex();
+ return false;
+ }
// If preceded by an expansion operator, first expand all text macros and
// macro functions.
@@ -1981,321 +1981,321 @@ bool MasmParser::parseStatement(ParseStatementInfo &Info,
return true;
}
- // Statements always start with an identifier, unless we're dealing with a
- // processor directive (.386, .686, etc.) that lexes as a real.
- AsmToken ID = getTok();
- SMLoc IDLoc = ID.getLoc();
- StringRef IDVal;
- int64_t LocalLabelVal = -1;
- if (Lexer.is(AsmToken::HashDirective))
- return parseCppHashLineFilenameComment(IDLoc);
- // Allow an integer followed by a ':' as a directional local label.
- if (Lexer.is(AsmToken::Integer)) {
- LocalLabelVal = getTok().getIntVal();
- if (LocalLabelVal < 0) {
- 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) {
- Lex(); // always eat a token
- return Error(IDLoc, "unexpected token at start of statement");
- }
- }
- }
- } else if (Lexer.is(AsmToken::Dot)) {
- // Treat '.' as a valid identifier in this context.
- Lex();
- IDVal = ".";
- } else if (Lexer.is(AsmToken::LCurly)) {
- // Treat '{' as a valid identifier in this context.
- Lex();
- IDVal = "{";
-
- } else if (Lexer.is(AsmToken::RCurly)) {
- // Treat '}' as a valid identifier in this context.
- Lex();
- IDVal = "}";
- } else if (Lexer.is(AsmToken::Star) &&
- getTargetParser().starIsStartOfStatement()) {
- // Accept '*' as a valid start of statement.
- Lex();
- IDVal = "*";
- } else if (Lexer.is(AsmToken::Real)) {
- // Treat ".<number>" as a valid identifier in this context.
- IDVal = getTok().getString();
- Lex(); // always eat a token
- if (!IDVal.startswith("."))
- return Error(IDLoc, "unexpected token at start of statement");
+ // Statements always start with an identifier, unless we're dealing with a
+ // processor directive (.386, .686, etc.) that lexes as a real.
+ AsmToken ID = getTok();
+ SMLoc IDLoc = ID.getLoc();
+ StringRef IDVal;
+ int64_t LocalLabelVal = -1;
+ if (Lexer.is(AsmToken::HashDirective))
+ return parseCppHashLineFilenameComment(IDLoc);
+ // Allow an integer followed by a ':' as a directional local label.
+ if (Lexer.is(AsmToken::Integer)) {
+ LocalLabelVal = getTok().getIntVal();
+ if (LocalLabelVal < 0) {
+ 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) {
+ Lex(); // always eat a token
+ return Error(IDLoc, "unexpected token at start of statement");
+ }
+ }
+ }
+ } else if (Lexer.is(AsmToken::Dot)) {
+ // Treat '.' as a valid identifier in this context.
+ Lex();
+ IDVal = ".";
+ } else if (Lexer.is(AsmToken::LCurly)) {
+ // Treat '{' as a valid identifier in this context.
+ Lex();
+ IDVal = "{";
+
+ } else if (Lexer.is(AsmToken::RCurly)) {
+ // Treat '}' as a valid identifier in this context.
+ Lex();
+ IDVal = "}";
+ } else if (Lexer.is(AsmToken::Star) &&
+ getTargetParser().starIsStartOfStatement()) {
+ // Accept '*' as a valid start of statement.
+ Lex();
+ IDVal = "*";
+ } else if (Lexer.is(AsmToken::Real)) {
+ // Treat ".<number>" as a valid identifier in this context.
+ IDVal = getTok().getString();
+ Lex(); // always eat a token
+ if (!IDVal.startswith("."))
+ return Error(IDLoc, "unexpected token at start of statement");
} else if (Lexer.is(AsmToken::Identifier) &&
getTok().getString().equals_lower("echo")) {
// Intercept echo early to avoid lexical substitution in its message, and
// delegate all handling to the appropriate function.
return parseDirectiveEcho();
- } else if (parseIdentifier(IDVal)) {
- if (!TheCondState.Ignore) {
- Lex(); // always eat a token
- return Error(IDLoc, "unexpected token at start of statement");
- }
- IDVal = "";
- }
-
- // Handle conditional assembly here before checking for skipping. We
- // have to do this so that .endif isn't skipped in a ".if 0" block for
- // example.
- StringMap<DirectiveKind>::const_iterator DirKindIt =
- DirectiveKindMap.find(IDVal.lower());
- DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
- ? DK_NO_DIRECTIVE
- : DirKindIt->getValue();
- switch (DirKind) {
- default:
- break;
- case DK_IF:
- case DK_IFE:
- return parseDirectiveIf(IDLoc, DirKind);
- case DK_IFB:
- return parseDirectiveIfb(IDLoc, true);
- case DK_IFNB:
- return parseDirectiveIfb(IDLoc, false);
- case DK_IFDEF:
- return parseDirectiveIfdef(IDLoc, true);
- case DK_IFNDEF:
- return parseDirectiveIfdef(IDLoc, false);
- case DK_IFDIF:
- return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
- /*CaseInsensitive=*/false);
- case DK_IFDIFI:
- return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
- /*CaseInsensitive=*/true);
- case DK_IFIDN:
- return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
- /*CaseInsensitive=*/false);
- case DK_IFIDNI:
- return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
- /*CaseInsensitive=*/true);
- case DK_ELSEIF:
- case DK_ELSEIFE:
- return parseDirectiveElseIf(IDLoc, DirKind);
- case DK_ELSEIFB:
- return parseDirectiveElseIfb(IDLoc, true);
- case DK_ELSEIFNB:
- return parseDirectiveElseIfb(IDLoc, false);
- case DK_ELSEIFDEF:
- return parseDirectiveElseIfdef(IDLoc, true);
- case DK_ELSEIFNDEF:
- return parseDirectiveElseIfdef(IDLoc, false);
- case DK_ELSEIFDIF:
- return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
- /*CaseInsensitive=*/false);
- case DK_ELSEIFDIFI:
- return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
- /*CaseInsensitive=*/true);
- case DK_ELSEIFIDN:
- return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
- /*CaseInsensitive=*/false);
- case DK_ELSEIFIDNI:
- return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
- /*CaseInsensitive=*/true);
- case DK_ELSE:
- return parseDirectiveElse(IDLoc);
- case DK_ENDIF:
- return parseDirectiveEndIf(IDLoc);
- }
-
- // Ignore the statement if in the middle of inactive conditional
- // (e.g. ".if 0").
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- return false;
- }
-
- // FIXME: Recurse on local labels?
-
- // See what kind of statement we have.
- switch (Lexer.getKind()) {
- case AsmToken::Colon: {
- if (!getTargetParser().isLabel(ID))
- break;
- if (checkForValidSection())
- return true;
-
- // identifier ':' -> Label.
- Lex();
-
- // Diagnose attempt to use '.' as a label.
- if (IDVal == ".")
- return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
-
- // Diagnose attempt to use a variable as a label.
- //
- // FIXME: Diagnostics. Note the location of the definition as a label.
- // FIXME: This doesn't diagnose assignment to a symbol which has been
- // implicitly marked as external.
- MCSymbol *Sym;
- if (LocalLabelVal == -1) {
- if (ParsingMSInlineAsm && SI) {
- StringRef RewrittenLabel =
- SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
- assert(!RewrittenLabel.empty() &&
- "We should have an internal name here.");
- Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
- RewrittenLabel);
- IDVal = RewrittenLabel;
- }
- Sym = getContext().getOrCreateSymbol(IDVal);
- } else
- Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
- // 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)) {
+ } else if (parseIdentifier(IDVal)) {
+ if (!TheCondState.Ignore) {
+ Lex(); // always eat a token
+ return Error(IDLoc, "unexpected token at start of statement");
+ }
+ IDVal = "";
+ }
+
+ // Handle conditional assembly here before checking for skipping. We
+ // have to do this so that .endif isn't skipped in a ".if 0" block for
+ // example.
+ StringMap<DirectiveKind>::const_iterator DirKindIt =
+ DirectiveKindMap.find(IDVal.lower());
+ DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
+ ? DK_NO_DIRECTIVE
+ : DirKindIt->getValue();
+ switch (DirKind) {
+ default:
+ break;
+ case DK_IF:
+ case DK_IFE:
+ return parseDirectiveIf(IDLoc, DirKind);
+ case DK_IFB:
+ return parseDirectiveIfb(IDLoc, true);
+ case DK_IFNB:
+ return parseDirectiveIfb(IDLoc, false);
+ case DK_IFDEF:
+ return parseDirectiveIfdef(IDLoc, true);
+ case DK_IFNDEF:
+ return parseDirectiveIfdef(IDLoc, false);
+ case DK_IFDIF:
+ return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
+ /*CaseInsensitive=*/false);
+ case DK_IFDIFI:
+ return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
+ /*CaseInsensitive=*/true);
+ case DK_IFIDN:
+ return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
+ /*CaseInsensitive=*/false);
+ case DK_IFIDNI:
+ return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
+ /*CaseInsensitive=*/true);
+ case DK_ELSEIF:
+ case DK_ELSEIFE:
+ return parseDirectiveElseIf(IDLoc, DirKind);
+ case DK_ELSEIFB:
+ return parseDirectiveElseIfb(IDLoc, true);
+ case DK_ELSEIFNB:
+ return parseDirectiveElseIfb(IDLoc, false);
+ case DK_ELSEIFDEF:
+ return parseDirectiveElseIfdef(IDLoc, true);
+ case DK_ELSEIFNDEF:
+ return parseDirectiveElseIfdef(IDLoc, false);
+ case DK_ELSEIFDIF:
+ return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
+ /*CaseInsensitive=*/false);
+ case DK_ELSEIFDIFI:
+ return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
+ /*CaseInsensitive=*/true);
+ case DK_ELSEIFIDN:
+ return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
+ /*CaseInsensitive=*/false);
+ case DK_ELSEIFIDNI:
+ return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
+ /*CaseInsensitive=*/true);
+ case DK_ELSE:
+ return parseDirectiveElse(IDLoc);
+ case DK_ENDIF:
+ return parseDirectiveEndIf(IDLoc);
+ }
+
+ // Ignore the statement if in the middle of inactive conditional
+ // (e.g. ".if 0").
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+
+ // FIXME: Recurse on local labels?
+
+ // See what kind of statement we have.
+ switch (Lexer.getKind()) {
+ case AsmToken::Colon: {
+ if (!getTargetParser().isLabel(ID))
+ break;
+ if (checkForValidSection())
+ return true;
+
+ // identifier ':' -> Label.
+ Lex();
+
+ // Diagnose attempt to use '.' as a label.
+ if (IDVal == ".")
+ return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
+
+ // Diagnose attempt to use a variable as a label.
+ //
+ // FIXME: Diagnostics. Note the location of the definition as a label.
+ // FIXME: This doesn't diagnose assignment to a symbol which has been
+ // implicitly marked as external.
+ MCSymbol *Sym;
+ if (LocalLabelVal == -1) {
+ if (ParsingMSInlineAsm && SI) {
+ StringRef RewrittenLabel =
+ SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
+ assert(!RewrittenLabel.empty() &&
+ "We should have an internal name here.");
+ Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
+ RewrittenLabel);
+ IDVal = RewrittenLabel;
+ }
+ Sym = getContext().getOrCreateSymbol(IDVal);
+ } else
+ Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
+ // 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)) {
std::string CommentStr = parseStringTo(AsmToken::EndOfStatement);
- 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)) {
- Lex();
- }
-
- getTargetParser().doBeforeLabelEmit(Sym);
-
- // Emit the label.
- if (!getTargetParser().isParsingMSInlineAsm())
- Out.emitLabel(Sym, IDLoc);
-
- // If we are generating dwarf for assembly source files then gather the
- // info to make a dwarf label entry for this label if needed.
- if (enabledGenDwarfForAssembly())
- MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
- IDLoc);
-
- getTargetParser().onLabelParsed(Sym);
-
- return false;
- }
-
- default: // Normal instruction or directive.
- break;
- }
-
- // If macros are enabled, check to see if this is a macro instantiation.
+ 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)) {
+ Lex();
+ }
+
+ getTargetParser().doBeforeLabelEmit(Sym);
+
+ // Emit the label.
+ if (!getTargetParser().isParsingMSInlineAsm())
+ Out.emitLabel(Sym, IDLoc);
+
+ // If we are generating dwarf for assembly source files then gather the
+ // info to make a dwarf label entry for this label if needed.
+ if (enabledGenDwarfForAssembly())
+ MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
+ IDLoc);
+
+ getTargetParser().onLabelParsed(Sym);
+
+ return false;
+ }
+
+ default: // Normal instruction or directive.
+ break;
+ }
+
+ // If macros are enabled, check to see if this is a macro instantiation.
if (const MCAsmMacro *M = getContext().lookupMacro(IDVal.lower())) {
- return handleMacroEntry(M, IDLoc);
- }
-
- // Otherwise, we have a normal instruction or directive.
-
- if (DirKind != DK_NO_DIRECTIVE) {
- // There are several entities interested in parsing directives:
- //
- // 1. Asm parser extensions. For example, platform-specific parsers
- // (like the ELF parser) register themselves as extensions.
- // 2. The target-specific assembly parser. Some directives are target
- // specific or may potentially behave differently on certain targets.
- // 3. The generic directive parser implemented by this class. These are
- // all the directives that behave in a target and platform independent
- // manner, or at least have a default behavior that's shared between
- // all targets and platforms.
-
- getTargetParser().flushPendingInstructions(getStreamer());
-
- // Special-case handling of structure-end directives at higher priority,
- // since ENDS is overloaded as a segment-end directive.
- if (IDVal.equals_lower("ends") && StructInProgress.size() > 1 &&
- getTok().is(AsmToken::EndOfStatement)) {
- return parseDirectiveNestedEnds();
- }
-
- // First, check the extension directive map to see if any extension has
- // registered itself to parse this directive.
- std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
- ExtensionDirectiveMap.lookup(IDVal.lower());
- if (Handler.first)
- return (*Handler.second)(Handler.first, IDVal, IDLoc);
-
- // Next, let the target-specific assembly parser try.
- SMLoc StartTokLoc = getTok().getLoc();
- bool TPDirectiveReturn =
- ID.is(AsmToken::Identifier) && 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;
-
- // Finally, if no one else is interested in this directive, it must be
- // generic and familiar to this class.
- switch (DirKind) {
- default:
- break;
- case DK_ASCII:
- return parseDirectiveAscii(IDVal, false);
- case DK_ASCIZ:
- case DK_STRING:
- return parseDirectiveAscii(IDVal, true);
- case DK_BYTE:
- case DK_SBYTE:
- case DK_DB:
- return parseDirectiveValue(IDVal, 1);
- case DK_WORD:
- case DK_SWORD:
- case DK_DW:
- return parseDirectiveValue(IDVal, 2);
- case DK_DWORD:
- case DK_SDWORD:
- case DK_DD:
- return parseDirectiveValue(IDVal, 4);
- case DK_FWORD:
+ return handleMacroEntry(M, IDLoc);
+ }
+
+ // Otherwise, we have a normal instruction or directive.
+
+ if (DirKind != DK_NO_DIRECTIVE) {
+ // There are several entities interested in parsing directives:
+ //
+ // 1. Asm parser extensions. For example, platform-specific parsers
+ // (like the ELF parser) register themselves as extensions.
+ // 2. The target-specific assembly parser. Some directives are target
+ // specific or may potentially behave differently on certain targets.
+ // 3. The generic directive parser implemented by this class. These are
+ // all the directives that behave in a target and platform independent
+ // manner, or at least have a default behavior that's shared between
+ // all targets and platforms.
+
+ getTargetParser().flushPendingInstructions(getStreamer());
+
+ // Special-case handling of structure-end directives at higher priority,
+ // since ENDS is overloaded as a segment-end directive.
+ if (IDVal.equals_lower("ends") && StructInProgress.size() > 1 &&
+ getTok().is(AsmToken::EndOfStatement)) {
+ return parseDirectiveNestedEnds();
+ }
+
+ // First, check the extension directive map to see if any extension has
+ // registered itself to parse this directive.
+ std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
+ ExtensionDirectiveMap.lookup(IDVal.lower());
+ if (Handler.first)
+ return (*Handler.second)(Handler.first, IDVal, IDLoc);
+
+ // Next, let the target-specific assembly parser try.
+ SMLoc StartTokLoc = getTok().getLoc();
+ bool TPDirectiveReturn =
+ ID.is(AsmToken::Identifier) && 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;
+
+ // Finally, if no one else is interested in this directive, it must be
+ // generic and familiar to this class.
+ switch (DirKind) {
+ default:
+ break;
+ case DK_ASCII:
+ return parseDirectiveAscii(IDVal, false);
+ case DK_ASCIZ:
+ case DK_STRING:
+ return parseDirectiveAscii(IDVal, true);
+ case DK_BYTE:
+ case DK_SBYTE:
+ case DK_DB:
+ return parseDirectiveValue(IDVal, 1);
+ case DK_WORD:
+ case DK_SWORD:
+ case DK_DW:
+ return parseDirectiveValue(IDVal, 2);
+ case DK_DWORD:
+ case DK_SDWORD:
+ case DK_DD:
+ return parseDirectiveValue(IDVal, 4);
+ case DK_FWORD:
case DK_DF:
- return parseDirectiveValue(IDVal, 6);
- case DK_QWORD:
- case DK_SQWORD:
- case DK_DQ:
- return parseDirectiveValue(IDVal, 8);
- case DK_REAL4:
+ return parseDirectiveValue(IDVal, 6);
+ case DK_QWORD:
+ case DK_SQWORD:
+ case DK_DQ:
+ return parseDirectiveValue(IDVal, 8);
+ case DK_REAL4:
return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
- case DK_REAL8:
+ case DK_REAL8:
return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
case DK_REAL10:
return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
- case DK_STRUCT:
- case DK_UNION:
- return parseDirectiveNestedStruct(IDVal, DirKind);
- case DK_ENDS:
- return parseDirectiveNestedEnds();
- case DK_ALIGN:
- return parseDirectiveAlign();
- case DK_ORG:
- return parseDirectiveOrg();
- case DK_EXTERN:
- eatToEndOfStatement(); // .extern is the default, ignore it.
- return false;
- case DK_PUBLIC:
- return parseDirectiveSymbolAttribute(MCSA_Global);
- case DK_COMM:
- return parseDirectiveComm(/*IsLocal=*/false);
- case DK_COMMENT:
- return parseDirectiveComment(IDLoc);
- case DK_INCLUDE:
- return parseDirectiveInclude();
+ case DK_STRUCT:
+ case DK_UNION:
+ return parseDirectiveNestedStruct(IDVal, DirKind);
+ case DK_ENDS:
+ return parseDirectiveNestedEnds();
+ case DK_ALIGN:
+ return parseDirectiveAlign();
+ case DK_ORG:
+ return parseDirectiveOrg();
+ case DK_EXTERN:
+ eatToEndOfStatement(); // .extern is the default, ignore it.
+ return false;
+ case DK_PUBLIC:
+ return parseDirectiveSymbolAttribute(MCSA_Global);
+ case DK_COMM:
+ return parseDirectiveComm(/*IsLocal=*/false);
+ case DK_COMMENT:
+ return parseDirectiveComment(IDLoc);
+ case DK_INCLUDE:
+ return parseDirectiveInclude();
case DK_REPEAT:
return parseDirectiveRepeat(IDLoc, IDVal);
case DK_WHILE:
@@ -2304,428 +2304,428 @@ bool MasmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectiveFor(IDLoc, IDVal);
case DK_FORC:
return parseDirectiveForc(IDLoc, IDVal);
- case DK_FILE:
- return parseDirectiveFile(IDLoc);
- case DK_LINE:
- return parseDirectiveLine();
- case DK_LOC:
- return parseDirectiveLoc();
- case DK_STABS:
- 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:
- return parseDirectiveCVLinetable();
- case DK_CV_INLINE_LINETABLE:
- return parseDirectiveCVInlineLinetable();
- case DK_CV_DEF_RANGE:
- return parseDirectiveCVDefRange();
- case DK_CV_STRING:
- return parseDirectiveCVString();
- case DK_CV_STRINGTABLE:
- return parseDirectiveCVStringTable();
- case DK_CV_FILECHECKSUMS:
- return parseDirectiveCVFileChecksums();
- case DK_CV_FILECHECKSUM_OFFSET:
- return parseDirectiveCVFileChecksumOffset();
- case DK_CV_FPO_DATA:
- return parseDirectiveCVFPOData();
- case DK_CFI_SECTIONS:
- return parseDirectiveCFISections();
- case DK_CFI_STARTPROC:
- return parseDirectiveCFIStartProc();
- case DK_CFI_ENDPROC:
- return parseDirectiveCFIEndProc();
- case DK_CFI_DEF_CFA:
- return parseDirectiveCFIDefCfa(IDLoc);
- case DK_CFI_DEF_CFA_OFFSET:
- return parseDirectiveCFIDefCfaOffset();
- case DK_CFI_ADJUST_CFA_OFFSET:
- return parseDirectiveCFIAdjustCfaOffset();
- case DK_CFI_DEF_CFA_REGISTER:
- return parseDirectiveCFIDefCfaRegister(IDLoc);
- case DK_CFI_OFFSET:
- return parseDirectiveCFIOffset(IDLoc);
- case DK_CFI_REL_OFFSET:
- return parseDirectiveCFIRelOffset(IDLoc);
- case DK_CFI_PERSONALITY:
- return parseDirectiveCFIPersonalityOrLsda(true);
- case DK_CFI_LSDA:
- return parseDirectiveCFIPersonalityOrLsda(false);
- case DK_CFI_REMEMBER_STATE:
- return parseDirectiveCFIRememberState();
- case DK_CFI_RESTORE_STATE:
- return parseDirectiveCFIRestoreState();
- case DK_CFI_SAME_VALUE:
- return parseDirectiveCFISameValue(IDLoc);
- case DK_CFI_RESTORE:
- return parseDirectiveCFIRestore(IDLoc);
- case DK_CFI_ESCAPE:
- return parseDirectiveCFIEscape();
- case DK_CFI_RETURN_COLUMN:
- return parseDirectiveCFIReturnColumn(IDLoc);
- case DK_CFI_SIGNAL_FRAME:
- return parseDirectiveCFISignalFrame();
- case DK_CFI_UNDEFINED:
- return parseDirectiveCFIUndefined(IDLoc);
- case DK_CFI_REGISTER:
- return parseDirectiveCFIRegister(IDLoc);
- case DK_CFI_WINDOW_SAVE:
- return parseDirectiveCFIWindowSave();
- case DK_EXITM:
+ case DK_FILE:
+ return parseDirectiveFile(IDLoc);
+ case DK_LINE:
+ return parseDirectiveLine();
+ case DK_LOC:
+ return parseDirectiveLoc();
+ case DK_STABS:
+ 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:
+ return parseDirectiveCVLinetable();
+ case DK_CV_INLINE_LINETABLE:
+ return parseDirectiveCVInlineLinetable();
+ case DK_CV_DEF_RANGE:
+ return parseDirectiveCVDefRange();
+ case DK_CV_STRING:
+ return parseDirectiveCVString();
+ case DK_CV_STRINGTABLE:
+ return parseDirectiveCVStringTable();
+ case DK_CV_FILECHECKSUMS:
+ return parseDirectiveCVFileChecksums();
+ case DK_CV_FILECHECKSUM_OFFSET:
+ return parseDirectiveCVFileChecksumOffset();
+ case DK_CV_FPO_DATA:
+ return parseDirectiveCVFPOData();
+ case DK_CFI_SECTIONS:
+ return parseDirectiveCFISections();
+ case DK_CFI_STARTPROC:
+ return parseDirectiveCFIStartProc();
+ case DK_CFI_ENDPROC:
+ return parseDirectiveCFIEndProc();
+ case DK_CFI_DEF_CFA:
+ return parseDirectiveCFIDefCfa(IDLoc);
+ case DK_CFI_DEF_CFA_OFFSET:
+ return parseDirectiveCFIDefCfaOffset();
+ case DK_CFI_ADJUST_CFA_OFFSET:
+ return parseDirectiveCFIAdjustCfaOffset();
+ case DK_CFI_DEF_CFA_REGISTER:
+ return parseDirectiveCFIDefCfaRegister(IDLoc);
+ case DK_CFI_OFFSET:
+ return parseDirectiveCFIOffset(IDLoc);
+ case DK_CFI_REL_OFFSET:
+ return parseDirectiveCFIRelOffset(IDLoc);
+ case DK_CFI_PERSONALITY:
+ return parseDirectiveCFIPersonalityOrLsda(true);
+ case DK_CFI_LSDA:
+ return parseDirectiveCFIPersonalityOrLsda(false);
+ case DK_CFI_REMEMBER_STATE:
+ return parseDirectiveCFIRememberState();
+ case DK_CFI_RESTORE_STATE:
+ return parseDirectiveCFIRestoreState();
+ case DK_CFI_SAME_VALUE:
+ return parseDirectiveCFISameValue(IDLoc);
+ case DK_CFI_RESTORE:
+ return parseDirectiveCFIRestore(IDLoc);
+ case DK_CFI_ESCAPE:
+ return parseDirectiveCFIEscape();
+ case DK_CFI_RETURN_COLUMN:
+ return parseDirectiveCFIReturnColumn(IDLoc);
+ case DK_CFI_SIGNAL_FRAME:
+ return parseDirectiveCFISignalFrame();
+ case DK_CFI_UNDEFINED:
+ return parseDirectiveCFIUndefined(IDLoc);
+ case DK_CFI_REGISTER:
+ return parseDirectiveCFIRegister(IDLoc);
+ case DK_CFI_WINDOW_SAVE:
+ return parseDirectiveCFIWindowSave();
+ case DK_EXITM:
Info.ExitValue = "";
return parseDirectiveExitMacro(IDLoc, IDVal, *Info.ExitValue);
- case DK_ENDM:
+ case DK_ENDM:
Info.ExitValue = "";
- return parseDirectiveEndMacro(IDVal);
+ return parseDirectiveEndMacro(IDVal);
case DK_PURGE:
- return parseDirectivePurgeMacro(IDLoc);
- case DK_END:
- return parseDirectiveEnd(IDLoc);
- case DK_ERR:
- return parseDirectiveError(IDLoc);
- case DK_ERRB:
- return parseDirectiveErrorIfb(IDLoc, true);
- case DK_ERRNB:
- return parseDirectiveErrorIfb(IDLoc, false);
- case DK_ERRDEF:
- return parseDirectiveErrorIfdef(IDLoc, true);
- case DK_ERRNDEF:
- return parseDirectiveErrorIfdef(IDLoc, false);
- case DK_ERRDIF:
- return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
- /*CaseInsensitive=*/false);
- case DK_ERRDIFI:
- return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
- /*CaseInsensitive=*/true);
- case DK_ERRIDN:
- return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
- /*CaseInsensitive=*/false);
- case DK_ERRIDNI:
- return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
- /*CaseInsensitive=*/true);
- case DK_ERRE:
- return parseDirectiveErrorIfe(IDLoc, true);
- case DK_ERRNZ:
- return parseDirectiveErrorIfe(IDLoc, false);
+ return parseDirectivePurgeMacro(IDLoc);
+ case DK_END:
+ return parseDirectiveEnd(IDLoc);
+ case DK_ERR:
+ return parseDirectiveError(IDLoc);
+ case DK_ERRB:
+ return parseDirectiveErrorIfb(IDLoc, true);
+ case DK_ERRNB:
+ return parseDirectiveErrorIfb(IDLoc, false);
+ case DK_ERRDEF:
+ return parseDirectiveErrorIfdef(IDLoc, true);
+ case DK_ERRNDEF:
+ return parseDirectiveErrorIfdef(IDLoc, false);
+ case DK_ERRDIF:
+ return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
+ /*CaseInsensitive=*/false);
+ case DK_ERRDIFI:
+ return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
+ /*CaseInsensitive=*/true);
+ case DK_ERRIDN:
+ return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
+ /*CaseInsensitive=*/false);
+ case DK_ERRIDNI:
+ return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
+ /*CaseInsensitive=*/true);
+ case DK_ERRE:
+ return parseDirectiveErrorIfe(IDLoc, true);
+ case DK_ERRNZ:
+ return parseDirectiveErrorIfe(IDLoc, false);
case DK_RADIX:
return parseDirectiveRadix(IDLoc);
- }
-
- return Error(IDLoc, "unknown directive");
- }
-
- // We also check if this is allocating memory with user-defined type.
- auto IDIt = Structs.find(IDVal.lower());
- if (IDIt != Structs.end())
- return parseDirectiveStructValue(/*Structure=*/IDIt->getValue(), IDVal,
- IDLoc);
-
- // Non-conditional Microsoft directives sometimes follow their first argument.
- const AsmToken nextTok = getTok();
- const StringRef nextVal = nextTok.getString();
- const SMLoc nextLoc = nextTok.getLoc();
-
- // There are several entities interested in parsing infix directives:
- //
- // 1. Asm parser extensions. For example, platform-specific parsers
- // (like the ELF parser) register themselves as extensions.
- // 2. The generic directive parser implemented by this class. These are
- // all the directives that behave in a target and platform independent
- // manner, or at least have a default behavior that's shared between
- // all targets and platforms.
-
- getTargetParser().flushPendingInstructions(getStreamer());
-
- // Special-case handling of structure-end directives at higher priority, since
- // ENDS is overloaded as a segment-end directive.
- if (nextVal.equals_lower("ends") && StructInProgress.size() == 1) {
- Lex();
- return parseDirectiveEnds(IDVal, IDLoc);
- }
-
- // First, check the extension directive map to see if any extension has
- // registered itself to parse this directive.
- std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
- ExtensionDirectiveMap.lookup(nextVal.lower());
- if (Handler.first) {
- Lex();
- Lexer.UnLex(ID);
- return (*Handler.second)(Handler.first, nextVal, nextLoc);
- }
-
- // If no one else is interested in this directive, it must be
- // generic and familiar to this class.
- DirKindIt = DirectiveKindMap.find(nextVal.lower());
- DirKind = (DirKindIt == DirectiveKindMap.end())
- ? DK_NO_DIRECTIVE
- : DirKindIt->getValue();
- switch (DirKind) {
- default:
- break;
- case DK_ASSIGN:
- case DK_EQU:
- case DK_TEXTEQU:
- Lex();
- return parseDirectiveEquate(nextVal, IDVal, DirKind);
- case DK_BYTE:
+ }
+
+ return Error(IDLoc, "unknown directive");
+ }
+
+ // We also check if this is allocating memory with user-defined type.
+ auto IDIt = Structs.find(IDVal.lower());
+ if (IDIt != Structs.end())
+ return parseDirectiveStructValue(/*Structure=*/IDIt->getValue(), IDVal,
+ IDLoc);
+
+ // Non-conditional Microsoft directives sometimes follow their first argument.
+ const AsmToken nextTok = getTok();
+ const StringRef nextVal = nextTok.getString();
+ const SMLoc nextLoc = nextTok.getLoc();
+
+ // There are several entities interested in parsing infix directives:
+ //
+ // 1. Asm parser extensions. For example, platform-specific parsers
+ // (like the ELF parser) register themselves as extensions.
+ // 2. The generic directive parser implemented by this class. These are
+ // all the directives that behave in a target and platform independent
+ // manner, or at least have a default behavior that's shared between
+ // all targets and platforms.
+
+ getTargetParser().flushPendingInstructions(getStreamer());
+
+ // Special-case handling of structure-end directives at higher priority, since
+ // ENDS is overloaded as a segment-end directive.
+ if (nextVal.equals_lower("ends") && StructInProgress.size() == 1) {
+ Lex();
+ return parseDirectiveEnds(IDVal, IDLoc);
+ }
+
+ // First, check the extension directive map to see if any extension has
+ // registered itself to parse this directive.
+ std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
+ ExtensionDirectiveMap.lookup(nextVal.lower());
+ if (Handler.first) {
+ Lex();
+ Lexer.UnLex(ID);
+ return (*Handler.second)(Handler.first, nextVal, nextLoc);
+ }
+
+ // If no one else is interested in this directive, it must be
+ // generic and familiar to this class.
+ DirKindIt = DirectiveKindMap.find(nextVal.lower());
+ DirKind = (DirKindIt == DirectiveKindMap.end())
+ ? DK_NO_DIRECTIVE
+ : DirKindIt->getValue();
+ switch (DirKind) {
+ default:
+ break;
+ case DK_ASSIGN:
+ case DK_EQU:
+ case DK_TEXTEQU:
+ Lex();
+ return parseDirectiveEquate(nextVal, IDVal, DirKind);
+ case DK_BYTE:
case DK_SBYTE:
- case DK_DB:
- Lex();
- return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
- case DK_WORD:
+ case DK_DB:
+ Lex();
+ return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
+ case DK_WORD:
case DK_SWORD:
- case DK_DW:
- Lex();
- return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
- case DK_DWORD:
+ case DK_DW:
+ Lex();
+ return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
+ case DK_DWORD:
case DK_SDWORD:
- case DK_DD:
- Lex();
- return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
- case DK_FWORD:
+ case DK_DD:
+ Lex();
+ return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
+ case DK_FWORD:
case DK_DF:
- Lex();
- return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
- case DK_QWORD:
+ Lex();
+ return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
+ case DK_QWORD:
case DK_SQWORD:
- case DK_DQ:
- Lex();
- return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
- case DK_REAL4:
- Lex();
+ case DK_DQ:
+ Lex();
+ return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
+ case DK_REAL4:
+ Lex();
return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
IDVal, IDLoc);
- case DK_REAL8:
- Lex();
+ case DK_REAL8:
+ Lex();
return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
IDVal, IDLoc);
case DK_REAL10:
Lex();
return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
10, IDVal, IDLoc);
- case DK_STRUCT:
- case DK_UNION:
- Lex();
- return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
- case DK_ENDS:
- Lex();
- return parseDirectiveEnds(IDVal, IDLoc);
+ case DK_STRUCT:
+ case DK_UNION:
+ Lex();
+ return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
+ case DK_ENDS:
+ Lex();
+ return parseDirectiveEnds(IDVal, IDLoc);
case DK_MACRO:
Lex();
return parseDirectiveMacro(IDVal, IDLoc);
- }
-
- // Finally, we check if this is allocating a variable with user-defined type.
- auto NextIt = Structs.find(nextVal.lower());
- if (NextIt != Structs.end()) {
- Lex();
- return parseDirectiveNamedStructValue(/*Structure=*/NextIt->getValue(),
- nextVal, nextLoc, IDVal);
- }
-
- // __asm _emit or __asm __emit
- if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
- IDVal == "_EMIT" || IDVal == "__EMIT"))
- return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
-
- // __asm align
- if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
- return parseDirectiveMSAlign(IDLoc, Info);
-
- if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
- Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
- if (checkForValidSection())
- return true;
-
- // Canonicalize the opcode to lower case.
- std::string OpcodeStr = IDVal.lower();
- ParseInstructionInfo IInfo(Info.AsmRewrites);
- bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
- Info.ParsedOperands);
- Info.ParseError = ParseHadError;
-
- // Dump the parsed representation, if requested.
- if (getShowParsedOperands()) {
- SmallString<256> Str;
- raw_svector_ostream OS(Str);
- OS << "parsed instruction: [";
- for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
- if (i != 0)
- OS << ", ";
- Info.ParsedOperands[i]->print(OS);
- }
- OS << "]";
-
- 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 (!ParseHadError && enabledGenDwarfForAssembly() &&
- getContext().getGenDwarfSectionSyms().count(
- getStreamer().getCurrentSectionOnly())) {
- unsigned Line;
- if (ActiveMacros.empty())
- Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
- else
- Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
- ActiveMacros.front()->ExitBuffer);
-
- // If we previously parsed a cpp hash file line comment then make sure the
- // current Dwarf File is for the CppHashFilename if not then emit the
- // Dwarf File table for it and adjust the line number for the .loc.
- if (!CppHashInfo.Filename.empty()) {
- unsigned FileNumber = getStreamer().emitDwarfFileDirective(
- 0, StringRef(), CppHashInfo.Filename);
- getContext().setGenDwarfFileNumber(FileNumber);
-
- unsigned CppHashLocLineNo =
- SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
- Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
- }
-
- getStreamer().emitDwarfLocDirective(
- getContext().getGenDwarfFileNumber(), Line, 0,
- DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
- StringRef());
- }
-
- // If parsing succeeded, match the instruction.
- if (!ParseHadError) {
- uint64_t ErrorInfo;
- if (getTargetParser().MatchAndEmitInstruction(
- IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
- getTargetParser().isParsingMSInlineAsm()))
- return true;
- }
- return false;
-}
-
-// Parse and erase curly braces marking block start/end.
-bool MasmParser::parseCurlyBlockScope(
- SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
- // Identify curly brace marking block start/end.
- if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
- return false;
-
- SMLoc StartLoc = Lexer.getLoc();
- Lex(); // Eat the brace.
- if (Lexer.is(AsmToken::EndOfStatement))
- Lex(); // Eat EndOfStatement following the brace.
-
- // Erase the block start/end brace from the output asm string.
- AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
- StartLoc.getPointer());
- return true;
-}
-
-/// parseCppHashLineFilenameComment as this:
-/// ::= # number "filename"
-bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
- Lex(); // Eat the hash token.
- // Lexer only ever emits HashDirective if it fully formed if it's
- // done the checking already so this is an internal error.
- assert(getTok().is(AsmToken::Integer) &&
- "Lexing Cpp line comment: Expected Integer");
- int64_t LineNumber = getTok().getIntVal();
- Lex();
- assert(getTok().is(AsmToken::String) &&
- "Lexing Cpp line comment: Expected String");
- StringRef Filename = getTok().getString();
- Lex();
-
- // Get rid of the enclosing quotes.
- Filename = Filename.substr(1, Filename.size() - 2);
-
- // Save the SMLoc, Filename and LineNumber for later use by diagnostics
- // and possibly DWARF file info.
- CppHashInfo.Loc = L;
- CppHashInfo.Filename = Filename;
- CppHashInfo.LineNumber = LineNumber;
- CppHashInfo.Buf = CurBuffer;
- if (FirstCppHashFilename.empty())
- FirstCppHashFilename = Filename;
- return false;
-}
-
-/// will use the last parsed cpp hash line filename comment
-/// for the Filename and LineNo if any in the diagnostic.
-void MasmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
- const MasmParser *Parser = static_cast<const MasmParser *>(Context);
- raw_ostream &OS = errs();
-
- const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
- SMLoc DiagLoc = Diag.getLoc();
- unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
- unsigned CppHashBuf =
- Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
-
- // Like SourceMgr::printMessage() we need to print the include stack if any
- // before printing the message.
- unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
- if (!Parser->SavedDiagHandler && DiagCurBuffer &&
- DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
- SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
- DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
- }
-
- // If we have not parsed a cpp hash line filename comment or the source
- // manager changed or buffer changed (like in a nested include) then just
- // print the normal diagnostic using its Filename and LineNo.
- if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
- DiagBuf != CppHashBuf) {
- if (Parser->SavedDiagHandler)
- Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
- else
- Diag.print(nullptr, OS);
- return;
- }
-
- // Use the CppHashFilename and calculate a line number based on the
- // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
- // for the diagnostic.
- const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
-
- int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
- int CppHashLocLineNo =
- Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
- int LineNo =
- Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
-
- SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
- Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
- Diag.getLineContents(), Diag.getRanges());
-
- if (Parser->SavedDiagHandler)
- Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
- else
- NewDiag.print(nullptr, OS);
-}
-
+ }
+
+ // Finally, we check if this is allocating a variable with user-defined type.
+ auto NextIt = Structs.find(nextVal.lower());
+ if (NextIt != Structs.end()) {
+ Lex();
+ return parseDirectiveNamedStructValue(/*Structure=*/NextIt->getValue(),
+ nextVal, nextLoc, IDVal);
+ }
+
+ // __asm _emit or __asm __emit
+ if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
+ IDVal == "_EMIT" || IDVal == "__EMIT"))
+ return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
+
+ // __asm align
+ if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
+ return parseDirectiveMSAlign(IDLoc, Info);
+
+ if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
+ Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
+ if (checkForValidSection())
+ return true;
+
+ // Canonicalize the opcode to lower case.
+ std::string OpcodeStr = IDVal.lower();
+ ParseInstructionInfo IInfo(Info.AsmRewrites);
+ bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
+ Info.ParsedOperands);
+ Info.ParseError = ParseHadError;
+
+ // Dump the parsed representation, if requested.
+ if (getShowParsedOperands()) {
+ SmallString<256> Str;
+ raw_svector_ostream OS(Str);
+ OS << "parsed instruction: [";
+ for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
+ if (i != 0)
+ OS << ", ";
+ Info.ParsedOperands[i]->print(OS);
+ }
+ OS << "]";
+
+ 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 (!ParseHadError && enabledGenDwarfForAssembly() &&
+ getContext().getGenDwarfSectionSyms().count(
+ getStreamer().getCurrentSectionOnly())) {
+ unsigned Line;
+ if (ActiveMacros.empty())
+ Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
+ else
+ Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
+ ActiveMacros.front()->ExitBuffer);
+
+ // If we previously parsed a cpp hash file line comment then make sure the
+ // current Dwarf File is for the CppHashFilename if not then emit the
+ // Dwarf File table for it and adjust the line number for the .loc.
+ if (!CppHashInfo.Filename.empty()) {
+ unsigned FileNumber = getStreamer().emitDwarfFileDirective(
+ 0, StringRef(), CppHashInfo.Filename);
+ getContext().setGenDwarfFileNumber(FileNumber);
+
+ unsigned CppHashLocLineNo =
+ SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
+ Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
+ }
+
+ getStreamer().emitDwarfLocDirective(
+ getContext().getGenDwarfFileNumber(), Line, 0,
+ DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
+ StringRef());
+ }
+
+ // If parsing succeeded, match the instruction.
+ if (!ParseHadError) {
+ uint64_t ErrorInfo;
+ if (getTargetParser().MatchAndEmitInstruction(
+ IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
+ getTargetParser().isParsingMSInlineAsm()))
+ return true;
+ }
+ return false;
+}
+
+// Parse and erase curly braces marking block start/end.
+bool MasmParser::parseCurlyBlockScope(
+ SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
+ // Identify curly brace marking block start/end.
+ if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
+ return false;
+
+ SMLoc StartLoc = Lexer.getLoc();
+ Lex(); // Eat the brace.
+ if (Lexer.is(AsmToken::EndOfStatement))
+ Lex(); // Eat EndOfStatement following the brace.
+
+ // Erase the block start/end brace from the output asm string.
+ AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
+ StartLoc.getPointer());
+ return true;
+}
+
+/// parseCppHashLineFilenameComment as this:
+/// ::= # number "filename"
+bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
+ Lex(); // Eat the hash token.
+ // Lexer only ever emits HashDirective if it fully formed if it's
+ // done the checking already so this is an internal error.
+ assert(getTok().is(AsmToken::Integer) &&
+ "Lexing Cpp line comment: Expected Integer");
+ int64_t LineNumber = getTok().getIntVal();
+ Lex();
+ assert(getTok().is(AsmToken::String) &&
+ "Lexing Cpp line comment: Expected String");
+ StringRef Filename = getTok().getString();
+ Lex();
+
+ // Get rid of the enclosing quotes.
+ Filename = Filename.substr(1, Filename.size() - 2);
+
+ // Save the SMLoc, Filename and LineNumber for later use by diagnostics
+ // and possibly DWARF file info.
+ CppHashInfo.Loc = L;
+ CppHashInfo.Filename = Filename;
+ CppHashInfo.LineNumber = LineNumber;
+ CppHashInfo.Buf = CurBuffer;
+ if (FirstCppHashFilename.empty())
+ FirstCppHashFilename = Filename;
+ return false;
+}
+
+/// will use the last parsed cpp hash line filename comment
+/// for the Filename and LineNo if any in the diagnostic.
+void MasmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
+ const MasmParser *Parser = static_cast<const MasmParser *>(Context);
+ raw_ostream &OS = errs();
+
+ const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
+ SMLoc DiagLoc = Diag.getLoc();
+ unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
+ unsigned CppHashBuf =
+ Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
+
+ // Like SourceMgr::printMessage() we need to print the include stack if any
+ // before printing the message.
+ unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
+ if (!Parser->SavedDiagHandler && DiagCurBuffer &&
+ DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
+ SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
+ DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
+ }
+
+ // If we have not parsed a cpp hash line filename comment or the source
+ // manager changed or buffer changed (like in a nested include) then just
+ // print the normal diagnostic using its Filename and LineNo.
+ if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
+ DiagBuf != CppHashBuf) {
+ if (Parser->SavedDiagHandler)
+ Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
+ else
+ Diag.print(nullptr, OS);
+ return;
+ }
+
+ // Use the CppHashFilename and calculate a line number based on the
+ // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
+ // for the diagnostic.
+ const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
+
+ int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
+ int CppHashLocLineNo =
+ Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
+ int LineNo =
+ Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
+
+ SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
+ Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
+ Diag.getLineContents(), Diag.getRanges());
+
+ if (Parser->SavedDiagHandler)
+ Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
+ else
+ NewDiag.print(nullptr, OS);
+}
+
// This is similar to the IsIdentifierChar function in AsmLexer.cpp, but does
// not accept '.'.
static bool isMacroParameterChar(char C) {
return isAlnum(C) || C == '_' || C == '$' || C == '@' || C == '?';
-}
-
-bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
- ArrayRef<MCAsmMacroParameter> Parameters,
- ArrayRef<MCAsmMacroArgument> A,
+}
+
+bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
+ ArrayRef<MCAsmMacroParameter> Parameters,
+ ArrayRef<MCAsmMacroArgument> A,
const std::vector<std::string> &Locals, SMLoc L) {
- unsigned NParameters = Parameters.size();
+ unsigned NParameters = Parameters.size();
if (NParameters != A.size())
- return Error(L, "Wrong number of arguments");
+ return Error(L, "Wrong number of arguments");
StringMap<std::string> LocalSymbols;
std::string Name;
Name.reserve(6);
@@ -2736,25 +2736,25 @@ bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
LocalSymbols.insert({Local, LocalName.str()});
Name.clear();
}
-
+
Optional<char> CurrentQuote;
- while (!Body.empty()) {
- // Scan for the next substitution.
- std::size_t End = Body.size(), Pos = 0;
+ while (!Body.empty()) {
+ // Scan for the next substitution.
+ std::size_t End = Body.size(), Pos = 0;
std::size_t IdentifierPos = End;
- for (; Pos != End; ++Pos) {
+ for (; Pos != End; ++Pos) {
// Find the next possible macro parameter, including preceding a '&'
// inside quotes.
if (Body[Pos] == '&')
break;
if (isMacroParameterChar(Body[Pos])) {
if (!CurrentQuote.hasValue())
- break;
+ break;
if (IdentifierPos == End)
IdentifierPos = Pos;
- } else {
+ } else {
IdentifierPos = End;
- }
+ }
// Track quotation status
if (!CurrentQuote.hasValue()) {
@@ -2769,21 +2769,21 @@ bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
CurrentQuote.reset();
}
}
- }
+ }
if (IdentifierPos != End) {
// We've recognized an identifier before an apostrophe inside quotes;
// check once to see if we can expand it.
Pos = IdentifierPos;
IdentifierPos = End;
}
-
- // Add the prefix.
- OS << Body.slice(0, Pos);
-
- // Check if we reached the end.
- if (Pos == End)
- break;
-
+
+ // Add the prefix.
+ OS << Body.slice(0, Pos);
+
+ // Check if we reached the end.
+ if (Pos == End)
+ break;
+
unsigned I = Pos;
bool InitialAmpersand = (Body[I] == '&');
if (InitialAmpersand) {
@@ -2792,15 +2792,15 @@ bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
}
while (I < End && isMacroParameterChar(Body[I]))
++I;
-
+
const char *Begin = Body.data() + Pos;
StringRef Argument(Begin, I - Pos);
unsigned Index = 0;
for (; Index < NParameters; ++Index)
if (Parameters[Index].Name == Argument)
- break;
-
+ break;
+
if (Index == NParameters) {
if (InitialAmpersand)
OS << '&';
@@ -2823,69 +2823,69 @@ bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
// Emit an integer value to the buffer.
OS << Token.getIntVal();
else
- OS << Token.getString();
- }
-
+ OS << Token.getString();
+ }
+
Pos += Argument.size();
if (Pos < End && Body[Pos] == '&') {
++Pos;
- }
- }
- // Update the scan point.
- Body = Body.substr(Pos);
- }
-
- return false;
-}
-
-static bool isOperator(AsmToken::TokenKind kind) {
- switch (kind) {
- default:
- return false;
- case AsmToken::Plus:
- case AsmToken::Minus:
- case AsmToken::Tilde:
- case AsmToken::Slash:
- case AsmToken::Star:
- case AsmToken::Dot:
- case AsmToken::Equal:
- case AsmToken::EqualEqual:
- case AsmToken::Pipe:
- case AsmToken::PipePipe:
- case AsmToken::Caret:
- case AsmToken::Amp:
- case AsmToken::AmpAmp:
- case AsmToken::Exclaim:
- case AsmToken::ExclaimEqual:
- case AsmToken::Less:
- case AsmToken::LessEqual:
- case AsmToken::LessLess:
- case AsmToken::LessGreater:
- case AsmToken::Greater:
- case AsmToken::GreaterEqual:
- case AsmToken::GreaterGreater:
- return true;
- }
-}
-
-namespace {
-
-class AsmLexerSkipSpaceRAII {
-public:
- AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
- Lexer.setSkipSpace(SkipSpace);
- }
-
- ~AsmLexerSkipSpaceRAII() {
- Lexer.setSkipSpace(true);
- }
-
-private:
- AsmLexer &Lexer;
-};
-
-} // end anonymous namespace
-
+ }
+ }
+ // Update the scan point.
+ Body = Body.substr(Pos);
+ }
+
+ return false;
+}
+
+static bool isOperator(AsmToken::TokenKind kind) {
+ switch (kind) {
+ default:
+ return false;
+ case AsmToken::Plus:
+ case AsmToken::Minus:
+ case AsmToken::Tilde:
+ case AsmToken::Slash:
+ case AsmToken::Star:
+ case AsmToken::Dot:
+ case AsmToken::Equal:
+ case AsmToken::EqualEqual:
+ case AsmToken::Pipe:
+ case AsmToken::PipePipe:
+ case AsmToken::Caret:
+ case AsmToken::Amp:
+ case AsmToken::AmpAmp:
+ case AsmToken::Exclaim:
+ case AsmToken::ExclaimEqual:
+ case AsmToken::Less:
+ case AsmToken::LessEqual:
+ case AsmToken::LessLess:
+ case AsmToken::LessGreater:
+ case AsmToken::Greater:
+ case AsmToken::GreaterEqual:
+ case AsmToken::GreaterGreater:
+ return true;
+ }
+}
+
+namespace {
+
+class AsmLexerSkipSpaceRAII {
+public:
+ AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
+ Lexer.setSkipSpace(SkipSpace);
+ }
+
+ ~AsmLexerSkipSpaceRAII() {
+ Lexer.setSkipSpace(true);
+ }
+
+private:
+ AsmLexer &Lexer;
+};
+
+} // end anonymous namespace
+
bool MasmParser::parseMacroArgument(const MCAsmMacroParameter *MP,
MCAsmMacroArgument &MA,
AsmToken::TokenKind EndTok) {
@@ -2895,10 +2895,10 @@ bool MasmParser::parseMacroArgument(const MCAsmMacroParameter *MP,
for (StringRef S : Str) {
MA.emplace_back(AsmToken::String, S);
}
- }
- return false;
- }
-
+ }
+ return false;
+ }
+
SMLoc StrLoc = Lexer.getLoc(), EndLoc;
if (Lexer.is(AsmToken::Less) && isAngleBracketString(StrLoc, EndLoc)) {
const char *StrChar = StrLoc.getPointer() + 1;
@@ -2910,63 +2910,63 @@ bool MasmParser::parseMacroArgument(const MCAsmMacroParameter *MP,
return false;
}
- unsigned ParenLevel = 0;
-
- // Darwin doesn't use spaces to delmit arguments.
- AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
-
- bool SpaceEaten;
-
- while (true) {
- SpaceEaten = false;
- if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
+ unsigned ParenLevel = 0;
+
+ // Darwin doesn't use spaces to delmit arguments.
+ AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
+
+ bool SpaceEaten;
+
+ while (true) {
+ SpaceEaten = false;
+ if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
return TokError("unexpected token");
-
- if (ParenLevel == 0) {
- if (Lexer.is(AsmToken::Comma))
- break;
-
- if (Lexer.is(AsmToken::Space)) {
- SpaceEaten = true;
+
+ if (ParenLevel == 0) {
+ if (Lexer.is(AsmToken::Comma))
+ break;
+
+ if (Lexer.is(AsmToken::Space)) {
+ SpaceEaten = true;
Lex(); // Eat spaces.
- }
-
- // Spaces can delimit parameters, but could also be part an expression.
- // If the token after a space is an operator, add the token and the next
- // one into this argument
- if (!IsDarwin) {
+ }
+
+ // Spaces can delimit parameters, but could also be part an expression.
+ // If the token after a space is an operator, add the token and the next
+ // one into this argument
+ if (!IsDarwin) {
if (isOperator(Lexer.getKind()) && Lexer.isNot(EndTok)) {
- MA.push_back(getTok());
+ MA.push_back(getTok());
Lex();
-
- // Whitespace after an operator can be ignored.
- if (Lexer.is(AsmToken::Space))
+
+ // Whitespace after an operator can be ignored.
+ if (Lexer.is(AsmToken::Space))
Lex();
-
- continue;
- }
- }
- if (SpaceEaten)
- break;
- }
-
- // handleMacroEntry relies on not advancing the lexer here
- // to be able to fill in the remaining default parameter values
+
+ continue;
+ }
+ }
+ if (SpaceEaten)
+ break;
+ }
+
+ // handleMacroEntry relies on not advancing the lexer here
+ // to be able to fill in the remaining default parameter values
if (Lexer.is(EndTok) && (EndTok != AsmToken::RParen || ParenLevel == 0))
- break;
-
- // Adjust the current parentheses level.
- if (Lexer.is(AsmToken::LParen))
- ++ParenLevel;
- else if (Lexer.is(AsmToken::RParen) && ParenLevel)
- --ParenLevel;
-
- // Append the token to the current argument list.
- MA.push_back(getTok());
+ break;
+
+ // Adjust the current parentheses level.
+ if (Lexer.is(AsmToken::LParen))
+ ++ParenLevel;
+ else if (Lexer.is(AsmToken::RParen) && ParenLevel)
+ --ParenLevel;
+
+ // Append the token to the current argument list.
+ MA.push_back(getTok());
Lex();
- }
-
- if (ParenLevel != 0)
+ }
+
+ if (ParenLevel != 0)
return TokError("unbalanced parentheses in argument");
if (MA.empty() && MP) {
@@ -2977,43 +2977,43 @@ bool MasmParser::parseMacroArgument(const MCAsmMacroParameter *MP,
MA = MP->Value;
}
}
- return false;
-}
-
-// Parse the macro instantiation arguments.
-bool MasmParser::parseMacroArguments(const MCAsmMacro *M,
+ return false;
+}
+
+// Parse the macro instantiation arguments.
+bool MasmParser::parseMacroArguments(const MCAsmMacro *M,
MCAsmMacroArguments &A,
AsmToken::TokenKind EndTok) {
- const unsigned NParameters = M ? M->Parameters.size() : 0;
- bool NamedParametersFound = false;
- SmallVector<SMLoc, 4> FALocs;
-
- A.resize(NParameters);
- FALocs.resize(NParameters);
-
- // Parse two kinds of macro invocations:
- // - macros defined without any parameters accept an arbitrary number of them
- // - macros defined with parameters accept at most that many of them
- for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
- ++Parameter) {
- SMLoc IDLoc = Lexer.getLoc();
- MCAsmMacroParameter FA;
-
- if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
- 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");
-
- Lex();
-
- NamedParametersFound = true;
- }
-
- if (NamedParametersFound && FA.Name.empty())
- return Error(IDLoc, "cannot mix positional and keyword arguments");
-
+ const unsigned NParameters = M ? M->Parameters.size() : 0;
+ bool NamedParametersFound = false;
+ SmallVector<SMLoc, 4> FALocs;
+
+ A.resize(NParameters);
+ FALocs.resize(NParameters);
+
+ // Parse two kinds of macro invocations:
+ // - macros defined without any parameters accept an arbitrary number of them
+ // - macros defined with parameters accept at most that many of them
+ for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
+ ++Parameter) {
+ SMLoc IDLoc = Lexer.getLoc();
+ MCAsmMacroParameter FA;
+
+ if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
+ 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");
+
+ Lex();
+
+ NamedParametersFound = true;
+ }
+
+ if (NamedParametersFound && FA.Name.empty())
+ return Error(IDLoc, "cannot mix positional and keyword arguments");
+
unsigned PI = Parameter;
if (!FA.Name.empty()) {
assert(M && "expected macro to be defined");
@@ -3032,133 +3032,133 @@ bool MasmParser::parseMacroArguments(const MCAsmMacro *M,
if (M && PI < NParameters)
MP = &M->Parameters[PI];
- SMLoc StrLoc = Lexer.getLoc();
- SMLoc EndLoc;
+ SMLoc StrLoc = Lexer.getLoc();
+ SMLoc EndLoc;
if (Lexer.is(AsmToken::Percent)) {
- const MCExpr *AbsoluteExp;
- int64_t Value;
- /// Eat '%'.
- Lex();
- if (parseExpression(AbsoluteExp, EndLoc))
- return false;
- if (!AbsoluteExp->evaluateAsAbsolute(Value,
- getStreamer().getAssemblerPtr()))
- return Error(StrLoc, "expected absolute expression");
- const char *StrChar = StrLoc.getPointer();
- const char *EndChar = EndLoc.getPointer();
- AsmToken newToken(AsmToken::Integer,
- StringRef(StrChar, EndChar - StrChar), Value);
- FA.Value.push_back(newToken);
+ const MCExpr *AbsoluteExp;
+ int64_t Value;
+ /// Eat '%'.
+ Lex();
+ if (parseExpression(AbsoluteExp, EndLoc))
+ return false;
+ if (!AbsoluteExp->evaluateAsAbsolute(Value,
+ getStreamer().getAssemblerPtr()))
+ return Error(StrLoc, "expected absolute expression");
+ const char *StrChar = StrLoc.getPointer();
+ const char *EndChar = EndLoc.getPointer();
+ AsmToken newToken(AsmToken::Integer,
+ StringRef(StrChar, EndChar - StrChar), Value);
+ FA.Value.push_back(newToken);
} else if (parseMacroArgument(MP, FA.Value, EndTok)) {
if (M)
return addErrorSuffix(" in '" + M->Name + "' macro");
else
return true;
- }
-
- if (!FA.Value.empty()) {
- if (A.size() <= PI)
- A.resize(PI + 1);
- A[PI] = FA.Value;
-
- if (FALocs.size() <= PI)
- FALocs.resize(PI + 1);
-
- FALocs[PI] = Lexer.getLoc();
- }
-
- // At the end of the statement, fill in remaining arguments that have
- // default values. If there aren't any, then the next argument is
- // required but missing
+ }
+
+ if (!FA.Value.empty()) {
+ if (A.size() <= PI)
+ A.resize(PI + 1);
+ A[PI] = FA.Value;
+
+ if (FALocs.size() <= PI)
+ FALocs.resize(PI + 1);
+
+ FALocs[PI] = Lexer.getLoc();
+ }
+
+ // At the end of the statement, fill in remaining arguments that have
+ // default values. If there aren't any, then the next argument is
+ // required but missing
if (Lexer.is(EndTok)) {
- bool Failure = false;
- for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
- if (A[FAI].empty()) {
- if (M->Parameters[FAI].Required) {
- Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
- "missing value for required parameter "
+ bool Failure = false;
+ for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
+ if (A[FAI].empty()) {
+ if (M->Parameters[FAI].Required) {
+ Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
+ "missing value for required parameter "
"'" +
M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
- Failure = true;
- }
-
- if (!M->Parameters[FAI].Value.empty())
- A[FAI] = M->Parameters[FAI].Value;
- }
- }
- return Failure;
- }
-
- if (Lexer.is(AsmToken::Comma))
- Lex();
- }
-
- return TokError("too many positional arguments");
-}
-
+ Failure = true;
+ }
+
+ if (!M->Parameters[FAI].Value.empty())
+ A[FAI] = M->Parameters[FAI].Value;
+ }
+ }
+ return Failure;
+ }
+
+ if (Lexer.is(AsmToken::Comma))
+ Lex();
+ }
+
+ return TokError("too many positional arguments");
+}
+
bool MasmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc,
AsmToken::TokenKind ArgumentEndTok) {
- // 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;
+ // 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, ArgumentEndTok))
- return true;
-
- // Macro instantiation is lexical, unfortunately. We construct a new buffer
- // to hold the macro body with substitutions.
- SmallString<256> Buf;
- StringRef Body = M->Body;
- raw_svector_ostream OS(Buf);
-
+ return true;
+
+ // Macro instantiation is lexical, unfortunately. We construct a new buffer
+ // to hold the macro body with substitutions.
+ SmallString<256> Buf;
+ StringRef Body = M->Body;
+ raw_svector_ostream OS(Buf);
+
if (expandMacro(OS, Body, M->Parameters, A, M->Locals, getTok().getLoc()))
- return true;
-
+ return true;
+
// We include the endm in the buffer as our cue to exit the macro
- // instantiation.
+ // instantiation.
OS << "endm\n";
-
- std::unique_ptr<MemoryBuffer> Instantiation =
- MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
-
- // Create the macro instantiation object and add to the current macro
- // instantiation stack.
- MacroInstantiation *MI = new MacroInstantiation{
- NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
- ActiveMacros.push_back(MI);
-
- ++NumOfMacroInstantiations;
-
- // Jump to the macro instantiation and prime the lexer.
- CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
+
+ std::unique_ptr<MemoryBuffer> Instantiation =
+ MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
+
+ // Create the macro instantiation object and add to the current macro
+ // instantiation stack.
+ MacroInstantiation *MI = new MacroInstantiation{
+ NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
+ ActiveMacros.push_back(MI);
+
+ ++NumOfMacroInstantiations;
+
+ // Jump to the macro instantiation and prime the lexer.
+ CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
EndStatementAtEOFStack.push_back(true);
- Lex();
-
- return false;
-}
-
-void MasmParser::handleMacroExit() {
+ Lex();
+
+ return false;
+}
+
+void MasmParser::handleMacroExit() {
// Jump to the token we should return to, and consume it.
EndStatementAtEOFStack.pop_back();
jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
EndStatementAtEOFStack.back());
- Lex();
-
- // Pop the instantiation entry.
- delete ActiveMacros.back();
- ActiveMacros.pop_back();
-}
-
+ Lex();
+
+ // Pop the instantiation entry.
+ delete ActiveMacros.back();
+ ActiveMacros.pop_back();
+}
+
bool MasmParser::handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc) {
if (!M->IsFunction)
return Error(NameLoc, "cannot invoke macro procedure as function");
@@ -3216,115 +3216,115 @@ bool MasmParser::handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc) {
return false;
}
-/// parseIdentifier:
-/// ::= identifier
-/// ::= string
-bool MasmParser::parseIdentifier(StringRef &Res) {
- // The assembler has relaxed rules for accepting identifiers, in particular we
- // allow things like '.globl $foo' and '.def @feat.00', which would normally
- // be separate tokens. At this level, we have already lexed so we cannot
- // (currently) handle this as a context dependent token, instead we detect
- // adjacent tokens and return the combined identifier.
- if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
- SMLoc PrefixLoc = getLexer().getLoc();
-
- // Consume the prefix character, and check for a following 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 != 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);
- Lex(); // Parser Lex to maintain invariants.
- return false;
- }
-
- if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
- return true;
-
- Res = getTok().getIdentifier();
-
- Lex(); // Consume the identifier token.
-
- return false;
-}
-
-/// parseDirectiveEquate:
-/// ::= name "=" expression
-/// | name "equ" expression (not redefinable)
-/// | name "equ" text-list
-/// | name "textequ" text-list
-bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
- DirectiveKind DirKind) {
- Variable &Var = Variables[Name];
- if (Var.Name.empty()) {
- Var.Name = Name;
- } else if (!Var.Redefinable) {
- return TokError("invalid variable redefinition");
- }
- Var.Redefinable = (DirKind != DK_EQU);
-
- if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
- // "equ" and "textequ" both allow text expressions.
- std::string Value;
- if (!parseTextItem(Value)) {
- Var.IsText = true;
- Var.TextValue = Value;
-
- // Accept a text-list, not just one text-item.
- auto parseItem = [&]() -> bool {
- if (parseTextItem(Value))
+/// parseIdentifier:
+/// ::= identifier
+/// ::= string
+bool MasmParser::parseIdentifier(StringRef &Res) {
+ // The assembler has relaxed rules for accepting identifiers, in particular we
+ // allow things like '.globl $foo' and '.def @feat.00', which would normally
+ // be separate tokens. At this level, we have already lexed so we cannot
+ // (currently) handle this as a context dependent token, instead we detect
+ // adjacent tokens and return the combined identifier.
+ if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
+ SMLoc PrefixLoc = getLexer().getLoc();
+
+ // Consume the prefix character, and check for a following 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 != 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);
+ Lex(); // Parser Lex to maintain invariants.
+ return false;
+ }
+
+ if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
+ return true;
+
+ Res = getTok().getIdentifier();
+
+ Lex(); // Consume the identifier token.
+
+ return false;
+}
+
+/// parseDirectiveEquate:
+/// ::= name "=" expression
+/// | name "equ" expression (not redefinable)
+/// | name "equ" text-list
+/// | name "textequ" text-list
+bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
+ DirectiveKind DirKind) {
+ Variable &Var = Variables[Name];
+ if (Var.Name.empty()) {
+ Var.Name = Name;
+ } else if (!Var.Redefinable) {
+ return TokError("invalid variable redefinition");
+ }
+ Var.Redefinable = (DirKind != DK_EQU);
+
+ if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
+ // "equ" and "textequ" both allow text expressions.
+ std::string Value;
+ if (!parseTextItem(Value)) {
+ Var.IsText = true;
+ Var.TextValue = Value;
+
+ // Accept a text-list, not just one text-item.
+ auto parseItem = [&]() -> bool {
+ if (parseTextItem(Value))
return TokError("expected text item");
- Var.TextValue += Value;
- return false;
- };
- if (parseOptionalToken(AsmToken::Comma) && parseMany(parseItem))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
-
- return false;
- }
- }
- if (DirKind == DK_TEXTEQU)
- return TokError("expected <text> in '" + Twine(IDVal) + "' directive");
-
- // Parse as expression assignment.
- const MCExpr *Expr;
- SMLoc EndLoc, StartLoc = Lexer.getLoc();
- if (parseExpression(Expr, EndLoc))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ Var.TextValue += Value;
+ return false;
+ };
+ if (parseOptionalToken(AsmToken::Comma) && parseMany(parseItem))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+
+ return false;
+ }
+ }
+ if (DirKind == DK_TEXTEQU)
+ return TokError("expected <text> in '" + Twine(IDVal) + "' directive");
+
+ // Parse as expression assignment.
+ const MCExpr *Expr;
+ SMLoc EndLoc, StartLoc = Lexer.getLoc();
+ if (parseExpression(Expr, EndLoc))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
MCSymbol *Sym = getContext().getOrCreateSymbol(Var.Name);
Sym->setRedefinable(Var.Redefinable);
Sym->setVariableValue(Expr);
Sym->setExternal(false);
- if (Expr->evaluateAsAbsolute(Var.NumericValue,
- getStreamer().getAssemblerPtr()))
- return false;
-
- // Not an absolute expression; define as a text replacement.
- Var.IsText = true;
- Var.TextValue = StringRef(StartLoc.getPointer(),
- EndLoc.getPointer() - StartLoc.getPointer()).str();
- return false;
-}
-
-bool MasmParser::parseEscapedString(std::string &Data) {
- if (check(getTok().isNot(AsmToken::String), "expected string"))
- return true;
-
- Data = "";
+ if (Expr->evaluateAsAbsolute(Var.NumericValue,
+ getStreamer().getAssemblerPtr()))
+ return false;
+
+ // Not an absolute expression; define as a text replacement.
+ Var.IsText = true;
+ Var.TextValue = StringRef(StartLoc.getPointer(),
+ EndLoc.getPointer() - StartLoc.getPointer()).str();
+ return false;
+}
+
+bool MasmParser::parseEscapedString(std::string &Data) {
+ if (check(getTok().isNot(AsmToken::String), "expected string"))
+ return true;
+
+ Data = "";
char Quote = getTok().getString().front();
- StringRef Str = getTok().getStringContents();
+ StringRef Str = getTok().getStringContents();
Data.reserve(Str.size());
for (size_t i = 0, e = Str.size(); i != e; ++i) {
Data.push_back(Str[i]);
@@ -3335,31 +3335,31 @@ bool MasmParser::parseEscapedString(std::string &Data) {
if (i + 1 == Str.size())
return Error(getTok().getLoc(), "missing quotation mark in string");
if (Str[i + 1] == Quote)
- ++i;
- }
- }
-
- Lex();
- return false;
-}
-
-bool MasmParser::parseAngleBracketString(std::string &Data) {
- SMLoc EndLoc, StartLoc = getTok().getLoc();
- if (isAngleBracketString(StartLoc, EndLoc)) {
- const char *StartChar = StartLoc.getPointer() + 1;
- const char *EndChar = EndLoc.getPointer() - 1;
+ ++i;
+ }
+ }
+
+ Lex();
+ return false;
+}
+
+bool MasmParser::parseAngleBracketString(std::string &Data) {
+ SMLoc EndLoc, StartLoc = getTok().getLoc();
+ if (isAngleBracketString(StartLoc, EndLoc)) {
+ const char *StartChar = StartLoc.getPointer() + 1;
+ const char *EndChar = EndLoc.getPointer() - 1;
jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
- // Eat from '<' to '>'.
- Lex();
-
- Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
- return false;
- }
- return true;
-}
-
-/// textItem ::= textLiteral | textMacroID | % constExpr
-bool MasmParser::parseTextItem(std::string &Data) {
+ // Eat from '<' to '>'.
+ Lex();
+
+ Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
+ return false;
+ }
+ return true;
+}
+
+/// textItem ::= textLiteral | textMacroID | % constExpr
+bool MasmParser::parseTextItem(std::string &Data) {
switch (getTok().getKind()) {
default:
return true;
@@ -3396,49 +3396,49 @@ bool MasmParser::parseTextItem(std::string &Data) {
}
}
llvm_unreachable("unhandled token kind");
-}
-
-/// parseDirectiveAscii:
-/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
-bool MasmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
- auto parseOp = [&]() -> bool {
- std::string Data;
- if (checkForValidSection() || parseEscapedString(Data))
- return true;
- getStreamer().emitBytes(Data);
- if (ZeroTerminated)
- getStreamer().emitBytes(StringRef("\0", 1));
- return false;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- return false;
-}
-
-bool MasmParser::emitIntValue(const MCExpr *Value, unsigned Size) {
- // Special case constant expressions to match code generator.
- if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
- assert(Size <= 8 && "Invalid size");
- int64_t IntValue = MCE->getValue();
- if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
- return Error(MCE->getLoc(), "out of range literal value");
- getStreamer().emitIntValue(IntValue, Size);
- } else {
- const MCSymbolRefExpr *MSE = dyn_cast<MCSymbolRefExpr>(Value);
- if (MSE && MSE->getSymbol().getName() == "?") {
- // ? initializer; treat as 0.
- getStreamer().emitIntValue(0, Size);
- } else {
- getStreamer().emitValue(Value, Size, Value->getLoc());
- }
- }
- return false;
-}
-
-bool MasmParser::parseScalarInitializer(unsigned Size,
- SmallVectorImpl<const MCExpr *> &Values,
- unsigned StringPadLength) {
+}
+
+/// parseDirectiveAscii:
+/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
+bool MasmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
+ auto parseOp = [&]() -> bool {
+ std::string Data;
+ if (checkForValidSection() || parseEscapedString(Data))
+ return true;
+ getStreamer().emitBytes(Data);
+ if (ZeroTerminated)
+ getStreamer().emitBytes(StringRef("\0", 1));
+ return false;
+ };
+
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ return false;
+}
+
+bool MasmParser::emitIntValue(const MCExpr *Value, unsigned Size) {
+ // Special case constant expressions to match code generator.
+ if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
+ assert(Size <= 8 && "Invalid size");
+ int64_t IntValue = MCE->getValue();
+ if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
+ return Error(MCE->getLoc(), "out of range literal value");
+ getStreamer().emitIntValue(IntValue, Size);
+ } else {
+ const MCSymbolRefExpr *MSE = dyn_cast<MCSymbolRefExpr>(Value);
+ if (MSE && MSE->getSymbol().getName() == "?") {
+ // ? initializer; treat as 0.
+ getStreamer().emitIntValue(0, Size);
+ } else {
+ getStreamer().emitValue(Value, Size, Value->getLoc());
+ }
+ }
+ return false;
+}
+
+bool MasmParser::parseScalarInitializer(unsigned Size,
+ SmallVectorImpl<const MCExpr *> &Values,
+ unsigned StringPadLength) {
if (Size == 1 && getTok().is(AsmToken::String)) {
std::string Value;
if (parseEscapedString(Value))
@@ -3446,113 +3446,113 @@ bool MasmParser::parseScalarInitializer(unsigned Size,
// Treat each character as an initializer.
for (const unsigned char CharVal : Value)
Values.push_back(MCConstantExpr::create(CharVal, getContext()));
-
+
// Pad the string with spaces to the specified length.
for (size_t i = Value.size(); i < StringPadLength; ++i)
Values.push_back(MCConstantExpr::create(' ', getContext()));
- } else {
- const MCExpr *Value;
+ } else {
+ const MCExpr *Value;
if (parseExpression(Value))
- return true;
- if (getTok().is(AsmToken::Identifier) &&
- getTok().getString().equals_lower("dup")) {
- Lex(); // Eat 'dup'.
- const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
- if (!MCE)
- return Error(Value->getLoc(),
- "cannot repeat value a non-constant number of times");
- const int64_t Repetitions = MCE->getValue();
- if (Repetitions < 0)
- return Error(Value->getLoc(),
- "cannot repeat value a negative number of times");
-
- SmallVector<const MCExpr *, 1> DuplicatedValues;
- if (parseToken(AsmToken::LParen,
- "parentheses required for 'dup' contents") ||
- parseScalarInstList(Size, DuplicatedValues) ||
- parseToken(AsmToken::RParen, "unmatched parentheses"))
- return true;
-
- for (int i = 0; i < Repetitions; ++i)
- Values.append(DuplicatedValues.begin(), DuplicatedValues.end());
- } else {
- Values.push_back(Value);
- }
- }
- return false;
-}
-
-bool MasmParser::parseScalarInstList(unsigned Size,
- SmallVectorImpl<const MCExpr *> &Values,
- const AsmToken::TokenKind EndToken) {
- while (getTok().isNot(EndToken) &&
- (EndToken != AsmToken::Greater ||
- getTok().isNot(AsmToken::GreaterGreater))) {
- parseScalarInitializer(Size, Values);
-
- // If we see a comma, continue, and allow line continuation.
- if (!parseOptionalToken(AsmToken::Comma))
- break;
- parseOptionalToken(AsmToken::EndOfStatement);
- }
- return false;
-}
-
+ return true;
+ if (getTok().is(AsmToken::Identifier) &&
+ getTok().getString().equals_lower("dup")) {
+ Lex(); // Eat 'dup'.
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
+ if (!MCE)
+ return Error(Value->getLoc(),
+ "cannot repeat value a non-constant number of times");
+ const int64_t Repetitions = MCE->getValue();
+ if (Repetitions < 0)
+ return Error(Value->getLoc(),
+ "cannot repeat value a negative number of times");
+
+ SmallVector<const MCExpr *, 1> DuplicatedValues;
+ if (parseToken(AsmToken::LParen,
+ "parentheses required for 'dup' contents") ||
+ parseScalarInstList(Size, DuplicatedValues) ||
+ parseToken(AsmToken::RParen, "unmatched parentheses"))
+ return true;
+
+ for (int i = 0; i < Repetitions; ++i)
+ Values.append(DuplicatedValues.begin(), DuplicatedValues.end());
+ } else {
+ Values.push_back(Value);
+ }
+ }
+ return false;
+}
+
+bool MasmParser::parseScalarInstList(unsigned Size,
+ SmallVectorImpl<const MCExpr *> &Values,
+ const AsmToken::TokenKind EndToken) {
+ while (getTok().isNot(EndToken) &&
+ (EndToken != AsmToken::Greater ||
+ getTok().isNot(AsmToken::GreaterGreater))) {
+ parseScalarInitializer(Size, Values);
+
+ // If we see a comma, continue, and allow line continuation.
+ if (!parseOptionalToken(AsmToken::Comma))
+ break;
+ parseOptionalToken(AsmToken::EndOfStatement);
+ }
+ return false;
+}
+
bool MasmParser::emitIntegralValues(unsigned Size, unsigned *Count) {
- SmallVector<const MCExpr *, 1> Values;
- if (checkForValidSection() || parseScalarInstList(Size, Values))
- return true;
-
- for (auto Value : Values) {
- emitIntValue(Value, Size);
- }
+ SmallVector<const MCExpr *, 1> Values;
+ if (checkForValidSection() || parseScalarInstList(Size, Values))
+ return true;
+
+ for (auto Value : Values) {
+ emitIntValue(Value, Size);
+ }
if (Count)
*Count = Values.size();
- return false;
-}
-
-// Add a field to the current structure.
-bool MasmParser::addIntegralField(StringRef Name, unsigned Size) {
- StructInfo &Struct = StructInProgress.back();
+ return false;
+}
+
+// Add a field to the current structure.
+bool MasmParser::addIntegralField(StringRef Name, unsigned Size) {
+ StructInfo &Struct = StructInProgress.back();
FieldInfo &Field = Struct.addField(Name, FT_INTEGRAL, Size);
- IntFieldInfo &IntInfo = Field.Contents.IntInfo;
-
- Field.Type = Size;
-
- if (parseScalarInstList(Size, IntInfo.Values))
- return true;
-
- Field.SizeOf = Field.Type * IntInfo.Values.size();
- Field.LengthOf = IntInfo.Values.size();
- if (Struct.IsUnion)
- Struct.Size = std::max(Struct.Size, Field.SizeOf);
- else
- Struct.Size += Field.SizeOf;
- return false;
-}
-
-/// parseDirectiveValue
-/// ::= (byte | word | ... ) [ expression (, expression)* ]
-bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
- if (StructInProgress.empty()) {
- // Initialize data value.
- if (emitIntegralValues(Size))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- } else if (addIntegralField("", Size)) {
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- }
-
- return false;
-}
-
-/// parseDirectiveNamedValue
-/// ::= name (byte | word | ... ) [ expression (, expression)* ]
+ IntFieldInfo &IntInfo = Field.Contents.IntInfo;
+
+ Field.Type = Size;
+
+ if (parseScalarInstList(Size, IntInfo.Values))
+ return true;
+
+ Field.SizeOf = Field.Type * IntInfo.Values.size();
+ Field.LengthOf = IntInfo.Values.size();
+ if (Struct.IsUnion)
+ Struct.Size = std::max(Struct.Size, Field.SizeOf);
+ else
+ Struct.Size += Field.SizeOf;
+ return false;
+}
+
+/// parseDirectiveValue
+/// ::= (byte | word | ... ) [ expression (, expression)* ]
+bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
+ if (StructInProgress.empty()) {
+ // Initialize data value.
+ if (emitIntegralValues(Size))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ } else if (addIntegralField("", Size)) {
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ }
+
+ return false;
+}
+
+/// parseDirectiveNamedValue
+/// ::= name (byte | word | ... ) [ expression (, expression)* ]
bool MasmParser::parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
- StringRef Name, SMLoc NameLoc) {
- if (StructInProgress.empty()) {
- // Initialize named data value.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().emitLabel(Sym);
+ StringRef Name, SMLoc NameLoc) {
+ if (StructInProgress.empty()) {
+ // Initialize named data value.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ getStreamer().emitLabel(Sym);
unsigned Count;
if (emitIntegralValues(Size, &Count))
return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
@@ -3563,64 +3563,64 @@ bool MasmParser::parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
Type.ElementSize = Size;
Type.Length = Count;
KnownType[Name.lower()] = Type;
- } else if (addIntegralField(Name, Size)) {
+ } else if (addIntegralField(Name, Size)) {
return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
- }
-
- return false;
-}
-
-static bool parseHexOcta(MasmParser &Asm, uint64_t &hi, uint64_t &lo) {
- if (Asm.getTok().isNot(AsmToken::Integer) &&
- Asm.getTok().isNot(AsmToken::BigNum))
- return Asm.TokError("unknown token in expression");
- SMLoc ExprLoc = Asm.getTok().getLoc();
- APInt IntValue = Asm.getTok().getAPIntVal();
- Asm.Lex();
- if (!IntValue.isIntN(128))
- return Asm.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();
- }
- return false;
-}
-
-bool MasmParser::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;
+ }
+
+ return false;
+}
+
+static bool parseHexOcta(MasmParser &Asm, uint64_t &hi, uint64_t &lo) {
+ if (Asm.getTok().isNot(AsmToken::Integer) &&
+ Asm.getTok().isNot(AsmToken::BigNum))
+ return Asm.TokError("unknown token in expression");
+ SMLoc ExprLoc = Asm.getTok().getLoc();
+ APInt IntValue = Asm.getTok().getAPIntVal();
+ Asm.Lex();
+ if (!IntValue.isIntN(128))
+ return Asm.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();
+ }
+ return false;
+}
+
+bool MasmParser::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;
SMLoc SignLoc;
- if (getLexer().is(AsmToken::Minus)) {
+ if (getLexer().is(AsmToken::Minus)) {
SignLoc = getLexer().getLoc();
- Lexer.Lex();
- IsNeg = true;
- } else if (getLexer().is(AsmToken::Plus)) {
+ Lexer.Lex();
+ IsNeg = true;
+ } else if (getLexer().is(AsmToken::Plus)) {
SignLoc = getLexer().getLoc();
- 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.equals_lower("infinity") || IDVal.equals_lower("inf"))
- Value = APFloat::getInf(Semantics);
- else if (IDVal.equals_lower("nan"))
- Value = APFloat::getNaN(Semantics, false, ~0);
- else if (IDVal.equals_lower("?"))
- Value = APFloat::getZero(Semantics);
- else
- return TokError("invalid floating point literal");
+ 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.equals_lower("infinity") || IDVal.equals_lower("inf"))
+ Value = APFloat::getInf(Semantics);
+ else if (IDVal.equals_lower("nan"))
+ Value = APFloat::getNaN(Semantics, false, ~0);
+ else if (IDVal.equals_lower("?"))
+ Value = APFloat::getZero(Semantics);
+ else
+ return TokError("invalid floating point literal");
} else if (IDVal.consume_back("r") || IDVal.consume_back("R")) {
// MASM hexadecimal floating-point literal; no APFloat conversion needed.
// To match ML64.exe, ignore the initial sign.
@@ -3635,133 +3635,133 @@ bool MasmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
if (SignLoc.isValid())
return Warning(SignLoc, "MASM-style hex floats ignore explicit sign");
return false;
- } else if (errorToBool(
- Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
- .takeError())) {
- return TokError("invalid floating point literal");
- }
- if (IsNeg)
- Value.changeSign();
-
- // Consume the numeric token.
- Lex();
-
- Res = Value.bitcastToAPInt();
-
- return false;
-}
-
-bool MasmParser::parseRealInstList(const fltSemantics &Semantics,
- SmallVectorImpl<APInt> &ValuesAsInt,
- const AsmToken::TokenKind EndToken) {
- while (getTok().isNot(EndToken) ||
- (EndToken == AsmToken::Greater &&
- getTok().isNot(AsmToken::GreaterGreater))) {
- const AsmToken NextTok = Lexer.peekTok();
- if (NextTok.is(AsmToken::Identifier) &&
- NextTok.getString().equals_lower("dup")) {
- const MCExpr *Value;
- if (parseExpression(Value) || parseToken(AsmToken::Identifier))
- return true;
- const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
- if (!MCE)
- return Error(Value->getLoc(),
- "cannot repeat value a non-constant number of times");
- const int64_t Repetitions = MCE->getValue();
- if (Repetitions < 0)
- return Error(Value->getLoc(),
- "cannot repeat value a negative number of times");
-
- SmallVector<APInt, 1> DuplicatedValues;
- if (parseToken(AsmToken::LParen,
- "parentheses required for 'dup' contents") ||
- parseRealInstList(Semantics, DuplicatedValues) ||
- parseToken(AsmToken::RParen, "unmatched parentheses"))
- return true;
-
- for (int i = 0; i < Repetitions; ++i)
- ValuesAsInt.append(DuplicatedValues.begin(), DuplicatedValues.end());
- } else {
- APInt AsInt;
- if (parseRealValue(Semantics, AsInt))
- return true;
- ValuesAsInt.push_back(AsInt);
- }
-
- // Continue if we see a comma. (Also, allow line continuation.)
- if (!parseOptionalToken(AsmToken::Comma))
- break;
- parseOptionalToken(AsmToken::EndOfStatement);
- }
-
- return false;
-}
-
-// Initialize real data values.
+ } else if (errorToBool(
+ Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
+ .takeError())) {
+ return TokError("invalid floating point literal");
+ }
+ if (IsNeg)
+ Value.changeSign();
+
+ // Consume the numeric token.
+ Lex();
+
+ Res = Value.bitcastToAPInt();
+
+ return false;
+}
+
+bool MasmParser::parseRealInstList(const fltSemantics &Semantics,
+ SmallVectorImpl<APInt> &ValuesAsInt,
+ const AsmToken::TokenKind EndToken) {
+ while (getTok().isNot(EndToken) ||
+ (EndToken == AsmToken::Greater &&
+ getTok().isNot(AsmToken::GreaterGreater))) {
+ const AsmToken NextTok = Lexer.peekTok();
+ if (NextTok.is(AsmToken::Identifier) &&
+ NextTok.getString().equals_lower("dup")) {
+ const MCExpr *Value;
+ if (parseExpression(Value) || parseToken(AsmToken::Identifier))
+ return true;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
+ if (!MCE)
+ return Error(Value->getLoc(),
+ "cannot repeat value a non-constant number of times");
+ const int64_t Repetitions = MCE->getValue();
+ if (Repetitions < 0)
+ return Error(Value->getLoc(),
+ "cannot repeat value a negative number of times");
+
+ SmallVector<APInt, 1> DuplicatedValues;
+ if (parseToken(AsmToken::LParen,
+ "parentheses required for 'dup' contents") ||
+ parseRealInstList(Semantics, DuplicatedValues) ||
+ parseToken(AsmToken::RParen, "unmatched parentheses"))
+ return true;
+
+ for (int i = 0; i < Repetitions; ++i)
+ ValuesAsInt.append(DuplicatedValues.begin(), DuplicatedValues.end());
+ } else {
+ APInt AsInt;
+ if (parseRealValue(Semantics, AsInt))
+ return true;
+ ValuesAsInt.push_back(AsInt);
+ }
+
+ // Continue if we see a comma. (Also, allow line continuation.)
+ if (!parseOptionalToken(AsmToken::Comma))
+ break;
+ parseOptionalToken(AsmToken::EndOfStatement);
+ }
+
+ return false;
+}
+
+// Initialize real data values.
bool MasmParser::emitRealValues(const fltSemantics &Semantics,
unsigned *Count) {
if (checkForValidSection())
return true;
- SmallVector<APInt, 1> ValuesAsInt;
- if (parseRealInstList(Semantics, ValuesAsInt))
- return true;
-
- for (const APInt &AsInt : ValuesAsInt) {
+ SmallVector<APInt, 1> ValuesAsInt;
+ if (parseRealInstList(Semantics, ValuesAsInt))
+ return true;
+
+ for (const APInt &AsInt : ValuesAsInt) {
getStreamer().emitIntValue(AsInt);
- }
+ }
if (Count)
*Count = ValuesAsInt.size();
- return false;
-}
-
-// Add a real field to the current struct.
+ return false;
+}
+
+// Add a real field to the current struct.
bool MasmParser::addRealField(StringRef Name, const fltSemantics &Semantics,
size_t Size) {
- StructInfo &Struct = StructInProgress.back();
+ StructInfo &Struct = StructInProgress.back();
FieldInfo &Field = Struct.addField(Name, FT_REAL, Size);
- RealFieldInfo &RealInfo = Field.Contents.RealInfo;
-
- Field.SizeOf = 0;
-
+ RealFieldInfo &RealInfo = Field.Contents.RealInfo;
+
+ Field.SizeOf = 0;
+
if (parseRealInstList(Semantics, RealInfo.AsIntValues))
- return true;
-
- Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
- Field.LengthOf = RealInfo.AsIntValues.size();
- Field.SizeOf = Field.Type * Field.LengthOf;
- if (Struct.IsUnion)
- Struct.Size = std::max(Struct.Size, Field.SizeOf);
- else
- Struct.Size += Field.SizeOf;
- return false;
-}
-
-/// parseDirectiveRealValue
+ return true;
+
+ Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
+ Field.LengthOf = RealInfo.AsIntValues.size();
+ Field.SizeOf = Field.Type * Field.LengthOf;
+ if (Struct.IsUnion)
+ Struct.Size = std::max(Struct.Size, Field.SizeOf);
+ else
+ Struct.Size += Field.SizeOf;
+ return false;
+}
+
+/// parseDirectiveRealValue
/// ::= (real4 | real8 | real10) [ expression (, expression)* ]
-bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
+bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
const fltSemantics &Semantics,
size_t Size) {
- if (StructInProgress.empty()) {
- // Initialize data value.
- if (emitRealValues(Semantics))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ if (StructInProgress.empty()) {
+ // Initialize data value.
+ if (emitRealValues(Semantics))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
} else if (addRealField("", Semantics, Size)) {
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- }
- return false;
-}
-
-/// parseDirectiveNamedRealValue
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ }
+ return false;
+}
+
+/// parseDirectiveNamedRealValue
/// ::= name (real4 | real8 | real10) [ expression (, expression)* ]
bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
- const fltSemantics &Semantics,
+ const fltSemantics &Semantics,
unsigned Size, StringRef Name,
SMLoc NameLoc) {
- if (StructInProgress.empty()) {
- // Initialize named data value.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().emitLabel(Sym);
+ if (StructInProgress.empty()) {
+ // Initialize named data value.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ getStreamer().emitLabel(Sym);
unsigned Count;
if (emitRealValues(Semantics, &Count))
return addErrorSuffix(" in '" + TypeName + "' directive");
@@ -3774,79 +3774,79 @@ bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
KnownType[Name.lower()] = Type;
} else if (addRealField(Name, Semantics, Size)) {
return addErrorSuffix(" in '" + TypeName + "' directive");
- }
- return false;
-}
-
-bool MasmParser::parseOptionalAngleBracketOpen() {
- const AsmToken Tok = getTok();
- if (parseOptionalToken(AsmToken::LessLess)) {
- AngleBracketDepth++;
- Lexer.UnLex(AsmToken(AsmToken::Less, Tok.getString().substr(1)));
- return true;
- } else if (parseOptionalToken(AsmToken::LessGreater)) {
- AngleBracketDepth++;
- Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
- return true;
- } else if (parseOptionalToken(AsmToken::Less)) {
- AngleBracketDepth++;
- return true;
- }
-
- return false;
-}
-
-bool MasmParser::parseAngleBracketClose(const Twine &Msg) {
- const AsmToken Tok = getTok();
- if (parseOptionalToken(AsmToken::GreaterGreater)) {
- Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
- } else if (parseToken(AsmToken::Greater, Msg)) {
- return true;
- }
- AngleBracketDepth--;
- return false;
-}
-
-bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
- const IntFieldInfo &Contents,
- FieldInitializer &Initializer) {
- SMLoc Loc = getTok().getLoc();
-
- SmallVector<const MCExpr *, 1> Values;
- if (parseOptionalToken(AsmToken::LCurly)) {
- if (Field.LengthOf == 1 && Field.Type > 1)
- return Error(Loc, "Cannot initialize scalar field with array value");
- if (parseScalarInstList(Field.Type, Values, AsmToken::RCurly) ||
- parseToken(AsmToken::RCurly))
- return true;
- } else if (parseOptionalAngleBracketOpen()) {
- if (Field.LengthOf == 1 && Field.Type > 1)
- return Error(Loc, "Cannot initialize scalar field with array value");
- if (parseScalarInstList(Field.Type, Values, AsmToken::Greater) ||
- parseAngleBracketClose())
- return true;
- } else if (Field.LengthOf > 1 && Field.Type > 1) {
- return Error(Loc, "Cannot initialize array field with scalar value");
- } else if (parseScalarInitializer(Field.Type, Values,
- /*StringPadLength=*/Field.LengthOf)) {
- return true;
- }
-
- if (Values.size() > Field.LengthOf) {
- return Error(Loc, "Initializer too long for field; expected at most " +
- std::to_string(Field.LengthOf) + " elements, got " +
- std::to_string(Values.size()));
- }
- // Default-initialize all remaining values.
- Values.append(Contents.Values.begin() + Values.size(), Contents.Values.end());
-
- Initializer = FieldInitializer(std::move(Values));
- return false;
-}
-
-bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
- const RealFieldInfo &Contents,
- FieldInitializer &Initializer) {
+ }
+ return false;
+}
+
+bool MasmParser::parseOptionalAngleBracketOpen() {
+ const AsmToken Tok = getTok();
+ if (parseOptionalToken(AsmToken::LessLess)) {
+ AngleBracketDepth++;
+ Lexer.UnLex(AsmToken(AsmToken::Less, Tok.getString().substr(1)));
+ return true;
+ } else if (parseOptionalToken(AsmToken::LessGreater)) {
+ AngleBracketDepth++;
+ Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
+ return true;
+ } else if (parseOptionalToken(AsmToken::Less)) {
+ AngleBracketDepth++;
+ return true;
+ }
+
+ return false;
+}
+
+bool MasmParser::parseAngleBracketClose(const Twine &Msg) {
+ const AsmToken Tok = getTok();
+ if (parseOptionalToken(AsmToken::GreaterGreater)) {
+ Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
+ } else if (parseToken(AsmToken::Greater, Msg)) {
+ return true;
+ }
+ AngleBracketDepth--;
+ return false;
+}
+
+bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
+ const IntFieldInfo &Contents,
+ FieldInitializer &Initializer) {
+ SMLoc Loc = getTok().getLoc();
+
+ SmallVector<const MCExpr *, 1> Values;
+ if (parseOptionalToken(AsmToken::LCurly)) {
+ if (Field.LengthOf == 1 && Field.Type > 1)
+ return Error(Loc, "Cannot initialize scalar field with array value");
+ if (parseScalarInstList(Field.Type, Values, AsmToken::RCurly) ||
+ parseToken(AsmToken::RCurly))
+ return true;
+ } else if (parseOptionalAngleBracketOpen()) {
+ if (Field.LengthOf == 1 && Field.Type > 1)
+ return Error(Loc, "Cannot initialize scalar field with array value");
+ if (parseScalarInstList(Field.Type, Values, AsmToken::Greater) ||
+ parseAngleBracketClose())
+ return true;
+ } else if (Field.LengthOf > 1 && Field.Type > 1) {
+ return Error(Loc, "Cannot initialize array field with scalar value");
+ } else if (parseScalarInitializer(Field.Type, Values,
+ /*StringPadLength=*/Field.LengthOf)) {
+ return true;
+ }
+
+ if (Values.size() > Field.LengthOf) {
+ return Error(Loc, "Initializer too long for field; expected at most " +
+ std::to_string(Field.LengthOf) + " elements, got " +
+ std::to_string(Values.size()));
+ }
+ // Default-initialize all remaining values.
+ Values.append(Contents.Values.begin() + Values.size(), Contents.Values.end());
+
+ Initializer = FieldInitializer(std::move(Values));
+ return false;
+}
+
+bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
+ const RealFieldInfo &Contents,
+ FieldInitializer &Initializer) {
const fltSemantics *Semantics;
switch (Field.Type) {
case 4:
@@ -3861,1665 +3861,1665 @@ bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
default:
llvm_unreachable("unknown real field type");
}
-
- SMLoc Loc = getTok().getLoc();
-
- SmallVector<APInt, 1> AsIntValues;
- if (parseOptionalToken(AsmToken::LCurly)) {
- if (Field.LengthOf == 1)
- return Error(Loc, "Cannot initialize scalar field with array value");
+
+ SMLoc Loc = getTok().getLoc();
+
+ SmallVector<APInt, 1> AsIntValues;
+ if (parseOptionalToken(AsmToken::LCurly)) {
+ if (Field.LengthOf == 1)
+ return Error(Loc, "Cannot initialize scalar field with array value");
if (parseRealInstList(*Semantics, AsIntValues, AsmToken::RCurly) ||
- parseToken(AsmToken::RCurly))
- return true;
- } else if (parseOptionalAngleBracketOpen()) {
- if (Field.LengthOf == 1)
- return Error(Loc, "Cannot initialize scalar field with array value");
+ parseToken(AsmToken::RCurly))
+ return true;
+ } else if (parseOptionalAngleBracketOpen()) {
+ if (Field.LengthOf == 1)
+ return Error(Loc, "Cannot initialize scalar field with array value");
if (parseRealInstList(*Semantics, AsIntValues, AsmToken::Greater) ||
- parseAngleBracketClose())
- return true;
- } else if (Field.LengthOf > 1) {
- return Error(Loc, "Cannot initialize array field with scalar value");
- } else {
- AsIntValues.emplace_back();
+ parseAngleBracketClose())
+ return true;
+ } else if (Field.LengthOf > 1) {
+ return Error(Loc, "Cannot initialize array field with scalar value");
+ } else {
+ AsIntValues.emplace_back();
if (parseRealValue(*Semantics, AsIntValues.back()))
- return true;
- }
-
- if (AsIntValues.size() > Field.LengthOf) {
- return Error(Loc, "Initializer too long for field; expected at most " +
- std::to_string(Field.LengthOf) + " elements, got " +
- std::to_string(AsIntValues.size()));
- }
- // Default-initialize all remaining values.
- AsIntValues.append(Contents.AsIntValues.begin() + AsIntValues.size(),
- Contents.AsIntValues.end());
-
- Initializer = FieldInitializer(std::move(AsIntValues));
- return false;
-}
-
-bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
- const StructFieldInfo &Contents,
- FieldInitializer &Initializer) {
- SMLoc Loc = getTok().getLoc();
-
- std::vector<StructInitializer> Initializers;
- if (Field.LengthOf > 1) {
- if (parseOptionalToken(AsmToken::LCurly)) {
- if (parseStructInstList(Contents.Structure, Initializers,
- AsmToken::RCurly) ||
- parseToken(AsmToken::RCurly))
- return true;
- } else if (parseOptionalAngleBracketOpen()) {
- if (parseStructInstList(Contents.Structure, Initializers,
- AsmToken::Greater) ||
- parseAngleBracketClose())
- return true;
- } else {
- return Error(Loc, "Cannot initialize array field with scalar value");
- }
- } else {
- Initializers.emplace_back();
- if (parseStructInitializer(Contents.Structure, Initializers.back()))
- return true;
- }
-
- if (Initializers.size() > Field.LengthOf) {
- return Error(Loc, "Initializer too long for field; expected at most " +
- std::to_string(Field.LengthOf) + " elements, got " +
- std::to_string(Initializers.size()));
- }
- // Default-initialize all remaining values.
- Initializers.insert(Initializers.end(),
- Contents.Initializers.begin() + Initializers.size(),
- Contents.Initializers.end());
-
- Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
- return false;
-}
-
-bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
- FieldInitializer &Initializer) {
- switch (Field.Contents.FT) {
- case FT_INTEGRAL:
- return parseFieldInitializer(Field, Field.Contents.IntInfo, Initializer);
- case FT_REAL:
- return parseFieldInitializer(Field, Field.Contents.RealInfo, Initializer);
- case FT_STRUCT:
- return parseFieldInitializer(Field, Field.Contents.StructInfo, Initializer);
- }
- llvm_unreachable("Unhandled FieldType enum");
-}
-
-bool MasmParser::parseStructInitializer(const StructInfo &Structure,
- StructInitializer &Initializer) {
- const AsmToken FirstToken = getTok();
-
- Optional<AsmToken::TokenKind> EndToken;
- if (parseOptionalToken(AsmToken::LCurly)) {
- EndToken = AsmToken::RCurly;
- } else if (parseOptionalAngleBracketOpen()) {
- EndToken = AsmToken::Greater;
- AngleBracketDepth++;
- } else if (FirstToken.is(AsmToken::Identifier) &&
- FirstToken.getString() == "?") {
- // ? initializer; leave EndToken uninitialized to treat as empty.
- if (parseToken(AsmToken::Identifier))
- return true;
- } else {
- return Error(FirstToken.getLoc(), "Expected struct initializer");
- }
-
- auto &FieldInitializers = Initializer.FieldInitializers;
- size_t FieldIndex = 0;
- if (EndToken.hasValue()) {
- // Initialize all fields with given initializers.
- while (getTok().isNot(EndToken.getValue()) &&
- FieldIndex < Structure.Fields.size()) {
- const FieldInfo &Field = Structure.Fields[FieldIndex++];
- if (parseOptionalToken(AsmToken::Comma)) {
- // Empty initializer; use the default and continue. (Also, allow line
- // continuation.)
- FieldInitializers.push_back(Field.Contents);
- parseOptionalToken(AsmToken::EndOfStatement);
- continue;
- }
- FieldInitializers.emplace_back(Field.Contents.FT);
- if (parseFieldInitializer(Field, FieldInitializers.back()))
- return true;
-
- // Continue if we see a comma. (Also, allow line continuation.)
- SMLoc CommaLoc = getTok().getLoc();
- if (!parseOptionalToken(AsmToken::Comma))
- break;
- if (FieldIndex == Structure.Fields.size())
- return Error(CommaLoc, "'" + Structure.Name +
- "' initializer initializes too many fields");
- parseOptionalToken(AsmToken::EndOfStatement);
- }
- }
- // Default-initialize all remaining fields.
- for (auto It = Structure.Fields.begin() + FieldIndex;
- It != Structure.Fields.end(); ++It) {
- const FieldInfo &Field = *It;
- FieldInitializers.push_back(Field.Contents);
- }
-
- if (EndToken.hasValue()) {
- if (EndToken.getValue() == AsmToken::Greater)
- return parseAngleBracketClose();
-
- return parseToken(EndToken.getValue());
- }
-
- return false;
-}
-
-bool MasmParser::parseStructInstList(
- const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
- const AsmToken::TokenKind EndToken) {
- while (getTok().isNot(EndToken) ||
- (EndToken == AsmToken::Greater &&
- getTok().isNot(AsmToken::GreaterGreater))) {
- const AsmToken NextTok = Lexer.peekTok();
- if (NextTok.is(AsmToken::Identifier) &&
- NextTok.getString().equals_lower("dup")) {
- const MCExpr *Value;
- if (parseExpression(Value) || parseToken(AsmToken::Identifier))
- return true;
- const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
- if (!MCE)
- return Error(Value->getLoc(),
- "cannot repeat value a non-constant number of times");
- const int64_t Repetitions = MCE->getValue();
- if (Repetitions < 0)
- return Error(Value->getLoc(),
- "cannot repeat value a negative number of times");
-
- std::vector<StructInitializer> DuplicatedValues;
- if (parseToken(AsmToken::LParen,
- "parentheses required for 'dup' contents") ||
- parseStructInstList(Structure, DuplicatedValues) ||
- parseToken(AsmToken::RParen, "unmatched parentheses"))
- return true;
-
- for (int i = 0; i < Repetitions; ++i)
+ return true;
+ }
+
+ if (AsIntValues.size() > Field.LengthOf) {
+ return Error(Loc, "Initializer too long for field; expected at most " +
+ std::to_string(Field.LengthOf) + " elements, got " +
+ std::to_string(AsIntValues.size()));
+ }
+ // Default-initialize all remaining values.
+ AsIntValues.append(Contents.AsIntValues.begin() + AsIntValues.size(),
+ Contents.AsIntValues.end());
+
+ Initializer = FieldInitializer(std::move(AsIntValues));
+ return false;
+}
+
+bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
+ const StructFieldInfo &Contents,
+ FieldInitializer &Initializer) {
+ SMLoc Loc = getTok().getLoc();
+
+ std::vector<StructInitializer> Initializers;
+ if (Field.LengthOf > 1) {
+ if (parseOptionalToken(AsmToken::LCurly)) {
+ if (parseStructInstList(Contents.Structure, Initializers,
+ AsmToken::RCurly) ||
+ parseToken(AsmToken::RCurly))
+ return true;
+ } else if (parseOptionalAngleBracketOpen()) {
+ if (parseStructInstList(Contents.Structure, Initializers,
+ AsmToken::Greater) ||
+ parseAngleBracketClose())
+ return true;
+ } else {
+ return Error(Loc, "Cannot initialize array field with scalar value");
+ }
+ } else {
+ Initializers.emplace_back();
+ if (parseStructInitializer(Contents.Structure, Initializers.back()))
+ return true;
+ }
+
+ if (Initializers.size() > Field.LengthOf) {
+ return Error(Loc, "Initializer too long for field; expected at most " +
+ std::to_string(Field.LengthOf) + " elements, got " +
+ std::to_string(Initializers.size()));
+ }
+ // Default-initialize all remaining values.
+ Initializers.insert(Initializers.end(),
+ Contents.Initializers.begin() + Initializers.size(),
+ Contents.Initializers.end());
+
+ Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
+ return false;
+}
+
+bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
+ FieldInitializer &Initializer) {
+ switch (Field.Contents.FT) {
+ case FT_INTEGRAL:
+ return parseFieldInitializer(Field, Field.Contents.IntInfo, Initializer);
+ case FT_REAL:
+ return parseFieldInitializer(Field, Field.Contents.RealInfo, Initializer);
+ case FT_STRUCT:
+ return parseFieldInitializer(Field, Field.Contents.StructInfo, Initializer);
+ }
+ llvm_unreachable("Unhandled FieldType enum");
+}
+
+bool MasmParser::parseStructInitializer(const StructInfo &Structure,
+ StructInitializer &Initializer) {
+ const AsmToken FirstToken = getTok();
+
+ Optional<AsmToken::TokenKind> EndToken;
+ if (parseOptionalToken(AsmToken::LCurly)) {
+ EndToken = AsmToken::RCurly;
+ } else if (parseOptionalAngleBracketOpen()) {
+ EndToken = AsmToken::Greater;
+ AngleBracketDepth++;
+ } else if (FirstToken.is(AsmToken::Identifier) &&
+ FirstToken.getString() == "?") {
+ // ? initializer; leave EndToken uninitialized to treat as empty.
+ if (parseToken(AsmToken::Identifier))
+ return true;
+ } else {
+ return Error(FirstToken.getLoc(), "Expected struct initializer");
+ }
+
+ auto &FieldInitializers = Initializer.FieldInitializers;
+ size_t FieldIndex = 0;
+ if (EndToken.hasValue()) {
+ // Initialize all fields with given initializers.
+ while (getTok().isNot(EndToken.getValue()) &&
+ FieldIndex < Structure.Fields.size()) {
+ const FieldInfo &Field = Structure.Fields[FieldIndex++];
+ if (parseOptionalToken(AsmToken::Comma)) {
+ // Empty initializer; use the default and continue. (Also, allow line
+ // continuation.)
+ FieldInitializers.push_back(Field.Contents);
+ parseOptionalToken(AsmToken::EndOfStatement);
+ continue;
+ }
+ FieldInitializers.emplace_back(Field.Contents.FT);
+ if (parseFieldInitializer(Field, FieldInitializers.back()))
+ return true;
+
+ // Continue if we see a comma. (Also, allow line continuation.)
+ SMLoc CommaLoc = getTok().getLoc();
+ if (!parseOptionalToken(AsmToken::Comma))
+ break;
+ if (FieldIndex == Structure.Fields.size())
+ return Error(CommaLoc, "'" + Structure.Name +
+ "' initializer initializes too many fields");
+ parseOptionalToken(AsmToken::EndOfStatement);
+ }
+ }
+ // Default-initialize all remaining fields.
+ for (auto It = Structure.Fields.begin() + FieldIndex;
+ It != Structure.Fields.end(); ++It) {
+ const FieldInfo &Field = *It;
+ FieldInitializers.push_back(Field.Contents);
+ }
+
+ if (EndToken.hasValue()) {
+ if (EndToken.getValue() == AsmToken::Greater)
+ return parseAngleBracketClose();
+
+ return parseToken(EndToken.getValue());
+ }
+
+ return false;
+}
+
+bool MasmParser::parseStructInstList(
+ const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
+ const AsmToken::TokenKind EndToken) {
+ while (getTok().isNot(EndToken) ||
+ (EndToken == AsmToken::Greater &&
+ getTok().isNot(AsmToken::GreaterGreater))) {
+ const AsmToken NextTok = Lexer.peekTok();
+ if (NextTok.is(AsmToken::Identifier) &&
+ NextTok.getString().equals_lower("dup")) {
+ const MCExpr *Value;
+ if (parseExpression(Value) || parseToken(AsmToken::Identifier))
+ return true;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
+ if (!MCE)
+ return Error(Value->getLoc(),
+ "cannot repeat value a non-constant number of times");
+ const int64_t Repetitions = MCE->getValue();
+ if (Repetitions < 0)
+ return Error(Value->getLoc(),
+ "cannot repeat value a negative number of times");
+
+ std::vector<StructInitializer> DuplicatedValues;
+ if (parseToken(AsmToken::LParen,
+ "parentheses required for 'dup' contents") ||
+ parseStructInstList(Structure, DuplicatedValues) ||
+ parseToken(AsmToken::RParen, "unmatched parentheses"))
+ return true;
+
+ for (int i = 0; i < Repetitions; ++i)
llvm::append_range(Initializers, DuplicatedValues);
- } else {
- Initializers.emplace_back();
- if (parseStructInitializer(Structure, Initializers.back()))
- return true;
- }
-
- // Continue if we see a comma. (Also, allow line continuation.)
- if (!parseOptionalToken(AsmToken::Comma))
- break;
- parseOptionalToken(AsmToken::EndOfStatement);
- }
-
- return false;
-}
-
-bool MasmParser::emitFieldValue(const FieldInfo &Field,
- const IntFieldInfo &Contents) {
- // Default-initialize all values.
- for (const MCExpr *Value : Contents.Values) {
- if (emitIntValue(Value, Field.Type))
- return true;
- }
- return false;
-}
-
-bool MasmParser::emitFieldValue(const FieldInfo &Field,
- const RealFieldInfo &Contents) {
- for (const APInt &AsInt : Contents.AsIntValues) {
- getStreamer().emitIntValue(AsInt.getLimitedValue(),
- AsInt.getBitWidth() / 8);
- }
- return false;
-}
-
-bool MasmParser::emitFieldValue(const FieldInfo &Field,
- const StructFieldInfo &Contents) {
- for (const auto &Initializer : Contents.Initializers) {
- size_t Index = 0, Offset = 0;
- for (const auto &SubField : Contents.Structure.Fields) {
- getStreamer().emitZeros(SubField.Offset - Offset);
- Offset = SubField.Offset + SubField.SizeOf;
- emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
- }
- }
- return false;
-}
-
-bool MasmParser::emitFieldValue(const FieldInfo &Field) {
- switch (Field.Contents.FT) {
- case FT_INTEGRAL:
- return emitFieldValue(Field, Field.Contents.IntInfo);
- case FT_REAL:
- return emitFieldValue(Field, Field.Contents.RealInfo);
- case FT_STRUCT:
- return emitFieldValue(Field, Field.Contents.StructInfo);
- }
- llvm_unreachable("Unhandled FieldType enum");
-}
-
-bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
- const IntFieldInfo &Contents,
- const IntFieldInfo &Initializer) {
- for (const auto &Value : Initializer.Values) {
- if (emitIntValue(Value, Field.Type))
- return true;
- }
- // Default-initialize all remaining values.
- for (auto it = Contents.Values.begin() + Initializer.Values.size();
- it != Contents.Values.end(); ++it) {
- const auto &Value = *it;
- if (emitIntValue(Value, Field.Type))
- return true;
- }
- return false;
-}
-
-bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
- const RealFieldInfo &Contents,
- const RealFieldInfo &Initializer) {
- for (const auto &AsInt : Initializer.AsIntValues) {
- getStreamer().emitIntValue(AsInt.getLimitedValue(),
- AsInt.getBitWidth() / 8);
- }
- // Default-initialize all remaining values.
- for (auto It = Contents.AsIntValues.begin() + Initializer.AsIntValues.size();
- It != Contents.AsIntValues.end(); ++It) {
- const auto &AsInt = *It;
- getStreamer().emitIntValue(AsInt.getLimitedValue(),
- AsInt.getBitWidth() / 8);
- }
- return false;
-}
-
-bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
- const StructFieldInfo &Contents,
- const StructFieldInfo &Initializer) {
- for (const auto &Init : Initializer.Initializers) {
- emitStructInitializer(Contents.Structure, Init);
- }
- // Default-initialize all remaining values.
- for (auto It =
- Contents.Initializers.begin() + Initializer.Initializers.size();
- It != Contents.Initializers.end(); ++It) {
- const auto &Init = *It;
- emitStructInitializer(Contents.Structure, Init);
- }
- return false;
-}
-
-bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
- const FieldInitializer &Initializer) {
- switch (Field.Contents.FT) {
- case FT_INTEGRAL:
- return emitFieldInitializer(Field, Field.Contents.IntInfo,
- Initializer.IntInfo);
- case FT_REAL:
- return emitFieldInitializer(Field, Field.Contents.RealInfo,
- Initializer.RealInfo);
- case FT_STRUCT:
- return emitFieldInitializer(Field, Field.Contents.StructInfo,
- Initializer.StructInfo);
- }
- llvm_unreachable("Unhandled FieldType enum");
-}
-
-bool MasmParser::emitStructInitializer(const StructInfo &Structure,
- const StructInitializer &Initializer) {
- size_t Index = 0, Offset = 0;
- for (const auto &Init : Initializer.FieldInitializers) {
- const auto &Field = Structure.Fields[Index++];
- getStreamer().emitZeros(Field.Offset - Offset);
- Offset = Field.Offset + Field.SizeOf;
- if (emitFieldInitializer(Field, Init))
- return true;
- }
- // Default-initialize all remaining fields.
- for (auto It =
- Structure.Fields.begin() + Initializer.FieldInitializers.size();
- It != Structure.Fields.end(); ++It) {
- const auto &Field = *It;
- getStreamer().emitZeros(Field.Offset - Offset);
- Offset = Field.Offset + Field.SizeOf;
- if (emitFieldValue(Field))
- return true;
- }
- // Add final padding.
- if (Offset != Structure.Size)
- getStreamer().emitZeros(Structure.Size - Offset);
- return false;
-}
-
-// Set data values from initializers.
+ } else {
+ Initializers.emplace_back();
+ if (parseStructInitializer(Structure, Initializers.back()))
+ return true;
+ }
+
+ // Continue if we see a comma. (Also, allow line continuation.)
+ if (!parseOptionalToken(AsmToken::Comma))
+ break;
+ parseOptionalToken(AsmToken::EndOfStatement);
+ }
+
+ return false;
+}
+
+bool MasmParser::emitFieldValue(const FieldInfo &Field,
+ const IntFieldInfo &Contents) {
+ // Default-initialize all values.
+ for (const MCExpr *Value : Contents.Values) {
+ if (emitIntValue(Value, Field.Type))
+ return true;
+ }
+ return false;
+}
+
+bool MasmParser::emitFieldValue(const FieldInfo &Field,
+ const RealFieldInfo &Contents) {
+ for (const APInt &AsInt : Contents.AsIntValues) {
+ getStreamer().emitIntValue(AsInt.getLimitedValue(),
+ AsInt.getBitWidth() / 8);
+ }
+ return false;
+}
+
+bool MasmParser::emitFieldValue(const FieldInfo &Field,
+ const StructFieldInfo &Contents) {
+ for (const auto &Initializer : Contents.Initializers) {
+ size_t Index = 0, Offset = 0;
+ for (const auto &SubField : Contents.Structure.Fields) {
+ getStreamer().emitZeros(SubField.Offset - Offset);
+ Offset = SubField.Offset + SubField.SizeOf;
+ emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
+ }
+ }
+ return false;
+}
+
+bool MasmParser::emitFieldValue(const FieldInfo &Field) {
+ switch (Field.Contents.FT) {
+ case FT_INTEGRAL:
+ return emitFieldValue(Field, Field.Contents.IntInfo);
+ case FT_REAL:
+ return emitFieldValue(Field, Field.Contents.RealInfo);
+ case FT_STRUCT:
+ return emitFieldValue(Field, Field.Contents.StructInfo);
+ }
+ llvm_unreachable("Unhandled FieldType enum");
+}
+
+bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
+ const IntFieldInfo &Contents,
+ const IntFieldInfo &Initializer) {
+ for (const auto &Value : Initializer.Values) {
+ if (emitIntValue(Value, Field.Type))
+ return true;
+ }
+ // Default-initialize all remaining values.
+ for (auto it = Contents.Values.begin() + Initializer.Values.size();
+ it != Contents.Values.end(); ++it) {
+ const auto &Value = *it;
+ if (emitIntValue(Value, Field.Type))
+ return true;
+ }
+ return false;
+}
+
+bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
+ const RealFieldInfo &Contents,
+ const RealFieldInfo &Initializer) {
+ for (const auto &AsInt : Initializer.AsIntValues) {
+ getStreamer().emitIntValue(AsInt.getLimitedValue(),
+ AsInt.getBitWidth() / 8);
+ }
+ // Default-initialize all remaining values.
+ for (auto It = Contents.AsIntValues.begin() + Initializer.AsIntValues.size();
+ It != Contents.AsIntValues.end(); ++It) {
+ const auto &AsInt = *It;
+ getStreamer().emitIntValue(AsInt.getLimitedValue(),
+ AsInt.getBitWidth() / 8);
+ }
+ return false;
+}
+
+bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
+ const StructFieldInfo &Contents,
+ const StructFieldInfo &Initializer) {
+ for (const auto &Init : Initializer.Initializers) {
+ emitStructInitializer(Contents.Structure, Init);
+ }
+ // Default-initialize all remaining values.
+ for (auto It =
+ Contents.Initializers.begin() + Initializer.Initializers.size();
+ It != Contents.Initializers.end(); ++It) {
+ const auto &Init = *It;
+ emitStructInitializer(Contents.Structure, Init);
+ }
+ return false;
+}
+
+bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
+ const FieldInitializer &Initializer) {
+ switch (Field.Contents.FT) {
+ case FT_INTEGRAL:
+ return emitFieldInitializer(Field, Field.Contents.IntInfo,
+ Initializer.IntInfo);
+ case FT_REAL:
+ return emitFieldInitializer(Field, Field.Contents.RealInfo,
+ Initializer.RealInfo);
+ case FT_STRUCT:
+ return emitFieldInitializer(Field, Field.Contents.StructInfo,
+ Initializer.StructInfo);
+ }
+ llvm_unreachable("Unhandled FieldType enum");
+}
+
+bool MasmParser::emitStructInitializer(const StructInfo &Structure,
+ const StructInitializer &Initializer) {
+ size_t Index = 0, Offset = 0;
+ for (const auto &Init : Initializer.FieldInitializers) {
+ const auto &Field = Structure.Fields[Index++];
+ getStreamer().emitZeros(Field.Offset - Offset);
+ Offset = Field.Offset + Field.SizeOf;
+ if (emitFieldInitializer(Field, Init))
+ return true;
+ }
+ // Default-initialize all remaining fields.
+ for (auto It =
+ Structure.Fields.begin() + Initializer.FieldInitializers.size();
+ It != Structure.Fields.end(); ++It) {
+ const auto &Field = *It;
+ getStreamer().emitZeros(Field.Offset - Offset);
+ Offset = Field.Offset + Field.SizeOf;
+ if (emitFieldValue(Field))
+ return true;
+ }
+ // Add final padding.
+ if (Offset != Structure.Size)
+ getStreamer().emitZeros(Structure.Size - Offset);
+ return false;
+}
+
+// Set data values from initializers.
bool MasmParser::emitStructValues(const StructInfo &Structure,
unsigned *Count) {
- std::vector<StructInitializer> Initializers;
- if (parseStructInstList(Structure, Initializers))
- return true;
-
- for (const auto &Initializer : Initializers) {
- if (emitStructInitializer(Structure, Initializer))
- return true;
- }
-
+ std::vector<StructInitializer> Initializers;
+ if (parseStructInstList(Structure, Initializers))
+ return true;
+
+ for (const auto &Initializer : Initializers) {
+ if (emitStructInitializer(Structure, Initializer))
+ return true;
+ }
+
if (Count)
*Count = Initializers.size();
- return false;
-}
-
-// Declare a field in the current struct.
-bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) {
- StructInfo &OwningStruct = StructInProgress.back();
+ return false;
+}
+
+// Declare a field in the current struct.
+bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) {
+ StructInfo &OwningStruct = StructInProgress.back();
FieldInfo &Field =
OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
- StructFieldInfo &StructInfo = Field.Contents.StructInfo;
-
- StructInfo.Structure = Structure;
- Field.Type = Structure.Size;
-
- if (parseStructInstList(Structure, StructInfo.Initializers))
- return true;
-
- Field.LengthOf = StructInfo.Initializers.size();
- Field.SizeOf = Field.Type * Field.LengthOf;
- if (OwningStruct.IsUnion)
- OwningStruct.Size = std::max(OwningStruct.Size, Field.SizeOf);
- else
- OwningStruct.Size += Field.SizeOf;
-
- return false;
-}
-
-/// parseDirectiveStructValue
-/// ::= struct-id (<struct-initializer> | {struct-initializer})
-/// [, (<struct-initializer> | {struct-initializer})]*
-bool MasmParser::parseDirectiveStructValue(const StructInfo &Structure,
- StringRef Directive, SMLoc DirLoc) {
- if (StructInProgress.empty()) {
- if (emitStructValues(Structure))
- return true;
- } else if (addStructField("", Structure)) {
- return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
- }
-
- return false;
-}
-
-/// parseDirectiveNamedValue
-/// ::= name (byte | word | ... ) [ expression (, expression)* ]
-bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure,
- StringRef Directive,
- SMLoc DirLoc, StringRef Name) {
- if (StructInProgress.empty()) {
- // Initialize named data value.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().emitLabel(Sym);
+ StructFieldInfo &StructInfo = Field.Contents.StructInfo;
+
+ StructInfo.Structure = Structure;
+ Field.Type = Structure.Size;
+
+ if (parseStructInstList(Structure, StructInfo.Initializers))
+ return true;
+
+ Field.LengthOf = StructInfo.Initializers.size();
+ Field.SizeOf = Field.Type * Field.LengthOf;
+ if (OwningStruct.IsUnion)
+ OwningStruct.Size = std::max(OwningStruct.Size, Field.SizeOf);
+ else
+ OwningStruct.Size += Field.SizeOf;
+
+ return false;
+}
+
+/// parseDirectiveStructValue
+/// ::= struct-id (<struct-initializer> | {struct-initializer})
+/// [, (<struct-initializer> | {struct-initializer})]*
+bool MasmParser::parseDirectiveStructValue(const StructInfo &Structure,
+ StringRef Directive, SMLoc DirLoc) {
+ if (StructInProgress.empty()) {
+ if (emitStructValues(Structure))
+ return true;
+ } else if (addStructField("", Structure)) {
+ return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
+ }
+
+ return false;
+}
+
+/// parseDirectiveNamedValue
+/// ::= name (byte | word | ... ) [ expression (, expression)* ]
+bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure,
+ StringRef Directive,
+ SMLoc DirLoc, StringRef Name) {
+ if (StructInProgress.empty()) {
+ // Initialize named data value.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ getStreamer().emitLabel(Sym);
unsigned Count;
if (emitStructValues(Structure, &Count))
- return true;
+ return true;
AsmTypeInfo Type;
Type.Name = Structure.Name;
Type.Size = Structure.Size * Count;
Type.ElementSize = Structure.Size;
Type.Length = Count;
KnownType[Name.lower()] = Type;
- } else if (addStructField(Name, Structure)) {
- return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
- }
-
- return false;
-}
-
-/// parseDirectiveStruct
-/// ::= <name> (STRUC | STRUCT | UNION) [fieldAlign] [, NONUNIQUE]
-/// (dataDir | generalDir | offsetDir | nestedStruct)+
-/// <name> ENDS
-////// dataDir = data declaration
-////// offsetDir = EVEN, ORG, ALIGN
-bool MasmParser::parseDirectiveStruct(StringRef Directive,
- DirectiveKind DirKind, StringRef Name,
- SMLoc NameLoc) {
- // We ignore NONUNIQUE; we do not support OPTION M510 or OPTION OLDSTRUCTS
- // anyway, so all field accesses must be qualified.
- AsmToken NextTok = getTok();
- int64_t AlignmentValue = 1;
- if (NextTok.isNot(AsmToken::Comma) &&
- NextTok.isNot(AsmToken::EndOfStatement) &&
- parseAbsoluteExpression(AlignmentValue)) {
- return addErrorSuffix(" in alignment value for '" + Twine(Directive) +
- "' directive");
- }
- if (!isPowerOf2_64(AlignmentValue)) {
- return Error(NextTok.getLoc(), "alignment must be a power of two; was " +
- std::to_string(AlignmentValue));
- }
-
- StringRef Qualifier;
- SMLoc QualifierLoc;
- if (parseOptionalToken(AsmToken::Comma)) {
- QualifierLoc = getTok().getLoc();
- if (parseIdentifier(Qualifier))
- return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
- if (!Qualifier.equals_lower("nonunique"))
- return Error(QualifierLoc, "Unrecognized qualifier for '" +
- Twine(Directive) +
- "' directive; expected none or NONUNIQUE");
- }
-
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
-
- StructInProgress.emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
- return false;
-}
-
-/// parseDirectiveNestedStruct
-/// ::= (STRUC | STRUCT | UNION) [name]
-/// (dataDir | generalDir | offsetDir | nestedStruct)+
-/// ENDS
-bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
- DirectiveKind DirKind) {
- if (StructInProgress.empty())
- return TokError("missing name in top-level '" + Twine(Directive) +
- "' directive");
-
- StringRef Name;
- if (getTok().is(AsmToken::Identifier)) {
- Name = getTok().getIdentifier();
- parseToken(AsmToken::Identifier);
- }
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
-
+ } else if (addStructField(Name, Structure)) {
+ return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
+ }
+
+ return false;
+}
+
+/// parseDirectiveStruct
+/// ::= <name> (STRUC | STRUCT | UNION) [fieldAlign] [, NONUNIQUE]
+/// (dataDir | generalDir | offsetDir | nestedStruct)+
+/// <name> ENDS
+////// dataDir = data declaration
+////// offsetDir = EVEN, ORG, ALIGN
+bool MasmParser::parseDirectiveStruct(StringRef Directive,
+ DirectiveKind DirKind, StringRef Name,
+ SMLoc NameLoc) {
+ // We ignore NONUNIQUE; we do not support OPTION M510 or OPTION OLDSTRUCTS
+ // anyway, so all field accesses must be qualified.
+ AsmToken NextTok = getTok();
+ int64_t AlignmentValue = 1;
+ if (NextTok.isNot(AsmToken::Comma) &&
+ NextTok.isNot(AsmToken::EndOfStatement) &&
+ parseAbsoluteExpression(AlignmentValue)) {
+ return addErrorSuffix(" in alignment value for '" + Twine(Directive) +
+ "' directive");
+ }
+ if (!isPowerOf2_64(AlignmentValue)) {
+ return Error(NextTok.getLoc(), "alignment must be a power of two; was " +
+ std::to_string(AlignmentValue));
+ }
+
+ StringRef Qualifier;
+ SMLoc QualifierLoc;
+ if (parseOptionalToken(AsmToken::Comma)) {
+ QualifierLoc = getTok().getLoc();
+ if (parseIdentifier(Qualifier))
+ return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
+ if (!Qualifier.equals_lower("nonunique"))
+ return Error(QualifierLoc, "Unrecognized qualifier for '" +
+ Twine(Directive) +
+ "' directive; expected none or NONUNIQUE");
+ }
+
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
+
+ StructInProgress.emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
+ return false;
+}
+
+/// parseDirectiveNestedStruct
+/// ::= (STRUC | STRUCT | UNION) [name]
+/// (dataDir | generalDir | offsetDir | nestedStruct)+
+/// ENDS
+bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
+ DirectiveKind DirKind) {
+ if (StructInProgress.empty())
+ return TokError("missing name in top-level '" + Twine(Directive) +
+ "' directive");
+
+ StringRef Name;
+ if (getTok().is(AsmToken::Identifier)) {
+ Name = getTok().getIdentifier();
+ parseToken(AsmToken::Identifier);
+ }
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
+
// Reserve space to ensure Alignment doesn't get invalidated when
// StructInProgress grows.
StructInProgress.reserve(StructInProgress.size() + 1);
- StructInProgress.emplace_back(Name, DirKind == DK_UNION,
- StructInProgress.back().Alignment);
- return false;
-}
-
-bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
- if (StructInProgress.empty())
- return Error(NameLoc, "ENDS directive without matching STRUC/STRUCT/UNION");
- if (StructInProgress.size() > 1)
- return Error(NameLoc, "unexpected name in nested ENDS directive");
- if (StructInProgress.back().Name.compare_lower(Name))
- return Error(NameLoc, "mismatched name in ENDS directive; expected '" +
- StructInProgress.back().Name + "'");
- StructInfo Structure = StructInProgress.pop_back_val();
+ StructInProgress.emplace_back(Name, DirKind == DK_UNION,
+ StructInProgress.back().Alignment);
+ return false;
+}
+
+bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
+ if (StructInProgress.empty())
+ return Error(NameLoc, "ENDS directive without matching STRUC/STRUCT/UNION");
+ if (StructInProgress.size() > 1)
+ return Error(NameLoc, "unexpected name in nested ENDS directive");
+ if (StructInProgress.back().Name.compare_lower(Name))
+ return Error(NameLoc, "mismatched name in ENDS directive; expected '" +
+ StructInProgress.back().Name + "'");
+ StructInfo Structure = StructInProgress.pop_back_val();
// Pad to make the structure's size divisible by the smaller of its alignment
// and the size of its largest field.
Structure.Size = llvm::alignTo(
Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
- Structs[Name.lower()] = Structure;
-
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in ENDS directive");
-
- return false;
-}
-
-bool MasmParser::parseDirectiveNestedEnds() {
- if (StructInProgress.empty())
- return TokError("ENDS directive without matching STRUC/STRUCT/UNION");
- if (StructInProgress.size() == 1)
- return TokError("missing name in top-level ENDS directive");
-
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in nested ENDS directive");
-
- StructInfo Structure = StructInProgress.pop_back_val();
- // Pad to make the structure's size divisible by its alignment.
- Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
-
- StructInfo &ParentStruct = StructInProgress.back();
- if (Structure.Name.empty()) {
- const size_t OldFields = ParentStruct.Fields.size();
- ParentStruct.Fields.insert(
- ParentStruct.Fields.end(),
- std::make_move_iterator(Structure.Fields.begin()),
- std::make_move_iterator(Structure.Fields.end()));
- for (const auto &FieldByName : Structure.FieldsByName) {
- ParentStruct.FieldsByName[FieldByName.getKey()] =
- FieldByName.getValue() + OldFields;
- }
- if (!ParentStruct.IsUnion) {
- for (auto FieldIter = ParentStruct.Fields.begin() + OldFields;
- FieldIter != ParentStruct.Fields.end(); ++FieldIter) {
- FieldIter->Offset += ParentStruct.Size;
- }
- }
-
- if (ParentStruct.IsUnion)
- ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
- else
- ParentStruct.Size += Structure.Size;
- } else {
+ Structs[Name.lower()] = Structure;
+
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in ENDS directive");
+
+ return false;
+}
+
+bool MasmParser::parseDirectiveNestedEnds() {
+ if (StructInProgress.empty())
+ return TokError("ENDS directive without matching STRUC/STRUCT/UNION");
+ if (StructInProgress.size() == 1)
+ return TokError("missing name in top-level ENDS directive");
+
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in nested ENDS directive");
+
+ StructInfo Structure = StructInProgress.pop_back_val();
+ // Pad to make the structure's size divisible by its alignment.
+ Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
+
+ StructInfo &ParentStruct = StructInProgress.back();
+ if (Structure.Name.empty()) {
+ const size_t OldFields = ParentStruct.Fields.size();
+ ParentStruct.Fields.insert(
+ ParentStruct.Fields.end(),
+ std::make_move_iterator(Structure.Fields.begin()),
+ std::make_move_iterator(Structure.Fields.end()));
+ for (const auto &FieldByName : Structure.FieldsByName) {
+ ParentStruct.FieldsByName[FieldByName.getKey()] =
+ FieldByName.getValue() + OldFields;
+ }
+ if (!ParentStruct.IsUnion) {
+ for (auto FieldIter = ParentStruct.Fields.begin() + OldFields;
+ FieldIter != ParentStruct.Fields.end(); ++FieldIter) {
+ FieldIter->Offset += ParentStruct.Size;
+ }
+ }
+
+ if (ParentStruct.IsUnion)
+ ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
+ else
+ ParentStruct.Size += Structure.Size;
+ } else {
FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
Structure.AlignmentSize);
- StructFieldInfo &StructInfo = Field.Contents.StructInfo;
- Field.Type = Structure.Size;
- Field.LengthOf = 1;
- Field.SizeOf = Structure.Size;
-
- if (ParentStruct.IsUnion)
- ParentStruct.Size = std::max(ParentStruct.Size, Field.SizeOf);
- else
- ParentStruct.Size += Field.SizeOf;
-
- StructInfo.Structure = Structure;
- StructInfo.Initializers.emplace_back();
- auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
- for (const auto &SubField : Structure.Fields) {
- FieldInitializers.push_back(SubField.Contents);
- }
- }
-
- return false;
-}
-
-/// parseDirectiveOrg
-/// ::= .org expression [ , expression ]
-bool MasmParser::parseDirectiveOrg() {
- const MCExpr *Offset;
- SMLoc OffsetLoc = Lexer.getLoc();
- if (checkForValidSection() || parseExpression(Offset))
- return true;
-
- // Parse optional fill expression.
- int64_t FillExpr = 0;
- if (parseOptionalToken(AsmToken::Comma))
- if (parseAbsoluteExpression(FillExpr))
- return addErrorSuffix(" in '.org' directive");
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in '.org' directive");
-
- getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
- return false;
-}
-
-/// parseDirectiveAlign
-/// ::= align expression
-bool MasmParser::parseDirectiveAlign() {
- SMLoc AlignmentLoc = getLexer().getLoc();
- int64_t Alignment;
-
- if (checkForValidSection())
- return addErrorSuffix(" in align directive");
- // Ignore empty 'align' directives.
- if (getTok().is(AsmToken::EndOfStatement)) {
- Warning(AlignmentLoc, "align directive with no operand is ignored");
- return parseToken(AsmToken::EndOfStatement);
- }
- if (parseAbsoluteExpression(Alignment) ||
- parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in align directive");
-
- // Always emit an alignment here even if we thrown an error.
- bool ReturnVal = false;
-
- // Reject alignments that aren't either a power of two or zero, for gas
- // compatibility. Alignment of zero is silently rounded up to one.
- if (Alignment == 0)
- Alignment = 1;
- if (!isPowerOf2_64(Alignment))
- ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
-
- // Check whether we should use optimal code alignment for this align
- // directive.
- const MCSection *Section = getStreamer().getCurrentSectionOnly();
- assert(Section && "must have section to emit alignment");
- if (Section->UseCodeAlign()) {
- getStreamer().emitCodeAlignment(Alignment, /*MaxBytesToEmit=*/0);
- } else {
- // FIXME: Target specific behavior about how the "extra" bytes are filled.
- getStreamer().emitValueToAlignment(Alignment, /*Value=*/0, /*ValueSize=*/1,
- /*MaxBytesToEmit=*/0);
- }
-
- return ReturnVal;
-}
-
-/// parseDirectiveFile
-/// ::= .file filename
-/// ::= .file number [directory] filename [md5 checksum] [source source-text]
-bool MasmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
- // FIXME: I'm not sure what this is.
- int64_t FileNumber = -1;
- if (getLexer().is(AsmToken::Integer)) {
- FileNumber = getTok().getIntVal();
- Lex();
-
- if (FileNumber < 0)
- return TokError("negative file number");
- }
-
- std::string Path;
-
- // Usually the directory and filename together, otherwise just the directory.
- // Allow the strings to have escaped octal character sequence.
- if (check(getTok().isNot(AsmToken::String),
- "unexpected token in '.file' directive") ||
- parseEscapedString(Path))
- return true;
-
- StringRef Directory;
- StringRef Filename;
- std::string FilenameData;
- if (getLexer().is(AsmToken::String)) {
- if (check(FileNumber == -1,
- "explicit path specified, but no file number") ||
- parseEscapedString(FilenameData))
- return true;
- Filename = FilenameData;
- Directory = Path;
- } else {
- Filename = Path;
- }
-
- uint64_t MD5Hi, MD5Lo;
- bool HasMD5 = false;
-
- Optional<StringRef> Source;
- bool HasSource = false;
- std::string SourceString;
-
- while (!parseOptionalToken(AsmToken::EndOfStatement)) {
- StringRef Keyword;
- if (check(getTok().isNot(AsmToken::Identifier),
- "unexpected token in '.file' directive") ||
- parseIdentifier(Keyword))
- return true;
- if (Keyword == "md5") {
- HasMD5 = true;
- if (check(FileNumber == -1,
- "MD5 checksum specified, but no file number") ||
- parseHexOcta(*this, MD5Hi, MD5Lo))
- return true;
- } else if (Keyword == "source") {
- HasSource = true;
- if (check(FileNumber == -1,
- "source specified, but no file number") ||
- check(getTok().isNot(AsmToken::String),
- "unexpected token in '.file' directive") ||
- parseEscapedString(SourceString))
- return true;
- } else {
- return TokError("unexpected token in '.file' directive");
- }
- }
-
- if (FileNumber == -1) {
- // Ignore the directive if there is no number and the target doesn't support
- // numberless .file directives. This allows some portability of assembler
- // between different object file formats.
- if (getContext().getAsmInfo()->hasSingleParameterDotFile())
- getStreamer().emitFileDirective(Filename);
- } else {
- // In case there is a -g option as well as debug info from directive .file,
- // we turn off the -g option, directly use the existing debug info instead.
- // Throw away any implicit file table for the assembler source.
- if (Ctx.getGenDwarfForAssembly()) {
- Ctx.getMCDwarfLineTable(0).resetFileTable();
- Ctx.setGenDwarfForAssembly(false);
- }
-
- Optional<MD5::MD5Result> CKMem;
- if (HasMD5) {
- MD5::MD5Result Sum;
- for (unsigned i = 0; i != 8; ++i) {
- Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
- Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
- }
- CKMem = Sum;
- }
- if (HasSource) {
- char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
- memcpy(SourceBuf, SourceString.data(), SourceString.size());
- Source = StringRef(SourceBuf, SourceString.size());
- }
- if (FileNumber == 0) {
- if (Ctx.getDwarfVersion() < 5)
- return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5");
- getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
- } else {
- Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
- FileNumber, Directory, Filename, CKMem, Source);
- if (!FileNumOrErr)
- return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
- }
- // Alert the user if there are some .file directives with MD5 and some not.
- // But only do that once.
- if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
- ReportedInconsistentMD5 = true;
- return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
- }
- }
-
- return false;
-}
-
-/// parseDirectiveLine
-/// ::= .line [number]
-bool MasmParser::parseDirectiveLine() {
- int64_t LineNumber;
- if (getLexer().is(AsmToken::Integer)) {
- if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
- return true;
- (void)LineNumber;
- // FIXME: Do something with the .line.
- }
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.line' directive"))
- return true;
-
- return false;
-}
-
-/// parseDirectiveLoc
-/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
-/// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
-/// The first number is a file number, must have been previously assigned with
-/// a .file directive, the second number is the line number and optionally the
-/// third number is a column position (zero if not specified). The remaining
-/// optional items are .loc sub-directives.
-bool MasmParser::parseDirectiveLoc() {
- int64_t FileNumber = 0, LineNumber = 0;
- SMLoc Loc = getTok().getLoc();
- if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
- check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
- "file number less than one in '.loc' directive") ||
- check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
- "unassigned file number in '.loc' directive"))
- return true;
-
- // optional
- if (getLexer().is(AsmToken::Integer)) {
- LineNumber = getTok().getIntVal();
- if (LineNumber < 0)
- return TokError("line number less than zero in '.loc' directive");
- Lex();
- }
-
- int64_t ColumnPos = 0;
- if (getLexer().is(AsmToken::Integer)) {
- ColumnPos = getTok().getIntVal();
- if (ColumnPos < 0)
- return TokError("column position less than zero in '.loc' directive");
- Lex();
- }
-
- auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
- unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
- unsigned Isa = 0;
- int64_t Discriminator = 0;
-
- 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, "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;
- } else {
- return Error(Loc, "unknown sub-directive in '.loc' directive");
- }
- return false;
- };
-
- if (parseMany(parseLocOp, false /*hasComma*/))
- return true;
-
- getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
- Isa, Discriminator, StringRef());
-
- return false;
-}
-
-/// parseDirectiveStabs
-/// ::= .stabs string, number, number, number
-bool MasmParser::parseDirectiveStabs() {
- return TokError("unsupported directive '.stabs'");
-}
-
-/// parseDirectiveCVFile
-/// ::= .cv_file number filename [checksum] [checksumkind]
-bool MasmParser::parseDirectiveCVFile() {
- SMLoc FileNumberLoc = getTok().getLoc();
- int64_t FileNumber;
- std::string Filename;
- std::string Checksum;
- int64_t ChecksumKind = 0;
-
- if (parseIntToken(FileNumber,
- "expected file number in '.cv_file' directive") ||
- check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
- check(getTok().isNot(AsmToken::String),
- "unexpected token in '.cv_file' directive") ||
- parseEscapedString(Filename))
- return true;
- if (!parseOptionalToken(AsmToken::EndOfStatement)) {
- if (check(getTok().isNot(AsmToken::String),
- "unexpected token in '.cv_file' directive") ||
- parseEscapedString(Checksum) ||
- parseIntToken(ChecksumKind,
- "expected checksum kind in '.cv_file' directive") ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.cv_file' directive"))
- return true;
- }
-
- Checksum = fromHex(Checksum);
- void *CKMem = Ctx.allocate(Checksum.size(), 1);
- memcpy(CKMem, Checksum.data(), Checksum.size());
- ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
- Checksum.size());
-
- if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
- static_cast<uint8_t>(ChecksumKind)))
- return Error(FileNumberLoc, "file number already allocated");
-
- return false;
-}
-
-bool MasmParser::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 MasmParser::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 MasmParser::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 MasmParser::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;
-}
-
-/// parseDirectiveCVLoc
-/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
-/// [is_stmt VALUE]
-/// The first number is a file number, must have been previously assigned with
-/// a .file directive, the second number is the line number and optionally the
-/// third number is a column position (zero if not specified). The remaining
-/// optional items are .loc sub-directives.
-bool MasmParser::parseDirectiveCVLoc() {
- SMLoc DirectiveLoc = getTok().getLoc();
- int64_t FunctionId, FileNumber;
- if (parseCVFunctionId(FunctionId, ".cv_loc") ||
- parseCVFileId(FileNumber, ".cv_loc"))
- return true;
-
- int64_t LineNumber = 0;
- if (getLexer().is(AsmToken::Integer)) {
- LineNumber = getTok().getIntVal();
- if (LineNumber < 0)
- return TokError("line number less than zero in '.cv_loc' directive");
- Lex();
- }
-
- int64_t ColumnPos = 0;
- if (getLexer().is(AsmToken::Integer)) {
- ColumnPos = getTok().getIntVal();
- if (ColumnPos < 0)
- return TokError("column position less than zero in '.cv_loc' directive");
- Lex();
- }
-
- bool PrologueEnd = false;
- uint64_t IsStmt = 0;
-
- 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") {
- Loc = getTok().getLoc();
- const MCExpr *Value;
- if (parseExpression(Value))
- return true;
- // The expression must be the constant 0 or 1.
- IsStmt = ~0ULL;
- if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
- IsStmt = MCE->getValue();
-
- if (IsStmt > 1)
- return Error(Loc, "is_stmt value not 0 or 1");
- } else {
- return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
- }
- return false;
- };
-
- if (parseMany(parseOp, false /*hasComma*/))
- return true;
-
- getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
- ColumnPos, PrologueEnd, IsStmt, StringRef(),
- DirectiveLoc);
- return false;
-}
-
-/// parseDirectiveCVLinetable
-/// ::= .cv_linetable FunctionId, FnStart, FnEnd
-bool MasmParser::parseDirectiveCVLinetable() {
- int64_t FunctionId;
- StringRef FnStartName, FnEndName;
- SMLoc Loc = getTok().getLoc();
- if (parseCVFunctionId(FunctionId, ".cv_linetable") ||
- parseToken(AsmToken::Comma,
- "unexpected token in '.cv_linetable' directive") ||
- parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
- "expected identifier in directive") ||
- parseToken(AsmToken::Comma,
- "unexpected token in '.cv_linetable' directive") ||
- parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
- "expected identifier in directive"))
- return true;
-
- MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
- MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
-
- getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
- return false;
-}
-
-/// parseDirectiveCVInlineLinetable
-/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
-bool MasmParser::parseDirectiveCVInlineLinetable() {
- int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
- StringRef FnStartName, FnEndName;
- SMLoc Loc = getTok().getLoc();
- 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") ||
- 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") ||
- parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
- "expected identifier in directive") ||
- parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
- "expected identifier in directive"))
- return true;
-
- if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
- return true;
-
- MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
- MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
- getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
- SourceLineNum, FnStartSym,
- FnEndSym);
- return false;
-}
-
-void MasmParser::initializeCVDefRangeTypeMap() {
- CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
- CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
- CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
- CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
-}
-
-/// parseDirectiveCVDefRange
-/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
-bool MasmParser::parseDirectiveCVDefRange() {
- SMLoc Loc;
- std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
- while (getLexer().is(AsmToken::Identifier)) {
- Loc = getLexer().getLoc();
- StringRef GapStartName;
- if (parseIdentifier(GapStartName))
- return Error(Loc, "expected identifier in directive");
- MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
-
- Loc = getLexer().getLoc();
- StringRef GapEndName;
- if (parseIdentifier(GapEndName))
- return Error(Loc, "expected identifier in directive");
- MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
-
- Ranges.push_back({GapStartSym, GapEndSym});
- }
-
- StringRef CVDefRangeTypeStr;
- if (parseToken(
- AsmToken::Comma,
- "expected comma before def_range type in .cv_def_range directive") ||
- parseIdentifier(CVDefRangeTypeStr))
- return Error(Loc, "expected def_range type in directive");
-
- StringMap<CVDefRangeType>::const_iterator CVTypeIt =
- CVDefRangeTypeMap.find(CVDefRangeTypeStr);
- CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
- ? CVDR_DEFRANGE
- : CVTypeIt->getValue();
- switch (CVDRType) {
- case CVDR_DEFRANGE_REGISTER: {
- int64_t DRRegister;
- if (parseToken(AsmToken::Comma, "expected comma before register number in "
- ".cv_def_range directive") ||
- parseAbsoluteExpression(DRRegister))
- return Error(Loc, "expected register number");
-
- codeview::DefRangeRegisterHeader DRHdr;
- DRHdr.Register = DRRegister;
- DRHdr.MayHaveNoName = 0;
- getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
- break;
- }
- case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
- int64_t DROffset;
- if (parseToken(AsmToken::Comma,
- "expected comma before offset in .cv_def_range directive") ||
- parseAbsoluteExpression(DROffset))
- return Error(Loc, "expected offset value");
-
- codeview::DefRangeFramePointerRelHeader DRHdr;
- DRHdr.Offset = DROffset;
- getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
- break;
- }
- case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
- int64_t DRRegister;
- int64_t DROffsetInParent;
- if (parseToken(AsmToken::Comma, "expected comma before register number in "
- ".cv_def_range directive") ||
- parseAbsoluteExpression(DRRegister))
- return Error(Loc, "expected register number");
- if (parseToken(AsmToken::Comma,
- "expected comma before offset in .cv_def_range directive") ||
- parseAbsoluteExpression(DROffsetInParent))
- return Error(Loc, "expected offset value");
-
- codeview::DefRangeSubfieldRegisterHeader DRHdr;
- DRHdr.Register = DRRegister;
- DRHdr.MayHaveNoName = 0;
- DRHdr.OffsetInParent = DROffsetInParent;
- getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
- break;
- }
- case CVDR_DEFRANGE_REGISTER_REL: {
- int64_t DRRegister;
- int64_t DRFlags;
- int64_t DRBasePointerOffset;
- if (parseToken(AsmToken::Comma, "expected comma before register number in "
- ".cv_def_range directive") ||
- parseAbsoluteExpression(DRRegister))
- return Error(Loc, "expected register value");
- if (parseToken(
- AsmToken::Comma,
- "expected comma before flag value in .cv_def_range directive") ||
- parseAbsoluteExpression(DRFlags))
- return Error(Loc, "expected flag value");
- if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
- "in .cv_def_range directive") ||
- parseAbsoluteExpression(DRBasePointerOffset))
- return Error(Loc, "expected base pointer offset value");
-
- codeview::DefRangeRegisterRelHeader DRHdr;
- DRHdr.Register = DRRegister;
- DRHdr.Flags = DRFlags;
- DRHdr.BasePointerOffset = DRBasePointerOffset;
- getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
- break;
- }
- default:
- return Error(Loc, "unexpected def_range type in .cv_def_range directive");
- }
- return true;
-}
-
-/// parseDirectiveCVString
-/// ::= .cv_stringtable "string"
-bool MasmParser::parseDirectiveCVString() {
- std::string Data;
- if (checkForValidSection() || parseEscapedString(Data))
- return addErrorSuffix(" in '.cv_string' directive");
-
- // Put the string in the table and emit the offset.
- std::pair<StringRef, unsigned> Insertion =
- getCVContext().addToStringTable(Data);
- getStreamer().emitIntValue(Insertion.second, 4);
- return false;
-}
-
-/// parseDirectiveCVStringTable
-/// ::= .cv_stringtable
-bool MasmParser::parseDirectiveCVStringTable() {
- getStreamer().emitCVStringTableDirective();
- return false;
-}
-
-/// parseDirectiveCVFileChecksums
-/// ::= .cv_filechecksums
-bool MasmParser::parseDirectiveCVFileChecksums() {
- getStreamer().emitCVFileChecksumsDirective();
- return false;
-}
-
-/// parseDirectiveCVFileChecksumOffset
-/// ::= .cv_filechecksumoffset fileno
-bool MasmParser::parseDirectiveCVFileChecksumOffset() {
- int64_t FileNo;
- if (parseIntToken(FileNo, "expected identifier in directive"))
- return true;
- if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
- return true;
- getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
- return false;
-}
-
-/// parseDirectiveCVFPOData
-/// ::= .cv_fpo_data procsym
-bool MasmParser::parseDirectiveCVFPOData() {
- SMLoc DirLoc = getLexer().getLoc();
- StringRef ProcName;
- if (parseIdentifier(ProcName))
- return TokError("expected symbol name");
- if (parseEOL("unexpected tokens"))
- return addErrorSuffix(" in '.cv_fpo_data' directive");
- MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
- getStreamer().EmitCVFPOData(ProcSym, DirLoc);
- return false;
-}
-
-/// parseDirectiveCFISections
-/// ::= .cfi_sections section [, section]
-bool MasmParser::parseDirectiveCFISections() {
- StringRef Name;
- bool EH = false;
- bool Debug = false;
-
- if (parseIdentifier(Name))
- return TokError("Expected an identifier");
-
- if (Name == ".eh_frame")
- EH = true;
- else if (Name == ".debug_frame")
- Debug = true;
-
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
-
- if (parseIdentifier(Name))
- return TokError("Expected an identifier");
-
- if (Name == ".eh_frame")
- EH = true;
- else if (Name == ".debug_frame")
- Debug = true;
- }
-
- getStreamer().emitCFISections(EH, Debug);
- return false;
-}
-
-/// parseDirectiveCFIStartProc
-/// ::= .cfi_startproc [simple]
-bool MasmParser::parseDirectiveCFIStartProc() {
- StringRef Simple;
- if (!parseOptionalToken(AsmToken::EndOfStatement)) {
- if (check(parseIdentifier(Simple) || Simple != "simple",
- "unexpected token") ||
- parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in '.cfi_startproc' directive");
- }
-
- // TODO(kristina): Deal with a corner case of incorrect diagnostic context
- // being produced if this directive is emitted as part of preprocessor macro
- // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
- // Tools like llvm-mc on the other hand are not affected by it, and report
- // correct context information.
- getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
- return false;
-}
-
-/// parseDirectiveCFIEndProc
-/// ::= .cfi_endproc
-bool MasmParser::parseDirectiveCFIEndProc() {
- getStreamer().emitCFIEndProc();
- return false;
-}
-
-/// parse register name or number.
-bool MasmParser::parseRegisterOrRegisterNumber(int64_t &Register,
- SMLoc DirectiveLoc) {
- unsigned RegNo;
-
- if (getLexer().isNot(AsmToken::Integer)) {
- if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc))
- return true;
- Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
- } else
- return parseAbsoluteExpression(Register);
-
- return false;
-}
-
-/// parseDirectiveCFIDefCfa
-/// ::= .cfi_def_cfa register, offset
-bool MasmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
- int64_t Register = 0, Offset = 0;
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseAbsoluteExpression(Offset))
- return true;
-
- getStreamer().emitCFIDefCfa(Register, Offset);
- return false;
-}
-
-/// parseDirectiveCFIDefCfaOffset
-/// ::= .cfi_def_cfa_offset offset
-bool MasmParser::parseDirectiveCFIDefCfaOffset() {
- int64_t Offset = 0;
- if (parseAbsoluteExpression(Offset))
- return true;
-
- getStreamer().emitCFIDefCfaOffset(Offset);
- return false;
-}
-
-/// parseDirectiveCFIRegister
-/// ::= .cfi_register register, register
-bool MasmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
- int64_t Register1 = 0, Register2 = 0;
- if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseRegisterOrRegisterNumber(Register2, DirectiveLoc))
- return true;
-
- getStreamer().emitCFIRegister(Register1, Register2);
- return false;
-}
-
-/// parseDirectiveCFIWindowSave
-/// ::= .cfi_window_save
-bool MasmParser::parseDirectiveCFIWindowSave() {
- getStreamer().emitCFIWindowSave();
- return false;
-}
-
-/// parseDirectiveCFIAdjustCfaOffset
-/// ::= .cfi_adjust_cfa_offset adjustment
-bool MasmParser::parseDirectiveCFIAdjustCfaOffset() {
- int64_t Adjustment = 0;
- if (parseAbsoluteExpression(Adjustment))
- return true;
-
- getStreamer().emitCFIAdjustCfaOffset(Adjustment);
- return false;
-}
-
-/// parseDirectiveCFIDefCfaRegister
-/// ::= .cfi_def_cfa_register register
-bool MasmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
- int64_t Register = 0;
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
-
- getStreamer().emitCFIDefCfaRegister(Register);
- return false;
-}
-
-/// parseDirectiveCFIOffset
-/// ::= .cfi_offset register, offset
-bool MasmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
- int64_t Register = 0;
- int64_t Offset = 0;
-
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseAbsoluteExpression(Offset))
- return true;
-
- getStreamer().emitCFIOffset(Register, Offset);
- return false;
-}
-
-/// parseDirectiveCFIRelOffset
-/// ::= .cfi_rel_offset register, offset
-bool MasmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
- int64_t Register = 0, Offset = 0;
-
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseAbsoluteExpression(Offset))
- return true;
-
- getStreamer().emitCFIRelOffset(Register, Offset);
- return false;
-}
-
-static bool isValidEncoding(int64_t Encoding) {
- if (Encoding & ~0xff)
- return false;
-
- if (Encoding == dwarf::DW_EH_PE_omit)
- return true;
-
- const unsigned Format = Encoding & 0xf;
- if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
- Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
- Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
- Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
- return false;
-
- const unsigned Application = Encoding & 0x70;
- if (Application != dwarf::DW_EH_PE_absptr &&
- Application != dwarf::DW_EH_PE_pcrel)
- return false;
-
- return true;
-}
-
-/// parseDirectiveCFIPersonalityOrLsda
-/// IsPersonality true for cfi_personality, false for cfi_lsda
-/// ::= .cfi_personality encoding, [symbol_name]
-/// ::= .cfi_lsda encoding, [symbol_name]
-bool MasmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
- int64_t Encoding = 0;
- if (parseAbsoluteExpression(Encoding))
- return true;
- if (Encoding == dwarf::DW_EH_PE_omit)
- return false;
-
- StringRef Name;
- if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- check(parseIdentifier(Name), "expected identifier in directive"))
- return true;
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (IsPersonality)
- getStreamer().emitCFIPersonality(Sym, Encoding);
- else
- getStreamer().emitCFILsda(Sym, Encoding);
- return false;
-}
-
-/// parseDirectiveCFIRememberState
-/// ::= .cfi_remember_state
-bool MasmParser::parseDirectiveCFIRememberState() {
- getStreamer().emitCFIRememberState();
- return false;
-}
-
-/// parseDirectiveCFIRestoreState
-/// ::= .cfi_remember_state
-bool MasmParser::parseDirectiveCFIRestoreState() {
- getStreamer().emitCFIRestoreState();
- return false;
-}
-
-/// parseDirectiveCFISameValue
-/// ::= .cfi_same_value register
-bool MasmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
- int64_t Register = 0;
-
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
-
- getStreamer().emitCFISameValue(Register);
- return false;
-}
-
-/// parseDirectiveCFIRestore
-/// ::= .cfi_restore register
-bool MasmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
- int64_t Register = 0;
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
-
- getStreamer().emitCFIRestore(Register);
- return false;
-}
-
-/// parseDirectiveCFIEscape
-/// ::= .cfi_escape expression[,...]
-bool MasmParser::parseDirectiveCFIEscape() {
- std::string Values;
- int64_t CurrValue;
- if (parseAbsoluteExpression(CurrValue))
- return true;
-
- Values.push_back((uint8_t)CurrValue);
-
- while (getLexer().is(AsmToken::Comma)) {
- Lex();
-
- if (parseAbsoluteExpression(CurrValue))
- return true;
-
- Values.push_back((uint8_t)CurrValue);
- }
-
- getStreamer().emitCFIEscape(Values);
- return false;
-}
-
-/// parseDirectiveCFIReturnColumn
-/// ::= .cfi_return_column register
-bool MasmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
- int64_t Register = 0;
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
- getStreamer().emitCFIReturnColumn(Register);
- return false;
-}
-
-/// parseDirectiveCFISignalFrame
-/// ::= .cfi_signal_frame
-bool MasmParser::parseDirectiveCFISignalFrame() {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.cfi_signal_frame'"))
- return true;
-
- getStreamer().emitCFISignalFrame();
- return false;
-}
-
-/// parseDirectiveCFIUndefined
-/// ::= .cfi_undefined register
-bool MasmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
- int64_t Register = 0;
-
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
-
- getStreamer().emitCFIUndefined(Register);
- return false;
-}
-
-/// parseDirectiveMacro
+ StructFieldInfo &StructInfo = Field.Contents.StructInfo;
+ Field.Type = Structure.Size;
+ Field.LengthOf = 1;
+ Field.SizeOf = Structure.Size;
+
+ if (ParentStruct.IsUnion)
+ ParentStruct.Size = std::max(ParentStruct.Size, Field.SizeOf);
+ else
+ ParentStruct.Size += Field.SizeOf;
+
+ StructInfo.Structure = Structure;
+ StructInfo.Initializers.emplace_back();
+ auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
+ for (const auto &SubField : Structure.Fields) {
+ FieldInitializers.push_back(SubField.Contents);
+ }
+ }
+
+ return false;
+}
+
+/// parseDirectiveOrg
+/// ::= .org expression [ , expression ]
+bool MasmParser::parseDirectiveOrg() {
+ const MCExpr *Offset;
+ SMLoc OffsetLoc = Lexer.getLoc();
+ if (checkForValidSection() || parseExpression(Offset))
+ return true;
+
+ // Parse optional fill expression.
+ int64_t FillExpr = 0;
+ if (parseOptionalToken(AsmToken::Comma))
+ if (parseAbsoluteExpression(FillExpr))
+ return addErrorSuffix(" in '.org' directive");
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '.org' directive");
+
+ getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
+ return false;
+}
+
+/// parseDirectiveAlign
+/// ::= align expression
+bool MasmParser::parseDirectiveAlign() {
+ SMLoc AlignmentLoc = getLexer().getLoc();
+ int64_t Alignment;
+
+ if (checkForValidSection())
+ return addErrorSuffix(" in align directive");
+ // Ignore empty 'align' directives.
+ if (getTok().is(AsmToken::EndOfStatement)) {
+ Warning(AlignmentLoc, "align directive with no operand is ignored");
+ return parseToken(AsmToken::EndOfStatement);
+ }
+ if (parseAbsoluteExpression(Alignment) ||
+ parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in align directive");
+
+ // Always emit an alignment here even if we thrown an error.
+ bool ReturnVal = false;
+
+ // Reject alignments that aren't either a power of two or zero, for gas
+ // compatibility. Alignment of zero is silently rounded up to one.
+ if (Alignment == 0)
+ Alignment = 1;
+ if (!isPowerOf2_64(Alignment))
+ ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
+
+ // Check whether we should use optimal code alignment for this align
+ // directive.
+ const MCSection *Section = getStreamer().getCurrentSectionOnly();
+ assert(Section && "must have section to emit alignment");
+ if (Section->UseCodeAlign()) {
+ getStreamer().emitCodeAlignment(Alignment, /*MaxBytesToEmit=*/0);
+ } else {
+ // FIXME: Target specific behavior about how the "extra" bytes are filled.
+ getStreamer().emitValueToAlignment(Alignment, /*Value=*/0, /*ValueSize=*/1,
+ /*MaxBytesToEmit=*/0);
+ }
+
+ return ReturnVal;
+}
+
+/// parseDirectiveFile
+/// ::= .file filename
+/// ::= .file number [directory] filename [md5 checksum] [source source-text]
+bool MasmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
+ // FIXME: I'm not sure what this is.
+ int64_t FileNumber = -1;
+ if (getLexer().is(AsmToken::Integer)) {
+ FileNumber = getTok().getIntVal();
+ Lex();
+
+ if (FileNumber < 0)
+ return TokError("negative file number");
+ }
+
+ std::string Path;
+
+ // Usually the directory and filename together, otherwise just the directory.
+ // Allow the strings to have escaped octal character sequence.
+ if (check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.file' directive") ||
+ parseEscapedString(Path))
+ return true;
+
+ StringRef Directory;
+ StringRef Filename;
+ std::string FilenameData;
+ if (getLexer().is(AsmToken::String)) {
+ if (check(FileNumber == -1,
+ "explicit path specified, but no file number") ||
+ parseEscapedString(FilenameData))
+ return true;
+ Filename = FilenameData;
+ Directory = Path;
+ } else {
+ Filename = Path;
+ }
+
+ uint64_t MD5Hi, MD5Lo;
+ bool HasMD5 = false;
+
+ Optional<StringRef> Source;
+ bool HasSource = false;
+ std::string SourceString;
+
+ while (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ StringRef Keyword;
+ if (check(getTok().isNot(AsmToken::Identifier),
+ "unexpected token in '.file' directive") ||
+ parseIdentifier(Keyword))
+ return true;
+ if (Keyword == "md5") {
+ HasMD5 = true;
+ if (check(FileNumber == -1,
+ "MD5 checksum specified, but no file number") ||
+ parseHexOcta(*this, MD5Hi, MD5Lo))
+ return true;
+ } else if (Keyword == "source") {
+ HasSource = true;
+ if (check(FileNumber == -1,
+ "source specified, but no file number") ||
+ check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.file' directive") ||
+ parseEscapedString(SourceString))
+ return true;
+ } else {
+ return TokError("unexpected token in '.file' directive");
+ }
+ }
+
+ if (FileNumber == -1) {
+ // Ignore the directive if there is no number and the target doesn't support
+ // numberless .file directives. This allows some portability of assembler
+ // between different object file formats.
+ if (getContext().getAsmInfo()->hasSingleParameterDotFile())
+ getStreamer().emitFileDirective(Filename);
+ } else {
+ // In case there is a -g option as well as debug info from directive .file,
+ // we turn off the -g option, directly use the existing debug info instead.
+ // Throw away any implicit file table for the assembler source.
+ if (Ctx.getGenDwarfForAssembly()) {
+ Ctx.getMCDwarfLineTable(0).resetFileTable();
+ Ctx.setGenDwarfForAssembly(false);
+ }
+
+ Optional<MD5::MD5Result> CKMem;
+ if (HasMD5) {
+ MD5::MD5Result Sum;
+ for (unsigned i = 0; i != 8; ++i) {
+ Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
+ Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
+ }
+ CKMem = Sum;
+ }
+ if (HasSource) {
+ char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
+ memcpy(SourceBuf, SourceString.data(), SourceString.size());
+ Source = StringRef(SourceBuf, SourceString.size());
+ }
+ if (FileNumber == 0) {
+ if (Ctx.getDwarfVersion() < 5)
+ return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5");
+ getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
+ } else {
+ Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
+ FileNumber, Directory, Filename, CKMem, Source);
+ if (!FileNumOrErr)
+ return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
+ }
+ // Alert the user if there are some .file directives with MD5 and some not.
+ // But only do that once.
+ if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
+ ReportedInconsistentMD5 = true;
+ return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
+ }
+ }
+
+ return false;
+}
+
+/// parseDirectiveLine
+/// ::= .line [number]
+bool MasmParser::parseDirectiveLine() {
+ int64_t LineNumber;
+ if (getLexer().is(AsmToken::Integer)) {
+ if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
+ return true;
+ (void)LineNumber;
+ // FIXME: Do something with the .line.
+ }
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.line' directive"))
+ return true;
+
+ return false;
+}
+
+/// parseDirectiveLoc
+/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
+/// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
+/// The first number is a file number, must have been previously assigned with
+/// a .file directive, the second number is the line number and optionally the
+/// third number is a column position (zero if not specified). The remaining
+/// optional items are .loc sub-directives.
+bool MasmParser::parseDirectiveLoc() {
+ int64_t FileNumber = 0, LineNumber = 0;
+ SMLoc Loc = getTok().getLoc();
+ if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
+ check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
+ "file number less than one in '.loc' directive") ||
+ check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
+ "unassigned file number in '.loc' directive"))
+ return true;
+
+ // optional
+ if (getLexer().is(AsmToken::Integer)) {
+ LineNumber = getTok().getIntVal();
+ if (LineNumber < 0)
+ return TokError("line number less than zero in '.loc' directive");
+ Lex();
+ }
+
+ int64_t ColumnPos = 0;
+ if (getLexer().is(AsmToken::Integer)) {
+ ColumnPos = getTok().getIntVal();
+ if (ColumnPos < 0)
+ return TokError("column position less than zero in '.loc' directive");
+ Lex();
+ }
+
+ auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
+ unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
+ unsigned Isa = 0;
+ int64_t Discriminator = 0;
+
+ 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, "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;
+ } else {
+ return Error(Loc, "unknown sub-directive in '.loc' directive");
+ }
+ return false;
+ };
+
+ if (parseMany(parseLocOp, false /*hasComma*/))
+ return true;
+
+ getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
+ Isa, Discriminator, StringRef());
+
+ return false;
+}
+
+/// parseDirectiveStabs
+/// ::= .stabs string, number, number, number
+bool MasmParser::parseDirectiveStabs() {
+ return TokError("unsupported directive '.stabs'");
+}
+
+/// parseDirectiveCVFile
+/// ::= .cv_file number filename [checksum] [checksumkind]
+bool MasmParser::parseDirectiveCVFile() {
+ SMLoc FileNumberLoc = getTok().getLoc();
+ int64_t FileNumber;
+ std::string Filename;
+ std::string Checksum;
+ int64_t ChecksumKind = 0;
+
+ if (parseIntToken(FileNumber,
+ "expected file number in '.cv_file' directive") ||
+ check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
+ check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.cv_file' directive") ||
+ parseEscapedString(Filename))
+ return true;
+ if (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ if (check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.cv_file' directive") ||
+ parseEscapedString(Checksum) ||
+ parseIntToken(ChecksumKind,
+ "expected checksum kind in '.cv_file' directive") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cv_file' directive"))
+ return true;
+ }
+
+ Checksum = fromHex(Checksum);
+ void *CKMem = Ctx.allocate(Checksum.size(), 1);
+ memcpy(CKMem, Checksum.data(), Checksum.size());
+ ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
+ Checksum.size());
+
+ if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
+ static_cast<uint8_t>(ChecksumKind)))
+ return Error(FileNumberLoc, "file number already allocated");
+
+ return false;
+}
+
+bool MasmParser::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 MasmParser::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 MasmParser::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 MasmParser::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;
+}
+
+/// parseDirectiveCVLoc
+/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
+/// [is_stmt VALUE]
+/// The first number is a file number, must have been previously assigned with
+/// a .file directive, the second number is the line number and optionally the
+/// third number is a column position (zero if not specified). The remaining
+/// optional items are .loc sub-directives.
+bool MasmParser::parseDirectiveCVLoc() {
+ SMLoc DirectiveLoc = getTok().getLoc();
+ int64_t FunctionId, FileNumber;
+ if (parseCVFunctionId(FunctionId, ".cv_loc") ||
+ parseCVFileId(FileNumber, ".cv_loc"))
+ return true;
+
+ int64_t LineNumber = 0;
+ if (getLexer().is(AsmToken::Integer)) {
+ LineNumber = getTok().getIntVal();
+ if (LineNumber < 0)
+ return TokError("line number less than zero in '.cv_loc' directive");
+ Lex();
+ }
+
+ int64_t ColumnPos = 0;
+ if (getLexer().is(AsmToken::Integer)) {
+ ColumnPos = getTok().getIntVal();
+ if (ColumnPos < 0)
+ return TokError("column position less than zero in '.cv_loc' directive");
+ Lex();
+ }
+
+ bool PrologueEnd = false;
+ uint64_t IsStmt = 0;
+
+ 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") {
+ Loc = getTok().getLoc();
+ const MCExpr *Value;
+ if (parseExpression(Value))
+ return true;
+ // The expression must be the constant 0 or 1.
+ IsStmt = ~0ULL;
+ if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
+ IsStmt = MCE->getValue();
+
+ if (IsStmt > 1)
+ return Error(Loc, "is_stmt value not 0 or 1");
+ } else {
+ return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
+ }
+ return false;
+ };
+
+ if (parseMany(parseOp, false /*hasComma*/))
+ return true;
+
+ getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
+ ColumnPos, PrologueEnd, IsStmt, StringRef(),
+ DirectiveLoc);
+ return false;
+}
+
+/// parseDirectiveCVLinetable
+/// ::= .cv_linetable FunctionId, FnStart, FnEnd
+bool MasmParser::parseDirectiveCVLinetable() {
+ int64_t FunctionId;
+ StringRef FnStartName, FnEndName;
+ SMLoc Loc = getTok().getLoc();
+ if (parseCVFunctionId(FunctionId, ".cv_linetable") ||
+ parseToken(AsmToken::Comma,
+ "unexpected token in '.cv_linetable' directive") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
+ "expected identifier in directive") ||
+ parseToken(AsmToken::Comma,
+ "unexpected token in '.cv_linetable' directive") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
+ "expected identifier in directive"))
+ return true;
+
+ MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
+ MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
+
+ getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
+ return false;
+}
+
+/// parseDirectiveCVInlineLinetable
+/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
+bool MasmParser::parseDirectiveCVInlineLinetable() {
+ int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
+ StringRef FnStartName, FnEndName;
+ SMLoc Loc = getTok().getLoc();
+ 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") ||
+ 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") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
+ "expected identifier in directive") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
+ "expected identifier in directive"))
+ return true;
+
+ if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
+ return true;
+
+ MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
+ MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
+ getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
+ SourceLineNum, FnStartSym,
+ FnEndSym);
+ return false;
+}
+
+void MasmParser::initializeCVDefRangeTypeMap() {
+ CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
+ CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
+ CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
+ CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
+}
+
+/// parseDirectiveCVDefRange
+/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
+bool MasmParser::parseDirectiveCVDefRange() {
+ SMLoc Loc;
+ std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
+ while (getLexer().is(AsmToken::Identifier)) {
+ Loc = getLexer().getLoc();
+ StringRef GapStartName;
+ if (parseIdentifier(GapStartName))
+ return Error(Loc, "expected identifier in directive");
+ MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
+
+ Loc = getLexer().getLoc();
+ StringRef GapEndName;
+ if (parseIdentifier(GapEndName))
+ return Error(Loc, "expected identifier in directive");
+ MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
+
+ Ranges.push_back({GapStartSym, GapEndSym});
+ }
+
+ StringRef CVDefRangeTypeStr;
+ if (parseToken(
+ AsmToken::Comma,
+ "expected comma before def_range type in .cv_def_range directive") ||
+ parseIdentifier(CVDefRangeTypeStr))
+ return Error(Loc, "expected def_range type in directive");
+
+ StringMap<CVDefRangeType>::const_iterator CVTypeIt =
+ CVDefRangeTypeMap.find(CVDefRangeTypeStr);
+ CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
+ ? CVDR_DEFRANGE
+ : CVTypeIt->getValue();
+ switch (CVDRType) {
+ case CVDR_DEFRANGE_REGISTER: {
+ int64_t DRRegister;
+ if (parseToken(AsmToken::Comma, "expected comma before register number in "
+ ".cv_def_range directive") ||
+ parseAbsoluteExpression(DRRegister))
+ return Error(Loc, "expected register number");
+
+ codeview::DefRangeRegisterHeader DRHdr;
+ DRHdr.Register = DRRegister;
+ DRHdr.MayHaveNoName = 0;
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
+ int64_t DROffset;
+ if (parseToken(AsmToken::Comma,
+ "expected comma before offset in .cv_def_range directive") ||
+ parseAbsoluteExpression(DROffset))
+ return Error(Loc, "expected offset value");
+
+ codeview::DefRangeFramePointerRelHeader DRHdr;
+ DRHdr.Offset = DROffset;
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
+ int64_t DRRegister;
+ int64_t DROffsetInParent;
+ if (parseToken(AsmToken::Comma, "expected comma before register number in "
+ ".cv_def_range directive") ||
+ parseAbsoluteExpression(DRRegister))
+ return Error(Loc, "expected register number");
+ if (parseToken(AsmToken::Comma,
+ "expected comma before offset in .cv_def_range directive") ||
+ parseAbsoluteExpression(DROffsetInParent))
+ return Error(Loc, "expected offset value");
+
+ codeview::DefRangeSubfieldRegisterHeader DRHdr;
+ DRHdr.Register = DRRegister;
+ DRHdr.MayHaveNoName = 0;
+ DRHdr.OffsetInParent = DROffsetInParent;
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ case CVDR_DEFRANGE_REGISTER_REL: {
+ int64_t DRRegister;
+ int64_t DRFlags;
+ int64_t DRBasePointerOffset;
+ if (parseToken(AsmToken::Comma, "expected comma before register number in "
+ ".cv_def_range directive") ||
+ parseAbsoluteExpression(DRRegister))
+ return Error(Loc, "expected register value");
+ if (parseToken(
+ AsmToken::Comma,
+ "expected comma before flag value in .cv_def_range directive") ||
+ parseAbsoluteExpression(DRFlags))
+ return Error(Loc, "expected flag value");
+ if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
+ "in .cv_def_range directive") ||
+ parseAbsoluteExpression(DRBasePointerOffset))
+ return Error(Loc, "expected base pointer offset value");
+
+ codeview::DefRangeRegisterRelHeader DRHdr;
+ DRHdr.Register = DRRegister;
+ DRHdr.Flags = DRFlags;
+ DRHdr.BasePointerOffset = DRBasePointerOffset;
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ default:
+ return Error(Loc, "unexpected def_range type in .cv_def_range directive");
+ }
+ return true;
+}
+
+/// parseDirectiveCVString
+/// ::= .cv_stringtable "string"
+bool MasmParser::parseDirectiveCVString() {
+ std::string Data;
+ if (checkForValidSection() || parseEscapedString(Data))
+ return addErrorSuffix(" in '.cv_string' directive");
+
+ // Put the string in the table and emit the offset.
+ std::pair<StringRef, unsigned> Insertion =
+ getCVContext().addToStringTable(Data);
+ getStreamer().emitIntValue(Insertion.second, 4);
+ return false;
+}
+
+/// parseDirectiveCVStringTable
+/// ::= .cv_stringtable
+bool MasmParser::parseDirectiveCVStringTable() {
+ getStreamer().emitCVStringTableDirective();
+ return false;
+}
+
+/// parseDirectiveCVFileChecksums
+/// ::= .cv_filechecksums
+bool MasmParser::parseDirectiveCVFileChecksums() {
+ getStreamer().emitCVFileChecksumsDirective();
+ return false;
+}
+
+/// parseDirectiveCVFileChecksumOffset
+/// ::= .cv_filechecksumoffset fileno
+bool MasmParser::parseDirectiveCVFileChecksumOffset() {
+ int64_t FileNo;
+ if (parseIntToken(FileNo, "expected identifier in directive"))
+ return true;
+ if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
+ return true;
+ getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
+ return false;
+}
+
+/// parseDirectiveCVFPOData
+/// ::= .cv_fpo_data procsym
+bool MasmParser::parseDirectiveCVFPOData() {
+ SMLoc DirLoc = getLexer().getLoc();
+ StringRef ProcName;
+ if (parseIdentifier(ProcName))
+ return TokError("expected symbol name");
+ if (parseEOL("unexpected tokens"))
+ return addErrorSuffix(" in '.cv_fpo_data' directive");
+ MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
+ getStreamer().EmitCVFPOData(ProcSym, DirLoc);
+ return false;
+}
+
+/// parseDirectiveCFISections
+/// ::= .cfi_sections section [, section]
+bool MasmParser::parseDirectiveCFISections() {
+ StringRef Name;
+ bool EH = false;
+ bool Debug = false;
+
+ if (parseIdentifier(Name))
+ return TokError("Expected an identifier");
+
+ if (Name == ".eh_frame")
+ EH = true;
+ else if (Name == ".debug_frame")
+ Debug = true;
+
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+
+ if (parseIdentifier(Name))
+ return TokError("Expected an identifier");
+
+ if (Name == ".eh_frame")
+ EH = true;
+ else if (Name == ".debug_frame")
+ Debug = true;
+ }
+
+ getStreamer().emitCFISections(EH, Debug);
+ return false;
+}
+
+/// parseDirectiveCFIStartProc
+/// ::= .cfi_startproc [simple]
+bool MasmParser::parseDirectiveCFIStartProc() {
+ StringRef Simple;
+ if (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ if (check(parseIdentifier(Simple) || Simple != "simple",
+ "unexpected token") ||
+ parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '.cfi_startproc' directive");
+ }
+
+ // TODO(kristina): Deal with a corner case of incorrect diagnostic context
+ // being produced if this directive is emitted as part of preprocessor macro
+ // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
+ // Tools like llvm-mc on the other hand are not affected by it, and report
+ // correct context information.
+ getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
+ return false;
+}
+
+/// parseDirectiveCFIEndProc
+/// ::= .cfi_endproc
+bool MasmParser::parseDirectiveCFIEndProc() {
+ getStreamer().emitCFIEndProc();
+ return false;
+}
+
+/// parse register name or number.
+bool MasmParser::parseRegisterOrRegisterNumber(int64_t &Register,
+ SMLoc DirectiveLoc) {
+ unsigned RegNo;
+
+ if (getLexer().isNot(AsmToken::Integer)) {
+ if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc))
+ return true;
+ Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
+ } else
+ return parseAbsoluteExpression(Register);
+
+ return false;
+}
+
+/// parseDirectiveCFIDefCfa
+/// ::= .cfi_def_cfa register, offset
+bool MasmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
+ int64_t Register = 0, Offset = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ parseAbsoluteExpression(Offset))
+ return true;
+
+ getStreamer().emitCFIDefCfa(Register, Offset);
+ return false;
+}
+
+/// parseDirectiveCFIDefCfaOffset
+/// ::= .cfi_def_cfa_offset offset
+bool MasmParser::parseDirectiveCFIDefCfaOffset() {
+ int64_t Offset = 0;
+ if (parseAbsoluteExpression(Offset))
+ return true;
+
+ getStreamer().emitCFIDefCfaOffset(Offset);
+ return false;
+}
+
+/// parseDirectiveCFIRegister
+/// ::= .cfi_register register, register
+bool MasmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
+ int64_t Register1 = 0, Register2 = 0;
+ if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ parseRegisterOrRegisterNumber(Register2, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFIRegister(Register1, Register2);
+ return false;
+}
+
+/// parseDirectiveCFIWindowSave
+/// ::= .cfi_window_save
+bool MasmParser::parseDirectiveCFIWindowSave() {
+ getStreamer().emitCFIWindowSave();
+ return false;
+}
+
+/// parseDirectiveCFIAdjustCfaOffset
+/// ::= .cfi_adjust_cfa_offset adjustment
+bool MasmParser::parseDirectiveCFIAdjustCfaOffset() {
+ int64_t Adjustment = 0;
+ if (parseAbsoluteExpression(Adjustment))
+ return true;
+
+ getStreamer().emitCFIAdjustCfaOffset(Adjustment);
+ return false;
+}
+
+/// parseDirectiveCFIDefCfaRegister
+/// ::= .cfi_def_cfa_register register
+bool MasmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFIDefCfaRegister(Register);
+ return false;
+}
+
+/// parseDirectiveCFIOffset
+/// ::= .cfi_offset register, offset
+bool MasmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ int64_t Offset = 0;
+
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ parseAbsoluteExpression(Offset))
+ return true;
+
+ getStreamer().emitCFIOffset(Register, Offset);
+ return false;
+}
+
+/// parseDirectiveCFIRelOffset
+/// ::= .cfi_rel_offset register, offset
+bool MasmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
+ int64_t Register = 0, Offset = 0;
+
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ parseAbsoluteExpression(Offset))
+ return true;
+
+ getStreamer().emitCFIRelOffset(Register, Offset);
+ return false;
+}
+
+static bool isValidEncoding(int64_t Encoding) {
+ if (Encoding & ~0xff)
+ return false;
+
+ if (Encoding == dwarf::DW_EH_PE_omit)
+ return true;
+
+ const unsigned Format = Encoding & 0xf;
+ if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
+ Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
+ Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
+ Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
+ return false;
+
+ const unsigned Application = Encoding & 0x70;
+ if (Application != dwarf::DW_EH_PE_absptr &&
+ Application != dwarf::DW_EH_PE_pcrel)
+ return false;
+
+ return true;
+}
+
+/// parseDirectiveCFIPersonalityOrLsda
+/// IsPersonality true for cfi_personality, false for cfi_lsda
+/// ::= .cfi_personality encoding, [symbol_name]
+/// ::= .cfi_lsda encoding, [symbol_name]
+bool MasmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
+ int64_t Encoding = 0;
+ if (parseAbsoluteExpression(Encoding))
+ return true;
+ if (Encoding == dwarf::DW_EH_PE_omit)
+ return false;
+
+ StringRef Name;
+ if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ check(parseIdentifier(Name), "expected identifier in directive"))
+ return true;
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ if (IsPersonality)
+ getStreamer().emitCFIPersonality(Sym, Encoding);
+ else
+ getStreamer().emitCFILsda(Sym, Encoding);
+ return false;
+}
+
+/// parseDirectiveCFIRememberState
+/// ::= .cfi_remember_state
+bool MasmParser::parseDirectiveCFIRememberState() {
+ getStreamer().emitCFIRememberState();
+ return false;
+}
+
+/// parseDirectiveCFIRestoreState
+/// ::= .cfi_remember_state
+bool MasmParser::parseDirectiveCFIRestoreState() {
+ getStreamer().emitCFIRestoreState();
+ return false;
+}
+
+/// parseDirectiveCFISameValue
+/// ::= .cfi_same_value register
+bool MasmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFISameValue(Register);
+ return false;
+}
+
+/// parseDirectiveCFIRestore
+/// ::= .cfi_restore register
+bool MasmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFIRestore(Register);
+ return false;
+}
+
+/// parseDirectiveCFIEscape
+/// ::= .cfi_escape expression[,...]
+bool MasmParser::parseDirectiveCFIEscape() {
+ std::string Values;
+ int64_t CurrValue;
+ if (parseAbsoluteExpression(CurrValue))
+ return true;
+
+ Values.push_back((uint8_t)CurrValue);
+
+ while (getLexer().is(AsmToken::Comma)) {
+ Lex();
+
+ if (parseAbsoluteExpression(CurrValue))
+ return true;
+
+ Values.push_back((uint8_t)CurrValue);
+ }
+
+ getStreamer().emitCFIEscape(Values);
+ return false;
+}
+
+/// parseDirectiveCFIReturnColumn
+/// ::= .cfi_return_column register
+bool MasmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+ getStreamer().emitCFIReturnColumn(Register);
+ return false;
+}
+
+/// parseDirectiveCFISignalFrame
+/// ::= .cfi_signal_frame
+bool MasmParser::parseDirectiveCFISignalFrame() {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cfi_signal_frame'"))
+ return true;
+
+ getStreamer().emitCFISignalFrame();
+ return false;
+}
+
+/// parseDirectiveCFIUndefined
+/// ::= .cfi_undefined register
+bool MasmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFIUndefined(Register);
+ return false;
+}
+
+/// parseDirectiveMacro
/// ::= name macro [parameters]
/// ["LOCAL" identifiers]
/// parameters ::= parameter [, parameter]*
/// parameter ::= name ":" qualifier
/// qualifier ::= "req" | "vararg" | "=" macro_argument
bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
- MCAsmMacroParameters Parameters;
- while (getLexer().isNot(AsmToken::EndOfStatement)) {
- if (!Parameters.empty() && Parameters.back().Vararg)
- return Error(Lexer.getLoc(),
- "Vararg parameter '" + Parameters.back().Name +
+ MCAsmMacroParameters Parameters;
+ while (getLexer().isNot(AsmToken::EndOfStatement)) {
+ if (!Parameters.empty() && Parameters.back().Vararg)
+ return Error(Lexer.getLoc(),
+ "Vararg parameter '" + Parameters.back().Name +
"' should be last in the list of parameters");
-
- MCAsmMacroParameter Parameter;
- if (parseIdentifier(Parameter.Name))
+
+ MCAsmMacroParameter Parameter;
+ if (parseIdentifier(Parameter.Name))
return TokError("expected identifier in 'macro' directive");
-
- // Emit an error if two (or more) named parameters share the same name.
- for (const MCAsmMacroParameter& CurrParam : Parameters)
+
+ // Emit an error if two (or more) named parameters share the same name.
+ for (const MCAsmMacroParameter& CurrParam : Parameters)
if (CurrParam.Name.equals_lower(Parameter.Name))
- return TokError("macro '" + Name + "' has multiple parameters"
- " named '" + Parameter.Name + "'");
-
- if (Lexer.is(AsmToken::Colon)) {
- Lex(); // consume ':'
-
+ return TokError("macro '" + Name + "' has multiple parameters"
+ " named '" + Parameter.Name + "'");
+
+ if (Lexer.is(AsmToken::Colon)) {
+ Lex(); // consume ':'
+
if (parseOptionalToken(AsmToken::Equal)) {
// Default value
SMLoc ParamLoc;
-
+
ParamLoc = Lexer.getLoc();
if (parseMacroArgument(nullptr, Parameter.Value))
return true;
} else {
SMLoc QualLoc;
StringRef Qualifier;
-
+
QualLoc = Lexer.getLoc();
if (parseIdentifier(Qualifier))
return Error(QualLoc, "missing parameter qualifier for "
"'" +
Parameter.Name + "' in macro '" + Name +
"'");
-
+
if (Qualifier.equals_lower("req"))
Parameter.Required = true;
else if (Qualifier.equals_lower("vararg"))
@@ -5529,17 +5529,17 @@ bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
Qualifier + " is not a valid parameter qualifier for '" +
Parameter.Name + "' in macro '" + Name + "'");
}
- }
-
- Parameters.push_back(std::move(Parameter));
-
- if (getLexer().is(AsmToken::Comma))
- Lex();
- }
-
- // Eat just the end of statement.
- Lexer.Lex();
-
+ }
+
+ Parameters.push_back(std::move(Parameter));
+
+ if (getLexer().is(AsmToken::Comma))
+ Lex();
+ }
+
+ // Eat just the end of statement.
+ Lexer.Lex();
+
std::vector<std::string> Locals;
if (getTok().is(AsmToken::Identifier) &&
getTok().getIdentifier().equals_lower("local")) {
@@ -5558,36 +5558,36 @@ bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
}
}
- // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors.
- AsmToken EndToken, StartToken = getTok();
- unsigned MacroDepth = 0;
+ // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors.
+ AsmToken EndToken, StartToken = getTok();
+ unsigned MacroDepth = 0;
bool IsMacroFunction = false;
- // Lex the macro definition.
- while (true) {
- // Ignore Lexing errors in macros.
- while (Lexer.is(AsmToken::Error)) {
- Lexer.Lex();
- }
-
- // Check whether we have reached the end of the file.
- if (getLexer().is(AsmToken::Eof))
+ // Lex the macro definition.
+ while (true) {
+ // Ignore Lexing errors in macros.
+ while (Lexer.is(AsmToken::Error)) {
+ Lexer.Lex();
+ }
+
+ // Check whether we have reached the end of the file.
+ if (getLexer().is(AsmToken::Eof))
return Error(NameLoc, "no matching 'endm' in definition");
-
+
// Otherwise, check whether we have reached the 'endm'... and determine if
// this is a macro function.
- if (getLexer().is(AsmToken::Identifier)) {
+ if (getLexer().is(AsmToken::Identifier)) {
if (getTok().getIdentifier().equals_lower("endm")) {
- if (MacroDepth == 0) { // Outermost macro.
- EndToken = getTok();
- Lexer.Lex();
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '" + EndToken.getIdentifier() +
- "' directive");
- break;
- } else {
- // Otherwise we just found the end of an inner macro.
- --MacroDepth;
- }
+ if (MacroDepth == 0) { // Outermost macro.
+ EndToken = getTok();
+ Lexer.Lex();
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '" + EndToken.getIdentifier() +
+ "' directive");
+ break;
+ } else {
+ // Otherwise we just found the end of an inner macro.
+ --MacroDepth;
+ }
} else if (getTok().getIdentifier().equals_lower("exitm")) {
if (MacroDepth == 0 &&
getLexer().peekTok().isNot(AsmToken::EndOfStatement)) {
@@ -5596,30 +5596,30 @@ bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
} else if (isMacroLikeDirective()) {
// We allow nested macros. Those aren't instantiated until the
// outermost macro is expanded so just ignore them for now.
- ++MacroDepth;
- }
- }
-
- // Otherwise, scan til the end of the statement.
- eatToEndOfStatement();
- }
-
+ ++MacroDepth;
+ }
+ }
+
+ // Otherwise, scan til the end of the statement.
+ eatToEndOfStatement();
+ }
+
if (getContext().lookupMacro(Name.lower())) {
return Error(NameLoc, "macro '" + Name + "' is already defined");
- }
-
- const char *BodyStart = StartToken.getLoc().getPointer();
- const char *BodyEnd = EndToken.getLoc().getPointer();
- StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
+ }
+
+ const char *BodyStart = StartToken.getLoc().getPointer();
+ const char *BodyEnd = EndToken.getLoc().getPointer();
+ StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
MCAsmMacro Macro(Name, Body, std::move(Parameters), std::move(Locals),
IsMacroFunction);
- DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
- Macro.dump());
- getContext().defineMacro(Name, std::move(Macro));
- return false;
-}
-
-/// parseDirectiveExitMacro
+ DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
+ Macro.dump());
+ getContext().defineMacro(Name, std::move(Macro));
+ return false;
+}
+
+/// parseDirectiveExitMacro
/// ::= "exitm" [textitem]
bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
StringRef Directive,
@@ -5629,764 +5629,764 @@ bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
return Error(EndLoc,
"unable to parse text item in '" + Directive + "' directive");
eatToEndOfStatement();
-
- if (!isInsideMacroInstantiation())
- return TokError("unexpected '" + Directive + "' in file, "
- "no current macro definition");
-
- // Exit all conditionals that are active in the current macro.
- while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
- TheCondState = TheCondStack.back();
- TheCondStack.pop_back();
- }
-
- handleMacroExit();
- return false;
-}
-
-/// parseDirectiveEndMacro
+
+ if (!isInsideMacroInstantiation())
+ return TokError("unexpected '" + Directive + "' in file, "
+ "no current macro definition");
+
+ // Exit all conditionals that are active in the current macro.
+ while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
+ TheCondState = TheCondStack.back();
+ TheCondStack.pop_back();
+ }
+
+ handleMacroExit();
+ return false;
+}
+
+/// parseDirectiveEndMacro
/// ::= endm
-bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '" + Directive + "' directive");
-
- // If we are inside a macro instantiation, terminate the current
- // instantiation.
- if (isInsideMacroInstantiation()) {
- handleMacroExit();
- return false;
- }
-
- // Otherwise, this .endmacro is a stray entry in the file; well formed
- // .endmacro directives are handled during the macro definition parsing.
- return TokError("unexpected '" + Directive + "' in file, "
- "no current macro definition");
-}
-
-/// parseDirectivePurgeMacro
+bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '" + Directive + "' directive");
+
+ // If we are inside a macro instantiation, terminate the current
+ // instantiation.
+ if (isInsideMacroInstantiation()) {
+ handleMacroExit();
+ return false;
+ }
+
+ // Otherwise, this .endmacro is a stray entry in the file; well formed
+ // .endmacro directives are handled during the macro definition parsing.
+ return TokError("unexpected '" + Directive + "' in file, "
+ "no current macro definition");
+}
+
+/// parseDirectivePurgeMacro
/// ::= purge identifier ( , identifier )*
-bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
- StringRef Name;
+bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
+ StringRef Name;
while (true) {
SMLoc NameLoc;
if (parseTokenLoc(NameLoc) ||
check(parseIdentifier(Name), NameLoc,
"expected identifier in 'purge' directive"))
return true;
-
+
DEBUG_WITH_TYPE("asm-macros", dbgs()
<< "Un-defining macro: " << Name << "\n");
if (!getContext().lookupMacro(Name.lower()))
return Error(NameLoc, "macro '" + Name + "' is not defined");
getContext().undefineMacro(Name.lower());
-
+
if (!parseOptionalToken(AsmToken::Comma))
break;
parseOptionalToken(AsmToken::EndOfStatement);
}
- return false;
-}
-
-/// parseDirectiveSymbolAttribute
-/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
-bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
- auto parseOp = [&]() -> bool {
- StringRef Name;
- SMLoc Loc = getTok().getLoc();
- if (parseIdentifier(Name))
- return Error(Loc, "expected identifier");
- 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");
-
- if (!getStreamer().emitSymbolAttribute(Sym, Attr))
- return Error(Loc, "unable to emit symbol attribute");
- return false;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in directive");
- return false;
-}
-
-/// parseDirectiveComm
-/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
-bool MasmParser::parseDirectiveComm(bool IsLocal) {
- if (checkForValidSection())
- return true;
-
- SMLoc IDLoc = getLexer().getLoc();
- StringRef Name;
- if (parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- int64_t Size;
- SMLoc SizeLoc = getLexer().getLoc();
- if (parseAbsoluteExpression(Size))
- return true;
-
- int64_t Pow2Alignment = 0;
- SMLoc Pow2AlignmentLoc;
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
- Pow2AlignmentLoc = getLexer().getLoc();
- if (parseAbsoluteExpression(Pow2Alignment))
- return true;
-
- LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
- if (IsLocal && LCOMM == LCOMM::NoAlignment)
- return Error(Pow2AlignmentLoc, "alignment not supported on this target");
-
- // If this target takes alignments in bytes (not log) validate and convert.
- if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
- (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
- if (!isPowerOf2_64(Pow2Alignment))
- return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
- Pow2Alignment = Log2_64(Pow2Alignment);
- }
- }
-
- 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.
- if (Size < 0)
- return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
- "be less than zero");
-
- // NOTE: The alignment in the directive is a power of 2 value, the assembler
- // may internally end up wanting an alignment in bytes.
- // FIXME: Diagnose overflow.
- if (Pow2Alignment < 0)
- return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
- "alignment, can't be less than zero");
-
- Sym->redefineIfPossible();
- if (!Sym->isUndefined())
- return Error(IDLoc, "invalid symbol redefinition");
-
- // Create the Symbol as a common or local common with Size and Pow2Alignment.
- if (IsLocal) {
- getStreamer().emitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
- return false;
- }
-
- getStreamer().emitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
- return false;
-}
-
-/// parseDirectiveComment
-/// ::= comment delimiter [[text]]
-/// [[text]]
-/// [[text]] delimiter [[text]]
-bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
+ return false;
+}
+
+/// parseDirectiveSymbolAttribute
+/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
+bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
+ auto parseOp = [&]() -> bool {
+ StringRef Name;
+ SMLoc Loc = getTok().getLoc();
+ if (parseIdentifier(Name))
+ return Error(Loc, "expected identifier");
+ 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");
+
+ if (!getStreamer().emitSymbolAttribute(Sym, Attr))
+ return Error(Loc, "unable to emit symbol attribute");
+ return false;
+ };
+
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in directive");
+ return false;
+}
+
+/// parseDirectiveComm
+/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
+bool MasmParser::parseDirectiveComm(bool IsLocal) {
+ if (checkForValidSection())
+ return true;
+
+ SMLoc IDLoc = getLexer().getLoc();
+ StringRef Name;
+ if (parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ int64_t Size;
+ SMLoc SizeLoc = getLexer().getLoc();
+ if (parseAbsoluteExpression(Size))
+ return true;
+
+ int64_t Pow2Alignment = 0;
+ SMLoc Pow2AlignmentLoc;
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+ Pow2AlignmentLoc = getLexer().getLoc();
+ if (parseAbsoluteExpression(Pow2Alignment))
+ return true;
+
+ LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
+ if (IsLocal && LCOMM == LCOMM::NoAlignment)
+ return Error(Pow2AlignmentLoc, "alignment not supported on this target");
+
+ // If this target takes alignments in bytes (not log) validate and convert.
+ if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
+ (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
+ if (!isPowerOf2_64(Pow2Alignment))
+ return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
+ Pow2Alignment = Log2_64(Pow2Alignment);
+ }
+ }
+
+ 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.
+ if (Size < 0)
+ return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
+ "be less than zero");
+
+ // NOTE: The alignment in the directive is a power of 2 value, the assembler
+ // may internally end up wanting an alignment in bytes.
+ // FIXME: Diagnose overflow.
+ if (Pow2Alignment < 0)
+ return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
+ "alignment, can't be less than zero");
+
+ Sym->redefineIfPossible();
+ if (!Sym->isUndefined())
+ return Error(IDLoc, "invalid symbol redefinition");
+
+ // Create the Symbol as a common or local common with Size and Pow2Alignment.
+ if (IsLocal) {
+ getStreamer().emitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
+ return false;
+ }
+
+ getStreamer().emitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
+ return false;
+}
+
+/// parseDirectiveComment
+/// ::= comment delimiter [[text]]
+/// [[text]]
+/// [[text]] delimiter [[text]]
+bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
std::string FirstLine = parseStringTo(AsmToken::EndOfStatement);
- size_t DelimiterEnd = FirstLine.find_first_of("\b\t\v\f\r\x1A ");
+ size_t DelimiterEnd = FirstLine.find_first_of("\b\t\v\f\r\x1A ");
StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
- if (Delimiter.empty())
- return Error(DirectiveLoc, "no delimiter in 'comment' directive");
- do {
- if (getTok().is(AsmToken::Eof))
- return Error(DirectiveLoc, "unmatched delimiter in 'comment' directive");
- Lex(); // eat end of statement
+ if (Delimiter.empty())
+ return Error(DirectiveLoc, "no delimiter in 'comment' directive");
+ do {
+ if (getTok().is(AsmToken::Eof))
+ return Error(DirectiveLoc, "unmatched delimiter in 'comment' directive");
+ Lex(); // eat end of statement
} while (
!StringRef(parseStringTo(AsmToken::EndOfStatement)).contains(Delimiter));
- return parseToken(AsmToken::EndOfStatement,
- "unexpected token in 'comment' directive");
-}
-
-/// parseDirectiveInclude
-/// ::= include <filename>
-/// | include filename
-bool MasmParser::parseDirectiveInclude() {
- // Allow the strings to have escaped octal character sequence.
- std::string Filename;
- SMLoc IncludeLoc = getTok().getLoc();
-
- if (!parseAngleBracketString(Filename))
+ return parseToken(AsmToken::EndOfStatement,
+ "unexpected token in 'comment' directive");
+}
+
+/// parseDirectiveInclude
+/// ::= include <filename>
+/// | include filename
+bool MasmParser::parseDirectiveInclude() {
+ // Allow the strings to have escaped octal character sequence.
+ std::string Filename;
+ SMLoc IncludeLoc = getTok().getLoc();
+
+ if (!parseAngleBracketString(Filename))
Filename = parseStringTo(AsmToken::EndOfStatement);
- if (check(!Filename.empty(), "missing filename in 'include' directive") ||
- check(getTok().isNot(AsmToken::EndOfStatement),
- "unexpected token in 'include' directive") ||
- // Attempt to switch the lexer to the included file before consuming the
- // end of statement to avoid losing it when we switch.
- check(enterIncludeFile(Filename), IncludeLoc,
- "Could not find include file '" + Filename + "'"))
- return true;
-
- return false;
-}
-
-/// parseDirectiveIf
-/// ::= .if{,eq,ge,gt,le,lt,ne} expression
-bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- } else {
- int64_t ExprValue;
- if (parseAbsoluteExpression(ExprValue) ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.if' directive"))
- return true;
-
- switch (DirKind) {
- default:
- llvm_unreachable("unsupported directive");
- case DK_IF:
- break;
- case DK_IFE:
- ExprValue = ExprValue == 0;
- break;
- }
-
- TheCondState.CondMet = ExprValue;
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveIfb
+ if (check(!Filename.empty(), "missing filename in 'include' directive") ||
+ check(getTok().isNot(AsmToken::EndOfStatement),
+ "unexpected token in 'include' directive") ||
+ // Attempt to switch the lexer to the included file before consuming the
+ // end of statement to avoid losing it when we switch.
+ check(enterIncludeFile(Filename), IncludeLoc,
+ "Could not find include file '" + Filename + "'"))
+ return true;
+
+ return false;
+}
+
+/// parseDirectiveIf
+/// ::= .if{,eq,ge,gt,le,lt,ne} expression
+bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ } else {
+ int64_t ExprValue;
+ if (parseAbsoluteExpression(ExprValue) ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.if' directive"))
+ return true;
+
+ switch (DirKind) {
+ default:
+ llvm_unreachable("unsupported directive");
+ case DK_IF:
+ break;
+ case DK_IFE:
+ ExprValue = ExprValue == 0;
+ break;
+ }
+
+ TheCondState.CondMet = ExprValue;
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveIfb
/// ::= .ifb textitem
-bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
-
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- } else {
- std::string Str;
- if (parseTextItem(Str))
+bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ } else {
+ std::string Str;
+ if (parseTextItem(Str))
return TokError("expected text item parameter for 'ifb' directive");
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in 'ifb' directive"))
- return true;
-
- TheCondState.CondMet = ExpectBlank == Str.empty();
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveIfidn
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in 'ifb' directive"))
+ return true;
+
+ TheCondState.CondMet = ExpectBlank == Str.empty();
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveIfidn
/// ::= ifidn textitem, textitem
bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
bool CaseInsensitive) {
- std::string String1, String2;
-
- if (parseTextItem(String1)) {
- if (ExpectEqual)
+ std::string String1, String2;
+
+ if (parseTextItem(String1)) {
+ if (ExpectEqual)
return TokError("expected text item parameter for 'ifidn' directive");
return TokError("expected text item parameter for 'ifdif' directive");
- }
-
- if (Lexer.isNot(AsmToken::Comma)) {
- if (ExpectEqual)
- return TokError(
- "expected comma after first string for 'ifidn' directive");
- return TokError("expected comma after first string for 'ifdif' directive");
- }
- Lex();
-
- if (parseTextItem(String2)) {
- if (ExpectEqual)
+ }
+
+ if (Lexer.isNot(AsmToken::Comma)) {
+ if (ExpectEqual)
+ return TokError(
+ "expected comma after first string for 'ifidn' directive");
+ return TokError("expected comma after first string for 'ifdif' directive");
+ }
+ Lex();
+
+ if (parseTextItem(String2)) {
+ if (ExpectEqual)
return TokError("expected text item parameter for 'ifidn' directive");
return TokError("expected text item parameter for 'ifdif' directive");
- }
-
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
- if (CaseInsensitive)
- TheCondState.CondMet =
- ExpectEqual == (StringRef(String1).equals_lower(String2));
- else
- TheCondState.CondMet = ExpectEqual == (String1 == String2);
- TheCondState.Ignore = !TheCondState.CondMet;
-
- return false;
-}
-
-/// parseDirectiveIfdef
-/// ::= ifdef symbol
-/// | ifdef variable
-bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
-
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- } else {
- bool is_defined = false;
- unsigned RegNo;
- SMLoc StartLoc, EndLoc;
- is_defined = (getTargetParser().tryParseRegister(
- RegNo, StartLoc, EndLoc) == MatchOperand_Success);
- if (!is_defined) {
- StringRef Name;
- if (check(parseIdentifier(Name), "expected identifier after 'ifdef'") ||
- parseToken(AsmToken::EndOfStatement, "unexpected token in 'ifdef'"))
- return true;
-
- if (Variables.find(Name) != Variables.end()) {
- is_defined = true;
- } else {
- MCSymbol *Sym = getContext().lookupSymbol(Name);
- is_defined = (Sym && !Sym->isUndefined(false));
- }
- }
-
- TheCondState.CondMet = (is_defined == expect_defined);
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveElseIf
-/// ::= elseif expression
-bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
- DirectiveKind DirKind) {
- if (TheCondState.TheCond != AsmCond::IfCond &&
- TheCondState.TheCond != AsmCond::ElseIfCond)
- return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
- " .if or an .elseif");
- TheCondState.TheCond = AsmCond::ElseIfCond;
-
- bool LastIgnoreState = false;
- if (!TheCondStack.empty())
- LastIgnoreState = TheCondStack.back().Ignore;
- if (LastIgnoreState || TheCondState.CondMet) {
- TheCondState.Ignore = true;
- eatToEndOfStatement();
- } else {
- int64_t ExprValue;
- if (parseAbsoluteExpression(ExprValue))
- return true;
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.elseif' directive"))
- return true;
-
- switch (DirKind) {
- default:
- llvm_unreachable("unsupported directive");
- case DK_ELSEIF:
- break;
- case DK_ELSEIFE:
- ExprValue = ExprValue == 0;
- break;
- }
-
- TheCondState.CondMet = ExprValue;
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveElseIfb
+ }
+
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+ if (CaseInsensitive)
+ TheCondState.CondMet =
+ ExpectEqual == (StringRef(String1).equals_lower(String2));
+ else
+ TheCondState.CondMet = ExpectEqual == (String1 == String2);
+ TheCondState.Ignore = !TheCondState.CondMet;
+
+ return false;
+}
+
+/// parseDirectiveIfdef
+/// ::= ifdef symbol
+/// | ifdef variable
+bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ } else {
+ bool is_defined = false;
+ unsigned RegNo;
+ SMLoc StartLoc, EndLoc;
+ is_defined = (getTargetParser().tryParseRegister(
+ RegNo, StartLoc, EndLoc) == MatchOperand_Success);
+ if (!is_defined) {
+ StringRef Name;
+ if (check(parseIdentifier(Name), "expected identifier after 'ifdef'") ||
+ parseToken(AsmToken::EndOfStatement, "unexpected token in 'ifdef'"))
+ return true;
+
+ if (Variables.find(Name) != Variables.end()) {
+ is_defined = true;
+ } else {
+ MCSymbol *Sym = getContext().lookupSymbol(Name);
+ is_defined = (Sym && !Sym->isUndefined(false));
+ }
+ }
+
+ TheCondState.CondMet = (is_defined == expect_defined);
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveElseIf
+/// ::= elseif expression
+bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
+ DirectiveKind DirKind) {
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
+ " .if or an .elseif");
+ TheCondState.TheCond = AsmCond::ElseIfCond;
+
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet) {
+ TheCondState.Ignore = true;
+ eatToEndOfStatement();
+ } else {
+ int64_t ExprValue;
+ if (parseAbsoluteExpression(ExprValue))
+ return true;
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.elseif' directive"))
+ return true;
+
+ switch (DirKind) {
+ default:
+ llvm_unreachable("unsupported directive");
+ case DK_ELSEIF:
+ break;
+ case DK_ELSEIFE:
+ ExprValue = ExprValue == 0;
+ break;
+ }
+
+ TheCondState.CondMet = ExprValue;
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveElseIfb
/// ::= elseifb textitem
-bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
- if (TheCondState.TheCond != AsmCond::IfCond &&
- TheCondState.TheCond != AsmCond::ElseIfCond)
- return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
- " if or an elseif");
- TheCondState.TheCond = AsmCond::ElseIfCond;
-
- bool LastIgnoreState = false;
- if (!TheCondStack.empty())
- LastIgnoreState = TheCondStack.back().Ignore;
- if (LastIgnoreState || TheCondState.CondMet) {
- TheCondState.Ignore = true;
- eatToEndOfStatement();
- } else {
- std::string Str;
+bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
+ " if or an elseif");
+ TheCondState.TheCond = AsmCond::ElseIfCond;
+
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet) {
+ TheCondState.Ignore = true;
+ eatToEndOfStatement();
+ } else {
+ std::string Str;
if (parseTextItem(Str)) {
if (ExpectBlank)
return TokError("expected text item parameter for 'elseifb' directive");
return TokError("expected text item parameter for 'elseifnb' directive");
}
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in 'elseifb' directive"))
- return true;
-
- TheCondState.CondMet = ExpectBlank == Str.empty();
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveElseIfdef
-/// ::= elseifdef symbol
-/// | elseifdef variable
-bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
- bool expect_defined) {
- if (TheCondState.TheCond != AsmCond::IfCond &&
- TheCondState.TheCond != AsmCond::ElseIfCond)
- return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
- " if or an elseif");
- TheCondState.TheCond = AsmCond::ElseIfCond;
-
- bool LastIgnoreState = false;
- if (!TheCondStack.empty())
- LastIgnoreState = TheCondStack.back().Ignore;
- if (LastIgnoreState || TheCondState.CondMet) {
- TheCondState.Ignore = true;
- eatToEndOfStatement();
- } else {
- bool is_defined = false;
- unsigned RegNo;
- SMLoc StartLoc, EndLoc;
- is_defined = (getTargetParser().tryParseRegister(RegNo, StartLoc, EndLoc) ==
- MatchOperand_Success);
- if (!is_defined) {
- StringRef Name;
- if (check(parseIdentifier(Name),
- "expected identifier after 'elseifdef'") ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in 'elseifdef'"))
- return true;
-
- if (Variables.find(Name) != Variables.end()) {
- is_defined = true;
- } else {
- MCSymbol *Sym = getContext().lookupSymbol(Name);
- is_defined = (Sym && !Sym->isUndefined(false));
- }
- }
-
- TheCondState.CondMet = (is_defined == expect_defined);
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveElseIfidn
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in 'elseifb' directive"))
+ return true;
+
+ TheCondState.CondMet = ExpectBlank == Str.empty();
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveElseIfdef
+/// ::= elseifdef symbol
+/// | elseifdef variable
+bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
+ bool expect_defined) {
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
+ " if or an elseif");
+ TheCondState.TheCond = AsmCond::ElseIfCond;
+
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet) {
+ TheCondState.Ignore = true;
+ eatToEndOfStatement();
+ } else {
+ bool is_defined = false;
+ unsigned RegNo;
+ SMLoc StartLoc, EndLoc;
+ is_defined = (getTargetParser().tryParseRegister(RegNo, StartLoc, EndLoc) ==
+ MatchOperand_Success);
+ if (!is_defined) {
+ StringRef Name;
+ if (check(parseIdentifier(Name),
+ "expected identifier after 'elseifdef'") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in 'elseifdef'"))
+ return true;
+
+ if (Variables.find(Name) != Variables.end()) {
+ is_defined = true;
+ } else {
+ MCSymbol *Sym = getContext().lookupSymbol(Name);
+ is_defined = (Sym && !Sym->isUndefined(false));
+ }
+ }
+
+ TheCondState.CondMet = (is_defined == expect_defined);
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveElseIfidn
/// ::= elseifidn textitem, textitem
-bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
- bool CaseInsensitive) {
- if (TheCondState.TheCond != AsmCond::IfCond &&
- TheCondState.TheCond != AsmCond::ElseIfCond)
- return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
- " if or an elseif");
- TheCondState.TheCond = AsmCond::ElseIfCond;
-
- bool LastIgnoreState = false;
- if (!TheCondStack.empty())
- LastIgnoreState = TheCondStack.back().Ignore;
- if (LastIgnoreState || TheCondState.CondMet) {
- TheCondState.Ignore = true;
- eatToEndOfStatement();
- } else {
- std::string String1, String2;
-
- if (parseTextItem(String1)) {
- if (ExpectEqual)
+bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+ bool CaseInsensitive) {
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
+ " if or an elseif");
+ TheCondState.TheCond = AsmCond::ElseIfCond;
+
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet) {
+ TheCondState.Ignore = true;
+ eatToEndOfStatement();
+ } else {
+ std::string String1, String2;
+
+ if (parseTextItem(String1)) {
+ if (ExpectEqual)
return TokError(
"expected text item parameter for 'elseifidn' directive");
return TokError("expected text item parameter for 'elseifdif' directive");
- }
-
- if (Lexer.isNot(AsmToken::Comma)) {
- if (ExpectEqual)
- return TokError(
- "expected comma after first string for 'elseifidn' directive");
- return TokError(
- "expected comma after first string for 'elseifdif' directive");
- }
- Lex();
-
- if (parseTextItem(String2)) {
- if (ExpectEqual)
+ }
+
+ if (Lexer.isNot(AsmToken::Comma)) {
+ if (ExpectEqual)
+ return TokError(
+ "expected comma after first string for 'elseifidn' directive");
+ return TokError(
+ "expected comma after first string for 'elseifdif' directive");
+ }
+ Lex();
+
+ if (parseTextItem(String2)) {
+ if (ExpectEqual)
return TokError(
"expected text item parameter for 'elseifidn' directive");
return TokError("expected text item parameter for 'elseifdif' directive");
- }
-
- if (CaseInsensitive)
- TheCondState.CondMet =
- ExpectEqual == (StringRef(String1).equals_lower(String2));
- else
- TheCondState.CondMet = ExpectEqual == (String1 == String2);
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveElse
-/// ::= else
-bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in 'else' directive"))
- return true;
-
- if (TheCondState.TheCond != AsmCond::IfCond &&
- TheCondState.TheCond != AsmCond::ElseIfCond)
- return Error(DirectiveLoc, "Encountered an else that doesn't follow an if"
- " or an elseif");
- TheCondState.TheCond = AsmCond::ElseCond;
- bool LastIgnoreState = false;
- if (!TheCondStack.empty())
- LastIgnoreState = TheCondStack.back().Ignore;
- if (LastIgnoreState || TheCondState.CondMet)
- TheCondState.Ignore = true;
- else
- TheCondState.Ignore = false;
-
- return false;
-}
-
-/// parseDirectiveEnd
-/// ::= end
-bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in 'end' directive"))
- return true;
-
- while (Lexer.isNot(AsmToken::Eof))
- Lexer.Lex();
-
- return false;
-}
-
-/// parseDirectiveError
-/// ::= .err [message]
-bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
- if (!TheCondStack.empty()) {
- if (TheCondStack.back().Ignore) {
- eatToEndOfStatement();
- return false;
- }
- }
-
+ }
+
+ if (CaseInsensitive)
+ TheCondState.CondMet =
+ ExpectEqual == (StringRef(String1).equals_lower(String2));
+ else
+ TheCondState.CondMet = ExpectEqual == (String1 == String2);
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveElse
+/// ::= else
+bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in 'else' directive"))
+ return true;
+
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ return Error(DirectiveLoc, "Encountered an else that doesn't follow an if"
+ " or an elseif");
+ TheCondState.TheCond = AsmCond::ElseCond;
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet)
+ TheCondState.Ignore = true;
+ else
+ TheCondState.Ignore = false;
+
+ return false;
+}
+
+/// parseDirectiveEnd
+/// ::= end
+bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in 'end' directive"))
+ return true;
+
+ while (Lexer.isNot(AsmToken::Eof))
+ Lexer.Lex();
+
+ return false;
+}
+
+/// parseDirectiveError
+/// ::= .err [message]
+bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+ }
+
std::string Message = ".err directive invoked in source file";
- if (Lexer.isNot(AsmToken::EndOfStatement))
+ if (Lexer.isNot(AsmToken::EndOfStatement))
Message = parseStringTo(AsmToken::EndOfStatement);
- Lex();
-
- return Error(DirectiveLoc, Message);
-}
-
-/// parseDirectiveErrorIfb
-/// ::= .errb textitem[, message]
-bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
- if (!TheCondStack.empty()) {
- if (TheCondStack.back().Ignore) {
- eatToEndOfStatement();
- return false;
- }
- }
-
- std::string Text;
- if (parseTextItem(Text))
- return Error(getTok().getLoc(), "missing text item in '.errb' directive");
-
+ Lex();
+
+ return Error(DirectiveLoc, Message);
+}
+
+/// parseDirectiveErrorIfb
+/// ::= .errb textitem[, message]
+bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+ }
+
+ std::string Text;
+ if (parseTextItem(Text))
+ return Error(getTok().getLoc(), "missing text item in '.errb' directive");
+
std::string Message = ".errb directive invoked in source file";
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (parseToken(AsmToken::Comma))
- return addErrorSuffix(" in '.errb' directive");
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (parseToken(AsmToken::Comma))
+ return addErrorSuffix(" in '.errb' directive");
Message = parseStringTo(AsmToken::EndOfStatement);
- }
- Lex();
-
- if (Text.empty() == ExpectBlank)
- return Error(DirectiveLoc, Message);
- return false;
-}
-
-/// parseDirectiveErrorIfdef
-/// ::= .errdef name[, message]
-bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
- bool ExpectDefined) {
- if (!TheCondStack.empty()) {
- if (TheCondStack.back().Ignore) {
- eatToEndOfStatement();
- return false;
- }
- }
-
- bool IsDefined = false;
- unsigned RegNo;
- SMLoc StartLoc, EndLoc;
- IsDefined = (getTargetParser().tryParseRegister(RegNo, StartLoc, EndLoc) ==
- MatchOperand_Success);
- if (!IsDefined) {
- StringRef Name;
- if (check(parseIdentifier(Name), "expected identifier after '.errdef'"))
- return true;
-
- if (Variables.find(Name) != Variables.end()) {
- IsDefined = true;
- } else {
- MCSymbol *Sym = getContext().lookupSymbol(Name);
- IsDefined = (Sym && !Sym->isUndefined(false));
- }
- }
-
+ }
+ Lex();
+
+ if (Text.empty() == ExpectBlank)
+ return Error(DirectiveLoc, Message);
+ return false;
+}
+
+/// parseDirectiveErrorIfdef
+/// ::= .errdef name[, message]
+bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
+ bool ExpectDefined) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+ }
+
+ bool IsDefined = false;
+ unsigned RegNo;
+ SMLoc StartLoc, EndLoc;
+ IsDefined = (getTargetParser().tryParseRegister(RegNo, StartLoc, EndLoc) ==
+ MatchOperand_Success);
+ if (!IsDefined) {
+ StringRef Name;
+ if (check(parseIdentifier(Name), "expected identifier after '.errdef'"))
+ return true;
+
+ if (Variables.find(Name) != Variables.end()) {
+ IsDefined = true;
+ } else {
+ MCSymbol *Sym = getContext().lookupSymbol(Name);
+ IsDefined = (Sym && !Sym->isUndefined(false));
+ }
+ }
+
std::string Message = ".errdef directive invoked in source file";
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (parseToken(AsmToken::Comma))
- return addErrorSuffix(" in '.errdef' directive");
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (parseToken(AsmToken::Comma))
+ return addErrorSuffix(" in '.errdef' directive");
Message = parseStringTo(AsmToken::EndOfStatement);
- }
- Lex();
-
- if (IsDefined == ExpectDefined)
- return Error(DirectiveLoc, Message);
- return false;
-}
-
-/// parseDirectiveErrorIfidn
+ }
+ Lex();
+
+ if (IsDefined == ExpectDefined)
+ return Error(DirectiveLoc, Message);
+ return false;
+}
+
+/// parseDirectiveErrorIfidn
/// ::= .erridn textitem, textitem[, message]
-bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
- bool CaseInsensitive) {
- if (!TheCondStack.empty()) {
- if (TheCondStack.back().Ignore) {
- eatToEndOfStatement();
- return false;
- }
- }
-
- std::string String1, String2;
-
- if (parseTextItem(String1)) {
- if (ExpectEqual)
- return TokError("expected string parameter for '.erridn' directive");
- return TokError("expected string parameter for '.errdif' directive");
- }
-
- if (Lexer.isNot(AsmToken::Comma)) {
- if (ExpectEqual)
- return TokError(
- "expected comma after first string for '.erridn' directive");
- return TokError(
- "expected comma after first string for '.errdif' directive");
- }
- Lex();
-
- if (parseTextItem(String2)) {
- if (ExpectEqual)
- return TokError("expected string parameter for '.erridn' directive");
- return TokError("expected string parameter for '.errdif' directive");
- }
-
+bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+ bool CaseInsensitive) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+ }
+
+ std::string String1, String2;
+
+ if (parseTextItem(String1)) {
+ if (ExpectEqual)
+ return TokError("expected string parameter for '.erridn' directive");
+ return TokError("expected string parameter for '.errdif' directive");
+ }
+
+ if (Lexer.isNot(AsmToken::Comma)) {
+ if (ExpectEqual)
+ return TokError(
+ "expected comma after first string for '.erridn' directive");
+ return TokError(
+ "expected comma after first string for '.errdif' directive");
+ }
+ Lex();
+
+ if (parseTextItem(String2)) {
+ if (ExpectEqual)
+ return TokError("expected string parameter for '.erridn' directive");
+ return TokError("expected string parameter for '.errdif' directive");
+ }
+
std::string Message;
- if (ExpectEqual)
- Message = ".erridn directive invoked in source file";
- else
- Message = ".errdif directive invoked in source file";
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (parseToken(AsmToken::Comma))
- return addErrorSuffix(" in '.erridn' directive");
+ if (ExpectEqual)
+ Message = ".erridn directive invoked in source file";
+ else
+ Message = ".errdif directive invoked in source file";
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (parseToken(AsmToken::Comma))
+ return addErrorSuffix(" in '.erridn' directive");
Message = parseStringTo(AsmToken::EndOfStatement);
- }
- Lex();
-
- if (CaseInsensitive)
- TheCondState.CondMet =
- ExpectEqual == (StringRef(String1).equals_lower(String2));
- else
- TheCondState.CondMet = ExpectEqual == (String1 == String2);
- TheCondState.Ignore = !TheCondState.CondMet;
-
- if ((CaseInsensitive &&
- ExpectEqual == StringRef(String1).equals_lower(String2)) ||
- (ExpectEqual == (String1 == String2)))
- return Error(DirectiveLoc, Message);
- return false;
-}
-
-/// parseDirectiveErrorIfe
-/// ::= .erre expression[, message]
-bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero) {
- if (!TheCondStack.empty()) {
- if (TheCondStack.back().Ignore) {
- eatToEndOfStatement();
- return false;
- }
- }
-
- int64_t ExprValue;
- if (parseAbsoluteExpression(ExprValue))
- return addErrorSuffix(" in '.erre' directive");
-
+ }
+ Lex();
+
+ if (CaseInsensitive)
+ TheCondState.CondMet =
+ ExpectEqual == (StringRef(String1).equals_lower(String2));
+ else
+ TheCondState.CondMet = ExpectEqual == (String1 == String2);
+ TheCondState.Ignore = !TheCondState.CondMet;
+
+ if ((CaseInsensitive &&
+ ExpectEqual == StringRef(String1).equals_lower(String2)) ||
+ (ExpectEqual == (String1 == String2)))
+ return Error(DirectiveLoc, Message);
+ return false;
+}
+
+/// parseDirectiveErrorIfe
+/// ::= .erre expression[, message]
+bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+ }
+
+ int64_t ExprValue;
+ if (parseAbsoluteExpression(ExprValue))
+ return addErrorSuffix(" in '.erre' directive");
+
std::string Message = ".erre directive invoked in source file";
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (parseToken(AsmToken::Comma))
- return addErrorSuffix(" in '.erre' directive");
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (parseToken(AsmToken::Comma))
+ return addErrorSuffix(" in '.erre' directive");
Message = parseStringTo(AsmToken::EndOfStatement);
- }
- Lex();
-
- if ((ExprValue == 0) == ExpectZero)
- return Error(DirectiveLoc, Message);
- return false;
-}
-
-/// parseDirectiveEndIf
-/// ::= .endif
-bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.endif' directive"))
- return true;
-
- if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
- return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
- "an .if or .else");
- if (!TheCondStack.empty()) {
- TheCondState = TheCondStack.back();
- TheCondStack.pop_back();
- }
-
- return false;
-}
-
-void MasmParser::initializeDirectiveKindMap() {
- DirectiveKindMap["="] = DK_ASSIGN;
- DirectiveKindMap["equ"] = DK_EQU;
- DirectiveKindMap["textequ"] = DK_TEXTEQU;
- // DirectiveKindMap[".ascii"] = DK_ASCII;
- // DirectiveKindMap[".asciz"] = DK_ASCIZ;
- // DirectiveKindMap[".string"] = DK_STRING;
- DirectiveKindMap["byte"] = DK_BYTE;
- DirectiveKindMap["sbyte"] = DK_SBYTE;
- DirectiveKindMap["word"] = DK_WORD;
- DirectiveKindMap["sword"] = DK_SWORD;
- DirectiveKindMap["dword"] = DK_DWORD;
- DirectiveKindMap["sdword"] = DK_SDWORD;
- DirectiveKindMap["fword"] = DK_FWORD;
- DirectiveKindMap["qword"] = DK_QWORD;
- DirectiveKindMap["sqword"] = DK_SQWORD;
- DirectiveKindMap["real4"] = DK_REAL4;
- DirectiveKindMap["real8"] = DK_REAL8;
+ }
+ Lex();
+
+ if ((ExprValue == 0) == ExpectZero)
+ return Error(DirectiveLoc, Message);
+ return false;
+}
+
+/// parseDirectiveEndIf
+/// ::= .endif
+bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.endif' directive"))
+ return true;
+
+ if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
+ return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
+ "an .if or .else");
+ if (!TheCondStack.empty()) {
+ TheCondState = TheCondStack.back();
+ TheCondStack.pop_back();
+ }
+
+ return false;
+}
+
+void MasmParser::initializeDirectiveKindMap() {
+ DirectiveKindMap["="] = DK_ASSIGN;
+ DirectiveKindMap["equ"] = DK_EQU;
+ DirectiveKindMap["textequ"] = DK_TEXTEQU;
+ // DirectiveKindMap[".ascii"] = DK_ASCII;
+ // DirectiveKindMap[".asciz"] = DK_ASCIZ;
+ // DirectiveKindMap[".string"] = DK_STRING;
+ DirectiveKindMap["byte"] = DK_BYTE;
+ DirectiveKindMap["sbyte"] = DK_SBYTE;
+ DirectiveKindMap["word"] = DK_WORD;
+ DirectiveKindMap["sword"] = DK_SWORD;
+ DirectiveKindMap["dword"] = DK_DWORD;
+ DirectiveKindMap["sdword"] = DK_SDWORD;
+ DirectiveKindMap["fword"] = DK_FWORD;
+ DirectiveKindMap["qword"] = DK_QWORD;
+ DirectiveKindMap["sqword"] = DK_SQWORD;
+ DirectiveKindMap["real4"] = DK_REAL4;
+ DirectiveKindMap["real8"] = DK_REAL8;
DirectiveKindMap["real10"] = DK_REAL10;
- DirectiveKindMap["align"] = DK_ALIGN;
- // DirectiveKindMap[".org"] = DK_ORG;
- DirectiveKindMap["extern"] = DK_EXTERN;
- DirectiveKindMap["public"] = DK_PUBLIC;
- // DirectiveKindMap[".comm"] = DK_COMM;
- DirectiveKindMap["comment"] = DK_COMMENT;
- DirectiveKindMap["include"] = DK_INCLUDE;
+ DirectiveKindMap["align"] = DK_ALIGN;
+ // DirectiveKindMap[".org"] = DK_ORG;
+ DirectiveKindMap["extern"] = DK_EXTERN;
+ DirectiveKindMap["public"] = DK_PUBLIC;
+ // DirectiveKindMap[".comm"] = DK_COMM;
+ DirectiveKindMap["comment"] = DK_COMMENT;
+ DirectiveKindMap["include"] = DK_INCLUDE;
DirectiveKindMap["repeat"] = DK_REPEAT;
DirectiveKindMap["rept"] = DK_REPEAT;
DirectiveKindMap["while"] = DK_WHILE;
@@ -6394,95 +6394,95 @@ void MasmParser::initializeDirectiveKindMap() {
DirectiveKindMap["irp"] = DK_FOR;
DirectiveKindMap["forc"] = DK_FORC;
DirectiveKindMap["irpc"] = DK_FORC;
- DirectiveKindMap["if"] = DK_IF;
- DirectiveKindMap["ife"] = DK_IFE;
- DirectiveKindMap["ifb"] = DK_IFB;
- DirectiveKindMap["ifnb"] = DK_IFNB;
- DirectiveKindMap["ifdef"] = DK_IFDEF;
- DirectiveKindMap["ifndef"] = DK_IFNDEF;
- DirectiveKindMap["ifdif"] = DK_IFDIF;
- DirectiveKindMap["ifdifi"] = DK_IFDIFI;
- DirectiveKindMap["ifidn"] = DK_IFIDN;
- DirectiveKindMap["ifidni"] = DK_IFIDNI;
- DirectiveKindMap["elseif"] = DK_ELSEIF;
- DirectiveKindMap["elseifdef"] = DK_ELSEIFDEF;
- DirectiveKindMap["elseifndef"] = DK_ELSEIFNDEF;
- DirectiveKindMap["elseifdif"] = DK_ELSEIFDIF;
- DirectiveKindMap["elseifidn"] = DK_ELSEIFIDN;
- DirectiveKindMap["else"] = DK_ELSE;
- DirectiveKindMap["end"] = DK_END;
- DirectiveKindMap["endif"] = DK_ENDIF;
- // DirectiveKindMap[".file"] = DK_FILE;
- // DirectiveKindMap[".line"] = DK_LINE;
- // 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_string"] = DK_CV_STRING;
- // DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
- // DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
- // DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
- // DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
- // DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
- // DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
- // DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
- // DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
- // DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
- // DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
- // DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
- // DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
- // DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
- // DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
- // DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
- // DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
- // DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
- // DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
- // DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
- // DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
- // DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
- // DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
- // DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
- // DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
- // DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
- // DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
+ DirectiveKindMap["if"] = DK_IF;
+ DirectiveKindMap["ife"] = DK_IFE;
+ DirectiveKindMap["ifb"] = DK_IFB;
+ DirectiveKindMap["ifnb"] = DK_IFNB;
+ DirectiveKindMap["ifdef"] = DK_IFDEF;
+ DirectiveKindMap["ifndef"] = DK_IFNDEF;
+ DirectiveKindMap["ifdif"] = DK_IFDIF;
+ DirectiveKindMap["ifdifi"] = DK_IFDIFI;
+ DirectiveKindMap["ifidn"] = DK_IFIDN;
+ DirectiveKindMap["ifidni"] = DK_IFIDNI;
+ DirectiveKindMap["elseif"] = DK_ELSEIF;
+ DirectiveKindMap["elseifdef"] = DK_ELSEIFDEF;
+ DirectiveKindMap["elseifndef"] = DK_ELSEIFNDEF;
+ DirectiveKindMap["elseifdif"] = DK_ELSEIFDIF;
+ DirectiveKindMap["elseifidn"] = DK_ELSEIFIDN;
+ DirectiveKindMap["else"] = DK_ELSE;
+ DirectiveKindMap["end"] = DK_END;
+ DirectiveKindMap["endif"] = DK_ENDIF;
+ // DirectiveKindMap[".file"] = DK_FILE;
+ // DirectiveKindMap[".line"] = DK_LINE;
+ // 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_string"] = DK_CV_STRING;
+ // DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
+ // DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
+ // DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
+ // DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
+ // DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
+ // DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
+ // DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
+ // DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
+ // DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
+ // DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
+ // DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
+ // DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
+ // DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
+ // DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
+ // DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
+ // DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
+ // DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
+ // DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
+ // DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
+ // DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
+ // DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
+ // DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
+ // DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
+ // DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
+ // DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
+ // DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
DirectiveKindMap["macro"] = DK_MACRO;
DirectiveKindMap["exitm"] = DK_EXITM;
DirectiveKindMap["endm"] = DK_ENDM;
DirectiveKindMap["purge"] = DK_PURGE;
- DirectiveKindMap[".err"] = DK_ERR;
- DirectiveKindMap[".errb"] = DK_ERRB;
- DirectiveKindMap[".errnb"] = DK_ERRNB;
- DirectiveKindMap[".errdef"] = DK_ERRDEF;
- DirectiveKindMap[".errndef"] = DK_ERRNDEF;
- DirectiveKindMap[".errdif"] = DK_ERRDIF;
- DirectiveKindMap[".errdifi"] = DK_ERRDIFI;
- DirectiveKindMap[".erridn"] = DK_ERRIDN;
- DirectiveKindMap[".erridni"] = DK_ERRIDNI;
- DirectiveKindMap[".erre"] = DK_ERRE;
- DirectiveKindMap[".errnz"] = DK_ERRNZ;
+ DirectiveKindMap[".err"] = DK_ERR;
+ DirectiveKindMap[".errb"] = DK_ERRB;
+ DirectiveKindMap[".errnb"] = DK_ERRNB;
+ DirectiveKindMap[".errdef"] = DK_ERRDEF;
+ DirectiveKindMap[".errndef"] = DK_ERRNDEF;
+ DirectiveKindMap[".errdif"] = DK_ERRDIF;
+ DirectiveKindMap[".errdifi"] = DK_ERRDIFI;
+ DirectiveKindMap[".erridn"] = DK_ERRIDN;
+ DirectiveKindMap[".erridni"] = DK_ERRIDNI;
+ DirectiveKindMap[".erre"] = DK_ERRE;
+ DirectiveKindMap[".errnz"] = DK_ERRNZ;
DirectiveKindMap[".pushframe"] = DK_PUSHFRAME;
DirectiveKindMap[".pushreg"] = DK_PUSHREG;
DirectiveKindMap[".savereg"] = DK_SAVEREG;
DirectiveKindMap[".savexmm128"] = DK_SAVEXMM128;
DirectiveKindMap[".setframe"] = DK_SETFRAME;
DirectiveKindMap[".radix"] = DK_RADIX;
- DirectiveKindMap["db"] = DK_DB;
- DirectiveKindMap["dd"] = DK_DD;
+ DirectiveKindMap["db"] = DK_DB;
+ DirectiveKindMap["dd"] = DK_DD;
DirectiveKindMap["df"] = DK_DF;
- DirectiveKindMap["dq"] = DK_DQ;
- DirectiveKindMap["dw"] = DK_DW;
- DirectiveKindMap["echo"] = DK_ECHO;
- DirectiveKindMap["struc"] = DK_STRUCT;
- DirectiveKindMap["struct"] = DK_STRUCT;
- DirectiveKindMap["union"] = DK_UNION;
- DirectiveKindMap["ends"] = DK_ENDS;
-}
-
+ DirectiveKindMap["dq"] = DK_DQ;
+ DirectiveKindMap["dw"] = DK_DW;
+ DirectiveKindMap["echo"] = DK_ECHO;
+ DirectiveKindMap["struc"] = DK_STRUCT;
+ DirectiveKindMap["struct"] = DK_STRUCT;
+ DirectiveKindMap["union"] = DK_UNION;
+ DirectiveKindMap["ends"] = DK_ENDS;
+}
+
bool MasmParser::isMacroLikeDirective() {
if (getLexer().is(AsmToken::Identifier)) {
bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
@@ -6501,48 +6501,48 @@ bool MasmParser::isMacroLikeDirective() {
return false;
}
-MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
- AsmToken EndToken, StartToken = getTok();
-
- unsigned NestLevel = 0;
- while (true) {
- // Check whether we have reached the end of the file.
- if (getLexer().is(AsmToken::Eof)) {
+MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
+ AsmToken EndToken, StartToken = getTok();
+
+ unsigned NestLevel = 0;
+ while (true) {
+ // Check whether we have reached the end of the file.
+ if (getLexer().is(AsmToken::Eof)) {
printError(DirectiveLoc, "no matching 'endm' in definition");
- return nullptr;
- }
-
+ return nullptr;
+ }
+
if (isMacroLikeDirective())
- ++NestLevel;
-
+ ++NestLevel;
+
// Otherwise, check whether we have reached the endm.
if (Lexer.is(AsmToken::Identifier) &&
getTok().getIdentifier().equals_lower("endm")) {
- if (NestLevel == 0) {
- EndToken = getTok();
- Lex();
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (NestLevel == 0) {
+ EndToken = getTok();
+ Lex();
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
printError(getTok().getLoc(), "unexpected token in 'endm' directive");
- return nullptr;
- }
- break;
- }
- --NestLevel;
- }
-
- // Otherwise, scan till the end of the statement.
- eatToEndOfStatement();
- }
-
- const char *BodyStart = StartToken.getLoc().getPointer();
- const char *BodyEnd = EndToken.getLoc().getPointer();
- StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
-
- // We Are Anonymous.
- MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
- return &MacroLikeBodies.back();
-}
-
+ return nullptr;
+ }
+ break;
+ }
+ --NestLevel;
+ }
+
+ // Otherwise, scan till the end of the statement.
+ eatToEndOfStatement();
+ }
+
+ const char *BodyStart = StartToken.getLoc().getPointer();
+ const char *BodyEnd = EndToken.getLoc().getPointer();
+ StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
+
+ // We Are Anonymous.
+ MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
+ return &MacroLikeBodies.back();
+}
+
bool MasmParser::expandStatement(SMLoc Loc) {
std::string Body = parseStringTo(AsmToken::EndOfStatement);
SMLoc EndLoc = getTok().getLoc();
@@ -6580,69 +6580,69 @@ bool MasmParser::expandStatement(SMLoc Loc) {
return false;
}
-void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
- raw_svector_ostream &OS) {
+void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
+ raw_svector_ostream &OS) {
instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/getTok().getLoc(), OS);
}
void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
SMLoc ExitLoc,
raw_svector_ostream &OS) {
OS << "endm\n";
-
- std::unique_ptr<MemoryBuffer> Instantiation =
- MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
-
- // Create the macro instantiation object and add to the current macro
- // instantiation stack.
+
+ std::unique_ptr<MemoryBuffer> Instantiation =
+ MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
+
+ // Create the macro instantiation object and add to the current macro
+ // instantiation stack.
MacroInstantiation *MI = new MacroInstantiation{DirectiveLoc, CurBuffer,
ExitLoc, TheCondStack.size()};
- ActiveMacros.push_back(MI);
-
- // Jump to the macro instantiation and prime the lexer.
- CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
+ ActiveMacros.push_back(MI);
+
+ // Jump to the macro instantiation and prime the lexer.
+ CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
EndStatementAtEOFStack.push_back(true);
- Lex();
-}
-
+ Lex();
+}
+
/// parseDirectiveRepeat
/// ::= ("repeat" | "rept") count
/// body
/// endm
bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
- const MCExpr *CountExpr;
- SMLoc CountLoc = getTok().getLoc();
- if (parseExpression(CountExpr))
- return true;
-
- int64_t Count;
- if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
- return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
- }
-
- if (check(Count < 0, CountLoc, "Count is negative") ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '" + Dir + "' directive"))
- return true;
-
+ const MCExpr *CountExpr;
+ SMLoc CountLoc = getTok().getLoc();
+ if (parseExpression(CountExpr))
+ return true;
+
+ int64_t Count;
+ if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
+ return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
+ }
+
+ if (check(Count < 0, CountLoc, "Count is negative") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '" + Dir + "' directive"))
+ return true;
+
// Lex the repeat definition.
- MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
- if (!M)
- return true;
-
- // Macro instantiation is lexical, unfortunately. We construct a new buffer
- // to hold the macro body with substitutions.
- SmallString<256> Buf;
- raw_svector_ostream OS(Buf);
- while (Count--) {
+ MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
+ if (!M)
+ return true;
+
+ // Macro instantiation is lexical, unfortunately. We construct a new buffer
+ // to hold the macro body with substitutions.
+ SmallString<256> Buf;
+ raw_svector_ostream OS(Buf);
+ while (Count--) {
if (expandMacro(OS, M->Body, None, None, M->Locals, getTok().getLoc()))
- return true;
- }
- instantiateMacroLikeBody(M, DirectiveLoc, OS);
-
- return false;
-}
-
+ return true;
+ }
+ instantiateMacroLikeBody(M, DirectiveLoc, OS);
+
+ return false;
+}
+
/// parseDirectiveWhile
/// ::= "while" expression
/// body
@@ -6681,9 +6681,9 @@ bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
/// body
/// endm
bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
- MCAsmMacroParameter Parameter;
- MCAsmMacroArguments A;
- if (check(parseIdentifier(Parameter.Name),
+ MCAsmMacroParameter Parameter;
+ MCAsmMacroArguments A;
+ if (check(parseIdentifier(Parameter.Name),
"expected identifier in '" + Dir + "' directive"))
return true;
@@ -6737,42 +6737,42 @@ bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
if (parseToken(AsmToken::Greater,
"values in '" + Dir +
"' directive must be enclosed in angle brackets") ||
- parseToken(AsmToken::EndOfStatement, "expected End of Statement"))
- return true;
-
+ parseToken(AsmToken::EndOfStatement, "expected End of Statement"))
+ return true;
+
// Lex the for definition.
- MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
- if (!M)
- return true;
-
- // Macro instantiation is lexical, unfortunately. We construct a new buffer
- // to hold the macro body with substitutions.
- SmallString<256> Buf;
- raw_svector_ostream OS(Buf);
-
- for (const MCAsmMacroArgument &Arg : A) {
+ MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
+ if (!M)
+ return true;
+
+ // Macro instantiation is lexical, unfortunately. We construct a new buffer
+ // to hold the macro body with substitutions.
+ SmallString<256> Buf;
+ raw_svector_ostream OS(Buf);
+
+ for (const MCAsmMacroArgument &Arg : A) {
if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
- return true;
- }
-
- instantiateMacroLikeBody(M, DirectiveLoc, OS);
-
- return false;
-}
-
+ return true;
+ }
+
+ instantiateMacroLikeBody(M, DirectiveLoc, OS);
+
+ return false;
+}
+
/// parseDirectiveForc
/// ::= ("forc" | "irpc") symbol, <string>
/// body
/// endm
bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
- MCAsmMacroParameter Parameter;
-
+ MCAsmMacroParameter Parameter;
+
std::string Argument;
- if (check(parseIdentifier(Parameter.Name),
+ if (check(parseIdentifier(Parameter.Name),
"expected identifier in '" + Directive + "' directive") ||
parseToken(AsmToken::Comma,
"expected comma in '" + Directive + "' directive"))
- return true;
+ return true;
if (parseAngleBracketString(Argument)) {
// Match ml64.exe; treat all characters to end of statement as a string,
// ignoring comment markers, then discard anything following a space (using
@@ -6787,66 +6787,66 @@ bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
}
Argument.resize(End);
}
- if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
- return true;
-
- // Lex the irpc definition.
- MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
- if (!M)
- return true;
-
- // Macro instantiation is lexical, unfortunately. We construct a new buffer
- // to hold the macro body with substitutions.
- SmallString<256> Buf;
- raw_svector_ostream OS(Buf);
-
+ if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
+ return true;
+
+ // Lex the irpc definition.
+ MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
+ if (!M)
+ return true;
+
+ // Macro instantiation is lexical, unfortunately. We construct a new buffer
+ // to hold the macro body with substitutions.
+ SmallString<256> Buf;
+ raw_svector_ostream OS(Buf);
+
StringRef Values(Argument);
- for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
- MCAsmMacroArgument Arg;
- Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
-
+ for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
+ MCAsmMacroArgument Arg;
+ Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
+
if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
- return true;
- }
-
- instantiateMacroLikeBody(M, DirectiveLoc, OS);
-
- return false;
-}
-
-bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
- size_t Len) {
- const MCExpr *Value;
- SMLoc ExprLoc = getLexer().getLoc();
- if (parseExpression(Value))
- return true;
- const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
- if (!MCE)
- return Error(ExprLoc, "unexpected expression in _emit");
- uint64_t IntValue = MCE->getValue();
- if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
- return Error(ExprLoc, "literal value out of range for directive");
-
- Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
- return false;
-}
-
-bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
- const MCExpr *Value;
- SMLoc ExprLoc = getLexer().getLoc();
- if (parseExpression(Value))
- return true;
- const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
- if (!MCE)
- return Error(ExprLoc, "unexpected expression in align");
- uint64_t IntValue = MCE->getValue();
- if (!isPowerOf2_64(IntValue))
- return Error(ExprLoc, "literal value not a power of two greater then zero");
-
- Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
- return false;
-}
-
+ return true;
+ }
+
+ instantiateMacroLikeBody(M, DirectiveLoc, OS);
+
+ return false;
+}
+
+bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
+ size_t Len) {
+ const MCExpr *Value;
+ SMLoc ExprLoc = getLexer().getLoc();
+ if (parseExpression(Value))
+ return true;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
+ if (!MCE)
+ return Error(ExprLoc, "unexpected expression in _emit");
+ uint64_t IntValue = MCE->getValue();
+ if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
+ return Error(ExprLoc, "literal value out of range for directive");
+
+ Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
+ return false;
+}
+
+bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
+ const MCExpr *Value;
+ SMLoc ExprLoc = getLexer().getLoc();
+ if (parseExpression(Value))
+ return true;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
+ if (!MCE)
+ return Error(ExprLoc, "unexpected expression in align");
+ uint64_t IntValue = MCE->getValue();
+ if (!isPowerOf2_64(IntValue))
+ return Error(ExprLoc, "literal value not a power of two greater then zero");
+
+ Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
+ return false;
+}
+
bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
const SMLoc Loc = getLexer().getLoc();
std::string RadixStringRaw = parseStringTo(AsmToken::EndOfStatement);
@@ -6866,7 +6866,7 @@ bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
/// parseDirectiveEcho
/// ::= "echo" message
-bool MasmParser::parseDirectiveEcho() {
+bool MasmParser::parseDirectiveEcho() {
// We're called before the directive is parsed, to avoid triggering lexical
// substitutions in the message. Assert that the next token is the directive,
// then eat it without using the Parser's Lex method.
@@ -6878,32 +6878,32 @@ bool MasmParser::parseDirectiveEcho() {
llvm::outs() << Message;
if (!StringRef(Message).endswith("\n"))
llvm::outs() << '\n';
- return false;
-}
-
-// We are comparing pointers, but the pointers are relative to a single string.
-// Thus, this should always be deterministic.
-static int rewritesSort(const AsmRewrite *AsmRewriteA,
- const AsmRewrite *AsmRewriteB) {
- if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
- return -1;
- if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
- return 1;
-
- // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
- // rewrite to the same location. Make sure the SizeDirective rewrite is
- // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
- // ensures the sort algorithm is stable.
- if (AsmRewritePrecedence[AsmRewriteA->Kind] >
- AsmRewritePrecedence[AsmRewriteB->Kind])
- return -1;
-
- if (AsmRewritePrecedence[AsmRewriteA->Kind] <
- AsmRewritePrecedence[AsmRewriteB->Kind])
- return 1;
- llvm_unreachable("Unstable rewrite sort.");
-}
-
+ return false;
+}
+
+// We are comparing pointers, but the pointers are relative to a single string.
+// Thus, this should always be deterministic.
+static int rewritesSort(const AsmRewrite *AsmRewriteA,
+ const AsmRewrite *AsmRewriteB) {
+ if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
+ return -1;
+ if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
+ return 1;
+
+ // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
+ // rewrite to the same location. Make sure the SizeDirective rewrite is
+ // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
+ // ensures the sort algorithm is stable.
+ if (AsmRewritePrecedence[AsmRewriteA->Kind] >
+ AsmRewritePrecedence[AsmRewriteB->Kind])
+ return -1;
+
+ if (AsmRewritePrecedence[AsmRewriteA->Kind] <
+ AsmRewritePrecedence[AsmRewriteB->Kind])
+ return 1;
+ llvm_unreachable("Unstable rewrite sort.");
+}
+
bool MasmParser::defineMacro(StringRef Name, StringRef Value) {
Variable &Var = Variables[Name.lower()];
if (Var.Name.empty()) {
@@ -6918,76 +6918,76 @@ bool MasmParser::defineMacro(StringRef Name, StringRef Value) {
}
bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info) const {
- const std::pair<StringRef, StringRef> BaseMember = Name.split('.');
- const StringRef Base = BaseMember.first, Member = BaseMember.second;
+ const std::pair<StringRef, StringRef> BaseMember = Name.split('.');
+ const StringRef Base = BaseMember.first, Member = BaseMember.second;
return lookUpField(Base, Member, Info);
-}
-
+}
+
bool MasmParser::lookUpField(StringRef Base, StringRef Member,
AsmFieldInfo &Info) const {
- if (Base.empty())
- return true;
-
+ if (Base.empty())
+ return true;
+
AsmFieldInfo BaseInfo;
if (Base.contains('.') && !lookUpField(Base, BaseInfo))
Base = BaseInfo.Type.Name;
-
- auto StructIt = Structs.find(Base.lower());
+
+ auto StructIt = Structs.find(Base.lower());
auto TypeIt = KnownType.find(Base.lower());
if (TypeIt != KnownType.end()) {
StructIt = Structs.find(TypeIt->second.Name.lower());
}
- if (StructIt != Structs.end())
+ if (StructIt != Structs.end())
return lookUpField(StructIt->second, Member, Info);
-
- return true;
-}
-
-bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
+
+ return true;
+}
+
+bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
AsmFieldInfo &Info) const {
- if (Member.empty()) {
+ if (Member.empty()) {
Info.Type.Name = Structure.Name;
Info.Type.Size = Structure.Size;
Info.Type.ElementSize = Structure.Size;
Info.Type.Length = 1;
- return false;
- }
-
- std::pair<StringRef, StringRef> Split = Member.split('.');
- const StringRef FieldName = Split.first, FieldMember = Split.second;
-
- auto StructIt = Structs.find(FieldName.lower());
- if (StructIt != Structs.end())
+ return false;
+ }
+
+ std::pair<StringRef, StringRef> Split = Member.split('.');
+ const StringRef FieldName = Split.first, FieldMember = Split.second;
+
+ auto StructIt = Structs.find(FieldName.lower());
+ if (StructIt != Structs.end())
return lookUpField(StructIt->second, FieldMember, Info);
-
- auto FieldIt = Structure.FieldsByName.find(FieldName.lower());
- if (FieldIt == Structure.FieldsByName.end())
- return true;
-
- const FieldInfo &Field = Structure.Fields[FieldIt->second];
- if (FieldMember.empty()) {
+
+ auto FieldIt = Structure.FieldsByName.find(FieldName.lower());
+ if (FieldIt == Structure.FieldsByName.end())
+ return true;
+
+ const FieldInfo &Field = Structure.Fields[FieldIt->second];
+ if (FieldMember.empty()) {
Info.Offset += Field.Offset;
Info.Type.Size = Field.SizeOf;
Info.Type.ElementSize = Field.Type;
Info.Type.Length = Field.LengthOf;
- if (Field.Contents.FT == FT_STRUCT)
+ if (Field.Contents.FT == FT_STRUCT)
Info.Type.Name = Field.Contents.StructInfo.Structure.Name;
else
Info.Type.Name = "";
- return false;
- }
-
- if (Field.Contents.FT != FT_STRUCT)
- return true;
- const StructFieldInfo &StructInfo = Field.Contents.StructInfo;
-
+ return false;
+ }
+
+ if (Field.Contents.FT != FT_STRUCT)
+ return true;
+ const StructFieldInfo &StructInfo = Field.Contents.StructInfo;
+
if (lookUpField(StructInfo.Structure, FieldMember, Info))
- return true;
-
+ return true;
+
Info.Offset += Field.Offset;
- return false;
-}
-
+ return false;
+}
+
bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const {
unsigned Size = StringSwitch<unsigned>(Name)
.CasesLower("byte", "db", "sbyte", 1)
@@ -7020,273 +7020,273 @@ bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const {
return true;
}
-bool MasmParser::parseMSInlineAsm(
- void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
- unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
- SmallVectorImpl<std::string> &Constraints,
- SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
- const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
- SmallVector<void *, 4> InputDecls;
- SmallVector<void *, 4> OutputDecls;
- SmallVector<bool, 4> InputDeclsAddressOf;
- SmallVector<bool, 4> OutputDeclsAddressOf;
- SmallVector<std::string, 4> InputConstraints;
- SmallVector<std::string, 4> OutputConstraints;
- SmallVector<unsigned, 4> ClobberRegs;
-
- SmallVector<AsmRewrite, 4> AsmStrRewrites;
-
- // Prime the lexer.
- Lex();
-
- // While we have input, parse each statement.
- unsigned InputIdx = 0;
- unsigned OutputIdx = 0;
- while (getLexer().isNot(AsmToken::Eof)) {
- // Parse curly braces marking block start/end.
- if (parseCurlyBlockScope(AsmStrRewrites))
- continue;
-
- ParseStatementInfo Info(&AsmStrRewrites);
- bool StatementErr = parseStatement(Info, &SI);
-
- 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;
-
- const MCInstrDesc &Desc = MII->get(Info.Opcode);
-
- // Build the list of clobbers, outputs and inputs.
- for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
- MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
-
- // Register operand.
- if (Operand.isReg() && !Operand.needAddressOf() &&
- !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
- unsigned NumDefs = Desc.getNumDefs();
- // Clobber.
- if (NumDefs && Operand.getMCOperandNum() < NumDefs)
- ClobberRegs.push_back(Operand.getReg());
- continue;
- }
-
- // Expr/Input or Output.
- StringRef SymName = Operand.getSymName();
- if (SymName.empty())
- continue;
-
- void *OpDecl = Operand.getOpDecl();
- if (!OpDecl)
- continue;
-
- StringRef Constraint = Operand.getConstraint();
- if (Operand.isImm()) {
- // Offset as immediate.
- if (Operand.isOffsetOfLocal())
- Constraint = "r";
- else
- Constraint = "i";
- }
-
- bool isOutput = (i == 1) && Desc.mayStore();
- SMLoc Start = SMLoc::getFromPointer(SymName.data());
- if (isOutput) {
- ++InputIdx;
- OutputDecls.push_back(OpDecl);
- OutputDeclsAddressOf.push_back(Operand.needAddressOf());
- OutputConstraints.push_back(("=" + Constraint).str());
- AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
- } else {
- InputDecls.push_back(OpDecl);
- InputDeclsAddressOf.push_back(Operand.needAddressOf());
- InputConstraints.push_back(Constraint.str());
- if (Desc.OpInfo[i - 1].isBranchTarget())
- AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
- else
- AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
- }
- }
-
- // Consider implicit defs to be clobbers. Think of cpuid and push.
- ArrayRef<MCPhysReg> ImpDefs(Desc.getImplicitDefs(),
- Desc.getNumImplicitDefs());
+bool MasmParser::parseMSInlineAsm(
+ void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
+ unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
+ SmallVectorImpl<std::string> &Constraints,
+ SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
+ const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
+ SmallVector<void *, 4> InputDecls;
+ SmallVector<void *, 4> OutputDecls;
+ SmallVector<bool, 4> InputDeclsAddressOf;
+ SmallVector<bool, 4> OutputDeclsAddressOf;
+ SmallVector<std::string, 4> InputConstraints;
+ SmallVector<std::string, 4> OutputConstraints;
+ SmallVector<unsigned, 4> ClobberRegs;
+
+ SmallVector<AsmRewrite, 4> AsmStrRewrites;
+
+ // Prime the lexer.
+ Lex();
+
+ // While we have input, parse each statement.
+ unsigned InputIdx = 0;
+ unsigned OutputIdx = 0;
+ while (getLexer().isNot(AsmToken::Eof)) {
+ // Parse curly braces marking block start/end.
+ if (parseCurlyBlockScope(AsmStrRewrites))
+ continue;
+
+ ParseStatementInfo Info(&AsmStrRewrites);
+ bool StatementErr = parseStatement(Info, &SI);
+
+ 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;
+
+ const MCInstrDesc &Desc = MII->get(Info.Opcode);
+
+ // Build the list of clobbers, outputs and inputs.
+ for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
+ MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
+
+ // Register operand.
+ if (Operand.isReg() && !Operand.needAddressOf() &&
+ !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
+ unsigned NumDefs = Desc.getNumDefs();
+ // Clobber.
+ if (NumDefs && Operand.getMCOperandNum() < NumDefs)
+ ClobberRegs.push_back(Operand.getReg());
+ continue;
+ }
+
+ // Expr/Input or Output.
+ StringRef SymName = Operand.getSymName();
+ if (SymName.empty())
+ continue;
+
+ void *OpDecl = Operand.getOpDecl();
+ if (!OpDecl)
+ continue;
+
+ StringRef Constraint = Operand.getConstraint();
+ if (Operand.isImm()) {
+ // Offset as immediate.
+ if (Operand.isOffsetOfLocal())
+ Constraint = "r";
+ else
+ Constraint = "i";
+ }
+
+ bool isOutput = (i == 1) && Desc.mayStore();
+ SMLoc Start = SMLoc::getFromPointer(SymName.data());
+ if (isOutput) {
+ ++InputIdx;
+ OutputDecls.push_back(OpDecl);
+ OutputDeclsAddressOf.push_back(Operand.needAddressOf());
+ OutputConstraints.push_back(("=" + Constraint).str());
+ AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
+ } else {
+ InputDecls.push_back(OpDecl);
+ InputDeclsAddressOf.push_back(Operand.needAddressOf());
+ InputConstraints.push_back(Constraint.str());
+ if (Desc.OpInfo[i - 1].isBranchTarget())
+ AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
+ else
+ AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
+ }
+ }
+
+ // Consider implicit defs to be clobbers. Think of cpuid and push.
+ ArrayRef<MCPhysReg> ImpDefs(Desc.getImplicitDefs(),
+ Desc.getNumImplicitDefs());
llvm::append_range(ClobberRegs, ImpDefs);
- }
-
- // Set the number of Outputs and Inputs.
- NumOutputs = OutputDecls.size();
- NumInputs = InputDecls.size();
-
- // Set the unique clobbers.
- array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
- ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
- ClobberRegs.end());
- Clobbers.assign(ClobberRegs.size(), std::string());
- for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
- raw_string_ostream OS(Clobbers[I]);
- IP->printRegName(OS, ClobberRegs[I]);
- }
-
- // Merge the various outputs and inputs. Output are expected first.
- if (NumOutputs || NumInputs) {
- unsigned NumExprs = NumOutputs + NumInputs;
- OpDecls.resize(NumExprs);
- Constraints.resize(NumExprs);
- for (unsigned i = 0; i < NumOutputs; ++i) {
- OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
- Constraints[i] = OutputConstraints[i];
- }
- for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
- OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
- Constraints[j] = InputConstraints[i];
- }
- }
-
- // Build the IR assembly string.
- std::string AsmStringIR;
- raw_string_ostream OS(AsmStringIR);
- StringRef ASMString =
- SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
- const char *AsmStart = ASMString.begin();
- const char *AsmEnd = ASMString.end();
- array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
- for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) {
- const AsmRewrite &AR = *it;
- // Check if this has already been covered by another rewrite...
- if (AR.Done)
- continue;
- AsmRewriteKind Kind = AR.Kind;
-
- const char *Loc = AR.Loc.getPointer();
- assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
-
- // Emit everything up to the immediate/expression.
- if (unsigned Len = Loc - AsmStart)
- OS << StringRef(AsmStart, Len);
-
- // Skip the original expression.
- if (Kind == AOK_Skip) {
- AsmStart = Loc + AR.Len;
- continue;
- }
-
- unsigned AdditionalSkip = 0;
- // Rewrite expressions in $N notation.
- switch (Kind) {
- default:
- break;
- case AOK_IntelExpr:
- assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
- if (AR.IntelExp.NeedBracs)
- OS << "[";
- if (AR.IntelExp.hasBaseReg())
- OS << AR.IntelExp.BaseReg;
- if (AR.IntelExp.hasIndexReg())
- OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
- << AR.IntelExp.IndexReg;
- if (AR.IntelExp.Scale > 1)
- OS << " * $$" << AR.IntelExp.Scale;
- if (AR.IntelExp.hasOffset()) {
- if (AR.IntelExp.hasRegs())
- OS << " + ";
- // Fuse this rewrite with a rewrite of the offset name, if present.
- StringRef OffsetName = AR.IntelExp.OffsetName;
- SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
- size_t OffsetLen = OffsetName.size();
- auto rewrite_it = std::find_if(
- it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
- return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
- (FusingAR.Kind == AOK_Input ||
- FusingAR.Kind == AOK_CallInput);
- });
- if (rewrite_it == AsmStrRewrites.end()) {
- OS << "offset " << OffsetName;
- } else if (rewrite_it->Kind == AOK_CallInput) {
- OS << "${" << InputIdx++ << ":P}";
- rewrite_it->Done = true;
- } else {
- OS << '$' << InputIdx++;
- rewrite_it->Done = true;
- }
- }
- if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
- OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
- if (AR.IntelExp.NeedBracs)
- OS << "]";
- break;
- case AOK_Label:
- OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
- break;
- case AOK_Input:
- OS << '$' << InputIdx++;
- break;
- case AOK_CallInput:
- OS << "${" << InputIdx++ << ":P}";
- break;
- case AOK_Output:
- OS << '$' << OutputIdx++;
- break;
- case AOK_SizeDirective:
- switch (AR.Val) {
- default: break;
- case 8: OS << "byte ptr "; break;
- case 16: OS << "word ptr "; break;
- case 32: OS << "dword ptr "; break;
- case 64: OS << "qword ptr "; break;
- case 80: OS << "xword ptr "; break;
- case 128: OS << "xmmword ptr "; break;
- case 256: OS << "ymmword ptr "; break;
- }
- break;
- case AOK_Emit:
- OS << ".byte";
- break;
- case AOK_Align: {
- // MS alignment directives are measured in bytes. If the native assembler
- // measures alignment in bytes, we can pass it straight through.
- OS << ".align";
- if (getContext().getAsmInfo()->getAlignmentIsInBytes())
- break;
-
- // Alignment is in log2 form, so print that instead and skip the original
- // immediate.
- unsigned Val = AR.Val;
- OS << ' ' << Val;
- assert(Val < 10 && "Expected alignment less then 2^10.");
- AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
- break;
- }
- case AOK_EVEN:
- OS << ".even";
- break;
- case AOK_EndOfStatement:
- OS << "\n\t";
- break;
- }
-
- // Skip the original expression.
- AsmStart = Loc + AR.Len + AdditionalSkip;
- }
-
- // Emit the remainder of the asm string.
- if (AsmStart != AsmEnd)
- OS << StringRef(AsmStart, AsmEnd - AsmStart);
-
- AsmString = OS.str();
- return false;
-}
-
-/// Create an MCAsmParser instance.
-MCAsmParser *llvm::createMCMasmParser(SourceMgr &SM, MCContext &C,
- MCStreamer &Out, const MCAsmInfo &MAI,
- unsigned CB) {
- return new MasmParser(SM, C, Out, MAI, CB);
-}
+ }
+
+ // Set the number of Outputs and Inputs.
+ NumOutputs = OutputDecls.size();
+ NumInputs = InputDecls.size();
+
+ // Set the unique clobbers.
+ array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
+ ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
+ ClobberRegs.end());
+ Clobbers.assign(ClobberRegs.size(), std::string());
+ for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
+ raw_string_ostream OS(Clobbers[I]);
+ IP->printRegName(OS, ClobberRegs[I]);
+ }
+
+ // Merge the various outputs and inputs. Output are expected first.
+ if (NumOutputs || NumInputs) {
+ unsigned NumExprs = NumOutputs + NumInputs;
+ OpDecls.resize(NumExprs);
+ Constraints.resize(NumExprs);
+ for (unsigned i = 0; i < NumOutputs; ++i) {
+ OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
+ Constraints[i] = OutputConstraints[i];
+ }
+ for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
+ OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
+ Constraints[j] = InputConstraints[i];
+ }
+ }
+
+ // Build the IR assembly string.
+ std::string AsmStringIR;
+ raw_string_ostream OS(AsmStringIR);
+ StringRef ASMString =
+ SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
+ const char *AsmStart = ASMString.begin();
+ const char *AsmEnd = ASMString.end();
+ array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
+ for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) {
+ const AsmRewrite &AR = *it;
+ // Check if this has already been covered by another rewrite...
+ if (AR.Done)
+ continue;
+ AsmRewriteKind Kind = AR.Kind;
+
+ const char *Loc = AR.Loc.getPointer();
+ assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
+
+ // Emit everything up to the immediate/expression.
+ if (unsigned Len = Loc - AsmStart)
+ OS << StringRef(AsmStart, Len);
+
+ // Skip the original expression.
+ if (Kind == AOK_Skip) {
+ AsmStart = Loc + AR.Len;
+ continue;
+ }
+
+ unsigned AdditionalSkip = 0;
+ // Rewrite expressions in $N notation.
+ switch (Kind) {
+ default:
+ break;
+ case AOK_IntelExpr:
+ assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
+ if (AR.IntelExp.NeedBracs)
+ OS << "[";
+ if (AR.IntelExp.hasBaseReg())
+ OS << AR.IntelExp.BaseReg;
+ if (AR.IntelExp.hasIndexReg())
+ OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
+ << AR.IntelExp.IndexReg;
+ if (AR.IntelExp.Scale > 1)
+ OS << " * $$" << AR.IntelExp.Scale;
+ if (AR.IntelExp.hasOffset()) {
+ if (AR.IntelExp.hasRegs())
+ OS << " + ";
+ // Fuse this rewrite with a rewrite of the offset name, if present.
+ StringRef OffsetName = AR.IntelExp.OffsetName;
+ SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
+ size_t OffsetLen = OffsetName.size();
+ auto rewrite_it = std::find_if(
+ it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
+ return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
+ (FusingAR.Kind == AOK_Input ||
+ FusingAR.Kind == AOK_CallInput);
+ });
+ if (rewrite_it == AsmStrRewrites.end()) {
+ OS << "offset " << OffsetName;
+ } else if (rewrite_it->Kind == AOK_CallInput) {
+ OS << "${" << InputIdx++ << ":P}";
+ rewrite_it->Done = true;
+ } else {
+ OS << '$' << InputIdx++;
+ rewrite_it->Done = true;
+ }
+ }
+ if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
+ OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
+ if (AR.IntelExp.NeedBracs)
+ OS << "]";
+ break;
+ case AOK_Label:
+ OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
+ break;
+ case AOK_Input:
+ OS << '$' << InputIdx++;
+ break;
+ case AOK_CallInput:
+ OS << "${" << InputIdx++ << ":P}";
+ break;
+ case AOK_Output:
+ OS << '$' << OutputIdx++;
+ break;
+ case AOK_SizeDirective:
+ switch (AR.Val) {
+ default: break;
+ case 8: OS << "byte ptr "; break;
+ case 16: OS << "word ptr "; break;
+ case 32: OS << "dword ptr "; break;
+ case 64: OS << "qword ptr "; break;
+ case 80: OS << "xword ptr "; break;
+ case 128: OS << "xmmword ptr "; break;
+ case 256: OS << "ymmword ptr "; break;
+ }
+ break;
+ case AOK_Emit:
+ OS << ".byte";
+ break;
+ case AOK_Align: {
+ // MS alignment directives are measured in bytes. If the native assembler
+ // measures alignment in bytes, we can pass it straight through.
+ OS << ".align";
+ if (getContext().getAsmInfo()->getAlignmentIsInBytes())
+ break;
+
+ // Alignment is in log2 form, so print that instead and skip the original
+ // immediate.
+ unsigned Val = AR.Val;
+ OS << ' ' << Val;
+ assert(Val < 10 && "Expected alignment less then 2^10.");
+ AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
+ break;
+ }
+ case AOK_EVEN:
+ OS << ".even";
+ break;
+ case AOK_EndOfStatement:
+ OS << "\n\t";
+ break;
+ }
+
+ // Skip the original expression.
+ AsmStart = Loc + AR.Len + AdditionalSkip;
+ }
+
+ // Emit the remainder of the asm string.
+ if (AsmStart != AsmEnd)
+ OS << StringRef(AsmStart, AsmEnd - AsmStart);
+
+ AsmString = OS.str();
+ return false;
+}
+
+/// Create an MCAsmParser instance.
+MCAsmParser *llvm::createMCMasmParser(SourceMgr &SM, MCContext &C,
+ MCStreamer &Out, const MCAsmInfo &MAI,
+ unsigned CB) {
+ return new MasmParser(SM, C, Out, MAI, CB);
+}
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/WasmAsmParser.cpp b/contrib/libs/llvm12/lib/MC/MCParser/WasmAsmParser.cpp
index 58aaebc2d7..0c255ef02d 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/WasmAsmParser.cpp
+++ b/contrib/libs/llvm12/lib/MC/MCParser/WasmAsmParser.cpp
@@ -1,100 +1,100 @@
-//===- WasmAsmParser.cpp - Wasm Assembly Parser -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// --
-//
-// Note, this is for wasm, the binary format (analogous to ELF), not wasm,
-// the instruction set (analogous to x86), for which parsing code lives in
-// WebAssemblyAsmParser.
-//
-// This file contains processing for generic directives implemented using
-// MCTargetStreamer, the ones that depend on WebAssemblyTargetStreamer are in
-// WebAssemblyAsmParser.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/BinaryFormat/Wasm.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-#include "llvm/MC/MCSectionWasm.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolWasm.h"
-#include "llvm/Support/MachineValueType.h"
-
-using namespace llvm;
-
-namespace {
-
-class WasmAsmParser : public MCAsmParserExtension {
- MCAsmParser *Parser = nullptr;
- MCAsmLexer *Lexer = nullptr;
-
- template<bool (WasmAsmParser::*HandlerMethod)(StringRef, SMLoc)>
- void addDirectiveHandler(StringRef Directive) {
- MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
- this, HandleDirective<WasmAsmParser, HandlerMethod>);
-
- getParser().addDirectiveHandler(Directive, Handler);
- }
-
-public:
- WasmAsmParser() { BracketExpressionsSupported = true; }
-
- void Initialize(MCAsmParser &P) override {
- Parser = &P;
- Lexer = &Parser->getLexer();
- // Call the base implementation.
- this->MCAsmParserExtension::Initialize(*Parser);
-
- addDirectiveHandler<&WasmAsmParser::parseSectionDirectiveText>(".text");
- addDirectiveHandler<&WasmAsmParser::parseSectionDirective>(".section");
- addDirectiveHandler<&WasmAsmParser::parseDirectiveSize>(".size");
- addDirectiveHandler<&WasmAsmParser::parseDirectiveType>(".type");
- addDirectiveHandler<&WasmAsmParser::ParseDirectiveIdent>(".ident");
- addDirectiveHandler<
- &WasmAsmParser::ParseDirectiveSymbolAttribute>(".weak");
- addDirectiveHandler<
- &WasmAsmParser::ParseDirectiveSymbolAttribute>(".local");
- addDirectiveHandler<
- &WasmAsmParser::ParseDirectiveSymbolAttribute>(".internal");
- addDirectiveHandler<
- &WasmAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
- }
-
- bool error(const StringRef &Msg, const AsmToken &Tok) {
- return Parser->Error(Tok.getLoc(), Msg + Tok.getString());
- }
-
- bool isNext(AsmToken::TokenKind Kind) {
- auto Ok = Lexer->is(Kind);
- if (Ok)
- Lex();
- return Ok;
- }
-
- bool expect(AsmToken::TokenKind Kind, const char *KindName) {
- if (!isNext(Kind))
- return error(std::string("Expected ") + KindName + ", instead got: ",
- Lexer->getTok());
- return false;
- }
-
- bool parseSectionDirectiveText(StringRef, SMLoc) {
- // FIXME: .text currently no-op.
- return false;
- }
-
+//===- WasmAsmParser.cpp - Wasm Assembly Parser -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// --
+//
+// Note, this is for wasm, the binary format (analogous to ELF), not wasm,
+// the instruction set (analogous to x86), for which parsing code lives in
+// WebAssemblyAsmParser.
+//
+// This file contains processing for generic directives implemented using
+// MCTargetStreamer, the ones that depend on WebAssemblyTargetStreamer are in
+// WebAssemblyAsmParser.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/Wasm.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCSectionWasm.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCSymbolWasm.h"
+#include "llvm/Support/MachineValueType.h"
+
+using namespace llvm;
+
+namespace {
+
+class WasmAsmParser : public MCAsmParserExtension {
+ MCAsmParser *Parser = nullptr;
+ MCAsmLexer *Lexer = nullptr;
+
+ template<bool (WasmAsmParser::*HandlerMethod)(StringRef, SMLoc)>
+ void addDirectiveHandler(StringRef Directive) {
+ MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
+ this, HandleDirective<WasmAsmParser, HandlerMethod>);
+
+ getParser().addDirectiveHandler(Directive, Handler);
+ }
+
+public:
+ WasmAsmParser() { BracketExpressionsSupported = true; }
+
+ void Initialize(MCAsmParser &P) override {
+ Parser = &P;
+ Lexer = &Parser->getLexer();
+ // Call the base implementation.
+ this->MCAsmParserExtension::Initialize(*Parser);
+
+ addDirectiveHandler<&WasmAsmParser::parseSectionDirectiveText>(".text");
+ addDirectiveHandler<&WasmAsmParser::parseSectionDirective>(".section");
+ addDirectiveHandler<&WasmAsmParser::parseDirectiveSize>(".size");
+ addDirectiveHandler<&WasmAsmParser::parseDirectiveType>(".type");
+ addDirectiveHandler<&WasmAsmParser::ParseDirectiveIdent>(".ident");
+ addDirectiveHandler<
+ &WasmAsmParser::ParseDirectiveSymbolAttribute>(".weak");
+ addDirectiveHandler<
+ &WasmAsmParser::ParseDirectiveSymbolAttribute>(".local");
+ addDirectiveHandler<
+ &WasmAsmParser::ParseDirectiveSymbolAttribute>(".internal");
+ addDirectiveHandler<
+ &WasmAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
+ }
+
+ bool error(const StringRef &Msg, const AsmToken &Tok) {
+ return Parser->Error(Tok.getLoc(), Msg + Tok.getString());
+ }
+
+ bool isNext(AsmToken::TokenKind Kind) {
+ auto Ok = Lexer->is(Kind);
+ if (Ok)
+ Lex();
+ return Ok;
+ }
+
+ bool expect(AsmToken::TokenKind Kind, const char *KindName) {
+ if (!isNext(Kind))
+ return error(std::string("Expected ") + KindName + ", instead got: ",
+ Lexer->getTok());
+ return false;
+ }
+
+ bool parseSectionDirectiveText(StringRef, SMLoc) {
+ // FIXME: .text currently no-op.
+ return false;
+ }
+
bool parseSectionFlags(StringRef FlagStr, bool &Passive, bool &Group) {
for (char C : FlagStr) {
switch (C) {
case 'p':
- Passive = true;
+ Passive = true;
break;
case 'G':
Group = true;
@@ -103,10 +103,10 @@ public:
return Parser->Error(getTok().getLoc(),
StringRef("Unexepcted section flag: ") + FlagStr);
}
- }
- return false;
- }
-
+ }
+ return false;
+ }
+
bool parseGroup(StringRef &GroupName) {
if (Lexer->isNot(AsmToken::Comma))
return TokError("expected group name");
@@ -128,40 +128,40 @@ public:
return false;
}
- bool parseSectionDirective(StringRef, SMLoc) {
- StringRef Name;
- if (Parser->parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- if (expect(AsmToken::Comma, ","))
- return true;
-
- if (Lexer->isNot(AsmToken::String))
- return error("expected string in directive, instead got: ", Lexer->getTok());
-
- auto Kind = StringSwitch<Optional<SectionKind>>(Name)
- .StartsWith(".data", SectionKind::getData())
+ bool parseSectionDirective(StringRef, SMLoc) {
+ StringRef Name;
+ if (Parser->parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ if (expect(AsmToken::Comma, ","))
+ return true;
+
+ if (Lexer->isNot(AsmToken::String))
+ return error("expected string in directive, instead got: ", Lexer->getTok());
+
+ auto Kind = StringSwitch<Optional<SectionKind>>(Name)
+ .StartsWith(".data", SectionKind::getData())
.StartsWith(".tdata", SectionKind::getThreadData())
.StartsWith(".tbss", SectionKind::getThreadBSS())
- .StartsWith(".rodata", SectionKind::getReadOnly())
- .StartsWith(".text", SectionKind::getText())
- .StartsWith(".custom_section", SectionKind::getMetadata())
- .StartsWith(".bss", SectionKind::getBSS())
- // See use of .init_array in WasmObjectWriter and
- // TargetLoweringObjectFileWasm
- .StartsWith(".init_array", SectionKind::getData())
- .StartsWith(".debug_", SectionKind::getMetadata())
- .Default(Optional<SectionKind>());
- if (!Kind.hasValue())
- return Parser->Error(Lexer->getLoc(), "unknown section kind: " + Name);
-
-
- // Update section flags if present in this .section directive
- bool Passive = false;
+ .StartsWith(".rodata", SectionKind::getReadOnly())
+ .StartsWith(".text", SectionKind::getText())
+ .StartsWith(".custom_section", SectionKind::getMetadata())
+ .StartsWith(".bss", SectionKind::getBSS())
+ // See use of .init_array in WasmObjectWriter and
+ // TargetLoweringObjectFileWasm
+ .StartsWith(".init_array", SectionKind::getData())
+ .StartsWith(".debug_", SectionKind::getMetadata())
+ .Default(Optional<SectionKind>());
+ if (!Kind.hasValue())
+ return Parser->Error(Lexer->getLoc(), "unknown section kind: " + Name);
+
+
+ // Update section flags if present in this .section directive
+ bool Passive = false;
bool Group = false;
if (parseSectionFlags(getTok().getStringContents(), Passive, Group))
- return true;
-
+ return true;
+
Lex();
if (expect(AsmToken::Comma, ",") || expect(AsmToken::At, "@"))
@@ -177,118 +177,118 @@ public:
// TODO: Parse UniqueID
MCSectionWasm *WS = getContext().getWasmSection(
Name, Kind.getValue(), GroupName, MCContext::GenericSectionID);
- if (Passive) {
+ if (Passive) {
if (!WS->isWasmData())
- return Parser->Error(getTok().getLoc(),
- "Only data sections can be passive");
+ return Parser->Error(getTok().getLoc(),
+ "Only data sections can be passive");
WS->setPassive();
- }
- getStreamer().SwitchSection(WS);
- return false;
- }
-
- // TODO: This function is almost the same as ELFAsmParser::ParseDirectiveSize
- // so maybe could be shared somehow.
- bool parseDirectiveSize(StringRef, SMLoc) {
- StringRef Name;
- if (Parser->parseIdentifier(Name))
- return TokError("expected identifier in directive");
- auto Sym = getContext().getOrCreateSymbol(Name);
- if (expect(AsmToken::Comma, ","))
- return true;
- const MCExpr *Expr;
- if (Parser->parseExpression(Expr))
- return true;
- if (expect(AsmToken::EndOfStatement, "eol"))
- return true;
- // This is done automatically by the assembler for functions currently,
- // so this is only currently needed for data sections:
- getStreamer().emitELFSize(Sym, Expr);
- return false;
- }
-
- bool parseDirectiveType(StringRef, SMLoc) {
- // This could be the start of a function, check if followed by
- // "label,@function"
- if (!Lexer->is(AsmToken::Identifier))
- return error("Expected label after .type directive, got: ",
- Lexer->getTok());
- auto WasmSym = cast<MCSymbolWasm>(
- getStreamer().getContext().getOrCreateSymbol(
- Lexer->getTok().getString()));
- Lex();
- if (!(isNext(AsmToken::Comma) && isNext(AsmToken::At) &&
- Lexer->is(AsmToken::Identifier)))
- return error("Expected label,@type declaration, got: ", Lexer->getTok());
- auto TypeName = Lexer->getTok().getString();
+ }
+ getStreamer().SwitchSection(WS);
+ return false;
+ }
+
+ // TODO: This function is almost the same as ELFAsmParser::ParseDirectiveSize
+ // so maybe could be shared somehow.
+ bool parseDirectiveSize(StringRef, SMLoc) {
+ StringRef Name;
+ if (Parser->parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+ auto Sym = getContext().getOrCreateSymbol(Name);
+ if (expect(AsmToken::Comma, ","))
+ return true;
+ const MCExpr *Expr;
+ if (Parser->parseExpression(Expr))
+ return true;
+ if (expect(AsmToken::EndOfStatement, "eol"))
+ return true;
+ // This is done automatically by the assembler for functions currently,
+ // so this is only currently needed for data sections:
+ getStreamer().emitELFSize(Sym, Expr);
+ return false;
+ }
+
+ bool parseDirectiveType(StringRef, SMLoc) {
+ // This could be the start of a function, check if followed by
+ // "label,@function"
+ if (!Lexer->is(AsmToken::Identifier))
+ return error("Expected label after .type directive, got: ",
+ Lexer->getTok());
+ auto WasmSym = cast<MCSymbolWasm>(
+ getStreamer().getContext().getOrCreateSymbol(
+ Lexer->getTok().getString()));
+ Lex();
+ if (!(isNext(AsmToken::Comma) && isNext(AsmToken::At) &&
+ Lexer->is(AsmToken::Identifier)))
+ return error("Expected label,@type declaration, got: ", Lexer->getTok());
+ auto TypeName = Lexer->getTok().getString();
if (TypeName == "function") {
- WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
+ WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
auto *Current =
cast<MCSectionWasm>(getStreamer().getCurrentSection().first);
if (Current->getGroup())
WasmSym->setComdat(true);
} else if (TypeName == "global")
- WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
- else if (TypeName == "object")
- WasmSym->setType(wasm::WASM_SYMBOL_TYPE_DATA);
- else
- return error("Unknown WASM symbol type: ", Lexer->getTok());
- Lex();
- return expect(AsmToken::EndOfStatement, "EOL");
- }
-
- // FIXME: Shared with ELF.
- /// ParseDirectiveIdent
- /// ::= .ident string
- bool ParseDirectiveIdent(StringRef, SMLoc) {
- if (getLexer().isNot(AsmToken::String))
- return TokError("unexpected token in '.ident' directive");
- StringRef Data = getTok().getIdentifier();
- Lex();
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.ident' directive");
- Lex();
- getStreamer().emitIdent(Data);
- return false;
- }
-
- // FIXME: Shared with ELF.
- /// ParseDirectiveSymbolAttribute
- /// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]
- bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
- MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
- .Case(".weak", MCSA_Weak)
- .Case(".local", MCSA_Local)
- .Case(".hidden", MCSA_Hidden)
- .Case(".internal", MCSA_Internal)
- .Case(".protected", MCSA_Protected)
- .Default(MCSA_Invalid);
- assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- while (true) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().emitSymbolAttribute(Sym, Attr);
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
- }
- }
- Lex();
- return false;
- }
-};
-
-} // end anonymous namespace
-
-namespace llvm {
-
-MCAsmParserExtension *createWasmAsmParser() {
- return new WasmAsmParser;
-}
-
-} // end namespace llvm
+ WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
+ else if (TypeName == "object")
+ WasmSym->setType(wasm::WASM_SYMBOL_TYPE_DATA);
+ else
+ return error("Unknown WASM symbol type: ", Lexer->getTok());
+ Lex();
+ return expect(AsmToken::EndOfStatement, "EOL");
+ }
+
+ // FIXME: Shared with ELF.
+ /// ParseDirectiveIdent
+ /// ::= .ident string
+ bool ParseDirectiveIdent(StringRef, SMLoc) {
+ if (getLexer().isNot(AsmToken::String))
+ return TokError("unexpected token in '.ident' directive");
+ StringRef Data = getTok().getIdentifier();
+ Lex();
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.ident' directive");
+ Lex();
+ getStreamer().emitIdent(Data);
+ return false;
+ }
+
+ // FIXME: Shared with ELF.
+ /// ParseDirectiveSymbolAttribute
+ /// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]
+ bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
+ MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
+ .Case(".weak", MCSA_Weak)
+ .Case(".local", MCSA_Local)
+ .Case(".hidden", MCSA_Hidden)
+ .Case(".internal", MCSA_Internal)
+ .Case(".protected", MCSA_Protected)
+ .Default(MCSA_Invalid);
+ assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ while (true) {
+ StringRef Name;
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ getStreamer().emitSymbolAttribute(Sym, Attr);
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+ }
+ }
+ Lex();
+ return false;
+ }
+};
+
+} // end anonymous namespace
+
+namespace llvm {
+
+MCAsmParserExtension *createWasmAsmParser() {
+ return new WasmAsmParser;
+}
+
+} // end namespace llvm
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/ya.make b/contrib/libs/llvm12/lib/MC/MCParser/ya.make
index cc9e74ac69..304ad7d65a 100644
--- a/contrib/libs/llvm12/lib/MC/MCParser/ya.make
+++ b/contrib/libs/llvm12/lib/MC/MCParser/ya.make
@@ -1,43 +1,43 @@
-# Generated by devtools/yamaker.
-
-LIBRARY()
-
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
OWNER(
orivej
g:cpp-contrib
)
-
+
LICENSE(Apache-2.0 WITH LLVM-exception)
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-PEERDIR(
+PEERDIR(
contrib/libs/llvm12
contrib/libs/llvm12/lib/MC
contrib/libs/llvm12/lib/Support
-)
-
+)
+
ADDINCL(
contrib/libs/llvm12/lib/MC/MCParser
)
-
-NO_COMPILER_WARNINGS()
-
-NO_UTIL()
-
-SRCS(
- AsmLexer.cpp
- AsmParser.cpp
- COFFAsmParser.cpp
- COFFMasmParser.cpp
- DarwinAsmParser.cpp
- ELFAsmParser.cpp
- MCAsmLexer.cpp
- MCAsmParser.cpp
- MCAsmParserExtension.cpp
- MCTargetAsmParser.cpp
- MasmParser.cpp
- WasmAsmParser.cpp
-)
-
-END()
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+SRCS(
+ AsmLexer.cpp
+ AsmParser.cpp
+ COFFAsmParser.cpp
+ COFFMasmParser.cpp
+ DarwinAsmParser.cpp
+ ELFAsmParser.cpp
+ MCAsmLexer.cpp
+ MCAsmParser.cpp
+ MCAsmParserExtension.cpp
+ MCTargetAsmParser.cpp
+ MasmParser.cpp
+ WasmAsmParser.cpp
+)
+
+END()