#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"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include <cctype>
+#include <deque>
#include <set>
#include <string>
#include <vector>
using namespace llvm;
-static cl::opt<bool>
-FatalAssemblerWarnings("fatal-assembler-warnings",
- cl::desc("Consider warnings as error"));
-
MCAsmParserSemaCallback::~MCAsmParserSemaCallback() {}
namespace {
StringRef Name;
MCAsmMacroArgument Value;
bool Required;
+ bool Vararg;
- MCAsmMacroParameter() : Required(false) { }
+ MCAsmMacroParameter() : Required(false), Vararg(false) {}
};
typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters;
MCAsmMacroParameters Parameters;
public:
- MCAsmMacro(StringRef N, StringRef B, ArrayRef<MCAsmMacroParameter> P) :
- Name(N), Body(B), Parameters(P) {}
+ MCAsmMacro(StringRef N, StringRef B, MCAsmMacroParameters P)
+ : Name(N), Body(B), Parameters(std::move(P)) {}
};
/// \brief Helper class for storing information about an active macro
/// instantiation.
struct MacroInstantiation {
- /// The macro being instantiated.
- const MCAsmMacro *TheMacro;
-
- /// The macro instantiation with substitutions.
- MemoryBuffer *Instantiation;
-
/// The location of the instantiation.
SMLoc InstantiationLoc;
/// The location where parsing should resume upon instantiation completion.
SMLoc ExitLoc;
+ /// The depth of TheCondStack at the start of the instantiation.
+ size_t CondStackDepth;
+
public:
- MacroInstantiation(const MCAsmMacro *M, SMLoc IL, int EB, SMLoc EL,
- MemoryBuffer *I);
+ MacroInstantiation(SMLoc IL, int EB, SMLoc EL, size_t CondStackDepth);
};
struct ParseStatementInfo {
/// \brief The parsed operands from the last parsed statement.
- SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
+ SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
/// \brief The opcode from the last parsed instruction.
unsigned Opcode;
SmallVectorImpl<AsmRewrite> *AsmRewrites;
- ParseStatementInfo() : Opcode(~0U), ParseError(false), AsmRewrites(0) {}
+ ParseStatementInfo() : Opcode(~0U), ParseError(false), AsmRewrites(nullptr) {}
ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
: Opcode(~0), ParseError(false), AsmRewrites(rewrites) {}
-
- ~ParseStatementInfo() {
- // Free any parsed operands.
- for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i)
- delete ParsedOperands[i];
- ParsedOperands.clear();
- }
};
/// \brief The concrete assembly parser instance.
class AsmParser : public MCAsmParser {
- AsmParser(const AsmParser &) LLVM_DELETED_FUNCTION;
- void operator=(const AsmParser &) LLVM_DELETED_FUNCTION;
+ AsmParser(const AsmParser &) = delete;
+ void operator=(const AsmParser &) = delete;
private:
AsmLexer Lexer;
MCContext &Ctx;
SourceMgr &SrcMgr;
SourceMgr::DiagHandlerTy SavedDiagHandler;
void *SavedDiagContext;
- MCAsmParserExtension *PlatformParser;
+ std::unique_ptr<MCAsmParserExtension> PlatformParser;
/// This is the current buffer index we're lexing from as managed by the
/// SourceMgr object.
- int CurBuffer;
+ unsigned CurBuffer;
AsmCond TheCondState;
std::vector<AsmCond> TheCondStack;
StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
/// \brief Map of currently defined macros.
- StringMap<MCAsmMacro*> MacroMap;
+ StringMap<MCAsmMacro> MacroMap;
/// \brief Stack of active macro instantiations.
std::vector<MacroInstantiation*> ActiveMacros;
/// 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;
StringRef CppHashFilename;
int64_t CppHashLineNumber;
SMLoc CppHashLoc;
- int CppHashBuf;
+ unsigned CppHashBuf;
/// When generating dwarf for assembly source files we need to calculate the
/// logical line number based on the last parsed cpp hash file line comment
/// and current line. Since this is slow and messes up the SourceMgr's
/// cache we save the last info we queried with SrcMgr.FindLineNumber().
SMLoc LastQueryIDLoc;
- int LastQueryBuffer;
+ unsigned LastQueryBuffer;
unsigned LastQueryLine;
/// AssemblerDialect. ~OU means unset value and use value provided by MAI.
public:
AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
const MCAsmInfo &MAI);
- virtual ~AsmParser();
+ ~AsmParser() override;
- virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false);
+ bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
- virtual void addDirectiveHandler(StringRef Directive,
- ExtensionDirectiveHandler Handler) {
+ void addDirectiveHandler(StringRef Directive,
+ ExtensionDirectiveHandler Handler) override {
ExtensionDirectiveMap[Directive] = Handler;
}
+ void addAliasForDirective(StringRef Directive, StringRef Alias) override {
+ DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
+ }
+
public:
/// @name MCAsmParser Interface
/// {
- virtual SourceMgr &getSourceManager() { return SrcMgr; }
- virtual MCAsmLexer &getLexer() { return Lexer; }
- virtual MCContext &getContext() { return Ctx; }
- virtual MCStreamer &getStreamer() { return Out; }
- virtual unsigned getAssemblerDialect() {
+ SourceMgr &getSourceManager() override { return SrcMgr; }
+ MCAsmLexer &getLexer() override { return Lexer; }
+ MCContext &getContext() override { return Ctx; }
+ MCStreamer &getStreamer() override { return Out; }
+ unsigned getAssemblerDialect() override {
if (AssemblerDialect == ~0U)
return MAI.getAssemblerDialect();
else
return AssemblerDialect;
}
- virtual void setAssemblerDialect(unsigned i) {
+ void setAssemblerDialect(unsigned i) override {
AssemblerDialect = i;
}
- virtual void Note(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None);
- virtual bool Warning(SMLoc L, const Twine &Msg,
- ArrayRef<SMRange> Ranges = None);
- virtual bool Error(SMLoc L, const Twine &Msg,
- ArrayRef<SMRange> Ranges = None);
+ void Note(SMLoc L, const Twine &Msg,
+ ArrayRef<SMRange> Ranges = None) override;
+ bool Warning(SMLoc L, const Twine &Msg,
+ ArrayRef<SMRange> Ranges = None) override;
+ bool Error(SMLoc L, const Twine &Msg,
+ ArrayRef<SMRange> Ranges = None) override;
- virtual const AsmToken &Lex();
+ const AsmToken &Lex() override;
- void setParsingInlineAsm(bool V) { ParsingInlineAsm = V; }
- bool isParsingInlineAsm() { return ParsingInlineAsm; }
+ void setParsingInlineAsm(bool V) override { ParsingInlineAsm = V; }
+ bool isParsingInlineAsm() override { return ParsingInlineAsm; }
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);
+ const MCInstrInfo *MII, const MCInstPrinter *IP,
+ MCAsmParserSemaCallback &SI) override;
bool parseExpression(const MCExpr *&Res);
- virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc);
- virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc);
- virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc);
- virtual bool parseAbsoluteExpression(int64_t &Res);
+ bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
+ bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
+ bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
+ bool parseAbsoluteExpression(int64_t &Res) override;
/// \brief Parse an identifier or string (as a quoted identifier)
/// and set \p Res to the identifier contents.
- virtual bool parseIdentifier(StringRef &Res);
- virtual void eatToEndOfStatement();
+ bool parseIdentifier(StringRef &Res) override;
+ void eatToEndOfStatement() override;
- virtual void checkForValidSection();
+ void checkForValidSection() override;
/// }
private:
- bool parseStatement(ParseStatementInfo &Info);
+ bool parseStatement(ParseStatementInfo &Info,
+ MCAsmParserSemaCallback *SI);
void eatToEndOfLine();
bool parseCppHashLineFilenameComment(const SMLoc &L);
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?
const MCAsmMacro* lookupMacro(StringRef Name);
/// \brief Define a new macro with the given name and information.
- void defineMacro(StringRef Name, const MCAsmMacro& Macro);
+ void defineMacro(StringRef Name, MCAsmMacro Macro);
/// \brief Undefine a macro. If no such macro was defined, it's a no-op.
void undefineMacro(StringRef Name);
void handleMacroExit();
/// \brief Extract AsmTokens for a macro argument.
- bool parseMacroArgument(MCAsmMacroArgument &MA);
+ bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
/// \brief Parse all macro arguments for a given macro.
bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
/// current token is not set; clients should ensure Lex() is called
/// subsequently.
///
- /// \param InBuffer If not -1, should be the known buffer id that contains the
+ /// \param InBuffer If not 0, should be the known buffer id that contains the
/// location.
- void jumpToLoc(SMLoc Loc, int InBuffer=-1);
+ void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);
/// \brief 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.
- virtual StringRef parseStringToEndOfStatement();
+ StringRef parseStringToEndOfStatement() override;
/// \brief 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.
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_REFERENCE, DK_WEAK_DEFINITION, DK_WEAK_REFERENCE,
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_IFNE, DK_IFB, DK_IFNB, DK_IFC, DK_IFNC, DK_IFDEF, DK_IFNDEF,
+ 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_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA,
DK_CFI_REMEMBER_STATE, DK_CFI_RESTORE_STATE, DK_CFI_SAME_VALUE,
DK_CFI_RESTORE, DK_CFI_ESCAPE, DK_CFI_SIGNAL_FRAME, DK_CFI_UNDEFINED,
DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE,
- DK_MACROS_ON, DK_MACROS_OFF, DK_MACRO, DK_ENDM, DK_ENDMACRO, DK_PURGEM,
+ DK_MACROS_ON, DK_MACROS_OFF,
+ DK_MACRO, DK_EXITM, DK_ENDM, DK_ENDMACRO, DK_PURGEM,
DK_SLEB128, DK_ULEB128,
- DK_ERR,
+ DK_ERR, DK_ERROR, DK_WARNING,
DK_END
};
// macro directives
bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
+ bool parseDirectiveExitMacro(StringRef Directive);
bool parseDirectiveEndMacro(StringRef Directive);
bool parseDirectiveMacro(SMLoc DirectiveLoc);
bool parseDirectiveMacrosOnOff(StringRef Directive);
bool parseDirectiveInclude(); // ".include"
bool parseDirectiveIncbin(); // ".incbin"
- // ".if" or ".ifne"
- bool parseDirectiveIf(SMLoc DirectiveLoc);
+ // ".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
- virtual bool parseEscapedString(std::string &Data);
+ bool parseEscapedString(std::string &Data) override;
const MCExpr *applyModifierToExpr(const MCExpr *E,
MCSymbolRefExpr::VariantKind Variant);
// "end"
bool parseDirectiveEnd(SMLoc DirectiveLoc);
- // "err"
- bool parseDirectiveErr(SMLoc DirectiveLoc);
+ // ".err" or ".error"
+ bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
+
+ // ".warning"
+ bool parseDirectiveWarning(SMLoc DirectiveLoc);
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(0), CurBuffer(0), MacrosEnabledFlag(true),
- CppHashLineNumber(0), AssemblerDialect(~0U), IsDarwin(false),
- ParsingInlineAsm(false) {
+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.
SavedDiagHandler = SrcMgr.getDiagHandler();
SavedDiagContext = SrcMgr.getDiagContext();
// Set our own handler which calls the saved handler.
SrcMgr.setDiagHandler(DiagHandler, this);
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
// Initialize the platform / file format parser.
- switch (_Ctx.getObjectFileInfo()->getObjectFileType()) {
+ switch (Ctx.getObjectFileInfo()->getObjectFileType()) {
case MCObjectFileInfo::IsCOFF:
- PlatformParser = createCOFFAsmParser();
- PlatformParser->Initialize(*this);
- break;
+ PlatformParser.reset(createCOFFAsmParser());
+ break;
case MCObjectFileInfo::IsMachO:
- PlatformParser = createDarwinAsmParser();
- PlatformParser->Initialize(*this);
- IsDarwin = true;
- break;
+ PlatformParser.reset(createDarwinAsmParser());
+ IsDarwin = true;
+ break;
case MCObjectFileInfo::IsELF:
- PlatformParser = createELFAsmParser();
- PlatformParser->Initialize(*this);
- break;
+ PlatformParser.reset(createELFAsmParser());
+ break;
}
+ PlatformParser->Initialize(*this);
initializeDirectiveKindMap();
+
+ NumOfMacroInstantiations = 0;
}
AsmParser::~AsmParser() {
- assert(ActiveMacros.empty() && "Unexpected active macro instantiation!");
-
- // Destroy any macros.
- for (StringMap<MCAsmMacro *>::iterator it = MacroMap.begin(),
- ie = MacroMap.end();
- it != ie; ++it)
- delete it->getValue();
-
- delete PlatformParser;
+ assert((HadError || ActiveMacros.empty()) &&
+ "Unexpected active macro instantiation!");
}
void AsmParser::printMacroInstantiations() {
}
bool AsmParser::Warning(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) {
- if (FatalAssemblerWarnings)
+ if (getTargetParser().getTargetOptions().MCFatalWarnings)
return Error(L, Msg, Ranges);
printMessage(L, SourceMgr::DK_Warning, Msg, Ranges);
printMacroInstantiations();
bool AsmParser::enterIncludeFile(const std::string &Filename) {
std::string IncludedFile;
- int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
- if (NewBuf == -1)
+ unsigned NewBuf =
+ SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
+ if (!NewBuf)
return true;
CurBuffer = NewBuf;
-
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
-
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
return false;
}
/// returns true on failure.
bool AsmParser::processIncbinFile(const std::string &Filename) {
std::string IncludedFile;
- int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
- if (NewBuf == -1)
+ unsigned NewBuf =
+ SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
+ if (!NewBuf)
return true;
// Pick up the bytes from the file and emit them.
return false;
}
-void AsmParser::jumpToLoc(SMLoc Loc, int InBuffer) {
- if (InBuffer != -1) {
- CurBuffer = InBuffer;
- } else {
- CurBuffer = SrcMgr.FindBufferContainingLoc(Loc);
- }
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer), Loc.getPointer());
+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() {
bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// Create the initial section, if requested.
if (!NoInitialTextSection)
- Out.InitSections();
+ Out.InitSections(false);
// Prime the lexer.
Lex();
// If we are generating dwarf for assembly source files save the initial text
// section and generate a .file directive.
if (getContext().getGenDwarfForAssembly()) {
- getContext().setGenDwarfSection(getStreamer().getCurrentSection().first);
- MCSymbol *SectionStartSym = getContext().CreateTempSymbol();
- getStreamer().EmitLabel(SectionStartSym);
- getContext().setGenDwarfSectionStartSym(SectionStartSym);
- getStreamer().EmitDwarfFileDirective(getContext().nextGenDwarfFileNumber(),
- StringRef(),
- getContext().getMainFileName());
+ 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()));
}
// While we have input, parse each statement.
while (Lexer.isNot(AsmToken::Eof)) {
ParseStatementInfo Info;
- if (!parseStatement(Info))
+ if (!parseStatement(Info, nullptr))
continue;
// We had an error, validate that one was emitted and recover by skipping to
return TokError("unmatched .ifs or .elses");
// Check to see there are no empty DwarfFile slots.
- const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles =
- getContext().getMCDwarfFiles();
- for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
- if (!MCDwarfFiles[i])
- TokError("unassigned file number: " + Twine(i) + " for .file directives");
+ 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)
+ TokError("unassigned file number: " + Twine(Index) +
+ " for .file directives");
+ ++Index;
+ }
}
// Check to see that all assembler local symbols were actually defined.
void AsmParser::checkForValidSection() {
if (!ParsingInlineAsm && !getStreamer().getCurrentSection().first) {
TokError("expected section directive before assembly directive");
- Out.InitSections();
+ Out.InitSections(false);
}
}
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;
- } else
- return Error(FirstTokenLoc, "invalid token in expression");
- return true;
+ }
+ return Error(FirstTokenLoc, "invalid token in expression");
}
}
// Parse symbol variant
std::pair<StringRef, StringRef> Split;
if (!MAI.useParensForSymbolVariant()) {
- Split = Identifier.split('@');
+ if (FirstTokenKind == AsmToken::String) {
+ if (Lexer.is(AsmToken::At)) {
+ Lexer.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)) {
Lexer.Lex(); // eat (
StringRef VName;
}
}
- 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
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
if (Split.first.size() != IDVal.size()) {
Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
- if (Variant == MCSymbolRefExpr::VK_Invalid) {
- Variant = MCSymbolRefExpr::VK_None;
+ 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 == "f" ? 1 : 0);
- 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;
}
}
switch (E->getKind()) {
case MCExpr::Target:
case MCExpr::Constant:
- return 0;
+ return nullptr;
case MCExpr::SymbolRef: {
const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
return E;
}
- return MCSymbolRefExpr::Create(&SRE->getSymbol(), Variant, getContext());
+ 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 0;
- return MCUnaryExpr::Create(UE->getOpcode(), Sub, getContext());
+ return nullptr;
+ return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext());
}
case MCExpr::Binary: {
const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant);
if (!LHS && !RHS)
- return 0;
+ return nullptr;
if (!LHS)
LHS = BE->getLHS();
if (!RHS)
RHS = BE->getRHS();
- return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, getContext());
+ return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext());
}
}
///
bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
// Parse the expression.
- Res = 0;
+ Res = nullptr;
if (parsePrimaryExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc))
return true;
// 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;
}
bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
- Res = 0;
+ Res = nullptr;
return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
}
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());
}
}
/// ::= EndOfStatement
/// ::= Label* Directive ...Operands... EndOfStatement
/// ::= Label* Identifier OperandList* EndOfStatement
-bool AsmParser::parseStatement(ParseStatementInfo &Info) {
+bool AsmParser::parseStatement(ParseStatementInfo &Info,
+ MCAsmParserSemaCallback *SI) {
if (Lexer.is(AsmToken::EndOfStatement)) {
Out.AddBlankLine();
Lex();
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);
+ 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:
// FIXME: This doesn't diagnose assignment to a symbol which has been
// implicitly marked as external.
MCSymbol *Sym;
- if (LocalLabelVal == -1)
- Sym = getContext().GetOrCreateSymbol(IDVal);
- else
- Sym = Ctx.CreateDirectionalLocalSymbol(LocalLabelVal);
+ if (LocalLabelVal == -1) {
+ if (ParsingInlineAsm && SI) {
+ 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);
+ } else
+ Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
+
+ Sym->redefineIfPossible();
+
if (!Sym->isUndefined() || Sym->isVariable())
return Error(IDLoc, "invalid symbol redefinition");
return parseDirectiveMacrosOnOff(IDVal);
case DK_MACRO:
return parseDirectiveMacro(IDLoc);
+ case DK_EXITM:
+ return parseDirectiveExitMacro(IDVal);
case DK_ENDM:
case DK_ENDMACRO:
return parseDirectiveEndMacro(IDVal);
case DK_END:
return parseDirectiveEnd(IDLoc);
case DK_ERR:
- return parseDirectiveErr(IDLoc);
+ return parseDirectiveError(IDLoc, false);
+ case DK_ERROR:
+ return parseDirectiveError(IDLoc, true);
+ case DK_WARNING:
+ return parseDirectiveWarning(IDLoc);
}
return Error(IDLoc, "unknown directive");
printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
}
- // If we are generating dwarf for assembly source files and the current
- // section is the initial text section then generate a .loc directive for
- // the instruction.
+ // If we are generating dwarf for the current section then generate a .loc
+ // directive for the instruction.
if (!HadError && getContext().getGenDwarfForAssembly() &&
- getContext().getGenDwarfSection() ==
- getStreamer().getCurrentSection().first) {
-
- unsigned Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
+ getContext().getGenDwarfSectionSyms().count(
+ getStreamer().getCurrentSection().first)) {
+ unsigned Line;
+ if (ActiveMacros.empty())
+ Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
+ else
+ Line = SrcMgr.FindLineNumber(ActiveMacros.back()->InstantiationLoc,
+ ActiveMacros.back()->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.
- const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles =
- getContext().getMCDwarfFiles();
- if (CppHashFilename.size() != 0) {
- if (MCDwarfFiles[getContext().getGenDwarfFileNumber()]->getName() !=
- CppHashFilename)
- getStreamer().EmitDwarfFileDirective(
- getContext().nextGenDwarfFileNumber(), StringRef(),
- CppHashFilename);
+ if (CppHashFilename.size()) {
+ unsigned FileNumber = getStreamer().EmitDwarfFileDirective(
+ 0, StringRef(), CppHashFilename);
+ getContext().setGenDwarfFileNumber(FileNumber);
// Since SrcMgr.FindLineNumber() is slow and messes up the SourceMgr's
// cache with the different Loc from the call above we save the last
// If parsing succeeded, match the instruction.
if (!HadError) {
- unsigned ErrorInfo;
- HadError = getTargetParser().MatchAndEmitInstruction(
- IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
- ParsingInlineAsm);
+ uint64_t ErrorInfo;
+ getTargetParser().MatchAndEmitInstruction(IDLoc, Info.Opcode,
+ Info.ParsedOperands, Out,
+ ErrorInfo, ParsingInlineAsm);
}
// Don't skip the rest of the line, the instruction parser is responsible for
const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
const SMLoc &DiagLoc = Diag.getLoc();
- int DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
- int CppHashBuf = Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashLoc);
+ unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
+ unsigned CppHashBuf =
+ Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashLoc);
// Like SourceMgr::printMessage() we need to print the include stack if any
// before printing the message.
- int DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
- if (!Parser->SavedDiagHandler && DiagCurBuffer > 0) {
+ unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
+ if (!Parser->SavedDiagHandler && DiagCurBuffer &&
+ DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
}
if (Parser->SavedDiagHandler)
Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
else
- Diag.print(0, OS);
+ Diag.print(nullptr, OS);
return;
}
if (Parser->SavedDiagHandler)
Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
else
- NewDiag.print(0, OS);
+ NewDiag.print(nullptr, OS);
}
// FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The
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())
return Error(L, "Wrong number of arguments");
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 {
- for (MCAsmMacroArgument::const_iterator it = A[Index].begin(),
- ie = A[Index].end();
- it != ie; ++it)
- if (it->getKind() == AsmToken::String)
- OS << it->getStringContents();
- else
- OS << it->getString();
-
- 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.
return false;
}
-MacroInstantiation::MacroInstantiation(const MCAsmMacro *M, SMLoc IL, int EB,
- SMLoc EL, MemoryBuffer *I)
- : TheMacro(M), Instantiation(I), InstantiationLoc(IL), ExitBuffer(EB),
- ExitLoc(EL) {}
+MacroInstantiation::MacroInstantiation(SMLoc IL, int EB, SMLoc EL,
+ size_t CondStackDepth)
+ : InstantiationLoc(IL), ExitBuffer(EB), ExitLoc(EL),
+ CondStackDepth(CondStackDepth) {}
static bool isOperator(AsmToken::TokenKind kind) {
switch (kind) {
private:
AsmLexer &Lexer;
};
-}
+} // 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;
+ }
-bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA) {
unsigned ParenLevel = 0;
unsigned AddTokens = 0;
// 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();
return true;
}
- if (parseMacroArgument(FA.Value))
+ bool Vararg = HasVararg && Parameter == (NParameters - 1);
+ if (parseMacroArgument(FA.Value, Vararg))
return true;
unsigned PI = Parameter;
break;
if (FAI >= NParameters) {
+ assert(M && "expected macro to be defined");
Error(IDLoc,
"parameter named '" + FA.Name + "' does not exist for macro '" +
M->Name + "'");
}
const MCAsmMacro *AsmParser::lookupMacro(StringRef Name) {
- StringMap<MCAsmMacro *>::iterator I = MacroMap.find(Name);
- return (I == MacroMap.end()) ? NULL : I->getValue();
+ StringMap<MCAsmMacro>::iterator I = MacroMap.find(Name);
+ return (I == MacroMap.end()) ? nullptr : &I->getValue();
}
-void AsmParser::defineMacro(StringRef Name, const MCAsmMacro &Macro) {
- MacroMap[Name] = new MCAsmMacro(Macro);
+void AsmParser::defineMacro(StringRef Name, MCAsmMacro Macro) {
+ MacroMap.insert(std::make_pair(Name, std::move(Macro)));
}
-void AsmParser::undefineMacro(StringRef Name) {
- StringMap<MCAsmMacro *>::iterator I = MacroMap.find(Name);
- if (I != MacroMap.end()) {
- delete I->getValue();
- MacroMap.erase(I);
- }
-}
+void AsmParser::undefineMacro(StringRef Name) { MacroMap.erase(Name); }
bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
// Arbitrarily limit macro nesting depth, to match 'as'. We can eliminate
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
// instantiation.
OS << ".endmacro\n";
- MemoryBuffer *Instantiation =
+ 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(
- M, NameLoc, CurBuffer, getTok().getLoc(), Instantiation);
+ NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size());
ActiveMacros.push_back(MI);
+ ++NumOfMacroInstantiations;
+
// Jump to the macro instantiation and prime the lexer.
- CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc());
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
+ CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
Lex();
return false;
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);
+ }
// Do the assignment.
Out.EmitAssignment(Sym, Value);
return Error(ExprLoc, "literal value out of range for directive");
getStreamer().EmitIntValue(IntValue, Size);
} else
- getStreamer().EmitValue(Value, Size);
+ getStreamer().EmitValue(Value, Size, ExprLoc);
if (getLexer().is(AsmToken::EndOfStatement))
break;
if (!isUInt<32>(FillExpr) && FillSize > 4)
Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
- int64_t NonZeroFillSize = FillSize > 4 ? 4 : FillSize;
- FillExpr &= ~0ULL >> (64 - NonZeroFillSize * 8);
-
- for (uint64_t i = 0, e = NumValues; i != e; ++i) {
- getStreamer().EmitIntValue(FillExpr, NonZeroFillSize);
- getStreamer().EmitIntValue(0, FillSize - NonZeroFillSize);
+ if (NumValues > 0) {
+ int64_t NonZeroFillSize = FillSize > 4 ? 4 : FillSize;
+ FillExpr &= ~0ULL >> (64 - NonZeroFillSize * 8);
+ for (uint64_t i = 0, e = NumValues; i != e; ++i) {
+ getStreamer().EmitIntValue(FillExpr, NonZeroFillSize);
+ if (NonZeroFillSize < FillSize)
+ getStreamer().EmitIntValue(0, FillSize - NonZeroFillSize);
+ }
}
return false;
// Check whether we should use optimal code alignment for this .align
// directive.
- bool UseCodeAlign = getStreamer().getCurrentSection().first->UseCodeAlign();
+ const MCSection *Section = getStreamer().getCurrentSection().first;
+ 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);
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 (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename))
+ if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename) ==
+ 0)
Error(FileNumberLoc, "file number already allocated");
}
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);
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 one in the list of parameters.");
+
MCAsmMacroParameter Parameter;
if (parseIdentifier(Parameter.Name))
return TokError("expected identifier in '.macro' directive");
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 + "'");
SMLoc ParamLoc;
ParamLoc = Lexer.getLoc();
- if (parseMacroArgument(Parameter.Value))
+ if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
return true;
if (Parameter.Required)
"'" + Parameter.Name + "' in macro '" + Name + "'");
}
- Parameters.push_back(Parameter);
+ Parameters.push_back(std::move(Parameter));
if (getLexer().is(AsmToken::Comma))
Lex();
const char *BodyEnd = EndToken.getLoc().getPointer();
StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
- defineMacro(Name, MCAsmMacro(Name, Body, Parameters));
+ defineMacro(Name, MCAsmMacro(Name, Body, std::move(Parameters)));
return false;
}
"found in body which will have no effect");
}
+/// parseDirectiveExitMacro
+/// ::= .exitm
+bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '" + Directive + "' directive");
+
+ 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
}
/// parseDirectiveLEB128
-/// ::= (.sleb128 | .uleb128) expression
+/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
bool AsmParser::parseDirectiveLEB128(bool Signed) {
checkForValidSection();
const MCExpr *Value;
- if (parseExpression(Value))
- return true;
+ for (;;) {
+ if (parseExpression(Value))
+ return true;
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
+ if (Signed)
+ getStreamer().EmitSLEB128Value(Value);
+ else
+ getStreamer().EmitULEB128Value(Value);
- if (Signed)
- getStreamer().EmitSLEB128Value(Value);
- else
- getStreamer().EmitULEB128Value(Value);
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+ }
return false;
}
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");
}
/// parseDirectiveIf
-/// ::= .if expression
-/// ::= .ifne expression
-bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc) {
+/// ::= .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) {
Lex();
+ 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;
}
+/// parseDirectiveIfeqs
+/// ::= .ifeqs string1, string2
+bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
+ if (Lexer.isNot(AsmToken::String)) {
+ if (ExpectEqual)
+ TokError("expected string parameter for '.ifeqs' directive");
+ else
+ TokError("expected string parameter for '.ifnes' directive");
+ eatToEndOfStatement();
+ return true;
+ }
+
+ StringRef String1 = getTok().getStringContents();
+ Lex();
+
+ if (Lexer.isNot(AsmToken::Comma)) {
+ 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)) {
+ if (ExpectEqual)
+ TokError("expected string parameter for '.ifeqs' directive");
+ else
+ TokError("expected string parameter for '.ifnes' directive");
+ eatToEndOfStatement();
+ return true;
+ }
+
+ 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) {
Lex();
- MCSymbol *Sym = getContext().LookupSymbol(Name);
+ MCSymbol *Sym = getContext().lookupSymbol(Name);
if (expect_defined)
- TheCondState.CondMet = (Sym != NULL && !Sym->isUndefined());
+ TheCondState.CondMet = (Sym && !Sym->isUndefined());
else
- TheCondState.CondMet = (Sym == NULL || Sym->isUndefined());
+ TheCondState.CondMet = (!Sym || Sym->isUndefined());
TheCondState.Ignore = !TheCondState.CondMet;
}
return false;
}
-/// parseDirectiveErr
-/// ::= .err
-bool AsmParser::parseDirectiveErr(SMLoc Loc) {
- if (!TheCondStack.empty())
- if (TheCondStack.back().Ignore)
+/// 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)) {
+ TokError(".error argument must be a string");
+ eatToEndOfStatement();
+ return true;
+ }
+
+ Message = getTok().getStringContents();
+ Lex();
+ }
+
+ Error(L, Message);
+ return true;
+}
+
+/// parseDirectiveWarning
+/// ::= .warning [string]
+bool AsmParser::parseDirectiveWarning(SMLoc L) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
return false;
- return Error(Loc, ".err encountered");
+ }
+ }
+
+ StringRef Message = ".warning directive invoked in source file";
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::String)) {
+ TokError(".warning argument must be a string");
+ eatToEndOfStatement();
+ return true;
+ }
+
+ Message = getTok().getStringContents();
+ Lex();
+ }
+
+ Warning(L, Message);
+ return false;
}
/// parseDirectiveEndIf
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[".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;
}
MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
// Check whether we have reached the end of the file.
if (getLexer().is(AsmToken::Eof)) {
Error(DirectiveLoc, "no matching '.endr' in definition");
- return 0;
+ return nullptr;
}
if (Lexer.is(AsmToken::Identifier) &&
Lex();
if (Lexer.isNot(AsmToken::EndOfStatement)) {
TokError("unexpected token in '.endr' directive");
- return 0;
+ return nullptr;
}
break;
}
StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
// We Are Anonymous.
- MacroLikeBodies.push_back(MCAsmMacro(StringRef(), Body, None));
+ MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
return &MacroLikeBodies.back();
}
raw_svector_ostream &OS) {
OS << ".endr\n";
- MemoryBuffer *Instantiation =
+ 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(
- M, DirectiveLoc, CurBuffer, getTok().getLoc(), Instantiation);
+ DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size());
ActiveMacros.push_back(MI);
// Jump to the macro instantiation and prime the lexer.
- CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc());
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
+ CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
Lex();
}
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);
Lex();
MCAsmMacroArguments A;
- if (parseMacroArguments(0, A))
+ if (parseMacroArguments(nullptr, A))
return true;
// Eat the end of statement.
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;
}
Lex();
MCAsmMacroArguments A;
- if (parseMacroArguments(0, A))
+ if (parseMacroArguments(nullptr, A))
return true;
if (A.size() != 1 || A.front().size() != 1)
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;
}
unsigned OutputIdx = 0;
while (getLexer().isNot(AsmToken::Eof)) {
ParseStatementInfo Info(&AsmStrRewrites);
- if (parseStatement(Info))
+ if (parseStatement(Info, &SI))
return true;
if (Info.ParseError)
// Build the list of clobbers, outputs and inputs.
for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
- MCParsedAsmOperand *Operand = Info.ParsedOperands[i];
+ MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
// Immediate.
- if (Operand->isImm())
+ if (Operand.isImm())
continue;
// Register operand.
- if (Operand->isReg() && !Operand->needAddressOf()) {
+ if (Operand.isReg() && !Operand.needAddressOf() &&
+ !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
unsigned NumDefs = Desc.getNumDefs();
// Clobber.
- if (NumDefs && Operand->getMCOperandNum() < NumDefs)
- ClobberRegs.push_back(Operand->getReg());
+ if (NumDefs && Operand.getMCOperandNum() < NumDefs)
+ ClobberRegs.push_back(Operand.getReg());
continue;
}
// Expr/Input or Output.
- StringRef SymName = Operand->getSymName();
+ StringRef SymName = Operand.getSymName();
if (SymName.empty())
continue;
- void *OpDecl = Operand->getOpDecl();
+ void *OpDecl = Operand.getOpDecl();
if (!OpDecl)
continue;
if (isOutput) {
++InputIdx;
OutputDecls.push_back(OpDecl);
- OutputDeclsAddressOf.push_back(Operand->needAddressOf());
- OutputConstraints.push_back('=' + Operand->getConstraint().str());
+ OutputDeclsAddressOf.push_back(Operand.needAddressOf());
+ OutputConstraints.push_back(("=" + Operand.getConstraint()).str());
AsmStrRewrites.push_back(AsmRewrite(AOK_Output, Start, SymName.size()));
} else {
InputDecls.push_back(OpDecl);
- InputDeclsAddressOf.push_back(Operand->needAddressOf());
- InputConstraints.push_back(Operand->getConstraint().str());
+ InputDeclsAddressOf.push_back(Operand.needAddressOf());
+ InputConstraints.push_back(Operand.getConstraint().str());
AsmStrRewrites.push_back(AsmRewrite(AOK_Input, Start, SymName.size()));
}
}
// Consider implicit defs to be clobbers. Think of cpuid and push.
- const uint16_t *ImpDefs = Desc.getImplicitDefs();
- for (unsigned I = 0, E = Desc.getNumImplicitDefs(); I != E; ++I)
- ClobberRegs.push_back(ImpDefs[I]);
+ ArrayRef<uint16_t> ImpDefs(Desc.getImplicitDefs(),
+ Desc.getNumImplicitDefs());
+ ClobberRegs.insert(ClobberRegs.end(), ImpDefs.begin(), ImpDefs.end());
}
// Set the number of Outputs and Inputs.
// Build the IR assembly string.
std::string AsmStringIR;
raw_string_ostream OS(AsmStringIR);
- const char *AsmStart = SrcMgr.getMemoryBuffer(0)->getBufferStart();
- const char *AsmEnd = SrcMgr.getMemoryBuffer(0)->getBufferEnd();
+ 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 (SmallVectorImpl<AsmRewrite>::iterator I = AsmStrRewrites.begin(),
- E = AsmStrRewrites.end();
- I != E; ++I) {
- AsmRewriteKind Kind = (*I).Kind;
+ for (const AsmRewrite &AR : AsmStrRewrites) {
+ AsmRewriteKind Kind = AR.Kind;
if (Kind == AOK_Delete)
continue;
- const char *Loc = (*I).Loc.getPointer();
+ const char *Loc = AR.Loc.getPointer();
assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
// Emit everything up to the immediate/expression.
- unsigned Len = Loc - AsmStart;
- if (Len)
+ if (unsigned Len = Loc - AsmStart)
OS << StringRef(AsmStart, Len);
// Skip the original expression.
if (Kind == AOK_Skip) {
- AsmStart = Loc + (*I).Len;
+ AsmStart = Loc + AR.Len;
continue;
}
default:
break;
case AOK_Imm:
- OS << "$$" << (*I).Val;
+ OS << "$$" << AR.Val;
break;
case AOK_ImmPrefix:
OS << "$$";
break;
+ case AOK_Label:
+ OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
+ break;
case AOK_Input:
OS << '$' << InputIdx++;
break;
OS << '$' << OutputIdx++;
break;
case AOK_SizeDirective:
- switch ((*I).Val) {
+ switch (AR.Val) {
default: break;
case 8: OS << "byte ptr "; break;
case 16: OS << "word ptr "; break;
OS << ".byte";
break;
case AOK_Align: {
- unsigned Val = (*I).Val;
+ unsigned Val = AR.Val;
OS << ".align " << Val;
// Skip the original immediate.
break;
}
case AOK_DotOperator:
- OS << (*I).Val;
+ // Insert the dot if the user omitted it.
+ OS.flush();
+ if (AsmStringIR.back() != '.')
+ OS << '.';
+ OS << AR.Val;
break;
}
// Skip the original expression.
- AsmStart = Loc + (*I).Len + AdditionalSkip;
+ AsmStart = Loc + AR.Len + AdditionalSkip;
}
// Emit the remainder of the asm string.
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) {