#include "llvm/MC/MCParser/AsmCond.h"
#include "llvm/MC/MCParser/AsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCAsmParserUtils.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionMachO.h"
/// Boolean tracking whether macro substitution is enabled.
unsigned MacrosEnabledFlag : 1;
+ /// \brief Keeps track of how many .macro's have been instantiated.
+ unsigned NumOfMacroInstantiations;
+
/// Flag tracking whether any errors have been encountered.
unsigned HadError : 1;
public:
AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
const MCAsmInfo &MAI);
- virtual ~AsmParser();
+ ~AsmParser() override;
bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
ExtensionDirectiveMap[Directive] = Handler;
}
+ void addAliasForDirective(StringRef Directive, StringRef Alias) override {
+ DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
+ }
+
public:
/// @name MCAsmParser Interface
/// {
ArrayRef<MCAsmMacroParameter> Parameters);
bool expandMacro(raw_svector_ostream &OS, StringRef Body,
ArrayRef<MCAsmMacroParameter> Parameters,
- ArrayRef<MCAsmMacroArgument> A,
+ ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable,
const SMLoc &L);
/// \brief Are macros enabled in the parser?
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);
DK_WEAK_DEF_CAN_BE_HIDDEN, 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_IFDEF, DK_IFNDEF, DK_IFNOTDEF,
- DK_ELSEIF, DK_ELSE, DK_ENDIF,
+ 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_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,
bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
// ".ifc" or ".ifnc", depending on ExpectEqual.
bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
- // ".ifeqs"
- bool parseDirectiveIfeqs(SMLoc DirectiveLoc);
+ // ".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"
void initializeDirectiveKindMap();
};
-}
+} // namespace
namespace llvm {
enum { DEFAULT_ADDRSPACE = 0 };
-AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out,
- const MCAsmInfo &_MAI)
- : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM),
- PlatformParser(nullptr), CurBuffer(_SM.getMainFileID()),
+AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
+ const MCAsmInfo &MAI)
+ : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
+ PlatformParser(nullptr), CurBuffer(SM.getMainFileID()),
MacrosEnabledFlag(true), HadError(false), CppHashLineNumber(0),
AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false) {
// Save the old handler.
Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
// Initialize the platform / file format parser.
- switch (_Ctx.getObjectFileInfo()->getObjectFileType()) {
+ switch (Ctx.getObjectFileInfo()->getObjectFileType()) {
case MCObjectFileInfo::IsCOFF:
PlatformParser.reset(createCOFFAsmParser());
break;
PlatformParser->Initialize(*this);
initializeDirectiveKindMap();
+
+ NumOfMacroInstantiations = 0;
}
AsmParser::~AsmParser() {
// If we are generating dwarf for assembly source files save the initial text
// section and generate a .file directive.
if (getContext().getGenDwarfForAssembly()) {
- MCSymbol *SectionStartSym = getContext().CreateTempSymbol();
- getStreamer().EmitLabel(SectionStartSym);
- auto InsertResult = getContext().addGenDwarfSection(
- getStreamer().getCurrentSection().first);
- assert(InsertResult.second && ".text section should not have debug info yet");
- InsertResult.first->second.first = SectionStartSym;
+ MCSection *Sec = getStreamer().getCurrentSection().first;
+ 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;
getContext().setGenDwarfFileNumber(getStreamer().EmitDwarfFileDirective(
0, StringRef(), getContext().getMainFileName()));
}
Lex(); // Eat the operator.
if (parsePrimaryExpr(Res, EndLoc))
return true;
- Res = MCUnaryExpr::CreateLNot(Res, getContext());
+ Res = MCUnaryExpr::createLNot(Res, getContext());
return false;
case AsmToken::Dollar:
case AsmToken::At:
if (Lexer.getMAI().getDollarIsPC()) {
// This is a '$' reference, which references the current PC. Emit a
// temporary label to the streamer and refer to it.
- MCSymbol *Sym = Ctx.CreateTempSymbol();
+ MCSymbol *Sym = Ctx.createTempSymbol();
Out.EmitLabel(Sym);
- Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
+ Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
getContext());
EndLoc = FirstTokenLoc;
return false;
}
}
- MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
+ MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
// If this is an absolute variable reference, substitute it now to preserve
// semantics in the face of reassignment.
}
// Otherwise create a symbol ref.
- Res = MCSymbolRefExpr::Create(Sym, Variant, getContext());
+ Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
return false;
}
case AsmToken::BigNum:
case AsmToken::Integer: {
SMLoc Loc = getTok().getLoc();
int64_t IntVal = getTok().getIntVal();
- Res = MCConstantExpr::Create(IntVal, getContext());
+ 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 (IDVal == "f" || IDVal == "b") {
MCSymbol *Sym =
- Ctx.GetDirectionalLocalSymbol(IntVal, IDVal == "b");
- Res = MCSymbolRefExpr::Create(Sym, Variant, getContext());
+ Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
+ Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
if (IDVal == "b" && Sym->isUndefined())
return Error(Loc, "invalid reference to undefined symbol");
EndLoc = Lexer.getTok().getEndLoc();
case AsmToken::Real: {
APFloat RealVal(APFloat::IEEEdouble, getTok().getString());
uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
- Res = MCConstantExpr::Create(IntVal, getContext());
+ 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();
+ MCSymbol *Sym = Ctx.createTempSymbol();
Out.EmitLabel(Sym);
- Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
+ Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
EndLoc = Lexer.getTok().getEndLoc();
Lex(); // Eat identifier.
return false;
Lex(); // Eat the operator.
if (parsePrimaryExpr(Res, EndLoc))
return true;
- Res = MCUnaryExpr::CreateMinus(Res, getContext());
+ Res = MCUnaryExpr::createMinus(Res, getContext());
return false;
case AsmToken::Plus:
Lex(); // Eat the operator.
if (parsePrimaryExpr(Res, EndLoc))
return true;
- Res = MCUnaryExpr::CreatePlus(Res, getContext());
+ Res = MCUnaryExpr::createPlus(Res, getContext());
return false;
case AsmToken::Tilde:
Lex(); // Eat the operator.
if (parsePrimaryExpr(Res, EndLoc))
return true;
- Res = MCUnaryExpr::CreateNot(Res, getContext());
+ Res = MCUnaryExpr::createNot(Res, getContext());
return false;
}
}
return E;
}
- return MCSymbolRefExpr::Create(&SRE->getSymbol(), Variant, getContext());
+ return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext());
}
case MCExpr::Unary: {
const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant);
if (!Sub)
return nullptr;
- return MCUnaryExpr::Create(UE->getOpcode(), Sub, getContext());
+ return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext());
}
case MCExpr::Binary: {
if (!RHS)
RHS = BE->getRHS();
- return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, getContext());
+ return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext());
}
}
// Try to constant fold it up front, if possible.
int64_t Value;
- if (Res->EvaluateAsAbsolute(Value))
- Res = MCConstantExpr::Create(Value, getContext());
+ if (Res->evaluateAsAbsolute(Value))
+ Res = MCConstantExpr::create(Value, getContext());
return false;
}
if (parseExpression(Expr))
return true;
- if (!Expr->EvaluateAsAbsolute(Res))
+ if (!Expr->evaluateAsAbsolute(Res))
return Error(StartLoc, "expected absolute expression");
return false;
}
-static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind) {
+unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
+ MCBinaryExpr::Opcode &Kind) {
switch (K) {
default:
return 0; // not a binop.
Kind = MCBinaryExpr::Shl;
return 4;
case AsmToken::GreaterGreater:
- Kind = MCBinaryExpr::Shr;
+ Kind = MAI.shouldUseLogicalShr() ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
return 4;
// High Intermediate Precedence: +, -
return true;
// Merge LHS and RHS according to operator.
- Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext());
+ Res = MCBinaryExpr::create(Kind, Res, RHS, getContext());
}
}
case DK_IFC:
return parseDirectiveIfc(IDLoc, true);
case DK_IFEQS:
- return parseDirectiveIfeqs(IDLoc);
+ 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:
MCSymbol *Sym;
if (LocalLabelVal == -1) {
if (ParsingInlineAsm && SI) {
- StringRef RewrittenLabel = SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
- assert(RewrittenLabel.size() && "We should have an internal name here.");
+ StringRef RewrittenLabel =
+ SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
+ assert(RewrittenLabel.size() &&
+ "We should have an internal name here.");
Info.AsmRewrites->push_back(AsmRewrite(AOK_Label, IDLoc,
IDVal.size(), RewrittenLabel));
IDVal = RewrittenLabel;
}
- Sym = getContext().GetOrCreateSymbol(IDVal);
+ Sym = getContext().getOrCreateSymbol(IDVal);
} else
- Sym = Ctx.CreateDirectionalLocalSymbol(LocalLabelVal);
+ Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
Sym->redefineIfPossible();
bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
ArrayRef<MCAsmMacroParameter> Parameters,
- ArrayRef<MCAsmMacroArgument> A, const SMLoc &L) {
+ ArrayRef<MCAsmMacroArgument> A,
+ bool EnableAtPseudoVariable, const SMLoc &L) {
unsigned NParameters = Parameters.size();
bool HasVararg = NParameters ? Parameters.back().Vararg : false;
if ((!IsDarwin || NParameters != 0) && NParameters != A.size())
Pos += 2;
} else {
unsigned I = Pos + 1;
- while (isIdentifierChar(Body[I]) && I + 1 != End)
+
+ // 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;
- 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;
- }
+ if (Argument == "@") {
+ OS << NumOfMacroInstantiations;
+ Pos += 2;
} else {
- bool VarargParameter = HasVararg && Index == (NParameters - 1);
- for (MCAsmMacroArgument::const_iterator it = A[Index].begin(),
- ie = A[Index].end();
- it != ie; ++it)
- // We expect no quotes around the string's contents when
- // parsing for varargs.
- if (it->getKind() != AsmToken::String || VarargParameter)
- OS << it->getString();
- else
- OS << it->getStringContents();
-
- Pos += 1 + Argument.size();
+ 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 (MCAsmMacroArgument::const_iterator it = A[Index].begin(),
+ ie = A[Index].end();
+ it != ie; ++it)
+ // We expect no quotes around the string's contents when
+ // parsing for varargs.
+ if (it->getKind() != AsmToken::String || VarargParameter)
+ OS << it->getString();
+ else
+ OS << it->getStringContents();
+
+ Pos += 1 + Argument.size();
+ }
}
}
// Update the scan point.
private:
AsmLexer &Lexer;
};
-}
+} // namespace
bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
if (Vararg) {
if (Lexer.isNot(AsmToken::EndOfStatement)) {
StringRef Str = parseStringToEndOfStatement();
- MA.push_back(AsmToken(AsmToken::String, Str));
+ MA.emplace_back(AsmToken::String, Str);
}
return false;
}
StringRef Body = M->Body;
raw_svector_ostream OS(Buf);
- if (expandMacro(OS, Body, M->Parameters, A, getTok().getLoc()))
+ 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
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());
ActiveMacros.pop_back();
}
-static bool isUsedIn(const MCSymbol *Sym, const MCExpr *Value) {
- switch (Value->getKind()) {
- case MCExpr::Binary: {
- const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
- return isUsedIn(Sym, BE->getLHS()) || isUsedIn(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 isUsedIn(Sym, S.getVariableValue());
- return &S == Sym;
- }
- case MCExpr::Unary:
- return isUsedIn(Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
- }
-
- llvm_unreachable("Unknown expr kind!");
-}
-
bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
bool NoDeadStrip) {
- // FIXME: Use better location, we should use proper tokens.
- SMLoc EqualLoc = Lexer.getLoc();
-
+ MCSymbol *Sym;
const MCExpr *Value;
- if (parseExpression(Value))
+ if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym,
+ Value))
return true;
- // Note: we don't count b as used in "a = b". This is to allow
- // a = b
- // b = c
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in assignment");
-
- // Eat the end of statement marker.
- Lex();
-
- // 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).
- MCSymbol *Sym = 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 (isUsedIn(Sym, Value))
- return Error(EqualLoc, "Recursive use of '" + Name + "'");
- else if (Sym->isUndefined() && !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 Error(EqualLoc, "redefinition of '" + Name + "'");
- else if (!Sym->isVariable())
- return Error(EqualLoc, "invalid assignment to '" + Name + "'");
- else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
- return Error(EqualLoc, "invalid reassignment of non-absolute variable '" +
- Name + "'");
-
- // Don't count these checks as uses.
- Sym->setUsed(false);
- } else if (Name == ".") {
- if (Out.EmitValueToOffset(Value, 0)) {
- Error(EqualLoc, "expected absolute expression");
- eatToEndOfStatement();
- }
+ 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;
- } else
- Sym = getContext().GetOrCreateSymbol(Name);
-
- Sym->setRedefinable(allow_redef);
+ }
// Do the assignment.
Out.EmitAssignment(Sym, Value);
if (FileNumber == -1)
getStreamer().EmitFileDirective(Filename);
else {
- if (getContext().getGenDwarfForAssembly() == true)
+ if (getContext().getGenDwarfForAssembly())
Error(DirectiveLoc,
"input can't have .file dwarf directives when -g is "
"used to generate dwarf debug info for assembly code");
if (parseIdentifier(Name))
return TokError("expected identifier in directive");
- MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
if (IsPersonality)
getStreamer().EmitCFIPersonality(Sym, Encoding);
if (parseIdentifier(Name))
return Error(Loc, "expected identifier in directive");
- MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
// Assembler local symbols don't make any sense here. Complain loudly.
if (Sym->isTemporary())
return TokError("expected identifier in directive");
// Handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
if (getLexer().isNot(AsmToken::Comma))
return TokError("unexpected token in directive");
/// parseDirectiveIfeqs
/// ::= .ifeqs string1, string2
-bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
if (Lexer.isNot(AsmToken::String)) {
- TokError("expected string parameter for '.ifeqs' directive");
+ if (ExpectEqual)
+ TokError("expected string parameter for '.ifeqs' directive");
+ else
+ TokError("expected string parameter for '.ifnes' directive");
eatToEndOfStatement();
return true;
}
Lex();
if (Lexer.isNot(AsmToken::Comma)) {
- TokError("expected comma after first string for '.ifeqs' directive");
+ if (ExpectEqual)
+ TokError("expected comma after first string for '.ifeqs' directive");
+ else
+ TokError("expected comma after first string for '.ifnes' directive");
eatToEndOfStatement();
return true;
}
Lex();
if (Lexer.isNot(AsmToken::String)) {
- TokError("expected string parameter for '.ifeqs' directive");
+ if (ExpectEqual)
+ TokError("expected string parameter for '.ifeqs' directive");
+ else
+ TokError("expected string parameter for '.ifnes' directive");
eatToEndOfStatement();
return true;
}
TheCondStack.push_back(TheCondState);
TheCondState.TheCond = AsmCond::IfCond;
- TheCondState.CondMet = String1 == String2;
+ TheCondState.CondMet = ExpectEqual == (String1 == String2);
TheCondState.Ignore = !TheCondState.CondMet;
return false;
Lex();
- MCSymbol *Sym = getContext().LookupSymbol(Name);
+ MCSymbol *Sym = getContext().lookupSymbol(Name);
if (expect_defined)
TheCondState.CondMet = (Sym && !Sym->isUndefined());
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;
StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
// We Are Anonymous.
- MacroLikeBodies.push_back(
- MCAsmMacro(StringRef(), Body, MCAsmMacroParameters()));
+ MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
return &MacroLikeBodies.back();
}
return true;
int64_t Count;
- if (!CountExpr->EvaluateAsAbsolute(Count)) {
+ if (!CountExpr->evaluateAsAbsolute(Count)) {
eatToEndOfStatement();
return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
}
SmallString<256> Buf;
raw_svector_ostream OS(Buf);
while (Count--) {
- if (expandMacro(OS, M->Body, None, None, getTok().getLoc()))
+ // 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);
raw_svector_ostream OS(Buf);
for (MCAsmMacroArguments::iterator i = A.begin(), e = A.end(); i != e; ++i) {
- if (expandMacro(OS, M->Body, Parameter, *i, getTok().getLoc()))
+ // 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, *i, true, getTok().getLoc()))
return true;
}
StringRef Values = A.front().front().getString();
for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
MCAsmMacroArgument Arg;
- Arg.push_back(AsmToken(AsmToken::Identifier, Values.slice(I, I + 1)));
+ Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
- if (expandMacro(OS, M->Body, Parameter, Arg, getTok().getLoc()))
+ // 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;
}
++InputIdx;
OutputDecls.push_back(OpDecl);
OutputDeclsAddressOf.push_back(Operand.needAddressOf());
- OutputConstraints.push_back('=' + Operand.getConstraint().str());
+ OutputConstraints.push_back(("=" + Operand.getConstraint()).str());
AsmStrRewrites.push_back(AsmRewrite(AOK_Output, Start, SymName.size()));
} else {
InputDecls.push_back(OpDecl);
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) {
+ MCAsmLexer &Lexer = Parser.getLexer();
+
+ // FIXME: Use better location, we should use proper tokens.
+ SMLoc EqualLoc = Lexer.getLoc();
+
+ if (Parser.parseExpression(Value)) {
+ Parser.TokError("missing expression");
+ Parser.eatToEndOfStatement();
+ return true;
+ }
+
+ // Note: we don't count b as used in "a = b". This is to allow
+ // a = b
+ // b = c
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return Parser.TokError("unexpected token in assignment");
+
+ // Eat the end of statement marker.
+ Parser.Lex();
+
+ // 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() && !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 + "'");
+
+ // Don't count these checks as uses.
+ Sym->setUsed(false);
+ } else if (Name == ".") {
+ if (Parser.getStreamer().EmitValueToOffset(Value, 0)) {
+ Parser.Error(EqualLoc, "expected absolute expression");
+ Parser.eatToEndOfStatement();
+ return true;
+ }
+ return false;
+ } else
+ Sym = Parser.getContext().getOrCreateSymbol(Name);
+
+ Sym->setRedefinable(allow_redef);
+
+ return false;
+}
+
+} // namespace MCParserUtils
+} // namespace llvm
+
/// \brief Create an MCAsmParser instance.
MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
MCStreamer &Out, const MCAsmInfo &MAI) {