summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-01-29 18:57:46 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-01-29 18:57:46 +0000
commit654247c3ea3304b434cb3f0dcf69338073651158 (patch)
treebbc783928f594d94a66da4a5a2bcfa75bd0fb2dc
parentfb70e11bbcbe57bb7a6295e2f3ae1a1a71af02d4 (diff)
downloadllvm-654247c3ea3304b434cb3f0dcf69338073651158.tar.gz
llvm-654247c3ea3304b434cb3f0dcf69338073651158.tar.bz2
llvm-654247c3ea3304b434cb3f0dcf69338073651158.tar.xz
MC: Better management of macro arguments
The linux kernel makes uses of a GAS `feature' which substitutes nothing for macro arguments which aren't specified. Proper support for these kind of macro arguments necessitated a cleanup of differences between `GAS' and `Darwin' dialect macro processing. Differential Revision: http://llvm-reviews.chandlerc.com/D2634 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200409 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/MC/MCParser/AsmParser.cpp77
-rw-r--r--test/MC/AsmParser/macros-darwin.s8
-rw-r--r--test/MC/AsmParser/macros-gas.s28
3 files changed, 38 insertions, 75 deletions
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 91699983e2..3f813a73cc 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -287,11 +287,8 @@ private:
/// \brief Handle exit from macro instantiation.
void handleMacroExit();
- /// \brief Extract AsmTokens for a macro argument. If the argument delimiter
- /// is initially unknown, set it to AsmToken::Eof. It will be set to the
- /// correct delimiter by the method.
- bool parseMacroArgument(MCAsmMacroArgument &MA,
- AsmToken::TokenKind &ArgumentDelimiter);
+ /// \brief Extract AsmTokens for a macro argument.
+ bool parseMacroArgument(MCAsmMacroArgument &MA);
/// \brief Parse all macro arguments for a given macro.
bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
@@ -1879,8 +1876,7 @@ private:
};
}
-bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA,
- AsmToken::TokenKind &ArgumentDelimiter) {
+bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA) {
unsigned ParenLevel = 0;
unsigned AddTokens = 0;
@@ -1891,14 +1887,8 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA,
if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
return TokError("unexpected token in macro instantiation");
- if (ParenLevel == 0 && Lexer.is(AsmToken::Comma)) {
- // Spaces and commas cannot be mixed to delimit parameters
- if (ArgumentDelimiter == AsmToken::Eof)
- ArgumentDelimiter = AsmToken::Comma;
- else if (ArgumentDelimiter != AsmToken::Comma)
- return TokError("expected ' ' for macro argument separator");
+ if (ParenLevel == 0 && Lexer.is(AsmToken::Comma))
break;
- }
if (Lexer.is(AsmToken::Space)) {
Lex(); // Eat spaces
@@ -1906,8 +1896,7 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA,
// 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 (ArgumentDelimiter == AsmToken::Space ||
- ArgumentDelimiter == AsmToken::Eof) {
+ if (!IsDarwin) {
if (isOperator(Lexer.getKind())) {
// Check to see whether the token is used as an operator,
// or part of an identifier
@@ -1917,9 +1906,6 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA,
}
if (!AddTokens && ParenLevel == 0) {
- if (ArgumentDelimiter == AsmToken::Eof &&
- !isOperator(Lexer.getKind()))
- ArgumentDelimiter = AsmToken::Space;
break;
}
}
@@ -1952,9 +1938,6 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA,
bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
MCAsmMacroArguments &A) {
const unsigned NParameters = M ? M->Parameters.size() : 0;
- // Argument delimiter is initially unknown. It will be set by
- // parseMacroArgument()
- AsmToken::TokenKind ArgumentDelimiter = AsmToken::Eof;
// Parse two kinds of macro invocations:
// - macros defined without any parameters accept an arbitrary number of them
@@ -1963,14 +1946,16 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
++Parameter) {
MCAsmMacroArgument MA;
- if (parseMacroArgument(MA, ArgumentDelimiter))
+ if (parseMacroArgument(MA))
return true;
- if (!MA.empty() || !NParameters)
+ if (!MA.empty() || (!NParameters && !Lexer.is(AsmToken::EndOfStatement)))
A.push_back(MA);
else if (NParameters) {
if (!M->Parameters[Parameter].second.empty())
A.push_back(M->Parameters[Parameter].second);
+ else
+ A.push_back(MA);
}
// At the end of the statement, fill in remaining arguments that have
@@ -1978,12 +1963,7 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
// required but missing
if (Lexer.is(AsmToken::EndOfStatement)) {
if (NParameters && Parameter < NParameters - 1) {
- if (M->Parameters[Parameter + 1].second.empty())
- return TokError("macro argument '" +
- Twine(M->Parameters[Parameter + 1].first) +
- "' is missing");
- else
- continue;
+ continue;
}
return false;
}
@@ -2021,12 +2001,6 @@ bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
if (parseMacroArguments(M, A))
return true;
- // Remove any trailing empty arguments. Do this after-the-fact as we have
- // to keep empty arguments in the middle of the list or positionality
- // gets off. e.g., "foo 1, , 2" vs. "foo 1, 2,"
- while (!A.empty() && A.back().empty())
- A.pop_back();
-
// Macro instantiation is lexical, unfortunately. We construct a new buffer
// to hold the macro body with substitutions.
SmallString<256> Buf;
@@ -3113,28 +3087,21 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
return TokError("expected identifier in '.macro' directive");
MCAsmMacroParameters Parameters;
- // Argument delimiter is initially unknown. It will be set by
- // parseMacroArgument()
- AsmToken::TokenKind ArgumentDelimiter = AsmToken::Eof;
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- for (;;) {
- MCAsmMacroParameter Parameter;
- if (parseIdentifier(Parameter.first))
- return TokError("expected identifier in '.macro' directive");
+ while (getLexer().isNot(AsmToken::EndOfStatement)) {
+ MCAsmMacroParameter Parameter;
+ if (parseIdentifier(Parameter.first))
+ return TokError("expected identifier in '.macro' directive");
- if (getLexer().is(AsmToken::Equal)) {
- Lex();
- if (parseMacroArgument(Parameter.second, ArgumentDelimiter))
- return true;
- }
+ if (getLexer().is(AsmToken::Equal)) {
+ Lex();
+ if (parseMacroArgument(Parameter.second))
+ return true;
+ }
- Parameters.push_back(Parameter);
+ Parameters.push_back(Parameter);
- if (getLexer().is(AsmToken::Comma))
- Lex();
- else if (getLexer().is(AsmToken::EndOfStatement))
- break;
- }
+ if (getLexer().is(AsmToken::Comma))
+ Lex();
}
// Eat the end of statement.
diff --git a/test/MC/AsmParser/macros-darwin.s b/test/MC/AsmParser/macros-darwin.s
index c4061f0663..e22038e7d1 100644
--- a/test/MC/AsmParser/macros-darwin.s
+++ b/test/MC/AsmParser/macros-darwin.s
@@ -86,12 +86,8 @@ test8 x - y, z, 1
// CHECK: .globl "1 2 3"
test9 1, 2,3
+// CHECK: .globl "1,23,"
test8 1,2 3
-// CHECK-ERRORS: error: macro argument '_c' is missing
-// CHECK-ERRORS-NEXT: test8 1,2 3
-// CHECK-ERRORS-NEXT: ^
+// CHECK: .globl "12,3,"
test8 1 2, 3
-// CHECK-ERRORS: error: macro argument '_c' is missing
-// CHECK-ERRORS-NEXT:test8 1 2, 3
-// CHECK-ERRORS-NEXT: ^
diff --git a/test/MC/AsmParser/macros-gas.s b/test/MC/AsmParser/macros-gas.s
index 39f654dd9a..6c75363b5e 100644
--- a/test/MC/AsmParser/macros-gas.s
+++ b/test/MC/AsmParser/macros-gas.s
@@ -32,17 +32,21 @@ test2 10
// CHECK: .ascii "1 2 3 \003"
test3 1, 2, 3
-// FIXME: test3 1, 2 3 should be treated like test 1, 2, 3
+// CHECK: .ascii "1 2 3 \003"
+test3 1, 2 3
+
+.macro test3_prime _a _b _c
+.ascii "\_a \_b \_c"
+.endm
-// FIXME: remove the n argument from the remaining test3 examples
-// CHECK: .ascii "1 (23) n \n"
-test3 1, (2 3), n
+// CHECK: .ascii "1 (23) "
+test3_prime 1, (2 3)
-// CHECK: .ascii "1 (23) n \n"
-test3 1 (2 3) n
+// CHECK: .ascii "1 (23) "
+test3_prime 1 (2 3)
-// CHECK: .ascii "1 2 n \n"
-test3 1 2 n
+// CHECK: .ascii "1 2 "
+test3_prime 1 2
.macro test5 _a
.globl \_a
@@ -82,12 +86,8 @@ test8 x - y z 1
// CHECK: .ascii "1 2 3"
test9 1, 2,3
+// CHECK: .ascii "1,2,3"
test8 1,2 3
-// CHECK-ERRORS: error: macro argument '_c' is missing
-// CHECK-ERRORS-NEXT: test8 1,2 3
-// CHECK-ERRORS-NEXT: ^
+// CHECK: .ascii "1,2,3"
test8 1 2, 3
-// CHECK-ERRORS: error: expected ' ' for macro argument separator
-// CHECK-ERRORS-NEXT:test8 1 2, 3
-// CHECK-ERRORS-NEXT: ^