xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/MC/MCParser/AsmParser.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
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