ARM IAS: handle errors more appropriately

Directive parsers must return false if the target assembler is interested in
handling the directive.  The Error member function returns true always.  Using
the 'return Error()' pattern would incorrectly indicate to the general parser
that the target was not interested in the directive, when in reality it simply
encountered a badly formed directive or some other error.  This corrects the
behaviour to ensure that the parser behaves appropriately.

llvm-svn: 198132
This commit is contained in:
Saleem Abdulrasool 2013-12-28 22:47:53 +00:00
parent 7afe481801
commit 0c4b10264b
1 changed files with 176 additions and 98 deletions

View File

@ -8026,8 +8026,10 @@ bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
else else
return Error(L, "unrecognized syntax mode in .syntax directive"); return Error(L, "unrecognized syntax mode in .syntax directive");
if (getLexer().isNot(AsmToken::EndOfStatement)) if (getLexer().isNot(AsmToken::EndOfStatement)) {
return Error(Parser.getTok().getLoc(), "unexpected token in directive"); Error(Parser.getTok().getLoc(), "unexpected token in directive");
return false;
}
Parser.Lex(); Parser.Lex();
// TODO tell the MC streamer the mode // TODO tell the MC streamer the mode
@ -8039,30 +8041,37 @@ bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
/// ::= .code 16 | 32 /// ::= .code 16 | 32
bool ARMAsmParser::parseDirectiveCode(SMLoc L) { bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
const AsmToken &Tok = Parser.getTok(); const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Integer)) if (Tok.isNot(AsmToken::Integer)) {
return Error(L, "unexpected token in .code directive"); Error(L, "unexpected token in .code directive");
return false;
}
int64_t Val = Parser.getTok().getIntVal(); int64_t Val = Parser.getTok().getIntVal();
if (Val == 16) if (Val != 16 && Val != 32) {
Parser.Lex(); Error(L, "invalid operand to .code directive");
else if (Val == 32) return false;
Parser.Lex(); }
else Parser.Lex();
return Error(L, "invalid operand to .code directive");
if (getLexer().isNot(AsmToken::EndOfStatement)) if (getLexer().isNot(AsmToken::EndOfStatement)) {
return Error(Parser.getTok().getLoc(), "unexpected token in directive"); Error(Parser.getTok().getLoc(), "unexpected token in directive");
return false;
}
Parser.Lex(); Parser.Lex();
if (Val == 16) { if (Val == 16) {
if (!hasThumb()) if (!hasThumb()) {
return Error(L, "target does not support Thumb mode"); Error(L, "target does not support Thumb mode");
return false;
}
if (!isThumb()) if (!isThumb())
SwitchMode(); SwitchMode();
getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
} else { } else {
if (!hasARM()) if (!hasARM()) {
return Error(L, "target does not support ARM mode"); Error(L, "target does not support ARM mode");
return false;
}
if (isThumb()) if (isThumb())
SwitchMode(); SwitchMode();
@ -8080,21 +8089,23 @@ bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
SMLoc SRegLoc, ERegLoc; SMLoc SRegLoc, ERegLoc;
if (ParseRegister(Reg, SRegLoc, ERegLoc)) { if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
Parser.eatToEndOfStatement(); Parser.eatToEndOfStatement();
return Error(SRegLoc, "register name expected"); Error(SRegLoc, "register name expected");
return false;
} }
// Shouldn't be anything else. // Shouldn't be anything else.
if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Parser.eatToEndOfStatement(); Parser.eatToEndOfStatement();
return Error(Parser.getTok().getLoc(), Error(Parser.getTok().getLoc(), "unexpected input in .req directive.");
"unexpected input in .req directive."); return false;
} }
Parser.Lex(); // Consume the EndOfStatement Parser.Lex(); // Consume the EndOfStatement
if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg) if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg) {
return Error(SRegLoc, "redefinition of '" + Name + Error(SRegLoc, "redefinition of '" + Name + "' does not match original.");
"' does not match original."); return false;
}
return false; return false;
} }
@ -8104,7 +8115,8 @@ bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) { bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
if (Parser.getTok().isNot(AsmToken::Identifier)) { if (Parser.getTok().isNot(AsmToken::Identifier)) {
Parser.eatToEndOfStatement(); Parser.eatToEndOfStatement();
return Error(L, "unexpected input in .unreq directive."); Error(L, "unexpected input in .unreq directive.");
return false;
} }
RegisterReqs.erase(Parser.getTok().getIdentifier()); RegisterReqs.erase(Parser.getTok().getIdentifier());
Parser.Lex(); // Eat the identifier. Parser.Lex(); // Eat the identifier.
@ -8124,8 +8136,10 @@ bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
#include "MCTargetDesc/ARMArchName.def" #include "MCTargetDesc/ARMArchName.def"
.Default(ARM::INVALID_ARCH); .Default(ARM::INVALID_ARCH);
if (ID == ARM::INVALID_ARCH) if (ID == ARM::INVALID_ARCH) {
return Error(L, "Unknown arch name"); Error(L, "Unknown arch name");
return false;
}
getTargetStreamer().emitArch(ID); getTargetStreamer().emitArch(ID);
return false; return false;
@ -8134,18 +8148,24 @@ bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
/// parseDirectiveEabiAttr /// parseDirectiveEabiAttr
/// ::= .eabi_attribute int, int /// ::= .eabi_attribute int, int
bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
if (Parser.getTok().isNot(AsmToken::Integer)) if (Parser.getTok().isNot(AsmToken::Integer)) {
return Error(L, "integer expected"); Error(L, "integer expected");
return false;
}
int64_t Tag = Parser.getTok().getIntVal(); int64_t Tag = Parser.getTok().getIntVal();
Parser.Lex(); // eat tag integer Parser.Lex(); // eat tag integer
if (Parser.getTok().isNot(AsmToken::Comma)) if (Parser.getTok().isNot(AsmToken::Comma)) {
return Error(L, "comma expected"); Error(L, "comma expected");
return false;
}
Parser.Lex(); // skip comma Parser.Lex(); // skip comma
L = Parser.getTok().getLoc(); L = Parser.getTok().getLoc();
if (Parser.getTok().isNot(AsmToken::Integer)) if (Parser.getTok().isNot(AsmToken::Integer)) {
return Error(L, "integer expected"); Error(L, "integer expected");
return false;
}
int64_t Value = Parser.getTok().getIntVal(); int64_t Value = Parser.getTok().getIntVal();
Parser.Lex(); // eat value integer Parser.Lex(); // eat value integer
@ -8171,8 +8191,10 @@ bool ARMAsmParser::parseDirectiveFPU(SMLoc L) {
#include "ARMFPUName.def" #include "ARMFPUName.def"
.Default(ARM::INVALID_FPU); .Default(ARM::INVALID_FPU);
if (ID == ARM::INVALID_FPU) if (ID == ARM::INVALID_FPU) {
return Error(L, "Unknown FPU name"); Error(L, "Unknown FPU name");
return false;
}
getTargetStreamer().emitFPU(ID); getTargetStreamer().emitFPU(ID);
return false; return false;
@ -8184,7 +8206,7 @@ bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) {
if (FnStartLoc.isValid()) { if (FnStartLoc.isValid()) {
Error(L, ".fnstart starts before the end of previous one"); Error(L, ".fnstart starts before the end of previous one");
Error(FnStartLoc, "previous .fnstart starts here"); Error(FnStartLoc, "previous .fnstart starts here");
return true; return false;
} }
FnStartLoc = L; FnStartLoc = L;
@ -8196,8 +8218,10 @@ bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) {
/// ::= .fnend /// ::= .fnend
bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) { bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) {
// Check the ordering of unwind directives // Check the ordering of unwind directives
if (!FnStartLoc.isValid()) if (!FnStartLoc.isValid()) {
return Error(L, ".fnstart must precede .fnend directive"); Error(L, ".fnstart must precede .fnend directive");
return false;
}
// Reset the unwind directives parser state // Reset the unwind directives parser state
resetUnwindDirectiveParserState(); resetUnwindDirectiveParserState();
@ -8210,17 +8234,19 @@ bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) {
bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) { bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) {
// Check the ordering of unwind directives // Check the ordering of unwind directives
CantUnwindLoc = L; CantUnwindLoc = L;
if (!FnStartLoc.isValid()) if (!FnStartLoc.isValid()) {
return Error(L, ".fnstart must precede .cantunwind directive"); Error(L, ".fnstart must precede .cantunwind directive");
return false;
}
if (HandlerDataLoc.isValid()) { if (HandlerDataLoc.isValid()) {
Error(L, ".cantunwind can't be used with .handlerdata directive"); Error(L, ".cantunwind can't be used with .handlerdata directive");
Error(HandlerDataLoc, ".handlerdata was specified here"); Error(HandlerDataLoc, ".handlerdata was specified here");
return true; return false;
} }
if (PersonalityLoc.isValid()) { if (PersonalityLoc.isValid()) {
Error(L, ".cantunwind can't be used with .personality directive"); Error(L, ".cantunwind can't be used with .personality directive");
Error(PersonalityLoc, ".personality was specified here"); Error(PersonalityLoc, ".personality was specified here");
return true; return false;
} }
getTargetStreamer().emitCantUnwind(); getTargetStreamer().emitCantUnwind();
@ -8232,23 +8258,26 @@ bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) {
bool ARMAsmParser::parseDirectivePersonality(SMLoc L) { bool ARMAsmParser::parseDirectivePersonality(SMLoc L) {
// Check the ordering of unwind directives // Check the ordering of unwind directives
PersonalityLoc = L; PersonalityLoc = L;
if (!FnStartLoc.isValid()) if (!FnStartLoc.isValid()) {
return Error(L, ".fnstart must precede .personality directive"); Error(L, ".fnstart must precede .personality directive");
return false;
}
if (CantUnwindLoc.isValid()) { if (CantUnwindLoc.isValid()) {
Error(L, ".personality can't be used with .cantunwind directive"); Error(L, ".personality can't be used with .cantunwind directive");
Error(CantUnwindLoc, ".cantunwind was specified here"); Error(CantUnwindLoc, ".cantunwind was specified here");
return true; return false;
} }
if (HandlerDataLoc.isValid()) { if (HandlerDataLoc.isValid()) {
Error(L, ".personality must precede .handlerdata directive"); Error(L, ".personality must precede .handlerdata directive");
Error(HandlerDataLoc, ".handlerdata was specified here"); Error(HandlerDataLoc, ".handlerdata was specified here");
return true; return false;
} }
// Parse the name of the personality routine // Parse the name of the personality routine
if (Parser.getTok().isNot(AsmToken::Identifier)) { if (Parser.getTok().isNot(AsmToken::Identifier)) {
Parser.eatToEndOfStatement(); Parser.eatToEndOfStatement();
return Error(L, "unexpected input in .personality directive."); Error(L, "unexpected input in .personality directive.");
return false;
} }
StringRef Name(Parser.getTok().getIdentifier()); StringRef Name(Parser.getTok().getIdentifier());
Parser.Lex(); Parser.Lex();
@ -8263,12 +8292,14 @@ bool ARMAsmParser::parseDirectivePersonality(SMLoc L) {
bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) { bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) {
// Check the ordering of unwind directives // Check the ordering of unwind directives
HandlerDataLoc = L; HandlerDataLoc = L;
if (!FnStartLoc.isValid()) if (!FnStartLoc.isValid()) {
return Error(L, ".fnstart must precede .personality directive"); Error(L, ".fnstart must precede .personality directive");
return false;
}
if (CantUnwindLoc.isValid()) { if (CantUnwindLoc.isValid()) {
Error(L, ".handlerdata can't be used with .cantunwind directive"); Error(L, ".handlerdata can't be used with .cantunwind directive");
Error(CantUnwindLoc, ".cantunwind was specified here"); Error(CantUnwindLoc, ".cantunwind was specified here");
return true; return false;
} }
getTargetStreamer().emitHandlerData(); getTargetStreamer().emitHandlerData();
@ -8279,31 +8310,43 @@ bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) {
/// ::= .setfp fpreg, spreg [, offset] /// ::= .setfp fpreg, spreg [, offset]
bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) { bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) {
// Check the ordering of unwind directives // Check the ordering of unwind directives
if (!FnStartLoc.isValid()) if (!FnStartLoc.isValid()) {
return Error(L, ".fnstart must precede .setfp directive"); Error(L, ".fnstart must precede .setfp directive");
if (HandlerDataLoc.isValid()) return false;
return Error(L, ".setfp must precede .handlerdata directive"); }
if (HandlerDataLoc.isValid()) {
Error(L, ".setfp must precede .handlerdata directive");
return false;
}
// Parse fpreg // Parse fpreg
SMLoc NewFPRegLoc = Parser.getTok().getLoc(); SMLoc NewFPRegLoc = Parser.getTok().getLoc();
int NewFPReg = tryParseRegister(); int NewFPReg = tryParseRegister();
if (NewFPReg == -1) if (NewFPReg == -1) {
return Error(NewFPRegLoc, "frame pointer register expected"); Error(NewFPRegLoc, "frame pointer register expected");
return false;
}
// Consume comma // Consume comma
if (!Parser.getTok().is(AsmToken::Comma)) if (!Parser.getTok().is(AsmToken::Comma)) {
return Error(Parser.getTok().getLoc(), "comma expected"); Error(Parser.getTok().getLoc(), "comma expected");
return false;
}
Parser.Lex(); // skip comma Parser.Lex(); // skip comma
// Parse spreg // Parse spreg
SMLoc NewSPRegLoc = Parser.getTok().getLoc(); SMLoc NewSPRegLoc = Parser.getTok().getLoc();
int NewSPReg = tryParseRegister(); int NewSPReg = tryParseRegister();
if (NewSPReg == -1) if (NewSPReg == -1) {
return Error(NewSPRegLoc, "stack pointer register expected"); Error(NewSPRegLoc, "stack pointer register expected");
return false;
}
if (NewSPReg != ARM::SP && NewSPReg != FPReg) if (NewSPReg != ARM::SP && NewSPReg != FPReg) {
return Error(NewSPRegLoc, Error(NewSPRegLoc,
"register should be either $sp or the latest fp register"); "register should be either $sp or the latest fp register");
return false;
}
// Update the frame pointer register // Update the frame pointer register
FPReg = NewFPReg; FPReg = NewFPReg;
@ -8315,18 +8358,23 @@ bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) {
if (Parser.getTok().isNot(AsmToken::Hash) && if (Parser.getTok().isNot(AsmToken::Hash) &&
Parser.getTok().isNot(AsmToken::Dollar)) { Parser.getTok().isNot(AsmToken::Dollar)) {
return Error(Parser.getTok().getLoc(), "'#' expected"); Error(Parser.getTok().getLoc(), "'#' expected");
return false;
} }
Parser.Lex(); // skip hash token. Parser.Lex(); // skip hash token.
const MCExpr *OffsetExpr; const MCExpr *OffsetExpr;
SMLoc ExLoc = Parser.getTok().getLoc(); SMLoc ExLoc = Parser.getTok().getLoc();
SMLoc EndLoc; SMLoc EndLoc;
if (getParser().parseExpression(OffsetExpr, EndLoc)) if (getParser().parseExpression(OffsetExpr, EndLoc)) {
return Error(ExLoc, "malformed setfp offset"); Error(ExLoc, "malformed setfp offset");
return false;
}
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr); const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
if (!CE) if (!CE) {
return Error(ExLoc, "setfp offset must be an immediate"); Error(ExLoc, "setfp offset must be an immediate");
return false;
}
Offset = CE->getValue(); Offset = CE->getValue();
} }
@ -8340,26 +8388,35 @@ bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) {
/// ::= .pad offset /// ::= .pad offset
bool ARMAsmParser::parseDirectivePad(SMLoc L) { bool ARMAsmParser::parseDirectivePad(SMLoc L) {
// Check the ordering of unwind directives // Check the ordering of unwind directives
if (!FnStartLoc.isValid()) if (!FnStartLoc.isValid()) {
return Error(L, ".fnstart must precede .pad directive"); Error(L, ".fnstart must precede .pad directive");
if (HandlerDataLoc.isValid()) return false;
return Error(L, ".pad must precede .handlerdata directive"); }
if (HandlerDataLoc.isValid()) {
Error(L, ".pad must precede .handlerdata directive");
return false;
}
// Parse the offset // Parse the offset
if (Parser.getTok().isNot(AsmToken::Hash) && if (Parser.getTok().isNot(AsmToken::Hash) &&
Parser.getTok().isNot(AsmToken::Dollar)) { Parser.getTok().isNot(AsmToken::Dollar)) {
return Error(Parser.getTok().getLoc(), "'#' expected"); Error(Parser.getTok().getLoc(), "'#' expected");
return false;
} }
Parser.Lex(); // skip hash token. Parser.Lex(); // skip hash token.
const MCExpr *OffsetExpr; const MCExpr *OffsetExpr;
SMLoc ExLoc = Parser.getTok().getLoc(); SMLoc ExLoc = Parser.getTok().getLoc();
SMLoc EndLoc; SMLoc EndLoc;
if (getParser().parseExpression(OffsetExpr, EndLoc)) if (getParser().parseExpression(OffsetExpr, EndLoc)) {
return Error(ExLoc, "malformed pad offset"); Error(ExLoc, "malformed pad offset");
return false;
}
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr); const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
if (!CE) if (!CE) {
return Error(ExLoc, "pad offset must be an immediate"); Error(ExLoc, "pad offset must be an immediate");
return false;
}
getTargetStreamer().emitPad(CE->getValue()); getTargetStreamer().emitPad(CE->getValue());
return false; return false;
@ -8370,10 +8427,14 @@ bool ARMAsmParser::parseDirectivePad(SMLoc L) {
/// ::= .vsave { registers } /// ::= .vsave { registers }
bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) { bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) {
// Check the ordering of unwind directives // Check the ordering of unwind directives
if (!FnStartLoc.isValid()) if (!FnStartLoc.isValid()) {
return Error(L, ".fnstart must precede .save or .vsave directives"); Error(L, ".fnstart must precede .save or .vsave directives");
if (HandlerDataLoc.isValid()) return false;
return Error(L, ".save or .vsave must precede .handlerdata directive"); }
if (HandlerDataLoc.isValid()) {
Error(L, ".save or .vsave must precede .handlerdata directive");
return false;
}
// RAII object to make sure parsed operands are deleted. // RAII object to make sure parsed operands are deleted.
struct CleanupObject { struct CleanupObject {
@ -8388,10 +8449,14 @@ bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) {
if (parseRegisterList(CO.Operands)) if (parseRegisterList(CO.Operands))
return true; return true;
ARMOperand *Op = (ARMOperand*)CO.Operands[0]; ARMOperand *Op = (ARMOperand*)CO.Operands[0];
if (!IsVector && !Op->isRegList()) if (!IsVector && !Op->isRegList()) {
return Error(L, ".save expects GPR registers"); Error(L, ".save expects GPR registers");
if (IsVector && !Op->isDPRRegList()) return false;
return Error(L, ".vsave expects DPR registers"); }
if (IsVector && !Op->isDPRRegList()) {
Error(L, ".vsave expects DPR registers");
return false;
}
getTargetStreamer().emitRegSave(Op->getRegList(), IsVector); getTargetStreamer().emitRegSave(Op->getRegList(), IsVector);
return false; return false;
@ -8414,41 +8479,52 @@ bool ARMAsmParser::parseDirectiveInst(SMLoc Loc, char Suffix) {
break; break;
default: default:
Parser.eatToEndOfStatement(); Parser.eatToEndOfStatement();
return Error(Loc, "cannot determine Thumb instruction size, " Error(Loc, "cannot determine Thumb instruction size, "
"use inst.n/inst.w instead"); "use inst.n/inst.w instead");
return false;
} }
} else { } else {
if (Suffix) { if (Suffix) {
Parser.eatToEndOfStatement(); Parser.eatToEndOfStatement();
return Error(Loc, "width suffixes are invalid in ARM mode"); Error(Loc, "width suffixes are invalid in ARM mode");
return false;
} }
Width = 4; Width = 4;
} }
if (getLexer().is(AsmToken::EndOfStatement)) { if (getLexer().is(AsmToken::EndOfStatement)) {
Parser.eatToEndOfStatement(); Parser.eatToEndOfStatement();
return Error(Loc, "expected expression following directive"); Error(Loc, "expected expression following directive");
return false;
} }
for (;;) { for (;;) {
const MCExpr *Expr; const MCExpr *Expr;
if (getParser().parseExpression(Expr)) if (getParser().parseExpression(Expr)) {
return Error(Loc, "expected expression"); Error(Loc, "expected expression");
return false;
}
const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr); const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
if (!Value) if (!Value) {
return Error(Loc, "expected constant expression"); Error(Loc, "expected constant expression");
return false;
}
switch (Width) { switch (Width) {
case 2: case 2:
if (Value->getValue() > 0xffff) if (Value->getValue() > 0xffff) {
return Error(Loc, "inst.n operand is too big, use inst.w instead"); Error(Loc, "inst.n operand is too big, use inst.w instead");
return false;
}
break; break;
case 4: case 4:
if (Value->getValue() > 0xffffffff) if (Value->getValue() > 0xffffffff) {
return Error(Loc, Error(Loc,
StringRef(Suffix ? "inst.w" : "inst") + " operand is too big"); StringRef(Suffix ? "inst.w" : "inst") + " operand is too big");
return false;
}
break; break;
default: default:
llvm_unreachable("only supported widths are 2 and 4"); llvm_unreachable("only supported widths are 2 and 4");
@ -8459,8 +8535,10 @@ bool ARMAsmParser::parseDirectiveInst(SMLoc Loc, char Suffix) {
if (getLexer().is(AsmToken::EndOfStatement)) if (getLexer().is(AsmToken::EndOfStatement))
break; break;
if (getLexer().isNot(AsmToken::Comma)) if (getLexer().isNot(AsmToken::Comma)) {
return Error(Loc, "unexpected token in directive"); Error(Loc, "unexpected token in directive");
return false;
}
Parser.Lex(); Parser.Lex();
} }