17330f729Sjoerg //===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
9*82d56013Sjoerg // This class implements a parser for assembly files similar to gas syntax.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg
137330f729Sjoerg #include "llvm/ADT/APFloat.h"
147330f729Sjoerg #include "llvm/ADT/APInt.h"
157330f729Sjoerg #include "llvm/ADT/ArrayRef.h"
167330f729Sjoerg #include "llvm/ADT/None.h"
177330f729Sjoerg #include "llvm/ADT/STLExtras.h"
18*82d56013Sjoerg #include "llvm/ADT/SmallSet.h"
197330f729Sjoerg #include "llvm/ADT/SmallString.h"
207330f729Sjoerg #include "llvm/ADT/SmallVector.h"
217330f729Sjoerg #include "llvm/ADT/StringExtras.h"
227330f729Sjoerg #include "llvm/ADT/StringMap.h"
237330f729Sjoerg #include "llvm/ADT/StringRef.h"
247330f729Sjoerg #include "llvm/ADT/Twine.h"
257330f729Sjoerg #include "llvm/BinaryFormat/Dwarf.h"
267330f729Sjoerg #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
277330f729Sjoerg #include "llvm/MC/MCAsmInfo.h"
287330f729Sjoerg #include "llvm/MC/MCCodeView.h"
297330f729Sjoerg #include "llvm/MC/MCContext.h"
307330f729Sjoerg #include "llvm/MC/MCDirectives.h"
317330f729Sjoerg #include "llvm/MC/MCDwarf.h"
327330f729Sjoerg #include "llvm/MC/MCExpr.h"
337330f729Sjoerg #include "llvm/MC/MCInstPrinter.h"
347330f729Sjoerg #include "llvm/MC/MCInstrDesc.h"
357330f729Sjoerg #include "llvm/MC/MCInstrInfo.h"
367330f729Sjoerg #include "llvm/MC/MCObjectFileInfo.h"
377330f729Sjoerg #include "llvm/MC/MCParser/AsmCond.h"
387330f729Sjoerg #include "llvm/MC/MCParser/AsmLexer.h"
397330f729Sjoerg #include "llvm/MC/MCParser/MCAsmLexer.h"
407330f729Sjoerg #include "llvm/MC/MCParser/MCAsmParser.h"
417330f729Sjoerg #include "llvm/MC/MCParser/MCAsmParserExtension.h"
427330f729Sjoerg #include "llvm/MC/MCParser/MCAsmParserUtils.h"
437330f729Sjoerg #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
447330f729Sjoerg #include "llvm/MC/MCParser/MCTargetAsmParser.h"
457330f729Sjoerg #include "llvm/MC/MCRegisterInfo.h"
467330f729Sjoerg #include "llvm/MC/MCSection.h"
477330f729Sjoerg #include "llvm/MC/MCStreamer.h"
487330f729Sjoerg #include "llvm/MC/MCSymbol.h"
497330f729Sjoerg #include "llvm/MC/MCTargetOptions.h"
507330f729Sjoerg #include "llvm/MC/MCValue.h"
517330f729Sjoerg #include "llvm/Support/Casting.h"
527330f729Sjoerg #include "llvm/Support/CommandLine.h"
537330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
547330f729Sjoerg #include "llvm/Support/MD5.h"
557330f729Sjoerg #include "llvm/Support/MathExtras.h"
567330f729Sjoerg #include "llvm/Support/MemoryBuffer.h"
577330f729Sjoerg #include "llvm/Support/SMLoc.h"
587330f729Sjoerg #include "llvm/Support/SourceMgr.h"
597330f729Sjoerg #include "llvm/Support/raw_ostream.h"
607330f729Sjoerg #include <algorithm>
617330f729Sjoerg #include <cassert>
627330f729Sjoerg #include <cctype>
637330f729Sjoerg #include <climits>
647330f729Sjoerg #include <cstddef>
657330f729Sjoerg #include <cstdint>
667330f729Sjoerg #include <deque>
677330f729Sjoerg #include <memory>
687330f729Sjoerg #include <sstream>
697330f729Sjoerg #include <string>
707330f729Sjoerg #include <tuple>
717330f729Sjoerg #include <utility>
727330f729Sjoerg #include <vector>
737330f729Sjoerg
747330f729Sjoerg using namespace llvm;
757330f729Sjoerg
767330f729Sjoerg MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;
777330f729Sjoerg
78*82d56013Sjoerg extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
797330f729Sjoerg
807330f729Sjoerg namespace {
817330f729Sjoerg
827330f729Sjoerg /// Helper types for tracking macro definitions.
837330f729Sjoerg typedef std::vector<AsmToken> MCAsmMacroArgument;
847330f729Sjoerg typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
857330f729Sjoerg
867330f729Sjoerg /// Helper class for storing information about an active macro
877330f729Sjoerg /// instantiation.
887330f729Sjoerg struct MacroInstantiation {
897330f729Sjoerg /// The location of the instantiation.
907330f729Sjoerg SMLoc InstantiationLoc;
917330f729Sjoerg
927330f729Sjoerg /// The buffer where parsing should resume upon instantiation completion.
93*82d56013Sjoerg unsigned ExitBuffer;
947330f729Sjoerg
957330f729Sjoerg /// The location where parsing should resume upon instantiation completion.
967330f729Sjoerg SMLoc ExitLoc;
977330f729Sjoerg
987330f729Sjoerg /// The depth of TheCondStack at the start of the instantiation.
997330f729Sjoerg size_t CondStackDepth;
1007330f729Sjoerg };
1017330f729Sjoerg
1027330f729Sjoerg struct ParseStatementInfo {
1037330f729Sjoerg /// The parsed operands from the last parsed statement.
1047330f729Sjoerg SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
1057330f729Sjoerg
1067330f729Sjoerg /// The opcode from the last parsed instruction.
1077330f729Sjoerg unsigned Opcode = ~0U;
1087330f729Sjoerg
1097330f729Sjoerg /// Was there an error parsing the inline assembly?
1107330f729Sjoerg bool ParseError = false;
1117330f729Sjoerg
1127330f729Sjoerg SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
1137330f729Sjoerg
1147330f729Sjoerg ParseStatementInfo() = delete;
ParseStatementInfo__anon107f35340111::ParseStatementInfo1157330f729Sjoerg ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
1167330f729Sjoerg : AsmRewrites(rewrites) {}
1177330f729Sjoerg };
1187330f729Sjoerg
1197330f729Sjoerg /// The concrete assembly parser instance.
1207330f729Sjoerg class AsmParser : public MCAsmParser {
1217330f729Sjoerg private:
1227330f729Sjoerg AsmLexer Lexer;
1237330f729Sjoerg MCContext &Ctx;
1247330f729Sjoerg MCStreamer &Out;
1257330f729Sjoerg const MCAsmInfo &MAI;
1267330f729Sjoerg SourceMgr &SrcMgr;
1277330f729Sjoerg SourceMgr::DiagHandlerTy SavedDiagHandler;
1287330f729Sjoerg void *SavedDiagContext;
1297330f729Sjoerg std::unique_ptr<MCAsmParserExtension> PlatformParser;
130*82d56013Sjoerg SMLoc StartTokLoc;
1317330f729Sjoerg
1327330f729Sjoerg /// This is the current buffer index we're lexing from as managed by the
1337330f729Sjoerg /// SourceMgr object.
1347330f729Sjoerg unsigned CurBuffer;
1357330f729Sjoerg
1367330f729Sjoerg AsmCond TheCondState;
1377330f729Sjoerg std::vector<AsmCond> TheCondStack;
1387330f729Sjoerg
1397330f729Sjoerg /// maps directive names to handler methods in parser
1407330f729Sjoerg /// extensions. Extensions register themselves in this map by calling
1417330f729Sjoerg /// addDirectiveHandler.
1427330f729Sjoerg StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
1437330f729Sjoerg
1447330f729Sjoerg /// Stack of active macro instantiations.
1457330f729Sjoerg std::vector<MacroInstantiation*> ActiveMacros;
1467330f729Sjoerg
1477330f729Sjoerg /// List of bodies of anonymous macros.
1487330f729Sjoerg std::deque<MCAsmMacro> MacroLikeBodies;
1497330f729Sjoerg
1507330f729Sjoerg /// Boolean tracking whether macro substitution is enabled.
1517330f729Sjoerg unsigned MacrosEnabledFlag : 1;
1527330f729Sjoerg
1537330f729Sjoerg /// Keeps track of how many .macro's have been instantiated.
1547330f729Sjoerg unsigned NumOfMacroInstantiations;
1557330f729Sjoerg
1567330f729Sjoerg /// The values from the last parsed cpp hash file line comment if any.
1577330f729Sjoerg struct CppHashInfoTy {
1587330f729Sjoerg StringRef Filename;
1597330f729Sjoerg int64_t LineNumber;
1607330f729Sjoerg SMLoc Loc;
1617330f729Sjoerg unsigned Buf;
CppHashInfoTy__anon107f35340111::AsmParser::CppHashInfoTy1627330f729Sjoerg CppHashInfoTy() : Filename(), LineNumber(0), Loc(), Buf(0) {}
1637330f729Sjoerg };
1647330f729Sjoerg CppHashInfoTy CppHashInfo;
1657330f729Sjoerg
1667330f729Sjoerg /// The filename from the first cpp hash file line comment, if any.
1677330f729Sjoerg StringRef FirstCppHashFilename;
1687330f729Sjoerg
1697330f729Sjoerg /// List of forward directional labels for diagnosis at the end.
1707330f729Sjoerg SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
1717330f729Sjoerg
172*82d56013Sjoerg SmallSet<StringRef, 2> LTODiscardSymbols;
173*82d56013Sjoerg
1747330f729Sjoerg /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
1757330f729Sjoerg unsigned AssemblerDialect = ~0U;
1767330f729Sjoerg
1777330f729Sjoerg /// is Darwin compatibility enabled?
1787330f729Sjoerg bool IsDarwin = false;
1797330f729Sjoerg
1807330f729Sjoerg /// Are we parsing ms-style inline assembly?
181*82d56013Sjoerg bool ParsingMSInlineAsm = false;
1827330f729Sjoerg
1837330f729Sjoerg /// Did we already inform the user about inconsistent MD5 usage?
1847330f729Sjoerg bool ReportedInconsistentMD5 = false;
1857330f729Sjoerg
1867330f729Sjoerg // Is alt macro mode enabled.
1877330f729Sjoerg bool AltMacroMode = false;
1887330f729Sjoerg
189*82d56013Sjoerg protected:
190*82d56013Sjoerg virtual bool parseStatement(ParseStatementInfo &Info,
191*82d56013Sjoerg MCAsmParserSemaCallback *SI);
192*82d56013Sjoerg
193*82d56013Sjoerg /// This routine uses the target specific ParseInstruction function to
194*82d56013Sjoerg /// parse an instruction into Operands, and then call the target specific
195*82d56013Sjoerg /// MatchAndEmit function to match and emit the instruction.
196*82d56013Sjoerg bool parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,
197*82d56013Sjoerg StringRef IDVal, AsmToken ID,
198*82d56013Sjoerg SMLoc IDLoc);
199*82d56013Sjoerg
2007330f729Sjoerg public:
2017330f729Sjoerg AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
2027330f729Sjoerg const MCAsmInfo &MAI, unsigned CB);
2037330f729Sjoerg AsmParser(const AsmParser &) = delete;
2047330f729Sjoerg AsmParser &operator=(const AsmParser &) = delete;
2057330f729Sjoerg ~AsmParser() override;
2067330f729Sjoerg
2077330f729Sjoerg bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
2087330f729Sjoerg
addDirectiveHandler(StringRef Directive,ExtensionDirectiveHandler Handler)2097330f729Sjoerg void addDirectiveHandler(StringRef Directive,
2107330f729Sjoerg ExtensionDirectiveHandler Handler) override {
2117330f729Sjoerg ExtensionDirectiveMap[Directive] = Handler;
2127330f729Sjoerg }
2137330f729Sjoerg
addAliasForDirective(StringRef Directive,StringRef Alias)2147330f729Sjoerg void addAliasForDirective(StringRef Directive, StringRef Alias) override {
215*82d56013Sjoerg DirectiveKindMap[Directive.lower()] = DirectiveKindMap[Alias.lower()];
2167330f729Sjoerg }
2177330f729Sjoerg
2187330f729Sjoerg /// @name MCAsmParser Interface
2197330f729Sjoerg /// {
2207330f729Sjoerg
getSourceManager()2217330f729Sjoerg SourceMgr &getSourceManager() override { return SrcMgr; }
getLexer()2227330f729Sjoerg MCAsmLexer &getLexer() override { return Lexer; }
getContext()2237330f729Sjoerg MCContext &getContext() override { return Ctx; }
getStreamer()2247330f729Sjoerg MCStreamer &getStreamer() override { return Out; }
2257330f729Sjoerg
getCVContext()2267330f729Sjoerg CodeViewContext &getCVContext() { return Ctx.getCVContext(); }
2277330f729Sjoerg
getAssemblerDialect()2287330f729Sjoerg unsigned getAssemblerDialect() override {
2297330f729Sjoerg if (AssemblerDialect == ~0U)
2307330f729Sjoerg return MAI.getAssemblerDialect();
2317330f729Sjoerg else
2327330f729Sjoerg return AssemblerDialect;
2337330f729Sjoerg }
setAssemblerDialect(unsigned i)2347330f729Sjoerg void setAssemblerDialect(unsigned i) override {
2357330f729Sjoerg AssemblerDialect = i;
2367330f729Sjoerg }
2377330f729Sjoerg
2387330f729Sjoerg void Note(SMLoc L, const Twine &Msg, SMRange Range = None) override;
2397330f729Sjoerg bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) override;
2407330f729Sjoerg bool printError(SMLoc L, const Twine &Msg, SMRange Range = None) override;
2417330f729Sjoerg
2427330f729Sjoerg const AsmToken &Lex() override;
2437330f729Sjoerg
setParsingMSInlineAsm(bool V)244*82d56013Sjoerg void setParsingMSInlineAsm(bool V) override {
245*82d56013Sjoerg ParsingMSInlineAsm = V;
2467330f729Sjoerg // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
2477330f729Sjoerg // hex integer literals.
2487330f729Sjoerg Lexer.setLexMasmIntegers(V);
2497330f729Sjoerg }
isParsingMSInlineAsm()250*82d56013Sjoerg bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
251*82d56013Sjoerg
discardLTOSymbol(StringRef Name) const252*82d56013Sjoerg bool discardLTOSymbol(StringRef Name) const override {
253*82d56013Sjoerg return LTODiscardSymbols.contains(Name);
254*82d56013Sjoerg }
2557330f729Sjoerg
2567330f729Sjoerg bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
2577330f729Sjoerg unsigned &NumOutputs, unsigned &NumInputs,
2587330f729Sjoerg SmallVectorImpl<std::pair<void *,bool>> &OpDecls,
2597330f729Sjoerg SmallVectorImpl<std::string> &Constraints,
2607330f729Sjoerg SmallVectorImpl<std::string> &Clobbers,
2617330f729Sjoerg const MCInstrInfo *MII, const MCInstPrinter *IP,
2627330f729Sjoerg MCAsmParserSemaCallback &SI) override;
2637330f729Sjoerg
2647330f729Sjoerg bool parseExpression(const MCExpr *&Res);
2657330f729Sjoerg bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
266*82d56013Sjoerg bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
267*82d56013Sjoerg AsmTypeInfo *TypeInfo) override;
2687330f729Sjoerg bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
2697330f729Sjoerg bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
2707330f729Sjoerg SMLoc &EndLoc) override;
2717330f729Sjoerg bool parseAbsoluteExpression(int64_t &Res) override;
2727330f729Sjoerg
2737330f729Sjoerg /// Parse a floating point expression using the float \p Semantics
2747330f729Sjoerg /// and set \p Res to the value.
2757330f729Sjoerg bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
2767330f729Sjoerg
2777330f729Sjoerg /// Parse an identifier or string (as a quoted identifier)
2787330f729Sjoerg /// and set \p Res to the identifier contents.
2797330f729Sjoerg bool parseIdentifier(StringRef &Res) override;
2807330f729Sjoerg void eatToEndOfStatement() override;
2817330f729Sjoerg
2827330f729Sjoerg bool checkForValidSection() override;
2837330f729Sjoerg
2847330f729Sjoerg /// }
2857330f729Sjoerg
2867330f729Sjoerg private:
2877330f729Sjoerg bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
288*82d56013Sjoerg bool parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo = true);
2897330f729Sjoerg
2907330f729Sjoerg void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
2917330f729Sjoerg ArrayRef<MCAsmMacroParameter> Parameters);
2927330f729Sjoerg bool expandMacro(raw_svector_ostream &OS, StringRef Body,
2937330f729Sjoerg ArrayRef<MCAsmMacroParameter> Parameters,
2947330f729Sjoerg ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable,
2957330f729Sjoerg SMLoc L);
2967330f729Sjoerg
2977330f729Sjoerg /// Are macros enabled in the parser?
areMacrosEnabled()2987330f729Sjoerg bool areMacrosEnabled() {return MacrosEnabledFlag;}
2997330f729Sjoerg
3007330f729Sjoerg /// Control a flag in the parser that enables or disables macros.
setMacrosEnabled(bool Flag)3017330f729Sjoerg void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
3027330f729Sjoerg
3037330f729Sjoerg /// Are we inside a macro instantiation?
isInsideMacroInstantiation()3047330f729Sjoerg bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
3057330f729Sjoerg
3067330f729Sjoerg /// Handle entry to macro instantiation.
3077330f729Sjoerg ///
3087330f729Sjoerg /// \param M The macro.
3097330f729Sjoerg /// \param NameLoc Instantiation location.
3107330f729Sjoerg bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
3117330f729Sjoerg
3127330f729Sjoerg /// Handle exit from macro instantiation.
3137330f729Sjoerg void handleMacroExit();
3147330f729Sjoerg
3157330f729Sjoerg /// Extract AsmTokens for a macro argument.
3167330f729Sjoerg bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
3177330f729Sjoerg
3187330f729Sjoerg /// Parse all macro arguments for a given macro.
3197330f729Sjoerg bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
3207330f729Sjoerg
3217330f729Sjoerg void printMacroInstantiations();
printMessage(SMLoc Loc,SourceMgr::DiagKind Kind,const Twine & Msg,SMRange Range=None) const3227330f729Sjoerg void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
3237330f729Sjoerg SMRange Range = None) const {
3247330f729Sjoerg ArrayRef<SMRange> Ranges(Range);
3257330f729Sjoerg SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
3267330f729Sjoerg }
3277330f729Sjoerg static void DiagHandler(const SMDiagnostic &Diag, void *Context);
3287330f729Sjoerg
3297330f729Sjoerg /// Should we emit DWARF describing this assembler source? (Returns false if
3307330f729Sjoerg /// the source has .file directives, which means we don't want to generate
3317330f729Sjoerg /// info describing the assembler source itself.)
3327330f729Sjoerg bool enabledGenDwarfForAssembly();
3337330f729Sjoerg
3347330f729Sjoerg /// Enter the specified file. This returns true on failure.
3357330f729Sjoerg bool enterIncludeFile(const std::string &Filename);
3367330f729Sjoerg
3377330f729Sjoerg /// Process the specified file for the .incbin directive.
3387330f729Sjoerg /// This returns true on failure.
3397330f729Sjoerg bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,
3407330f729Sjoerg const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());
3417330f729Sjoerg
3427330f729Sjoerg /// Reset the current lexer position to that given by \p Loc. The
3437330f729Sjoerg /// current token is not set; clients should ensure Lex() is called
3447330f729Sjoerg /// subsequently.
3457330f729Sjoerg ///
3467330f729Sjoerg /// \param InBuffer If not 0, should be the known buffer id that contains the
3477330f729Sjoerg /// location.
3487330f729Sjoerg void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);
3497330f729Sjoerg
3507330f729Sjoerg /// Parse up to the end of statement and a return the contents from the
3517330f729Sjoerg /// current token until the end of the statement; the current token on exit
3527330f729Sjoerg /// will be either the EndOfStatement or EOF.
3537330f729Sjoerg StringRef parseStringToEndOfStatement() override;
3547330f729Sjoerg
3557330f729Sjoerg /// Parse until the end of a statement or a comma is encountered,
3567330f729Sjoerg /// return the contents from the current token up to the end or comma.
3577330f729Sjoerg StringRef parseStringToComma();
3587330f729Sjoerg
3597330f729Sjoerg bool parseAssignment(StringRef Name, bool allow_redef,
3607330f729Sjoerg bool NoDeadStrip = false);
3617330f729Sjoerg
3627330f729Sjoerg unsigned getBinOpPrecedence(AsmToken::TokenKind K,
3637330f729Sjoerg MCBinaryExpr::Opcode &Kind);
3647330f729Sjoerg
3657330f729Sjoerg bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
3667330f729Sjoerg bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
3677330f729Sjoerg bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
3687330f729Sjoerg
3697330f729Sjoerg bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
3707330f729Sjoerg
3717330f729Sjoerg bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);
3727330f729Sjoerg bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);
3737330f729Sjoerg
3747330f729Sjoerg // Generic (target and platform independent) directive parsing.
3757330f729Sjoerg enum DirectiveKind {
3767330f729Sjoerg DK_NO_DIRECTIVE, // Placeholder
3777330f729Sjoerg DK_SET,
3787330f729Sjoerg DK_EQU,
3797330f729Sjoerg DK_EQUIV,
3807330f729Sjoerg DK_ASCII,
3817330f729Sjoerg DK_ASCIZ,
3827330f729Sjoerg DK_STRING,
3837330f729Sjoerg DK_BYTE,
3847330f729Sjoerg DK_SHORT,
3857330f729Sjoerg DK_RELOC,
3867330f729Sjoerg DK_VALUE,
3877330f729Sjoerg DK_2BYTE,
3887330f729Sjoerg DK_LONG,
3897330f729Sjoerg DK_INT,
3907330f729Sjoerg DK_4BYTE,
3917330f729Sjoerg DK_QUAD,
3927330f729Sjoerg DK_8BYTE,
3937330f729Sjoerg DK_OCTA,
3947330f729Sjoerg DK_DC,
3957330f729Sjoerg DK_DC_A,
3967330f729Sjoerg DK_DC_B,
3977330f729Sjoerg DK_DC_D,
3987330f729Sjoerg DK_DC_L,
3997330f729Sjoerg DK_DC_S,
4007330f729Sjoerg DK_DC_W,
4017330f729Sjoerg DK_DC_X,
4027330f729Sjoerg DK_DCB,
4037330f729Sjoerg DK_DCB_B,
4047330f729Sjoerg DK_DCB_D,
4057330f729Sjoerg DK_DCB_L,
4067330f729Sjoerg DK_DCB_S,
4077330f729Sjoerg DK_DCB_W,
4087330f729Sjoerg DK_DCB_X,
4097330f729Sjoerg DK_DS,
4107330f729Sjoerg DK_DS_B,
4117330f729Sjoerg DK_DS_D,
4127330f729Sjoerg DK_DS_L,
4137330f729Sjoerg DK_DS_P,
4147330f729Sjoerg DK_DS_S,
4157330f729Sjoerg DK_DS_W,
4167330f729Sjoerg DK_DS_X,
4177330f729Sjoerg DK_SINGLE,
4187330f729Sjoerg DK_FLOAT,
4197330f729Sjoerg DK_DOUBLE,
4207330f729Sjoerg DK_ALIGN,
4217330f729Sjoerg DK_ALIGN32,
4227330f729Sjoerg DK_BALIGN,
4237330f729Sjoerg DK_BALIGNW,
4247330f729Sjoerg DK_BALIGNL,
4257330f729Sjoerg DK_P2ALIGN,
4267330f729Sjoerg DK_P2ALIGNW,
4277330f729Sjoerg DK_P2ALIGNL,
4287330f729Sjoerg DK_ORG,
4297330f729Sjoerg DK_FILL,
4307330f729Sjoerg DK_ENDR,
4317330f729Sjoerg DK_BUNDLE_ALIGN_MODE,
4327330f729Sjoerg DK_BUNDLE_LOCK,
4337330f729Sjoerg DK_BUNDLE_UNLOCK,
4347330f729Sjoerg DK_ZERO,
4357330f729Sjoerg DK_EXTERN,
4367330f729Sjoerg DK_GLOBL,
4377330f729Sjoerg DK_GLOBAL,
4387330f729Sjoerg DK_LAZY_REFERENCE,
4397330f729Sjoerg DK_NO_DEAD_STRIP,
4407330f729Sjoerg DK_SYMBOL_RESOLVER,
4417330f729Sjoerg DK_PRIVATE_EXTERN,
4427330f729Sjoerg DK_REFERENCE,
4437330f729Sjoerg DK_WEAK_DEFINITION,
4447330f729Sjoerg DK_WEAK_REFERENCE,
4457330f729Sjoerg DK_WEAK_DEF_CAN_BE_HIDDEN,
4467330f729Sjoerg DK_COLD,
4477330f729Sjoerg DK_COMM,
4487330f729Sjoerg DK_COMMON,
4497330f729Sjoerg DK_LCOMM,
4507330f729Sjoerg DK_ABORT,
4517330f729Sjoerg DK_INCLUDE,
4527330f729Sjoerg DK_INCBIN,
4537330f729Sjoerg DK_CODE16,
4547330f729Sjoerg DK_CODE16GCC,
4557330f729Sjoerg DK_REPT,
4567330f729Sjoerg DK_IRP,
4577330f729Sjoerg DK_IRPC,
4587330f729Sjoerg DK_IF,
4597330f729Sjoerg DK_IFEQ,
4607330f729Sjoerg DK_IFGE,
4617330f729Sjoerg DK_IFGT,
4627330f729Sjoerg DK_IFLE,
4637330f729Sjoerg DK_IFLT,
4647330f729Sjoerg DK_IFNE,
4657330f729Sjoerg DK_IFB,
4667330f729Sjoerg DK_IFNB,
4677330f729Sjoerg DK_IFC,
4687330f729Sjoerg DK_IFEQS,
4697330f729Sjoerg DK_IFNC,
4707330f729Sjoerg DK_IFNES,
4717330f729Sjoerg DK_IFDEF,
4727330f729Sjoerg DK_IFNDEF,
4737330f729Sjoerg DK_IFNOTDEF,
4747330f729Sjoerg DK_ELSEIF,
4757330f729Sjoerg DK_ELSE,
4767330f729Sjoerg DK_ENDIF,
4777330f729Sjoerg DK_SPACE,
4787330f729Sjoerg DK_SKIP,
4797330f729Sjoerg DK_FILE,
4807330f729Sjoerg DK_LINE,
4817330f729Sjoerg DK_LOC,
4827330f729Sjoerg DK_STABS,
4837330f729Sjoerg DK_CV_FILE,
4847330f729Sjoerg DK_CV_FUNC_ID,
4857330f729Sjoerg DK_CV_INLINE_SITE_ID,
4867330f729Sjoerg DK_CV_LOC,
4877330f729Sjoerg DK_CV_LINETABLE,
4887330f729Sjoerg DK_CV_INLINE_LINETABLE,
4897330f729Sjoerg DK_CV_DEF_RANGE,
4907330f729Sjoerg DK_CV_STRINGTABLE,
4917330f729Sjoerg DK_CV_STRING,
4927330f729Sjoerg DK_CV_FILECHECKSUMS,
4937330f729Sjoerg DK_CV_FILECHECKSUM_OFFSET,
4947330f729Sjoerg DK_CV_FPO_DATA,
4957330f729Sjoerg DK_CFI_SECTIONS,
4967330f729Sjoerg DK_CFI_STARTPROC,
4977330f729Sjoerg DK_CFI_ENDPROC,
4987330f729Sjoerg DK_CFI_DEF_CFA,
4997330f729Sjoerg DK_CFI_DEF_CFA_OFFSET,
5007330f729Sjoerg DK_CFI_ADJUST_CFA_OFFSET,
5017330f729Sjoerg DK_CFI_DEF_CFA_REGISTER,
5027330f729Sjoerg DK_CFI_OFFSET,
5037330f729Sjoerg DK_CFI_REL_OFFSET,
5047330f729Sjoerg DK_CFI_PERSONALITY,
5057330f729Sjoerg DK_CFI_LSDA,
5067330f729Sjoerg DK_CFI_REMEMBER_STATE,
5077330f729Sjoerg DK_CFI_RESTORE_STATE,
5087330f729Sjoerg DK_CFI_SAME_VALUE,
5097330f729Sjoerg DK_CFI_RESTORE,
5107330f729Sjoerg DK_CFI_ESCAPE,
5117330f729Sjoerg DK_CFI_RETURN_COLUMN,
5127330f729Sjoerg DK_CFI_SIGNAL_FRAME,
5137330f729Sjoerg DK_CFI_UNDEFINED,
5147330f729Sjoerg DK_CFI_REGISTER,
5157330f729Sjoerg DK_CFI_WINDOW_SAVE,
5167330f729Sjoerg DK_CFI_B_KEY_FRAME,
5177330f729Sjoerg DK_MACROS_ON,
5187330f729Sjoerg DK_MACROS_OFF,
5197330f729Sjoerg DK_ALTMACRO,
5207330f729Sjoerg DK_NOALTMACRO,
5217330f729Sjoerg DK_MACRO,
5227330f729Sjoerg DK_EXITM,
5237330f729Sjoerg DK_ENDM,
5247330f729Sjoerg DK_ENDMACRO,
5257330f729Sjoerg DK_PURGEM,
5267330f729Sjoerg DK_SLEB128,
5277330f729Sjoerg DK_ULEB128,
5287330f729Sjoerg DK_ERR,
5297330f729Sjoerg DK_ERROR,
5307330f729Sjoerg DK_WARNING,
5317330f729Sjoerg DK_PRINT,
5327330f729Sjoerg DK_ADDRSIG,
5337330f729Sjoerg DK_ADDRSIG_SYM,
534*82d56013Sjoerg DK_PSEUDO_PROBE,
535*82d56013Sjoerg DK_LTO_DISCARD,
5367330f729Sjoerg DK_END
5377330f729Sjoerg };
5387330f729Sjoerg
5397330f729Sjoerg /// Maps directive name --> DirectiveKind enum, for
5407330f729Sjoerg /// directives parsed by this class.
5417330f729Sjoerg StringMap<DirectiveKind> DirectiveKindMap;
5427330f729Sjoerg
5437330f729Sjoerg // Codeview def_range type parsing.
5447330f729Sjoerg enum CVDefRangeType {
5457330f729Sjoerg CVDR_DEFRANGE = 0, // Placeholder
5467330f729Sjoerg CVDR_DEFRANGE_REGISTER,
5477330f729Sjoerg CVDR_DEFRANGE_FRAMEPOINTER_REL,
5487330f729Sjoerg CVDR_DEFRANGE_SUBFIELD_REGISTER,
5497330f729Sjoerg CVDR_DEFRANGE_REGISTER_REL
5507330f729Sjoerg };
5517330f729Sjoerg
5527330f729Sjoerg /// Maps Codeview def_range types --> CVDefRangeType enum, for
5537330f729Sjoerg /// Codeview def_range types parsed by this class.
5547330f729Sjoerg StringMap<CVDefRangeType> CVDefRangeTypeMap;
5557330f729Sjoerg
5567330f729Sjoerg // ".ascii", ".asciz", ".string"
5577330f729Sjoerg bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
5587330f729Sjoerg bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
5597330f729Sjoerg bool parseDirectiveValue(StringRef IDVal,
5607330f729Sjoerg unsigned Size); // ".byte", ".long", ...
5617330f729Sjoerg bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ...
5627330f729Sjoerg bool parseDirectiveRealValue(StringRef IDVal,
5637330f729Sjoerg const fltSemantics &); // ".single", ...
5647330f729Sjoerg bool parseDirectiveFill(); // ".fill"
5657330f729Sjoerg bool parseDirectiveZero(); // ".zero"
5667330f729Sjoerg // ".set", ".equ", ".equiv"
5677330f729Sjoerg bool parseDirectiveSet(StringRef IDVal, bool allow_redef);
5687330f729Sjoerg bool parseDirectiveOrg(); // ".org"
5697330f729Sjoerg // ".align{,32}", ".p2align{,w,l}"
5707330f729Sjoerg bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);
5717330f729Sjoerg
5727330f729Sjoerg // ".file", ".line", ".loc", ".stabs"
5737330f729Sjoerg bool parseDirectiveFile(SMLoc DirectiveLoc);
5747330f729Sjoerg bool parseDirectiveLine();
5757330f729Sjoerg bool parseDirectiveLoc();
5767330f729Sjoerg bool parseDirectiveStabs();
5777330f729Sjoerg
5787330f729Sjoerg // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
5797330f729Sjoerg // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
5807330f729Sjoerg bool parseDirectiveCVFile();
5817330f729Sjoerg bool parseDirectiveCVFuncId();
5827330f729Sjoerg bool parseDirectiveCVInlineSiteId();
5837330f729Sjoerg bool parseDirectiveCVLoc();
5847330f729Sjoerg bool parseDirectiveCVLinetable();
5857330f729Sjoerg bool parseDirectiveCVInlineLinetable();
5867330f729Sjoerg bool parseDirectiveCVDefRange();
5877330f729Sjoerg bool parseDirectiveCVString();
5887330f729Sjoerg bool parseDirectiveCVStringTable();
5897330f729Sjoerg bool parseDirectiveCVFileChecksums();
5907330f729Sjoerg bool parseDirectiveCVFileChecksumOffset();
5917330f729Sjoerg bool parseDirectiveCVFPOData();
5927330f729Sjoerg
5937330f729Sjoerg // .cfi directives
5947330f729Sjoerg bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
5957330f729Sjoerg bool parseDirectiveCFIWindowSave();
5967330f729Sjoerg bool parseDirectiveCFISections();
5977330f729Sjoerg bool parseDirectiveCFIStartProc();
5987330f729Sjoerg bool parseDirectiveCFIEndProc();
5997330f729Sjoerg bool parseDirectiveCFIDefCfaOffset();
6007330f729Sjoerg bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
6017330f729Sjoerg bool parseDirectiveCFIAdjustCfaOffset();
6027330f729Sjoerg bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
6037330f729Sjoerg bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
6047330f729Sjoerg bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
6057330f729Sjoerg bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
6067330f729Sjoerg bool parseDirectiveCFIRememberState();
6077330f729Sjoerg bool parseDirectiveCFIRestoreState();
6087330f729Sjoerg bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
6097330f729Sjoerg bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
6107330f729Sjoerg bool parseDirectiveCFIEscape();
6117330f729Sjoerg bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
6127330f729Sjoerg bool parseDirectiveCFISignalFrame();
6137330f729Sjoerg bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
6147330f729Sjoerg
6157330f729Sjoerg // macro directives
6167330f729Sjoerg bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
6177330f729Sjoerg bool parseDirectiveExitMacro(StringRef Directive);
6187330f729Sjoerg bool parseDirectiveEndMacro(StringRef Directive);
6197330f729Sjoerg bool parseDirectiveMacro(SMLoc DirectiveLoc);
6207330f729Sjoerg bool parseDirectiveMacrosOnOff(StringRef Directive);
6217330f729Sjoerg // alternate macro mode directives
6227330f729Sjoerg bool parseDirectiveAltmacro(StringRef Directive);
6237330f729Sjoerg // ".bundle_align_mode"
6247330f729Sjoerg bool parseDirectiveBundleAlignMode();
6257330f729Sjoerg // ".bundle_lock"
6267330f729Sjoerg bool parseDirectiveBundleLock();
6277330f729Sjoerg // ".bundle_unlock"
6287330f729Sjoerg bool parseDirectiveBundleUnlock();
6297330f729Sjoerg
6307330f729Sjoerg // ".space", ".skip"
6317330f729Sjoerg bool parseDirectiveSpace(StringRef IDVal);
6327330f729Sjoerg
6337330f729Sjoerg // ".dcb"
6347330f729Sjoerg bool parseDirectiveDCB(StringRef IDVal, unsigned Size);
6357330f729Sjoerg bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &);
6367330f729Sjoerg // ".ds"
6377330f729Sjoerg bool parseDirectiveDS(StringRef IDVal, unsigned Size);
6387330f729Sjoerg
6397330f729Sjoerg // .sleb128 (Signed=true) and .uleb128 (Signed=false)
6407330f729Sjoerg bool parseDirectiveLEB128(bool Signed);
6417330f729Sjoerg
6427330f729Sjoerg /// Parse a directive like ".globl" which
6437330f729Sjoerg /// accepts a single symbol (which should be a label or an external).
6447330f729Sjoerg bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
6457330f729Sjoerg
6467330f729Sjoerg bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
6477330f729Sjoerg
6487330f729Sjoerg bool parseDirectiveAbort(); // ".abort"
6497330f729Sjoerg bool parseDirectiveInclude(); // ".include"
6507330f729Sjoerg bool parseDirectiveIncbin(); // ".incbin"
6517330f729Sjoerg
6527330f729Sjoerg // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"
6537330f729Sjoerg bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
6547330f729Sjoerg // ".ifb" or ".ifnb", depending on ExpectBlank.
6557330f729Sjoerg bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
6567330f729Sjoerg // ".ifc" or ".ifnc", depending on ExpectEqual.
6577330f729Sjoerg bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
6587330f729Sjoerg // ".ifeqs" or ".ifnes", depending on ExpectEqual.
6597330f729Sjoerg bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);
6607330f729Sjoerg // ".ifdef" or ".ifndef", depending on expect_defined
6617330f729Sjoerg bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
6627330f729Sjoerg bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
6637330f729Sjoerg bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
6647330f729Sjoerg bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
6657330f729Sjoerg bool parseEscapedString(std::string &Data) override;
666*82d56013Sjoerg bool parseAngleBracketString(std::string &Data) override;
6677330f729Sjoerg
6687330f729Sjoerg const MCExpr *applyModifierToExpr(const MCExpr *E,
6697330f729Sjoerg MCSymbolRefExpr::VariantKind Variant);
6707330f729Sjoerg
6717330f729Sjoerg // Macro-like directives
6727330f729Sjoerg MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
6737330f729Sjoerg void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
6747330f729Sjoerg raw_svector_ostream &OS);
6757330f729Sjoerg bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);
6767330f729Sjoerg bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
6777330f729Sjoerg bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
6787330f729Sjoerg bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
6797330f729Sjoerg
6807330f729Sjoerg // "_emit" or "__emit"
6817330f729Sjoerg bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
6827330f729Sjoerg size_t Len);
6837330f729Sjoerg
6847330f729Sjoerg // "align"
6857330f729Sjoerg bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
6867330f729Sjoerg
6877330f729Sjoerg // "end"
6887330f729Sjoerg bool parseDirectiveEnd(SMLoc DirectiveLoc);
6897330f729Sjoerg
6907330f729Sjoerg // ".err" or ".error"
6917330f729Sjoerg bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
6927330f729Sjoerg
6937330f729Sjoerg // ".warning"
6947330f729Sjoerg bool parseDirectiveWarning(SMLoc DirectiveLoc);
6957330f729Sjoerg
6967330f729Sjoerg // .print <double-quotes-string>
6977330f729Sjoerg bool parseDirectivePrint(SMLoc DirectiveLoc);
6987330f729Sjoerg
699*82d56013Sjoerg // .pseudoprobe
700*82d56013Sjoerg bool parseDirectivePseudoProbe();
701*82d56013Sjoerg
702*82d56013Sjoerg // ".lto_discard"
703*82d56013Sjoerg bool parseDirectiveLTODiscard();
704*82d56013Sjoerg
7057330f729Sjoerg // Directives to support address-significance tables.
7067330f729Sjoerg bool parseDirectiveAddrsig();
7077330f729Sjoerg bool parseDirectiveAddrsigSym();
7087330f729Sjoerg
7097330f729Sjoerg void initializeDirectiveKindMap();
7107330f729Sjoerg void initializeCVDefRangeTypeMap();
7117330f729Sjoerg };
7127330f729Sjoerg
713*82d56013Sjoerg class HLASMAsmParser final : public AsmParser {
714*82d56013Sjoerg private:
715*82d56013Sjoerg MCAsmLexer &Lexer;
716*82d56013Sjoerg MCStreamer &Out;
717*82d56013Sjoerg
lexLeadingSpaces()718*82d56013Sjoerg void lexLeadingSpaces() {
719*82d56013Sjoerg while (Lexer.is(AsmToken::Space))
720*82d56013Sjoerg Lexer.Lex();
721*82d56013Sjoerg }
722*82d56013Sjoerg
723*82d56013Sjoerg bool parseAsHLASMLabel(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI);
724*82d56013Sjoerg bool parseAsMachineInstruction(ParseStatementInfo &Info,
725*82d56013Sjoerg MCAsmParserSemaCallback *SI);
726*82d56013Sjoerg
727*82d56013Sjoerg public:
HLASMAsmParser(SourceMgr & SM,MCContext & Ctx,MCStreamer & Out,const MCAsmInfo & MAI,unsigned CB=0)728*82d56013Sjoerg HLASMAsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
729*82d56013Sjoerg const MCAsmInfo &MAI, unsigned CB = 0)
730*82d56013Sjoerg : AsmParser(SM, Ctx, Out, MAI, CB), Lexer(getLexer()), Out(Out) {
731*82d56013Sjoerg Lexer.setSkipSpace(false);
732*82d56013Sjoerg Lexer.setAllowHashInIdentifier(true);
733*82d56013Sjoerg Lexer.setLexHLASMIntegers(true);
734*82d56013Sjoerg Lexer.setLexHLASMStrings(true);
735*82d56013Sjoerg }
736*82d56013Sjoerg
~HLASMAsmParser()737*82d56013Sjoerg ~HLASMAsmParser() { Lexer.setSkipSpace(true); }
738*82d56013Sjoerg
739*82d56013Sjoerg bool parseStatement(ParseStatementInfo &Info,
740*82d56013Sjoerg MCAsmParserSemaCallback *SI) override;
741*82d56013Sjoerg };
742*82d56013Sjoerg
7437330f729Sjoerg } // end anonymous namespace
7447330f729Sjoerg
7457330f729Sjoerg namespace llvm {
7467330f729Sjoerg
7477330f729Sjoerg extern MCAsmParserExtension *createDarwinAsmParser();
7487330f729Sjoerg extern MCAsmParserExtension *createELFAsmParser();
7497330f729Sjoerg extern MCAsmParserExtension *createCOFFAsmParser();
7507330f729Sjoerg extern MCAsmParserExtension *createWasmAsmParser();
7517330f729Sjoerg
7527330f729Sjoerg } // end namespace llvm
7537330f729Sjoerg
7547330f729Sjoerg enum { DEFAULT_ADDRSPACE = 0 };
7557330f729Sjoerg
AsmParser(SourceMgr & SM,MCContext & Ctx,MCStreamer & Out,const MCAsmInfo & MAI,unsigned CB=0)7567330f729Sjoerg AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
7577330f729Sjoerg const MCAsmInfo &MAI, unsigned CB = 0)
7587330f729Sjoerg : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
7597330f729Sjoerg CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {
7607330f729Sjoerg HadError = false;
7617330f729Sjoerg // Save the old handler.
7627330f729Sjoerg SavedDiagHandler = SrcMgr.getDiagHandler();
7637330f729Sjoerg SavedDiagContext = SrcMgr.getDiagContext();
7647330f729Sjoerg // Set our own handler which calls the saved handler.
7657330f729Sjoerg SrcMgr.setDiagHandler(DiagHandler, this);
7667330f729Sjoerg Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
767*82d56013Sjoerg // Make MCStreamer aware of the StartTokLoc for locations in diagnostics.
768*82d56013Sjoerg Out.setStartTokLocPtr(&StartTokLoc);
7697330f729Sjoerg
7707330f729Sjoerg // Initialize the platform / file format parser.
771*82d56013Sjoerg switch (Ctx.getObjectFileType()) {
772*82d56013Sjoerg case MCContext::IsCOFF:
7737330f729Sjoerg PlatformParser.reset(createCOFFAsmParser());
7747330f729Sjoerg break;
775*82d56013Sjoerg case MCContext::IsMachO:
7767330f729Sjoerg PlatformParser.reset(createDarwinAsmParser());
7777330f729Sjoerg IsDarwin = true;
7787330f729Sjoerg break;
779*82d56013Sjoerg case MCContext::IsELF:
7807330f729Sjoerg PlatformParser.reset(createELFAsmParser());
7817330f729Sjoerg break;
782*82d56013Sjoerg case MCContext::IsWasm:
7837330f729Sjoerg PlatformParser.reset(createWasmAsmParser());
7847330f729Sjoerg break;
785*82d56013Sjoerg case MCContext::IsXCOFF:
7867330f729Sjoerg report_fatal_error(
7877330f729Sjoerg "Need to implement createXCOFFAsmParser for XCOFF format.");
7887330f729Sjoerg break;
7897330f729Sjoerg }
7907330f729Sjoerg
7917330f729Sjoerg PlatformParser->Initialize(*this);
7927330f729Sjoerg initializeDirectiveKindMap();
7937330f729Sjoerg initializeCVDefRangeTypeMap();
7947330f729Sjoerg
7957330f729Sjoerg NumOfMacroInstantiations = 0;
7967330f729Sjoerg }
7977330f729Sjoerg
~AsmParser()7987330f729Sjoerg AsmParser::~AsmParser() {
7997330f729Sjoerg assert((HadError || ActiveMacros.empty()) &&
8007330f729Sjoerg "Unexpected active macro instantiation!");
8017330f729Sjoerg
802*82d56013Sjoerg // Remove MCStreamer's reference to the parser SMLoc.
803*82d56013Sjoerg Out.setStartTokLocPtr(nullptr);
8047330f729Sjoerg // Restore the saved diagnostics handler and context for use during
8057330f729Sjoerg // finalization.
8067330f729Sjoerg SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
8077330f729Sjoerg }
8087330f729Sjoerg
printMacroInstantiations()8097330f729Sjoerg void AsmParser::printMacroInstantiations() {
8107330f729Sjoerg // Print the active macro instantiation stack.
8117330f729Sjoerg for (std::vector<MacroInstantiation *>::const_reverse_iterator
8127330f729Sjoerg it = ActiveMacros.rbegin(),
8137330f729Sjoerg ie = ActiveMacros.rend();
8147330f729Sjoerg it != ie; ++it)
8157330f729Sjoerg printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
8167330f729Sjoerg "while in macro instantiation");
8177330f729Sjoerg }
8187330f729Sjoerg
Note(SMLoc L,const Twine & Msg,SMRange Range)8197330f729Sjoerg void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
8207330f729Sjoerg printPendingErrors();
8217330f729Sjoerg printMessage(L, SourceMgr::DK_Note, Msg, Range);
8227330f729Sjoerg printMacroInstantiations();
8237330f729Sjoerg }
8247330f729Sjoerg
Warning(SMLoc L,const Twine & Msg,SMRange Range)8257330f729Sjoerg bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
8267330f729Sjoerg if(getTargetParser().getTargetOptions().MCNoWarn)
8277330f729Sjoerg return false;
8287330f729Sjoerg if (getTargetParser().getTargetOptions().MCFatalWarnings)
8297330f729Sjoerg return Error(L, Msg, Range);
8307330f729Sjoerg printMessage(L, SourceMgr::DK_Warning, Msg, Range);
8317330f729Sjoerg printMacroInstantiations();
8327330f729Sjoerg return false;
8337330f729Sjoerg }
8347330f729Sjoerg
printError(SMLoc L,const Twine & Msg,SMRange Range)8357330f729Sjoerg bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
8367330f729Sjoerg HadError = true;
8377330f729Sjoerg printMessage(L, SourceMgr::DK_Error, Msg, Range);
8387330f729Sjoerg printMacroInstantiations();
8397330f729Sjoerg return true;
8407330f729Sjoerg }
8417330f729Sjoerg
enterIncludeFile(const std::string & Filename)8427330f729Sjoerg bool AsmParser::enterIncludeFile(const std::string &Filename) {
8437330f729Sjoerg std::string IncludedFile;
8447330f729Sjoerg unsigned NewBuf =
8457330f729Sjoerg SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
8467330f729Sjoerg if (!NewBuf)
8477330f729Sjoerg return true;
8487330f729Sjoerg
8497330f729Sjoerg CurBuffer = NewBuf;
8507330f729Sjoerg Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
8517330f729Sjoerg return false;
8527330f729Sjoerg }
8537330f729Sjoerg
8547330f729Sjoerg /// Process the specified .incbin file by searching for it in the include paths
8557330f729Sjoerg /// then just emitting the byte contents of the file to the streamer. This
8567330f729Sjoerg /// returns true on failure.
processIncbinFile(const std::string & Filename,int64_t Skip,const MCExpr * Count,SMLoc Loc)8577330f729Sjoerg bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
8587330f729Sjoerg const MCExpr *Count, SMLoc Loc) {
8597330f729Sjoerg std::string IncludedFile;
8607330f729Sjoerg unsigned NewBuf =
8617330f729Sjoerg SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
8627330f729Sjoerg if (!NewBuf)
8637330f729Sjoerg return true;
8647330f729Sjoerg
8657330f729Sjoerg // Pick up the bytes from the file and emit them.
8667330f729Sjoerg StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();
8677330f729Sjoerg Bytes = Bytes.drop_front(Skip);
8687330f729Sjoerg if (Count) {
8697330f729Sjoerg int64_t Res;
8707330f729Sjoerg if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
8717330f729Sjoerg return Error(Loc, "expected absolute expression");
8727330f729Sjoerg if (Res < 0)
8737330f729Sjoerg return Warning(Loc, "negative count has no effect");
8747330f729Sjoerg Bytes = Bytes.take_front(Res);
8757330f729Sjoerg }
876*82d56013Sjoerg getStreamer().emitBytes(Bytes);
8777330f729Sjoerg return false;
8787330f729Sjoerg }
8797330f729Sjoerg
jumpToLoc(SMLoc Loc,unsigned InBuffer)8807330f729Sjoerg void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
8817330f729Sjoerg CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
8827330f729Sjoerg Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
8837330f729Sjoerg Loc.getPointer());
8847330f729Sjoerg }
8857330f729Sjoerg
Lex()8867330f729Sjoerg const AsmToken &AsmParser::Lex() {
8877330f729Sjoerg if (Lexer.getTok().is(AsmToken::Error))
8887330f729Sjoerg Error(Lexer.getErrLoc(), Lexer.getErr());
8897330f729Sjoerg
8907330f729Sjoerg // if it's a end of statement with a comment in it
8917330f729Sjoerg if (getTok().is(AsmToken::EndOfStatement)) {
8927330f729Sjoerg // if this is a line comment output it.
8937330f729Sjoerg if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
8947330f729Sjoerg getTok().getString().front() != '\r' && MAI.preserveAsmComments())
8957330f729Sjoerg Out.addExplicitComment(Twine(getTok().getString()));
8967330f729Sjoerg }
8977330f729Sjoerg
8987330f729Sjoerg const AsmToken *tok = &Lexer.Lex();
8997330f729Sjoerg
9007330f729Sjoerg // Parse comments here to be deferred until end of next statement.
9017330f729Sjoerg while (tok->is(AsmToken::Comment)) {
9027330f729Sjoerg if (MAI.preserveAsmComments())
9037330f729Sjoerg Out.addExplicitComment(Twine(tok->getString()));
9047330f729Sjoerg tok = &Lexer.Lex();
9057330f729Sjoerg }
9067330f729Sjoerg
9077330f729Sjoerg if (tok->is(AsmToken::Eof)) {
9087330f729Sjoerg // If this is the end of an included file, pop the parent file off the
9097330f729Sjoerg // include stack.
9107330f729Sjoerg SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
9117330f729Sjoerg if (ParentIncludeLoc != SMLoc()) {
9127330f729Sjoerg jumpToLoc(ParentIncludeLoc);
9137330f729Sjoerg return Lex();
9147330f729Sjoerg }
9157330f729Sjoerg }
9167330f729Sjoerg
9177330f729Sjoerg return *tok;
9187330f729Sjoerg }
9197330f729Sjoerg
enabledGenDwarfForAssembly()9207330f729Sjoerg bool AsmParser::enabledGenDwarfForAssembly() {
9217330f729Sjoerg // Check whether the user specified -g.
9227330f729Sjoerg if (!getContext().getGenDwarfForAssembly())
9237330f729Sjoerg return false;
9247330f729Sjoerg // If we haven't encountered any .file directives (which would imply that
9257330f729Sjoerg // the assembler source was produced with debug info already) then emit one
9267330f729Sjoerg // describing the assembler source file itself.
9277330f729Sjoerg if (getContext().getGenDwarfFileNumber() == 0) {
9287330f729Sjoerg // Use the first #line directive for this, if any. It's preprocessed, so
9297330f729Sjoerg // there is no checksum, and of course no source directive.
9307330f729Sjoerg if (!FirstCppHashFilename.empty())
9317330f729Sjoerg getContext().setMCLineTableRootFile(/*CUID=*/0,
9327330f729Sjoerg getContext().getCompilationDir(),
9337330f729Sjoerg FirstCppHashFilename,
9347330f729Sjoerg /*Cksum=*/None, /*Source=*/None);
9357330f729Sjoerg const MCDwarfFile &RootFile =
9367330f729Sjoerg getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
937*82d56013Sjoerg getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
9387330f729Sjoerg /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
9397330f729Sjoerg RootFile.Checksum, RootFile.Source));
9407330f729Sjoerg }
9417330f729Sjoerg return true;
9427330f729Sjoerg }
9437330f729Sjoerg
Run(bool NoInitialTextSection,bool NoFinalize)9447330f729Sjoerg bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
945*82d56013Sjoerg LTODiscardSymbols.clear();
946*82d56013Sjoerg
9477330f729Sjoerg // Create the initial section, if requested.
9487330f729Sjoerg if (!NoInitialTextSection)
9497330f729Sjoerg Out.InitSections(false);
9507330f729Sjoerg
9517330f729Sjoerg // Prime the lexer.
9527330f729Sjoerg Lex();
9537330f729Sjoerg
9547330f729Sjoerg HadError = false;
9557330f729Sjoerg AsmCond StartingCondState = TheCondState;
9567330f729Sjoerg SmallVector<AsmRewrite, 4> AsmStrRewrites;
9577330f729Sjoerg
9587330f729Sjoerg // If we are generating dwarf for assembly source files save the initial text
9597330f729Sjoerg // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't
9607330f729Sjoerg // emitting any actual debug info yet and haven't had a chance to parse any
9617330f729Sjoerg // embedded .file directives.)
9627330f729Sjoerg if (getContext().getGenDwarfForAssembly()) {
9637330f729Sjoerg MCSection *Sec = getStreamer().getCurrentSectionOnly();
9647330f729Sjoerg if (!Sec->getBeginSymbol()) {
9657330f729Sjoerg MCSymbol *SectionStartSym = getContext().createTempSymbol();
966*82d56013Sjoerg getStreamer().emitLabel(SectionStartSym);
9677330f729Sjoerg Sec->setBeginSymbol(SectionStartSym);
9687330f729Sjoerg }
9697330f729Sjoerg bool InsertResult = getContext().addGenDwarfSection(Sec);
9707330f729Sjoerg assert(InsertResult && ".text section should not have debug info yet");
9717330f729Sjoerg (void)InsertResult;
9727330f729Sjoerg }
9737330f729Sjoerg
974*82d56013Sjoerg getTargetParser().onBeginOfFile();
975*82d56013Sjoerg
9767330f729Sjoerg // While we have input, parse each statement.
9777330f729Sjoerg while (Lexer.isNot(AsmToken::Eof)) {
9787330f729Sjoerg ParseStatementInfo Info(&AsmStrRewrites);
9797330f729Sjoerg bool Parsed = parseStatement(Info, nullptr);
9807330f729Sjoerg
9817330f729Sjoerg // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
9827330f729Sjoerg // for printing ErrMsg via Lex() only if no (presumably better) parser error
9837330f729Sjoerg // exists.
9847330f729Sjoerg if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
9857330f729Sjoerg Lex();
9867330f729Sjoerg }
9877330f729Sjoerg
9887330f729Sjoerg // parseStatement returned true so may need to emit an error.
9897330f729Sjoerg printPendingErrors();
9907330f729Sjoerg
9917330f729Sjoerg // Skipping to the next line if needed.
9927330f729Sjoerg if (Parsed && !getLexer().isAtStartOfStatement())
9937330f729Sjoerg eatToEndOfStatement();
9947330f729Sjoerg }
9957330f729Sjoerg
9967330f729Sjoerg getTargetParser().onEndOfFile();
9977330f729Sjoerg printPendingErrors();
9987330f729Sjoerg
9997330f729Sjoerg // All errors should have been emitted.
10007330f729Sjoerg assert(!hasPendingError() && "unexpected error from parseStatement");
10017330f729Sjoerg
10027330f729Sjoerg getTargetParser().flushPendingInstructions(getStreamer());
10037330f729Sjoerg
10047330f729Sjoerg if (TheCondState.TheCond != StartingCondState.TheCond ||
10057330f729Sjoerg TheCondState.Ignore != StartingCondState.Ignore)
10067330f729Sjoerg printError(getTok().getLoc(), "unmatched .ifs or .elses");
10077330f729Sjoerg // Check to see there are no empty DwarfFile slots.
10087330f729Sjoerg const auto &LineTables = getContext().getMCDwarfLineTables();
10097330f729Sjoerg if (!LineTables.empty()) {
10107330f729Sjoerg unsigned Index = 0;
10117330f729Sjoerg for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {
10127330f729Sjoerg if (File.Name.empty() && Index != 0)
10137330f729Sjoerg printError(getTok().getLoc(), "unassigned file number: " +
10147330f729Sjoerg Twine(Index) +
10157330f729Sjoerg " for .file directives");
10167330f729Sjoerg ++Index;
10177330f729Sjoerg }
10187330f729Sjoerg }
10197330f729Sjoerg
10207330f729Sjoerg // Check to see that all assembler local symbols were actually defined.
10217330f729Sjoerg // Targets that don't do subsections via symbols may not want this, though,
10227330f729Sjoerg // so conservatively exclude them. Only do this if we're finalizing, though,
10237330f729Sjoerg // as otherwise we won't necessarilly have seen everything yet.
10247330f729Sjoerg if (!NoFinalize) {
10257330f729Sjoerg if (MAI.hasSubsectionsViaSymbols()) {
10267330f729Sjoerg for (const auto &TableEntry : getContext().getSymbols()) {
10277330f729Sjoerg MCSymbol *Sym = TableEntry.getValue();
10287330f729Sjoerg // Variable symbols may not be marked as defined, so check those
10297330f729Sjoerg // explicitly. If we know it's a variable, we have a definition for
10307330f729Sjoerg // the purposes of this check.
10317330f729Sjoerg if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
10327330f729Sjoerg // FIXME: We would really like to refer back to where the symbol was
10337330f729Sjoerg // first referenced for a source location. We need to add something
10347330f729Sjoerg // to track that. Currently, we just point to the end of the file.
10357330f729Sjoerg printError(getTok().getLoc(), "assembler local symbol '" +
10367330f729Sjoerg Sym->getName() + "' not defined");
10377330f729Sjoerg }
10387330f729Sjoerg }
10397330f729Sjoerg
10407330f729Sjoerg // Temporary symbols like the ones for directional jumps don't go in the
10417330f729Sjoerg // symbol table. They also need to be diagnosed in all (final) cases.
10427330f729Sjoerg for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
10437330f729Sjoerg if (std::get<2>(LocSym)->isUndefined()) {
10447330f729Sjoerg // Reset the state of any "# line file" directives we've seen to the
10457330f729Sjoerg // context as it was at the diagnostic site.
10467330f729Sjoerg CppHashInfo = std::get<1>(LocSym);
10477330f729Sjoerg printError(std::get<0>(LocSym), "directional label undefined");
10487330f729Sjoerg }
10497330f729Sjoerg }
10507330f729Sjoerg }
10517330f729Sjoerg
10527330f729Sjoerg // Finalize the output stream if there are no errors and if the client wants
10537330f729Sjoerg // us to.
10547330f729Sjoerg if (!HadError && !NoFinalize)
1055*82d56013Sjoerg Out.Finish(Lexer.getLoc());
10567330f729Sjoerg
10577330f729Sjoerg return HadError || getContext().hadError();
10587330f729Sjoerg }
10597330f729Sjoerg
checkForValidSection()10607330f729Sjoerg bool AsmParser::checkForValidSection() {
1061*82d56013Sjoerg if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
10627330f729Sjoerg Out.InitSections(false);
10637330f729Sjoerg return Error(getTok().getLoc(),
10647330f729Sjoerg "expected section directive before assembly directive");
10657330f729Sjoerg }
10667330f729Sjoerg return false;
10677330f729Sjoerg }
10687330f729Sjoerg
10697330f729Sjoerg /// Throw away the rest of the line for testing purposes.
eatToEndOfStatement()10707330f729Sjoerg void AsmParser::eatToEndOfStatement() {
10717330f729Sjoerg while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
10727330f729Sjoerg Lexer.Lex();
10737330f729Sjoerg
10747330f729Sjoerg // Eat EOL.
10757330f729Sjoerg if (Lexer.is(AsmToken::EndOfStatement))
10767330f729Sjoerg Lexer.Lex();
10777330f729Sjoerg }
10787330f729Sjoerg
parseStringToEndOfStatement()10797330f729Sjoerg StringRef AsmParser::parseStringToEndOfStatement() {
10807330f729Sjoerg const char *Start = getTok().getLoc().getPointer();
10817330f729Sjoerg
10827330f729Sjoerg while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
10837330f729Sjoerg Lexer.Lex();
10847330f729Sjoerg
10857330f729Sjoerg const char *End = getTok().getLoc().getPointer();
10867330f729Sjoerg return StringRef(Start, End - Start);
10877330f729Sjoerg }
10887330f729Sjoerg
parseStringToComma()10897330f729Sjoerg StringRef AsmParser::parseStringToComma() {
10907330f729Sjoerg const char *Start = getTok().getLoc().getPointer();
10917330f729Sjoerg
10927330f729Sjoerg while (Lexer.isNot(AsmToken::EndOfStatement) &&
10937330f729Sjoerg Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof))
10947330f729Sjoerg Lexer.Lex();
10957330f729Sjoerg
10967330f729Sjoerg const char *End = getTok().getLoc().getPointer();
10977330f729Sjoerg return StringRef(Start, End - Start);
10987330f729Sjoerg }
10997330f729Sjoerg
11007330f729Sjoerg /// Parse a paren expression and return it.
11017330f729Sjoerg /// NOTE: This assumes the leading '(' has already been consumed.
11027330f729Sjoerg ///
11037330f729Sjoerg /// parenexpr ::= expr)
11047330f729Sjoerg ///
parseParenExpr(const MCExpr * & Res,SMLoc & EndLoc)11057330f729Sjoerg bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
11067330f729Sjoerg if (parseExpression(Res))
11077330f729Sjoerg return true;
11087330f729Sjoerg if (Lexer.isNot(AsmToken::RParen))
11097330f729Sjoerg return TokError("expected ')' in parentheses expression");
11107330f729Sjoerg EndLoc = Lexer.getTok().getEndLoc();
11117330f729Sjoerg Lex();
11127330f729Sjoerg return false;
11137330f729Sjoerg }
11147330f729Sjoerg
11157330f729Sjoerg /// Parse a bracket expression and return it.
11167330f729Sjoerg /// NOTE: This assumes the leading '[' has already been consumed.
11177330f729Sjoerg ///
11187330f729Sjoerg /// bracketexpr ::= expr]
11197330f729Sjoerg ///
parseBracketExpr(const MCExpr * & Res,SMLoc & EndLoc)11207330f729Sjoerg bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
11217330f729Sjoerg if (parseExpression(Res))
11227330f729Sjoerg return true;
11237330f729Sjoerg EndLoc = getTok().getEndLoc();
11247330f729Sjoerg if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
11257330f729Sjoerg return true;
11267330f729Sjoerg return false;
11277330f729Sjoerg }
11287330f729Sjoerg
11297330f729Sjoerg /// Parse a primary expression and return it.
11307330f729Sjoerg /// primaryexpr ::= (parenexpr
11317330f729Sjoerg /// primaryexpr ::= symbol
11327330f729Sjoerg /// primaryexpr ::= number
11337330f729Sjoerg /// primaryexpr ::= '.'
11347330f729Sjoerg /// primaryexpr ::= ~,+,- primaryexpr
parsePrimaryExpr(const MCExpr * & Res,SMLoc & EndLoc,AsmTypeInfo * TypeInfo)1135*82d56013Sjoerg bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
1136*82d56013Sjoerg AsmTypeInfo *TypeInfo) {
11377330f729Sjoerg SMLoc FirstTokenLoc = getLexer().getLoc();
11387330f729Sjoerg AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
11397330f729Sjoerg switch (FirstTokenKind) {
11407330f729Sjoerg default:
11417330f729Sjoerg return TokError("unknown token in expression");
11427330f729Sjoerg // If we have an error assume that we've already handled it.
11437330f729Sjoerg case AsmToken::Error:
11447330f729Sjoerg return true;
11457330f729Sjoerg case AsmToken::Exclaim:
11467330f729Sjoerg Lex(); // Eat the operator.
1147*82d56013Sjoerg if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
11487330f729Sjoerg return true;
11497330f729Sjoerg Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
11507330f729Sjoerg return false;
11517330f729Sjoerg case AsmToken::Dollar:
1152*82d56013Sjoerg case AsmToken::Star:
11537330f729Sjoerg case AsmToken::At:
11547330f729Sjoerg case AsmToken::String:
11557330f729Sjoerg case AsmToken::Identifier: {
11567330f729Sjoerg StringRef Identifier;
11577330f729Sjoerg if (parseIdentifier(Identifier)) {
1158*82d56013Sjoerg // We may have failed but '$'|'*' may be a valid token in context of
1159*82d56013Sjoerg // the current PC.
1160*82d56013Sjoerg if (getTok().is(AsmToken::Dollar) || getTok().is(AsmToken::Star)) {
1161*82d56013Sjoerg bool ShouldGenerateTempSymbol = false;
1162*82d56013Sjoerg if ((getTok().is(AsmToken::Dollar) && MAI.getDollarIsPC()) ||
1163*82d56013Sjoerg (getTok().is(AsmToken::Star) && MAI.getStarIsPC()))
1164*82d56013Sjoerg ShouldGenerateTempSymbol = true;
1165*82d56013Sjoerg
1166*82d56013Sjoerg if (!ShouldGenerateTempSymbol)
1167*82d56013Sjoerg return Error(FirstTokenLoc, "invalid token in expression");
1168*82d56013Sjoerg
1169*82d56013Sjoerg // Eat the '$'|'*' token.
11707330f729Sjoerg Lex();
1171*82d56013Sjoerg // This is either a '$'|'*' reference, which references the current PC.
1172*82d56013Sjoerg // Emit a temporary label to the streamer and refer to it.
11737330f729Sjoerg MCSymbol *Sym = Ctx.createTempSymbol();
1174*82d56013Sjoerg Out.emitLabel(Sym);
11757330f729Sjoerg Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
11767330f729Sjoerg getContext());
11777330f729Sjoerg EndLoc = FirstTokenLoc;
11787330f729Sjoerg return false;
11797330f729Sjoerg }
11807330f729Sjoerg }
11817330f729Sjoerg // Parse symbol variant
11827330f729Sjoerg std::pair<StringRef, StringRef> Split;
11837330f729Sjoerg if (!MAI.useParensForSymbolVariant()) {
11847330f729Sjoerg if (FirstTokenKind == AsmToken::String) {
11857330f729Sjoerg if (Lexer.is(AsmToken::At)) {
11867330f729Sjoerg Lex(); // eat @
11877330f729Sjoerg SMLoc AtLoc = getLexer().getLoc();
11887330f729Sjoerg StringRef VName;
11897330f729Sjoerg if (parseIdentifier(VName))
11907330f729Sjoerg return Error(AtLoc, "expected symbol variant after '@'");
11917330f729Sjoerg
11927330f729Sjoerg Split = std::make_pair(Identifier, VName);
11937330f729Sjoerg }
11947330f729Sjoerg } else {
11957330f729Sjoerg Split = Identifier.split('@');
11967330f729Sjoerg }
11977330f729Sjoerg } else if (Lexer.is(AsmToken::LParen)) {
11987330f729Sjoerg Lex(); // eat '('.
11997330f729Sjoerg StringRef VName;
12007330f729Sjoerg parseIdentifier(VName);
12017330f729Sjoerg // eat ')'.
12027330f729Sjoerg if (parseToken(AsmToken::RParen,
12037330f729Sjoerg "unexpected token in variant, expected ')'"))
12047330f729Sjoerg return true;
12057330f729Sjoerg Split = std::make_pair(Identifier, VName);
12067330f729Sjoerg }
12077330f729Sjoerg
12087330f729Sjoerg EndLoc = SMLoc::getFromPointer(Identifier.end());
12097330f729Sjoerg
12107330f729Sjoerg // This is a symbol reference.
12117330f729Sjoerg StringRef SymbolName = Identifier;
12127330f729Sjoerg if (SymbolName.empty())
12137330f729Sjoerg return Error(getLexer().getLoc(), "expected a symbol reference");
12147330f729Sjoerg
12157330f729Sjoerg MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
12167330f729Sjoerg
12177330f729Sjoerg // Lookup the symbol variant if used.
12187330f729Sjoerg if (!Split.second.empty()) {
12197330f729Sjoerg Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
12207330f729Sjoerg if (Variant != MCSymbolRefExpr::VK_Invalid) {
12217330f729Sjoerg SymbolName = Split.first;
12227330f729Sjoerg } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
12237330f729Sjoerg Variant = MCSymbolRefExpr::VK_None;
12247330f729Sjoerg } else {
12257330f729Sjoerg return Error(SMLoc::getFromPointer(Split.second.begin()),
12267330f729Sjoerg "invalid variant '" + Split.second + "'");
12277330f729Sjoerg }
12287330f729Sjoerg }
12297330f729Sjoerg
12307330f729Sjoerg MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
12317330f729Sjoerg if (!Sym)
12327330f729Sjoerg Sym = getContext().getOrCreateSymbol(SymbolName);
12337330f729Sjoerg
12347330f729Sjoerg // If this is an absolute variable reference, substitute it now to preserve
12357330f729Sjoerg // semantics in the face of reassignment.
12367330f729Sjoerg if (Sym->isVariable()) {
12377330f729Sjoerg auto V = Sym->getVariableValue(/*SetUsed*/ false);
12387330f729Sjoerg bool DoInline = isa<MCConstantExpr>(V) && !Variant;
12397330f729Sjoerg if (auto TV = dyn_cast<MCTargetExpr>(V))
12407330f729Sjoerg DoInline = TV->inlineAssignedExpr();
12417330f729Sjoerg if (DoInline) {
12427330f729Sjoerg if (Variant)
12437330f729Sjoerg return Error(EndLoc, "unexpected modifier on variable reference");
12447330f729Sjoerg Res = Sym->getVariableValue(/*SetUsed*/ false);
12457330f729Sjoerg return false;
12467330f729Sjoerg }
12477330f729Sjoerg }
12487330f729Sjoerg
12497330f729Sjoerg // Otherwise create a symbol ref.
12507330f729Sjoerg Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
12517330f729Sjoerg return false;
12527330f729Sjoerg }
12537330f729Sjoerg case AsmToken::BigNum:
12547330f729Sjoerg return TokError("literal value out of range for directive");
12557330f729Sjoerg case AsmToken::Integer: {
12567330f729Sjoerg SMLoc Loc = getTok().getLoc();
12577330f729Sjoerg int64_t IntVal = getTok().getIntVal();
12587330f729Sjoerg Res = MCConstantExpr::create(IntVal, getContext());
12597330f729Sjoerg EndLoc = Lexer.getTok().getEndLoc();
12607330f729Sjoerg Lex(); // Eat token.
12617330f729Sjoerg // Look for 'b' or 'f' following an Integer as a directional label
12627330f729Sjoerg if (Lexer.getKind() == AsmToken::Identifier) {
12637330f729Sjoerg StringRef IDVal = getTok().getString();
12647330f729Sjoerg // Lookup the symbol variant if used.
12657330f729Sjoerg std::pair<StringRef, StringRef> Split = IDVal.split('@');
12667330f729Sjoerg MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
12677330f729Sjoerg if (Split.first.size() != IDVal.size()) {
12687330f729Sjoerg Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
12697330f729Sjoerg if (Variant == MCSymbolRefExpr::VK_Invalid)
12707330f729Sjoerg return TokError("invalid variant '" + Split.second + "'");
12717330f729Sjoerg IDVal = Split.first;
12727330f729Sjoerg }
12737330f729Sjoerg if (IDVal == "f" || IDVal == "b") {
12747330f729Sjoerg MCSymbol *Sym =
12757330f729Sjoerg Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
12767330f729Sjoerg Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
12777330f729Sjoerg if (IDVal == "b" && Sym->isUndefined())
12787330f729Sjoerg return Error(Loc, "directional label undefined");
12797330f729Sjoerg DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
12807330f729Sjoerg EndLoc = Lexer.getTok().getEndLoc();
12817330f729Sjoerg Lex(); // Eat identifier.
12827330f729Sjoerg }
12837330f729Sjoerg }
12847330f729Sjoerg return false;
12857330f729Sjoerg }
12867330f729Sjoerg case AsmToken::Real: {
12877330f729Sjoerg APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
12887330f729Sjoerg uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
12897330f729Sjoerg Res = MCConstantExpr::create(IntVal, getContext());
12907330f729Sjoerg EndLoc = Lexer.getTok().getEndLoc();
12917330f729Sjoerg Lex(); // Eat token.
12927330f729Sjoerg return false;
12937330f729Sjoerg }
12947330f729Sjoerg case AsmToken::Dot: {
1295*82d56013Sjoerg if (!MAI.getDotIsPC())
1296*82d56013Sjoerg return TokError("cannot use . as current PC");
1297*82d56013Sjoerg
12987330f729Sjoerg // This is a '.' reference, which references the current PC. Emit a
12997330f729Sjoerg // temporary label to the streamer and refer to it.
13007330f729Sjoerg MCSymbol *Sym = Ctx.createTempSymbol();
1301*82d56013Sjoerg Out.emitLabel(Sym);
13027330f729Sjoerg Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
13037330f729Sjoerg EndLoc = Lexer.getTok().getEndLoc();
13047330f729Sjoerg Lex(); // Eat identifier.
13057330f729Sjoerg return false;
13067330f729Sjoerg }
13077330f729Sjoerg case AsmToken::LParen:
13087330f729Sjoerg Lex(); // Eat the '('.
13097330f729Sjoerg return parseParenExpr(Res, EndLoc);
13107330f729Sjoerg case AsmToken::LBrac:
13117330f729Sjoerg if (!PlatformParser->HasBracketExpressions())
13127330f729Sjoerg return TokError("brackets expression not supported on this target");
13137330f729Sjoerg Lex(); // Eat the '['.
13147330f729Sjoerg return parseBracketExpr(Res, EndLoc);
13157330f729Sjoerg case AsmToken::Minus:
13167330f729Sjoerg Lex(); // Eat the operator.
1317*82d56013Sjoerg if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
13187330f729Sjoerg return true;
13197330f729Sjoerg Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
13207330f729Sjoerg return false;
13217330f729Sjoerg case AsmToken::Plus:
13227330f729Sjoerg Lex(); // Eat the operator.
1323*82d56013Sjoerg if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
13247330f729Sjoerg return true;
13257330f729Sjoerg Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
13267330f729Sjoerg return false;
13277330f729Sjoerg case AsmToken::Tilde:
13287330f729Sjoerg Lex(); // Eat the operator.
1329*82d56013Sjoerg if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
13307330f729Sjoerg return true;
13317330f729Sjoerg Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
13327330f729Sjoerg return false;
13337330f729Sjoerg // MIPS unary expression operators. The lexer won't generate these tokens if
13347330f729Sjoerg // MCAsmInfo::HasMipsExpressions is false for the target.
13357330f729Sjoerg case AsmToken::PercentCall16:
13367330f729Sjoerg case AsmToken::PercentCall_Hi:
13377330f729Sjoerg case AsmToken::PercentCall_Lo:
13387330f729Sjoerg case AsmToken::PercentDtprel_Hi:
13397330f729Sjoerg case AsmToken::PercentDtprel_Lo:
13407330f729Sjoerg case AsmToken::PercentGot:
13417330f729Sjoerg case AsmToken::PercentGot_Disp:
13427330f729Sjoerg case AsmToken::PercentGot_Hi:
13437330f729Sjoerg case AsmToken::PercentGot_Lo:
13447330f729Sjoerg case AsmToken::PercentGot_Ofst:
13457330f729Sjoerg case AsmToken::PercentGot_Page:
13467330f729Sjoerg case AsmToken::PercentGottprel:
13477330f729Sjoerg case AsmToken::PercentGp_Rel:
13487330f729Sjoerg case AsmToken::PercentHi:
13497330f729Sjoerg case AsmToken::PercentHigher:
13507330f729Sjoerg case AsmToken::PercentHighest:
13517330f729Sjoerg case AsmToken::PercentLo:
13527330f729Sjoerg case AsmToken::PercentNeg:
13537330f729Sjoerg case AsmToken::PercentPcrel_Hi:
13547330f729Sjoerg case AsmToken::PercentPcrel_Lo:
13557330f729Sjoerg case AsmToken::PercentTlsgd:
13567330f729Sjoerg case AsmToken::PercentTlsldm:
13577330f729Sjoerg case AsmToken::PercentTprel_Hi:
13587330f729Sjoerg case AsmToken::PercentTprel_Lo:
13597330f729Sjoerg Lex(); // Eat the operator.
13607330f729Sjoerg if (Lexer.isNot(AsmToken::LParen))
13617330f729Sjoerg return TokError("expected '(' after operator");
13627330f729Sjoerg Lex(); // Eat the operator.
13637330f729Sjoerg if (parseExpression(Res, EndLoc))
13647330f729Sjoerg return true;
13657330f729Sjoerg if (Lexer.isNot(AsmToken::RParen))
13667330f729Sjoerg return TokError("expected ')'");
13677330f729Sjoerg Lex(); // Eat the operator.
13687330f729Sjoerg Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
13697330f729Sjoerg return !Res;
13707330f729Sjoerg }
13717330f729Sjoerg }
13727330f729Sjoerg
parseExpression(const MCExpr * & Res)13737330f729Sjoerg bool AsmParser::parseExpression(const MCExpr *&Res) {
13747330f729Sjoerg SMLoc EndLoc;
13757330f729Sjoerg return parseExpression(Res, EndLoc);
13767330f729Sjoerg }
13777330f729Sjoerg
13787330f729Sjoerg const MCExpr *
applyModifierToExpr(const MCExpr * E,MCSymbolRefExpr::VariantKind Variant)13797330f729Sjoerg AsmParser::applyModifierToExpr(const MCExpr *E,
13807330f729Sjoerg MCSymbolRefExpr::VariantKind Variant) {
13817330f729Sjoerg // Ask the target implementation about this expression first.
13827330f729Sjoerg const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx);
13837330f729Sjoerg if (NewE)
13847330f729Sjoerg return NewE;
13857330f729Sjoerg // Recurse over the given expression, rebuilding it to apply the given variant
13867330f729Sjoerg // if there is exactly one symbol.
13877330f729Sjoerg switch (E->getKind()) {
13887330f729Sjoerg case MCExpr::Target:
13897330f729Sjoerg case MCExpr::Constant:
13907330f729Sjoerg return nullptr;
13917330f729Sjoerg
13927330f729Sjoerg case MCExpr::SymbolRef: {
13937330f729Sjoerg const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
13947330f729Sjoerg
13957330f729Sjoerg if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
13967330f729Sjoerg TokError("invalid variant on expression '" + getTok().getIdentifier() +
13977330f729Sjoerg "' (already modified)");
13987330f729Sjoerg return E;
13997330f729Sjoerg }
14007330f729Sjoerg
14017330f729Sjoerg return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext());
14027330f729Sjoerg }
14037330f729Sjoerg
14047330f729Sjoerg case MCExpr::Unary: {
14057330f729Sjoerg const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
14067330f729Sjoerg const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant);
14077330f729Sjoerg if (!Sub)
14087330f729Sjoerg return nullptr;
14097330f729Sjoerg return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext());
14107330f729Sjoerg }
14117330f729Sjoerg
14127330f729Sjoerg case MCExpr::Binary: {
14137330f729Sjoerg const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
14147330f729Sjoerg const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant);
14157330f729Sjoerg const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant);
14167330f729Sjoerg
14177330f729Sjoerg if (!LHS && !RHS)
14187330f729Sjoerg return nullptr;
14197330f729Sjoerg
14207330f729Sjoerg if (!LHS)
14217330f729Sjoerg LHS = BE->getLHS();
14227330f729Sjoerg if (!RHS)
14237330f729Sjoerg RHS = BE->getRHS();
14247330f729Sjoerg
14257330f729Sjoerg return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext());
14267330f729Sjoerg }
14277330f729Sjoerg }
14287330f729Sjoerg
14297330f729Sjoerg llvm_unreachable("Invalid expression kind!");
14307330f729Sjoerg }
14317330f729Sjoerg
14327330f729Sjoerg /// This function checks if the next token is <string> type or arithmetic.
14337330f729Sjoerg /// string that begin with character '<' must end with character '>'.
14347330f729Sjoerg /// otherwise it is arithmetics.
14357330f729Sjoerg /// If the function returns a 'true' value,
14367330f729Sjoerg /// the End argument will be filled with the last location pointed to the '>'
14377330f729Sjoerg /// character.
14387330f729Sjoerg
14397330f729Sjoerg /// There is a gap between the AltMacro's documentation and the single quote
14407330f729Sjoerg /// implementation. GCC does not fully support this feature and so we will not
14417330f729Sjoerg /// support it.
14427330f729Sjoerg /// TODO: Adding single quote as a string.
isAngleBracketString(SMLoc & StrLoc,SMLoc & EndLoc)1443*82d56013Sjoerg static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
14447330f729Sjoerg assert((StrLoc.getPointer() != nullptr) &&
14457330f729Sjoerg "Argument to the function cannot be a NULL value");
14467330f729Sjoerg const char *CharPtr = StrLoc.getPointer();
14477330f729Sjoerg while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
14487330f729Sjoerg (*CharPtr != '\0')) {
14497330f729Sjoerg if (*CharPtr == '!')
14507330f729Sjoerg CharPtr++;
14517330f729Sjoerg CharPtr++;
14527330f729Sjoerg }
14537330f729Sjoerg if (*CharPtr == '>') {
14547330f729Sjoerg EndLoc = StrLoc.getFromPointer(CharPtr + 1);
14557330f729Sjoerg return true;
14567330f729Sjoerg }
14577330f729Sjoerg return false;
14587330f729Sjoerg }
14597330f729Sjoerg
14607330f729Sjoerg /// creating a string without the escape characters '!'.
angleBracketString(StringRef AltMacroStr)1461*82d56013Sjoerg static std::string angleBracketString(StringRef AltMacroStr) {
14627330f729Sjoerg std::string Res;
14637330f729Sjoerg for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
14647330f729Sjoerg if (AltMacroStr[Pos] == '!')
14657330f729Sjoerg Pos++;
14667330f729Sjoerg Res += AltMacroStr[Pos];
14677330f729Sjoerg }
14687330f729Sjoerg return Res;
14697330f729Sjoerg }
14707330f729Sjoerg
14717330f729Sjoerg /// Parse an expression and return it.
14727330f729Sjoerg ///
14737330f729Sjoerg /// expr ::= expr &&,|| expr -> lowest.
14747330f729Sjoerg /// expr ::= expr |,^,&,! expr
14757330f729Sjoerg /// expr ::= expr ==,!=,<>,<,<=,>,>= expr
14767330f729Sjoerg /// expr ::= expr <<,>> expr
14777330f729Sjoerg /// expr ::= expr +,- expr
14787330f729Sjoerg /// expr ::= expr *,/,% expr -> highest.
14797330f729Sjoerg /// expr ::= primaryexpr
14807330f729Sjoerg ///
parseExpression(const MCExpr * & Res,SMLoc & EndLoc)14817330f729Sjoerg bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
14827330f729Sjoerg // Parse the expression.
14837330f729Sjoerg Res = nullptr;
14847330f729Sjoerg if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
14857330f729Sjoerg parseBinOpRHS(1, Res, EndLoc))
14867330f729Sjoerg return true;
14877330f729Sjoerg
14887330f729Sjoerg // As a special case, we support 'a op b @ modifier' by rewriting the
14897330f729Sjoerg // expression to include the modifier. This is inefficient, but in general we
14907330f729Sjoerg // expect users to use 'a@modifier op b'.
14917330f729Sjoerg if (Lexer.getKind() == AsmToken::At) {
14927330f729Sjoerg Lex();
14937330f729Sjoerg
14947330f729Sjoerg if (Lexer.isNot(AsmToken::Identifier))
14957330f729Sjoerg return TokError("unexpected symbol modifier following '@'");
14967330f729Sjoerg
14977330f729Sjoerg MCSymbolRefExpr::VariantKind Variant =
14987330f729Sjoerg MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
14997330f729Sjoerg if (Variant == MCSymbolRefExpr::VK_Invalid)
15007330f729Sjoerg return TokError("invalid variant '" + getTok().getIdentifier() + "'");
15017330f729Sjoerg
15027330f729Sjoerg const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant);
15037330f729Sjoerg if (!ModifiedRes) {
15047330f729Sjoerg return TokError("invalid modifier '" + getTok().getIdentifier() +
15057330f729Sjoerg "' (no symbols present)");
15067330f729Sjoerg }
15077330f729Sjoerg
15087330f729Sjoerg Res = ModifiedRes;
15097330f729Sjoerg Lex();
15107330f729Sjoerg }
15117330f729Sjoerg
15127330f729Sjoerg // Try to constant fold it up front, if possible. Do not exploit
15137330f729Sjoerg // assembler here.
15147330f729Sjoerg int64_t Value;
15157330f729Sjoerg if (Res->evaluateAsAbsolute(Value))
15167330f729Sjoerg Res = MCConstantExpr::create(Value, getContext());
15177330f729Sjoerg
15187330f729Sjoerg return false;
15197330f729Sjoerg }
15207330f729Sjoerg
parseParenExpression(const MCExpr * & Res,SMLoc & EndLoc)15217330f729Sjoerg bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
15227330f729Sjoerg Res = nullptr;
15237330f729Sjoerg return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
15247330f729Sjoerg }
15257330f729Sjoerg
parseParenExprOfDepth(unsigned ParenDepth,const MCExpr * & Res,SMLoc & EndLoc)15267330f729Sjoerg bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
15277330f729Sjoerg SMLoc &EndLoc) {
15287330f729Sjoerg if (parseParenExpr(Res, EndLoc))
15297330f729Sjoerg return true;
15307330f729Sjoerg
15317330f729Sjoerg for (; ParenDepth > 0; --ParenDepth) {
15327330f729Sjoerg if (parseBinOpRHS(1, Res, EndLoc))
15337330f729Sjoerg return true;
15347330f729Sjoerg
15357330f729Sjoerg // We don't Lex() the last RParen.
15367330f729Sjoerg // This is the same behavior as parseParenExpression().
15377330f729Sjoerg if (ParenDepth - 1 > 0) {
15387330f729Sjoerg EndLoc = getTok().getEndLoc();
15397330f729Sjoerg if (parseToken(AsmToken::RParen,
15407330f729Sjoerg "expected ')' in parentheses expression"))
15417330f729Sjoerg return true;
15427330f729Sjoerg }
15437330f729Sjoerg }
15447330f729Sjoerg return false;
15457330f729Sjoerg }
15467330f729Sjoerg
parseAbsoluteExpression(int64_t & Res)15477330f729Sjoerg bool AsmParser::parseAbsoluteExpression(int64_t &Res) {
15487330f729Sjoerg const MCExpr *Expr;
15497330f729Sjoerg
15507330f729Sjoerg SMLoc StartLoc = Lexer.getLoc();
15517330f729Sjoerg if (parseExpression(Expr))
15527330f729Sjoerg return true;
15537330f729Sjoerg
15547330f729Sjoerg if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
15557330f729Sjoerg return Error(StartLoc, "expected absolute expression");
15567330f729Sjoerg
15577330f729Sjoerg return false;
15587330f729Sjoerg }
15597330f729Sjoerg
getDarwinBinOpPrecedence(AsmToken::TokenKind K,MCBinaryExpr::Opcode & Kind,bool ShouldUseLogicalShr)15607330f729Sjoerg static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K,
15617330f729Sjoerg MCBinaryExpr::Opcode &Kind,
15627330f729Sjoerg bool ShouldUseLogicalShr) {
15637330f729Sjoerg switch (K) {
15647330f729Sjoerg default:
15657330f729Sjoerg return 0; // not a binop.
15667330f729Sjoerg
15677330f729Sjoerg // Lowest Precedence: &&, ||
15687330f729Sjoerg case AsmToken::AmpAmp:
15697330f729Sjoerg Kind = MCBinaryExpr::LAnd;
15707330f729Sjoerg return 1;
15717330f729Sjoerg case AsmToken::PipePipe:
15727330f729Sjoerg Kind = MCBinaryExpr::LOr;
15737330f729Sjoerg return 1;
15747330f729Sjoerg
15757330f729Sjoerg // Low Precedence: |, &, ^
15767330f729Sjoerg case AsmToken::Pipe:
15777330f729Sjoerg Kind = MCBinaryExpr::Or;
15787330f729Sjoerg return 2;
15797330f729Sjoerg case AsmToken::Caret:
15807330f729Sjoerg Kind = MCBinaryExpr::Xor;
15817330f729Sjoerg return 2;
15827330f729Sjoerg case AsmToken::Amp:
15837330f729Sjoerg Kind = MCBinaryExpr::And;
15847330f729Sjoerg return 2;
15857330f729Sjoerg
15867330f729Sjoerg // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
15877330f729Sjoerg case AsmToken::EqualEqual:
15887330f729Sjoerg Kind = MCBinaryExpr::EQ;
15897330f729Sjoerg return 3;
15907330f729Sjoerg case AsmToken::ExclaimEqual:
15917330f729Sjoerg case AsmToken::LessGreater:
15927330f729Sjoerg Kind = MCBinaryExpr::NE;
15937330f729Sjoerg return 3;
15947330f729Sjoerg case AsmToken::Less:
15957330f729Sjoerg Kind = MCBinaryExpr::LT;
15967330f729Sjoerg return 3;
15977330f729Sjoerg case AsmToken::LessEqual:
15987330f729Sjoerg Kind = MCBinaryExpr::LTE;
15997330f729Sjoerg return 3;
16007330f729Sjoerg case AsmToken::Greater:
16017330f729Sjoerg Kind = MCBinaryExpr::GT;
16027330f729Sjoerg return 3;
16037330f729Sjoerg case AsmToken::GreaterEqual:
16047330f729Sjoerg Kind = MCBinaryExpr::GTE;
16057330f729Sjoerg return 3;
16067330f729Sjoerg
16077330f729Sjoerg // Intermediate Precedence: <<, >>
16087330f729Sjoerg case AsmToken::LessLess:
16097330f729Sjoerg Kind = MCBinaryExpr::Shl;
16107330f729Sjoerg return 4;
16117330f729Sjoerg case AsmToken::GreaterGreater:
16127330f729Sjoerg Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
16137330f729Sjoerg return 4;
16147330f729Sjoerg
16157330f729Sjoerg // High Intermediate Precedence: +, -
16167330f729Sjoerg case AsmToken::Plus:
16177330f729Sjoerg Kind = MCBinaryExpr::Add;
16187330f729Sjoerg return 5;
16197330f729Sjoerg case AsmToken::Minus:
16207330f729Sjoerg Kind = MCBinaryExpr::Sub;
16217330f729Sjoerg return 5;
16227330f729Sjoerg
16237330f729Sjoerg // Highest Precedence: *, /, %
16247330f729Sjoerg case AsmToken::Star:
16257330f729Sjoerg Kind = MCBinaryExpr::Mul;
16267330f729Sjoerg return 6;
16277330f729Sjoerg case AsmToken::Slash:
16287330f729Sjoerg Kind = MCBinaryExpr::Div;
16297330f729Sjoerg return 6;
16307330f729Sjoerg case AsmToken::Percent:
16317330f729Sjoerg Kind = MCBinaryExpr::Mod;
16327330f729Sjoerg return 6;
16337330f729Sjoerg }
16347330f729Sjoerg }
16357330f729Sjoerg
getGNUBinOpPrecedence(const MCAsmInfo & MAI,AsmToken::TokenKind K,MCBinaryExpr::Opcode & Kind,bool ShouldUseLogicalShr)1636*82d56013Sjoerg static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI,
1637*82d56013Sjoerg AsmToken::TokenKind K,
16387330f729Sjoerg MCBinaryExpr::Opcode &Kind,
16397330f729Sjoerg bool ShouldUseLogicalShr) {
16407330f729Sjoerg switch (K) {
16417330f729Sjoerg default:
16427330f729Sjoerg return 0; // not a binop.
16437330f729Sjoerg
16447330f729Sjoerg // Lowest Precedence: &&, ||
16457330f729Sjoerg case AsmToken::AmpAmp:
16467330f729Sjoerg Kind = MCBinaryExpr::LAnd;
16477330f729Sjoerg return 2;
16487330f729Sjoerg case AsmToken::PipePipe:
16497330f729Sjoerg Kind = MCBinaryExpr::LOr;
16507330f729Sjoerg return 1;
16517330f729Sjoerg
16527330f729Sjoerg // Low Precedence: ==, !=, <>, <, <=, >, >=
16537330f729Sjoerg case AsmToken::EqualEqual:
16547330f729Sjoerg Kind = MCBinaryExpr::EQ;
16557330f729Sjoerg return 3;
16567330f729Sjoerg case AsmToken::ExclaimEqual:
16577330f729Sjoerg case AsmToken::LessGreater:
16587330f729Sjoerg Kind = MCBinaryExpr::NE;
16597330f729Sjoerg return 3;
16607330f729Sjoerg case AsmToken::Less:
16617330f729Sjoerg Kind = MCBinaryExpr::LT;
16627330f729Sjoerg return 3;
16637330f729Sjoerg case AsmToken::LessEqual:
16647330f729Sjoerg Kind = MCBinaryExpr::LTE;
16657330f729Sjoerg return 3;
16667330f729Sjoerg case AsmToken::Greater:
16677330f729Sjoerg Kind = MCBinaryExpr::GT;
16687330f729Sjoerg return 3;
16697330f729Sjoerg case AsmToken::GreaterEqual:
16707330f729Sjoerg Kind = MCBinaryExpr::GTE;
16717330f729Sjoerg return 3;
16727330f729Sjoerg
16737330f729Sjoerg // Low Intermediate Precedence: +, -
16747330f729Sjoerg case AsmToken::Plus:
16757330f729Sjoerg Kind = MCBinaryExpr::Add;
16767330f729Sjoerg return 4;
16777330f729Sjoerg case AsmToken::Minus:
16787330f729Sjoerg Kind = MCBinaryExpr::Sub;
16797330f729Sjoerg return 4;
16807330f729Sjoerg
1681*82d56013Sjoerg // High Intermediate Precedence: |, !, &, ^
16827330f729Sjoerg //
16837330f729Sjoerg case AsmToken::Pipe:
16847330f729Sjoerg Kind = MCBinaryExpr::Or;
16857330f729Sjoerg return 5;
1686*82d56013Sjoerg case AsmToken::Exclaim:
1687*82d56013Sjoerg // Hack to support ARM compatible aliases (implied 'sp' operand in 'srs*'
1688*82d56013Sjoerg // instructions like 'srsda #31!') and not parse ! as an infix operator.
1689*82d56013Sjoerg if (MAI.getCommentString() == "@")
1690*82d56013Sjoerg return 0;
1691*82d56013Sjoerg Kind = MCBinaryExpr::OrNot;
1692*82d56013Sjoerg return 5;
16937330f729Sjoerg case AsmToken::Caret:
16947330f729Sjoerg Kind = MCBinaryExpr::Xor;
16957330f729Sjoerg return 5;
16967330f729Sjoerg case AsmToken::Amp:
16977330f729Sjoerg Kind = MCBinaryExpr::And;
16987330f729Sjoerg return 5;
16997330f729Sjoerg
17007330f729Sjoerg // Highest Precedence: *, /, %, <<, >>
17017330f729Sjoerg case AsmToken::Star:
17027330f729Sjoerg Kind = MCBinaryExpr::Mul;
17037330f729Sjoerg return 6;
17047330f729Sjoerg case AsmToken::Slash:
17057330f729Sjoerg Kind = MCBinaryExpr::Div;
17067330f729Sjoerg return 6;
17077330f729Sjoerg case AsmToken::Percent:
17087330f729Sjoerg Kind = MCBinaryExpr::Mod;
17097330f729Sjoerg return 6;
17107330f729Sjoerg case AsmToken::LessLess:
17117330f729Sjoerg Kind = MCBinaryExpr::Shl;
17127330f729Sjoerg return 6;
17137330f729Sjoerg case AsmToken::GreaterGreater:
17147330f729Sjoerg Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
17157330f729Sjoerg return 6;
17167330f729Sjoerg }
17177330f729Sjoerg }
17187330f729Sjoerg
getBinOpPrecedence(AsmToken::TokenKind K,MCBinaryExpr::Opcode & Kind)17197330f729Sjoerg unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
17207330f729Sjoerg MCBinaryExpr::Opcode &Kind) {
17217330f729Sjoerg bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
17227330f729Sjoerg return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)
1723*82d56013Sjoerg : getGNUBinOpPrecedence(MAI, K, Kind, ShouldUseLogicalShr);
17247330f729Sjoerg }
17257330f729Sjoerg
17267330f729Sjoerg /// Parse all binary operators with precedence >= 'Precedence'.
17277330f729Sjoerg /// Res contains the LHS of the expression on input.
parseBinOpRHS(unsigned Precedence,const MCExpr * & Res,SMLoc & EndLoc)17287330f729Sjoerg bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
17297330f729Sjoerg SMLoc &EndLoc) {
17307330f729Sjoerg SMLoc StartLoc = Lexer.getLoc();
17317330f729Sjoerg while (true) {
17327330f729Sjoerg MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
17337330f729Sjoerg unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
17347330f729Sjoerg
17357330f729Sjoerg // If the next token is lower precedence than we are allowed to eat, return
17367330f729Sjoerg // successfully with what we ate already.
17377330f729Sjoerg if (TokPrec < Precedence)
17387330f729Sjoerg return false;
17397330f729Sjoerg
17407330f729Sjoerg Lex();
17417330f729Sjoerg
17427330f729Sjoerg // Eat the next primary expression.
17437330f729Sjoerg const MCExpr *RHS;
17447330f729Sjoerg if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
17457330f729Sjoerg return true;
17467330f729Sjoerg
17477330f729Sjoerg // If BinOp binds less tightly with RHS than the operator after RHS, let
17487330f729Sjoerg // the pending operator take RHS as its LHS.
17497330f729Sjoerg MCBinaryExpr::Opcode Dummy;
17507330f729Sjoerg unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
17517330f729Sjoerg if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
17527330f729Sjoerg return true;
17537330f729Sjoerg
17547330f729Sjoerg // Merge LHS and RHS according to operator.
17557330f729Sjoerg Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
17567330f729Sjoerg }
17577330f729Sjoerg }
17587330f729Sjoerg
17597330f729Sjoerg /// ParseStatement:
17607330f729Sjoerg /// ::= EndOfStatement
17617330f729Sjoerg /// ::= Label* Directive ...Operands... EndOfStatement
17627330f729Sjoerg /// ::= Label* Identifier OperandList* EndOfStatement
parseStatement(ParseStatementInfo & Info,MCAsmParserSemaCallback * SI)17637330f729Sjoerg bool AsmParser::parseStatement(ParseStatementInfo &Info,
17647330f729Sjoerg MCAsmParserSemaCallback *SI) {
17657330f729Sjoerg assert(!hasPendingError() && "parseStatement started with pending error");
17667330f729Sjoerg // Eat initial spaces and comments
17677330f729Sjoerg while (Lexer.is(AsmToken::Space))
17687330f729Sjoerg Lex();
17697330f729Sjoerg if (Lexer.is(AsmToken::EndOfStatement)) {
17707330f729Sjoerg // if this is a line comment we can drop it safely
17717330f729Sjoerg if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
17727330f729Sjoerg getTok().getString().front() == '\n')
17737330f729Sjoerg Out.AddBlankLine();
17747330f729Sjoerg Lex();
17757330f729Sjoerg return false;
17767330f729Sjoerg }
17777330f729Sjoerg // Statements always start with an identifier.
17787330f729Sjoerg AsmToken ID = getTok();
17797330f729Sjoerg SMLoc IDLoc = ID.getLoc();
17807330f729Sjoerg StringRef IDVal;
17817330f729Sjoerg int64_t LocalLabelVal = -1;
1782*82d56013Sjoerg StartTokLoc = ID.getLoc();
17837330f729Sjoerg if (Lexer.is(AsmToken::HashDirective))
1784*82d56013Sjoerg return parseCppHashLineFilenameComment(IDLoc,
1785*82d56013Sjoerg !isInsideMacroInstantiation());
1786*82d56013Sjoerg
17877330f729Sjoerg // Allow an integer followed by a ':' as a directional local label.
17887330f729Sjoerg if (Lexer.is(AsmToken::Integer)) {
17897330f729Sjoerg LocalLabelVal = getTok().getIntVal();
17907330f729Sjoerg if (LocalLabelVal < 0) {
17917330f729Sjoerg if (!TheCondState.Ignore) {
17927330f729Sjoerg Lex(); // always eat a token
17937330f729Sjoerg return Error(IDLoc, "unexpected token at start of statement");
17947330f729Sjoerg }
17957330f729Sjoerg IDVal = "";
17967330f729Sjoerg } else {
17977330f729Sjoerg IDVal = getTok().getString();
17987330f729Sjoerg Lex(); // Consume the integer token to be used as an identifier token.
17997330f729Sjoerg if (Lexer.getKind() != AsmToken::Colon) {
18007330f729Sjoerg if (!TheCondState.Ignore) {
18017330f729Sjoerg Lex(); // always eat a token
18027330f729Sjoerg return Error(IDLoc, "unexpected token at start of statement");
18037330f729Sjoerg }
18047330f729Sjoerg }
18057330f729Sjoerg }
18067330f729Sjoerg } else if (Lexer.is(AsmToken::Dot)) {
18077330f729Sjoerg // Treat '.' as a valid identifier in this context.
18087330f729Sjoerg Lex();
18097330f729Sjoerg IDVal = ".";
18107330f729Sjoerg } else if (Lexer.is(AsmToken::LCurly)) {
18117330f729Sjoerg // Treat '{' as a valid identifier in this context.
18127330f729Sjoerg Lex();
18137330f729Sjoerg IDVal = "{";
18147330f729Sjoerg
18157330f729Sjoerg } else if (Lexer.is(AsmToken::RCurly)) {
18167330f729Sjoerg // Treat '}' as a valid identifier in this context.
18177330f729Sjoerg Lex();
18187330f729Sjoerg IDVal = "}";
18197330f729Sjoerg } else if (Lexer.is(AsmToken::Star) &&
18207330f729Sjoerg getTargetParser().starIsStartOfStatement()) {
18217330f729Sjoerg // Accept '*' as a valid start of statement.
18227330f729Sjoerg Lex();
18237330f729Sjoerg IDVal = "*";
18247330f729Sjoerg } else if (parseIdentifier(IDVal)) {
18257330f729Sjoerg if (!TheCondState.Ignore) {
18267330f729Sjoerg Lex(); // always eat a token
18277330f729Sjoerg return Error(IDLoc, "unexpected token at start of statement");
18287330f729Sjoerg }
18297330f729Sjoerg IDVal = "";
18307330f729Sjoerg }
18317330f729Sjoerg
18327330f729Sjoerg // Handle conditional assembly here before checking for skipping. We
18337330f729Sjoerg // have to do this so that .endif isn't skipped in a ".if 0" block for
18347330f729Sjoerg // example.
18357330f729Sjoerg StringMap<DirectiveKind>::const_iterator DirKindIt =
1836*82d56013Sjoerg DirectiveKindMap.find(IDVal.lower());
18377330f729Sjoerg DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
18387330f729Sjoerg ? DK_NO_DIRECTIVE
18397330f729Sjoerg : DirKindIt->getValue();
18407330f729Sjoerg switch (DirKind) {
18417330f729Sjoerg default:
18427330f729Sjoerg break;
18437330f729Sjoerg case DK_IF:
18447330f729Sjoerg case DK_IFEQ:
18457330f729Sjoerg case DK_IFGE:
18467330f729Sjoerg case DK_IFGT:
18477330f729Sjoerg case DK_IFLE:
18487330f729Sjoerg case DK_IFLT:
18497330f729Sjoerg case DK_IFNE:
18507330f729Sjoerg return parseDirectiveIf(IDLoc, DirKind);
18517330f729Sjoerg case DK_IFB:
18527330f729Sjoerg return parseDirectiveIfb(IDLoc, true);
18537330f729Sjoerg case DK_IFNB:
18547330f729Sjoerg return parseDirectiveIfb(IDLoc, false);
18557330f729Sjoerg case DK_IFC:
18567330f729Sjoerg return parseDirectiveIfc(IDLoc, true);
18577330f729Sjoerg case DK_IFEQS:
18587330f729Sjoerg return parseDirectiveIfeqs(IDLoc, true);
18597330f729Sjoerg case DK_IFNC:
18607330f729Sjoerg return parseDirectiveIfc(IDLoc, false);
18617330f729Sjoerg case DK_IFNES:
18627330f729Sjoerg return parseDirectiveIfeqs(IDLoc, false);
18637330f729Sjoerg case DK_IFDEF:
18647330f729Sjoerg return parseDirectiveIfdef(IDLoc, true);
18657330f729Sjoerg case DK_IFNDEF:
18667330f729Sjoerg case DK_IFNOTDEF:
18677330f729Sjoerg return parseDirectiveIfdef(IDLoc, false);
18687330f729Sjoerg case DK_ELSEIF:
18697330f729Sjoerg return parseDirectiveElseIf(IDLoc);
18707330f729Sjoerg case DK_ELSE:
18717330f729Sjoerg return parseDirectiveElse(IDLoc);
18727330f729Sjoerg case DK_ENDIF:
18737330f729Sjoerg return parseDirectiveEndIf(IDLoc);
18747330f729Sjoerg }
18757330f729Sjoerg
18767330f729Sjoerg // Ignore the statement if in the middle of inactive conditional
18777330f729Sjoerg // (e.g. ".if 0").
18787330f729Sjoerg if (TheCondState.Ignore) {
18797330f729Sjoerg eatToEndOfStatement();
18807330f729Sjoerg return false;
18817330f729Sjoerg }
18827330f729Sjoerg
18837330f729Sjoerg // FIXME: Recurse on local labels?
18847330f729Sjoerg
18857330f729Sjoerg // See what kind of statement we have.
18867330f729Sjoerg switch (Lexer.getKind()) {
18877330f729Sjoerg case AsmToken::Colon: {
18887330f729Sjoerg if (!getTargetParser().isLabel(ID))
18897330f729Sjoerg break;
18907330f729Sjoerg if (checkForValidSection())
18917330f729Sjoerg return true;
18927330f729Sjoerg
18937330f729Sjoerg // identifier ':' -> Label.
18947330f729Sjoerg Lex();
18957330f729Sjoerg
18967330f729Sjoerg // Diagnose attempt to use '.' as a label.
18977330f729Sjoerg if (IDVal == ".")
18987330f729Sjoerg return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
18997330f729Sjoerg
19007330f729Sjoerg // Diagnose attempt to use a variable as a label.
19017330f729Sjoerg //
19027330f729Sjoerg // FIXME: Diagnostics. Note the location of the definition as a label.
19037330f729Sjoerg // FIXME: This doesn't diagnose assignment to a symbol which has been
19047330f729Sjoerg // implicitly marked as external.
19057330f729Sjoerg MCSymbol *Sym;
19067330f729Sjoerg if (LocalLabelVal == -1) {
1907*82d56013Sjoerg if (ParsingMSInlineAsm && SI) {
19087330f729Sjoerg StringRef RewrittenLabel =
19097330f729Sjoerg SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
19107330f729Sjoerg assert(!RewrittenLabel.empty() &&
19117330f729Sjoerg "We should have an internal name here.");
19127330f729Sjoerg Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
19137330f729Sjoerg RewrittenLabel);
19147330f729Sjoerg IDVal = RewrittenLabel;
19157330f729Sjoerg }
19167330f729Sjoerg Sym = getContext().getOrCreateSymbol(IDVal);
19177330f729Sjoerg } else
19187330f729Sjoerg Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
19197330f729Sjoerg // End of Labels should be treated as end of line for lexing
19207330f729Sjoerg // purposes but that information is not available to the Lexer who
19217330f729Sjoerg // does not understand Labels. This may cause us to see a Hash
19227330f729Sjoerg // here instead of a preprocessor line comment.
19237330f729Sjoerg if (getTok().is(AsmToken::Hash)) {
19247330f729Sjoerg StringRef CommentStr = parseStringToEndOfStatement();
19257330f729Sjoerg Lexer.Lex();
19267330f729Sjoerg Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
19277330f729Sjoerg }
19287330f729Sjoerg
19297330f729Sjoerg // Consume any end of statement token, if present, to avoid spurious
19307330f729Sjoerg // AddBlankLine calls().
19317330f729Sjoerg if (getTok().is(AsmToken::EndOfStatement)) {
19327330f729Sjoerg Lex();
19337330f729Sjoerg }
19347330f729Sjoerg
1935*82d56013Sjoerg if (discardLTOSymbol(IDVal))
1936*82d56013Sjoerg return false;
1937*82d56013Sjoerg
19387330f729Sjoerg getTargetParser().doBeforeLabelEmit(Sym);
19397330f729Sjoerg
19407330f729Sjoerg // Emit the label.
1941*82d56013Sjoerg if (!getTargetParser().isParsingMSInlineAsm())
1942*82d56013Sjoerg Out.emitLabel(Sym, IDLoc);
19437330f729Sjoerg
19447330f729Sjoerg // If we are generating dwarf for assembly source files then gather the
19457330f729Sjoerg // info to make a dwarf label entry for this label if needed.
19467330f729Sjoerg if (enabledGenDwarfForAssembly())
19477330f729Sjoerg MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
19487330f729Sjoerg IDLoc);
19497330f729Sjoerg
19507330f729Sjoerg getTargetParser().onLabelParsed(Sym);
19517330f729Sjoerg
19527330f729Sjoerg return false;
19537330f729Sjoerg }
19547330f729Sjoerg
19557330f729Sjoerg case AsmToken::Equal:
19567330f729Sjoerg if (!getTargetParser().equalIsAsmAssignment())
19577330f729Sjoerg break;
19587330f729Sjoerg // identifier '=' ... -> assignment statement
19597330f729Sjoerg Lex();
19607330f729Sjoerg
19617330f729Sjoerg return parseAssignment(IDVal, true);
19627330f729Sjoerg
19637330f729Sjoerg default: // Normal instruction or directive.
19647330f729Sjoerg break;
19657330f729Sjoerg }
19667330f729Sjoerg
19677330f729Sjoerg // If macros are enabled, check to see if this is a macro instantiation.
19687330f729Sjoerg if (areMacrosEnabled())
19697330f729Sjoerg if (const MCAsmMacro *M = getContext().lookupMacro(IDVal)) {
19707330f729Sjoerg return handleMacroEntry(M, IDLoc);
19717330f729Sjoerg }
19727330f729Sjoerg
19737330f729Sjoerg // Otherwise, we have a normal instruction or directive.
19747330f729Sjoerg
19757330f729Sjoerg // Directives start with "."
19767330f729Sjoerg if (IDVal.startswith(".") && IDVal != ".") {
19777330f729Sjoerg // There are several entities interested in parsing directives:
19787330f729Sjoerg //
19797330f729Sjoerg // 1. The target-specific assembly parser. Some directives are target
19807330f729Sjoerg // specific or may potentially behave differently on certain targets.
19817330f729Sjoerg // 2. Asm parser extensions. For example, platform-specific parsers
19827330f729Sjoerg // (like the ELF parser) register themselves as extensions.
19837330f729Sjoerg // 3. The generic directive parser implemented by this class. These are
19847330f729Sjoerg // all the directives that behave in a target and platform independent
19857330f729Sjoerg // manner, or at least have a default behavior that's shared between
19867330f729Sjoerg // all targets and platforms.
19877330f729Sjoerg
19887330f729Sjoerg getTargetParser().flushPendingInstructions(getStreamer());
19897330f729Sjoerg
19907330f729Sjoerg SMLoc StartTokLoc = getTok().getLoc();
19917330f729Sjoerg bool TPDirectiveReturn = getTargetParser().ParseDirective(ID);
19927330f729Sjoerg
19937330f729Sjoerg if (hasPendingError())
19947330f729Sjoerg return true;
19957330f729Sjoerg // Currently the return value should be true if we are
19967330f729Sjoerg // uninterested but as this is at odds with the standard parsing
19977330f729Sjoerg // convention (return true = error) we have instances of a parsed
19987330f729Sjoerg // directive that fails returning true as an error. Catch these
19997330f729Sjoerg // cases as best as possible errors here.
20007330f729Sjoerg if (TPDirectiveReturn && StartTokLoc != getTok().getLoc())
20017330f729Sjoerg return true;
20027330f729Sjoerg // Return if we did some parsing or believe we succeeded.
20037330f729Sjoerg if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc())
20047330f729Sjoerg return false;
20057330f729Sjoerg
20067330f729Sjoerg // Next, check the extension directive map to see if any extension has
20077330f729Sjoerg // registered itself to parse this directive.
20087330f729Sjoerg std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
20097330f729Sjoerg ExtensionDirectiveMap.lookup(IDVal);
20107330f729Sjoerg if (Handler.first)
20117330f729Sjoerg return (*Handler.second)(Handler.first, IDVal, IDLoc);
20127330f729Sjoerg
20137330f729Sjoerg // Finally, if no one else is interested in this directive, it must be
20147330f729Sjoerg // generic and familiar to this class.
20157330f729Sjoerg switch (DirKind) {
20167330f729Sjoerg default:
20177330f729Sjoerg break;
20187330f729Sjoerg case DK_SET:
20197330f729Sjoerg case DK_EQU:
20207330f729Sjoerg return parseDirectiveSet(IDVal, true);
20217330f729Sjoerg case DK_EQUIV:
20227330f729Sjoerg return parseDirectiveSet(IDVal, false);
20237330f729Sjoerg case DK_ASCII:
20247330f729Sjoerg return parseDirectiveAscii(IDVal, false);
20257330f729Sjoerg case DK_ASCIZ:
20267330f729Sjoerg case DK_STRING:
20277330f729Sjoerg return parseDirectiveAscii(IDVal, true);
20287330f729Sjoerg case DK_BYTE:
20297330f729Sjoerg case DK_DC_B:
20307330f729Sjoerg return parseDirectiveValue(IDVal, 1);
20317330f729Sjoerg case DK_DC:
20327330f729Sjoerg case DK_DC_W:
20337330f729Sjoerg case DK_SHORT:
20347330f729Sjoerg case DK_VALUE:
20357330f729Sjoerg case DK_2BYTE:
20367330f729Sjoerg return parseDirectiveValue(IDVal, 2);
20377330f729Sjoerg case DK_LONG:
20387330f729Sjoerg case DK_INT:
20397330f729Sjoerg case DK_4BYTE:
20407330f729Sjoerg case DK_DC_L:
20417330f729Sjoerg return parseDirectiveValue(IDVal, 4);
20427330f729Sjoerg case DK_QUAD:
20437330f729Sjoerg case DK_8BYTE:
20447330f729Sjoerg return parseDirectiveValue(IDVal, 8);
20457330f729Sjoerg case DK_DC_A:
20467330f729Sjoerg return parseDirectiveValue(
20477330f729Sjoerg IDVal, getContext().getAsmInfo()->getCodePointerSize());
20487330f729Sjoerg case DK_OCTA:
20497330f729Sjoerg return parseDirectiveOctaValue(IDVal);
20507330f729Sjoerg case DK_SINGLE:
20517330f729Sjoerg case DK_FLOAT:
20527330f729Sjoerg case DK_DC_S:
20537330f729Sjoerg return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());
20547330f729Sjoerg case DK_DOUBLE:
20557330f729Sjoerg case DK_DC_D:
20567330f729Sjoerg return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());
20577330f729Sjoerg case DK_ALIGN: {
20587330f729Sjoerg bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
20597330f729Sjoerg return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);
20607330f729Sjoerg }
20617330f729Sjoerg case DK_ALIGN32: {
20627330f729Sjoerg bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
20637330f729Sjoerg return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);
20647330f729Sjoerg }
20657330f729Sjoerg case DK_BALIGN:
20667330f729Sjoerg return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
20677330f729Sjoerg case DK_BALIGNW:
20687330f729Sjoerg return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
20697330f729Sjoerg case DK_BALIGNL:
20707330f729Sjoerg return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
20717330f729Sjoerg case DK_P2ALIGN:
20727330f729Sjoerg return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
20737330f729Sjoerg case DK_P2ALIGNW:
20747330f729Sjoerg return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
20757330f729Sjoerg case DK_P2ALIGNL:
20767330f729Sjoerg return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
20777330f729Sjoerg case DK_ORG:
20787330f729Sjoerg return parseDirectiveOrg();
20797330f729Sjoerg case DK_FILL:
20807330f729Sjoerg return parseDirectiveFill();
20817330f729Sjoerg case DK_ZERO:
20827330f729Sjoerg return parseDirectiveZero();
20837330f729Sjoerg case DK_EXTERN:
20847330f729Sjoerg eatToEndOfStatement(); // .extern is the default, ignore it.
20857330f729Sjoerg return false;
20867330f729Sjoerg case DK_GLOBL:
20877330f729Sjoerg case DK_GLOBAL:
20887330f729Sjoerg return parseDirectiveSymbolAttribute(MCSA_Global);
20897330f729Sjoerg case DK_LAZY_REFERENCE:
20907330f729Sjoerg return parseDirectiveSymbolAttribute(MCSA_LazyReference);
20917330f729Sjoerg case DK_NO_DEAD_STRIP:
20927330f729Sjoerg return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
20937330f729Sjoerg case DK_SYMBOL_RESOLVER:
20947330f729Sjoerg return parseDirectiveSymbolAttribute(MCSA_SymbolResolver);
20957330f729Sjoerg case DK_PRIVATE_EXTERN:
20967330f729Sjoerg return parseDirectiveSymbolAttribute(MCSA_PrivateExtern);
20977330f729Sjoerg case DK_REFERENCE:
20987330f729Sjoerg return parseDirectiveSymbolAttribute(MCSA_Reference);
20997330f729Sjoerg case DK_WEAK_DEFINITION:
21007330f729Sjoerg return parseDirectiveSymbolAttribute(MCSA_WeakDefinition);
21017330f729Sjoerg case DK_WEAK_REFERENCE:
21027330f729Sjoerg return parseDirectiveSymbolAttribute(MCSA_WeakReference);
21037330f729Sjoerg case DK_WEAK_DEF_CAN_BE_HIDDEN:
21047330f729Sjoerg return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
21057330f729Sjoerg case DK_COLD:
21067330f729Sjoerg return parseDirectiveSymbolAttribute(MCSA_Cold);
21077330f729Sjoerg case DK_COMM:
21087330f729Sjoerg case DK_COMMON:
21097330f729Sjoerg return parseDirectiveComm(/*IsLocal=*/false);
21107330f729Sjoerg case DK_LCOMM:
21117330f729Sjoerg return parseDirectiveComm(/*IsLocal=*/true);
21127330f729Sjoerg case DK_ABORT:
21137330f729Sjoerg return parseDirectiveAbort();
21147330f729Sjoerg case DK_INCLUDE:
21157330f729Sjoerg return parseDirectiveInclude();
21167330f729Sjoerg case DK_INCBIN:
21177330f729Sjoerg return parseDirectiveIncbin();
21187330f729Sjoerg case DK_CODE16:
21197330f729Sjoerg case DK_CODE16GCC:
21207330f729Sjoerg return TokError(Twine(IDVal) +
21217330f729Sjoerg " not currently supported for this target");
21227330f729Sjoerg case DK_REPT:
21237330f729Sjoerg return parseDirectiveRept(IDLoc, IDVal);
21247330f729Sjoerg case DK_IRP:
21257330f729Sjoerg return parseDirectiveIrp(IDLoc);
21267330f729Sjoerg case DK_IRPC:
21277330f729Sjoerg return parseDirectiveIrpc(IDLoc);
21287330f729Sjoerg case DK_ENDR:
21297330f729Sjoerg return parseDirectiveEndr(IDLoc);
21307330f729Sjoerg case DK_BUNDLE_ALIGN_MODE:
21317330f729Sjoerg return parseDirectiveBundleAlignMode();
21327330f729Sjoerg case DK_BUNDLE_LOCK:
21337330f729Sjoerg return parseDirectiveBundleLock();
21347330f729Sjoerg case DK_BUNDLE_UNLOCK:
21357330f729Sjoerg return parseDirectiveBundleUnlock();
21367330f729Sjoerg case DK_SLEB128:
21377330f729Sjoerg return parseDirectiveLEB128(true);
21387330f729Sjoerg case DK_ULEB128:
21397330f729Sjoerg return parseDirectiveLEB128(false);
21407330f729Sjoerg case DK_SPACE:
21417330f729Sjoerg case DK_SKIP:
21427330f729Sjoerg return parseDirectiveSpace(IDVal);
21437330f729Sjoerg case DK_FILE:
21447330f729Sjoerg return parseDirectiveFile(IDLoc);
21457330f729Sjoerg case DK_LINE:
21467330f729Sjoerg return parseDirectiveLine();
21477330f729Sjoerg case DK_LOC:
21487330f729Sjoerg return parseDirectiveLoc();
21497330f729Sjoerg case DK_STABS:
21507330f729Sjoerg return parseDirectiveStabs();
21517330f729Sjoerg case DK_CV_FILE:
21527330f729Sjoerg return parseDirectiveCVFile();
21537330f729Sjoerg case DK_CV_FUNC_ID:
21547330f729Sjoerg return parseDirectiveCVFuncId();
21557330f729Sjoerg case DK_CV_INLINE_SITE_ID:
21567330f729Sjoerg return parseDirectiveCVInlineSiteId();
21577330f729Sjoerg case DK_CV_LOC:
21587330f729Sjoerg return parseDirectiveCVLoc();
21597330f729Sjoerg case DK_CV_LINETABLE:
21607330f729Sjoerg return parseDirectiveCVLinetable();
21617330f729Sjoerg case DK_CV_INLINE_LINETABLE:
21627330f729Sjoerg return parseDirectiveCVInlineLinetable();
21637330f729Sjoerg case DK_CV_DEF_RANGE:
21647330f729Sjoerg return parseDirectiveCVDefRange();
21657330f729Sjoerg case DK_CV_STRING:
21667330f729Sjoerg return parseDirectiveCVString();
21677330f729Sjoerg case DK_CV_STRINGTABLE:
21687330f729Sjoerg return parseDirectiveCVStringTable();
21697330f729Sjoerg case DK_CV_FILECHECKSUMS:
21707330f729Sjoerg return parseDirectiveCVFileChecksums();
21717330f729Sjoerg case DK_CV_FILECHECKSUM_OFFSET:
21727330f729Sjoerg return parseDirectiveCVFileChecksumOffset();
21737330f729Sjoerg case DK_CV_FPO_DATA:
21747330f729Sjoerg return parseDirectiveCVFPOData();
21757330f729Sjoerg case DK_CFI_SECTIONS:
21767330f729Sjoerg return parseDirectiveCFISections();
21777330f729Sjoerg case DK_CFI_STARTPROC:
21787330f729Sjoerg return parseDirectiveCFIStartProc();
21797330f729Sjoerg case DK_CFI_ENDPROC:
21807330f729Sjoerg return parseDirectiveCFIEndProc();
21817330f729Sjoerg case DK_CFI_DEF_CFA:
21827330f729Sjoerg return parseDirectiveCFIDefCfa(IDLoc);
21837330f729Sjoerg case DK_CFI_DEF_CFA_OFFSET:
21847330f729Sjoerg return parseDirectiveCFIDefCfaOffset();
21857330f729Sjoerg case DK_CFI_ADJUST_CFA_OFFSET:
21867330f729Sjoerg return parseDirectiveCFIAdjustCfaOffset();
21877330f729Sjoerg case DK_CFI_DEF_CFA_REGISTER:
21887330f729Sjoerg return parseDirectiveCFIDefCfaRegister(IDLoc);
21897330f729Sjoerg case DK_CFI_OFFSET:
21907330f729Sjoerg return parseDirectiveCFIOffset(IDLoc);
21917330f729Sjoerg case DK_CFI_REL_OFFSET:
21927330f729Sjoerg return parseDirectiveCFIRelOffset(IDLoc);
21937330f729Sjoerg case DK_CFI_PERSONALITY:
21947330f729Sjoerg return parseDirectiveCFIPersonalityOrLsda(true);
21957330f729Sjoerg case DK_CFI_LSDA:
21967330f729Sjoerg return parseDirectiveCFIPersonalityOrLsda(false);
21977330f729Sjoerg case DK_CFI_REMEMBER_STATE:
21987330f729Sjoerg return parseDirectiveCFIRememberState();
21997330f729Sjoerg case DK_CFI_RESTORE_STATE:
22007330f729Sjoerg return parseDirectiveCFIRestoreState();
22017330f729Sjoerg case DK_CFI_SAME_VALUE:
22027330f729Sjoerg return parseDirectiveCFISameValue(IDLoc);
22037330f729Sjoerg case DK_CFI_RESTORE:
22047330f729Sjoerg return parseDirectiveCFIRestore(IDLoc);
22057330f729Sjoerg case DK_CFI_ESCAPE:
22067330f729Sjoerg return parseDirectiveCFIEscape();
22077330f729Sjoerg case DK_CFI_RETURN_COLUMN:
22087330f729Sjoerg return parseDirectiveCFIReturnColumn(IDLoc);
22097330f729Sjoerg case DK_CFI_SIGNAL_FRAME:
22107330f729Sjoerg return parseDirectiveCFISignalFrame();
22117330f729Sjoerg case DK_CFI_UNDEFINED:
22127330f729Sjoerg return parseDirectiveCFIUndefined(IDLoc);
22137330f729Sjoerg case DK_CFI_REGISTER:
22147330f729Sjoerg return parseDirectiveCFIRegister(IDLoc);
22157330f729Sjoerg case DK_CFI_WINDOW_SAVE:
22167330f729Sjoerg return parseDirectiveCFIWindowSave();
22177330f729Sjoerg case DK_MACROS_ON:
22187330f729Sjoerg case DK_MACROS_OFF:
22197330f729Sjoerg return parseDirectiveMacrosOnOff(IDVal);
22207330f729Sjoerg case DK_MACRO:
22217330f729Sjoerg return parseDirectiveMacro(IDLoc);
22227330f729Sjoerg case DK_ALTMACRO:
22237330f729Sjoerg case DK_NOALTMACRO:
22247330f729Sjoerg return parseDirectiveAltmacro(IDVal);
22257330f729Sjoerg case DK_EXITM:
22267330f729Sjoerg return parseDirectiveExitMacro(IDVal);
22277330f729Sjoerg case DK_ENDM:
22287330f729Sjoerg case DK_ENDMACRO:
22297330f729Sjoerg return parseDirectiveEndMacro(IDVal);
22307330f729Sjoerg case DK_PURGEM:
22317330f729Sjoerg return parseDirectivePurgeMacro(IDLoc);
22327330f729Sjoerg case DK_END:
22337330f729Sjoerg return parseDirectiveEnd(IDLoc);
22347330f729Sjoerg case DK_ERR:
22357330f729Sjoerg return parseDirectiveError(IDLoc, false);
22367330f729Sjoerg case DK_ERROR:
22377330f729Sjoerg return parseDirectiveError(IDLoc, true);
22387330f729Sjoerg case DK_WARNING:
22397330f729Sjoerg return parseDirectiveWarning(IDLoc);
22407330f729Sjoerg case DK_RELOC:
22417330f729Sjoerg return parseDirectiveReloc(IDLoc);
22427330f729Sjoerg case DK_DCB:
22437330f729Sjoerg case DK_DCB_W:
22447330f729Sjoerg return parseDirectiveDCB(IDVal, 2);
22457330f729Sjoerg case DK_DCB_B:
22467330f729Sjoerg return parseDirectiveDCB(IDVal, 1);
22477330f729Sjoerg case DK_DCB_D:
22487330f729Sjoerg return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble());
22497330f729Sjoerg case DK_DCB_L:
22507330f729Sjoerg return parseDirectiveDCB(IDVal, 4);
22517330f729Sjoerg case DK_DCB_S:
22527330f729Sjoerg return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle());
22537330f729Sjoerg case DK_DC_X:
22547330f729Sjoerg case DK_DCB_X:
22557330f729Sjoerg return TokError(Twine(IDVal) +
22567330f729Sjoerg " not currently supported for this target");
22577330f729Sjoerg case DK_DS:
22587330f729Sjoerg case DK_DS_W:
22597330f729Sjoerg return parseDirectiveDS(IDVal, 2);
22607330f729Sjoerg case DK_DS_B:
22617330f729Sjoerg return parseDirectiveDS(IDVal, 1);
22627330f729Sjoerg case DK_DS_D:
22637330f729Sjoerg return parseDirectiveDS(IDVal, 8);
22647330f729Sjoerg case DK_DS_L:
22657330f729Sjoerg case DK_DS_S:
22667330f729Sjoerg return parseDirectiveDS(IDVal, 4);
22677330f729Sjoerg case DK_DS_P:
22687330f729Sjoerg case DK_DS_X:
22697330f729Sjoerg return parseDirectiveDS(IDVal, 12);
22707330f729Sjoerg case DK_PRINT:
22717330f729Sjoerg return parseDirectivePrint(IDLoc);
22727330f729Sjoerg case DK_ADDRSIG:
22737330f729Sjoerg return parseDirectiveAddrsig();
22747330f729Sjoerg case DK_ADDRSIG_SYM:
22757330f729Sjoerg return parseDirectiveAddrsigSym();
2276*82d56013Sjoerg case DK_PSEUDO_PROBE:
2277*82d56013Sjoerg return parseDirectivePseudoProbe();
2278*82d56013Sjoerg case DK_LTO_DISCARD:
2279*82d56013Sjoerg return parseDirectiveLTODiscard();
22807330f729Sjoerg }
22817330f729Sjoerg
22827330f729Sjoerg return Error(IDLoc, "unknown directive");
22837330f729Sjoerg }
22847330f729Sjoerg
22857330f729Sjoerg // __asm _emit or __asm __emit
2286*82d56013Sjoerg if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
22877330f729Sjoerg IDVal == "_EMIT" || IDVal == "__EMIT"))
22887330f729Sjoerg return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
22897330f729Sjoerg
22907330f729Sjoerg // __asm align
2291*82d56013Sjoerg if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
22927330f729Sjoerg return parseDirectiveMSAlign(IDLoc, Info);
22937330f729Sjoerg
2294*82d56013Sjoerg if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
22957330f729Sjoerg Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
22967330f729Sjoerg if (checkForValidSection())
22977330f729Sjoerg return true;
22987330f729Sjoerg
2299*82d56013Sjoerg return parseAndMatchAndEmitTargetInstruction(Info, IDVal, ID, IDLoc);
2300*82d56013Sjoerg }
2301*82d56013Sjoerg
parseAndMatchAndEmitTargetInstruction(ParseStatementInfo & Info,StringRef IDVal,AsmToken ID,SMLoc IDLoc)2302*82d56013Sjoerg bool AsmParser::parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,
2303*82d56013Sjoerg StringRef IDVal,
2304*82d56013Sjoerg AsmToken ID,
2305*82d56013Sjoerg SMLoc IDLoc) {
23067330f729Sjoerg // Canonicalize the opcode to lower case.
23077330f729Sjoerg std::string OpcodeStr = IDVal.lower();
23087330f729Sjoerg ParseInstructionInfo IInfo(Info.AsmRewrites);
23097330f729Sjoerg bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
23107330f729Sjoerg Info.ParsedOperands);
23117330f729Sjoerg Info.ParseError = ParseHadError;
23127330f729Sjoerg
23137330f729Sjoerg // Dump the parsed representation, if requested.
23147330f729Sjoerg if (getShowParsedOperands()) {
23157330f729Sjoerg SmallString<256> Str;
23167330f729Sjoerg raw_svector_ostream OS(Str);
23177330f729Sjoerg OS << "parsed instruction: [";
23187330f729Sjoerg for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
23197330f729Sjoerg if (i != 0)
23207330f729Sjoerg OS << ", ";
23217330f729Sjoerg Info.ParsedOperands[i]->print(OS);
23227330f729Sjoerg }
23237330f729Sjoerg OS << "]";
23247330f729Sjoerg
23257330f729Sjoerg printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
23267330f729Sjoerg }
23277330f729Sjoerg
23287330f729Sjoerg // Fail even if ParseInstruction erroneously returns false.
23297330f729Sjoerg if (hasPendingError() || ParseHadError)
23307330f729Sjoerg return true;
23317330f729Sjoerg
23327330f729Sjoerg // If we are generating dwarf for the current section then generate a .loc
23337330f729Sjoerg // directive for the instruction.
23347330f729Sjoerg if (!ParseHadError && enabledGenDwarfForAssembly() &&
23357330f729Sjoerg getContext().getGenDwarfSectionSyms().count(
23367330f729Sjoerg getStreamer().getCurrentSectionOnly())) {
23377330f729Sjoerg unsigned Line;
23387330f729Sjoerg if (ActiveMacros.empty())
23397330f729Sjoerg Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
23407330f729Sjoerg else
23417330f729Sjoerg Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
23427330f729Sjoerg ActiveMacros.front()->ExitBuffer);
23437330f729Sjoerg
23447330f729Sjoerg // If we previously parsed a cpp hash file line comment then make sure the
23457330f729Sjoerg // current Dwarf File is for the CppHashFilename if not then emit the
23467330f729Sjoerg // Dwarf File table for it and adjust the line number for the .loc.
23477330f729Sjoerg if (!CppHashInfo.Filename.empty()) {
2348*82d56013Sjoerg unsigned FileNumber = getStreamer().emitDwarfFileDirective(
23497330f729Sjoerg 0, StringRef(), CppHashInfo.Filename);
23507330f729Sjoerg getContext().setGenDwarfFileNumber(FileNumber);
23517330f729Sjoerg
23527330f729Sjoerg unsigned CppHashLocLineNo =
23537330f729Sjoerg SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
23547330f729Sjoerg Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
23557330f729Sjoerg }
23567330f729Sjoerg
2357*82d56013Sjoerg getStreamer().emitDwarfLocDirective(
23587330f729Sjoerg getContext().getGenDwarfFileNumber(), Line, 0,
23597330f729Sjoerg DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
23607330f729Sjoerg StringRef());
23617330f729Sjoerg }
23627330f729Sjoerg
23637330f729Sjoerg // If parsing succeeded, match the instruction.
23647330f729Sjoerg if (!ParseHadError) {
23657330f729Sjoerg uint64_t ErrorInfo;
23667330f729Sjoerg if (getTargetParser().MatchAndEmitInstruction(
23677330f729Sjoerg IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
2368*82d56013Sjoerg getTargetParser().isParsingMSInlineAsm()))
23697330f729Sjoerg return true;
23707330f729Sjoerg }
23717330f729Sjoerg return false;
23727330f729Sjoerg }
23737330f729Sjoerg
23747330f729Sjoerg // Parse and erase curly braces marking block start/end
23757330f729Sjoerg bool
parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> & AsmStrRewrites)23767330f729Sjoerg AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
23777330f729Sjoerg // Identify curly brace marking block start/end
23787330f729Sjoerg if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
23797330f729Sjoerg return false;
23807330f729Sjoerg
23817330f729Sjoerg SMLoc StartLoc = Lexer.getLoc();
23827330f729Sjoerg Lex(); // Eat the brace
23837330f729Sjoerg if (Lexer.is(AsmToken::EndOfStatement))
23847330f729Sjoerg Lex(); // Eat EndOfStatement following the brace
23857330f729Sjoerg
23867330f729Sjoerg // Erase the block start/end brace from the output asm string
23877330f729Sjoerg AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
23887330f729Sjoerg StartLoc.getPointer());
23897330f729Sjoerg return true;
23907330f729Sjoerg }
23917330f729Sjoerg
23927330f729Sjoerg /// parseCppHashLineFilenameComment as this:
23937330f729Sjoerg /// ::= # number "filename"
parseCppHashLineFilenameComment(SMLoc L,bool SaveLocInfo)2394*82d56013Sjoerg bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) {
23957330f729Sjoerg Lex(); // Eat the hash token.
23967330f729Sjoerg // Lexer only ever emits HashDirective if it fully formed if it's
23977330f729Sjoerg // done the checking already so this is an internal error.
23987330f729Sjoerg assert(getTok().is(AsmToken::Integer) &&
23997330f729Sjoerg "Lexing Cpp line comment: Expected Integer");
24007330f729Sjoerg int64_t LineNumber = getTok().getIntVal();
24017330f729Sjoerg Lex();
24027330f729Sjoerg assert(getTok().is(AsmToken::String) &&
24037330f729Sjoerg "Lexing Cpp line comment: Expected String");
24047330f729Sjoerg StringRef Filename = getTok().getString();
24057330f729Sjoerg Lex();
24067330f729Sjoerg
2407*82d56013Sjoerg if (!SaveLocInfo)
2408*82d56013Sjoerg return false;
2409*82d56013Sjoerg
24107330f729Sjoerg // Get rid of the enclosing quotes.
24117330f729Sjoerg Filename = Filename.substr(1, Filename.size() - 2);
24127330f729Sjoerg
24137330f729Sjoerg // Save the SMLoc, Filename and LineNumber for later use by diagnostics
24147330f729Sjoerg // and possibly DWARF file info.
24157330f729Sjoerg CppHashInfo.Loc = L;
24167330f729Sjoerg CppHashInfo.Filename = Filename;
24177330f729Sjoerg CppHashInfo.LineNumber = LineNumber;
24187330f729Sjoerg CppHashInfo.Buf = CurBuffer;
24197330f729Sjoerg if (FirstCppHashFilename.empty())
24207330f729Sjoerg FirstCppHashFilename = Filename;
24217330f729Sjoerg return false;
24227330f729Sjoerg }
24237330f729Sjoerg
24247330f729Sjoerg /// will use the last parsed cpp hash line filename comment
24257330f729Sjoerg /// for the Filename and LineNo if any in the diagnostic.
DiagHandler(const SMDiagnostic & Diag,void * Context)24267330f729Sjoerg void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
2427*82d56013Sjoerg auto *Parser = static_cast<AsmParser *>(Context);
24287330f729Sjoerg raw_ostream &OS = errs();
24297330f729Sjoerg
24307330f729Sjoerg const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
24317330f729Sjoerg SMLoc DiagLoc = Diag.getLoc();
24327330f729Sjoerg unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
24337330f729Sjoerg unsigned CppHashBuf =
24347330f729Sjoerg Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
24357330f729Sjoerg
24367330f729Sjoerg // Like SourceMgr::printMessage() we need to print the include stack if any
24377330f729Sjoerg // before printing the message.
24387330f729Sjoerg unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
24397330f729Sjoerg if (!Parser->SavedDiagHandler && DiagCurBuffer &&
24407330f729Sjoerg DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
24417330f729Sjoerg SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
24427330f729Sjoerg DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
24437330f729Sjoerg }
24447330f729Sjoerg
24457330f729Sjoerg // If we have not parsed a cpp hash line filename comment or the source
24467330f729Sjoerg // manager changed or buffer changed (like in a nested include) then just
24477330f729Sjoerg // print the normal diagnostic using its Filename and LineNo.
2448*82d56013Sjoerg if (!Parser->CppHashInfo.LineNumber || DiagBuf != CppHashBuf) {
24497330f729Sjoerg if (Parser->SavedDiagHandler)
24507330f729Sjoerg Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
24517330f729Sjoerg else
2452*82d56013Sjoerg Parser->getContext().diagnose(Diag);
24537330f729Sjoerg return;
24547330f729Sjoerg }
24557330f729Sjoerg
24567330f729Sjoerg // Use the CppHashFilename and calculate a line number based on the
24577330f729Sjoerg // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
24587330f729Sjoerg // for the diagnostic.
2459*82d56013Sjoerg const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
24607330f729Sjoerg
24617330f729Sjoerg int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
24627330f729Sjoerg int CppHashLocLineNo =
24637330f729Sjoerg Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
24647330f729Sjoerg int LineNo =
24657330f729Sjoerg Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
24667330f729Sjoerg
24677330f729Sjoerg SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
24687330f729Sjoerg Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
24697330f729Sjoerg Diag.getLineContents(), Diag.getRanges());
24707330f729Sjoerg
24717330f729Sjoerg if (Parser->SavedDiagHandler)
2472*82d56013Sjoerg Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
24737330f729Sjoerg else
2474*82d56013Sjoerg Parser->getContext().diagnose(NewDiag);
24757330f729Sjoerg }
24767330f729Sjoerg
24777330f729Sjoerg // FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The
24787330f729Sjoerg // difference being that that function accepts '@' as part of identifiers and
24797330f729Sjoerg // we can't do that. AsmLexer.cpp should probably be changed to handle
24807330f729Sjoerg // '@' as a special case when needed.
isIdentifierChar(char c)24817330f729Sjoerg static bool isIdentifierChar(char c) {
24827330f729Sjoerg return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||
24837330f729Sjoerg c == '.';
24847330f729Sjoerg }
24857330f729Sjoerg
expandMacro(raw_svector_ostream & OS,StringRef Body,ArrayRef<MCAsmMacroParameter> Parameters,ArrayRef<MCAsmMacroArgument> A,bool EnableAtPseudoVariable,SMLoc L)24867330f729Sjoerg bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
24877330f729Sjoerg ArrayRef<MCAsmMacroParameter> Parameters,
24887330f729Sjoerg ArrayRef<MCAsmMacroArgument> A,
24897330f729Sjoerg bool EnableAtPseudoVariable, SMLoc L) {
24907330f729Sjoerg unsigned NParameters = Parameters.size();
24917330f729Sjoerg bool HasVararg = NParameters ? Parameters.back().Vararg : false;
24927330f729Sjoerg if ((!IsDarwin || NParameters != 0) && NParameters != A.size())
24937330f729Sjoerg return Error(L, "Wrong number of arguments");
24947330f729Sjoerg
24957330f729Sjoerg // A macro without parameters is handled differently on Darwin:
24967330f729Sjoerg // gas accepts no arguments and does no substitutions
24977330f729Sjoerg while (!Body.empty()) {
24987330f729Sjoerg // Scan for the next substitution.
24997330f729Sjoerg std::size_t End = Body.size(), Pos = 0;
25007330f729Sjoerg for (; Pos != End; ++Pos) {
25017330f729Sjoerg // Check for a substitution or escape.
25027330f729Sjoerg if (IsDarwin && !NParameters) {
25037330f729Sjoerg // This macro has no parameters, look for $0, $1, etc.
25047330f729Sjoerg if (Body[Pos] != '$' || Pos + 1 == End)
25057330f729Sjoerg continue;
25067330f729Sjoerg
25077330f729Sjoerg char Next = Body[Pos + 1];
25087330f729Sjoerg if (Next == '$' || Next == 'n' ||
25097330f729Sjoerg isdigit(static_cast<unsigned char>(Next)))
25107330f729Sjoerg break;
25117330f729Sjoerg } else {
25127330f729Sjoerg // This macro has parameters, look for \foo, \bar, etc.
25137330f729Sjoerg if (Body[Pos] == '\\' && Pos + 1 != End)
25147330f729Sjoerg break;
25157330f729Sjoerg }
25167330f729Sjoerg }
25177330f729Sjoerg
25187330f729Sjoerg // Add the prefix.
25197330f729Sjoerg OS << Body.slice(0, Pos);
25207330f729Sjoerg
25217330f729Sjoerg // Check if we reached the end.
25227330f729Sjoerg if (Pos == End)
25237330f729Sjoerg break;
25247330f729Sjoerg
25257330f729Sjoerg if (IsDarwin && !NParameters) {
25267330f729Sjoerg switch (Body[Pos + 1]) {
25277330f729Sjoerg // $$ => $
25287330f729Sjoerg case '$':
25297330f729Sjoerg OS << '$';
25307330f729Sjoerg break;
25317330f729Sjoerg
25327330f729Sjoerg // $n => number of arguments
25337330f729Sjoerg case 'n':
25347330f729Sjoerg OS << A.size();
25357330f729Sjoerg break;
25367330f729Sjoerg
25377330f729Sjoerg // $[0-9] => argument
25387330f729Sjoerg default: {
25397330f729Sjoerg // Missing arguments are ignored.
25407330f729Sjoerg unsigned Index = Body[Pos + 1] - '0';
25417330f729Sjoerg if (Index >= A.size())
25427330f729Sjoerg break;
25437330f729Sjoerg
25447330f729Sjoerg // Otherwise substitute with the token values, with spaces eliminated.
25457330f729Sjoerg for (const AsmToken &Token : A[Index])
25467330f729Sjoerg OS << Token.getString();
25477330f729Sjoerg break;
25487330f729Sjoerg }
25497330f729Sjoerg }
25507330f729Sjoerg Pos += 2;
25517330f729Sjoerg } else {
25527330f729Sjoerg unsigned I = Pos + 1;
25537330f729Sjoerg
25547330f729Sjoerg // Check for the \@ pseudo-variable.
25557330f729Sjoerg if (EnableAtPseudoVariable && Body[I] == '@' && I + 1 != End)
25567330f729Sjoerg ++I;
25577330f729Sjoerg else
25587330f729Sjoerg while (isIdentifierChar(Body[I]) && I + 1 != End)
25597330f729Sjoerg ++I;
25607330f729Sjoerg
25617330f729Sjoerg const char *Begin = Body.data() + Pos + 1;
25627330f729Sjoerg StringRef Argument(Begin, I - (Pos + 1));
25637330f729Sjoerg unsigned Index = 0;
25647330f729Sjoerg
25657330f729Sjoerg if (Argument == "@") {
25667330f729Sjoerg OS << NumOfMacroInstantiations;
25677330f729Sjoerg Pos += 2;
25687330f729Sjoerg } else {
25697330f729Sjoerg for (; Index < NParameters; ++Index)
25707330f729Sjoerg if (Parameters[Index].Name == Argument)
25717330f729Sjoerg break;
25727330f729Sjoerg
25737330f729Sjoerg if (Index == NParameters) {
25747330f729Sjoerg if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
25757330f729Sjoerg Pos += 3;
25767330f729Sjoerg else {
25777330f729Sjoerg OS << '\\' << Argument;
25787330f729Sjoerg Pos = I;
25797330f729Sjoerg }
25807330f729Sjoerg } else {
25817330f729Sjoerg bool VarargParameter = HasVararg && Index == (NParameters - 1);
25827330f729Sjoerg for (const AsmToken &Token : A[Index])
25837330f729Sjoerg // For altmacro mode, you can write '%expr'.
25847330f729Sjoerg // The prefix '%' evaluates the expression 'expr'
25857330f729Sjoerg // and uses the result as a string (e.g. replace %(1+2) with the
25867330f729Sjoerg // string "3").
25877330f729Sjoerg // Here, we identify the integer token which is the result of the
25887330f729Sjoerg // absolute expression evaluation and replace it with its string
25897330f729Sjoerg // representation.
25907330f729Sjoerg if (AltMacroMode && Token.getString().front() == '%' &&
25917330f729Sjoerg Token.is(AsmToken::Integer))
25927330f729Sjoerg // Emit an integer value to the buffer.
25937330f729Sjoerg OS << Token.getIntVal();
25947330f729Sjoerg // Only Token that was validated as a string and begins with '<'
25957330f729Sjoerg // is considered altMacroString!!!
25967330f729Sjoerg else if (AltMacroMode && Token.getString().front() == '<' &&
25977330f729Sjoerg Token.is(AsmToken::String)) {
2598*82d56013Sjoerg OS << angleBracketString(Token.getStringContents());
25997330f729Sjoerg }
26007330f729Sjoerg // We expect no quotes around the string's contents when
26017330f729Sjoerg // parsing for varargs.
26027330f729Sjoerg else if (Token.isNot(AsmToken::String) || VarargParameter)
26037330f729Sjoerg OS << Token.getString();
26047330f729Sjoerg else
26057330f729Sjoerg OS << Token.getStringContents();
26067330f729Sjoerg
26077330f729Sjoerg Pos += 1 + Argument.size();
26087330f729Sjoerg }
26097330f729Sjoerg }
26107330f729Sjoerg }
26117330f729Sjoerg // Update the scan point.
26127330f729Sjoerg Body = Body.substr(Pos);
26137330f729Sjoerg }
26147330f729Sjoerg
26157330f729Sjoerg return false;
26167330f729Sjoerg }
26177330f729Sjoerg
isOperator(AsmToken::TokenKind kind)26187330f729Sjoerg static bool isOperator(AsmToken::TokenKind kind) {
26197330f729Sjoerg switch (kind) {
26207330f729Sjoerg default:
26217330f729Sjoerg return false;
26227330f729Sjoerg case AsmToken::Plus:
26237330f729Sjoerg case AsmToken::Minus:
26247330f729Sjoerg case AsmToken::Tilde:
26257330f729Sjoerg case AsmToken::Slash:
26267330f729Sjoerg case AsmToken::Star:
26277330f729Sjoerg case AsmToken::Dot:
26287330f729Sjoerg case AsmToken::Equal:
26297330f729Sjoerg case AsmToken::EqualEqual:
26307330f729Sjoerg case AsmToken::Pipe:
26317330f729Sjoerg case AsmToken::PipePipe:
26327330f729Sjoerg case AsmToken::Caret:
26337330f729Sjoerg case AsmToken::Amp:
26347330f729Sjoerg case AsmToken::AmpAmp:
26357330f729Sjoerg case AsmToken::Exclaim:
26367330f729Sjoerg case AsmToken::ExclaimEqual:
26377330f729Sjoerg case AsmToken::Less:
26387330f729Sjoerg case AsmToken::LessEqual:
26397330f729Sjoerg case AsmToken::LessLess:
26407330f729Sjoerg case AsmToken::LessGreater:
26417330f729Sjoerg case AsmToken::Greater:
26427330f729Sjoerg case AsmToken::GreaterEqual:
26437330f729Sjoerg case AsmToken::GreaterGreater:
26447330f729Sjoerg return true;
26457330f729Sjoerg }
26467330f729Sjoerg }
26477330f729Sjoerg
26487330f729Sjoerg namespace {
26497330f729Sjoerg
26507330f729Sjoerg class AsmLexerSkipSpaceRAII {
26517330f729Sjoerg public:
AsmLexerSkipSpaceRAII(AsmLexer & Lexer,bool SkipSpace)26527330f729Sjoerg AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
26537330f729Sjoerg Lexer.setSkipSpace(SkipSpace);
26547330f729Sjoerg }
26557330f729Sjoerg
~AsmLexerSkipSpaceRAII()26567330f729Sjoerg ~AsmLexerSkipSpaceRAII() {
26577330f729Sjoerg Lexer.setSkipSpace(true);
26587330f729Sjoerg }
26597330f729Sjoerg
26607330f729Sjoerg private:
26617330f729Sjoerg AsmLexer &Lexer;
26627330f729Sjoerg };
26637330f729Sjoerg
26647330f729Sjoerg } // end anonymous namespace
26657330f729Sjoerg
parseMacroArgument(MCAsmMacroArgument & MA,bool Vararg)26667330f729Sjoerg bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
26677330f729Sjoerg
26687330f729Sjoerg if (Vararg) {
26697330f729Sjoerg if (Lexer.isNot(AsmToken::EndOfStatement)) {
26707330f729Sjoerg StringRef Str = parseStringToEndOfStatement();
26717330f729Sjoerg MA.emplace_back(AsmToken::String, Str);
26727330f729Sjoerg }
26737330f729Sjoerg return false;
26747330f729Sjoerg }
26757330f729Sjoerg
26767330f729Sjoerg unsigned ParenLevel = 0;
26777330f729Sjoerg
26787330f729Sjoerg // Darwin doesn't use spaces to delmit arguments.
26797330f729Sjoerg AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
26807330f729Sjoerg
26817330f729Sjoerg bool SpaceEaten;
26827330f729Sjoerg
26837330f729Sjoerg while (true) {
26847330f729Sjoerg SpaceEaten = false;
26857330f729Sjoerg if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
26867330f729Sjoerg return TokError("unexpected token in macro instantiation");
26877330f729Sjoerg
26887330f729Sjoerg if (ParenLevel == 0) {
26897330f729Sjoerg
26907330f729Sjoerg if (Lexer.is(AsmToken::Comma))
26917330f729Sjoerg break;
26927330f729Sjoerg
26937330f729Sjoerg if (Lexer.is(AsmToken::Space)) {
26947330f729Sjoerg SpaceEaten = true;
26957330f729Sjoerg Lexer.Lex(); // Eat spaces
26967330f729Sjoerg }
26977330f729Sjoerg
26987330f729Sjoerg // Spaces can delimit parameters, but could also be part an expression.
26997330f729Sjoerg // If the token after a space is an operator, add the token and the next
27007330f729Sjoerg // one into this argument
27017330f729Sjoerg if (!IsDarwin) {
27027330f729Sjoerg if (isOperator(Lexer.getKind())) {
27037330f729Sjoerg MA.push_back(getTok());
27047330f729Sjoerg Lexer.Lex();
27057330f729Sjoerg
27067330f729Sjoerg // Whitespace after an operator can be ignored.
27077330f729Sjoerg if (Lexer.is(AsmToken::Space))
27087330f729Sjoerg Lexer.Lex();
27097330f729Sjoerg
27107330f729Sjoerg continue;
27117330f729Sjoerg }
27127330f729Sjoerg }
27137330f729Sjoerg if (SpaceEaten)
27147330f729Sjoerg break;
27157330f729Sjoerg }
27167330f729Sjoerg
27177330f729Sjoerg // handleMacroEntry relies on not advancing the lexer here
27187330f729Sjoerg // to be able to fill in the remaining default parameter values
27197330f729Sjoerg if (Lexer.is(AsmToken::EndOfStatement))
27207330f729Sjoerg break;
27217330f729Sjoerg
27227330f729Sjoerg // Adjust the current parentheses level.
27237330f729Sjoerg if (Lexer.is(AsmToken::LParen))
27247330f729Sjoerg ++ParenLevel;
27257330f729Sjoerg else if (Lexer.is(AsmToken::RParen) && ParenLevel)
27267330f729Sjoerg --ParenLevel;
27277330f729Sjoerg
27287330f729Sjoerg // Append the token to the current argument list.
27297330f729Sjoerg MA.push_back(getTok());
27307330f729Sjoerg Lexer.Lex();
27317330f729Sjoerg }
27327330f729Sjoerg
27337330f729Sjoerg if (ParenLevel != 0)
27347330f729Sjoerg return TokError("unbalanced parentheses in macro argument");
27357330f729Sjoerg return false;
27367330f729Sjoerg }
27377330f729Sjoerg
27387330f729Sjoerg // Parse the macro instantiation arguments.
parseMacroArguments(const MCAsmMacro * M,MCAsmMacroArguments & A)27397330f729Sjoerg bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
27407330f729Sjoerg MCAsmMacroArguments &A) {
27417330f729Sjoerg const unsigned NParameters = M ? M->Parameters.size() : 0;
27427330f729Sjoerg bool NamedParametersFound = false;
27437330f729Sjoerg SmallVector<SMLoc, 4> FALocs;
27447330f729Sjoerg
27457330f729Sjoerg A.resize(NParameters);
27467330f729Sjoerg FALocs.resize(NParameters);
27477330f729Sjoerg
27487330f729Sjoerg // Parse two kinds of macro invocations:
27497330f729Sjoerg // - macros defined without any parameters accept an arbitrary number of them
27507330f729Sjoerg // - macros defined with parameters accept at most that many of them
27517330f729Sjoerg bool HasVararg = NParameters ? M->Parameters.back().Vararg : false;
27527330f729Sjoerg for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
27537330f729Sjoerg ++Parameter) {
27547330f729Sjoerg SMLoc IDLoc = Lexer.getLoc();
27557330f729Sjoerg MCAsmMacroParameter FA;
27567330f729Sjoerg
27577330f729Sjoerg if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
27587330f729Sjoerg if (parseIdentifier(FA.Name))
27597330f729Sjoerg return Error(IDLoc, "invalid argument identifier for formal argument");
27607330f729Sjoerg
27617330f729Sjoerg if (Lexer.isNot(AsmToken::Equal))
27627330f729Sjoerg return TokError("expected '=' after formal parameter identifier");
27637330f729Sjoerg
27647330f729Sjoerg Lex();
27657330f729Sjoerg
27667330f729Sjoerg NamedParametersFound = true;
27677330f729Sjoerg }
27687330f729Sjoerg bool Vararg = HasVararg && Parameter == (NParameters - 1);
27697330f729Sjoerg
27707330f729Sjoerg if (NamedParametersFound && FA.Name.empty())
27717330f729Sjoerg return Error(IDLoc, "cannot mix positional and keyword arguments");
27727330f729Sjoerg
27737330f729Sjoerg SMLoc StrLoc = Lexer.getLoc();
27747330f729Sjoerg SMLoc EndLoc;
27757330f729Sjoerg if (AltMacroMode && Lexer.is(AsmToken::Percent)) {
27767330f729Sjoerg const MCExpr *AbsoluteExp;
27777330f729Sjoerg int64_t Value;
27787330f729Sjoerg /// Eat '%'
27797330f729Sjoerg Lex();
27807330f729Sjoerg if (parseExpression(AbsoluteExp, EndLoc))
27817330f729Sjoerg return false;
27827330f729Sjoerg if (!AbsoluteExp->evaluateAsAbsolute(Value,
27837330f729Sjoerg getStreamer().getAssemblerPtr()))
27847330f729Sjoerg return Error(StrLoc, "expected absolute expression");
27857330f729Sjoerg const char *StrChar = StrLoc.getPointer();
27867330f729Sjoerg const char *EndChar = EndLoc.getPointer();
27877330f729Sjoerg AsmToken newToken(AsmToken::Integer,
27887330f729Sjoerg StringRef(StrChar, EndChar - StrChar), Value);
27897330f729Sjoerg FA.Value.push_back(newToken);
27907330f729Sjoerg } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
2791*82d56013Sjoerg isAngleBracketString(StrLoc, EndLoc)) {
27927330f729Sjoerg const char *StrChar = StrLoc.getPointer();
27937330f729Sjoerg const char *EndChar = EndLoc.getPointer();
27947330f729Sjoerg jumpToLoc(EndLoc, CurBuffer);
27957330f729Sjoerg /// Eat from '<' to '>'
27967330f729Sjoerg Lex();
27977330f729Sjoerg AsmToken newToken(AsmToken::String,
27987330f729Sjoerg StringRef(StrChar, EndChar - StrChar));
27997330f729Sjoerg FA.Value.push_back(newToken);
28007330f729Sjoerg } else if(parseMacroArgument(FA.Value, Vararg))
28017330f729Sjoerg return true;
28027330f729Sjoerg
28037330f729Sjoerg unsigned PI = Parameter;
28047330f729Sjoerg if (!FA.Name.empty()) {
28057330f729Sjoerg unsigned FAI = 0;
28067330f729Sjoerg for (FAI = 0; FAI < NParameters; ++FAI)
28077330f729Sjoerg if (M->Parameters[FAI].Name == FA.Name)
28087330f729Sjoerg break;
28097330f729Sjoerg
28107330f729Sjoerg if (FAI >= NParameters) {
28117330f729Sjoerg assert(M && "expected macro to be defined");
28127330f729Sjoerg return Error(IDLoc, "parameter named '" + FA.Name +
28137330f729Sjoerg "' does not exist for macro '" + M->Name + "'");
28147330f729Sjoerg }
28157330f729Sjoerg PI = FAI;
28167330f729Sjoerg }
28177330f729Sjoerg
28187330f729Sjoerg if (!FA.Value.empty()) {
28197330f729Sjoerg if (A.size() <= PI)
28207330f729Sjoerg A.resize(PI + 1);
28217330f729Sjoerg A[PI] = FA.Value;
28227330f729Sjoerg
28237330f729Sjoerg if (FALocs.size() <= PI)
28247330f729Sjoerg FALocs.resize(PI + 1);
28257330f729Sjoerg
28267330f729Sjoerg FALocs[PI] = Lexer.getLoc();
28277330f729Sjoerg }
28287330f729Sjoerg
28297330f729Sjoerg // At the end of the statement, fill in remaining arguments that have
28307330f729Sjoerg // default values. If there aren't any, then the next argument is
28317330f729Sjoerg // required but missing
28327330f729Sjoerg if (Lexer.is(AsmToken::EndOfStatement)) {
28337330f729Sjoerg bool Failure = false;
28347330f729Sjoerg for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
28357330f729Sjoerg if (A[FAI].empty()) {
28367330f729Sjoerg if (M->Parameters[FAI].Required) {
28377330f729Sjoerg Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
28387330f729Sjoerg "missing value for required parameter "
28397330f729Sjoerg "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
28407330f729Sjoerg Failure = true;
28417330f729Sjoerg }
28427330f729Sjoerg
28437330f729Sjoerg if (!M->Parameters[FAI].Value.empty())
28447330f729Sjoerg A[FAI] = M->Parameters[FAI].Value;
28457330f729Sjoerg }
28467330f729Sjoerg }
28477330f729Sjoerg return Failure;
28487330f729Sjoerg }
28497330f729Sjoerg
28507330f729Sjoerg if (Lexer.is(AsmToken::Comma))
28517330f729Sjoerg Lex();
28527330f729Sjoerg }
28537330f729Sjoerg
28547330f729Sjoerg return TokError("too many positional arguments");
28557330f729Sjoerg }
28567330f729Sjoerg
handleMacroEntry(const MCAsmMacro * M,SMLoc NameLoc)28577330f729Sjoerg bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
28587330f729Sjoerg // Arbitrarily limit macro nesting depth (default matches 'as'). We can
28597330f729Sjoerg // eliminate this, although we should protect against infinite loops.
28607330f729Sjoerg unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
28617330f729Sjoerg if (ActiveMacros.size() == MaxNestingDepth) {
28627330f729Sjoerg std::ostringstream MaxNestingDepthError;
28637330f729Sjoerg MaxNestingDepthError << "macros cannot be nested more than "
28647330f729Sjoerg << MaxNestingDepth << " levels deep."
28657330f729Sjoerg << " Use -asm-macro-max-nesting-depth to increase "
28667330f729Sjoerg "this limit.";
28677330f729Sjoerg return TokError(MaxNestingDepthError.str());
28687330f729Sjoerg }
28697330f729Sjoerg
28707330f729Sjoerg MCAsmMacroArguments A;
28717330f729Sjoerg if (parseMacroArguments(M, A))
28727330f729Sjoerg return true;
28737330f729Sjoerg
28747330f729Sjoerg // Macro instantiation is lexical, unfortunately. We construct a new buffer
28757330f729Sjoerg // to hold the macro body with substitutions.
28767330f729Sjoerg SmallString<256> Buf;
28777330f729Sjoerg StringRef Body = M->Body;
28787330f729Sjoerg raw_svector_ostream OS(Buf);
28797330f729Sjoerg
28807330f729Sjoerg if (expandMacro(OS, Body, M->Parameters, A, true, getTok().getLoc()))
28817330f729Sjoerg return true;
28827330f729Sjoerg
28837330f729Sjoerg // We include the .endmacro in the buffer as our cue to exit the macro
28847330f729Sjoerg // instantiation.
28857330f729Sjoerg OS << ".endmacro\n";
28867330f729Sjoerg
28877330f729Sjoerg std::unique_ptr<MemoryBuffer> Instantiation =
28887330f729Sjoerg MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
28897330f729Sjoerg
28907330f729Sjoerg // Create the macro instantiation object and add to the current macro
28917330f729Sjoerg // instantiation stack.
2892*82d56013Sjoerg MacroInstantiation *MI = new MacroInstantiation{
2893*82d56013Sjoerg NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
28947330f729Sjoerg ActiveMacros.push_back(MI);
28957330f729Sjoerg
28967330f729Sjoerg ++NumOfMacroInstantiations;
28977330f729Sjoerg
28987330f729Sjoerg // Jump to the macro instantiation and prime the lexer.
28997330f729Sjoerg CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
29007330f729Sjoerg Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
29017330f729Sjoerg Lex();
29027330f729Sjoerg
29037330f729Sjoerg return false;
29047330f729Sjoerg }
29057330f729Sjoerg
handleMacroExit()29067330f729Sjoerg void AsmParser::handleMacroExit() {
29077330f729Sjoerg // Jump to the EndOfStatement we should return to, and consume it.
29087330f729Sjoerg jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
29097330f729Sjoerg Lex();
29107330f729Sjoerg
29117330f729Sjoerg // Pop the instantiation entry.
29127330f729Sjoerg delete ActiveMacros.back();
29137330f729Sjoerg ActiveMacros.pop_back();
29147330f729Sjoerg }
29157330f729Sjoerg
parseAssignment(StringRef Name,bool allow_redef,bool NoDeadStrip)29167330f729Sjoerg bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
29177330f729Sjoerg bool NoDeadStrip) {
29187330f729Sjoerg MCSymbol *Sym;
29197330f729Sjoerg const MCExpr *Value;
29207330f729Sjoerg if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym,
29217330f729Sjoerg Value))
29227330f729Sjoerg return true;
29237330f729Sjoerg
29247330f729Sjoerg if (!Sym) {
29257330f729Sjoerg // In the case where we parse an expression starting with a '.', we will
29267330f729Sjoerg // not generate an error, nor will we create a symbol. In this case we
29277330f729Sjoerg // should just return out.
29287330f729Sjoerg return false;
29297330f729Sjoerg }
29307330f729Sjoerg
2931*82d56013Sjoerg if (discardLTOSymbol(Name))
2932*82d56013Sjoerg return false;
2933*82d56013Sjoerg
29347330f729Sjoerg // Do the assignment.
2935*82d56013Sjoerg Out.emitAssignment(Sym, Value);
29367330f729Sjoerg if (NoDeadStrip)
2937*82d56013Sjoerg Out.emitSymbolAttribute(Sym, MCSA_NoDeadStrip);
29387330f729Sjoerg
29397330f729Sjoerg return false;
29407330f729Sjoerg }
29417330f729Sjoerg
29427330f729Sjoerg /// parseIdentifier:
29437330f729Sjoerg /// ::= identifier
29447330f729Sjoerg /// ::= string
parseIdentifier(StringRef & Res)29457330f729Sjoerg bool AsmParser::parseIdentifier(StringRef &Res) {
29467330f729Sjoerg // The assembler has relaxed rules for accepting identifiers, in particular we
29477330f729Sjoerg // allow things like '.globl $foo' and '.def @feat.00', which would normally be
29487330f729Sjoerg // separate tokens. At this level, we have already lexed so we cannot (currently)
29497330f729Sjoerg // handle this as a context dependent token, instead we detect adjacent tokens
29507330f729Sjoerg // and return the combined identifier.
29517330f729Sjoerg if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
29527330f729Sjoerg SMLoc PrefixLoc = getLexer().getLoc();
29537330f729Sjoerg
29547330f729Sjoerg // Consume the prefix character, and check for a following identifier.
29557330f729Sjoerg
29567330f729Sjoerg AsmToken Buf[1];
29577330f729Sjoerg Lexer.peekTokens(Buf, false);
29587330f729Sjoerg
2959*82d56013Sjoerg if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer))
29607330f729Sjoerg return true;
29617330f729Sjoerg
2962*82d56013Sjoerg // We have a '$' or '@' followed by an identifier or integer token, make
2963*82d56013Sjoerg // sure they are adjacent.
29647330f729Sjoerg if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())
29657330f729Sjoerg return true;
29667330f729Sjoerg
29677330f729Sjoerg // eat $ or @
29687330f729Sjoerg Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
29697330f729Sjoerg // Construct the joined identifier and consume the token.
2970*82d56013Sjoerg Res = StringRef(PrefixLoc.getPointer(), getTok().getString().size() + 1);
29717330f729Sjoerg Lex(); // Parser Lex to maintain invariants.
29727330f729Sjoerg return false;
29737330f729Sjoerg }
29747330f729Sjoerg
29757330f729Sjoerg if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
29767330f729Sjoerg return true;
29777330f729Sjoerg
29787330f729Sjoerg Res = getTok().getIdentifier();
29797330f729Sjoerg
29807330f729Sjoerg Lex(); // Consume the identifier token.
29817330f729Sjoerg
29827330f729Sjoerg return false;
29837330f729Sjoerg }
29847330f729Sjoerg
29857330f729Sjoerg /// parseDirectiveSet:
29867330f729Sjoerg /// ::= .equ identifier ',' expression
29877330f729Sjoerg /// ::= .equiv identifier ',' expression
29887330f729Sjoerg /// ::= .set identifier ',' expression
parseDirectiveSet(StringRef IDVal,bool allow_redef)29897330f729Sjoerg bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) {
29907330f729Sjoerg StringRef Name;
2991*82d56013Sjoerg if (check(parseIdentifier(Name), "expected identifier") || parseComma() ||
2992*82d56013Sjoerg parseAssignment(Name, allow_redef, true))
2993*82d56013Sjoerg return true;
29947330f729Sjoerg return false;
29957330f729Sjoerg }
29967330f729Sjoerg
parseEscapedString(std::string & Data)29977330f729Sjoerg bool AsmParser::parseEscapedString(std::string &Data) {
29987330f729Sjoerg if (check(getTok().isNot(AsmToken::String), "expected string"))
29997330f729Sjoerg return true;
30007330f729Sjoerg
30017330f729Sjoerg Data = "";
30027330f729Sjoerg StringRef Str = getTok().getStringContents();
30037330f729Sjoerg for (unsigned i = 0, e = Str.size(); i != e; ++i) {
30047330f729Sjoerg if (Str[i] != '\\') {
30057330f729Sjoerg Data += Str[i];
30067330f729Sjoerg continue;
30077330f729Sjoerg }
30087330f729Sjoerg
30097330f729Sjoerg // Recognize escaped characters. Note that this escape semantics currently
30107330f729Sjoerg // loosely follows Darwin 'as'.
30117330f729Sjoerg ++i;
30127330f729Sjoerg if (i == e)
30137330f729Sjoerg return TokError("unexpected backslash at end of string");
30147330f729Sjoerg
30157330f729Sjoerg // Recognize hex sequences similarly to GNU 'as'.
30167330f729Sjoerg if (Str[i] == 'x' || Str[i] == 'X') {
30177330f729Sjoerg size_t length = Str.size();
30187330f729Sjoerg if (i + 1 >= length || !isHexDigit(Str[i + 1]))
30197330f729Sjoerg return TokError("invalid hexadecimal escape sequence");
30207330f729Sjoerg
30217330f729Sjoerg // Consume hex characters. GNU 'as' reads all hexadecimal characters and
30227330f729Sjoerg // then truncates to the lower 16 bits. Seems reasonable.
30237330f729Sjoerg unsigned Value = 0;
30247330f729Sjoerg while (i + 1 < length && isHexDigit(Str[i + 1]))
30257330f729Sjoerg Value = Value * 16 + hexDigitValue(Str[++i]);
30267330f729Sjoerg
30277330f729Sjoerg Data += (unsigned char)(Value & 0xFF);
30287330f729Sjoerg continue;
30297330f729Sjoerg }
30307330f729Sjoerg
30317330f729Sjoerg // Recognize octal sequences.
30327330f729Sjoerg if ((unsigned)(Str[i] - '0') <= 7) {
30337330f729Sjoerg // Consume up to three octal characters.
30347330f729Sjoerg unsigned Value = Str[i] - '0';
30357330f729Sjoerg
30367330f729Sjoerg if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
30377330f729Sjoerg ++i;
30387330f729Sjoerg Value = Value * 8 + (Str[i] - '0');
30397330f729Sjoerg
30407330f729Sjoerg if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
30417330f729Sjoerg ++i;
30427330f729Sjoerg Value = Value * 8 + (Str[i] - '0');
30437330f729Sjoerg }
30447330f729Sjoerg }
30457330f729Sjoerg
30467330f729Sjoerg if (Value > 255)
30477330f729Sjoerg return TokError("invalid octal escape sequence (out of range)");
30487330f729Sjoerg
30497330f729Sjoerg Data += (unsigned char)Value;
30507330f729Sjoerg continue;
30517330f729Sjoerg }
30527330f729Sjoerg
30537330f729Sjoerg // Otherwise recognize individual escapes.
30547330f729Sjoerg switch (Str[i]) {
30557330f729Sjoerg default:
30567330f729Sjoerg // Just reject invalid escape sequences for now.
30577330f729Sjoerg return TokError("invalid escape sequence (unrecognized character)");
30587330f729Sjoerg
30597330f729Sjoerg case 'b': Data += '\b'; break;
30607330f729Sjoerg case 'f': Data += '\f'; break;
30617330f729Sjoerg case 'n': Data += '\n'; break;
30627330f729Sjoerg case 'r': Data += '\r'; break;
30637330f729Sjoerg case 't': Data += '\t'; break;
30647330f729Sjoerg case '"': Data += '"'; break;
30657330f729Sjoerg case '\\': Data += '\\'; break;
30667330f729Sjoerg }
30677330f729Sjoerg }
30687330f729Sjoerg
30697330f729Sjoerg Lex();
30707330f729Sjoerg return false;
30717330f729Sjoerg }
30727330f729Sjoerg
parseAngleBracketString(std::string & Data)3073*82d56013Sjoerg bool AsmParser::parseAngleBracketString(std::string &Data) {
3074*82d56013Sjoerg SMLoc EndLoc, StartLoc = getTok().getLoc();
3075*82d56013Sjoerg if (isAngleBracketString(StartLoc, EndLoc)) {
3076*82d56013Sjoerg const char *StartChar = StartLoc.getPointer() + 1;
3077*82d56013Sjoerg const char *EndChar = EndLoc.getPointer() - 1;
3078*82d56013Sjoerg jumpToLoc(EndLoc, CurBuffer);
3079*82d56013Sjoerg /// Eat from '<' to '>'
3080*82d56013Sjoerg Lex();
3081*82d56013Sjoerg
3082*82d56013Sjoerg Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
3083*82d56013Sjoerg return false;
3084*82d56013Sjoerg }
3085*82d56013Sjoerg return true;
3086*82d56013Sjoerg }
3087*82d56013Sjoerg
30887330f729Sjoerg /// parseDirectiveAscii:
3089*82d56013Sjoerg // ::= .ascii [ "string"+ ( , "string"+ )* ]
3090*82d56013Sjoerg /// ::= ( .asciz | .string ) [ "string" ( , "string" )* ]
parseDirectiveAscii(StringRef IDVal,bool ZeroTerminated)30917330f729Sjoerg bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
30927330f729Sjoerg auto parseOp = [&]() -> bool {
30937330f729Sjoerg std::string Data;
3094*82d56013Sjoerg if (checkForValidSection())
30957330f729Sjoerg return true;
3096*82d56013Sjoerg // Only support spaces as separators for .ascii directive for now. See the
3097*82d56013Sjoerg // discusssion at https://reviews.llvm.org/D91460 for more details.
3098*82d56013Sjoerg do {
3099*82d56013Sjoerg if (parseEscapedString(Data))
3100*82d56013Sjoerg return true;
3101*82d56013Sjoerg getStreamer().emitBytes(Data);
3102*82d56013Sjoerg } while (!ZeroTerminated && getTok().is(AsmToken::String));
31037330f729Sjoerg if (ZeroTerminated)
3104*82d56013Sjoerg getStreamer().emitBytes(StringRef("\0", 1));
31057330f729Sjoerg return false;
31067330f729Sjoerg };
31077330f729Sjoerg
3108*82d56013Sjoerg return parseMany(parseOp);
31097330f729Sjoerg }
31107330f729Sjoerg
31117330f729Sjoerg /// parseDirectiveReloc
31127330f729Sjoerg /// ::= .reloc expression , identifier [ , expression ]
parseDirectiveReloc(SMLoc DirectiveLoc)31137330f729Sjoerg bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
31147330f729Sjoerg const MCExpr *Offset;
31157330f729Sjoerg const MCExpr *Expr = nullptr;
31167330f729Sjoerg SMLoc OffsetLoc = Lexer.getTok().getLoc();
31177330f729Sjoerg
31187330f729Sjoerg if (parseExpression(Offset))
31197330f729Sjoerg return true;
3120*82d56013Sjoerg if (parseComma() ||
3121*82d56013Sjoerg check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
31227330f729Sjoerg return true;
31237330f729Sjoerg
31247330f729Sjoerg SMLoc NameLoc = Lexer.getTok().getLoc();
31257330f729Sjoerg StringRef Name = Lexer.getTok().getIdentifier();
31267330f729Sjoerg Lex();
31277330f729Sjoerg
31287330f729Sjoerg if (Lexer.is(AsmToken::Comma)) {
31297330f729Sjoerg Lex();
31307330f729Sjoerg SMLoc ExprLoc = Lexer.getLoc();
31317330f729Sjoerg if (parseExpression(Expr))
31327330f729Sjoerg return true;
31337330f729Sjoerg
31347330f729Sjoerg MCValue Value;
31357330f729Sjoerg if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr))
31367330f729Sjoerg return Error(ExprLoc, "expression must be relocatable");
31377330f729Sjoerg }
31387330f729Sjoerg
3139*82d56013Sjoerg if (parseEOL())
31407330f729Sjoerg return true;
31417330f729Sjoerg
31427330f729Sjoerg const MCTargetAsmParser &MCT = getTargetParser();
31437330f729Sjoerg const MCSubtargetInfo &STI = MCT.getSTI();
3144*82d56013Sjoerg if (Optional<std::pair<bool, std::string>> Err =
3145*82d56013Sjoerg getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc,
3146*82d56013Sjoerg STI))
3147*82d56013Sjoerg return Error(Err->first ? NameLoc : OffsetLoc, Err->second);
31487330f729Sjoerg
31497330f729Sjoerg return false;
31507330f729Sjoerg }
31517330f729Sjoerg
31527330f729Sjoerg /// parseDirectiveValue
31537330f729Sjoerg /// ::= (.byte | .short | ... ) [ expression (, expression)* ]
parseDirectiveValue(StringRef IDVal,unsigned Size)31547330f729Sjoerg bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
31557330f729Sjoerg auto parseOp = [&]() -> bool {
31567330f729Sjoerg const MCExpr *Value;
31577330f729Sjoerg SMLoc ExprLoc = getLexer().getLoc();
31587330f729Sjoerg if (checkForValidSection() || parseExpression(Value))
31597330f729Sjoerg return true;
31607330f729Sjoerg // Special case constant expressions to match code generator.
31617330f729Sjoerg if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
31627330f729Sjoerg assert(Size <= 8 && "Invalid size");
31637330f729Sjoerg uint64_t IntValue = MCE->getValue();
31647330f729Sjoerg if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
31657330f729Sjoerg return Error(ExprLoc, "out of range literal value");
3166*82d56013Sjoerg getStreamer().emitIntValue(IntValue, Size);
31677330f729Sjoerg } else
3168*82d56013Sjoerg getStreamer().emitValue(Value, Size, ExprLoc);
31697330f729Sjoerg return false;
31707330f729Sjoerg };
31717330f729Sjoerg
3172*82d56013Sjoerg return parseMany(parseOp);
31737330f729Sjoerg }
31747330f729Sjoerg
parseHexOcta(AsmParser & Asm,uint64_t & hi,uint64_t & lo)31757330f729Sjoerg static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {
31767330f729Sjoerg if (Asm.getTok().isNot(AsmToken::Integer) &&
31777330f729Sjoerg Asm.getTok().isNot(AsmToken::BigNum))
31787330f729Sjoerg return Asm.TokError("unknown token in expression");
31797330f729Sjoerg SMLoc ExprLoc = Asm.getTok().getLoc();
31807330f729Sjoerg APInt IntValue = Asm.getTok().getAPIntVal();
31817330f729Sjoerg Asm.Lex();
31827330f729Sjoerg if (!IntValue.isIntN(128))
31837330f729Sjoerg return Asm.Error(ExprLoc, "out of range literal value");
31847330f729Sjoerg if (!IntValue.isIntN(64)) {
31857330f729Sjoerg hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
31867330f729Sjoerg lo = IntValue.getLoBits(64).getZExtValue();
31877330f729Sjoerg } else {
31887330f729Sjoerg hi = 0;
31897330f729Sjoerg lo = IntValue.getZExtValue();
31907330f729Sjoerg }
31917330f729Sjoerg return false;
31927330f729Sjoerg }
31937330f729Sjoerg
31947330f729Sjoerg /// ParseDirectiveOctaValue
31957330f729Sjoerg /// ::= .octa [ hexconstant (, hexconstant)* ]
31967330f729Sjoerg
parseDirectiveOctaValue(StringRef IDVal)31977330f729Sjoerg bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
31987330f729Sjoerg auto parseOp = [&]() -> bool {
31997330f729Sjoerg if (checkForValidSection())
32007330f729Sjoerg return true;
32017330f729Sjoerg uint64_t hi, lo;
32027330f729Sjoerg if (parseHexOcta(*this, hi, lo))
32037330f729Sjoerg return true;
32047330f729Sjoerg if (MAI.isLittleEndian()) {
3205*82d56013Sjoerg getStreamer().emitInt64(lo);
3206*82d56013Sjoerg getStreamer().emitInt64(hi);
32077330f729Sjoerg } else {
3208*82d56013Sjoerg getStreamer().emitInt64(hi);
3209*82d56013Sjoerg getStreamer().emitInt64(lo);
32107330f729Sjoerg }
32117330f729Sjoerg return false;
32127330f729Sjoerg };
32137330f729Sjoerg
3214*82d56013Sjoerg return parseMany(parseOp);
32157330f729Sjoerg }
32167330f729Sjoerg
parseRealValue(const fltSemantics & Semantics,APInt & Res)32177330f729Sjoerg bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
32187330f729Sjoerg // We don't truly support arithmetic on floating point expressions, so we
32197330f729Sjoerg // have to manually parse unary prefixes.
32207330f729Sjoerg bool IsNeg = false;
32217330f729Sjoerg if (getLexer().is(AsmToken::Minus)) {
32227330f729Sjoerg Lexer.Lex();
32237330f729Sjoerg IsNeg = true;
32247330f729Sjoerg } else if (getLexer().is(AsmToken::Plus))
32257330f729Sjoerg Lexer.Lex();
32267330f729Sjoerg
32277330f729Sjoerg if (Lexer.is(AsmToken::Error))
32287330f729Sjoerg return TokError(Lexer.getErr());
32297330f729Sjoerg if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
32307330f729Sjoerg Lexer.isNot(AsmToken::Identifier))
32317330f729Sjoerg return TokError("unexpected token in directive");
32327330f729Sjoerg
32337330f729Sjoerg // Convert to an APFloat.
32347330f729Sjoerg APFloat Value(Semantics);
32357330f729Sjoerg StringRef IDVal = getTok().getString();
32367330f729Sjoerg if (getLexer().is(AsmToken::Identifier)) {
32377330f729Sjoerg if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf"))
32387330f729Sjoerg Value = APFloat::getInf(Semantics);
32397330f729Sjoerg else if (!IDVal.compare_lower("nan"))
32407330f729Sjoerg Value = APFloat::getNaN(Semantics, false, ~0);
32417330f729Sjoerg else
32427330f729Sjoerg return TokError("invalid floating point literal");
3243*82d56013Sjoerg } else if (errorToBool(
3244*82d56013Sjoerg Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3245*82d56013Sjoerg .takeError()))
32467330f729Sjoerg return TokError("invalid floating point literal");
32477330f729Sjoerg if (IsNeg)
32487330f729Sjoerg Value.changeSign();
32497330f729Sjoerg
32507330f729Sjoerg // Consume the numeric token.
32517330f729Sjoerg Lex();
32527330f729Sjoerg
32537330f729Sjoerg Res = Value.bitcastToAPInt();
32547330f729Sjoerg
32557330f729Sjoerg return false;
32567330f729Sjoerg }
32577330f729Sjoerg
32587330f729Sjoerg /// parseDirectiveRealValue
32597330f729Sjoerg /// ::= (.single | .double) [ expression (, expression)* ]
parseDirectiveRealValue(StringRef IDVal,const fltSemantics & Semantics)32607330f729Sjoerg bool AsmParser::parseDirectiveRealValue(StringRef IDVal,
32617330f729Sjoerg const fltSemantics &Semantics) {
32627330f729Sjoerg auto parseOp = [&]() -> bool {
32637330f729Sjoerg APInt AsInt;
32647330f729Sjoerg if (checkForValidSection() || parseRealValue(Semantics, AsInt))
32657330f729Sjoerg return true;
3266*82d56013Sjoerg getStreamer().emitIntValue(AsInt.getLimitedValue(),
32677330f729Sjoerg AsInt.getBitWidth() / 8);
32687330f729Sjoerg return false;
32697330f729Sjoerg };
32707330f729Sjoerg
3271*82d56013Sjoerg return parseMany(parseOp);
32727330f729Sjoerg }
32737330f729Sjoerg
32747330f729Sjoerg /// parseDirectiveZero
32757330f729Sjoerg /// ::= .zero expression
parseDirectiveZero()32767330f729Sjoerg bool AsmParser::parseDirectiveZero() {
32777330f729Sjoerg SMLoc NumBytesLoc = Lexer.getLoc();
32787330f729Sjoerg const MCExpr *NumBytes;
32797330f729Sjoerg if (checkForValidSection() || parseExpression(NumBytes))
32807330f729Sjoerg return true;
32817330f729Sjoerg
32827330f729Sjoerg int64_t Val = 0;
32837330f729Sjoerg if (getLexer().is(AsmToken::Comma)) {
32847330f729Sjoerg Lex();
32857330f729Sjoerg if (parseAbsoluteExpression(Val))
32867330f729Sjoerg return true;
32877330f729Sjoerg }
32887330f729Sjoerg
3289*82d56013Sjoerg if (parseEOL())
32907330f729Sjoerg return true;
32917330f729Sjoerg getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);
32927330f729Sjoerg
32937330f729Sjoerg return false;
32947330f729Sjoerg }
32957330f729Sjoerg
32967330f729Sjoerg /// parseDirectiveFill
32977330f729Sjoerg /// ::= .fill expression [ , expression [ , expression ] ]
parseDirectiveFill()32987330f729Sjoerg bool AsmParser::parseDirectiveFill() {
32997330f729Sjoerg SMLoc NumValuesLoc = Lexer.getLoc();
33007330f729Sjoerg const MCExpr *NumValues;
33017330f729Sjoerg if (checkForValidSection() || parseExpression(NumValues))
33027330f729Sjoerg return true;
33037330f729Sjoerg
33047330f729Sjoerg int64_t FillSize = 1;
33057330f729Sjoerg int64_t FillExpr = 0;
33067330f729Sjoerg
33077330f729Sjoerg SMLoc SizeLoc, ExprLoc;
33087330f729Sjoerg
33097330f729Sjoerg if (parseOptionalToken(AsmToken::Comma)) {
33107330f729Sjoerg SizeLoc = getTok().getLoc();
33117330f729Sjoerg if (parseAbsoluteExpression(FillSize))
33127330f729Sjoerg return true;
33137330f729Sjoerg if (parseOptionalToken(AsmToken::Comma)) {
33147330f729Sjoerg ExprLoc = getTok().getLoc();
33157330f729Sjoerg if (parseAbsoluteExpression(FillExpr))
33167330f729Sjoerg return true;
33177330f729Sjoerg }
33187330f729Sjoerg }
3319*82d56013Sjoerg if (parseEOL())
33207330f729Sjoerg return true;
33217330f729Sjoerg
33227330f729Sjoerg if (FillSize < 0) {
33237330f729Sjoerg Warning(SizeLoc, "'.fill' directive with negative size has no effect");
33247330f729Sjoerg return false;
33257330f729Sjoerg }
33267330f729Sjoerg if (FillSize > 8) {
33277330f729Sjoerg Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
33287330f729Sjoerg FillSize = 8;
33297330f729Sjoerg }
33307330f729Sjoerg
33317330f729Sjoerg if (!isUInt<32>(FillExpr) && FillSize > 4)
33327330f729Sjoerg Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
33337330f729Sjoerg
33347330f729Sjoerg getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);
33357330f729Sjoerg
33367330f729Sjoerg return false;
33377330f729Sjoerg }
33387330f729Sjoerg
33397330f729Sjoerg /// parseDirectiveOrg
33407330f729Sjoerg /// ::= .org expression [ , expression ]
parseDirectiveOrg()33417330f729Sjoerg bool AsmParser::parseDirectiveOrg() {
33427330f729Sjoerg const MCExpr *Offset;
33437330f729Sjoerg SMLoc OffsetLoc = Lexer.getLoc();
33447330f729Sjoerg if (checkForValidSection() || parseExpression(Offset))
33457330f729Sjoerg return true;
33467330f729Sjoerg
33477330f729Sjoerg // Parse optional fill expression.
33487330f729Sjoerg int64_t FillExpr = 0;
33497330f729Sjoerg if (parseOptionalToken(AsmToken::Comma))
33507330f729Sjoerg if (parseAbsoluteExpression(FillExpr))
3351*82d56013Sjoerg return true;
3352*82d56013Sjoerg if (parseEOL())
3353*82d56013Sjoerg return true;
33547330f729Sjoerg
33557330f729Sjoerg getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
33567330f729Sjoerg return false;
33577330f729Sjoerg }
33587330f729Sjoerg
33597330f729Sjoerg /// parseDirectiveAlign
33607330f729Sjoerg /// ::= {.align, ...} expression [ , expression [ , expression ]]
parseDirectiveAlign(bool IsPow2,unsigned ValueSize)33617330f729Sjoerg bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
33627330f729Sjoerg SMLoc AlignmentLoc = getLexer().getLoc();
33637330f729Sjoerg int64_t Alignment;
33647330f729Sjoerg SMLoc MaxBytesLoc;
33657330f729Sjoerg bool HasFillExpr = false;
33667330f729Sjoerg int64_t FillExpr = 0;
33677330f729Sjoerg int64_t MaxBytesToFill = 0;
33687330f729Sjoerg
33697330f729Sjoerg auto parseAlign = [&]() -> bool {
33707330f729Sjoerg if (parseAbsoluteExpression(Alignment))
33717330f729Sjoerg return true;
33727330f729Sjoerg if (parseOptionalToken(AsmToken::Comma)) {
33737330f729Sjoerg // The fill expression can be omitted while specifying a maximum number of
33747330f729Sjoerg // alignment bytes, e.g:
33757330f729Sjoerg // .align 3,,4
33767330f729Sjoerg if (getTok().isNot(AsmToken::Comma)) {
33777330f729Sjoerg HasFillExpr = true;
33787330f729Sjoerg if (parseAbsoluteExpression(FillExpr))
33797330f729Sjoerg return true;
33807330f729Sjoerg }
33817330f729Sjoerg if (parseOptionalToken(AsmToken::Comma))
33827330f729Sjoerg if (parseTokenLoc(MaxBytesLoc) ||
33837330f729Sjoerg parseAbsoluteExpression(MaxBytesToFill))
33847330f729Sjoerg return true;
33857330f729Sjoerg }
3386*82d56013Sjoerg return parseEOL();
33877330f729Sjoerg };
33887330f729Sjoerg
33897330f729Sjoerg if (checkForValidSection())
3390*82d56013Sjoerg return true;
33917330f729Sjoerg // Ignore empty '.p2align' directives for GNU-as compatibility
33927330f729Sjoerg if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
33937330f729Sjoerg Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
3394*82d56013Sjoerg return parseEOL();
33957330f729Sjoerg }
33967330f729Sjoerg if (parseAlign())
3397*82d56013Sjoerg return true;
33987330f729Sjoerg
33997330f729Sjoerg // Always emit an alignment here even if we thrown an error.
34007330f729Sjoerg bool ReturnVal = false;
34017330f729Sjoerg
34027330f729Sjoerg // Compute alignment in bytes.
34037330f729Sjoerg if (IsPow2) {
34047330f729Sjoerg // FIXME: Diagnose overflow.
34057330f729Sjoerg if (Alignment >= 32) {
34067330f729Sjoerg ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
34077330f729Sjoerg Alignment = 31;
34087330f729Sjoerg }
34097330f729Sjoerg
34107330f729Sjoerg Alignment = 1ULL << Alignment;
34117330f729Sjoerg } else {
34127330f729Sjoerg // Reject alignments that aren't either a power of two or zero,
34137330f729Sjoerg // for gas compatibility. Alignment of zero is silently rounded
34147330f729Sjoerg // up to one.
34157330f729Sjoerg if (Alignment == 0)
34167330f729Sjoerg Alignment = 1;
34177330f729Sjoerg if (!isPowerOf2_64(Alignment))
34187330f729Sjoerg ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
3419*82d56013Sjoerg if (!isUInt<32>(Alignment))
3420*82d56013Sjoerg ReturnVal |= Error(AlignmentLoc, "alignment must be smaller than 2**32");
34217330f729Sjoerg }
34227330f729Sjoerg
34237330f729Sjoerg // Diagnose non-sensical max bytes to align.
34247330f729Sjoerg if (MaxBytesLoc.isValid()) {
34257330f729Sjoerg if (MaxBytesToFill < 1) {
34267330f729Sjoerg ReturnVal |= Error(MaxBytesLoc,
34277330f729Sjoerg "alignment directive can never be satisfied in this "
34287330f729Sjoerg "many bytes, ignoring maximum bytes expression");
34297330f729Sjoerg MaxBytesToFill = 0;
34307330f729Sjoerg }
34317330f729Sjoerg
34327330f729Sjoerg if (MaxBytesToFill >= Alignment) {
34337330f729Sjoerg Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
34347330f729Sjoerg "has no effect");
34357330f729Sjoerg MaxBytesToFill = 0;
34367330f729Sjoerg }
34377330f729Sjoerg }
34387330f729Sjoerg
34397330f729Sjoerg // Check whether we should use optimal code alignment for this .align
34407330f729Sjoerg // directive.
34417330f729Sjoerg const MCSection *Section = getStreamer().getCurrentSectionOnly();
34427330f729Sjoerg assert(Section && "must have section to emit alignment");
34437330f729Sjoerg bool UseCodeAlign = Section->UseCodeAlign();
34447330f729Sjoerg if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
34457330f729Sjoerg ValueSize == 1 && UseCodeAlign) {
3446*82d56013Sjoerg getStreamer().emitCodeAlignment(Alignment, MaxBytesToFill);
34477330f729Sjoerg } else {
34487330f729Sjoerg // FIXME: Target specific behavior about how the "extra" bytes are filled.
3449*82d56013Sjoerg getStreamer().emitValueToAlignment(Alignment, FillExpr, ValueSize,
34507330f729Sjoerg MaxBytesToFill);
34517330f729Sjoerg }
34527330f729Sjoerg
34537330f729Sjoerg return ReturnVal;
34547330f729Sjoerg }
34557330f729Sjoerg
34567330f729Sjoerg /// parseDirectiveFile
34577330f729Sjoerg /// ::= .file filename
34587330f729Sjoerg /// ::= .file number [directory] filename [md5 checksum] [source source-text]
parseDirectiveFile(SMLoc DirectiveLoc)34597330f729Sjoerg bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
34607330f729Sjoerg // FIXME: I'm not sure what this is.
34617330f729Sjoerg int64_t FileNumber = -1;
34627330f729Sjoerg if (getLexer().is(AsmToken::Integer)) {
34637330f729Sjoerg FileNumber = getTok().getIntVal();
34647330f729Sjoerg Lex();
34657330f729Sjoerg
34667330f729Sjoerg if (FileNumber < 0)
34677330f729Sjoerg return TokError("negative file number");
34687330f729Sjoerg }
34697330f729Sjoerg
34707330f729Sjoerg std::string Path;
34717330f729Sjoerg
34727330f729Sjoerg // Usually the directory and filename together, otherwise just the directory.
34737330f729Sjoerg // Allow the strings to have escaped octal character sequence.
3474*82d56013Sjoerg if (parseEscapedString(Path))
34757330f729Sjoerg return true;
34767330f729Sjoerg
34777330f729Sjoerg StringRef Directory;
34787330f729Sjoerg StringRef Filename;
34797330f729Sjoerg std::string FilenameData;
34807330f729Sjoerg if (getLexer().is(AsmToken::String)) {
34817330f729Sjoerg if (check(FileNumber == -1,
34827330f729Sjoerg "explicit path specified, but no file number") ||
34837330f729Sjoerg parseEscapedString(FilenameData))
34847330f729Sjoerg return true;
34857330f729Sjoerg Filename = FilenameData;
34867330f729Sjoerg Directory = Path;
34877330f729Sjoerg } else {
34887330f729Sjoerg Filename = Path;
34897330f729Sjoerg }
34907330f729Sjoerg
34917330f729Sjoerg uint64_t MD5Hi, MD5Lo;
34927330f729Sjoerg bool HasMD5 = false;
34937330f729Sjoerg
34947330f729Sjoerg Optional<StringRef> Source;
34957330f729Sjoerg bool HasSource = false;
34967330f729Sjoerg std::string SourceString;
34977330f729Sjoerg
34987330f729Sjoerg while (!parseOptionalToken(AsmToken::EndOfStatement)) {
34997330f729Sjoerg StringRef Keyword;
35007330f729Sjoerg if (check(getTok().isNot(AsmToken::Identifier),
35017330f729Sjoerg "unexpected token in '.file' directive") ||
35027330f729Sjoerg parseIdentifier(Keyword))
35037330f729Sjoerg return true;
35047330f729Sjoerg if (Keyword == "md5") {
35057330f729Sjoerg HasMD5 = true;
35067330f729Sjoerg if (check(FileNumber == -1,
35077330f729Sjoerg "MD5 checksum specified, but no file number") ||
35087330f729Sjoerg parseHexOcta(*this, MD5Hi, MD5Lo))
35097330f729Sjoerg return true;
35107330f729Sjoerg } else if (Keyword == "source") {
35117330f729Sjoerg HasSource = true;
35127330f729Sjoerg if (check(FileNumber == -1,
35137330f729Sjoerg "source specified, but no file number") ||
35147330f729Sjoerg check(getTok().isNot(AsmToken::String),
35157330f729Sjoerg "unexpected token in '.file' directive") ||
35167330f729Sjoerg parseEscapedString(SourceString))
35177330f729Sjoerg return true;
35187330f729Sjoerg } else {
35197330f729Sjoerg return TokError("unexpected token in '.file' directive");
35207330f729Sjoerg }
35217330f729Sjoerg }
35227330f729Sjoerg
35237330f729Sjoerg if (FileNumber == -1) {
35247330f729Sjoerg // Ignore the directive if there is no number and the target doesn't support
35257330f729Sjoerg // numberless .file directives. This allows some portability of assembler
35267330f729Sjoerg // between different object file formats.
35277330f729Sjoerg if (getContext().getAsmInfo()->hasSingleParameterDotFile())
3528*82d56013Sjoerg getStreamer().emitFileDirective(Filename);
35297330f729Sjoerg } else {
35307330f729Sjoerg // In case there is a -g option as well as debug info from directive .file,
35317330f729Sjoerg // we turn off the -g option, directly use the existing debug info instead.
35327330f729Sjoerg // Throw away any implicit file table for the assembler source.
35337330f729Sjoerg if (Ctx.getGenDwarfForAssembly()) {
35347330f729Sjoerg Ctx.getMCDwarfLineTable(0).resetFileTable();
35357330f729Sjoerg Ctx.setGenDwarfForAssembly(false);
35367330f729Sjoerg }
35377330f729Sjoerg
35387330f729Sjoerg Optional<MD5::MD5Result> CKMem;
35397330f729Sjoerg if (HasMD5) {
35407330f729Sjoerg MD5::MD5Result Sum;
35417330f729Sjoerg for (unsigned i = 0; i != 8; ++i) {
35427330f729Sjoerg Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
35437330f729Sjoerg Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
35447330f729Sjoerg }
35457330f729Sjoerg CKMem = Sum;
35467330f729Sjoerg }
35477330f729Sjoerg if (HasSource) {
35487330f729Sjoerg char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
35497330f729Sjoerg memcpy(SourceBuf, SourceString.data(), SourceString.size());
35507330f729Sjoerg Source = StringRef(SourceBuf, SourceString.size());
35517330f729Sjoerg }
35527330f729Sjoerg if (FileNumber == 0) {
3553*82d56013Sjoerg // Upgrade to Version 5 for assembly actions like clang -c a.s.
35547330f729Sjoerg if (Ctx.getDwarfVersion() < 5)
3555*82d56013Sjoerg Ctx.setDwarfVersion(5);
35567330f729Sjoerg getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
35577330f729Sjoerg } else {
35587330f729Sjoerg Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
35597330f729Sjoerg FileNumber, Directory, Filename, CKMem, Source);
35607330f729Sjoerg if (!FileNumOrErr)
35617330f729Sjoerg return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
35627330f729Sjoerg }
35637330f729Sjoerg // Alert the user if there are some .file directives with MD5 and some not.
35647330f729Sjoerg // But only do that once.
35657330f729Sjoerg if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
35667330f729Sjoerg ReportedInconsistentMD5 = true;
35677330f729Sjoerg return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
35687330f729Sjoerg }
35697330f729Sjoerg }
35707330f729Sjoerg
35717330f729Sjoerg return false;
35727330f729Sjoerg }
35737330f729Sjoerg
35747330f729Sjoerg /// parseDirectiveLine
35757330f729Sjoerg /// ::= .line [number]
parseDirectiveLine()35767330f729Sjoerg bool AsmParser::parseDirectiveLine() {
35777330f729Sjoerg int64_t LineNumber;
35787330f729Sjoerg if (getLexer().is(AsmToken::Integer)) {
35797330f729Sjoerg if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
35807330f729Sjoerg return true;
35817330f729Sjoerg (void)LineNumber;
35827330f729Sjoerg // FIXME: Do something with the .line.
35837330f729Sjoerg }
3584*82d56013Sjoerg return parseEOL();
35857330f729Sjoerg }
35867330f729Sjoerg
35877330f729Sjoerg /// parseDirectiveLoc
35887330f729Sjoerg /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
35897330f729Sjoerg /// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
35907330f729Sjoerg /// The first number is a file number, must have been previously assigned with
35917330f729Sjoerg /// a .file directive, the second number is the line number and optionally the
35927330f729Sjoerg /// third number is a column position (zero if not specified). The remaining
35937330f729Sjoerg /// optional items are .loc sub-directives.
parseDirectiveLoc()35947330f729Sjoerg bool AsmParser::parseDirectiveLoc() {
35957330f729Sjoerg int64_t FileNumber = 0, LineNumber = 0;
35967330f729Sjoerg SMLoc Loc = getTok().getLoc();
35977330f729Sjoerg if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
35987330f729Sjoerg check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
35997330f729Sjoerg "file number less than one in '.loc' directive") ||
36007330f729Sjoerg check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
36017330f729Sjoerg "unassigned file number in '.loc' directive"))
36027330f729Sjoerg return true;
36037330f729Sjoerg
36047330f729Sjoerg // optional
36057330f729Sjoerg if (getLexer().is(AsmToken::Integer)) {
36067330f729Sjoerg LineNumber = getTok().getIntVal();
36077330f729Sjoerg if (LineNumber < 0)
36087330f729Sjoerg return TokError("line number less than zero in '.loc' directive");
36097330f729Sjoerg Lex();
36107330f729Sjoerg }
36117330f729Sjoerg
36127330f729Sjoerg int64_t ColumnPos = 0;
36137330f729Sjoerg if (getLexer().is(AsmToken::Integer)) {
36147330f729Sjoerg ColumnPos = getTok().getIntVal();
36157330f729Sjoerg if (ColumnPos < 0)
36167330f729Sjoerg return TokError("column position less than zero in '.loc' directive");
36177330f729Sjoerg Lex();
36187330f729Sjoerg }
36197330f729Sjoerg
3620*82d56013Sjoerg auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
3621*82d56013Sjoerg unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
36227330f729Sjoerg unsigned Isa = 0;
36237330f729Sjoerg int64_t Discriminator = 0;
36247330f729Sjoerg
36257330f729Sjoerg auto parseLocOp = [&]() -> bool {
36267330f729Sjoerg StringRef Name;
36277330f729Sjoerg SMLoc Loc = getTok().getLoc();
36287330f729Sjoerg if (parseIdentifier(Name))
36297330f729Sjoerg return TokError("unexpected token in '.loc' directive");
36307330f729Sjoerg
36317330f729Sjoerg if (Name == "basic_block")
36327330f729Sjoerg Flags |= DWARF2_FLAG_BASIC_BLOCK;
36337330f729Sjoerg else if (Name == "prologue_end")
36347330f729Sjoerg Flags |= DWARF2_FLAG_PROLOGUE_END;
36357330f729Sjoerg else if (Name == "epilogue_begin")
36367330f729Sjoerg Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
36377330f729Sjoerg else if (Name == "is_stmt") {
36387330f729Sjoerg Loc = getTok().getLoc();
36397330f729Sjoerg const MCExpr *Value;
36407330f729Sjoerg if (parseExpression(Value))
36417330f729Sjoerg return true;
36427330f729Sjoerg // The expression must be the constant 0 or 1.
36437330f729Sjoerg if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
36447330f729Sjoerg int Value = MCE->getValue();
36457330f729Sjoerg if (Value == 0)
36467330f729Sjoerg Flags &= ~DWARF2_FLAG_IS_STMT;
36477330f729Sjoerg else if (Value == 1)
36487330f729Sjoerg Flags |= DWARF2_FLAG_IS_STMT;
36497330f729Sjoerg else
36507330f729Sjoerg return Error(Loc, "is_stmt value not 0 or 1");
36517330f729Sjoerg } else {
36527330f729Sjoerg return Error(Loc, "is_stmt value not the constant value of 0 or 1");
36537330f729Sjoerg }
36547330f729Sjoerg } else if (Name == "isa") {
36557330f729Sjoerg Loc = getTok().getLoc();
36567330f729Sjoerg const MCExpr *Value;
36577330f729Sjoerg if (parseExpression(Value))
36587330f729Sjoerg return true;
36597330f729Sjoerg // The expression must be a constant greater or equal to 0.
36607330f729Sjoerg if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
36617330f729Sjoerg int Value = MCE->getValue();
36627330f729Sjoerg if (Value < 0)
36637330f729Sjoerg return Error(Loc, "isa number less than zero");
36647330f729Sjoerg Isa = Value;
36657330f729Sjoerg } else {
36667330f729Sjoerg return Error(Loc, "isa number not a constant value");
36677330f729Sjoerg }
36687330f729Sjoerg } else if (Name == "discriminator") {
36697330f729Sjoerg if (parseAbsoluteExpression(Discriminator))
36707330f729Sjoerg return true;
36717330f729Sjoerg } else {
36727330f729Sjoerg return Error(Loc, "unknown sub-directive in '.loc' directive");
36737330f729Sjoerg }
36747330f729Sjoerg return false;
36757330f729Sjoerg };
36767330f729Sjoerg
36777330f729Sjoerg if (parseMany(parseLocOp, false /*hasComma*/))
36787330f729Sjoerg return true;
36797330f729Sjoerg
3680*82d56013Sjoerg getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
36817330f729Sjoerg Isa, Discriminator, StringRef());
36827330f729Sjoerg
36837330f729Sjoerg return false;
36847330f729Sjoerg }
36857330f729Sjoerg
36867330f729Sjoerg /// parseDirectiveStabs
36877330f729Sjoerg /// ::= .stabs string, number, number, number
parseDirectiveStabs()36887330f729Sjoerg bool AsmParser::parseDirectiveStabs() {
36897330f729Sjoerg return TokError("unsupported directive '.stabs'");
36907330f729Sjoerg }
36917330f729Sjoerg
36927330f729Sjoerg /// parseDirectiveCVFile
36937330f729Sjoerg /// ::= .cv_file number filename [checksum] [checksumkind]
parseDirectiveCVFile()36947330f729Sjoerg bool AsmParser::parseDirectiveCVFile() {
36957330f729Sjoerg SMLoc FileNumberLoc = getTok().getLoc();
36967330f729Sjoerg int64_t FileNumber;
36977330f729Sjoerg std::string Filename;
36987330f729Sjoerg std::string Checksum;
36997330f729Sjoerg int64_t ChecksumKind = 0;
37007330f729Sjoerg
37017330f729Sjoerg if (parseIntToken(FileNumber,
37027330f729Sjoerg "expected file number in '.cv_file' directive") ||
37037330f729Sjoerg check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
37047330f729Sjoerg check(getTok().isNot(AsmToken::String),
37057330f729Sjoerg "unexpected token in '.cv_file' directive") ||
37067330f729Sjoerg parseEscapedString(Filename))
37077330f729Sjoerg return true;
37087330f729Sjoerg if (!parseOptionalToken(AsmToken::EndOfStatement)) {
37097330f729Sjoerg if (check(getTok().isNot(AsmToken::String),
37107330f729Sjoerg "unexpected token in '.cv_file' directive") ||
37117330f729Sjoerg parseEscapedString(Checksum) ||
37127330f729Sjoerg parseIntToken(ChecksumKind,
37137330f729Sjoerg "expected checksum kind in '.cv_file' directive") ||
37147330f729Sjoerg parseToken(AsmToken::EndOfStatement,
37157330f729Sjoerg "unexpected token in '.cv_file' directive"))
37167330f729Sjoerg return true;
37177330f729Sjoerg }
37187330f729Sjoerg
37197330f729Sjoerg Checksum = fromHex(Checksum);
37207330f729Sjoerg void *CKMem = Ctx.allocate(Checksum.size(), 1);
37217330f729Sjoerg memcpy(CKMem, Checksum.data(), Checksum.size());
37227330f729Sjoerg ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
37237330f729Sjoerg Checksum.size());
37247330f729Sjoerg
37257330f729Sjoerg if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
37267330f729Sjoerg static_cast<uint8_t>(ChecksumKind)))
37277330f729Sjoerg return Error(FileNumberLoc, "file number already allocated");
37287330f729Sjoerg
37297330f729Sjoerg return false;
37307330f729Sjoerg }
37317330f729Sjoerg
parseCVFunctionId(int64_t & FunctionId,StringRef DirectiveName)37327330f729Sjoerg bool AsmParser::parseCVFunctionId(int64_t &FunctionId,
37337330f729Sjoerg StringRef DirectiveName) {
37347330f729Sjoerg SMLoc Loc;
37357330f729Sjoerg return parseTokenLoc(Loc) ||
37367330f729Sjoerg parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
37377330f729Sjoerg "' directive") ||
37387330f729Sjoerg check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
37397330f729Sjoerg "expected function id within range [0, UINT_MAX)");
37407330f729Sjoerg }
37417330f729Sjoerg
parseCVFileId(int64_t & FileNumber,StringRef DirectiveName)37427330f729Sjoerg bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
37437330f729Sjoerg SMLoc Loc;
37447330f729Sjoerg return parseTokenLoc(Loc) ||
37457330f729Sjoerg parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
37467330f729Sjoerg "' directive") ||
37477330f729Sjoerg check(FileNumber < 1, Loc, "file number less than one in '" +
37487330f729Sjoerg DirectiveName + "' directive") ||
37497330f729Sjoerg check(!getCVContext().isValidFileNumber(FileNumber), Loc,
37507330f729Sjoerg "unassigned file number in '" + DirectiveName + "' directive");
37517330f729Sjoerg }
37527330f729Sjoerg
37537330f729Sjoerg /// parseDirectiveCVFuncId
37547330f729Sjoerg /// ::= .cv_func_id FunctionId
37557330f729Sjoerg ///
37567330f729Sjoerg /// Introduces a function ID that can be used with .cv_loc.
parseDirectiveCVFuncId()37577330f729Sjoerg bool AsmParser::parseDirectiveCVFuncId() {
37587330f729Sjoerg SMLoc FunctionIdLoc = getTok().getLoc();
37597330f729Sjoerg int64_t FunctionId;
37607330f729Sjoerg
37617330f729Sjoerg if (parseCVFunctionId(FunctionId, ".cv_func_id") ||
37627330f729Sjoerg parseToken(AsmToken::EndOfStatement,
37637330f729Sjoerg "unexpected token in '.cv_func_id' directive"))
37647330f729Sjoerg return true;
37657330f729Sjoerg
37667330f729Sjoerg if (!getStreamer().EmitCVFuncIdDirective(FunctionId))
37677330f729Sjoerg return Error(FunctionIdLoc, "function id already allocated");
37687330f729Sjoerg
37697330f729Sjoerg return false;
37707330f729Sjoerg }
37717330f729Sjoerg
37727330f729Sjoerg /// parseDirectiveCVInlineSiteId
37737330f729Sjoerg /// ::= .cv_inline_site_id FunctionId
37747330f729Sjoerg /// "within" IAFunc
37757330f729Sjoerg /// "inlined_at" IAFile IALine [IACol]
37767330f729Sjoerg ///
37777330f729Sjoerg /// Introduces a function ID that can be used with .cv_loc. Includes "inlined
37787330f729Sjoerg /// at" source location information for use in the line table of the caller,
37797330f729Sjoerg /// whether the caller is a real function or another inlined call site.
parseDirectiveCVInlineSiteId()37807330f729Sjoerg bool AsmParser::parseDirectiveCVInlineSiteId() {
37817330f729Sjoerg SMLoc FunctionIdLoc = getTok().getLoc();
37827330f729Sjoerg int64_t FunctionId;
37837330f729Sjoerg int64_t IAFunc;
37847330f729Sjoerg int64_t IAFile;
37857330f729Sjoerg int64_t IALine;
37867330f729Sjoerg int64_t IACol = 0;
37877330f729Sjoerg
37887330f729Sjoerg // FunctionId
37897330f729Sjoerg if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
37907330f729Sjoerg return true;
37917330f729Sjoerg
37927330f729Sjoerg // "within"
37937330f729Sjoerg if (check((getLexer().isNot(AsmToken::Identifier) ||
37947330f729Sjoerg getTok().getIdentifier() != "within"),
37957330f729Sjoerg "expected 'within' identifier in '.cv_inline_site_id' directive"))
37967330f729Sjoerg return true;
37977330f729Sjoerg Lex();
37987330f729Sjoerg
37997330f729Sjoerg // IAFunc
38007330f729Sjoerg if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
38017330f729Sjoerg return true;
38027330f729Sjoerg
38037330f729Sjoerg // "inlined_at"
38047330f729Sjoerg if (check((getLexer().isNot(AsmToken::Identifier) ||
38057330f729Sjoerg getTok().getIdentifier() != "inlined_at"),
38067330f729Sjoerg "expected 'inlined_at' identifier in '.cv_inline_site_id' "
38077330f729Sjoerg "directive") )
38087330f729Sjoerg return true;
38097330f729Sjoerg Lex();
38107330f729Sjoerg
38117330f729Sjoerg // IAFile IALine
38127330f729Sjoerg if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
38137330f729Sjoerg parseIntToken(IALine, "expected line number after 'inlined_at'"))
38147330f729Sjoerg return true;
38157330f729Sjoerg
38167330f729Sjoerg // [IACol]
38177330f729Sjoerg if (getLexer().is(AsmToken::Integer)) {
38187330f729Sjoerg IACol = getTok().getIntVal();
38197330f729Sjoerg Lex();
38207330f729Sjoerg }
38217330f729Sjoerg
38227330f729Sjoerg if (parseToken(AsmToken::EndOfStatement,
38237330f729Sjoerg "unexpected token in '.cv_inline_site_id' directive"))
38247330f729Sjoerg return true;
38257330f729Sjoerg
38267330f729Sjoerg if (!getStreamer().EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
38277330f729Sjoerg IALine, IACol, FunctionIdLoc))
38287330f729Sjoerg return Error(FunctionIdLoc, "function id already allocated");
38297330f729Sjoerg
38307330f729Sjoerg return false;
38317330f729Sjoerg }
38327330f729Sjoerg
38337330f729Sjoerg /// parseDirectiveCVLoc
38347330f729Sjoerg /// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
38357330f729Sjoerg /// [is_stmt VALUE]
38367330f729Sjoerg /// The first number is a file number, must have been previously assigned with
38377330f729Sjoerg /// a .file directive, the second number is the line number and optionally the
38387330f729Sjoerg /// third number is a column position (zero if not specified). The remaining
38397330f729Sjoerg /// optional items are .loc sub-directives.
parseDirectiveCVLoc()38407330f729Sjoerg bool AsmParser::parseDirectiveCVLoc() {
38417330f729Sjoerg SMLoc DirectiveLoc = getTok().getLoc();
38427330f729Sjoerg int64_t FunctionId, FileNumber;
38437330f729Sjoerg if (parseCVFunctionId(FunctionId, ".cv_loc") ||
38447330f729Sjoerg parseCVFileId(FileNumber, ".cv_loc"))
38457330f729Sjoerg return true;
38467330f729Sjoerg
38477330f729Sjoerg int64_t LineNumber = 0;
38487330f729Sjoerg if (getLexer().is(AsmToken::Integer)) {
38497330f729Sjoerg LineNumber = getTok().getIntVal();
38507330f729Sjoerg if (LineNumber < 0)
38517330f729Sjoerg return TokError("line number less than zero in '.cv_loc' directive");
38527330f729Sjoerg Lex();
38537330f729Sjoerg }
38547330f729Sjoerg
38557330f729Sjoerg int64_t ColumnPos = 0;
38567330f729Sjoerg if (getLexer().is(AsmToken::Integer)) {
38577330f729Sjoerg ColumnPos = getTok().getIntVal();
38587330f729Sjoerg if (ColumnPos < 0)
38597330f729Sjoerg return TokError("column position less than zero in '.cv_loc' directive");
38607330f729Sjoerg Lex();
38617330f729Sjoerg }
38627330f729Sjoerg
38637330f729Sjoerg bool PrologueEnd = false;
38647330f729Sjoerg uint64_t IsStmt = 0;
38657330f729Sjoerg
38667330f729Sjoerg auto parseOp = [&]() -> bool {
38677330f729Sjoerg StringRef Name;
38687330f729Sjoerg SMLoc Loc = getTok().getLoc();
38697330f729Sjoerg if (parseIdentifier(Name))
38707330f729Sjoerg return TokError("unexpected token in '.cv_loc' directive");
38717330f729Sjoerg if (Name == "prologue_end")
38727330f729Sjoerg PrologueEnd = true;
38737330f729Sjoerg else if (Name == "is_stmt") {
38747330f729Sjoerg Loc = getTok().getLoc();
38757330f729Sjoerg const MCExpr *Value;
38767330f729Sjoerg if (parseExpression(Value))
38777330f729Sjoerg return true;
38787330f729Sjoerg // The expression must be the constant 0 or 1.
38797330f729Sjoerg IsStmt = ~0ULL;
38807330f729Sjoerg if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
38817330f729Sjoerg IsStmt = MCE->getValue();
38827330f729Sjoerg
38837330f729Sjoerg if (IsStmt > 1)
38847330f729Sjoerg return Error(Loc, "is_stmt value not 0 or 1");
38857330f729Sjoerg } else {
38867330f729Sjoerg return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
38877330f729Sjoerg }
38887330f729Sjoerg return false;
38897330f729Sjoerg };
38907330f729Sjoerg
38917330f729Sjoerg if (parseMany(parseOp, false /*hasComma*/))
38927330f729Sjoerg return true;
38937330f729Sjoerg
3894*82d56013Sjoerg getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
38957330f729Sjoerg ColumnPos, PrologueEnd, IsStmt, StringRef(),
38967330f729Sjoerg DirectiveLoc);
38977330f729Sjoerg return false;
38987330f729Sjoerg }
38997330f729Sjoerg
39007330f729Sjoerg /// parseDirectiveCVLinetable
39017330f729Sjoerg /// ::= .cv_linetable FunctionId, FnStart, FnEnd
parseDirectiveCVLinetable()39027330f729Sjoerg bool AsmParser::parseDirectiveCVLinetable() {
39037330f729Sjoerg int64_t FunctionId;
39047330f729Sjoerg StringRef FnStartName, FnEndName;
39057330f729Sjoerg SMLoc Loc = getTok().getLoc();
3906*82d56013Sjoerg if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() ||
3907*82d56013Sjoerg parseTokenLoc(Loc) ||
3908*82d56013Sjoerg check(parseIdentifier(FnStartName), Loc,
39097330f729Sjoerg "expected identifier in directive") ||
3910*82d56013Sjoerg parseComma() || parseTokenLoc(Loc) ||
3911*82d56013Sjoerg check(parseIdentifier(FnEndName), Loc,
39127330f729Sjoerg "expected identifier in directive"))
39137330f729Sjoerg return true;
39147330f729Sjoerg
39157330f729Sjoerg MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
39167330f729Sjoerg MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
39177330f729Sjoerg
3918*82d56013Sjoerg getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
39197330f729Sjoerg return false;
39207330f729Sjoerg }
39217330f729Sjoerg
39227330f729Sjoerg /// parseDirectiveCVInlineLinetable
39237330f729Sjoerg /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
parseDirectiveCVInlineLinetable()39247330f729Sjoerg bool AsmParser::parseDirectiveCVInlineLinetable() {
39257330f729Sjoerg int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
39267330f729Sjoerg StringRef FnStartName, FnEndName;
39277330f729Sjoerg SMLoc Loc = getTok().getLoc();
39287330f729Sjoerg if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
39297330f729Sjoerg parseTokenLoc(Loc) ||
39307330f729Sjoerg parseIntToken(
39317330f729Sjoerg SourceFileId,
39327330f729Sjoerg "expected SourceField in '.cv_inline_linetable' directive") ||
39337330f729Sjoerg check(SourceFileId <= 0, Loc,
39347330f729Sjoerg "File id less than zero in '.cv_inline_linetable' directive") ||
39357330f729Sjoerg parseTokenLoc(Loc) ||
39367330f729Sjoerg parseIntToken(
39377330f729Sjoerg SourceLineNum,
39387330f729Sjoerg "expected SourceLineNum in '.cv_inline_linetable' directive") ||
39397330f729Sjoerg check(SourceLineNum < 0, Loc,
39407330f729Sjoerg "Line number less than zero in '.cv_inline_linetable' directive") ||
39417330f729Sjoerg parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
39427330f729Sjoerg "expected identifier in directive") ||
39437330f729Sjoerg parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
39447330f729Sjoerg "expected identifier in directive"))
39457330f729Sjoerg return true;
39467330f729Sjoerg
39477330f729Sjoerg if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
39487330f729Sjoerg return true;
39497330f729Sjoerg
39507330f729Sjoerg MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
39517330f729Sjoerg MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
3952*82d56013Sjoerg getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
39537330f729Sjoerg SourceLineNum, FnStartSym,
39547330f729Sjoerg FnEndSym);
39557330f729Sjoerg return false;
39567330f729Sjoerg }
39577330f729Sjoerg
initializeCVDefRangeTypeMap()39587330f729Sjoerg void AsmParser::initializeCVDefRangeTypeMap() {
39597330f729Sjoerg CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
39607330f729Sjoerg CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
39617330f729Sjoerg CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
39627330f729Sjoerg CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
39637330f729Sjoerg }
39647330f729Sjoerg
39657330f729Sjoerg /// parseDirectiveCVDefRange
39667330f729Sjoerg /// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
parseDirectiveCVDefRange()39677330f729Sjoerg bool AsmParser::parseDirectiveCVDefRange() {
39687330f729Sjoerg SMLoc Loc;
39697330f729Sjoerg std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
39707330f729Sjoerg while (getLexer().is(AsmToken::Identifier)) {
39717330f729Sjoerg Loc = getLexer().getLoc();
39727330f729Sjoerg StringRef GapStartName;
39737330f729Sjoerg if (parseIdentifier(GapStartName))
39747330f729Sjoerg return Error(Loc, "expected identifier in directive");
39757330f729Sjoerg MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
39767330f729Sjoerg
39777330f729Sjoerg Loc = getLexer().getLoc();
39787330f729Sjoerg StringRef GapEndName;
39797330f729Sjoerg if (parseIdentifier(GapEndName))
39807330f729Sjoerg return Error(Loc, "expected identifier in directive");
39817330f729Sjoerg MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
39827330f729Sjoerg
39837330f729Sjoerg Ranges.push_back({GapStartSym, GapEndSym});
39847330f729Sjoerg }
39857330f729Sjoerg
39867330f729Sjoerg StringRef CVDefRangeTypeStr;
39877330f729Sjoerg if (parseToken(
39887330f729Sjoerg AsmToken::Comma,
39897330f729Sjoerg "expected comma before def_range type in .cv_def_range directive") ||
39907330f729Sjoerg parseIdentifier(CVDefRangeTypeStr))
39917330f729Sjoerg return Error(Loc, "expected def_range type in directive");
39927330f729Sjoerg
39937330f729Sjoerg StringMap<CVDefRangeType>::const_iterator CVTypeIt =
39947330f729Sjoerg CVDefRangeTypeMap.find(CVDefRangeTypeStr);
39957330f729Sjoerg CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
39967330f729Sjoerg ? CVDR_DEFRANGE
39977330f729Sjoerg : CVTypeIt->getValue();
39987330f729Sjoerg switch (CVDRType) {
39997330f729Sjoerg case CVDR_DEFRANGE_REGISTER: {
40007330f729Sjoerg int64_t DRRegister;
40017330f729Sjoerg if (parseToken(AsmToken::Comma, "expected comma before register number in "
40027330f729Sjoerg ".cv_def_range directive") ||
40037330f729Sjoerg parseAbsoluteExpression(DRRegister))
40047330f729Sjoerg return Error(Loc, "expected register number");
40057330f729Sjoerg
40067330f729Sjoerg codeview::DefRangeRegisterHeader DRHdr;
40077330f729Sjoerg DRHdr.Register = DRRegister;
40087330f729Sjoerg DRHdr.MayHaveNoName = 0;
4009*82d56013Sjoerg getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
40107330f729Sjoerg break;
40117330f729Sjoerg }
40127330f729Sjoerg case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
40137330f729Sjoerg int64_t DROffset;
40147330f729Sjoerg if (parseToken(AsmToken::Comma,
40157330f729Sjoerg "expected comma before offset in .cv_def_range directive") ||
40167330f729Sjoerg parseAbsoluteExpression(DROffset))
40177330f729Sjoerg return Error(Loc, "expected offset value");
40187330f729Sjoerg
40197330f729Sjoerg codeview::DefRangeFramePointerRelHeader DRHdr;
40207330f729Sjoerg DRHdr.Offset = DROffset;
4021*82d56013Sjoerg getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
40227330f729Sjoerg break;
40237330f729Sjoerg }
40247330f729Sjoerg case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
40257330f729Sjoerg int64_t DRRegister;
40267330f729Sjoerg int64_t DROffsetInParent;
40277330f729Sjoerg if (parseToken(AsmToken::Comma, "expected comma before register number in "
40287330f729Sjoerg ".cv_def_range directive") ||
40297330f729Sjoerg parseAbsoluteExpression(DRRegister))
40307330f729Sjoerg return Error(Loc, "expected register number");
40317330f729Sjoerg if (parseToken(AsmToken::Comma,
40327330f729Sjoerg "expected comma before offset in .cv_def_range directive") ||
40337330f729Sjoerg parseAbsoluteExpression(DROffsetInParent))
40347330f729Sjoerg return Error(Loc, "expected offset value");
40357330f729Sjoerg
40367330f729Sjoerg codeview::DefRangeSubfieldRegisterHeader DRHdr;
40377330f729Sjoerg DRHdr.Register = DRRegister;
40387330f729Sjoerg DRHdr.MayHaveNoName = 0;
40397330f729Sjoerg DRHdr.OffsetInParent = DROffsetInParent;
4040*82d56013Sjoerg getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
40417330f729Sjoerg break;
40427330f729Sjoerg }
40437330f729Sjoerg case CVDR_DEFRANGE_REGISTER_REL: {
40447330f729Sjoerg int64_t DRRegister;
40457330f729Sjoerg int64_t DRFlags;
40467330f729Sjoerg int64_t DRBasePointerOffset;
40477330f729Sjoerg if (parseToken(AsmToken::Comma, "expected comma before register number in "
40487330f729Sjoerg ".cv_def_range directive") ||
40497330f729Sjoerg parseAbsoluteExpression(DRRegister))
40507330f729Sjoerg return Error(Loc, "expected register value");
40517330f729Sjoerg if (parseToken(
40527330f729Sjoerg AsmToken::Comma,
40537330f729Sjoerg "expected comma before flag value in .cv_def_range directive") ||
40547330f729Sjoerg parseAbsoluteExpression(DRFlags))
40557330f729Sjoerg return Error(Loc, "expected flag value");
40567330f729Sjoerg if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
40577330f729Sjoerg "in .cv_def_range directive") ||
40587330f729Sjoerg parseAbsoluteExpression(DRBasePointerOffset))
40597330f729Sjoerg return Error(Loc, "expected base pointer offset value");
40607330f729Sjoerg
40617330f729Sjoerg codeview::DefRangeRegisterRelHeader DRHdr;
40627330f729Sjoerg DRHdr.Register = DRRegister;
40637330f729Sjoerg DRHdr.Flags = DRFlags;
40647330f729Sjoerg DRHdr.BasePointerOffset = DRBasePointerOffset;
4065*82d56013Sjoerg getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
40667330f729Sjoerg break;
40677330f729Sjoerg }
40687330f729Sjoerg default:
40697330f729Sjoerg return Error(Loc, "unexpected def_range type in .cv_def_range directive");
40707330f729Sjoerg }
40717330f729Sjoerg return true;
40727330f729Sjoerg }
40737330f729Sjoerg
40747330f729Sjoerg /// parseDirectiveCVString
40757330f729Sjoerg /// ::= .cv_stringtable "string"
parseDirectiveCVString()40767330f729Sjoerg bool AsmParser::parseDirectiveCVString() {
40777330f729Sjoerg std::string Data;
40787330f729Sjoerg if (checkForValidSection() || parseEscapedString(Data))
4079*82d56013Sjoerg return true;
40807330f729Sjoerg
40817330f729Sjoerg // Put the string in the table and emit the offset.
40827330f729Sjoerg std::pair<StringRef, unsigned> Insertion =
40837330f729Sjoerg getCVContext().addToStringTable(Data);
4084*82d56013Sjoerg getStreamer().emitInt32(Insertion.second);
40857330f729Sjoerg return false;
40867330f729Sjoerg }
40877330f729Sjoerg
40887330f729Sjoerg /// parseDirectiveCVStringTable
40897330f729Sjoerg /// ::= .cv_stringtable
parseDirectiveCVStringTable()40907330f729Sjoerg bool AsmParser::parseDirectiveCVStringTable() {
4091*82d56013Sjoerg getStreamer().emitCVStringTableDirective();
40927330f729Sjoerg return false;
40937330f729Sjoerg }
40947330f729Sjoerg
40957330f729Sjoerg /// parseDirectiveCVFileChecksums
40967330f729Sjoerg /// ::= .cv_filechecksums
parseDirectiveCVFileChecksums()40977330f729Sjoerg bool AsmParser::parseDirectiveCVFileChecksums() {
4098*82d56013Sjoerg getStreamer().emitCVFileChecksumsDirective();
40997330f729Sjoerg return false;
41007330f729Sjoerg }
41017330f729Sjoerg
41027330f729Sjoerg /// parseDirectiveCVFileChecksumOffset
41037330f729Sjoerg /// ::= .cv_filechecksumoffset fileno
parseDirectiveCVFileChecksumOffset()41047330f729Sjoerg bool AsmParser::parseDirectiveCVFileChecksumOffset() {
41057330f729Sjoerg int64_t FileNo;
41067330f729Sjoerg if (parseIntToken(FileNo, "expected identifier in directive"))
41077330f729Sjoerg return true;
41087330f729Sjoerg if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
41097330f729Sjoerg return true;
4110*82d56013Sjoerg getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
41117330f729Sjoerg return false;
41127330f729Sjoerg }
41137330f729Sjoerg
41147330f729Sjoerg /// parseDirectiveCVFPOData
41157330f729Sjoerg /// ::= .cv_fpo_data procsym
parseDirectiveCVFPOData()41167330f729Sjoerg bool AsmParser::parseDirectiveCVFPOData() {
41177330f729Sjoerg SMLoc DirLoc = getLexer().getLoc();
41187330f729Sjoerg StringRef ProcName;
41197330f729Sjoerg if (parseIdentifier(ProcName))
41207330f729Sjoerg return TokError("expected symbol name");
4121*82d56013Sjoerg if (parseEOL())
4122*82d56013Sjoerg return true;
41237330f729Sjoerg MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
41247330f729Sjoerg getStreamer().EmitCVFPOData(ProcSym, DirLoc);
41257330f729Sjoerg return false;
41267330f729Sjoerg }
41277330f729Sjoerg
41287330f729Sjoerg /// parseDirectiveCFISections
41297330f729Sjoerg /// ::= .cfi_sections section [, section]
parseDirectiveCFISections()41307330f729Sjoerg bool AsmParser::parseDirectiveCFISections() {
41317330f729Sjoerg StringRef Name;
41327330f729Sjoerg bool EH = false;
41337330f729Sjoerg bool Debug = false;
41347330f729Sjoerg
4135*82d56013Sjoerg if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4136*82d56013Sjoerg for (;;) {
41377330f729Sjoerg if (parseIdentifier(Name))
4138*82d56013Sjoerg return TokError("expected .eh_frame or .debug_frame");
41397330f729Sjoerg if (Name == ".eh_frame")
41407330f729Sjoerg EH = true;
41417330f729Sjoerg else if (Name == ".debug_frame")
41427330f729Sjoerg Debug = true;
4143*82d56013Sjoerg if (parseOptionalToken(AsmToken::EndOfStatement))
4144*82d56013Sjoerg break;
4145*82d56013Sjoerg if (parseComma())
4146*82d56013Sjoerg return true;
41477330f729Sjoerg }
4148*82d56013Sjoerg }
4149*82d56013Sjoerg getStreamer().emitCFISections(EH, Debug);
41507330f729Sjoerg return false;
41517330f729Sjoerg }
41527330f729Sjoerg
41537330f729Sjoerg /// parseDirectiveCFIStartProc
41547330f729Sjoerg /// ::= .cfi_startproc [simple]
parseDirectiveCFIStartProc()41557330f729Sjoerg bool AsmParser::parseDirectiveCFIStartProc() {
41567330f729Sjoerg StringRef Simple;
41577330f729Sjoerg if (!parseOptionalToken(AsmToken::EndOfStatement)) {
41587330f729Sjoerg if (check(parseIdentifier(Simple) || Simple != "simple",
41597330f729Sjoerg "unexpected token") ||
4160*82d56013Sjoerg parseEOL())
4161*82d56013Sjoerg return true;
41627330f729Sjoerg }
41637330f729Sjoerg
41647330f729Sjoerg // TODO(kristina): Deal with a corner case of incorrect diagnostic context
41657330f729Sjoerg // being produced if this directive is emitted as part of preprocessor macro
41667330f729Sjoerg // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
41677330f729Sjoerg // Tools like llvm-mc on the other hand are not affected by it, and report
41687330f729Sjoerg // correct context information.
4169*82d56013Sjoerg getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
41707330f729Sjoerg return false;
41717330f729Sjoerg }
41727330f729Sjoerg
41737330f729Sjoerg /// parseDirectiveCFIEndProc
41747330f729Sjoerg /// ::= .cfi_endproc
parseDirectiveCFIEndProc()41757330f729Sjoerg bool AsmParser::parseDirectiveCFIEndProc() {
4176*82d56013Sjoerg if (parseEOL())
4177*82d56013Sjoerg return true;
4178*82d56013Sjoerg getStreamer().emitCFIEndProc();
41797330f729Sjoerg return false;
41807330f729Sjoerg }
41817330f729Sjoerg
41827330f729Sjoerg /// parse register name or number.
parseRegisterOrRegisterNumber(int64_t & Register,SMLoc DirectiveLoc)41837330f729Sjoerg bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
41847330f729Sjoerg SMLoc DirectiveLoc) {
41857330f729Sjoerg unsigned RegNo;
41867330f729Sjoerg
41877330f729Sjoerg if (getLexer().isNot(AsmToken::Integer)) {
41887330f729Sjoerg if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc))
41897330f729Sjoerg return true;
41907330f729Sjoerg Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
41917330f729Sjoerg } else
41927330f729Sjoerg return parseAbsoluteExpression(Register);
41937330f729Sjoerg
41947330f729Sjoerg return false;
41957330f729Sjoerg }
41967330f729Sjoerg
41977330f729Sjoerg /// parseDirectiveCFIDefCfa
41987330f729Sjoerg /// ::= .cfi_def_cfa register, offset
parseDirectiveCFIDefCfa(SMLoc DirectiveLoc)41997330f729Sjoerg bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
42007330f729Sjoerg int64_t Register = 0, Offset = 0;
4201*82d56013Sjoerg if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4202*82d56013Sjoerg parseAbsoluteExpression(Offset) || parseEOL())
42037330f729Sjoerg return true;
42047330f729Sjoerg
4205*82d56013Sjoerg getStreamer().emitCFIDefCfa(Register, Offset);
42067330f729Sjoerg return false;
42077330f729Sjoerg }
42087330f729Sjoerg
42097330f729Sjoerg /// parseDirectiveCFIDefCfaOffset
42107330f729Sjoerg /// ::= .cfi_def_cfa_offset offset
parseDirectiveCFIDefCfaOffset()42117330f729Sjoerg bool AsmParser::parseDirectiveCFIDefCfaOffset() {
42127330f729Sjoerg int64_t Offset = 0;
4213*82d56013Sjoerg if (parseAbsoluteExpression(Offset) || parseEOL())
42147330f729Sjoerg return true;
42157330f729Sjoerg
4216*82d56013Sjoerg getStreamer().emitCFIDefCfaOffset(Offset);
42177330f729Sjoerg return false;
42187330f729Sjoerg }
42197330f729Sjoerg
42207330f729Sjoerg /// parseDirectiveCFIRegister
42217330f729Sjoerg /// ::= .cfi_register register, register
parseDirectiveCFIRegister(SMLoc DirectiveLoc)42227330f729Sjoerg bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
42237330f729Sjoerg int64_t Register1 = 0, Register2 = 0;
4224*82d56013Sjoerg if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || parseComma() ||
4225*82d56013Sjoerg parseRegisterOrRegisterNumber(Register2, DirectiveLoc) || parseEOL())
42267330f729Sjoerg return true;
42277330f729Sjoerg
4228*82d56013Sjoerg getStreamer().emitCFIRegister(Register1, Register2);
42297330f729Sjoerg return false;
42307330f729Sjoerg }
42317330f729Sjoerg
42327330f729Sjoerg /// parseDirectiveCFIWindowSave
42337330f729Sjoerg /// ::= .cfi_window_save
parseDirectiveCFIWindowSave()42347330f729Sjoerg bool AsmParser::parseDirectiveCFIWindowSave() {
4235*82d56013Sjoerg if (parseEOL())
4236*82d56013Sjoerg return true;
4237*82d56013Sjoerg getStreamer().emitCFIWindowSave();
42387330f729Sjoerg return false;
42397330f729Sjoerg }
42407330f729Sjoerg
42417330f729Sjoerg /// parseDirectiveCFIAdjustCfaOffset
42427330f729Sjoerg /// ::= .cfi_adjust_cfa_offset adjustment
parseDirectiveCFIAdjustCfaOffset()42437330f729Sjoerg bool AsmParser::parseDirectiveCFIAdjustCfaOffset() {
42447330f729Sjoerg int64_t Adjustment = 0;
4245*82d56013Sjoerg if (parseAbsoluteExpression(Adjustment) || parseEOL())
42467330f729Sjoerg return true;
42477330f729Sjoerg
4248*82d56013Sjoerg getStreamer().emitCFIAdjustCfaOffset(Adjustment);
42497330f729Sjoerg return false;
42507330f729Sjoerg }
42517330f729Sjoerg
42527330f729Sjoerg /// parseDirectiveCFIDefCfaRegister
42537330f729Sjoerg /// ::= .cfi_def_cfa_register register
parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc)42547330f729Sjoerg bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
42557330f729Sjoerg int64_t Register = 0;
4256*82d56013Sjoerg if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
42577330f729Sjoerg return true;
42587330f729Sjoerg
4259*82d56013Sjoerg getStreamer().emitCFIDefCfaRegister(Register);
42607330f729Sjoerg return false;
42617330f729Sjoerg }
42627330f729Sjoerg
42637330f729Sjoerg /// parseDirectiveCFIOffset
42647330f729Sjoerg /// ::= .cfi_offset register, offset
parseDirectiveCFIOffset(SMLoc DirectiveLoc)42657330f729Sjoerg bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
42667330f729Sjoerg int64_t Register = 0;
42677330f729Sjoerg int64_t Offset = 0;
42687330f729Sjoerg
4269*82d56013Sjoerg if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4270*82d56013Sjoerg parseAbsoluteExpression(Offset) || parseEOL())
42717330f729Sjoerg return true;
42727330f729Sjoerg
4273*82d56013Sjoerg getStreamer().emitCFIOffset(Register, Offset);
42747330f729Sjoerg return false;
42757330f729Sjoerg }
42767330f729Sjoerg
42777330f729Sjoerg /// parseDirectiveCFIRelOffset
42787330f729Sjoerg /// ::= .cfi_rel_offset register, offset
parseDirectiveCFIRelOffset(SMLoc DirectiveLoc)42797330f729Sjoerg bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
42807330f729Sjoerg int64_t Register = 0, Offset = 0;
42817330f729Sjoerg
4282*82d56013Sjoerg if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4283*82d56013Sjoerg parseAbsoluteExpression(Offset) || parseEOL())
42847330f729Sjoerg return true;
42857330f729Sjoerg
4286*82d56013Sjoerg getStreamer().emitCFIRelOffset(Register, Offset);
42877330f729Sjoerg return false;
42887330f729Sjoerg }
42897330f729Sjoerg
isValidEncoding(int64_t Encoding)42907330f729Sjoerg static bool isValidEncoding(int64_t Encoding) {
42917330f729Sjoerg if (Encoding & ~0xff)
42927330f729Sjoerg return false;
42937330f729Sjoerg
42947330f729Sjoerg if (Encoding == dwarf::DW_EH_PE_omit)
42957330f729Sjoerg return true;
42967330f729Sjoerg
42977330f729Sjoerg const unsigned Format = Encoding & 0xf;
42987330f729Sjoerg if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
42997330f729Sjoerg Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
43007330f729Sjoerg Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
43017330f729Sjoerg Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
43027330f729Sjoerg return false;
43037330f729Sjoerg
43047330f729Sjoerg const unsigned Application = Encoding & 0x70;
43057330f729Sjoerg if (Application != dwarf::DW_EH_PE_absptr &&
43067330f729Sjoerg Application != dwarf::DW_EH_PE_pcrel)
43077330f729Sjoerg return false;
43087330f729Sjoerg
43097330f729Sjoerg return true;
43107330f729Sjoerg }
43117330f729Sjoerg
43127330f729Sjoerg /// parseDirectiveCFIPersonalityOrLsda
43137330f729Sjoerg /// IsPersonality true for cfi_personality, false for cfi_lsda
43147330f729Sjoerg /// ::= .cfi_personality encoding, [symbol_name]
43157330f729Sjoerg /// ::= .cfi_lsda encoding, [symbol_name]
parseDirectiveCFIPersonalityOrLsda(bool IsPersonality)43167330f729Sjoerg bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
43177330f729Sjoerg int64_t Encoding = 0;
43187330f729Sjoerg if (parseAbsoluteExpression(Encoding))
43197330f729Sjoerg return true;
43207330f729Sjoerg if (Encoding == dwarf::DW_EH_PE_omit)
43217330f729Sjoerg return false;
43227330f729Sjoerg
43237330f729Sjoerg StringRef Name;
43247330f729Sjoerg if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
4325*82d56013Sjoerg parseComma() ||
4326*82d56013Sjoerg check(parseIdentifier(Name), "expected identifier in directive") ||
4327*82d56013Sjoerg parseEOL())
43287330f729Sjoerg return true;
43297330f729Sjoerg
43307330f729Sjoerg MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
43317330f729Sjoerg
43327330f729Sjoerg if (IsPersonality)
4333*82d56013Sjoerg getStreamer().emitCFIPersonality(Sym, Encoding);
43347330f729Sjoerg else
4335*82d56013Sjoerg getStreamer().emitCFILsda(Sym, Encoding);
43367330f729Sjoerg return false;
43377330f729Sjoerg }
43387330f729Sjoerg
43397330f729Sjoerg /// parseDirectiveCFIRememberState
43407330f729Sjoerg /// ::= .cfi_remember_state
parseDirectiveCFIRememberState()43417330f729Sjoerg bool AsmParser::parseDirectiveCFIRememberState() {
4342*82d56013Sjoerg if (parseEOL())
4343*82d56013Sjoerg return true;
4344*82d56013Sjoerg getStreamer().emitCFIRememberState();
43457330f729Sjoerg return false;
43467330f729Sjoerg }
43477330f729Sjoerg
43487330f729Sjoerg /// parseDirectiveCFIRestoreState
43497330f729Sjoerg /// ::= .cfi_remember_state
parseDirectiveCFIRestoreState()43507330f729Sjoerg bool AsmParser::parseDirectiveCFIRestoreState() {
4351*82d56013Sjoerg if (parseEOL())
4352*82d56013Sjoerg return true;
4353*82d56013Sjoerg getStreamer().emitCFIRestoreState();
43547330f729Sjoerg return false;
43557330f729Sjoerg }
43567330f729Sjoerg
43577330f729Sjoerg /// parseDirectiveCFISameValue
43587330f729Sjoerg /// ::= .cfi_same_value register
parseDirectiveCFISameValue(SMLoc DirectiveLoc)43597330f729Sjoerg bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
43607330f729Sjoerg int64_t Register = 0;
43617330f729Sjoerg
4362*82d56013Sjoerg if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
43637330f729Sjoerg return true;
43647330f729Sjoerg
4365*82d56013Sjoerg getStreamer().emitCFISameValue(Register);
43667330f729Sjoerg return false;
43677330f729Sjoerg }
43687330f729Sjoerg
43697330f729Sjoerg /// parseDirectiveCFIRestore
43707330f729Sjoerg /// ::= .cfi_restore register
parseDirectiveCFIRestore(SMLoc DirectiveLoc)43717330f729Sjoerg bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
43727330f729Sjoerg int64_t Register = 0;
4373*82d56013Sjoerg if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
43747330f729Sjoerg return true;
43757330f729Sjoerg
4376*82d56013Sjoerg getStreamer().emitCFIRestore(Register);
43777330f729Sjoerg return false;
43787330f729Sjoerg }
43797330f729Sjoerg
43807330f729Sjoerg /// parseDirectiveCFIEscape
43817330f729Sjoerg /// ::= .cfi_escape expression[,...]
parseDirectiveCFIEscape()43827330f729Sjoerg bool AsmParser::parseDirectiveCFIEscape() {
43837330f729Sjoerg std::string Values;
43847330f729Sjoerg int64_t CurrValue;
43857330f729Sjoerg if (parseAbsoluteExpression(CurrValue))
43867330f729Sjoerg return true;
43877330f729Sjoerg
43887330f729Sjoerg Values.push_back((uint8_t)CurrValue);
43897330f729Sjoerg
43907330f729Sjoerg while (getLexer().is(AsmToken::Comma)) {
43917330f729Sjoerg Lex();
43927330f729Sjoerg
43937330f729Sjoerg if (parseAbsoluteExpression(CurrValue))
43947330f729Sjoerg return true;
43957330f729Sjoerg
43967330f729Sjoerg Values.push_back((uint8_t)CurrValue);
43977330f729Sjoerg }
43987330f729Sjoerg
4399*82d56013Sjoerg getStreamer().emitCFIEscape(Values);
44007330f729Sjoerg return false;
44017330f729Sjoerg }
44027330f729Sjoerg
44037330f729Sjoerg /// parseDirectiveCFIReturnColumn
44047330f729Sjoerg /// ::= .cfi_return_column register
parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc)44057330f729Sjoerg bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
44067330f729Sjoerg int64_t Register = 0;
4407*82d56013Sjoerg if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
44087330f729Sjoerg return true;
4409*82d56013Sjoerg getStreamer().emitCFIReturnColumn(Register);
44107330f729Sjoerg return false;
44117330f729Sjoerg }
44127330f729Sjoerg
44137330f729Sjoerg /// parseDirectiveCFISignalFrame
44147330f729Sjoerg /// ::= .cfi_signal_frame
parseDirectiveCFISignalFrame()44157330f729Sjoerg bool AsmParser::parseDirectiveCFISignalFrame() {
4416*82d56013Sjoerg if (parseEOL())
44177330f729Sjoerg return true;
44187330f729Sjoerg
4419*82d56013Sjoerg getStreamer().emitCFISignalFrame();
44207330f729Sjoerg return false;
44217330f729Sjoerg }
44227330f729Sjoerg
44237330f729Sjoerg /// parseDirectiveCFIUndefined
44247330f729Sjoerg /// ::= .cfi_undefined register
parseDirectiveCFIUndefined(SMLoc DirectiveLoc)44257330f729Sjoerg bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
44267330f729Sjoerg int64_t Register = 0;
44277330f729Sjoerg
4428*82d56013Sjoerg if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
44297330f729Sjoerg return true;
44307330f729Sjoerg
4431*82d56013Sjoerg getStreamer().emitCFIUndefined(Register);
44327330f729Sjoerg return false;
44337330f729Sjoerg }
44347330f729Sjoerg
44357330f729Sjoerg /// parseDirectiveAltmacro
44367330f729Sjoerg /// ::= .altmacro
44377330f729Sjoerg /// ::= .noaltmacro
parseDirectiveAltmacro(StringRef Directive)44387330f729Sjoerg bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
4439*82d56013Sjoerg if (parseEOL())
4440*82d56013Sjoerg return true;
44417330f729Sjoerg AltMacroMode = (Directive == ".altmacro");
44427330f729Sjoerg return false;
44437330f729Sjoerg }
44447330f729Sjoerg
44457330f729Sjoerg /// parseDirectiveMacrosOnOff
44467330f729Sjoerg /// ::= .macros_on
44477330f729Sjoerg /// ::= .macros_off
parseDirectiveMacrosOnOff(StringRef Directive)44487330f729Sjoerg bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
4449*82d56013Sjoerg if (parseEOL())
44507330f729Sjoerg return true;
44517330f729Sjoerg setMacrosEnabled(Directive == ".macros_on");
44527330f729Sjoerg return false;
44537330f729Sjoerg }
44547330f729Sjoerg
44557330f729Sjoerg /// parseDirectiveMacro
44567330f729Sjoerg /// ::= .macro name[,] [parameters]
parseDirectiveMacro(SMLoc DirectiveLoc)44577330f729Sjoerg bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
44587330f729Sjoerg StringRef Name;
44597330f729Sjoerg if (parseIdentifier(Name))
44607330f729Sjoerg return TokError("expected identifier in '.macro' directive");
44617330f729Sjoerg
44627330f729Sjoerg if (getLexer().is(AsmToken::Comma))
44637330f729Sjoerg Lex();
44647330f729Sjoerg
44657330f729Sjoerg MCAsmMacroParameters Parameters;
44667330f729Sjoerg while (getLexer().isNot(AsmToken::EndOfStatement)) {
44677330f729Sjoerg
44687330f729Sjoerg if (!Parameters.empty() && Parameters.back().Vararg)
4469*82d56013Sjoerg return Error(Lexer.getLoc(), "vararg parameter '" +
4470*82d56013Sjoerg Parameters.back().Name +
4471*82d56013Sjoerg "' should be the last parameter");
44727330f729Sjoerg
44737330f729Sjoerg MCAsmMacroParameter Parameter;
44747330f729Sjoerg if (parseIdentifier(Parameter.Name))
44757330f729Sjoerg return TokError("expected identifier in '.macro' directive");
44767330f729Sjoerg
44777330f729Sjoerg // Emit an error if two (or more) named parameters share the same name
44787330f729Sjoerg for (const MCAsmMacroParameter& CurrParam : Parameters)
44797330f729Sjoerg if (CurrParam.Name.equals(Parameter.Name))
44807330f729Sjoerg return TokError("macro '" + Name + "' has multiple parameters"
44817330f729Sjoerg " named '" + Parameter.Name + "'");
44827330f729Sjoerg
44837330f729Sjoerg if (Lexer.is(AsmToken::Colon)) {
44847330f729Sjoerg Lex(); // consume ':'
44857330f729Sjoerg
44867330f729Sjoerg SMLoc QualLoc;
44877330f729Sjoerg StringRef Qualifier;
44887330f729Sjoerg
44897330f729Sjoerg QualLoc = Lexer.getLoc();
44907330f729Sjoerg if (parseIdentifier(Qualifier))
44917330f729Sjoerg return Error(QualLoc, "missing parameter qualifier for "
44927330f729Sjoerg "'" + Parameter.Name + "' in macro '" + Name + "'");
44937330f729Sjoerg
44947330f729Sjoerg if (Qualifier == "req")
44957330f729Sjoerg Parameter.Required = true;
44967330f729Sjoerg else if (Qualifier == "vararg")
44977330f729Sjoerg Parameter.Vararg = true;
44987330f729Sjoerg else
44997330f729Sjoerg return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
45007330f729Sjoerg "for '" + Parameter.Name + "' in macro '" + Name + "'");
45017330f729Sjoerg }
45027330f729Sjoerg
45037330f729Sjoerg if (getLexer().is(AsmToken::Equal)) {
45047330f729Sjoerg Lex();
45057330f729Sjoerg
45067330f729Sjoerg SMLoc ParamLoc;
45077330f729Sjoerg
45087330f729Sjoerg ParamLoc = Lexer.getLoc();
45097330f729Sjoerg if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
45107330f729Sjoerg return true;
45117330f729Sjoerg
45127330f729Sjoerg if (Parameter.Required)
45137330f729Sjoerg Warning(ParamLoc, "pointless default value for required parameter "
45147330f729Sjoerg "'" + Parameter.Name + "' in macro '" + Name + "'");
45157330f729Sjoerg }
45167330f729Sjoerg
45177330f729Sjoerg Parameters.push_back(std::move(Parameter));
45187330f729Sjoerg
45197330f729Sjoerg if (getLexer().is(AsmToken::Comma))
45207330f729Sjoerg Lex();
45217330f729Sjoerg }
45227330f729Sjoerg
45237330f729Sjoerg // Eat just the end of statement.
45247330f729Sjoerg Lexer.Lex();
45257330f729Sjoerg
45267330f729Sjoerg // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors
45277330f729Sjoerg AsmToken EndToken, StartToken = getTok();
45287330f729Sjoerg unsigned MacroDepth = 0;
45297330f729Sjoerg // Lex the macro definition.
45307330f729Sjoerg while (true) {
45317330f729Sjoerg // Ignore Lexing errors in macros.
45327330f729Sjoerg while (Lexer.is(AsmToken::Error)) {
45337330f729Sjoerg Lexer.Lex();
45347330f729Sjoerg }
45357330f729Sjoerg
45367330f729Sjoerg // Check whether we have reached the end of the file.
45377330f729Sjoerg if (getLexer().is(AsmToken::Eof))
45387330f729Sjoerg return Error(DirectiveLoc, "no matching '.endmacro' in definition");
45397330f729Sjoerg
4540*82d56013Sjoerg // Otherwise, check whether we have reach the .endmacro or the start of a
4541*82d56013Sjoerg // preprocessor line marker.
45427330f729Sjoerg if (getLexer().is(AsmToken::Identifier)) {
45437330f729Sjoerg if (getTok().getIdentifier() == ".endm" ||
45447330f729Sjoerg getTok().getIdentifier() == ".endmacro") {
45457330f729Sjoerg if (MacroDepth == 0) { // Outermost macro.
45467330f729Sjoerg EndToken = getTok();
45477330f729Sjoerg Lexer.Lex();
45487330f729Sjoerg if (getLexer().isNot(AsmToken::EndOfStatement))
45497330f729Sjoerg return TokError("unexpected token in '" + EndToken.getIdentifier() +
45507330f729Sjoerg "' directive");
45517330f729Sjoerg break;
45527330f729Sjoerg } else {
45537330f729Sjoerg // Otherwise we just found the end of an inner macro.
45547330f729Sjoerg --MacroDepth;
45557330f729Sjoerg }
45567330f729Sjoerg } else if (getTok().getIdentifier() == ".macro") {
45577330f729Sjoerg // We allow nested macros. Those aren't instantiated until the outermost
45587330f729Sjoerg // macro is expanded so just ignore them for now.
45597330f729Sjoerg ++MacroDepth;
45607330f729Sjoerg }
4561*82d56013Sjoerg } else if (Lexer.is(AsmToken::HashDirective)) {
4562*82d56013Sjoerg (void)parseCppHashLineFilenameComment(getLexer().getLoc());
45637330f729Sjoerg }
45647330f729Sjoerg
45657330f729Sjoerg // Otherwise, scan til the end of the statement.
45667330f729Sjoerg eatToEndOfStatement();
45677330f729Sjoerg }
45687330f729Sjoerg
45697330f729Sjoerg if (getContext().lookupMacro(Name)) {
45707330f729Sjoerg return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
45717330f729Sjoerg }
45727330f729Sjoerg
45737330f729Sjoerg const char *BodyStart = StartToken.getLoc().getPointer();
45747330f729Sjoerg const char *BodyEnd = EndToken.getLoc().getPointer();
45757330f729Sjoerg StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
45767330f729Sjoerg checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
45777330f729Sjoerg MCAsmMacro Macro(Name, Body, std::move(Parameters));
45787330f729Sjoerg DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
45797330f729Sjoerg Macro.dump());
45807330f729Sjoerg getContext().defineMacro(Name, std::move(Macro));
45817330f729Sjoerg return false;
45827330f729Sjoerg }
45837330f729Sjoerg
45847330f729Sjoerg /// checkForBadMacro
45857330f729Sjoerg ///
45867330f729Sjoerg /// With the support added for named parameters there may be code out there that
45877330f729Sjoerg /// is transitioning from positional parameters. In versions of gas that did
45887330f729Sjoerg /// not support named parameters they would be ignored on the macro definition.
45897330f729Sjoerg /// But to support both styles of parameters this is not possible so if a macro
45907330f729Sjoerg /// definition has named parameters but does not use them and has what appears
45917330f729Sjoerg /// to be positional parameters, strings like $1, $2, ... and $n, then issue a
45927330f729Sjoerg /// warning that the positional parameter found in body which have no effect.
45937330f729Sjoerg /// Hoping the developer will either remove the named parameters from the macro
45947330f729Sjoerg /// definition so the positional parameters get used if that was what was
45957330f729Sjoerg /// intended or change the macro to use the named parameters. It is possible
45967330f729Sjoerg /// this warning will trigger when the none of the named parameters are used
45977330f729Sjoerg /// and the strings like $1 are infact to simply to be passed trough unchanged.
checkForBadMacro(SMLoc DirectiveLoc,StringRef Name,StringRef Body,ArrayRef<MCAsmMacroParameter> Parameters)45987330f729Sjoerg void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
45997330f729Sjoerg StringRef Body,
46007330f729Sjoerg ArrayRef<MCAsmMacroParameter> Parameters) {
46017330f729Sjoerg // If this macro is not defined with named parameters the warning we are
46027330f729Sjoerg // checking for here doesn't apply.
46037330f729Sjoerg unsigned NParameters = Parameters.size();
46047330f729Sjoerg if (NParameters == 0)
46057330f729Sjoerg return;
46067330f729Sjoerg
46077330f729Sjoerg bool NamedParametersFound = false;
46087330f729Sjoerg bool PositionalParametersFound = false;
46097330f729Sjoerg
46107330f729Sjoerg // Look at the body of the macro for use of both the named parameters and what
46117330f729Sjoerg // are likely to be positional parameters. This is what expandMacro() is
46127330f729Sjoerg // doing when it finds the parameters in the body.
46137330f729Sjoerg while (!Body.empty()) {
46147330f729Sjoerg // Scan for the next possible parameter.
46157330f729Sjoerg std::size_t End = Body.size(), Pos = 0;
46167330f729Sjoerg for (; Pos != End; ++Pos) {
46177330f729Sjoerg // Check for a substitution or escape.
46187330f729Sjoerg // This macro is defined with parameters, look for \foo, \bar, etc.
46197330f729Sjoerg if (Body[Pos] == '\\' && Pos + 1 != End)
46207330f729Sjoerg break;
46217330f729Sjoerg
46227330f729Sjoerg // This macro should have parameters, but look for $0, $1, ..., $n too.
46237330f729Sjoerg if (Body[Pos] != '$' || Pos + 1 == End)
46247330f729Sjoerg continue;
46257330f729Sjoerg char Next = Body[Pos + 1];
46267330f729Sjoerg if (Next == '$' || Next == 'n' ||
46277330f729Sjoerg isdigit(static_cast<unsigned char>(Next)))
46287330f729Sjoerg break;
46297330f729Sjoerg }
46307330f729Sjoerg
46317330f729Sjoerg // Check if we reached the end.
46327330f729Sjoerg if (Pos == End)
46337330f729Sjoerg break;
46347330f729Sjoerg
46357330f729Sjoerg if (Body[Pos] == '$') {
46367330f729Sjoerg switch (Body[Pos + 1]) {
46377330f729Sjoerg // $$ => $
46387330f729Sjoerg case '$':
46397330f729Sjoerg break;
46407330f729Sjoerg
46417330f729Sjoerg // $n => number of arguments
46427330f729Sjoerg case 'n':
46437330f729Sjoerg PositionalParametersFound = true;
46447330f729Sjoerg break;
46457330f729Sjoerg
46467330f729Sjoerg // $[0-9] => argument
46477330f729Sjoerg default: {
46487330f729Sjoerg PositionalParametersFound = true;
46497330f729Sjoerg break;
46507330f729Sjoerg }
46517330f729Sjoerg }
46527330f729Sjoerg Pos += 2;
46537330f729Sjoerg } else {
46547330f729Sjoerg unsigned I = Pos + 1;
46557330f729Sjoerg while (isIdentifierChar(Body[I]) && I + 1 != End)
46567330f729Sjoerg ++I;
46577330f729Sjoerg
46587330f729Sjoerg const char *Begin = Body.data() + Pos + 1;
46597330f729Sjoerg StringRef Argument(Begin, I - (Pos + 1));
46607330f729Sjoerg unsigned Index = 0;
46617330f729Sjoerg for (; Index < NParameters; ++Index)
46627330f729Sjoerg if (Parameters[Index].Name == Argument)
46637330f729Sjoerg break;
46647330f729Sjoerg
46657330f729Sjoerg if (Index == NParameters) {
46667330f729Sjoerg if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
46677330f729Sjoerg Pos += 3;
46687330f729Sjoerg else {
46697330f729Sjoerg Pos = I;
46707330f729Sjoerg }
46717330f729Sjoerg } else {
46727330f729Sjoerg NamedParametersFound = true;
46737330f729Sjoerg Pos += 1 + Argument.size();
46747330f729Sjoerg }
46757330f729Sjoerg }
46767330f729Sjoerg // Update the scan point.
46777330f729Sjoerg Body = Body.substr(Pos);
46787330f729Sjoerg }
46797330f729Sjoerg
46807330f729Sjoerg if (!NamedParametersFound && PositionalParametersFound)
46817330f729Sjoerg Warning(DirectiveLoc, "macro defined with named parameters which are not "
46827330f729Sjoerg "used in macro body, possible positional parameter "
46837330f729Sjoerg "found in body which will have no effect");
46847330f729Sjoerg }
46857330f729Sjoerg
46867330f729Sjoerg /// parseDirectiveExitMacro
46877330f729Sjoerg /// ::= .exitm
parseDirectiveExitMacro(StringRef Directive)46887330f729Sjoerg bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
4689*82d56013Sjoerg if (parseEOL())
46907330f729Sjoerg return true;
46917330f729Sjoerg
46927330f729Sjoerg if (!isInsideMacroInstantiation())
46937330f729Sjoerg return TokError("unexpected '" + Directive + "' in file, "
46947330f729Sjoerg "no current macro definition");
46957330f729Sjoerg
46967330f729Sjoerg // Exit all conditionals that are active in the current macro.
46977330f729Sjoerg while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
46987330f729Sjoerg TheCondState = TheCondStack.back();
46997330f729Sjoerg TheCondStack.pop_back();
47007330f729Sjoerg }
47017330f729Sjoerg
47027330f729Sjoerg handleMacroExit();
47037330f729Sjoerg return false;
47047330f729Sjoerg }
47057330f729Sjoerg
47067330f729Sjoerg /// parseDirectiveEndMacro
47077330f729Sjoerg /// ::= .endm
47087330f729Sjoerg /// ::= .endmacro
parseDirectiveEndMacro(StringRef Directive)47097330f729Sjoerg bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
47107330f729Sjoerg if (getLexer().isNot(AsmToken::EndOfStatement))
47117330f729Sjoerg return TokError("unexpected token in '" + Directive + "' directive");
47127330f729Sjoerg
47137330f729Sjoerg // If we are inside a macro instantiation, terminate the current
47147330f729Sjoerg // instantiation.
47157330f729Sjoerg if (isInsideMacroInstantiation()) {
47167330f729Sjoerg handleMacroExit();
47177330f729Sjoerg return false;
47187330f729Sjoerg }
47197330f729Sjoerg
47207330f729Sjoerg // Otherwise, this .endmacro is a stray entry in the file; well formed
47217330f729Sjoerg // .endmacro directives are handled during the macro definition parsing.
47227330f729Sjoerg return TokError("unexpected '" + Directive + "' in file, "
47237330f729Sjoerg "no current macro definition");
47247330f729Sjoerg }
47257330f729Sjoerg
47267330f729Sjoerg /// parseDirectivePurgeMacro
4727*82d56013Sjoerg /// ::= .purgem name
parseDirectivePurgeMacro(SMLoc DirectiveLoc)47287330f729Sjoerg bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
47297330f729Sjoerg StringRef Name;
47307330f729Sjoerg SMLoc Loc;
47317330f729Sjoerg if (parseTokenLoc(Loc) ||
47327330f729Sjoerg check(parseIdentifier(Name), Loc,
47337330f729Sjoerg "expected identifier in '.purgem' directive") ||
4734*82d56013Sjoerg parseEOL())
47357330f729Sjoerg return true;
47367330f729Sjoerg
47377330f729Sjoerg if (!getContext().lookupMacro(Name))
47387330f729Sjoerg return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
47397330f729Sjoerg
47407330f729Sjoerg getContext().undefineMacro(Name);
47417330f729Sjoerg DEBUG_WITH_TYPE("asm-macros", dbgs()
47427330f729Sjoerg << "Un-defining macro: " << Name << "\n");
47437330f729Sjoerg return false;
47447330f729Sjoerg }
47457330f729Sjoerg
47467330f729Sjoerg /// parseDirectiveBundleAlignMode
47477330f729Sjoerg /// ::= {.bundle_align_mode} expression
parseDirectiveBundleAlignMode()47487330f729Sjoerg bool AsmParser::parseDirectiveBundleAlignMode() {
47497330f729Sjoerg // Expect a single argument: an expression that evaluates to a constant
47507330f729Sjoerg // in the inclusive range 0-30.
47517330f729Sjoerg SMLoc ExprLoc = getLexer().getLoc();
47527330f729Sjoerg int64_t AlignSizePow2;
47537330f729Sjoerg if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||
4754*82d56013Sjoerg parseEOL() ||
47557330f729Sjoerg check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc,
47567330f729Sjoerg "invalid bundle alignment size (expected between 0 and 30)"))
47577330f729Sjoerg return true;
47587330f729Sjoerg
47597330f729Sjoerg // Because of AlignSizePow2's verified range we can safely truncate it to
47607330f729Sjoerg // unsigned.
4761*82d56013Sjoerg getStreamer().emitBundleAlignMode(static_cast<unsigned>(AlignSizePow2));
47627330f729Sjoerg return false;
47637330f729Sjoerg }
47647330f729Sjoerg
47657330f729Sjoerg /// parseDirectiveBundleLock
47667330f729Sjoerg /// ::= {.bundle_lock} [align_to_end]
parseDirectiveBundleLock()47677330f729Sjoerg bool AsmParser::parseDirectiveBundleLock() {
47687330f729Sjoerg if (checkForValidSection())
47697330f729Sjoerg return true;
47707330f729Sjoerg bool AlignToEnd = false;
47717330f729Sjoerg
47727330f729Sjoerg StringRef Option;
47737330f729Sjoerg SMLoc Loc = getTok().getLoc();
47747330f729Sjoerg const char *kInvalidOptionError =
47757330f729Sjoerg "invalid option for '.bundle_lock' directive";
47767330f729Sjoerg
47777330f729Sjoerg if (!parseOptionalToken(AsmToken::EndOfStatement)) {
47787330f729Sjoerg if (check(parseIdentifier(Option), Loc, kInvalidOptionError) ||
4779*82d56013Sjoerg check(Option != "align_to_end", Loc, kInvalidOptionError) || parseEOL())
47807330f729Sjoerg return true;
47817330f729Sjoerg AlignToEnd = true;
47827330f729Sjoerg }
47837330f729Sjoerg
4784*82d56013Sjoerg getStreamer().emitBundleLock(AlignToEnd);
47857330f729Sjoerg return false;
47867330f729Sjoerg }
47877330f729Sjoerg
47887330f729Sjoerg /// parseDirectiveBundleLock
47897330f729Sjoerg /// ::= {.bundle_lock}
parseDirectiveBundleUnlock()47907330f729Sjoerg bool AsmParser::parseDirectiveBundleUnlock() {
4791*82d56013Sjoerg if (checkForValidSection() || parseEOL())
47927330f729Sjoerg return true;
47937330f729Sjoerg
4794*82d56013Sjoerg getStreamer().emitBundleUnlock();
47957330f729Sjoerg return false;
47967330f729Sjoerg }
47977330f729Sjoerg
47987330f729Sjoerg /// parseDirectiveSpace
47997330f729Sjoerg /// ::= (.skip | .space) expression [ , expression ]
parseDirectiveSpace(StringRef IDVal)48007330f729Sjoerg bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
48017330f729Sjoerg SMLoc NumBytesLoc = Lexer.getLoc();
48027330f729Sjoerg const MCExpr *NumBytes;
48037330f729Sjoerg if (checkForValidSection() || parseExpression(NumBytes))
48047330f729Sjoerg return true;
48057330f729Sjoerg
48067330f729Sjoerg int64_t FillExpr = 0;
48077330f729Sjoerg if (parseOptionalToken(AsmToken::Comma))
48087330f729Sjoerg if (parseAbsoluteExpression(FillExpr))
4809*82d56013Sjoerg return true;
4810*82d56013Sjoerg if (parseEOL())
4811*82d56013Sjoerg return true;
48127330f729Sjoerg
48137330f729Sjoerg // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
48147330f729Sjoerg getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
48157330f729Sjoerg
48167330f729Sjoerg return false;
48177330f729Sjoerg }
48187330f729Sjoerg
48197330f729Sjoerg /// parseDirectiveDCB
48207330f729Sjoerg /// ::= .dcb.{b, l, w} expression, expression
parseDirectiveDCB(StringRef IDVal,unsigned Size)48217330f729Sjoerg bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
48227330f729Sjoerg SMLoc NumValuesLoc = Lexer.getLoc();
48237330f729Sjoerg int64_t NumValues;
48247330f729Sjoerg if (checkForValidSection() || parseAbsoluteExpression(NumValues))
48257330f729Sjoerg return true;
48267330f729Sjoerg
48277330f729Sjoerg if (NumValues < 0) {
48287330f729Sjoerg Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
48297330f729Sjoerg return false;
48307330f729Sjoerg }
48317330f729Sjoerg
4832*82d56013Sjoerg if (parseComma())
48337330f729Sjoerg return true;
48347330f729Sjoerg
48357330f729Sjoerg const MCExpr *Value;
48367330f729Sjoerg SMLoc ExprLoc = getLexer().getLoc();
48377330f729Sjoerg if (parseExpression(Value))
48387330f729Sjoerg return true;
48397330f729Sjoerg
48407330f729Sjoerg // Special case constant expressions to match code generator.
48417330f729Sjoerg if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
48427330f729Sjoerg assert(Size <= 8 && "Invalid size");
48437330f729Sjoerg uint64_t IntValue = MCE->getValue();
48447330f729Sjoerg if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
48457330f729Sjoerg return Error(ExprLoc, "literal value out of range for directive");
48467330f729Sjoerg for (uint64_t i = 0, e = NumValues; i != e; ++i)
4847*82d56013Sjoerg getStreamer().emitIntValue(IntValue, Size);
48487330f729Sjoerg } else {
48497330f729Sjoerg for (uint64_t i = 0, e = NumValues; i != e; ++i)
4850*82d56013Sjoerg getStreamer().emitValue(Value, Size, ExprLoc);
48517330f729Sjoerg }
48527330f729Sjoerg
4853*82d56013Sjoerg return parseEOL();
48547330f729Sjoerg }
48557330f729Sjoerg
48567330f729Sjoerg /// parseDirectiveRealDCB
48577330f729Sjoerg /// ::= .dcb.{d, s} expression, expression
parseDirectiveRealDCB(StringRef IDVal,const fltSemantics & Semantics)48587330f729Sjoerg bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {
48597330f729Sjoerg SMLoc NumValuesLoc = Lexer.getLoc();
48607330f729Sjoerg int64_t NumValues;
48617330f729Sjoerg if (checkForValidSection() || parseAbsoluteExpression(NumValues))
48627330f729Sjoerg return true;
48637330f729Sjoerg
48647330f729Sjoerg if (NumValues < 0) {
48657330f729Sjoerg Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
48667330f729Sjoerg return false;
48677330f729Sjoerg }
48687330f729Sjoerg
4869*82d56013Sjoerg if (parseComma())
48707330f729Sjoerg return true;
48717330f729Sjoerg
48727330f729Sjoerg APInt AsInt;
4873*82d56013Sjoerg if (parseRealValue(Semantics, AsInt) || parseEOL())
48747330f729Sjoerg return true;
48757330f729Sjoerg
48767330f729Sjoerg for (uint64_t i = 0, e = NumValues; i != e; ++i)
4877*82d56013Sjoerg getStreamer().emitIntValue(AsInt.getLimitedValue(),
48787330f729Sjoerg AsInt.getBitWidth() / 8);
48797330f729Sjoerg
48807330f729Sjoerg return false;
48817330f729Sjoerg }
48827330f729Sjoerg
48837330f729Sjoerg /// parseDirectiveDS
48847330f729Sjoerg /// ::= .ds.{b, d, l, p, s, w, x} expression
parseDirectiveDS(StringRef IDVal,unsigned Size)48857330f729Sjoerg bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {
48867330f729Sjoerg SMLoc NumValuesLoc = Lexer.getLoc();
48877330f729Sjoerg int64_t NumValues;
4888*82d56013Sjoerg if (checkForValidSection() || parseAbsoluteExpression(NumValues) ||
4889*82d56013Sjoerg parseEOL())
48907330f729Sjoerg return true;
48917330f729Sjoerg
48927330f729Sjoerg if (NumValues < 0) {
48937330f729Sjoerg Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
48947330f729Sjoerg return false;
48957330f729Sjoerg }
48967330f729Sjoerg
48977330f729Sjoerg for (uint64_t i = 0, e = NumValues; i != e; ++i)
48987330f729Sjoerg getStreamer().emitFill(Size, 0);
48997330f729Sjoerg
49007330f729Sjoerg return false;
49017330f729Sjoerg }
49027330f729Sjoerg
49037330f729Sjoerg /// parseDirectiveLEB128
49047330f729Sjoerg /// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
parseDirectiveLEB128(bool Signed)49057330f729Sjoerg bool AsmParser::parseDirectiveLEB128(bool Signed) {
49067330f729Sjoerg if (checkForValidSection())
49077330f729Sjoerg return true;
49087330f729Sjoerg
49097330f729Sjoerg auto parseOp = [&]() -> bool {
49107330f729Sjoerg const MCExpr *Value;
49117330f729Sjoerg if (parseExpression(Value))
49127330f729Sjoerg return true;
49137330f729Sjoerg if (Signed)
4914*82d56013Sjoerg getStreamer().emitSLEB128Value(Value);
49157330f729Sjoerg else
4916*82d56013Sjoerg getStreamer().emitULEB128Value(Value);
49177330f729Sjoerg return false;
49187330f729Sjoerg };
49197330f729Sjoerg
4920*82d56013Sjoerg return parseMany(parseOp);
49217330f729Sjoerg }
49227330f729Sjoerg
49237330f729Sjoerg /// parseDirectiveSymbolAttribute
49247330f729Sjoerg /// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
parseDirectiveSymbolAttribute(MCSymbolAttr Attr)49257330f729Sjoerg bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
49267330f729Sjoerg auto parseOp = [&]() -> bool {
49277330f729Sjoerg StringRef Name;
49287330f729Sjoerg SMLoc Loc = getTok().getLoc();
49297330f729Sjoerg if (parseIdentifier(Name))
49307330f729Sjoerg return Error(Loc, "expected identifier");
4931*82d56013Sjoerg
4932*82d56013Sjoerg if (discardLTOSymbol(Name))
4933*82d56013Sjoerg return false;
4934*82d56013Sjoerg
49357330f729Sjoerg MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
49367330f729Sjoerg
49377330f729Sjoerg // Assembler local symbols don't make any sense here. Complain loudly.
49387330f729Sjoerg if (Sym->isTemporary())
49397330f729Sjoerg return Error(Loc, "non-local symbol required");
49407330f729Sjoerg
4941*82d56013Sjoerg if (!getStreamer().emitSymbolAttribute(Sym, Attr))
49427330f729Sjoerg return Error(Loc, "unable to emit symbol attribute");
49437330f729Sjoerg return false;
49447330f729Sjoerg };
49457330f729Sjoerg
4946*82d56013Sjoerg return parseMany(parseOp);
49477330f729Sjoerg }
49487330f729Sjoerg
49497330f729Sjoerg /// parseDirectiveComm
49507330f729Sjoerg /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
parseDirectiveComm(bool IsLocal)49517330f729Sjoerg bool AsmParser::parseDirectiveComm(bool IsLocal) {
49527330f729Sjoerg if (checkForValidSection())
49537330f729Sjoerg return true;
49547330f729Sjoerg
49557330f729Sjoerg SMLoc IDLoc = getLexer().getLoc();
49567330f729Sjoerg StringRef Name;
49577330f729Sjoerg if (parseIdentifier(Name))
49587330f729Sjoerg return TokError("expected identifier in directive");
49597330f729Sjoerg
49607330f729Sjoerg // Handle the identifier as the key symbol.
49617330f729Sjoerg MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
49627330f729Sjoerg
4963*82d56013Sjoerg if (parseComma())
4964*82d56013Sjoerg return true;
49657330f729Sjoerg
49667330f729Sjoerg int64_t Size;
49677330f729Sjoerg SMLoc SizeLoc = getLexer().getLoc();
49687330f729Sjoerg if (parseAbsoluteExpression(Size))
49697330f729Sjoerg return true;
49707330f729Sjoerg
49717330f729Sjoerg int64_t Pow2Alignment = 0;
49727330f729Sjoerg SMLoc Pow2AlignmentLoc;
49737330f729Sjoerg if (getLexer().is(AsmToken::Comma)) {
49747330f729Sjoerg Lex();
49757330f729Sjoerg Pow2AlignmentLoc = getLexer().getLoc();
49767330f729Sjoerg if (parseAbsoluteExpression(Pow2Alignment))
49777330f729Sjoerg return true;
49787330f729Sjoerg
49797330f729Sjoerg LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
49807330f729Sjoerg if (IsLocal && LCOMM == LCOMM::NoAlignment)
49817330f729Sjoerg return Error(Pow2AlignmentLoc, "alignment not supported on this target");
49827330f729Sjoerg
49837330f729Sjoerg // If this target takes alignments in bytes (not log) validate and convert.
49847330f729Sjoerg if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
49857330f729Sjoerg (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
49867330f729Sjoerg if (!isPowerOf2_64(Pow2Alignment))
49877330f729Sjoerg return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
49887330f729Sjoerg Pow2Alignment = Log2_64(Pow2Alignment);
49897330f729Sjoerg }
49907330f729Sjoerg }
49917330f729Sjoerg
4992*82d56013Sjoerg if (parseEOL())
49937330f729Sjoerg return true;
49947330f729Sjoerg
49957330f729Sjoerg // NOTE: a size of zero for a .comm should create a undefined symbol
49967330f729Sjoerg // but a size of .lcomm creates a bss symbol of size zero.
49977330f729Sjoerg if (Size < 0)
49987330f729Sjoerg return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
49997330f729Sjoerg "be less than zero");
50007330f729Sjoerg
50017330f729Sjoerg // NOTE: The alignment in the directive is a power of 2 value, the assembler
50027330f729Sjoerg // may internally end up wanting an alignment in bytes.
50037330f729Sjoerg // FIXME: Diagnose overflow.
50047330f729Sjoerg if (Pow2Alignment < 0)
50057330f729Sjoerg return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
50067330f729Sjoerg "alignment, can't be less than zero");
50077330f729Sjoerg
50087330f729Sjoerg Sym->redefineIfPossible();
50097330f729Sjoerg if (!Sym->isUndefined())
50107330f729Sjoerg return Error(IDLoc, "invalid symbol redefinition");
50117330f729Sjoerg
50127330f729Sjoerg // Create the Symbol as a common or local common with Size and Pow2Alignment
50137330f729Sjoerg if (IsLocal) {
5014*82d56013Sjoerg getStreamer().emitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
50157330f729Sjoerg return false;
50167330f729Sjoerg }
50177330f729Sjoerg
5018*82d56013Sjoerg getStreamer().emitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
50197330f729Sjoerg return false;
50207330f729Sjoerg }
50217330f729Sjoerg
50227330f729Sjoerg /// parseDirectiveAbort
50237330f729Sjoerg /// ::= .abort [... message ...]
parseDirectiveAbort()50247330f729Sjoerg bool AsmParser::parseDirectiveAbort() {
50257330f729Sjoerg // FIXME: Use loc from directive.
50267330f729Sjoerg SMLoc Loc = getLexer().getLoc();
50277330f729Sjoerg
50287330f729Sjoerg StringRef Str = parseStringToEndOfStatement();
5029*82d56013Sjoerg if (parseEOL())
50307330f729Sjoerg return true;
50317330f729Sjoerg
50327330f729Sjoerg if (Str.empty())
50337330f729Sjoerg return Error(Loc, ".abort detected. Assembly stopping.");
50347330f729Sjoerg else
50357330f729Sjoerg return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
50367330f729Sjoerg // FIXME: Actually abort assembly here.
50377330f729Sjoerg
50387330f729Sjoerg return false;
50397330f729Sjoerg }
50407330f729Sjoerg
50417330f729Sjoerg /// parseDirectiveInclude
50427330f729Sjoerg /// ::= .include "filename"
parseDirectiveInclude()50437330f729Sjoerg bool AsmParser::parseDirectiveInclude() {
50447330f729Sjoerg // Allow the strings to have escaped octal character sequence.
50457330f729Sjoerg std::string Filename;
50467330f729Sjoerg SMLoc IncludeLoc = getTok().getLoc();
50477330f729Sjoerg
50487330f729Sjoerg if (check(getTok().isNot(AsmToken::String),
50497330f729Sjoerg "expected string in '.include' directive") ||
50507330f729Sjoerg parseEscapedString(Filename) ||
50517330f729Sjoerg check(getTok().isNot(AsmToken::EndOfStatement),
50527330f729Sjoerg "unexpected token in '.include' directive") ||
50537330f729Sjoerg // Attempt to switch the lexer to the included file before consuming the
50547330f729Sjoerg // end of statement to avoid losing it when we switch.
50557330f729Sjoerg check(enterIncludeFile(Filename), IncludeLoc,
50567330f729Sjoerg "Could not find include file '" + Filename + "'"))
50577330f729Sjoerg return true;
50587330f729Sjoerg
50597330f729Sjoerg return false;
50607330f729Sjoerg }
50617330f729Sjoerg
50627330f729Sjoerg /// parseDirectiveIncbin
50637330f729Sjoerg /// ::= .incbin "filename" [ , skip [ , count ] ]
parseDirectiveIncbin()50647330f729Sjoerg bool AsmParser::parseDirectiveIncbin() {
50657330f729Sjoerg // Allow the strings to have escaped octal character sequence.
50667330f729Sjoerg std::string Filename;
50677330f729Sjoerg SMLoc IncbinLoc = getTok().getLoc();
50687330f729Sjoerg if (check(getTok().isNot(AsmToken::String),
50697330f729Sjoerg "expected string in '.incbin' directive") ||
50707330f729Sjoerg parseEscapedString(Filename))
50717330f729Sjoerg return true;
50727330f729Sjoerg
50737330f729Sjoerg int64_t Skip = 0;
50747330f729Sjoerg const MCExpr *Count = nullptr;
50757330f729Sjoerg SMLoc SkipLoc, CountLoc;
50767330f729Sjoerg if (parseOptionalToken(AsmToken::Comma)) {
50777330f729Sjoerg // The skip expression can be omitted while specifying the count, e.g:
50787330f729Sjoerg // .incbin "filename",,4
50797330f729Sjoerg if (getTok().isNot(AsmToken::Comma)) {
50807330f729Sjoerg if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))
50817330f729Sjoerg return true;
50827330f729Sjoerg }
50837330f729Sjoerg if (parseOptionalToken(AsmToken::Comma)) {
50847330f729Sjoerg CountLoc = getTok().getLoc();
50857330f729Sjoerg if (parseExpression(Count))
50867330f729Sjoerg return true;
50877330f729Sjoerg }
50887330f729Sjoerg }
50897330f729Sjoerg
5090*82d56013Sjoerg if (parseEOL())
50917330f729Sjoerg return true;
50927330f729Sjoerg
50937330f729Sjoerg if (check(Skip < 0, SkipLoc, "skip is negative"))
50947330f729Sjoerg return true;
50957330f729Sjoerg
50967330f729Sjoerg // Attempt to process the included file.
50977330f729Sjoerg if (processIncbinFile(Filename, Skip, Count, CountLoc))
50987330f729Sjoerg return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
50997330f729Sjoerg return false;
51007330f729Sjoerg }
51017330f729Sjoerg
51027330f729Sjoerg /// parseDirectiveIf
51037330f729Sjoerg /// ::= .if{,eq,ge,gt,le,lt,ne} expression
parseDirectiveIf(SMLoc DirectiveLoc,DirectiveKind DirKind)51047330f729Sjoerg bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
51057330f729Sjoerg TheCondStack.push_back(TheCondState);
51067330f729Sjoerg TheCondState.TheCond = AsmCond::IfCond;
51077330f729Sjoerg if (TheCondState.Ignore) {
51087330f729Sjoerg eatToEndOfStatement();
51097330f729Sjoerg } else {
51107330f729Sjoerg int64_t ExprValue;
5111*82d56013Sjoerg if (parseAbsoluteExpression(ExprValue) || parseEOL())
51127330f729Sjoerg return true;
51137330f729Sjoerg
51147330f729Sjoerg switch (DirKind) {
51157330f729Sjoerg default:
51167330f729Sjoerg llvm_unreachable("unsupported directive");
51177330f729Sjoerg case DK_IF:
51187330f729Sjoerg case DK_IFNE:
51197330f729Sjoerg break;
51207330f729Sjoerg case DK_IFEQ:
51217330f729Sjoerg ExprValue = ExprValue == 0;
51227330f729Sjoerg break;
51237330f729Sjoerg case DK_IFGE:
51247330f729Sjoerg ExprValue = ExprValue >= 0;
51257330f729Sjoerg break;
51267330f729Sjoerg case DK_IFGT:
51277330f729Sjoerg ExprValue = ExprValue > 0;
51287330f729Sjoerg break;
51297330f729Sjoerg case DK_IFLE:
51307330f729Sjoerg ExprValue = ExprValue <= 0;
51317330f729Sjoerg break;
51327330f729Sjoerg case DK_IFLT:
51337330f729Sjoerg ExprValue = ExprValue < 0;
51347330f729Sjoerg break;
51357330f729Sjoerg }
51367330f729Sjoerg
51377330f729Sjoerg TheCondState.CondMet = ExprValue;
51387330f729Sjoerg TheCondState.Ignore = !TheCondState.CondMet;
51397330f729Sjoerg }
51407330f729Sjoerg
51417330f729Sjoerg return false;
51427330f729Sjoerg }
51437330f729Sjoerg
51447330f729Sjoerg /// parseDirectiveIfb
51457330f729Sjoerg /// ::= .ifb string
parseDirectiveIfb(SMLoc DirectiveLoc,bool ExpectBlank)51467330f729Sjoerg bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
51477330f729Sjoerg TheCondStack.push_back(TheCondState);
51487330f729Sjoerg TheCondState.TheCond = AsmCond::IfCond;
51497330f729Sjoerg
51507330f729Sjoerg if (TheCondState.Ignore) {
51517330f729Sjoerg eatToEndOfStatement();
51527330f729Sjoerg } else {
51537330f729Sjoerg StringRef Str = parseStringToEndOfStatement();
51547330f729Sjoerg
5155*82d56013Sjoerg if (parseEOL())
51567330f729Sjoerg return true;
51577330f729Sjoerg
51587330f729Sjoerg TheCondState.CondMet = ExpectBlank == Str.empty();
51597330f729Sjoerg TheCondState.Ignore = !TheCondState.CondMet;
51607330f729Sjoerg }
51617330f729Sjoerg
51627330f729Sjoerg return false;
51637330f729Sjoerg }
51647330f729Sjoerg
51657330f729Sjoerg /// parseDirectiveIfc
51667330f729Sjoerg /// ::= .ifc string1, string2
51677330f729Sjoerg /// ::= .ifnc string1, string2
parseDirectiveIfc(SMLoc DirectiveLoc,bool ExpectEqual)51687330f729Sjoerg bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
51697330f729Sjoerg TheCondStack.push_back(TheCondState);
51707330f729Sjoerg TheCondState.TheCond = AsmCond::IfCond;
51717330f729Sjoerg
51727330f729Sjoerg if (TheCondState.Ignore) {
51737330f729Sjoerg eatToEndOfStatement();
51747330f729Sjoerg } else {
51757330f729Sjoerg StringRef Str1 = parseStringToComma();
51767330f729Sjoerg
5177*82d56013Sjoerg if (parseComma())
51787330f729Sjoerg return true;
51797330f729Sjoerg
51807330f729Sjoerg StringRef Str2 = parseStringToEndOfStatement();
51817330f729Sjoerg
5182*82d56013Sjoerg if (parseEOL())
51837330f729Sjoerg return true;
51847330f729Sjoerg
51857330f729Sjoerg TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
51867330f729Sjoerg TheCondState.Ignore = !TheCondState.CondMet;
51877330f729Sjoerg }
51887330f729Sjoerg
51897330f729Sjoerg return false;
51907330f729Sjoerg }
51917330f729Sjoerg
51927330f729Sjoerg /// parseDirectiveIfeqs
51937330f729Sjoerg /// ::= .ifeqs string1, string2
parseDirectiveIfeqs(SMLoc DirectiveLoc,bool ExpectEqual)51947330f729Sjoerg bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
51957330f729Sjoerg if (Lexer.isNot(AsmToken::String)) {
51967330f729Sjoerg if (ExpectEqual)
51977330f729Sjoerg return TokError("expected string parameter for '.ifeqs' directive");
51987330f729Sjoerg return TokError("expected string parameter for '.ifnes' directive");
51997330f729Sjoerg }
52007330f729Sjoerg
52017330f729Sjoerg StringRef String1 = getTok().getStringContents();
52027330f729Sjoerg Lex();
52037330f729Sjoerg
52047330f729Sjoerg if (Lexer.isNot(AsmToken::Comma)) {
52057330f729Sjoerg if (ExpectEqual)
52067330f729Sjoerg return TokError(
52077330f729Sjoerg "expected comma after first string for '.ifeqs' directive");
52087330f729Sjoerg return TokError("expected comma after first string for '.ifnes' directive");
52097330f729Sjoerg }
52107330f729Sjoerg
52117330f729Sjoerg Lex();
52127330f729Sjoerg
52137330f729Sjoerg if (Lexer.isNot(AsmToken::String)) {
52147330f729Sjoerg if (ExpectEqual)
52157330f729Sjoerg return TokError("expected string parameter for '.ifeqs' directive");
52167330f729Sjoerg return TokError("expected string parameter for '.ifnes' directive");
52177330f729Sjoerg }
52187330f729Sjoerg
52197330f729Sjoerg StringRef String2 = getTok().getStringContents();
52207330f729Sjoerg Lex();
52217330f729Sjoerg
52227330f729Sjoerg TheCondStack.push_back(TheCondState);
52237330f729Sjoerg TheCondState.TheCond = AsmCond::IfCond;
52247330f729Sjoerg TheCondState.CondMet = ExpectEqual == (String1 == String2);
52257330f729Sjoerg TheCondState.Ignore = !TheCondState.CondMet;
52267330f729Sjoerg
52277330f729Sjoerg return false;
52287330f729Sjoerg }
52297330f729Sjoerg
52307330f729Sjoerg /// parseDirectiveIfdef
52317330f729Sjoerg /// ::= .ifdef symbol
parseDirectiveIfdef(SMLoc DirectiveLoc,bool expect_defined)52327330f729Sjoerg bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
52337330f729Sjoerg StringRef Name;
52347330f729Sjoerg TheCondStack.push_back(TheCondState);
52357330f729Sjoerg TheCondState.TheCond = AsmCond::IfCond;
52367330f729Sjoerg
52377330f729Sjoerg if (TheCondState.Ignore) {
52387330f729Sjoerg eatToEndOfStatement();
52397330f729Sjoerg } else {
52407330f729Sjoerg if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
5241*82d56013Sjoerg parseEOL())
52427330f729Sjoerg return true;
52437330f729Sjoerg
52447330f729Sjoerg MCSymbol *Sym = getContext().lookupSymbol(Name);
52457330f729Sjoerg
52467330f729Sjoerg if (expect_defined)
52477330f729Sjoerg TheCondState.CondMet = (Sym && !Sym->isUndefined(false));
52487330f729Sjoerg else
52497330f729Sjoerg TheCondState.CondMet = (!Sym || Sym->isUndefined(false));
52507330f729Sjoerg TheCondState.Ignore = !TheCondState.CondMet;
52517330f729Sjoerg }
52527330f729Sjoerg
52537330f729Sjoerg return false;
52547330f729Sjoerg }
52557330f729Sjoerg
52567330f729Sjoerg /// parseDirectiveElseIf
52577330f729Sjoerg /// ::= .elseif expression
parseDirectiveElseIf(SMLoc DirectiveLoc)52587330f729Sjoerg bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
52597330f729Sjoerg if (TheCondState.TheCond != AsmCond::IfCond &&
52607330f729Sjoerg TheCondState.TheCond != AsmCond::ElseIfCond)
52617330f729Sjoerg return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
52627330f729Sjoerg " .if or an .elseif");
52637330f729Sjoerg TheCondState.TheCond = AsmCond::ElseIfCond;
52647330f729Sjoerg
52657330f729Sjoerg bool LastIgnoreState = false;
52667330f729Sjoerg if (!TheCondStack.empty())
52677330f729Sjoerg LastIgnoreState = TheCondStack.back().Ignore;
52687330f729Sjoerg if (LastIgnoreState || TheCondState.CondMet) {
52697330f729Sjoerg TheCondState.Ignore = true;
52707330f729Sjoerg eatToEndOfStatement();
52717330f729Sjoerg } else {
52727330f729Sjoerg int64_t ExprValue;
52737330f729Sjoerg if (parseAbsoluteExpression(ExprValue))
52747330f729Sjoerg return true;
52757330f729Sjoerg
5276*82d56013Sjoerg if (parseEOL())
52777330f729Sjoerg return true;
52787330f729Sjoerg
52797330f729Sjoerg TheCondState.CondMet = ExprValue;
52807330f729Sjoerg TheCondState.Ignore = !TheCondState.CondMet;
52817330f729Sjoerg }
52827330f729Sjoerg
52837330f729Sjoerg return false;
52847330f729Sjoerg }
52857330f729Sjoerg
52867330f729Sjoerg /// parseDirectiveElse
52877330f729Sjoerg /// ::= .else
parseDirectiveElse(SMLoc DirectiveLoc)52887330f729Sjoerg bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
5289*82d56013Sjoerg if (parseEOL())
52907330f729Sjoerg return true;
52917330f729Sjoerg
52927330f729Sjoerg if (TheCondState.TheCond != AsmCond::IfCond &&
52937330f729Sjoerg TheCondState.TheCond != AsmCond::ElseIfCond)
52947330f729Sjoerg return Error(DirectiveLoc, "Encountered a .else that doesn't follow "
52957330f729Sjoerg " an .if or an .elseif");
52967330f729Sjoerg TheCondState.TheCond = AsmCond::ElseCond;
52977330f729Sjoerg bool LastIgnoreState = false;
52987330f729Sjoerg if (!TheCondStack.empty())
52997330f729Sjoerg LastIgnoreState = TheCondStack.back().Ignore;
53007330f729Sjoerg if (LastIgnoreState || TheCondState.CondMet)
53017330f729Sjoerg TheCondState.Ignore = true;
53027330f729Sjoerg else
53037330f729Sjoerg TheCondState.Ignore = false;
53047330f729Sjoerg
53057330f729Sjoerg return false;
53067330f729Sjoerg }
53077330f729Sjoerg
53087330f729Sjoerg /// parseDirectiveEnd
53097330f729Sjoerg /// ::= .end
parseDirectiveEnd(SMLoc DirectiveLoc)53107330f729Sjoerg bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5311*82d56013Sjoerg if (parseEOL())
53127330f729Sjoerg return true;
53137330f729Sjoerg
53147330f729Sjoerg while (Lexer.isNot(AsmToken::Eof))
53157330f729Sjoerg Lexer.Lex();
53167330f729Sjoerg
53177330f729Sjoerg return false;
53187330f729Sjoerg }
53197330f729Sjoerg
53207330f729Sjoerg /// parseDirectiveError
53217330f729Sjoerg /// ::= .err
53227330f729Sjoerg /// ::= .error [string]
parseDirectiveError(SMLoc L,bool WithMessage)53237330f729Sjoerg bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
53247330f729Sjoerg if (!TheCondStack.empty()) {
53257330f729Sjoerg if (TheCondStack.back().Ignore) {
53267330f729Sjoerg eatToEndOfStatement();
53277330f729Sjoerg return false;
53287330f729Sjoerg }
53297330f729Sjoerg }
53307330f729Sjoerg
53317330f729Sjoerg if (!WithMessage)
53327330f729Sjoerg return Error(L, ".err encountered");
53337330f729Sjoerg
53347330f729Sjoerg StringRef Message = ".error directive invoked in source file";
53357330f729Sjoerg if (Lexer.isNot(AsmToken::EndOfStatement)) {
53367330f729Sjoerg if (Lexer.isNot(AsmToken::String))
53377330f729Sjoerg return TokError(".error argument must be a string");
53387330f729Sjoerg
53397330f729Sjoerg Message = getTok().getStringContents();
53407330f729Sjoerg Lex();
53417330f729Sjoerg }
53427330f729Sjoerg
53437330f729Sjoerg return Error(L, Message);
53447330f729Sjoerg }
53457330f729Sjoerg
53467330f729Sjoerg /// parseDirectiveWarning
53477330f729Sjoerg /// ::= .warning [string]
parseDirectiveWarning(SMLoc L)53487330f729Sjoerg bool AsmParser::parseDirectiveWarning(SMLoc L) {
53497330f729Sjoerg if (!TheCondStack.empty()) {
53507330f729Sjoerg if (TheCondStack.back().Ignore) {
53517330f729Sjoerg eatToEndOfStatement();
53527330f729Sjoerg return false;
53537330f729Sjoerg }
53547330f729Sjoerg }
53557330f729Sjoerg
53567330f729Sjoerg StringRef Message = ".warning directive invoked in source file";
53577330f729Sjoerg
53587330f729Sjoerg if (!parseOptionalToken(AsmToken::EndOfStatement)) {
53597330f729Sjoerg if (Lexer.isNot(AsmToken::String))
53607330f729Sjoerg return TokError(".warning argument must be a string");
53617330f729Sjoerg
53627330f729Sjoerg Message = getTok().getStringContents();
53637330f729Sjoerg Lex();
5364*82d56013Sjoerg if (parseEOL())
53657330f729Sjoerg return true;
53667330f729Sjoerg }
53677330f729Sjoerg
53687330f729Sjoerg return Warning(L, Message);
53697330f729Sjoerg }
53707330f729Sjoerg
53717330f729Sjoerg /// parseDirectiveEndIf
53727330f729Sjoerg /// ::= .endif
parseDirectiveEndIf(SMLoc DirectiveLoc)53737330f729Sjoerg bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5374*82d56013Sjoerg if (parseEOL())
53757330f729Sjoerg return true;
53767330f729Sjoerg
53777330f729Sjoerg if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
53787330f729Sjoerg return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
53797330f729Sjoerg "an .if or .else");
53807330f729Sjoerg if (!TheCondStack.empty()) {
53817330f729Sjoerg TheCondState = TheCondStack.back();
53827330f729Sjoerg TheCondStack.pop_back();
53837330f729Sjoerg }
53847330f729Sjoerg
53857330f729Sjoerg return false;
53867330f729Sjoerg }
53877330f729Sjoerg
initializeDirectiveKindMap()53887330f729Sjoerg void AsmParser::initializeDirectiveKindMap() {
5389*82d56013Sjoerg /* Lookup will be done with the directive
5390*82d56013Sjoerg * converted to lower case, so all these
5391*82d56013Sjoerg * keys should be lower case.
5392*82d56013Sjoerg * (target specific directives are handled
5393*82d56013Sjoerg * elsewhere)
5394*82d56013Sjoerg */
53957330f729Sjoerg DirectiveKindMap[".set"] = DK_SET;
53967330f729Sjoerg DirectiveKindMap[".equ"] = DK_EQU;
53977330f729Sjoerg DirectiveKindMap[".equiv"] = DK_EQUIV;
53987330f729Sjoerg DirectiveKindMap[".ascii"] = DK_ASCII;
53997330f729Sjoerg DirectiveKindMap[".asciz"] = DK_ASCIZ;
54007330f729Sjoerg DirectiveKindMap[".string"] = DK_STRING;
54017330f729Sjoerg DirectiveKindMap[".byte"] = DK_BYTE;
54027330f729Sjoerg DirectiveKindMap[".short"] = DK_SHORT;
54037330f729Sjoerg DirectiveKindMap[".value"] = DK_VALUE;
54047330f729Sjoerg DirectiveKindMap[".2byte"] = DK_2BYTE;
54057330f729Sjoerg DirectiveKindMap[".long"] = DK_LONG;
54067330f729Sjoerg DirectiveKindMap[".int"] = DK_INT;
54077330f729Sjoerg DirectiveKindMap[".4byte"] = DK_4BYTE;
54087330f729Sjoerg DirectiveKindMap[".quad"] = DK_QUAD;
54097330f729Sjoerg DirectiveKindMap[".8byte"] = DK_8BYTE;
54107330f729Sjoerg DirectiveKindMap[".octa"] = DK_OCTA;
54117330f729Sjoerg DirectiveKindMap[".single"] = DK_SINGLE;
54127330f729Sjoerg DirectiveKindMap[".float"] = DK_FLOAT;
54137330f729Sjoerg DirectiveKindMap[".double"] = DK_DOUBLE;
54147330f729Sjoerg DirectiveKindMap[".align"] = DK_ALIGN;
54157330f729Sjoerg DirectiveKindMap[".align32"] = DK_ALIGN32;
54167330f729Sjoerg DirectiveKindMap[".balign"] = DK_BALIGN;
54177330f729Sjoerg DirectiveKindMap[".balignw"] = DK_BALIGNW;
54187330f729Sjoerg DirectiveKindMap[".balignl"] = DK_BALIGNL;
54197330f729Sjoerg DirectiveKindMap[".p2align"] = DK_P2ALIGN;
54207330f729Sjoerg DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
54217330f729Sjoerg DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
54227330f729Sjoerg DirectiveKindMap[".org"] = DK_ORG;
54237330f729Sjoerg DirectiveKindMap[".fill"] = DK_FILL;
54247330f729Sjoerg DirectiveKindMap[".zero"] = DK_ZERO;
54257330f729Sjoerg DirectiveKindMap[".extern"] = DK_EXTERN;
54267330f729Sjoerg DirectiveKindMap[".globl"] = DK_GLOBL;
54277330f729Sjoerg DirectiveKindMap[".global"] = DK_GLOBAL;
54287330f729Sjoerg DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
54297330f729Sjoerg DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
54307330f729Sjoerg DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
54317330f729Sjoerg DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
54327330f729Sjoerg DirectiveKindMap[".reference"] = DK_REFERENCE;
54337330f729Sjoerg DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
54347330f729Sjoerg DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
54357330f729Sjoerg DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
54367330f729Sjoerg DirectiveKindMap[".cold"] = DK_COLD;
54377330f729Sjoerg DirectiveKindMap[".comm"] = DK_COMM;
54387330f729Sjoerg DirectiveKindMap[".common"] = DK_COMMON;
54397330f729Sjoerg DirectiveKindMap[".lcomm"] = DK_LCOMM;
54407330f729Sjoerg DirectiveKindMap[".abort"] = DK_ABORT;
54417330f729Sjoerg DirectiveKindMap[".include"] = DK_INCLUDE;
54427330f729Sjoerg DirectiveKindMap[".incbin"] = DK_INCBIN;
54437330f729Sjoerg DirectiveKindMap[".code16"] = DK_CODE16;
54447330f729Sjoerg DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
54457330f729Sjoerg DirectiveKindMap[".rept"] = DK_REPT;
54467330f729Sjoerg DirectiveKindMap[".rep"] = DK_REPT;
54477330f729Sjoerg DirectiveKindMap[".irp"] = DK_IRP;
54487330f729Sjoerg DirectiveKindMap[".irpc"] = DK_IRPC;
54497330f729Sjoerg DirectiveKindMap[".endr"] = DK_ENDR;
54507330f729Sjoerg DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE;
54517330f729Sjoerg DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK;
54527330f729Sjoerg DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK;
54537330f729Sjoerg DirectiveKindMap[".if"] = DK_IF;
54547330f729Sjoerg DirectiveKindMap[".ifeq"] = DK_IFEQ;
54557330f729Sjoerg DirectiveKindMap[".ifge"] = DK_IFGE;
54567330f729Sjoerg DirectiveKindMap[".ifgt"] = DK_IFGT;
54577330f729Sjoerg DirectiveKindMap[".ifle"] = DK_IFLE;
54587330f729Sjoerg DirectiveKindMap[".iflt"] = DK_IFLT;
54597330f729Sjoerg DirectiveKindMap[".ifne"] = DK_IFNE;
54607330f729Sjoerg DirectiveKindMap[".ifb"] = DK_IFB;
54617330f729Sjoerg DirectiveKindMap[".ifnb"] = DK_IFNB;
54627330f729Sjoerg DirectiveKindMap[".ifc"] = DK_IFC;
54637330f729Sjoerg DirectiveKindMap[".ifeqs"] = DK_IFEQS;
54647330f729Sjoerg DirectiveKindMap[".ifnc"] = DK_IFNC;
54657330f729Sjoerg DirectiveKindMap[".ifnes"] = DK_IFNES;
54667330f729Sjoerg DirectiveKindMap[".ifdef"] = DK_IFDEF;
54677330f729Sjoerg DirectiveKindMap[".ifndef"] = DK_IFNDEF;
54687330f729Sjoerg DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
54697330f729Sjoerg DirectiveKindMap[".elseif"] = DK_ELSEIF;
54707330f729Sjoerg DirectiveKindMap[".else"] = DK_ELSE;
54717330f729Sjoerg DirectiveKindMap[".end"] = DK_END;
54727330f729Sjoerg DirectiveKindMap[".endif"] = DK_ENDIF;
54737330f729Sjoerg DirectiveKindMap[".skip"] = DK_SKIP;
54747330f729Sjoerg DirectiveKindMap[".space"] = DK_SPACE;
54757330f729Sjoerg DirectiveKindMap[".file"] = DK_FILE;
54767330f729Sjoerg DirectiveKindMap[".line"] = DK_LINE;
54777330f729Sjoerg DirectiveKindMap[".loc"] = DK_LOC;
54787330f729Sjoerg DirectiveKindMap[".stabs"] = DK_STABS;
54797330f729Sjoerg DirectiveKindMap[".cv_file"] = DK_CV_FILE;
54807330f729Sjoerg DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
54817330f729Sjoerg DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
54827330f729Sjoerg DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
54837330f729Sjoerg DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
54847330f729Sjoerg DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
54857330f729Sjoerg DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
54867330f729Sjoerg DirectiveKindMap[".cv_string"] = DK_CV_STRING;
54877330f729Sjoerg DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
54887330f729Sjoerg DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
54897330f729Sjoerg DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
54907330f729Sjoerg DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
54917330f729Sjoerg DirectiveKindMap[".sleb128"] = DK_SLEB128;
54927330f729Sjoerg DirectiveKindMap[".uleb128"] = DK_ULEB128;
54937330f729Sjoerg DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
54947330f729Sjoerg DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
54957330f729Sjoerg DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
54967330f729Sjoerg DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
54977330f729Sjoerg DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
54987330f729Sjoerg DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
54997330f729Sjoerg DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
55007330f729Sjoerg DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
55017330f729Sjoerg DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
55027330f729Sjoerg DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
55037330f729Sjoerg DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
55047330f729Sjoerg DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
55057330f729Sjoerg DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
55067330f729Sjoerg DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
55077330f729Sjoerg DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
55087330f729Sjoerg DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
55097330f729Sjoerg DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
55107330f729Sjoerg DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
55117330f729Sjoerg DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
55127330f729Sjoerg DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
55137330f729Sjoerg DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
55147330f729Sjoerg DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
55157330f729Sjoerg DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
55167330f729Sjoerg DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
55177330f729Sjoerg DirectiveKindMap[".macro"] = DK_MACRO;
55187330f729Sjoerg DirectiveKindMap[".exitm"] = DK_EXITM;
55197330f729Sjoerg DirectiveKindMap[".endm"] = DK_ENDM;
55207330f729Sjoerg DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
55217330f729Sjoerg DirectiveKindMap[".purgem"] = DK_PURGEM;
55227330f729Sjoerg DirectiveKindMap[".err"] = DK_ERR;
55237330f729Sjoerg DirectiveKindMap[".error"] = DK_ERROR;
55247330f729Sjoerg DirectiveKindMap[".warning"] = DK_WARNING;
55257330f729Sjoerg DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
55267330f729Sjoerg DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
55277330f729Sjoerg DirectiveKindMap[".reloc"] = DK_RELOC;
55287330f729Sjoerg DirectiveKindMap[".dc"] = DK_DC;
55297330f729Sjoerg DirectiveKindMap[".dc.a"] = DK_DC_A;
55307330f729Sjoerg DirectiveKindMap[".dc.b"] = DK_DC_B;
55317330f729Sjoerg DirectiveKindMap[".dc.d"] = DK_DC_D;
55327330f729Sjoerg DirectiveKindMap[".dc.l"] = DK_DC_L;
55337330f729Sjoerg DirectiveKindMap[".dc.s"] = DK_DC_S;
55347330f729Sjoerg DirectiveKindMap[".dc.w"] = DK_DC_W;
55357330f729Sjoerg DirectiveKindMap[".dc.x"] = DK_DC_X;
55367330f729Sjoerg DirectiveKindMap[".dcb"] = DK_DCB;
55377330f729Sjoerg DirectiveKindMap[".dcb.b"] = DK_DCB_B;
55387330f729Sjoerg DirectiveKindMap[".dcb.d"] = DK_DCB_D;
55397330f729Sjoerg DirectiveKindMap[".dcb.l"] = DK_DCB_L;
55407330f729Sjoerg DirectiveKindMap[".dcb.s"] = DK_DCB_S;
55417330f729Sjoerg DirectiveKindMap[".dcb.w"] = DK_DCB_W;
55427330f729Sjoerg DirectiveKindMap[".dcb.x"] = DK_DCB_X;
55437330f729Sjoerg DirectiveKindMap[".ds"] = DK_DS;
55447330f729Sjoerg DirectiveKindMap[".ds.b"] = DK_DS_B;
55457330f729Sjoerg DirectiveKindMap[".ds.d"] = DK_DS_D;
55467330f729Sjoerg DirectiveKindMap[".ds.l"] = DK_DS_L;
55477330f729Sjoerg DirectiveKindMap[".ds.p"] = DK_DS_P;
55487330f729Sjoerg DirectiveKindMap[".ds.s"] = DK_DS_S;
55497330f729Sjoerg DirectiveKindMap[".ds.w"] = DK_DS_W;
55507330f729Sjoerg DirectiveKindMap[".ds.x"] = DK_DS_X;
55517330f729Sjoerg DirectiveKindMap[".print"] = DK_PRINT;
55527330f729Sjoerg DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
55537330f729Sjoerg DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
5554*82d56013Sjoerg DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE;
5555*82d56013Sjoerg DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD;
55567330f729Sjoerg }
55577330f729Sjoerg
parseMacroLikeBody(SMLoc DirectiveLoc)55587330f729Sjoerg MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
55597330f729Sjoerg AsmToken EndToken, StartToken = getTok();
55607330f729Sjoerg
55617330f729Sjoerg unsigned NestLevel = 0;
55627330f729Sjoerg while (true) {
55637330f729Sjoerg // Check whether we have reached the end of the file.
55647330f729Sjoerg if (getLexer().is(AsmToken::Eof)) {
55657330f729Sjoerg printError(DirectiveLoc, "no matching '.endr' in definition");
55667330f729Sjoerg return nullptr;
55677330f729Sjoerg }
55687330f729Sjoerg
55697330f729Sjoerg if (Lexer.is(AsmToken::Identifier) &&
55707330f729Sjoerg (getTok().getIdentifier() == ".rep" ||
55717330f729Sjoerg getTok().getIdentifier() == ".rept" ||
55727330f729Sjoerg getTok().getIdentifier() == ".irp" ||
55737330f729Sjoerg getTok().getIdentifier() == ".irpc")) {
55747330f729Sjoerg ++NestLevel;
55757330f729Sjoerg }
55767330f729Sjoerg
55777330f729Sjoerg // Otherwise, check whether we have reached the .endr.
55787330f729Sjoerg if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") {
55797330f729Sjoerg if (NestLevel == 0) {
55807330f729Sjoerg EndToken = getTok();
55817330f729Sjoerg Lex();
55827330f729Sjoerg if (Lexer.isNot(AsmToken::EndOfStatement)) {
55837330f729Sjoerg printError(getTok().getLoc(),
55847330f729Sjoerg "unexpected token in '.endr' directive");
55857330f729Sjoerg return nullptr;
55867330f729Sjoerg }
55877330f729Sjoerg break;
55887330f729Sjoerg }
55897330f729Sjoerg --NestLevel;
55907330f729Sjoerg }
55917330f729Sjoerg
55927330f729Sjoerg // Otherwise, scan till the end of the statement.
55937330f729Sjoerg eatToEndOfStatement();
55947330f729Sjoerg }
55957330f729Sjoerg
55967330f729Sjoerg const char *BodyStart = StartToken.getLoc().getPointer();
55977330f729Sjoerg const char *BodyEnd = EndToken.getLoc().getPointer();
55987330f729Sjoerg StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
55997330f729Sjoerg
56007330f729Sjoerg // We Are Anonymous.
56017330f729Sjoerg MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
56027330f729Sjoerg return &MacroLikeBodies.back();
56037330f729Sjoerg }
56047330f729Sjoerg
instantiateMacroLikeBody(MCAsmMacro * M,SMLoc DirectiveLoc,raw_svector_ostream & OS)56057330f729Sjoerg void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
56067330f729Sjoerg raw_svector_ostream &OS) {
56077330f729Sjoerg OS << ".endr\n";
56087330f729Sjoerg
56097330f729Sjoerg std::unique_ptr<MemoryBuffer> Instantiation =
56107330f729Sjoerg MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
56117330f729Sjoerg
56127330f729Sjoerg // Create the macro instantiation object and add to the current macro
56137330f729Sjoerg // instantiation stack.
5614*82d56013Sjoerg MacroInstantiation *MI = new MacroInstantiation{
5615*82d56013Sjoerg DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
56167330f729Sjoerg ActiveMacros.push_back(MI);
56177330f729Sjoerg
56187330f729Sjoerg // Jump to the macro instantiation and prime the lexer.
56197330f729Sjoerg CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
56207330f729Sjoerg Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
56217330f729Sjoerg Lex();
56227330f729Sjoerg }
56237330f729Sjoerg
56247330f729Sjoerg /// parseDirectiveRept
56257330f729Sjoerg /// ::= .rep | .rept count
parseDirectiveRept(SMLoc DirectiveLoc,StringRef Dir)56267330f729Sjoerg bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
56277330f729Sjoerg const MCExpr *CountExpr;
56287330f729Sjoerg SMLoc CountLoc = getTok().getLoc();
56297330f729Sjoerg if (parseExpression(CountExpr))
56307330f729Sjoerg return true;
56317330f729Sjoerg
56327330f729Sjoerg int64_t Count;
56337330f729Sjoerg if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
56347330f729Sjoerg return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
56357330f729Sjoerg }
56367330f729Sjoerg
5637*82d56013Sjoerg if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())
56387330f729Sjoerg return true;
56397330f729Sjoerg
56407330f729Sjoerg // Lex the rept definition.
56417330f729Sjoerg MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
56427330f729Sjoerg if (!M)
56437330f729Sjoerg return true;
56447330f729Sjoerg
56457330f729Sjoerg // Macro instantiation is lexical, unfortunately. We construct a new buffer
56467330f729Sjoerg // to hold the macro body with substitutions.
56477330f729Sjoerg SmallString<256> Buf;
56487330f729Sjoerg raw_svector_ostream OS(Buf);
56497330f729Sjoerg while (Count--) {
56507330f729Sjoerg // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
56517330f729Sjoerg if (expandMacro(OS, M->Body, None, None, false, getTok().getLoc()))
56527330f729Sjoerg return true;
56537330f729Sjoerg }
56547330f729Sjoerg instantiateMacroLikeBody(M, DirectiveLoc, OS);
56557330f729Sjoerg
56567330f729Sjoerg return false;
56577330f729Sjoerg }
56587330f729Sjoerg
56597330f729Sjoerg /// parseDirectiveIrp
56607330f729Sjoerg /// ::= .irp symbol,values
parseDirectiveIrp(SMLoc DirectiveLoc)56617330f729Sjoerg bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
56627330f729Sjoerg MCAsmMacroParameter Parameter;
56637330f729Sjoerg MCAsmMacroArguments A;
56647330f729Sjoerg if (check(parseIdentifier(Parameter.Name),
56657330f729Sjoerg "expected identifier in '.irp' directive") ||
5666*82d56013Sjoerg parseComma() || parseMacroArguments(nullptr, A) || parseEOL())
56677330f729Sjoerg return true;
56687330f729Sjoerg
56697330f729Sjoerg // Lex the irp definition.
56707330f729Sjoerg MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
56717330f729Sjoerg if (!M)
56727330f729Sjoerg return true;
56737330f729Sjoerg
56747330f729Sjoerg // Macro instantiation is lexical, unfortunately. We construct a new buffer
56757330f729Sjoerg // to hold the macro body with substitutions.
56767330f729Sjoerg SmallString<256> Buf;
56777330f729Sjoerg raw_svector_ostream OS(Buf);
56787330f729Sjoerg
56797330f729Sjoerg for (const MCAsmMacroArgument &Arg : A) {
56807330f729Sjoerg // Note that the AtPseudoVariable is enabled for instantiations of .irp.
56817330f729Sjoerg // This is undocumented, but GAS seems to support it.
56827330f729Sjoerg if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
56837330f729Sjoerg return true;
56847330f729Sjoerg }
56857330f729Sjoerg
56867330f729Sjoerg instantiateMacroLikeBody(M, DirectiveLoc, OS);
56877330f729Sjoerg
56887330f729Sjoerg return false;
56897330f729Sjoerg }
56907330f729Sjoerg
56917330f729Sjoerg /// parseDirectiveIrpc
56927330f729Sjoerg /// ::= .irpc symbol,values
parseDirectiveIrpc(SMLoc DirectiveLoc)56937330f729Sjoerg bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
56947330f729Sjoerg MCAsmMacroParameter Parameter;
56957330f729Sjoerg MCAsmMacroArguments A;
56967330f729Sjoerg
56977330f729Sjoerg if (check(parseIdentifier(Parameter.Name),
56987330f729Sjoerg "expected identifier in '.irpc' directive") ||
5699*82d56013Sjoerg parseComma() || parseMacroArguments(nullptr, A))
57007330f729Sjoerg return true;
57017330f729Sjoerg
57027330f729Sjoerg if (A.size() != 1 || A.front().size() != 1)
57037330f729Sjoerg return TokError("unexpected token in '.irpc' directive");
5704*82d56013Sjoerg if (parseEOL())
57057330f729Sjoerg return true;
57067330f729Sjoerg
57077330f729Sjoerg // Lex the irpc definition.
57087330f729Sjoerg MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
57097330f729Sjoerg if (!M)
57107330f729Sjoerg return true;
57117330f729Sjoerg
57127330f729Sjoerg // Macro instantiation is lexical, unfortunately. We construct a new buffer
57137330f729Sjoerg // to hold the macro body with substitutions.
57147330f729Sjoerg SmallString<256> Buf;
57157330f729Sjoerg raw_svector_ostream OS(Buf);
57167330f729Sjoerg
57177330f729Sjoerg StringRef Values = A.front().front().getString();
57187330f729Sjoerg for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
57197330f729Sjoerg MCAsmMacroArgument Arg;
57207330f729Sjoerg Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
57217330f729Sjoerg
57227330f729Sjoerg // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
57237330f729Sjoerg // This is undocumented, but GAS seems to support it.
57247330f729Sjoerg if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
57257330f729Sjoerg return true;
57267330f729Sjoerg }
57277330f729Sjoerg
57287330f729Sjoerg instantiateMacroLikeBody(M, DirectiveLoc, OS);
57297330f729Sjoerg
57307330f729Sjoerg return false;
57317330f729Sjoerg }
57327330f729Sjoerg
parseDirectiveEndr(SMLoc DirectiveLoc)57337330f729Sjoerg bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
57347330f729Sjoerg if (ActiveMacros.empty())
57357330f729Sjoerg return TokError("unmatched '.endr' directive");
57367330f729Sjoerg
57377330f729Sjoerg // The only .repl that should get here are the ones created by
57387330f729Sjoerg // instantiateMacroLikeBody.
57397330f729Sjoerg assert(getLexer().is(AsmToken::EndOfStatement));
57407330f729Sjoerg
57417330f729Sjoerg handleMacroExit();
57427330f729Sjoerg return false;
57437330f729Sjoerg }
57447330f729Sjoerg
parseDirectiveMSEmit(SMLoc IDLoc,ParseStatementInfo & Info,size_t Len)57457330f729Sjoerg bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
57467330f729Sjoerg size_t Len) {
57477330f729Sjoerg const MCExpr *Value;
57487330f729Sjoerg SMLoc ExprLoc = getLexer().getLoc();
57497330f729Sjoerg if (parseExpression(Value))
57507330f729Sjoerg return true;
57517330f729Sjoerg const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
57527330f729Sjoerg if (!MCE)
57537330f729Sjoerg return Error(ExprLoc, "unexpected expression in _emit");
57547330f729Sjoerg uint64_t IntValue = MCE->getValue();
57557330f729Sjoerg if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
57567330f729Sjoerg return Error(ExprLoc, "literal value out of range for directive");
57577330f729Sjoerg
57587330f729Sjoerg Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
57597330f729Sjoerg return false;
57607330f729Sjoerg }
57617330f729Sjoerg
parseDirectiveMSAlign(SMLoc IDLoc,ParseStatementInfo & Info)57627330f729Sjoerg bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
57637330f729Sjoerg const MCExpr *Value;
57647330f729Sjoerg SMLoc ExprLoc = getLexer().getLoc();
57657330f729Sjoerg if (parseExpression(Value))
57667330f729Sjoerg return true;
57677330f729Sjoerg const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
57687330f729Sjoerg if (!MCE)
57697330f729Sjoerg return Error(ExprLoc, "unexpected expression in align");
57707330f729Sjoerg uint64_t IntValue = MCE->getValue();
57717330f729Sjoerg if (!isPowerOf2_64(IntValue))
57727330f729Sjoerg return Error(ExprLoc, "literal value not a power of two greater then zero");
57737330f729Sjoerg
57747330f729Sjoerg Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
57757330f729Sjoerg return false;
57767330f729Sjoerg }
57777330f729Sjoerg
parseDirectivePrint(SMLoc DirectiveLoc)57787330f729Sjoerg bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
57797330f729Sjoerg const AsmToken StrTok = getTok();
57807330f729Sjoerg Lex();
57817330f729Sjoerg if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
57827330f729Sjoerg return Error(DirectiveLoc, "expected double quoted string after .print");
5783*82d56013Sjoerg if (parseEOL())
57847330f729Sjoerg return true;
57857330f729Sjoerg llvm::outs() << StrTok.getStringContents() << '\n';
57867330f729Sjoerg return false;
57877330f729Sjoerg }
57887330f729Sjoerg
parseDirectiveAddrsig()57897330f729Sjoerg bool AsmParser::parseDirectiveAddrsig() {
5790*82d56013Sjoerg if (parseEOL())
5791*82d56013Sjoerg return true;
5792*82d56013Sjoerg getStreamer().emitAddrsig();
57937330f729Sjoerg return false;
57947330f729Sjoerg }
57957330f729Sjoerg
parseDirectiveAddrsigSym()57967330f729Sjoerg bool AsmParser::parseDirectiveAddrsigSym() {
57977330f729Sjoerg StringRef Name;
5798*82d56013Sjoerg if (check(parseIdentifier(Name), "expected identifier") || parseEOL())
57997330f729Sjoerg return true;
58007330f729Sjoerg MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5801*82d56013Sjoerg getStreamer().emitAddrsigSym(Sym);
58027330f729Sjoerg return false;
58037330f729Sjoerg }
58047330f729Sjoerg
parseDirectivePseudoProbe()5805*82d56013Sjoerg bool AsmParser::parseDirectivePseudoProbe() {
5806*82d56013Sjoerg int64_t Guid;
5807*82d56013Sjoerg int64_t Index;
5808*82d56013Sjoerg int64_t Type;
5809*82d56013Sjoerg int64_t Attr;
5810*82d56013Sjoerg
5811*82d56013Sjoerg if (getLexer().is(AsmToken::Integer)) {
5812*82d56013Sjoerg if (parseIntToken(Guid, "unexpected token in '.pseudoprobe' directive"))
5813*82d56013Sjoerg return true;
5814*82d56013Sjoerg }
5815*82d56013Sjoerg
5816*82d56013Sjoerg if (getLexer().is(AsmToken::Integer)) {
5817*82d56013Sjoerg if (parseIntToken(Index, "unexpected token in '.pseudoprobe' directive"))
5818*82d56013Sjoerg return true;
5819*82d56013Sjoerg }
5820*82d56013Sjoerg
5821*82d56013Sjoerg if (getLexer().is(AsmToken::Integer)) {
5822*82d56013Sjoerg if (parseIntToken(Type, "unexpected token in '.pseudoprobe' directive"))
5823*82d56013Sjoerg return true;
5824*82d56013Sjoerg }
5825*82d56013Sjoerg
5826*82d56013Sjoerg if (getLexer().is(AsmToken::Integer)) {
5827*82d56013Sjoerg if (parseIntToken(Attr, "unexpected token in '.pseudoprobe' directive"))
5828*82d56013Sjoerg return true;
5829*82d56013Sjoerg }
5830*82d56013Sjoerg
5831*82d56013Sjoerg // Parse inline stack like @ GUID:11:12 @ GUID:1:11 @ GUID:3:21
5832*82d56013Sjoerg MCPseudoProbeInlineStack InlineStack;
5833*82d56013Sjoerg
5834*82d56013Sjoerg while (getLexer().is(AsmToken::At)) {
5835*82d56013Sjoerg // eat @
5836*82d56013Sjoerg Lex();
5837*82d56013Sjoerg
5838*82d56013Sjoerg int64_t CallerGuid = 0;
5839*82d56013Sjoerg if (getLexer().is(AsmToken::Integer)) {
5840*82d56013Sjoerg if (parseIntToken(CallerGuid,
5841*82d56013Sjoerg "unexpected token in '.pseudoprobe' directive"))
5842*82d56013Sjoerg return true;
5843*82d56013Sjoerg }
5844*82d56013Sjoerg
5845*82d56013Sjoerg // eat colon
5846*82d56013Sjoerg if (getLexer().is(AsmToken::Colon))
5847*82d56013Sjoerg Lex();
5848*82d56013Sjoerg
5849*82d56013Sjoerg int64_t CallerProbeId = 0;
5850*82d56013Sjoerg if (getLexer().is(AsmToken::Integer)) {
5851*82d56013Sjoerg if (parseIntToken(CallerProbeId,
5852*82d56013Sjoerg "unexpected token in '.pseudoprobe' directive"))
5853*82d56013Sjoerg return true;
5854*82d56013Sjoerg }
5855*82d56013Sjoerg
5856*82d56013Sjoerg InlineSite Site(CallerGuid, CallerProbeId);
5857*82d56013Sjoerg InlineStack.push_back(Site);
5858*82d56013Sjoerg }
5859*82d56013Sjoerg
5860*82d56013Sjoerg if (parseEOL())
5861*82d56013Sjoerg return true;
5862*82d56013Sjoerg
5863*82d56013Sjoerg getStreamer().emitPseudoProbe(Guid, Index, Type, Attr, InlineStack);
5864*82d56013Sjoerg return false;
5865*82d56013Sjoerg }
5866*82d56013Sjoerg
5867*82d56013Sjoerg /// parseDirectiveLTODiscard
5868*82d56013Sjoerg /// ::= ".lto_discard" [ identifier ( , identifier )* ]
5869*82d56013Sjoerg /// The LTO library emits this directive to discard non-prevailing symbols.
5870*82d56013Sjoerg /// We ignore symbol assignments and attribute changes for the specified
5871*82d56013Sjoerg /// symbols.
parseDirectiveLTODiscard()5872*82d56013Sjoerg bool AsmParser::parseDirectiveLTODiscard() {
5873*82d56013Sjoerg auto ParseOp = [&]() -> bool {
5874*82d56013Sjoerg StringRef Name;
5875*82d56013Sjoerg SMLoc Loc = getTok().getLoc();
5876*82d56013Sjoerg if (parseIdentifier(Name))
5877*82d56013Sjoerg return Error(Loc, "expected identifier");
5878*82d56013Sjoerg LTODiscardSymbols.insert(Name);
5879*82d56013Sjoerg return false;
5880*82d56013Sjoerg };
5881*82d56013Sjoerg
5882*82d56013Sjoerg LTODiscardSymbols.clear();
5883*82d56013Sjoerg return parseMany(ParseOp);
5884*82d56013Sjoerg }
5885*82d56013Sjoerg
58867330f729Sjoerg // We are comparing pointers, but the pointers are relative to a single string.
58877330f729Sjoerg // Thus, this should always be deterministic.
rewritesSort(const AsmRewrite * AsmRewriteA,const AsmRewrite * AsmRewriteB)58887330f729Sjoerg static int rewritesSort(const AsmRewrite *AsmRewriteA,
58897330f729Sjoerg const AsmRewrite *AsmRewriteB) {
58907330f729Sjoerg if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
58917330f729Sjoerg return -1;
58927330f729Sjoerg if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
58937330f729Sjoerg return 1;
58947330f729Sjoerg
58957330f729Sjoerg // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
58967330f729Sjoerg // rewrite to the same location. Make sure the SizeDirective rewrite is
58977330f729Sjoerg // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
58987330f729Sjoerg // ensures the sort algorithm is stable.
58997330f729Sjoerg if (AsmRewritePrecedence[AsmRewriteA->Kind] >
59007330f729Sjoerg AsmRewritePrecedence[AsmRewriteB->Kind])
59017330f729Sjoerg return -1;
59027330f729Sjoerg
59037330f729Sjoerg if (AsmRewritePrecedence[AsmRewriteA->Kind] <
59047330f729Sjoerg AsmRewritePrecedence[AsmRewriteB->Kind])
59057330f729Sjoerg return 1;
59067330f729Sjoerg llvm_unreachable("Unstable rewrite sort.");
59077330f729Sjoerg }
59087330f729Sjoerg
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)59097330f729Sjoerg bool AsmParser::parseMSInlineAsm(
59107330f729Sjoerg void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
59117330f729Sjoerg unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
59127330f729Sjoerg SmallVectorImpl<std::string> &Constraints,
59137330f729Sjoerg SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
59147330f729Sjoerg const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
59157330f729Sjoerg SmallVector<void *, 4> InputDecls;
59167330f729Sjoerg SmallVector<void *, 4> OutputDecls;
59177330f729Sjoerg SmallVector<bool, 4> InputDeclsAddressOf;
59187330f729Sjoerg SmallVector<bool, 4> OutputDeclsAddressOf;
59197330f729Sjoerg SmallVector<std::string, 4> InputConstraints;
59207330f729Sjoerg SmallVector<std::string, 4> OutputConstraints;
59217330f729Sjoerg SmallVector<unsigned, 4> ClobberRegs;
59227330f729Sjoerg
59237330f729Sjoerg SmallVector<AsmRewrite, 4> AsmStrRewrites;
59247330f729Sjoerg
59257330f729Sjoerg // Prime the lexer.
59267330f729Sjoerg Lex();
59277330f729Sjoerg
59287330f729Sjoerg // While we have input, parse each statement.
59297330f729Sjoerg unsigned InputIdx = 0;
59307330f729Sjoerg unsigned OutputIdx = 0;
59317330f729Sjoerg while (getLexer().isNot(AsmToken::Eof)) {
59327330f729Sjoerg // Parse curly braces marking block start/end
59337330f729Sjoerg if (parseCurlyBlockScope(AsmStrRewrites))
59347330f729Sjoerg continue;
59357330f729Sjoerg
59367330f729Sjoerg ParseStatementInfo Info(&AsmStrRewrites);
59377330f729Sjoerg bool StatementErr = parseStatement(Info, &SI);
59387330f729Sjoerg
59397330f729Sjoerg if (StatementErr || Info.ParseError) {
59407330f729Sjoerg // Emit pending errors if any exist.
59417330f729Sjoerg printPendingErrors();
59427330f729Sjoerg return true;
59437330f729Sjoerg }
59447330f729Sjoerg
59457330f729Sjoerg // No pending error should exist here.
59467330f729Sjoerg assert(!hasPendingError() && "unexpected error from parseStatement");
59477330f729Sjoerg
59487330f729Sjoerg if (Info.Opcode == ~0U)
59497330f729Sjoerg continue;
59507330f729Sjoerg
59517330f729Sjoerg const MCInstrDesc &Desc = MII->get(Info.Opcode);
59527330f729Sjoerg
59537330f729Sjoerg // Build the list of clobbers, outputs and inputs.
59547330f729Sjoerg for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
59557330f729Sjoerg MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
59567330f729Sjoerg
59577330f729Sjoerg // Register operand.
59587330f729Sjoerg if (Operand.isReg() && !Operand.needAddressOf() &&
59597330f729Sjoerg !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
59607330f729Sjoerg unsigned NumDefs = Desc.getNumDefs();
59617330f729Sjoerg // Clobber.
59627330f729Sjoerg if (NumDefs && Operand.getMCOperandNum() < NumDefs)
59637330f729Sjoerg ClobberRegs.push_back(Operand.getReg());
59647330f729Sjoerg continue;
59657330f729Sjoerg }
59667330f729Sjoerg
59677330f729Sjoerg // Expr/Input or Output.
59687330f729Sjoerg StringRef SymName = Operand.getSymName();
59697330f729Sjoerg if (SymName.empty())
59707330f729Sjoerg continue;
59717330f729Sjoerg
59727330f729Sjoerg void *OpDecl = Operand.getOpDecl();
59737330f729Sjoerg if (!OpDecl)
59747330f729Sjoerg continue;
59757330f729Sjoerg
5976*82d56013Sjoerg StringRef Constraint = Operand.getConstraint();
5977*82d56013Sjoerg if (Operand.isImm()) {
5978*82d56013Sjoerg // Offset as immediate
5979*82d56013Sjoerg if (Operand.isOffsetOfLocal())
5980*82d56013Sjoerg Constraint = "r";
5981*82d56013Sjoerg else
5982*82d56013Sjoerg Constraint = "i";
5983*82d56013Sjoerg }
5984*82d56013Sjoerg
59857330f729Sjoerg bool isOutput = (i == 1) && Desc.mayStore();
59867330f729Sjoerg SMLoc Start = SMLoc::getFromPointer(SymName.data());
59877330f729Sjoerg if (isOutput) {
59887330f729Sjoerg ++InputIdx;
59897330f729Sjoerg OutputDecls.push_back(OpDecl);
59907330f729Sjoerg OutputDeclsAddressOf.push_back(Operand.needAddressOf());
5991*82d56013Sjoerg OutputConstraints.push_back(("=" + Constraint).str());
59927330f729Sjoerg AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
59937330f729Sjoerg } else {
59947330f729Sjoerg InputDecls.push_back(OpDecl);
59957330f729Sjoerg InputDeclsAddressOf.push_back(Operand.needAddressOf());
5996*82d56013Sjoerg InputConstraints.push_back(Constraint.str());
5997*82d56013Sjoerg if (Desc.OpInfo[i - 1].isBranchTarget())
5998*82d56013Sjoerg AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
5999*82d56013Sjoerg else
60007330f729Sjoerg AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
60017330f729Sjoerg }
60027330f729Sjoerg }
60037330f729Sjoerg
60047330f729Sjoerg // Consider implicit defs to be clobbers. Think of cpuid and push.
60057330f729Sjoerg ArrayRef<MCPhysReg> ImpDefs(Desc.getImplicitDefs(),
60067330f729Sjoerg Desc.getNumImplicitDefs());
6007*82d56013Sjoerg llvm::append_range(ClobberRegs, ImpDefs);
60087330f729Sjoerg }
60097330f729Sjoerg
60107330f729Sjoerg // Set the number of Outputs and Inputs.
60117330f729Sjoerg NumOutputs = OutputDecls.size();
60127330f729Sjoerg NumInputs = InputDecls.size();
60137330f729Sjoerg
60147330f729Sjoerg // Set the unique clobbers.
60157330f729Sjoerg array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
60167330f729Sjoerg ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
60177330f729Sjoerg ClobberRegs.end());
60187330f729Sjoerg Clobbers.assign(ClobberRegs.size(), std::string());
60197330f729Sjoerg for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
60207330f729Sjoerg raw_string_ostream OS(Clobbers[I]);
60217330f729Sjoerg IP->printRegName(OS, ClobberRegs[I]);
60227330f729Sjoerg }
60237330f729Sjoerg
60247330f729Sjoerg // Merge the various outputs and inputs. Output are expected first.
60257330f729Sjoerg if (NumOutputs || NumInputs) {
60267330f729Sjoerg unsigned NumExprs = NumOutputs + NumInputs;
60277330f729Sjoerg OpDecls.resize(NumExprs);
60287330f729Sjoerg Constraints.resize(NumExprs);
60297330f729Sjoerg for (unsigned i = 0; i < NumOutputs; ++i) {
60307330f729Sjoerg OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
60317330f729Sjoerg Constraints[i] = OutputConstraints[i];
60327330f729Sjoerg }
60337330f729Sjoerg for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
60347330f729Sjoerg OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
60357330f729Sjoerg Constraints[j] = InputConstraints[i];
60367330f729Sjoerg }
60377330f729Sjoerg }
60387330f729Sjoerg
60397330f729Sjoerg // Build the IR assembly string.
60407330f729Sjoerg std::string AsmStringIR;
60417330f729Sjoerg raw_string_ostream OS(AsmStringIR);
60427330f729Sjoerg StringRef ASMString =
60437330f729Sjoerg SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
60447330f729Sjoerg const char *AsmStart = ASMString.begin();
60457330f729Sjoerg const char *AsmEnd = ASMString.end();
60467330f729Sjoerg array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
6047*82d56013Sjoerg for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) {
6048*82d56013Sjoerg const AsmRewrite &AR = *it;
6049*82d56013Sjoerg // Check if this has already been covered by another rewrite...
6050*82d56013Sjoerg if (AR.Done)
6051*82d56013Sjoerg continue;
60527330f729Sjoerg AsmRewriteKind Kind = AR.Kind;
60537330f729Sjoerg
60547330f729Sjoerg const char *Loc = AR.Loc.getPointer();
60557330f729Sjoerg assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
60567330f729Sjoerg
60577330f729Sjoerg // Emit everything up to the immediate/expression.
60587330f729Sjoerg if (unsigned Len = Loc - AsmStart)
60597330f729Sjoerg OS << StringRef(AsmStart, Len);
60607330f729Sjoerg
60617330f729Sjoerg // Skip the original expression.
60627330f729Sjoerg if (Kind == AOK_Skip) {
60637330f729Sjoerg AsmStart = Loc + AR.Len;
60647330f729Sjoerg continue;
60657330f729Sjoerg }
60667330f729Sjoerg
60677330f729Sjoerg unsigned AdditionalSkip = 0;
60687330f729Sjoerg // Rewrite expressions in $N notation.
60697330f729Sjoerg switch (Kind) {
60707330f729Sjoerg default:
60717330f729Sjoerg break;
60727330f729Sjoerg case AOK_IntelExpr:
60737330f729Sjoerg assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
60747330f729Sjoerg if (AR.IntelExp.NeedBracs)
60757330f729Sjoerg OS << "[";
60767330f729Sjoerg if (AR.IntelExp.hasBaseReg())
60777330f729Sjoerg OS << AR.IntelExp.BaseReg;
60787330f729Sjoerg if (AR.IntelExp.hasIndexReg())
60797330f729Sjoerg OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
60807330f729Sjoerg << AR.IntelExp.IndexReg;
60817330f729Sjoerg if (AR.IntelExp.Scale > 1)
60827330f729Sjoerg OS << " * $$" << AR.IntelExp.Scale;
6083*82d56013Sjoerg if (AR.IntelExp.hasOffset()) {
6084*82d56013Sjoerg if (AR.IntelExp.hasRegs())
6085*82d56013Sjoerg OS << " + ";
6086*82d56013Sjoerg // Fuse this rewrite with a rewrite of the offset name, if present.
6087*82d56013Sjoerg StringRef OffsetName = AR.IntelExp.OffsetName;
6088*82d56013Sjoerg SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
6089*82d56013Sjoerg size_t OffsetLen = OffsetName.size();
6090*82d56013Sjoerg auto rewrite_it = std::find_if(
6091*82d56013Sjoerg it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
6092*82d56013Sjoerg return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6093*82d56013Sjoerg (FusingAR.Kind == AOK_Input ||
6094*82d56013Sjoerg FusingAR.Kind == AOK_CallInput);
6095*82d56013Sjoerg });
6096*82d56013Sjoerg if (rewrite_it == AsmStrRewrites.end()) {
6097*82d56013Sjoerg OS << "offset " << OffsetName;
6098*82d56013Sjoerg } else if (rewrite_it->Kind == AOK_CallInput) {
6099*82d56013Sjoerg OS << "${" << InputIdx++ << ":P}";
6100*82d56013Sjoerg rewrite_it->Done = true;
6101*82d56013Sjoerg } else {
6102*82d56013Sjoerg OS << '$' << InputIdx++;
6103*82d56013Sjoerg rewrite_it->Done = true;
6104*82d56013Sjoerg }
6105*82d56013Sjoerg }
6106*82d56013Sjoerg if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
6107*82d56013Sjoerg OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
61087330f729Sjoerg if (AR.IntelExp.NeedBracs)
61097330f729Sjoerg OS << "]";
61107330f729Sjoerg break;
61117330f729Sjoerg case AOK_Label:
61127330f729Sjoerg OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
61137330f729Sjoerg break;
61147330f729Sjoerg case AOK_Input:
61157330f729Sjoerg OS << '$' << InputIdx++;
61167330f729Sjoerg break;
6117*82d56013Sjoerg case AOK_CallInput:
6118*82d56013Sjoerg OS << "${" << InputIdx++ << ":P}";
6119*82d56013Sjoerg break;
61207330f729Sjoerg case AOK_Output:
61217330f729Sjoerg OS << '$' << OutputIdx++;
61227330f729Sjoerg break;
61237330f729Sjoerg case AOK_SizeDirective:
61247330f729Sjoerg switch (AR.Val) {
61257330f729Sjoerg default: break;
61267330f729Sjoerg case 8: OS << "byte ptr "; break;
61277330f729Sjoerg case 16: OS << "word ptr "; break;
61287330f729Sjoerg case 32: OS << "dword ptr "; break;
61297330f729Sjoerg case 64: OS << "qword ptr "; break;
61307330f729Sjoerg case 80: OS << "xword ptr "; break;
61317330f729Sjoerg case 128: OS << "xmmword ptr "; break;
61327330f729Sjoerg case 256: OS << "ymmword ptr "; break;
61337330f729Sjoerg }
61347330f729Sjoerg break;
61357330f729Sjoerg case AOK_Emit:
61367330f729Sjoerg OS << ".byte";
61377330f729Sjoerg break;
61387330f729Sjoerg case AOK_Align: {
61397330f729Sjoerg // MS alignment directives are measured in bytes. If the native assembler
61407330f729Sjoerg // measures alignment in bytes, we can pass it straight through.
61417330f729Sjoerg OS << ".align";
61427330f729Sjoerg if (getContext().getAsmInfo()->getAlignmentIsInBytes())
61437330f729Sjoerg break;
61447330f729Sjoerg
61457330f729Sjoerg // Alignment is in log2 form, so print that instead and skip the original
61467330f729Sjoerg // immediate.
61477330f729Sjoerg unsigned Val = AR.Val;
61487330f729Sjoerg OS << ' ' << Val;
61497330f729Sjoerg assert(Val < 10 && "Expected alignment less then 2^10.");
61507330f729Sjoerg AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
61517330f729Sjoerg break;
61527330f729Sjoerg }
61537330f729Sjoerg case AOK_EVEN:
61547330f729Sjoerg OS << ".even";
61557330f729Sjoerg break;
61567330f729Sjoerg case AOK_EndOfStatement:
61577330f729Sjoerg OS << "\n\t";
61587330f729Sjoerg break;
61597330f729Sjoerg }
61607330f729Sjoerg
61617330f729Sjoerg // Skip the original expression.
61627330f729Sjoerg AsmStart = Loc + AR.Len + AdditionalSkip;
61637330f729Sjoerg }
61647330f729Sjoerg
61657330f729Sjoerg // Emit the remainder of the asm string.
61667330f729Sjoerg if (AsmStart != AsmEnd)
61677330f729Sjoerg OS << StringRef(AsmStart, AsmEnd - AsmStart);
61687330f729Sjoerg
61697330f729Sjoerg AsmString = OS.str();
61707330f729Sjoerg return false;
61717330f729Sjoerg }
61727330f729Sjoerg
parseAsMachineInstruction(ParseStatementInfo & Info,MCAsmParserSemaCallback * SI)6173*82d56013Sjoerg bool HLASMAsmParser::parseAsMachineInstruction(ParseStatementInfo &Info,
6174*82d56013Sjoerg MCAsmParserSemaCallback *SI) {
6175*82d56013Sjoerg AsmToken OperationEntryTok = Lexer.getTok();
6176*82d56013Sjoerg SMLoc OperationEntryLoc = OperationEntryTok.getLoc();
6177*82d56013Sjoerg StringRef OperationEntryVal;
6178*82d56013Sjoerg
6179*82d56013Sjoerg // If we see a new line or carriage return, emit the new line
6180*82d56013Sjoerg // and lex it.
6181*82d56013Sjoerg if (OperationEntryTok.is(AsmToken::EndOfStatement)) {
6182*82d56013Sjoerg if (getTok().getString().front() == '\n' ||
6183*82d56013Sjoerg getTok().getString().front() == '\r') {
6184*82d56013Sjoerg Out.AddBlankLine();
6185*82d56013Sjoerg Lex();
6186*82d56013Sjoerg return false;
6187*82d56013Sjoerg }
6188*82d56013Sjoerg }
6189*82d56013Sjoerg
6190*82d56013Sjoerg // Attempt to parse the first token as an Identifier
6191*82d56013Sjoerg if (parseIdentifier(OperationEntryVal))
6192*82d56013Sjoerg return Error(OperationEntryLoc, "unexpected token at start of statement");
6193*82d56013Sjoerg
6194*82d56013Sjoerg // Once we've parsed the operation entry successfully, lex
6195*82d56013Sjoerg // any spaces to get to the OperandEntries.
6196*82d56013Sjoerg lexLeadingSpaces();
6197*82d56013Sjoerg
6198*82d56013Sjoerg return parseAndMatchAndEmitTargetInstruction(
6199*82d56013Sjoerg Info, OperationEntryVal, OperationEntryTok, OperationEntryLoc);
6200*82d56013Sjoerg }
6201*82d56013Sjoerg
parseStatement(ParseStatementInfo & Info,MCAsmParserSemaCallback * SI)6202*82d56013Sjoerg bool HLASMAsmParser::parseStatement(ParseStatementInfo &Info,
6203*82d56013Sjoerg MCAsmParserSemaCallback *SI) {
6204*82d56013Sjoerg assert(!hasPendingError() && "parseStatement started with pending error");
6205*82d56013Sjoerg
6206*82d56013Sjoerg // Should the first token be interpreted as a machine instruction.
6207*82d56013Sjoerg bool ShouldParseAsMachineInstruction = false;
6208*82d56013Sjoerg
6209*82d56013Sjoerg // If a Name Entry exists, it should occur at the very
6210*82d56013Sjoerg // start of the string. In this case, we should parse the
6211*82d56013Sjoerg // first non-space token as a Label.
6212*82d56013Sjoerg // If the Name entry is missing (i.e. there's some other
6213*82d56013Sjoerg // token), then we attempt to parse the first non-space
6214*82d56013Sjoerg // token as a Machine Instruction.
6215*82d56013Sjoerg if (getTok().is(AsmToken::Space))
6216*82d56013Sjoerg ShouldParseAsMachineInstruction = true;
6217*82d56013Sjoerg
6218*82d56013Sjoerg // If we have an EndOfStatement (which includes the target's comment
6219*82d56013Sjoerg // string) we can appropriately lex it early on)
6220*82d56013Sjoerg if (Lexer.is(AsmToken::EndOfStatement)) {
6221*82d56013Sjoerg // if this is a line comment we can drop it safely
6222*82d56013Sjoerg if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
6223*82d56013Sjoerg getTok().getString().front() == '\n')
6224*82d56013Sjoerg Out.AddBlankLine();
6225*82d56013Sjoerg Lex();
6226*82d56013Sjoerg return false;
6227*82d56013Sjoerg }
6228*82d56013Sjoerg
6229*82d56013Sjoerg // We have established how to parse the inline asm statement.
6230*82d56013Sjoerg // Now we can safely lex any leading spaces to get to the
6231*82d56013Sjoerg // first token.
6232*82d56013Sjoerg lexLeadingSpaces();
6233*82d56013Sjoerg
6234*82d56013Sjoerg if (ShouldParseAsMachineInstruction)
6235*82d56013Sjoerg return parseAsMachineInstruction(Info, SI);
6236*82d56013Sjoerg
6237*82d56013Sjoerg // Label parsing support isn't implemented completely (yet).
6238*82d56013Sjoerg SMLoc Loc = getTok().getLoc();
6239*82d56013Sjoerg eatToEndOfStatement();
6240*82d56013Sjoerg return Error(Loc, "HLASM Label parsing support not yet implemented");
6241*82d56013Sjoerg }
6242*82d56013Sjoerg
62437330f729Sjoerg namespace llvm {
62447330f729Sjoerg namespace MCParserUtils {
62457330f729Sjoerg
62467330f729Sjoerg /// Returns whether the given symbol is used anywhere in the given expression,
62477330f729Sjoerg /// or subexpressions.
isSymbolUsedInExpression(const MCSymbol * Sym,const MCExpr * Value)62487330f729Sjoerg static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
62497330f729Sjoerg switch (Value->getKind()) {
62507330f729Sjoerg case MCExpr::Binary: {
62517330f729Sjoerg const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
62527330f729Sjoerg return isSymbolUsedInExpression(Sym, BE->getLHS()) ||
62537330f729Sjoerg isSymbolUsedInExpression(Sym, BE->getRHS());
62547330f729Sjoerg }
62557330f729Sjoerg case MCExpr::Target:
62567330f729Sjoerg case MCExpr::Constant:
62577330f729Sjoerg return false;
62587330f729Sjoerg case MCExpr::SymbolRef: {
62597330f729Sjoerg const MCSymbol &S =
62607330f729Sjoerg static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
62617330f729Sjoerg if (S.isVariable())
62627330f729Sjoerg return isSymbolUsedInExpression(Sym, S.getVariableValue());
62637330f729Sjoerg return &S == Sym;
62647330f729Sjoerg }
62657330f729Sjoerg case MCExpr::Unary:
62667330f729Sjoerg return isSymbolUsedInExpression(
62677330f729Sjoerg Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
62687330f729Sjoerg }
62697330f729Sjoerg
62707330f729Sjoerg llvm_unreachable("Unknown expr kind!");
62717330f729Sjoerg }
62727330f729Sjoerg
parseAssignmentExpression(StringRef Name,bool allow_redef,MCAsmParser & Parser,MCSymbol * & Sym,const MCExpr * & Value)62737330f729Sjoerg bool parseAssignmentExpression(StringRef Name, bool allow_redef,
62747330f729Sjoerg MCAsmParser &Parser, MCSymbol *&Sym,
62757330f729Sjoerg const MCExpr *&Value) {
62767330f729Sjoerg
62777330f729Sjoerg // FIXME: Use better location, we should use proper tokens.
62787330f729Sjoerg SMLoc EqualLoc = Parser.getTok().getLoc();
62797330f729Sjoerg if (Parser.parseExpression(Value))
62807330f729Sjoerg return Parser.TokError("missing expression");
62817330f729Sjoerg
62827330f729Sjoerg // Note: we don't count b as used in "a = b". This is to allow
62837330f729Sjoerg // a = b
62847330f729Sjoerg // b = c
62857330f729Sjoerg
6286*82d56013Sjoerg if (Parser.parseEOL())
62877330f729Sjoerg return true;
62887330f729Sjoerg
62897330f729Sjoerg // Validate that the LHS is allowed to be a variable (either it has not been
62907330f729Sjoerg // used as a symbol, or it is an absolute symbol).
62917330f729Sjoerg Sym = Parser.getContext().lookupSymbol(Name);
62927330f729Sjoerg if (Sym) {
62937330f729Sjoerg // Diagnose assignment to a label.
62947330f729Sjoerg //
62957330f729Sjoerg // FIXME: Diagnostics. Note the location of the definition as a label.
62967330f729Sjoerg // FIXME: Diagnose assignment to protected identifier (e.g., register name).
62977330f729Sjoerg if (isSymbolUsedInExpression(Sym, Value))
62987330f729Sjoerg return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'");
62997330f729Sjoerg else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() &&
63007330f729Sjoerg !Sym->isVariable())
63017330f729Sjoerg ; // Allow redefinitions of undefined symbols only used in directives.
63027330f729Sjoerg else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
63037330f729Sjoerg ; // Allow redefinitions of variables that haven't yet been used.
63047330f729Sjoerg else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
63057330f729Sjoerg return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
63067330f729Sjoerg else if (!Sym->isVariable())
63077330f729Sjoerg return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'");
63087330f729Sjoerg else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
63097330f729Sjoerg return Parser.Error(EqualLoc,
63107330f729Sjoerg "invalid reassignment of non-absolute variable '" +
63117330f729Sjoerg Name + "'");
63127330f729Sjoerg } else if (Name == ".") {
63137330f729Sjoerg Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
63147330f729Sjoerg return false;
63157330f729Sjoerg } else
63167330f729Sjoerg Sym = Parser.getContext().getOrCreateSymbol(Name);
63177330f729Sjoerg
63187330f729Sjoerg Sym->setRedefinable(allow_redef);
63197330f729Sjoerg
63207330f729Sjoerg return false;
63217330f729Sjoerg }
63227330f729Sjoerg
63237330f729Sjoerg } // end namespace MCParserUtils
63247330f729Sjoerg } // end namespace llvm
63257330f729Sjoerg
63267330f729Sjoerg /// Create an MCAsmParser instance.
createMCAsmParser(SourceMgr & SM,MCContext & C,MCStreamer & Out,const MCAsmInfo & MAI,unsigned CB)63277330f729Sjoerg MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
63287330f729Sjoerg MCStreamer &Out, const MCAsmInfo &MAI,
63297330f729Sjoerg unsigned CB) {
6330*82d56013Sjoerg if (C.getTargetTriple().isOSzOS())
6331*82d56013Sjoerg return new HLASMAsmParser(SM, C, Out, MAI, CB);
6332*82d56013Sjoerg
63337330f729Sjoerg return new AsmParser(SM, C, Out, MAI, CB);
63347330f729Sjoerg }
6335