summaryrefslogtreecommitdiff
path: root/lib/MC/MCParser/AsmParser.cpp
diff options
context:
space:
mode:
authorSaleem Abdulrasool <compnerd@compnerd.org>2014-02-19 03:00:29 +0000
committerSaleem Abdulrasool <compnerd@compnerd.org>2014-02-19 03:00:29 +0000
commit156f2a1f5ddad573a884b52774c14e4b327d2ad0 (patch)
tree6f0da2c588f6b631288f34fa4984276cf5a0e9d7 /lib/MC/MCParser/AsmParser.cpp
parent5bbd4d2bd4749894ed7c53bbfd040532f98c37df (diff)
downloadllvm-156f2a1f5ddad573a884b52774c14e4b327d2ad0.tar.gz
llvm-156f2a1f5ddad573a884b52774c14e4b327d2ad0.tar.bz2
llvm-156f2a1f5ddad573a884b52774c14e4b327d2ad0.tar.xz
MCAsmParser: support required parameters
This enhances the macro parser to parse and handle parameter qualifications, which is needed to support required formal parameters in macro definitions. A required parameter may not be defaulted (though providing a default value is accepted with a warning). This improves GAS compatibility. Partially addresses PR9248. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201630 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC/MCParser/AsmParser.cpp')
-rw-r--r--lib/MC/MCParser/AsmParser.cpp71
1 files changed, 59 insertions, 12 deletions
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 1692b2f190..f73e56ade2 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -58,6 +58,9 @@ typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
struct MCAsmMacroParameter {
StringRef Name;
MCAsmMacroArgument Value;
+ bool Required;
+
+ MCAsmMacroParameter() : Required(false) { }
};
typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters;
@@ -1940,26 +1943,23 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA) {
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);
- for (unsigned PI = 0; PI < NParameters; ++PI)
- if (!M->Parameters[PI].Value.empty())
- A[PI] = M->Parameters[PI].Value;
-
- bool NamedParametersFound = false;
+ 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;
- SMLoc L;
if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
- L = Lexer.getLoc();
if (parseIdentifier(FA.Name)) {
- Error(L, "invalid argument identifier for formal argument");
+ Error(IDLoc, "invalid argument identifier for formal argument");
eatToEndOfStatement();
return true;
}
@@ -1975,7 +1975,7 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
}
if (NamedParametersFound && FA.Name.empty()) {
- Error(Lexer.getLoc(), "cannot mix positional and keyword arguments");
+ Error(IDLoc, "cannot mix positional and keyword arguments");
eatToEndOfStatement();
return true;
}
@@ -1989,8 +1989,9 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
for (FAI = 0; FAI < NParameters; ++FAI)
if (M->Parameters[FAI].Name == FA.Name)
break;
+
if (FAI >= NParameters) {
- Error(L,
+ Error(IDLoc,
"parameter named '" + FA.Name + "' does not exist for macro '" +
M->Name + "'");
return true;
@@ -2002,13 +2003,33 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
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))
- return false;
+ 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();
@@ -3210,10 +3231,36 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
if (parseIdentifier(Parameter.Name))
return TokError("expected identifier in '.macro' directive");
+ 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
+ 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))
return true;
+
+ if (Parameter.Required)
+ Warning(ParamLoc, "pointless default value for required parameter "
+ "'" + Parameter.Name + "' in macro '" + Name + "'");
}
Parameters.push_back(Parameter);