xref: /openbsd/gnu/llvm/llvm/lib/MC/MCParser/AsmParser.cpp (revision a96b3639)
109467b48Spatrick //===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
9097a140dSpatrick // This class implements a parser for assembly files similar to gas syntax.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #include "llvm/ADT/APFloat.h"
1409467b48Spatrick #include "llvm/ADT/APInt.h"
1509467b48Spatrick #include "llvm/ADT/ArrayRef.h"
1609467b48Spatrick #include "llvm/ADT/STLExtras.h"
17a0747c9fSpatrick #include "llvm/ADT/SmallSet.h"
1809467b48Spatrick #include "llvm/ADT/SmallString.h"
1909467b48Spatrick #include "llvm/ADT/SmallVector.h"
2009467b48Spatrick #include "llvm/ADT/StringExtras.h"
2109467b48Spatrick #include "llvm/ADT/StringMap.h"
2209467b48Spatrick #include "llvm/ADT/StringRef.h"
2309467b48Spatrick #include "llvm/ADT/Twine.h"
2409467b48Spatrick #include "llvm/BinaryFormat/Dwarf.h"
2509467b48Spatrick #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
2609467b48Spatrick #include "llvm/MC/MCAsmInfo.h"
2709467b48Spatrick #include "llvm/MC/MCCodeView.h"
2809467b48Spatrick #include "llvm/MC/MCContext.h"
2909467b48Spatrick #include "llvm/MC/MCDirectives.h"
3009467b48Spatrick #include "llvm/MC/MCDwarf.h"
3109467b48Spatrick #include "llvm/MC/MCExpr.h"
3209467b48Spatrick #include "llvm/MC/MCInstPrinter.h"
3309467b48Spatrick #include "llvm/MC/MCInstrDesc.h"
3409467b48Spatrick #include "llvm/MC/MCInstrInfo.h"
3509467b48Spatrick #include "llvm/MC/MCParser/AsmCond.h"
3609467b48Spatrick #include "llvm/MC/MCParser/AsmLexer.h"
3709467b48Spatrick #include "llvm/MC/MCParser/MCAsmLexer.h"
3809467b48Spatrick #include "llvm/MC/MCParser/MCAsmParser.h"
3909467b48Spatrick #include "llvm/MC/MCParser/MCAsmParserExtension.h"
4009467b48Spatrick #include "llvm/MC/MCParser/MCAsmParserUtils.h"
4109467b48Spatrick #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
4209467b48Spatrick #include "llvm/MC/MCParser/MCTargetAsmParser.h"
4309467b48Spatrick #include "llvm/MC/MCRegisterInfo.h"
4409467b48Spatrick #include "llvm/MC/MCSection.h"
4509467b48Spatrick #include "llvm/MC/MCStreamer.h"
4609467b48Spatrick #include "llvm/MC/MCSymbol.h"
4709467b48Spatrick #include "llvm/MC/MCTargetOptions.h"
4809467b48Spatrick #include "llvm/MC/MCValue.h"
4909467b48Spatrick #include "llvm/Support/Casting.h"
5009467b48Spatrick #include "llvm/Support/CommandLine.h"
5109467b48Spatrick #include "llvm/Support/ErrorHandling.h"
5209467b48Spatrick #include "llvm/Support/MD5.h"
5309467b48Spatrick #include "llvm/Support/MathExtras.h"
5409467b48Spatrick #include "llvm/Support/MemoryBuffer.h"
5509467b48Spatrick #include "llvm/Support/SMLoc.h"
5609467b48Spatrick #include "llvm/Support/SourceMgr.h"
5709467b48Spatrick #include "llvm/Support/raw_ostream.h"
5809467b48Spatrick #include <algorithm>
5909467b48Spatrick #include <cassert>
6009467b48Spatrick #include <cctype>
6109467b48Spatrick #include <climits>
6209467b48Spatrick #include <cstddef>
6309467b48Spatrick #include <cstdint>
6409467b48Spatrick #include <deque>
6509467b48Spatrick #include <memory>
66*a96b3639Srobert #include <optional>
6709467b48Spatrick #include <sstream>
6809467b48Spatrick #include <string>
6909467b48Spatrick #include <tuple>
7009467b48Spatrick #include <utility>
7109467b48Spatrick #include <vector>
7209467b48Spatrick 
7309467b48Spatrick using namespace llvm;
7409467b48Spatrick 
7509467b48Spatrick MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;
7609467b48Spatrick 
7709467b48Spatrick namespace {
7809467b48Spatrick 
7909467b48Spatrick /// Helper types for tracking macro definitions.
8009467b48Spatrick typedef std::vector<AsmToken> MCAsmMacroArgument;
8109467b48Spatrick typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
8209467b48Spatrick 
8309467b48Spatrick /// Helper class for storing information about an active macro
8409467b48Spatrick /// instantiation.
8509467b48Spatrick struct MacroInstantiation {
8609467b48Spatrick   /// The location of the instantiation.
8709467b48Spatrick   SMLoc InstantiationLoc;
8809467b48Spatrick 
8909467b48Spatrick   /// The buffer where parsing should resume upon instantiation completion.
9009467b48Spatrick   unsigned ExitBuffer;
9109467b48Spatrick 
9209467b48Spatrick   /// The location where parsing should resume upon instantiation completion.
9309467b48Spatrick   SMLoc ExitLoc;
9409467b48Spatrick 
9509467b48Spatrick   /// The depth of TheCondStack at the start of the instantiation.
9609467b48Spatrick   size_t CondStackDepth;
9709467b48Spatrick };
9809467b48Spatrick 
9909467b48Spatrick struct ParseStatementInfo {
10009467b48Spatrick   /// The parsed operands from the last parsed statement.
10109467b48Spatrick   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
10209467b48Spatrick 
10309467b48Spatrick   /// The opcode from the last parsed instruction.
10409467b48Spatrick   unsigned Opcode = ~0U;
10509467b48Spatrick 
10609467b48Spatrick   /// Was there an error parsing the inline assembly?
10709467b48Spatrick   bool ParseError = false;
10809467b48Spatrick 
10909467b48Spatrick   SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
11009467b48Spatrick 
11109467b48Spatrick   ParseStatementInfo() = delete;
ParseStatementInfo__anone19baf360111::ParseStatementInfo11209467b48Spatrick   ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
11309467b48Spatrick     : AsmRewrites(rewrites) {}
11409467b48Spatrick };
11509467b48Spatrick 
11609467b48Spatrick /// The concrete assembly parser instance.
11709467b48Spatrick class AsmParser : public MCAsmParser {
11809467b48Spatrick private:
11909467b48Spatrick   AsmLexer Lexer;
12009467b48Spatrick   MCContext &Ctx;
12109467b48Spatrick   MCStreamer &Out;
12209467b48Spatrick   const MCAsmInfo &MAI;
12309467b48Spatrick   SourceMgr &SrcMgr;
12409467b48Spatrick   SourceMgr::DiagHandlerTy SavedDiagHandler;
12509467b48Spatrick   void *SavedDiagContext;
12609467b48Spatrick   std::unique_ptr<MCAsmParserExtension> PlatformParser;
127a0747c9fSpatrick   SMLoc StartTokLoc;
12809467b48Spatrick 
12909467b48Spatrick   /// This is the current buffer index we're lexing from as managed by the
13009467b48Spatrick   /// SourceMgr object.
13109467b48Spatrick   unsigned CurBuffer;
13209467b48Spatrick 
13309467b48Spatrick   AsmCond TheCondState;
13409467b48Spatrick   std::vector<AsmCond> TheCondStack;
13509467b48Spatrick 
13609467b48Spatrick   /// maps directive names to handler methods in parser
13709467b48Spatrick   /// extensions. Extensions register themselves in this map by calling
13809467b48Spatrick   /// addDirectiveHandler.
13909467b48Spatrick   StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
14009467b48Spatrick 
14109467b48Spatrick   /// Stack of active macro instantiations.
14209467b48Spatrick   std::vector<MacroInstantiation*> ActiveMacros;
14309467b48Spatrick 
14409467b48Spatrick   /// List of bodies of anonymous macros.
14509467b48Spatrick   std::deque<MCAsmMacro> MacroLikeBodies;
14609467b48Spatrick 
14709467b48Spatrick   /// Boolean tracking whether macro substitution is enabled.
14809467b48Spatrick   unsigned MacrosEnabledFlag : 1;
14909467b48Spatrick 
15009467b48Spatrick   /// Keeps track of how many .macro's have been instantiated.
15109467b48Spatrick   unsigned NumOfMacroInstantiations;
15209467b48Spatrick 
15309467b48Spatrick   /// The values from the last parsed cpp hash file line comment if any.
15409467b48Spatrick   struct CppHashInfoTy {
15509467b48Spatrick     StringRef Filename;
15609467b48Spatrick     int64_t LineNumber;
15709467b48Spatrick     SMLoc Loc;
15809467b48Spatrick     unsigned Buf;
CppHashInfoTy__anone19baf360111::AsmParser::CppHashInfoTy159*a96b3639Srobert     CppHashInfoTy() : LineNumber(0), Buf(0) {}
16009467b48Spatrick   };
16109467b48Spatrick   CppHashInfoTy CppHashInfo;
16209467b48Spatrick 
16309467b48Spatrick   /// The filename from the first cpp hash file line comment, if any.
16409467b48Spatrick   StringRef FirstCppHashFilename;
16509467b48Spatrick 
16609467b48Spatrick   /// List of forward directional labels for diagnosis at the end.
16709467b48Spatrick   SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
16809467b48Spatrick 
169a0747c9fSpatrick   SmallSet<StringRef, 2> LTODiscardSymbols;
170a0747c9fSpatrick 
17109467b48Spatrick   /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
17209467b48Spatrick   unsigned AssemblerDialect = ~0U;
17309467b48Spatrick 
17409467b48Spatrick   /// is Darwin compatibility enabled?
17509467b48Spatrick   bool IsDarwin = false;
17609467b48Spatrick 
17709467b48Spatrick   /// Are we parsing ms-style inline assembly?
178097a140dSpatrick   bool ParsingMSInlineAsm = false;
17909467b48Spatrick 
18009467b48Spatrick   /// Did we already inform the user about inconsistent MD5 usage?
18109467b48Spatrick   bool ReportedInconsistentMD5 = false;
18209467b48Spatrick 
18309467b48Spatrick   // Is alt macro mode enabled.
18409467b48Spatrick   bool AltMacroMode = false;
18509467b48Spatrick 
186a0747c9fSpatrick protected:
187a0747c9fSpatrick   virtual bool parseStatement(ParseStatementInfo &Info,
188a0747c9fSpatrick                               MCAsmParserSemaCallback *SI);
189a0747c9fSpatrick 
190a0747c9fSpatrick   /// This routine uses the target specific ParseInstruction function to
191a0747c9fSpatrick   /// parse an instruction into Operands, and then call the target specific
192a0747c9fSpatrick   /// MatchAndEmit function to match and emit the instruction.
193a0747c9fSpatrick   bool parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,
194a0747c9fSpatrick                                              StringRef IDVal, AsmToken ID,
195a0747c9fSpatrick                                              SMLoc IDLoc);
196a0747c9fSpatrick 
197a0747c9fSpatrick   /// Should we emit DWARF describing this assembler source?  (Returns false if
198a0747c9fSpatrick   /// the source has .file directives, which means we don't want to generate
199a0747c9fSpatrick   /// info describing the assembler source itself.)
200a0747c9fSpatrick   bool enabledGenDwarfForAssembly();
201a0747c9fSpatrick 
20209467b48Spatrick public:
20309467b48Spatrick   AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
20409467b48Spatrick             const MCAsmInfo &MAI, unsigned CB);
20509467b48Spatrick   AsmParser(const AsmParser &) = delete;
20609467b48Spatrick   AsmParser &operator=(const AsmParser &) = delete;
20709467b48Spatrick   ~AsmParser() override;
20809467b48Spatrick 
20909467b48Spatrick   bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
21009467b48Spatrick 
addDirectiveHandler(StringRef Directive,ExtensionDirectiveHandler Handler)21109467b48Spatrick   void addDirectiveHandler(StringRef Directive,
21209467b48Spatrick                            ExtensionDirectiveHandler Handler) override {
21309467b48Spatrick     ExtensionDirectiveMap[Directive] = Handler;
21409467b48Spatrick   }
21509467b48Spatrick 
addAliasForDirective(StringRef Directive,StringRef Alias)21609467b48Spatrick   void addAliasForDirective(StringRef Directive, StringRef Alias) override {
217097a140dSpatrick     DirectiveKindMap[Directive.lower()] = DirectiveKindMap[Alias.lower()];
21809467b48Spatrick   }
21909467b48Spatrick 
22009467b48Spatrick   /// @name MCAsmParser Interface
22109467b48Spatrick   /// {
22209467b48Spatrick 
getSourceManager()22309467b48Spatrick   SourceMgr &getSourceManager() override { return SrcMgr; }
getLexer()22409467b48Spatrick   MCAsmLexer &getLexer() override { return Lexer; }
getContext()22509467b48Spatrick   MCContext &getContext() override { return Ctx; }
getStreamer()22609467b48Spatrick   MCStreamer &getStreamer() override { return Out; }
22709467b48Spatrick 
getCVContext()22809467b48Spatrick   CodeViewContext &getCVContext() { return Ctx.getCVContext(); }
22909467b48Spatrick 
getAssemblerDialect()23009467b48Spatrick   unsigned getAssemblerDialect() override {
23109467b48Spatrick     if (AssemblerDialect == ~0U)
23209467b48Spatrick       return MAI.getAssemblerDialect();
23309467b48Spatrick     else
23409467b48Spatrick       return AssemblerDialect;
23509467b48Spatrick   }
setAssemblerDialect(unsigned i)23609467b48Spatrick   void setAssemblerDialect(unsigned i) override {
23709467b48Spatrick     AssemblerDialect = i;
23809467b48Spatrick   }
23909467b48Spatrick 
240*a96b3639Srobert   void Note(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) override;
241*a96b3639Srobert   bool Warning(SMLoc L, const Twine &Msg,
242*a96b3639Srobert                SMRange Range = std::nullopt) override;
243*a96b3639Srobert   bool printError(SMLoc L, const Twine &Msg,
244*a96b3639Srobert                   SMRange Range = std::nullopt) override;
24509467b48Spatrick 
24609467b48Spatrick   const AsmToken &Lex() override;
24709467b48Spatrick 
setParsingMSInlineAsm(bool V)248097a140dSpatrick   void setParsingMSInlineAsm(bool V) override {
249097a140dSpatrick     ParsingMSInlineAsm = V;
25009467b48Spatrick     // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
25109467b48Spatrick     // hex integer literals.
25209467b48Spatrick     Lexer.setLexMasmIntegers(V);
25309467b48Spatrick   }
isParsingMSInlineAsm()254097a140dSpatrick   bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
25509467b48Spatrick 
discardLTOSymbol(StringRef Name) const256a0747c9fSpatrick   bool discardLTOSymbol(StringRef Name) const override {
257a0747c9fSpatrick     return LTODiscardSymbols.contains(Name);
258a0747c9fSpatrick   }
259a0747c9fSpatrick 
260a0747c9fSpatrick   bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs,
261a0747c9fSpatrick                         unsigned &NumInputs,
26209467b48Spatrick                         SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
26309467b48Spatrick                         SmallVectorImpl<std::string> &Constraints,
26409467b48Spatrick                         SmallVectorImpl<std::string> &Clobbers,
26509467b48Spatrick                         const MCInstrInfo *MII, const MCInstPrinter *IP,
26609467b48Spatrick                         MCAsmParserSemaCallback &SI) override;
26709467b48Spatrick 
26809467b48Spatrick   bool parseExpression(const MCExpr *&Res);
26909467b48Spatrick   bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
270a0747c9fSpatrick   bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
271a0747c9fSpatrick                         AsmTypeInfo *TypeInfo) override;
27209467b48Spatrick   bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
27309467b48Spatrick   bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
27409467b48Spatrick                              SMLoc &EndLoc) override;
27509467b48Spatrick   bool parseAbsoluteExpression(int64_t &Res) override;
27609467b48Spatrick 
27709467b48Spatrick   /// Parse a floating point expression using the float \p Semantics
27809467b48Spatrick   /// and set \p Res to the value.
27909467b48Spatrick   bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
28009467b48Spatrick 
28109467b48Spatrick   /// Parse an identifier or string (as a quoted identifier)
28209467b48Spatrick   /// and set \p Res to the identifier contents.
28309467b48Spatrick   bool parseIdentifier(StringRef &Res) override;
28409467b48Spatrick   void eatToEndOfStatement() override;
28509467b48Spatrick 
28609467b48Spatrick   bool checkForValidSection() override;
28709467b48Spatrick 
28809467b48Spatrick   /// }
28909467b48Spatrick 
29009467b48Spatrick private:
29109467b48Spatrick   bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
292097a140dSpatrick   bool parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo = true);
29309467b48Spatrick 
29409467b48Spatrick   void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
29509467b48Spatrick                         ArrayRef<MCAsmMacroParameter> Parameters);
29609467b48Spatrick   bool expandMacro(raw_svector_ostream &OS, StringRef Body,
29709467b48Spatrick                    ArrayRef<MCAsmMacroParameter> Parameters,
29809467b48Spatrick                    ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable,
29909467b48Spatrick                    SMLoc L);
30009467b48Spatrick 
30109467b48Spatrick   /// Are macros enabled in the parser?
areMacrosEnabled()30209467b48Spatrick   bool areMacrosEnabled() {return MacrosEnabledFlag;}
30309467b48Spatrick 
30409467b48Spatrick   /// Control a flag in the parser that enables or disables macros.
setMacrosEnabled(bool Flag)30509467b48Spatrick   void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
30609467b48Spatrick 
30709467b48Spatrick   /// Are we inside a macro instantiation?
isInsideMacroInstantiation()30809467b48Spatrick   bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
30909467b48Spatrick 
31009467b48Spatrick   /// Handle entry to macro instantiation.
31109467b48Spatrick   ///
31209467b48Spatrick   /// \param M The macro.
31309467b48Spatrick   /// \param NameLoc Instantiation location.
31409467b48Spatrick   bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
31509467b48Spatrick 
31609467b48Spatrick   /// Handle exit from macro instantiation.
31709467b48Spatrick   void handleMacroExit();
31809467b48Spatrick 
31909467b48Spatrick   /// Extract AsmTokens for a macro argument.
32009467b48Spatrick   bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
32109467b48Spatrick 
32209467b48Spatrick   /// Parse all macro arguments for a given macro.
32309467b48Spatrick   bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
32409467b48Spatrick 
32509467b48Spatrick   void printMacroInstantiations();
printMessage(SMLoc Loc,SourceMgr::DiagKind Kind,const Twine & Msg,SMRange Range=std::nullopt) const32609467b48Spatrick   void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
327*a96b3639Srobert                     SMRange Range = std::nullopt) const {
32809467b48Spatrick     ArrayRef<SMRange> Ranges(Range);
32909467b48Spatrick     SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
33009467b48Spatrick   }
33109467b48Spatrick   static void DiagHandler(const SMDiagnostic &Diag, void *Context);
33209467b48Spatrick 
33309467b48Spatrick   /// Enter the specified file. This returns true on failure.
33409467b48Spatrick   bool enterIncludeFile(const std::string &Filename);
33509467b48Spatrick 
33609467b48Spatrick   /// Process the specified file for the .incbin directive.
33709467b48Spatrick   /// This returns true on failure.
33809467b48Spatrick   bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,
33909467b48Spatrick                          const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());
34009467b48Spatrick 
34109467b48Spatrick   /// Reset the current lexer position to that given by \p Loc. The
34209467b48Spatrick   /// current token is not set; clients should ensure Lex() is called
34309467b48Spatrick   /// subsequently.
34409467b48Spatrick   ///
34509467b48Spatrick   /// \param InBuffer If not 0, should be the known buffer id that contains the
34609467b48Spatrick   /// location.
34709467b48Spatrick   void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);
34809467b48Spatrick 
34909467b48Spatrick   /// Parse up to the end of statement and a return the contents from the
35009467b48Spatrick   /// current token until the end of the statement; the current token on exit
35109467b48Spatrick   /// will be either the EndOfStatement or EOF.
35209467b48Spatrick   StringRef parseStringToEndOfStatement() override;
35309467b48Spatrick 
35409467b48Spatrick   /// Parse until the end of a statement or a comma is encountered,
35509467b48Spatrick   /// return the contents from the current token up to the end or comma.
35609467b48Spatrick   StringRef parseStringToComma();
35709467b48Spatrick 
358*a96b3639Srobert   enum class AssignmentKind {
359*a96b3639Srobert     Set,
360*a96b3639Srobert     Equiv,
361*a96b3639Srobert     Equal,
362*a96b3639Srobert     LTOSetConditional,
363*a96b3639Srobert   };
364*a96b3639Srobert 
365*a96b3639Srobert   bool parseAssignment(StringRef Name, AssignmentKind Kind);
36609467b48Spatrick 
36709467b48Spatrick   unsigned getBinOpPrecedence(AsmToken::TokenKind K,
36809467b48Spatrick                               MCBinaryExpr::Opcode &Kind);
36909467b48Spatrick 
37009467b48Spatrick   bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
37109467b48Spatrick   bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
37209467b48Spatrick   bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
37309467b48Spatrick 
37409467b48Spatrick   bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
37509467b48Spatrick 
37609467b48Spatrick   bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);
37709467b48Spatrick   bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);
37809467b48Spatrick 
37909467b48Spatrick   // Generic (target and platform independent) directive parsing.
38009467b48Spatrick   enum DirectiveKind {
38109467b48Spatrick     DK_NO_DIRECTIVE, // Placeholder
38209467b48Spatrick     DK_SET,
38309467b48Spatrick     DK_EQU,
38409467b48Spatrick     DK_EQUIV,
38509467b48Spatrick     DK_ASCII,
38609467b48Spatrick     DK_ASCIZ,
38709467b48Spatrick     DK_STRING,
38809467b48Spatrick     DK_BYTE,
38909467b48Spatrick     DK_SHORT,
39009467b48Spatrick     DK_RELOC,
39109467b48Spatrick     DK_VALUE,
39209467b48Spatrick     DK_2BYTE,
39309467b48Spatrick     DK_LONG,
39409467b48Spatrick     DK_INT,
39509467b48Spatrick     DK_4BYTE,
39609467b48Spatrick     DK_QUAD,
39709467b48Spatrick     DK_8BYTE,
39809467b48Spatrick     DK_OCTA,
39909467b48Spatrick     DK_DC,
40009467b48Spatrick     DK_DC_A,
40109467b48Spatrick     DK_DC_B,
40209467b48Spatrick     DK_DC_D,
40309467b48Spatrick     DK_DC_L,
40409467b48Spatrick     DK_DC_S,
40509467b48Spatrick     DK_DC_W,
40609467b48Spatrick     DK_DC_X,
40709467b48Spatrick     DK_DCB,
40809467b48Spatrick     DK_DCB_B,
40909467b48Spatrick     DK_DCB_D,
41009467b48Spatrick     DK_DCB_L,
41109467b48Spatrick     DK_DCB_S,
41209467b48Spatrick     DK_DCB_W,
41309467b48Spatrick     DK_DCB_X,
41409467b48Spatrick     DK_DS,
41509467b48Spatrick     DK_DS_B,
41609467b48Spatrick     DK_DS_D,
41709467b48Spatrick     DK_DS_L,
41809467b48Spatrick     DK_DS_P,
41909467b48Spatrick     DK_DS_S,
42009467b48Spatrick     DK_DS_W,
42109467b48Spatrick     DK_DS_X,
42209467b48Spatrick     DK_SINGLE,
42309467b48Spatrick     DK_FLOAT,
42409467b48Spatrick     DK_DOUBLE,
42509467b48Spatrick     DK_ALIGN,
42609467b48Spatrick     DK_ALIGN32,
42709467b48Spatrick     DK_BALIGN,
42809467b48Spatrick     DK_BALIGNW,
42909467b48Spatrick     DK_BALIGNL,
43009467b48Spatrick     DK_P2ALIGN,
43109467b48Spatrick     DK_P2ALIGNW,
43209467b48Spatrick     DK_P2ALIGNL,
43309467b48Spatrick     DK_ORG,
43409467b48Spatrick     DK_FILL,
43509467b48Spatrick     DK_ENDR,
43609467b48Spatrick     DK_BUNDLE_ALIGN_MODE,
43709467b48Spatrick     DK_BUNDLE_LOCK,
43809467b48Spatrick     DK_BUNDLE_UNLOCK,
43909467b48Spatrick     DK_ZERO,
44009467b48Spatrick     DK_EXTERN,
44109467b48Spatrick     DK_GLOBL,
44209467b48Spatrick     DK_GLOBAL,
44309467b48Spatrick     DK_LAZY_REFERENCE,
44409467b48Spatrick     DK_NO_DEAD_STRIP,
44509467b48Spatrick     DK_SYMBOL_RESOLVER,
44609467b48Spatrick     DK_PRIVATE_EXTERN,
44709467b48Spatrick     DK_REFERENCE,
44809467b48Spatrick     DK_WEAK_DEFINITION,
44909467b48Spatrick     DK_WEAK_REFERENCE,
45009467b48Spatrick     DK_WEAK_DEF_CAN_BE_HIDDEN,
45109467b48Spatrick     DK_COLD,
45209467b48Spatrick     DK_COMM,
45309467b48Spatrick     DK_COMMON,
45409467b48Spatrick     DK_LCOMM,
45509467b48Spatrick     DK_ABORT,
45609467b48Spatrick     DK_INCLUDE,
45709467b48Spatrick     DK_INCBIN,
45809467b48Spatrick     DK_CODE16,
45909467b48Spatrick     DK_CODE16GCC,
46009467b48Spatrick     DK_REPT,
46109467b48Spatrick     DK_IRP,
46209467b48Spatrick     DK_IRPC,
46309467b48Spatrick     DK_IF,
46409467b48Spatrick     DK_IFEQ,
46509467b48Spatrick     DK_IFGE,
46609467b48Spatrick     DK_IFGT,
46709467b48Spatrick     DK_IFLE,
46809467b48Spatrick     DK_IFLT,
46909467b48Spatrick     DK_IFNE,
47009467b48Spatrick     DK_IFB,
47109467b48Spatrick     DK_IFNB,
47209467b48Spatrick     DK_IFC,
47309467b48Spatrick     DK_IFEQS,
47409467b48Spatrick     DK_IFNC,
47509467b48Spatrick     DK_IFNES,
47609467b48Spatrick     DK_IFDEF,
47709467b48Spatrick     DK_IFNDEF,
47809467b48Spatrick     DK_IFNOTDEF,
47909467b48Spatrick     DK_ELSEIF,
48009467b48Spatrick     DK_ELSE,
48109467b48Spatrick     DK_ENDIF,
48209467b48Spatrick     DK_SPACE,
48309467b48Spatrick     DK_SKIP,
48409467b48Spatrick     DK_FILE,
48509467b48Spatrick     DK_LINE,
48609467b48Spatrick     DK_LOC,
48709467b48Spatrick     DK_STABS,
48809467b48Spatrick     DK_CV_FILE,
48909467b48Spatrick     DK_CV_FUNC_ID,
49009467b48Spatrick     DK_CV_INLINE_SITE_ID,
49109467b48Spatrick     DK_CV_LOC,
49209467b48Spatrick     DK_CV_LINETABLE,
49309467b48Spatrick     DK_CV_INLINE_LINETABLE,
49409467b48Spatrick     DK_CV_DEF_RANGE,
49509467b48Spatrick     DK_CV_STRINGTABLE,
49609467b48Spatrick     DK_CV_STRING,
49709467b48Spatrick     DK_CV_FILECHECKSUMS,
49809467b48Spatrick     DK_CV_FILECHECKSUM_OFFSET,
49909467b48Spatrick     DK_CV_FPO_DATA,
50009467b48Spatrick     DK_CFI_SECTIONS,
50109467b48Spatrick     DK_CFI_STARTPROC,
50209467b48Spatrick     DK_CFI_ENDPROC,
50309467b48Spatrick     DK_CFI_DEF_CFA,
50409467b48Spatrick     DK_CFI_DEF_CFA_OFFSET,
50509467b48Spatrick     DK_CFI_ADJUST_CFA_OFFSET,
50609467b48Spatrick     DK_CFI_DEF_CFA_REGISTER,
507a0747c9fSpatrick     DK_CFI_LLVM_DEF_ASPACE_CFA,
50809467b48Spatrick     DK_CFI_OFFSET,
50909467b48Spatrick     DK_CFI_REL_OFFSET,
51009467b48Spatrick     DK_CFI_PERSONALITY,
51109467b48Spatrick     DK_CFI_LSDA,
51209467b48Spatrick     DK_CFI_REMEMBER_STATE,
51309467b48Spatrick     DK_CFI_RESTORE_STATE,
51409467b48Spatrick     DK_CFI_SAME_VALUE,
51509467b48Spatrick     DK_CFI_RESTORE,
51609467b48Spatrick     DK_CFI_ESCAPE,
51709467b48Spatrick     DK_CFI_RETURN_COLUMN,
51809467b48Spatrick     DK_CFI_SIGNAL_FRAME,
51909467b48Spatrick     DK_CFI_UNDEFINED,
52009467b48Spatrick     DK_CFI_REGISTER,
52109467b48Spatrick     DK_CFI_WINDOW_SAVE,
52209467b48Spatrick     DK_CFI_B_KEY_FRAME,
52309467b48Spatrick     DK_MACROS_ON,
52409467b48Spatrick     DK_MACROS_OFF,
52509467b48Spatrick     DK_ALTMACRO,
52609467b48Spatrick     DK_NOALTMACRO,
52709467b48Spatrick     DK_MACRO,
52809467b48Spatrick     DK_EXITM,
52909467b48Spatrick     DK_ENDM,
53009467b48Spatrick     DK_ENDMACRO,
53109467b48Spatrick     DK_PURGEM,
53209467b48Spatrick     DK_SLEB128,
53309467b48Spatrick     DK_ULEB128,
53409467b48Spatrick     DK_ERR,
53509467b48Spatrick     DK_ERROR,
53609467b48Spatrick     DK_WARNING,
53709467b48Spatrick     DK_PRINT,
53809467b48Spatrick     DK_ADDRSIG,
53909467b48Spatrick     DK_ADDRSIG_SYM,
540a0747c9fSpatrick     DK_PSEUDO_PROBE,
541a0747c9fSpatrick     DK_LTO_DISCARD,
542*a96b3639Srobert     DK_LTO_SET_CONDITIONAL,
543*a96b3639Srobert     DK_CFI_MTE_TAGGED_FRAME,
544*a96b3639Srobert     DK_MEMTAG,
54509467b48Spatrick     DK_END
54609467b48Spatrick   };
54709467b48Spatrick 
54809467b48Spatrick   /// Maps directive name --> DirectiveKind enum, for
54909467b48Spatrick   /// directives parsed by this class.
55009467b48Spatrick   StringMap<DirectiveKind> DirectiveKindMap;
55109467b48Spatrick 
55209467b48Spatrick   // Codeview def_range type parsing.
55309467b48Spatrick   enum CVDefRangeType {
55409467b48Spatrick     CVDR_DEFRANGE = 0, // Placeholder
55509467b48Spatrick     CVDR_DEFRANGE_REGISTER,
55609467b48Spatrick     CVDR_DEFRANGE_FRAMEPOINTER_REL,
55709467b48Spatrick     CVDR_DEFRANGE_SUBFIELD_REGISTER,
55809467b48Spatrick     CVDR_DEFRANGE_REGISTER_REL
55909467b48Spatrick   };
56009467b48Spatrick 
56109467b48Spatrick   /// Maps Codeview def_range types --> CVDefRangeType enum, for
56209467b48Spatrick   /// Codeview def_range types parsed by this class.
56309467b48Spatrick   StringMap<CVDefRangeType> CVDefRangeTypeMap;
56409467b48Spatrick 
56509467b48Spatrick   // ".ascii", ".asciz", ".string"
56609467b48Spatrick   bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
56709467b48Spatrick   bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
56809467b48Spatrick   bool parseDirectiveValue(StringRef IDVal,
56909467b48Spatrick                            unsigned Size);       // ".byte", ".long", ...
57009467b48Spatrick   bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ...
57109467b48Spatrick   bool parseDirectiveRealValue(StringRef IDVal,
57209467b48Spatrick                                const fltSemantics &); // ".single", ...
57309467b48Spatrick   bool parseDirectiveFill(); // ".fill"
57409467b48Spatrick   bool parseDirectiveZero(); // ".zero"
575*a96b3639Srobert   // ".set", ".equ", ".equiv", ".lto_set_conditional"
576*a96b3639Srobert   bool parseDirectiveSet(StringRef IDVal, AssignmentKind Kind);
57709467b48Spatrick   bool parseDirectiveOrg(); // ".org"
57809467b48Spatrick   // ".align{,32}", ".p2align{,w,l}"
57909467b48Spatrick   bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);
58009467b48Spatrick 
58109467b48Spatrick   // ".file", ".line", ".loc", ".stabs"
58209467b48Spatrick   bool parseDirectiveFile(SMLoc DirectiveLoc);
58309467b48Spatrick   bool parseDirectiveLine();
58409467b48Spatrick   bool parseDirectiveLoc();
58509467b48Spatrick   bool parseDirectiveStabs();
58609467b48Spatrick 
58709467b48Spatrick   // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
58809467b48Spatrick   // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
58909467b48Spatrick   bool parseDirectiveCVFile();
59009467b48Spatrick   bool parseDirectiveCVFuncId();
59109467b48Spatrick   bool parseDirectiveCVInlineSiteId();
59209467b48Spatrick   bool parseDirectiveCVLoc();
59309467b48Spatrick   bool parseDirectiveCVLinetable();
59409467b48Spatrick   bool parseDirectiveCVInlineLinetable();
59509467b48Spatrick   bool parseDirectiveCVDefRange();
59609467b48Spatrick   bool parseDirectiveCVString();
59709467b48Spatrick   bool parseDirectiveCVStringTable();
59809467b48Spatrick   bool parseDirectiveCVFileChecksums();
59909467b48Spatrick   bool parseDirectiveCVFileChecksumOffset();
60009467b48Spatrick   bool parseDirectiveCVFPOData();
60109467b48Spatrick 
60209467b48Spatrick   // .cfi directives
60309467b48Spatrick   bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
60409467b48Spatrick   bool parseDirectiveCFIWindowSave();
60509467b48Spatrick   bool parseDirectiveCFISections();
60609467b48Spatrick   bool parseDirectiveCFIStartProc();
60709467b48Spatrick   bool parseDirectiveCFIEndProc();
60809467b48Spatrick   bool parseDirectiveCFIDefCfaOffset();
60909467b48Spatrick   bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
61009467b48Spatrick   bool parseDirectiveCFIAdjustCfaOffset();
61109467b48Spatrick   bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
612a0747c9fSpatrick   bool parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc);
61309467b48Spatrick   bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
61409467b48Spatrick   bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
61509467b48Spatrick   bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
61609467b48Spatrick   bool parseDirectiveCFIRememberState();
61709467b48Spatrick   bool parseDirectiveCFIRestoreState();
61809467b48Spatrick   bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
61909467b48Spatrick   bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
62009467b48Spatrick   bool parseDirectiveCFIEscape();
62109467b48Spatrick   bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
62209467b48Spatrick   bool parseDirectiveCFISignalFrame();
62309467b48Spatrick   bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
62409467b48Spatrick 
62509467b48Spatrick   // macro directives
62609467b48Spatrick   bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
62709467b48Spatrick   bool parseDirectiveExitMacro(StringRef Directive);
62809467b48Spatrick   bool parseDirectiveEndMacro(StringRef Directive);
62909467b48Spatrick   bool parseDirectiveMacro(SMLoc DirectiveLoc);
63009467b48Spatrick   bool parseDirectiveMacrosOnOff(StringRef Directive);
63109467b48Spatrick   // alternate macro mode directives
63209467b48Spatrick   bool parseDirectiveAltmacro(StringRef Directive);
63309467b48Spatrick   // ".bundle_align_mode"
63409467b48Spatrick   bool parseDirectiveBundleAlignMode();
63509467b48Spatrick   // ".bundle_lock"
63609467b48Spatrick   bool parseDirectiveBundleLock();
63709467b48Spatrick   // ".bundle_unlock"
63809467b48Spatrick   bool parseDirectiveBundleUnlock();
63909467b48Spatrick 
64009467b48Spatrick   // ".space", ".skip"
64109467b48Spatrick   bool parseDirectiveSpace(StringRef IDVal);
64209467b48Spatrick 
64309467b48Spatrick   // ".dcb"
64409467b48Spatrick   bool parseDirectiveDCB(StringRef IDVal, unsigned Size);
64509467b48Spatrick   bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &);
64609467b48Spatrick   // ".ds"
64709467b48Spatrick   bool parseDirectiveDS(StringRef IDVal, unsigned Size);
64809467b48Spatrick 
64909467b48Spatrick   // .sleb128 (Signed=true) and .uleb128 (Signed=false)
65009467b48Spatrick   bool parseDirectiveLEB128(bool Signed);
65109467b48Spatrick 
65209467b48Spatrick   /// Parse a directive like ".globl" which
65309467b48Spatrick   /// accepts a single symbol (which should be a label or an external).
65409467b48Spatrick   bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
65509467b48Spatrick 
65609467b48Spatrick   bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
65709467b48Spatrick 
65809467b48Spatrick   bool parseDirectiveAbort(); // ".abort"
65909467b48Spatrick   bool parseDirectiveInclude(); // ".include"
66009467b48Spatrick   bool parseDirectiveIncbin(); // ".incbin"
66109467b48Spatrick 
66209467b48Spatrick   // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"
66309467b48Spatrick   bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
66409467b48Spatrick   // ".ifb" or ".ifnb", depending on ExpectBlank.
66509467b48Spatrick   bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
66609467b48Spatrick   // ".ifc" or ".ifnc", depending on ExpectEqual.
66709467b48Spatrick   bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
66809467b48Spatrick   // ".ifeqs" or ".ifnes", depending on ExpectEqual.
66909467b48Spatrick   bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);
67009467b48Spatrick   // ".ifdef" or ".ifndef", depending on expect_defined
67109467b48Spatrick   bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
67209467b48Spatrick   bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
67309467b48Spatrick   bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
67409467b48Spatrick   bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
67509467b48Spatrick   bool parseEscapedString(std::string &Data) override;
676097a140dSpatrick   bool parseAngleBracketString(std::string &Data) override;
67709467b48Spatrick 
67809467b48Spatrick   const MCExpr *applyModifierToExpr(const MCExpr *E,
67909467b48Spatrick                                     MCSymbolRefExpr::VariantKind Variant);
68009467b48Spatrick 
68109467b48Spatrick   // Macro-like directives
68209467b48Spatrick   MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
68309467b48Spatrick   void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
68409467b48Spatrick                                 raw_svector_ostream &OS);
68509467b48Spatrick   bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);
68609467b48Spatrick   bool parseDirectiveIrp(SMLoc DirectiveLoc);  // ".irp"
68709467b48Spatrick   bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
68809467b48Spatrick   bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
68909467b48Spatrick 
69009467b48Spatrick   // "_emit" or "__emit"
69109467b48Spatrick   bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
69209467b48Spatrick                             size_t Len);
69309467b48Spatrick 
69409467b48Spatrick   // "align"
69509467b48Spatrick   bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
69609467b48Spatrick 
69709467b48Spatrick   // "end"
69809467b48Spatrick   bool parseDirectiveEnd(SMLoc DirectiveLoc);
69909467b48Spatrick 
70009467b48Spatrick   // ".err" or ".error"
70109467b48Spatrick   bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
70209467b48Spatrick 
70309467b48Spatrick   // ".warning"
70409467b48Spatrick   bool parseDirectiveWarning(SMLoc DirectiveLoc);
70509467b48Spatrick 
70609467b48Spatrick   // .print <double-quotes-string>
70709467b48Spatrick   bool parseDirectivePrint(SMLoc DirectiveLoc);
70809467b48Spatrick 
709a0747c9fSpatrick   // .pseudoprobe
710a0747c9fSpatrick   bool parseDirectivePseudoProbe();
711a0747c9fSpatrick 
712a0747c9fSpatrick   // ".lto_discard"
713a0747c9fSpatrick   bool parseDirectiveLTODiscard();
714a0747c9fSpatrick 
71509467b48Spatrick   // Directives to support address-significance tables.
71609467b48Spatrick   bool parseDirectiveAddrsig();
71709467b48Spatrick   bool parseDirectiveAddrsigSym();
71809467b48Spatrick 
71909467b48Spatrick   void initializeDirectiveKindMap();
72009467b48Spatrick   void initializeCVDefRangeTypeMap();
72109467b48Spatrick };
72209467b48Spatrick 
723a0747c9fSpatrick class HLASMAsmParser final : public AsmParser {
724a0747c9fSpatrick private:
725a0747c9fSpatrick   MCAsmLexer &Lexer;
726a0747c9fSpatrick   MCStreamer &Out;
727a0747c9fSpatrick 
lexLeadingSpaces()728a0747c9fSpatrick   void lexLeadingSpaces() {
729a0747c9fSpatrick     while (Lexer.is(AsmToken::Space))
730a0747c9fSpatrick       Lexer.Lex();
731a0747c9fSpatrick   }
732a0747c9fSpatrick 
733a0747c9fSpatrick   bool parseAsHLASMLabel(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI);
734a0747c9fSpatrick   bool parseAsMachineInstruction(ParseStatementInfo &Info,
735a0747c9fSpatrick                                  MCAsmParserSemaCallback *SI);
736a0747c9fSpatrick 
737a0747c9fSpatrick public:
HLASMAsmParser(SourceMgr & SM,MCContext & Ctx,MCStreamer & Out,const MCAsmInfo & MAI,unsigned CB=0)738a0747c9fSpatrick   HLASMAsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
739a0747c9fSpatrick                  const MCAsmInfo &MAI, unsigned CB = 0)
740a0747c9fSpatrick       : AsmParser(SM, Ctx, Out, MAI, CB), Lexer(getLexer()), Out(Out) {
741a0747c9fSpatrick     Lexer.setSkipSpace(false);
742a0747c9fSpatrick     Lexer.setAllowHashInIdentifier(true);
743a0747c9fSpatrick     Lexer.setLexHLASMIntegers(true);
744a0747c9fSpatrick     Lexer.setLexHLASMStrings(true);
745a0747c9fSpatrick   }
746a0747c9fSpatrick 
~HLASMAsmParser()747a0747c9fSpatrick   ~HLASMAsmParser() { Lexer.setSkipSpace(true); }
748a0747c9fSpatrick 
749a0747c9fSpatrick   bool parseStatement(ParseStatementInfo &Info,
750a0747c9fSpatrick                       MCAsmParserSemaCallback *SI) override;
751a0747c9fSpatrick };
752a0747c9fSpatrick 
75309467b48Spatrick } // end anonymous namespace
75409467b48Spatrick 
75509467b48Spatrick namespace llvm {
75609467b48Spatrick 
757*a96b3639Srobert extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
758*a96b3639Srobert 
75909467b48Spatrick extern MCAsmParserExtension *createDarwinAsmParser();
76009467b48Spatrick extern MCAsmParserExtension *createELFAsmParser();
76109467b48Spatrick extern MCAsmParserExtension *createCOFFAsmParser();
762*a96b3639Srobert extern MCAsmParserExtension *createGOFFAsmParser();
763a0747c9fSpatrick extern MCAsmParserExtension *createXCOFFAsmParser();
76409467b48Spatrick extern MCAsmParserExtension *createWasmAsmParser();
76509467b48Spatrick 
76609467b48Spatrick } // end namespace llvm
76709467b48Spatrick 
76809467b48Spatrick enum { DEFAULT_ADDRSPACE = 0 };
76909467b48Spatrick 
AsmParser(SourceMgr & SM,MCContext & Ctx,MCStreamer & Out,const MCAsmInfo & MAI,unsigned CB=0)77009467b48Spatrick AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
77109467b48Spatrick                      const MCAsmInfo &MAI, unsigned CB = 0)
77209467b48Spatrick     : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
77309467b48Spatrick       CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {
77409467b48Spatrick   HadError = false;
77509467b48Spatrick   // Save the old handler.
77609467b48Spatrick   SavedDiagHandler = SrcMgr.getDiagHandler();
77709467b48Spatrick   SavedDiagContext = SrcMgr.getDiagContext();
77809467b48Spatrick   // Set our own handler which calls the saved handler.
77909467b48Spatrick   SrcMgr.setDiagHandler(DiagHandler, this);
78009467b48Spatrick   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
781a0747c9fSpatrick   // Make MCStreamer aware of the StartTokLoc for locations in diagnostics.
782a0747c9fSpatrick   Out.setStartTokLocPtr(&StartTokLoc);
78309467b48Spatrick 
78409467b48Spatrick   // Initialize the platform / file format parser.
785a0747c9fSpatrick   switch (Ctx.getObjectFileType()) {
786a0747c9fSpatrick   case MCContext::IsCOFF:
78709467b48Spatrick     PlatformParser.reset(createCOFFAsmParser());
78809467b48Spatrick     break;
789a0747c9fSpatrick   case MCContext::IsMachO:
79009467b48Spatrick     PlatformParser.reset(createDarwinAsmParser());
79109467b48Spatrick     IsDarwin = true;
79209467b48Spatrick     break;
793a0747c9fSpatrick   case MCContext::IsELF:
79409467b48Spatrick     PlatformParser.reset(createELFAsmParser());
79509467b48Spatrick     break;
796a0747c9fSpatrick   case MCContext::IsGOFF:
797*a96b3639Srobert     PlatformParser.reset(createGOFFAsmParser());
798*a96b3639Srobert     break;
799*a96b3639Srobert   case MCContext::IsSPIRV:
800*a96b3639Srobert     report_fatal_error(
801*a96b3639Srobert         "Need to implement createSPIRVAsmParser for SPIRV format.");
802*a96b3639Srobert     break;
803a0747c9fSpatrick   case MCContext::IsWasm:
80409467b48Spatrick     PlatformParser.reset(createWasmAsmParser());
80509467b48Spatrick     break;
806a0747c9fSpatrick   case MCContext::IsXCOFF:
807a0747c9fSpatrick     PlatformParser.reset(createXCOFFAsmParser());
80809467b48Spatrick     break;
809*a96b3639Srobert   case MCContext::IsDXContainer:
810*a96b3639Srobert     llvm_unreachable("DXContainer is not supported yet");
811*a96b3639Srobert     break;
81209467b48Spatrick   }
81309467b48Spatrick 
81409467b48Spatrick   PlatformParser->Initialize(*this);
81509467b48Spatrick   initializeDirectiveKindMap();
81609467b48Spatrick   initializeCVDefRangeTypeMap();
81709467b48Spatrick 
81809467b48Spatrick   NumOfMacroInstantiations = 0;
81909467b48Spatrick }
82009467b48Spatrick 
~AsmParser()82109467b48Spatrick AsmParser::~AsmParser() {
82209467b48Spatrick   assert((HadError || ActiveMacros.empty()) &&
82309467b48Spatrick          "Unexpected active macro instantiation!");
82409467b48Spatrick 
825a0747c9fSpatrick   // Remove MCStreamer's reference to the parser SMLoc.
826a0747c9fSpatrick   Out.setStartTokLocPtr(nullptr);
82709467b48Spatrick   // Restore the saved diagnostics handler and context for use during
82809467b48Spatrick   // finalization.
82909467b48Spatrick   SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
83009467b48Spatrick }
83109467b48Spatrick 
printMacroInstantiations()83209467b48Spatrick void AsmParser::printMacroInstantiations() {
83309467b48Spatrick   // Print the active macro instantiation stack.
83409467b48Spatrick   for (std::vector<MacroInstantiation *>::const_reverse_iterator
83509467b48Spatrick            it = ActiveMacros.rbegin(),
83609467b48Spatrick            ie = ActiveMacros.rend();
83709467b48Spatrick        it != ie; ++it)
83809467b48Spatrick     printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
83909467b48Spatrick                  "while in macro instantiation");
84009467b48Spatrick }
84109467b48Spatrick 
Note(SMLoc L,const Twine & Msg,SMRange Range)84209467b48Spatrick void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
84309467b48Spatrick   printPendingErrors();
84409467b48Spatrick   printMessage(L, SourceMgr::DK_Note, Msg, Range);
84509467b48Spatrick   printMacroInstantiations();
84609467b48Spatrick }
84709467b48Spatrick 
Warning(SMLoc L,const Twine & Msg,SMRange Range)84809467b48Spatrick bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
84909467b48Spatrick   if(getTargetParser().getTargetOptions().MCNoWarn)
85009467b48Spatrick     return false;
85109467b48Spatrick   if (getTargetParser().getTargetOptions().MCFatalWarnings)
85209467b48Spatrick     return Error(L, Msg, Range);
85309467b48Spatrick   printMessage(L, SourceMgr::DK_Warning, Msg, Range);
85409467b48Spatrick   printMacroInstantiations();
85509467b48Spatrick   return false;
85609467b48Spatrick }
85709467b48Spatrick 
printError(SMLoc L,const Twine & Msg,SMRange Range)85809467b48Spatrick bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
85909467b48Spatrick   HadError = true;
86009467b48Spatrick   printMessage(L, SourceMgr::DK_Error, Msg, Range);
86109467b48Spatrick   printMacroInstantiations();
86209467b48Spatrick   return true;
86309467b48Spatrick }
86409467b48Spatrick 
enterIncludeFile(const std::string & Filename)86509467b48Spatrick bool AsmParser::enterIncludeFile(const std::string &Filename) {
86609467b48Spatrick   std::string IncludedFile;
86709467b48Spatrick   unsigned NewBuf =
86809467b48Spatrick       SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
86909467b48Spatrick   if (!NewBuf)
87009467b48Spatrick     return true;
87109467b48Spatrick 
87209467b48Spatrick   CurBuffer = NewBuf;
87309467b48Spatrick   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
87409467b48Spatrick   return false;
87509467b48Spatrick }
87609467b48Spatrick 
87709467b48Spatrick /// Process the specified .incbin file by searching for it in the include paths
87809467b48Spatrick /// then just emitting the byte contents of the file to the streamer. This
87909467b48Spatrick /// returns true on failure.
processIncbinFile(const std::string & Filename,int64_t Skip,const MCExpr * Count,SMLoc Loc)88009467b48Spatrick bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
88109467b48Spatrick                                   const MCExpr *Count, SMLoc Loc) {
88209467b48Spatrick   std::string IncludedFile;
88309467b48Spatrick   unsigned NewBuf =
88409467b48Spatrick       SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
88509467b48Spatrick   if (!NewBuf)
88609467b48Spatrick     return true;
88709467b48Spatrick 
88809467b48Spatrick   // Pick up the bytes from the file and emit them.
88909467b48Spatrick   StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();
89009467b48Spatrick   Bytes = Bytes.drop_front(Skip);
89109467b48Spatrick   if (Count) {
89209467b48Spatrick     int64_t Res;
89309467b48Spatrick     if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
89409467b48Spatrick       return Error(Loc, "expected absolute expression");
89509467b48Spatrick     if (Res < 0)
89609467b48Spatrick       return Warning(Loc, "negative count has no effect");
89709467b48Spatrick     Bytes = Bytes.take_front(Res);
89809467b48Spatrick   }
899097a140dSpatrick   getStreamer().emitBytes(Bytes);
90009467b48Spatrick   return false;
90109467b48Spatrick }
90209467b48Spatrick 
jumpToLoc(SMLoc Loc,unsigned InBuffer)90309467b48Spatrick void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
90409467b48Spatrick   CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
90509467b48Spatrick   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
90609467b48Spatrick                   Loc.getPointer());
90709467b48Spatrick }
90809467b48Spatrick 
Lex()90909467b48Spatrick const AsmToken &AsmParser::Lex() {
91009467b48Spatrick   if (Lexer.getTok().is(AsmToken::Error))
91109467b48Spatrick     Error(Lexer.getErrLoc(), Lexer.getErr());
91209467b48Spatrick 
91309467b48Spatrick   // if it's a end of statement with a comment in it
91409467b48Spatrick   if (getTok().is(AsmToken::EndOfStatement)) {
91509467b48Spatrick     // if this is a line comment output it.
91609467b48Spatrick     if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
91709467b48Spatrick         getTok().getString().front() != '\r' && MAI.preserveAsmComments())
91809467b48Spatrick       Out.addExplicitComment(Twine(getTok().getString()));
91909467b48Spatrick   }
92009467b48Spatrick 
92109467b48Spatrick   const AsmToken *tok = &Lexer.Lex();
92209467b48Spatrick 
92309467b48Spatrick   // Parse comments here to be deferred until end of next statement.
92409467b48Spatrick   while (tok->is(AsmToken::Comment)) {
92509467b48Spatrick     if (MAI.preserveAsmComments())
92609467b48Spatrick       Out.addExplicitComment(Twine(tok->getString()));
92709467b48Spatrick     tok = &Lexer.Lex();
92809467b48Spatrick   }
92909467b48Spatrick 
93009467b48Spatrick   if (tok->is(AsmToken::Eof)) {
93109467b48Spatrick     // If this is the end of an included file, pop the parent file off the
93209467b48Spatrick     // include stack.
93309467b48Spatrick     SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
93409467b48Spatrick     if (ParentIncludeLoc != SMLoc()) {
93509467b48Spatrick       jumpToLoc(ParentIncludeLoc);
93609467b48Spatrick       return Lex();
93709467b48Spatrick     }
93809467b48Spatrick   }
93909467b48Spatrick 
94009467b48Spatrick   return *tok;
94109467b48Spatrick }
94209467b48Spatrick 
enabledGenDwarfForAssembly()94309467b48Spatrick bool AsmParser::enabledGenDwarfForAssembly() {
94409467b48Spatrick   // Check whether the user specified -g.
94509467b48Spatrick   if (!getContext().getGenDwarfForAssembly())
94609467b48Spatrick     return false;
94709467b48Spatrick   // If we haven't encountered any .file directives (which would imply that
94809467b48Spatrick   // the assembler source was produced with debug info already) then emit one
94909467b48Spatrick   // describing the assembler source file itself.
95009467b48Spatrick   if (getContext().getGenDwarfFileNumber() == 0) {
95109467b48Spatrick     // Use the first #line directive for this, if any. It's preprocessed, so
95209467b48Spatrick     // there is no checksum, and of course no source directive.
95309467b48Spatrick     if (!FirstCppHashFilename.empty())
954*a96b3639Srobert       getContext().setMCLineTableRootFile(
955*a96b3639Srobert           /*CUID=*/0, getContext().getCompilationDir(), FirstCppHashFilename,
956*a96b3639Srobert           /*Cksum=*/std::nullopt, /*Source=*/std::nullopt);
95709467b48Spatrick     const MCDwarfFile &RootFile =
95809467b48Spatrick         getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
959097a140dSpatrick     getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
96009467b48Spatrick         /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
96109467b48Spatrick         RootFile.Checksum, RootFile.Source));
96209467b48Spatrick   }
96309467b48Spatrick   return true;
96409467b48Spatrick }
96509467b48Spatrick 
Run(bool NoInitialTextSection,bool NoFinalize)96609467b48Spatrick bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
967a0747c9fSpatrick   LTODiscardSymbols.clear();
968a0747c9fSpatrick 
96909467b48Spatrick   // Create the initial section, if requested.
97009467b48Spatrick   if (!NoInitialTextSection)
971*a96b3639Srobert     Out.initSections(false, getTargetParser().getSTI());
97209467b48Spatrick 
97309467b48Spatrick   // Prime the lexer.
97409467b48Spatrick   Lex();
97509467b48Spatrick 
97609467b48Spatrick   HadError = false;
97709467b48Spatrick   AsmCond StartingCondState = TheCondState;
97809467b48Spatrick   SmallVector<AsmRewrite, 4> AsmStrRewrites;
97909467b48Spatrick 
98009467b48Spatrick   // If we are generating dwarf for assembly source files save the initial text
98109467b48Spatrick   // section.  (Don't use enabledGenDwarfForAssembly() here, as we aren't
98209467b48Spatrick   // emitting any actual debug info yet and haven't had a chance to parse any
98309467b48Spatrick   // embedded .file directives.)
98409467b48Spatrick   if (getContext().getGenDwarfForAssembly()) {
98509467b48Spatrick     MCSection *Sec = getStreamer().getCurrentSectionOnly();
98609467b48Spatrick     if (!Sec->getBeginSymbol()) {
98709467b48Spatrick       MCSymbol *SectionStartSym = getContext().createTempSymbol();
988097a140dSpatrick       getStreamer().emitLabel(SectionStartSym);
98909467b48Spatrick       Sec->setBeginSymbol(SectionStartSym);
99009467b48Spatrick     }
99109467b48Spatrick     bool InsertResult = getContext().addGenDwarfSection(Sec);
99209467b48Spatrick     assert(InsertResult && ".text section should not have debug info yet");
99309467b48Spatrick     (void)InsertResult;
99409467b48Spatrick   }
99509467b48Spatrick 
996adae0cfdSpatrick   StringRef Filename = getContext().getMainFileName();
997adae0cfdSpatrick   if (!Filename.empty() && (Filename.compare(StringRef("-")) != 0))
998adae0cfdSpatrick     Out.emitFileDirective(Filename);
999adae0cfdSpatrick 
1000a0747c9fSpatrick   getTargetParser().onBeginOfFile();
1001a0747c9fSpatrick 
100209467b48Spatrick   // While we have input, parse each statement.
100309467b48Spatrick   while (Lexer.isNot(AsmToken::Eof)) {
100409467b48Spatrick     ParseStatementInfo Info(&AsmStrRewrites);
100509467b48Spatrick     bool Parsed = parseStatement(Info, nullptr);
100609467b48Spatrick 
100709467b48Spatrick     // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
100809467b48Spatrick     // for printing ErrMsg via Lex() only if no (presumably better) parser error
100909467b48Spatrick     // exists.
101009467b48Spatrick     if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
101109467b48Spatrick       Lex();
101209467b48Spatrick     }
101309467b48Spatrick 
101409467b48Spatrick     // parseStatement returned true so may need to emit an error.
101509467b48Spatrick     printPendingErrors();
101609467b48Spatrick 
101709467b48Spatrick     // Skipping to the next line if needed.
101809467b48Spatrick     if (Parsed && !getLexer().isAtStartOfStatement())
101909467b48Spatrick       eatToEndOfStatement();
102009467b48Spatrick   }
102109467b48Spatrick 
102209467b48Spatrick   getTargetParser().onEndOfFile();
102309467b48Spatrick   printPendingErrors();
102409467b48Spatrick 
102509467b48Spatrick   // All errors should have been emitted.
102609467b48Spatrick   assert(!hasPendingError() && "unexpected error from parseStatement");
102709467b48Spatrick 
102809467b48Spatrick   getTargetParser().flushPendingInstructions(getStreamer());
102909467b48Spatrick 
103009467b48Spatrick   if (TheCondState.TheCond != StartingCondState.TheCond ||
103109467b48Spatrick       TheCondState.Ignore != StartingCondState.Ignore)
103209467b48Spatrick     printError(getTok().getLoc(), "unmatched .ifs or .elses");
103309467b48Spatrick   // Check to see there are no empty DwarfFile slots.
103409467b48Spatrick   const auto &LineTables = getContext().getMCDwarfLineTables();
103509467b48Spatrick   if (!LineTables.empty()) {
103609467b48Spatrick     unsigned Index = 0;
103709467b48Spatrick     for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {
103809467b48Spatrick       if (File.Name.empty() && Index != 0)
103909467b48Spatrick         printError(getTok().getLoc(), "unassigned file number: " +
104009467b48Spatrick                                           Twine(Index) +
104109467b48Spatrick                                           " for .file directives");
104209467b48Spatrick       ++Index;
104309467b48Spatrick     }
104409467b48Spatrick   }
104509467b48Spatrick 
104609467b48Spatrick   // Check to see that all assembler local symbols were actually defined.
104709467b48Spatrick   // Targets that don't do subsections via symbols may not want this, though,
104809467b48Spatrick   // so conservatively exclude them. Only do this if we're finalizing, though,
104909467b48Spatrick   // as otherwise we won't necessarilly have seen everything yet.
105009467b48Spatrick   if (!NoFinalize) {
105109467b48Spatrick     if (MAI.hasSubsectionsViaSymbols()) {
105209467b48Spatrick       for (const auto &TableEntry : getContext().getSymbols()) {
105309467b48Spatrick         MCSymbol *Sym = TableEntry.getValue();
105409467b48Spatrick         // Variable symbols may not be marked as defined, so check those
105509467b48Spatrick         // explicitly. If we know it's a variable, we have a definition for
105609467b48Spatrick         // the purposes of this check.
105709467b48Spatrick         if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
105809467b48Spatrick           // FIXME: We would really like to refer back to where the symbol was
105909467b48Spatrick           // first referenced for a source location. We need to add something
106009467b48Spatrick           // to track that. Currently, we just point to the end of the file.
106109467b48Spatrick           printError(getTok().getLoc(), "assembler local symbol '" +
106209467b48Spatrick                                             Sym->getName() + "' not defined");
106309467b48Spatrick       }
106409467b48Spatrick     }
106509467b48Spatrick 
106609467b48Spatrick     // Temporary symbols like the ones for directional jumps don't go in the
106709467b48Spatrick     // symbol table. They also need to be diagnosed in all (final) cases.
106809467b48Spatrick     for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
106909467b48Spatrick       if (std::get<2>(LocSym)->isUndefined()) {
107009467b48Spatrick         // Reset the state of any "# line file" directives we've seen to the
107109467b48Spatrick         // context as it was at the diagnostic site.
107209467b48Spatrick         CppHashInfo = std::get<1>(LocSym);
107309467b48Spatrick         printError(std::get<0>(LocSym), "directional label undefined");
107409467b48Spatrick       }
107509467b48Spatrick     }
107609467b48Spatrick   }
107709467b48Spatrick   // Finalize the output stream if there are no errors and if the client wants
107809467b48Spatrick   // us to.
1079*a96b3639Srobert   if (!HadError && !NoFinalize) {
1080*a96b3639Srobert     if (auto *TS = Out.getTargetStreamer())
1081*a96b3639Srobert       TS->emitConstantPools();
1082*a96b3639Srobert 
1083*a96b3639Srobert     Out.finish(Lexer.getLoc());
1084*a96b3639Srobert   }
108509467b48Spatrick 
108609467b48Spatrick   return HadError || getContext().hadError();
108709467b48Spatrick }
108809467b48Spatrick 
checkForValidSection()108909467b48Spatrick bool AsmParser::checkForValidSection() {
1090097a140dSpatrick   if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
1091*a96b3639Srobert     Out.initSections(false, getTargetParser().getSTI());
109209467b48Spatrick     return Error(getTok().getLoc(),
109309467b48Spatrick                  "expected section directive before assembly directive");
109409467b48Spatrick   }
109509467b48Spatrick   return false;
109609467b48Spatrick }
109709467b48Spatrick 
109809467b48Spatrick /// Throw away the rest of the line for testing purposes.
eatToEndOfStatement()109909467b48Spatrick void AsmParser::eatToEndOfStatement() {
110009467b48Spatrick   while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
110109467b48Spatrick     Lexer.Lex();
110209467b48Spatrick 
110309467b48Spatrick   // Eat EOL.
110409467b48Spatrick   if (Lexer.is(AsmToken::EndOfStatement))
110509467b48Spatrick     Lexer.Lex();
110609467b48Spatrick }
110709467b48Spatrick 
parseStringToEndOfStatement()110809467b48Spatrick StringRef AsmParser::parseStringToEndOfStatement() {
110909467b48Spatrick   const char *Start = getTok().getLoc().getPointer();
111009467b48Spatrick 
111109467b48Spatrick   while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
111209467b48Spatrick     Lexer.Lex();
111309467b48Spatrick 
111409467b48Spatrick   const char *End = getTok().getLoc().getPointer();
111509467b48Spatrick   return StringRef(Start, End - Start);
111609467b48Spatrick }
111709467b48Spatrick 
parseStringToComma()111809467b48Spatrick StringRef AsmParser::parseStringToComma() {
111909467b48Spatrick   const char *Start = getTok().getLoc().getPointer();
112009467b48Spatrick 
112109467b48Spatrick   while (Lexer.isNot(AsmToken::EndOfStatement) &&
112209467b48Spatrick          Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof))
112309467b48Spatrick     Lexer.Lex();
112409467b48Spatrick 
112509467b48Spatrick   const char *End = getTok().getLoc().getPointer();
112609467b48Spatrick   return StringRef(Start, End - Start);
112709467b48Spatrick }
112809467b48Spatrick 
112909467b48Spatrick /// Parse a paren expression and return it.
113009467b48Spatrick /// NOTE: This assumes the leading '(' has already been consumed.
113109467b48Spatrick ///
113209467b48Spatrick /// parenexpr ::= expr)
113309467b48Spatrick ///
parseParenExpr(const MCExpr * & Res,SMLoc & EndLoc)113409467b48Spatrick bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
113509467b48Spatrick   if (parseExpression(Res))
113609467b48Spatrick     return true;
113709467b48Spatrick   EndLoc = Lexer.getTok().getEndLoc();
1138*a96b3639Srobert   return parseRParen();
113909467b48Spatrick }
114009467b48Spatrick 
114109467b48Spatrick /// Parse a bracket expression and return it.
114209467b48Spatrick /// NOTE: This assumes the leading '[' has already been consumed.
114309467b48Spatrick ///
114409467b48Spatrick /// bracketexpr ::= expr]
114509467b48Spatrick ///
parseBracketExpr(const MCExpr * & Res,SMLoc & EndLoc)114609467b48Spatrick bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
114709467b48Spatrick   if (parseExpression(Res))
114809467b48Spatrick     return true;
114909467b48Spatrick   EndLoc = getTok().getEndLoc();
115009467b48Spatrick   if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
115109467b48Spatrick     return true;
115209467b48Spatrick   return false;
115309467b48Spatrick }
115409467b48Spatrick 
115509467b48Spatrick /// Parse a primary expression and return it.
115609467b48Spatrick ///  primaryexpr ::= (parenexpr
115709467b48Spatrick ///  primaryexpr ::= symbol
115809467b48Spatrick ///  primaryexpr ::= number
115909467b48Spatrick ///  primaryexpr ::= '.'
116009467b48Spatrick ///  primaryexpr ::= ~,+,- primaryexpr
parsePrimaryExpr(const MCExpr * & Res,SMLoc & EndLoc,AsmTypeInfo * TypeInfo)1161a0747c9fSpatrick bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
1162a0747c9fSpatrick                                  AsmTypeInfo *TypeInfo) {
116309467b48Spatrick   SMLoc FirstTokenLoc = getLexer().getLoc();
116409467b48Spatrick   AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
116509467b48Spatrick   switch (FirstTokenKind) {
116609467b48Spatrick   default:
116709467b48Spatrick     return TokError("unknown token in expression");
116809467b48Spatrick   // If we have an error assume that we've already handled it.
116909467b48Spatrick   case AsmToken::Error:
117009467b48Spatrick     return true;
117109467b48Spatrick   case AsmToken::Exclaim:
117209467b48Spatrick     Lex(); // Eat the operator.
1173a0747c9fSpatrick     if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
117409467b48Spatrick       return true;
117509467b48Spatrick     Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
117609467b48Spatrick     return false;
117709467b48Spatrick   case AsmToken::Dollar:
1178a0747c9fSpatrick   case AsmToken::Star:
117909467b48Spatrick   case AsmToken::At:
118009467b48Spatrick   case AsmToken::String:
118109467b48Spatrick   case AsmToken::Identifier: {
118209467b48Spatrick     StringRef Identifier;
118309467b48Spatrick     if (parseIdentifier(Identifier)) {
1184a0747c9fSpatrick       // We may have failed but '$'|'*' may be a valid token in context of
1185a0747c9fSpatrick       // the current PC.
1186a0747c9fSpatrick       if (getTok().is(AsmToken::Dollar) || getTok().is(AsmToken::Star)) {
1187a0747c9fSpatrick         bool ShouldGenerateTempSymbol = false;
1188a0747c9fSpatrick         if ((getTok().is(AsmToken::Dollar) && MAI.getDollarIsPC()) ||
1189a0747c9fSpatrick             (getTok().is(AsmToken::Star) && MAI.getStarIsPC()))
1190a0747c9fSpatrick           ShouldGenerateTempSymbol = true;
1191a0747c9fSpatrick 
1192a0747c9fSpatrick         if (!ShouldGenerateTempSymbol)
1193a0747c9fSpatrick           return Error(FirstTokenLoc, "invalid token in expression");
1194a0747c9fSpatrick 
1195a0747c9fSpatrick         // Eat the '$'|'*' token.
119609467b48Spatrick         Lex();
1197a0747c9fSpatrick         // This is either a '$'|'*' reference, which references the current PC.
1198a0747c9fSpatrick         // Emit a temporary label to the streamer and refer to it.
119909467b48Spatrick         MCSymbol *Sym = Ctx.createTempSymbol();
1200097a140dSpatrick         Out.emitLabel(Sym);
120109467b48Spatrick         Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
120209467b48Spatrick                                       getContext());
120309467b48Spatrick         EndLoc = FirstTokenLoc;
120409467b48Spatrick         return false;
120509467b48Spatrick       }
120609467b48Spatrick     }
120709467b48Spatrick     // Parse symbol variant
120809467b48Spatrick     std::pair<StringRef, StringRef> Split;
120909467b48Spatrick     if (!MAI.useParensForSymbolVariant()) {
121009467b48Spatrick       if (FirstTokenKind == AsmToken::String) {
121109467b48Spatrick         if (Lexer.is(AsmToken::At)) {
121209467b48Spatrick           Lex(); // eat @
121309467b48Spatrick           SMLoc AtLoc = getLexer().getLoc();
121409467b48Spatrick           StringRef VName;
121509467b48Spatrick           if (parseIdentifier(VName))
121609467b48Spatrick             return Error(AtLoc, "expected symbol variant after '@'");
121709467b48Spatrick 
121809467b48Spatrick           Split = std::make_pair(Identifier, VName);
121909467b48Spatrick         }
122009467b48Spatrick       } else {
122109467b48Spatrick         Split = Identifier.split('@');
122209467b48Spatrick       }
122309467b48Spatrick     } else if (Lexer.is(AsmToken::LParen)) {
122409467b48Spatrick       Lex(); // eat '('.
122509467b48Spatrick       StringRef VName;
122609467b48Spatrick       parseIdentifier(VName);
1227*a96b3639Srobert       if (parseRParen())
122809467b48Spatrick         return true;
122909467b48Spatrick       Split = std::make_pair(Identifier, VName);
123009467b48Spatrick     }
123109467b48Spatrick 
123209467b48Spatrick     EndLoc = SMLoc::getFromPointer(Identifier.end());
123309467b48Spatrick 
123409467b48Spatrick     // This is a symbol reference.
123509467b48Spatrick     StringRef SymbolName = Identifier;
123609467b48Spatrick     if (SymbolName.empty())
123709467b48Spatrick       return Error(getLexer().getLoc(), "expected a symbol reference");
123809467b48Spatrick 
123909467b48Spatrick     MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
124009467b48Spatrick 
124109467b48Spatrick     // Lookup the symbol variant if used.
124209467b48Spatrick     if (!Split.second.empty()) {
124309467b48Spatrick       Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
124409467b48Spatrick       if (Variant != MCSymbolRefExpr::VK_Invalid) {
124509467b48Spatrick         SymbolName = Split.first;
124609467b48Spatrick       } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
124709467b48Spatrick         Variant = MCSymbolRefExpr::VK_None;
124809467b48Spatrick       } else {
124909467b48Spatrick         return Error(SMLoc::getFromPointer(Split.second.begin()),
125009467b48Spatrick                      "invalid variant '" + Split.second + "'");
125109467b48Spatrick       }
125209467b48Spatrick     }
125309467b48Spatrick 
125409467b48Spatrick     MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
125509467b48Spatrick     if (!Sym)
1256a0747c9fSpatrick       Sym = getContext().getOrCreateSymbol(
1257a0747c9fSpatrick           MAI.shouldEmitLabelsInUpperCase() ? SymbolName.upper() : SymbolName);
125809467b48Spatrick 
125909467b48Spatrick     // If this is an absolute variable reference, substitute it now to preserve
126009467b48Spatrick     // semantics in the face of reassignment.
126109467b48Spatrick     if (Sym->isVariable()) {
126209467b48Spatrick       auto V = Sym->getVariableValue(/*SetUsed*/ false);
126309467b48Spatrick       bool DoInline = isa<MCConstantExpr>(V) && !Variant;
126409467b48Spatrick       if (auto TV = dyn_cast<MCTargetExpr>(V))
126509467b48Spatrick         DoInline = TV->inlineAssignedExpr();
126609467b48Spatrick       if (DoInline) {
126709467b48Spatrick         if (Variant)
126809467b48Spatrick           return Error(EndLoc, "unexpected modifier on variable reference");
126909467b48Spatrick         Res = Sym->getVariableValue(/*SetUsed*/ false);
127009467b48Spatrick         return false;
127109467b48Spatrick       }
127209467b48Spatrick     }
127309467b48Spatrick 
127409467b48Spatrick     // Otherwise create a symbol ref.
127509467b48Spatrick     Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
127609467b48Spatrick     return false;
127709467b48Spatrick   }
127809467b48Spatrick   case AsmToken::BigNum:
127909467b48Spatrick     return TokError("literal value out of range for directive");
128009467b48Spatrick   case AsmToken::Integer: {
128109467b48Spatrick     SMLoc Loc = getTok().getLoc();
128209467b48Spatrick     int64_t IntVal = getTok().getIntVal();
128309467b48Spatrick     Res = MCConstantExpr::create(IntVal, getContext());
128409467b48Spatrick     EndLoc = Lexer.getTok().getEndLoc();
128509467b48Spatrick     Lex(); // Eat token.
128609467b48Spatrick     // Look for 'b' or 'f' following an Integer as a directional label
128709467b48Spatrick     if (Lexer.getKind() == AsmToken::Identifier) {
128809467b48Spatrick       StringRef IDVal = getTok().getString();
128909467b48Spatrick       // Lookup the symbol variant if used.
129009467b48Spatrick       std::pair<StringRef, StringRef> Split = IDVal.split('@');
129109467b48Spatrick       MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
129209467b48Spatrick       if (Split.first.size() != IDVal.size()) {
129309467b48Spatrick         Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
129409467b48Spatrick         if (Variant == MCSymbolRefExpr::VK_Invalid)
129509467b48Spatrick           return TokError("invalid variant '" + Split.second + "'");
129609467b48Spatrick         IDVal = Split.first;
129709467b48Spatrick       }
129809467b48Spatrick       if (IDVal == "f" || IDVal == "b") {
129909467b48Spatrick         MCSymbol *Sym =
130009467b48Spatrick             Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
130109467b48Spatrick         Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
130209467b48Spatrick         if (IDVal == "b" && Sym->isUndefined())
130309467b48Spatrick           return Error(Loc, "directional label undefined");
130409467b48Spatrick         DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
130509467b48Spatrick         EndLoc = Lexer.getTok().getEndLoc();
130609467b48Spatrick         Lex(); // Eat identifier.
130709467b48Spatrick       }
130809467b48Spatrick     }
130909467b48Spatrick     return false;
131009467b48Spatrick   }
131109467b48Spatrick   case AsmToken::Real: {
131209467b48Spatrick     APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
131309467b48Spatrick     uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
131409467b48Spatrick     Res = MCConstantExpr::create(IntVal, getContext());
131509467b48Spatrick     EndLoc = Lexer.getTok().getEndLoc();
131609467b48Spatrick     Lex(); // Eat token.
131709467b48Spatrick     return false;
131809467b48Spatrick   }
131909467b48Spatrick   case AsmToken::Dot: {
1320a0747c9fSpatrick     if (!MAI.getDotIsPC())
1321a0747c9fSpatrick       return TokError("cannot use . as current PC");
1322a0747c9fSpatrick 
132309467b48Spatrick     // This is a '.' reference, which references the current PC.  Emit a
132409467b48Spatrick     // temporary label to the streamer and refer to it.
132509467b48Spatrick     MCSymbol *Sym = Ctx.createTempSymbol();
1326097a140dSpatrick     Out.emitLabel(Sym);
132709467b48Spatrick     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
132809467b48Spatrick     EndLoc = Lexer.getTok().getEndLoc();
132909467b48Spatrick     Lex(); // Eat identifier.
133009467b48Spatrick     return false;
133109467b48Spatrick   }
133209467b48Spatrick   case AsmToken::LParen:
133309467b48Spatrick     Lex(); // Eat the '('.
133409467b48Spatrick     return parseParenExpr(Res, EndLoc);
133509467b48Spatrick   case AsmToken::LBrac:
133609467b48Spatrick     if (!PlatformParser->HasBracketExpressions())
133709467b48Spatrick       return TokError("brackets expression not supported on this target");
133809467b48Spatrick     Lex(); // Eat the '['.
133909467b48Spatrick     return parseBracketExpr(Res, EndLoc);
134009467b48Spatrick   case AsmToken::Minus:
134109467b48Spatrick     Lex(); // Eat the operator.
1342a0747c9fSpatrick     if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
134309467b48Spatrick       return true;
134409467b48Spatrick     Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
134509467b48Spatrick     return false;
134609467b48Spatrick   case AsmToken::Plus:
134709467b48Spatrick     Lex(); // Eat the operator.
1348a0747c9fSpatrick     if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
134909467b48Spatrick       return true;
135009467b48Spatrick     Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
135109467b48Spatrick     return false;
135209467b48Spatrick   case AsmToken::Tilde:
135309467b48Spatrick     Lex(); // Eat the operator.
1354a0747c9fSpatrick     if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
135509467b48Spatrick       return true;
135609467b48Spatrick     Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
135709467b48Spatrick     return false;
135809467b48Spatrick   // MIPS unary expression operators. The lexer won't generate these tokens if
135909467b48Spatrick   // MCAsmInfo::HasMipsExpressions is false for the target.
136009467b48Spatrick   case AsmToken::PercentCall16:
136109467b48Spatrick   case AsmToken::PercentCall_Hi:
136209467b48Spatrick   case AsmToken::PercentCall_Lo:
136309467b48Spatrick   case AsmToken::PercentDtprel_Hi:
136409467b48Spatrick   case AsmToken::PercentDtprel_Lo:
136509467b48Spatrick   case AsmToken::PercentGot:
136609467b48Spatrick   case AsmToken::PercentGot_Disp:
136709467b48Spatrick   case AsmToken::PercentGot_Hi:
136809467b48Spatrick   case AsmToken::PercentGot_Lo:
136909467b48Spatrick   case AsmToken::PercentGot_Ofst:
137009467b48Spatrick   case AsmToken::PercentGot_Page:
137109467b48Spatrick   case AsmToken::PercentGottprel:
137209467b48Spatrick   case AsmToken::PercentGp_Rel:
137309467b48Spatrick   case AsmToken::PercentHi:
137409467b48Spatrick   case AsmToken::PercentHigher:
137509467b48Spatrick   case AsmToken::PercentHighest:
137609467b48Spatrick   case AsmToken::PercentLo:
137709467b48Spatrick   case AsmToken::PercentNeg:
137809467b48Spatrick   case AsmToken::PercentPcrel_Hi:
137909467b48Spatrick   case AsmToken::PercentPcrel_Lo:
138009467b48Spatrick   case AsmToken::PercentTlsgd:
138109467b48Spatrick   case AsmToken::PercentTlsldm:
138209467b48Spatrick   case AsmToken::PercentTprel_Hi:
138309467b48Spatrick   case AsmToken::PercentTprel_Lo:
138409467b48Spatrick     Lex(); // Eat the operator.
138509467b48Spatrick     if (Lexer.isNot(AsmToken::LParen))
138609467b48Spatrick       return TokError("expected '(' after operator");
138709467b48Spatrick     Lex(); // Eat the operator.
138809467b48Spatrick     if (parseExpression(Res, EndLoc))
138909467b48Spatrick       return true;
1390*a96b3639Srobert     if (parseRParen())
1391*a96b3639Srobert       return true;
139209467b48Spatrick     Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
139309467b48Spatrick     return !Res;
139409467b48Spatrick   }
139509467b48Spatrick }
139609467b48Spatrick 
parseExpression(const MCExpr * & Res)139709467b48Spatrick bool AsmParser::parseExpression(const MCExpr *&Res) {
139809467b48Spatrick   SMLoc EndLoc;
139909467b48Spatrick   return parseExpression(Res, EndLoc);
140009467b48Spatrick }
140109467b48Spatrick 
140209467b48Spatrick const MCExpr *
applyModifierToExpr(const MCExpr * E,MCSymbolRefExpr::VariantKind Variant)140309467b48Spatrick AsmParser::applyModifierToExpr(const MCExpr *E,
140409467b48Spatrick                                MCSymbolRefExpr::VariantKind Variant) {
140509467b48Spatrick   // Ask the target implementation about this expression first.
140609467b48Spatrick   const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx);
140709467b48Spatrick   if (NewE)
140809467b48Spatrick     return NewE;
140909467b48Spatrick   // Recurse over the given expression, rebuilding it to apply the given variant
141009467b48Spatrick   // if there is exactly one symbol.
141109467b48Spatrick   switch (E->getKind()) {
141209467b48Spatrick   case MCExpr::Target:
141309467b48Spatrick   case MCExpr::Constant:
141409467b48Spatrick     return nullptr;
141509467b48Spatrick 
141609467b48Spatrick   case MCExpr::SymbolRef: {
141709467b48Spatrick     const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
141809467b48Spatrick 
141909467b48Spatrick     if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
142009467b48Spatrick       TokError("invalid variant on expression '" + getTok().getIdentifier() +
142109467b48Spatrick                "' (already modified)");
142209467b48Spatrick       return E;
142309467b48Spatrick     }
142409467b48Spatrick 
142509467b48Spatrick     return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext());
142609467b48Spatrick   }
142709467b48Spatrick 
142809467b48Spatrick   case MCExpr::Unary: {
142909467b48Spatrick     const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
143009467b48Spatrick     const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant);
143109467b48Spatrick     if (!Sub)
143209467b48Spatrick       return nullptr;
143309467b48Spatrick     return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext());
143409467b48Spatrick   }
143509467b48Spatrick 
143609467b48Spatrick   case MCExpr::Binary: {
143709467b48Spatrick     const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
143809467b48Spatrick     const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant);
143909467b48Spatrick     const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant);
144009467b48Spatrick 
144109467b48Spatrick     if (!LHS && !RHS)
144209467b48Spatrick       return nullptr;
144309467b48Spatrick 
144409467b48Spatrick     if (!LHS)
144509467b48Spatrick       LHS = BE->getLHS();
144609467b48Spatrick     if (!RHS)
144709467b48Spatrick       RHS = BE->getRHS();
144809467b48Spatrick 
144909467b48Spatrick     return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext());
145009467b48Spatrick   }
145109467b48Spatrick   }
145209467b48Spatrick 
145309467b48Spatrick   llvm_unreachable("Invalid expression kind!");
145409467b48Spatrick }
145509467b48Spatrick 
145609467b48Spatrick /// This function checks if the next token is <string> type or arithmetic.
145709467b48Spatrick /// string that begin with character '<' must end with character '>'.
145809467b48Spatrick /// otherwise it is arithmetics.
145909467b48Spatrick /// If the function returns a 'true' value,
146009467b48Spatrick /// the End argument will be filled with the last location pointed to the '>'
146109467b48Spatrick /// character.
146209467b48Spatrick 
146309467b48Spatrick /// There is a gap between the AltMacro's documentation and the single quote
146409467b48Spatrick /// implementation. GCC does not fully support this feature and so we will not
146509467b48Spatrick /// support it.
146609467b48Spatrick /// TODO: Adding single quote as a string.
isAngleBracketString(SMLoc & StrLoc,SMLoc & EndLoc)1467097a140dSpatrick static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
146809467b48Spatrick   assert((StrLoc.getPointer() != nullptr) &&
146909467b48Spatrick          "Argument to the function cannot be a NULL value");
147009467b48Spatrick   const char *CharPtr = StrLoc.getPointer();
147109467b48Spatrick   while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
147209467b48Spatrick          (*CharPtr != '\0')) {
147309467b48Spatrick     if (*CharPtr == '!')
147409467b48Spatrick       CharPtr++;
147509467b48Spatrick     CharPtr++;
147609467b48Spatrick   }
147709467b48Spatrick   if (*CharPtr == '>') {
147809467b48Spatrick     EndLoc = StrLoc.getFromPointer(CharPtr + 1);
147909467b48Spatrick     return true;
148009467b48Spatrick   }
148109467b48Spatrick   return false;
148209467b48Spatrick }
148309467b48Spatrick 
148409467b48Spatrick /// creating a string without the escape characters '!'.
angleBracketString(StringRef AltMacroStr)1485097a140dSpatrick static std::string angleBracketString(StringRef AltMacroStr) {
148609467b48Spatrick   std::string Res;
148709467b48Spatrick   for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
148809467b48Spatrick     if (AltMacroStr[Pos] == '!')
148909467b48Spatrick       Pos++;
149009467b48Spatrick     Res += AltMacroStr[Pos];
149109467b48Spatrick   }
149209467b48Spatrick   return Res;
149309467b48Spatrick }
149409467b48Spatrick 
149509467b48Spatrick /// Parse an expression and return it.
149609467b48Spatrick ///
149709467b48Spatrick ///  expr ::= expr &&,|| expr               -> lowest.
149809467b48Spatrick ///  expr ::= expr |,^,&,! expr
149909467b48Spatrick ///  expr ::= expr ==,!=,<>,<,<=,>,>= expr
150009467b48Spatrick ///  expr ::= expr <<,>> expr
150109467b48Spatrick ///  expr ::= expr +,- expr
150209467b48Spatrick ///  expr ::= expr *,/,% expr               -> highest.
150309467b48Spatrick ///  expr ::= primaryexpr
150409467b48Spatrick ///
parseExpression(const MCExpr * & Res,SMLoc & EndLoc)150509467b48Spatrick bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
150609467b48Spatrick   // Parse the expression.
150709467b48Spatrick   Res = nullptr;
150809467b48Spatrick   if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
150909467b48Spatrick       parseBinOpRHS(1, Res, EndLoc))
151009467b48Spatrick     return true;
151109467b48Spatrick 
151209467b48Spatrick   // As a special case, we support 'a op b @ modifier' by rewriting the
151309467b48Spatrick   // expression to include the modifier. This is inefficient, but in general we
151409467b48Spatrick   // expect users to use 'a@modifier op b'.
151509467b48Spatrick   if (Lexer.getKind() == AsmToken::At) {
151609467b48Spatrick     Lex();
151709467b48Spatrick 
151809467b48Spatrick     if (Lexer.isNot(AsmToken::Identifier))
151909467b48Spatrick       return TokError("unexpected symbol modifier following '@'");
152009467b48Spatrick 
152109467b48Spatrick     MCSymbolRefExpr::VariantKind Variant =
152209467b48Spatrick         MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
152309467b48Spatrick     if (Variant == MCSymbolRefExpr::VK_Invalid)
152409467b48Spatrick       return TokError("invalid variant '" + getTok().getIdentifier() + "'");
152509467b48Spatrick 
152609467b48Spatrick     const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant);
152709467b48Spatrick     if (!ModifiedRes) {
152809467b48Spatrick       return TokError("invalid modifier '" + getTok().getIdentifier() +
152909467b48Spatrick                       "' (no symbols present)");
153009467b48Spatrick     }
153109467b48Spatrick 
153209467b48Spatrick     Res = ModifiedRes;
153309467b48Spatrick     Lex();
153409467b48Spatrick   }
153509467b48Spatrick 
153609467b48Spatrick   // Try to constant fold it up front, if possible. Do not exploit
153709467b48Spatrick   // assembler here.
153809467b48Spatrick   int64_t Value;
153909467b48Spatrick   if (Res->evaluateAsAbsolute(Value))
154009467b48Spatrick     Res = MCConstantExpr::create(Value, getContext());
154109467b48Spatrick 
154209467b48Spatrick   return false;
154309467b48Spatrick }
154409467b48Spatrick 
parseParenExpression(const MCExpr * & Res,SMLoc & EndLoc)154509467b48Spatrick bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
154609467b48Spatrick   Res = nullptr;
154709467b48Spatrick   return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
154809467b48Spatrick }
154909467b48Spatrick 
parseParenExprOfDepth(unsigned ParenDepth,const MCExpr * & Res,SMLoc & EndLoc)155009467b48Spatrick bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
155109467b48Spatrick                                       SMLoc &EndLoc) {
155209467b48Spatrick   if (parseParenExpr(Res, EndLoc))
155309467b48Spatrick     return true;
155409467b48Spatrick 
155509467b48Spatrick   for (; ParenDepth > 0; --ParenDepth) {
155609467b48Spatrick     if (parseBinOpRHS(1, Res, EndLoc))
155709467b48Spatrick       return true;
155809467b48Spatrick 
155909467b48Spatrick     // We don't Lex() the last RParen.
156009467b48Spatrick     // This is the same behavior as parseParenExpression().
156109467b48Spatrick     if (ParenDepth - 1 > 0) {
156209467b48Spatrick       EndLoc = getTok().getEndLoc();
1563*a96b3639Srobert       if (parseRParen())
156409467b48Spatrick         return true;
156509467b48Spatrick     }
156609467b48Spatrick   }
156709467b48Spatrick   return false;
156809467b48Spatrick }
156909467b48Spatrick 
parseAbsoluteExpression(int64_t & Res)157009467b48Spatrick bool AsmParser::parseAbsoluteExpression(int64_t &Res) {
157109467b48Spatrick   const MCExpr *Expr;
157209467b48Spatrick 
157309467b48Spatrick   SMLoc StartLoc = Lexer.getLoc();
157409467b48Spatrick   if (parseExpression(Expr))
157509467b48Spatrick     return true;
157609467b48Spatrick 
157709467b48Spatrick   if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
157809467b48Spatrick     return Error(StartLoc, "expected absolute expression");
157909467b48Spatrick 
158009467b48Spatrick   return false;
158109467b48Spatrick }
158209467b48Spatrick 
getDarwinBinOpPrecedence(AsmToken::TokenKind K,MCBinaryExpr::Opcode & Kind,bool ShouldUseLogicalShr)158309467b48Spatrick static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K,
158409467b48Spatrick                                          MCBinaryExpr::Opcode &Kind,
158509467b48Spatrick                                          bool ShouldUseLogicalShr) {
158609467b48Spatrick   switch (K) {
158709467b48Spatrick   default:
158809467b48Spatrick     return 0; // not a binop.
158909467b48Spatrick 
159009467b48Spatrick   // Lowest Precedence: &&, ||
159109467b48Spatrick   case AsmToken::AmpAmp:
159209467b48Spatrick     Kind = MCBinaryExpr::LAnd;
159309467b48Spatrick     return 1;
159409467b48Spatrick   case AsmToken::PipePipe:
159509467b48Spatrick     Kind = MCBinaryExpr::LOr;
159609467b48Spatrick     return 1;
159709467b48Spatrick 
159809467b48Spatrick   // Low Precedence: |, &, ^
159909467b48Spatrick   case AsmToken::Pipe:
160009467b48Spatrick     Kind = MCBinaryExpr::Or;
160109467b48Spatrick     return 2;
160209467b48Spatrick   case AsmToken::Caret:
160309467b48Spatrick     Kind = MCBinaryExpr::Xor;
160409467b48Spatrick     return 2;
160509467b48Spatrick   case AsmToken::Amp:
160609467b48Spatrick     Kind = MCBinaryExpr::And;
160709467b48Spatrick     return 2;
160809467b48Spatrick 
160909467b48Spatrick   // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
161009467b48Spatrick   case AsmToken::EqualEqual:
161109467b48Spatrick     Kind = MCBinaryExpr::EQ;
161209467b48Spatrick     return 3;
161309467b48Spatrick   case AsmToken::ExclaimEqual:
161409467b48Spatrick   case AsmToken::LessGreater:
161509467b48Spatrick     Kind = MCBinaryExpr::NE;
161609467b48Spatrick     return 3;
161709467b48Spatrick   case AsmToken::Less:
161809467b48Spatrick     Kind = MCBinaryExpr::LT;
161909467b48Spatrick     return 3;
162009467b48Spatrick   case AsmToken::LessEqual:
162109467b48Spatrick     Kind = MCBinaryExpr::LTE;
162209467b48Spatrick     return 3;
162309467b48Spatrick   case AsmToken::Greater:
162409467b48Spatrick     Kind = MCBinaryExpr::GT;
162509467b48Spatrick     return 3;
162609467b48Spatrick   case AsmToken::GreaterEqual:
162709467b48Spatrick     Kind = MCBinaryExpr::GTE;
162809467b48Spatrick     return 3;
162909467b48Spatrick 
163009467b48Spatrick   // Intermediate Precedence: <<, >>
163109467b48Spatrick   case AsmToken::LessLess:
163209467b48Spatrick     Kind = MCBinaryExpr::Shl;
163309467b48Spatrick     return 4;
163409467b48Spatrick   case AsmToken::GreaterGreater:
163509467b48Spatrick     Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
163609467b48Spatrick     return 4;
163709467b48Spatrick 
163809467b48Spatrick   // High Intermediate Precedence: +, -
163909467b48Spatrick   case AsmToken::Plus:
164009467b48Spatrick     Kind = MCBinaryExpr::Add;
164109467b48Spatrick     return 5;
164209467b48Spatrick   case AsmToken::Minus:
164309467b48Spatrick     Kind = MCBinaryExpr::Sub;
164409467b48Spatrick     return 5;
164509467b48Spatrick 
164609467b48Spatrick   // Highest Precedence: *, /, %
164709467b48Spatrick   case AsmToken::Star:
164809467b48Spatrick     Kind = MCBinaryExpr::Mul;
164909467b48Spatrick     return 6;
165009467b48Spatrick   case AsmToken::Slash:
165109467b48Spatrick     Kind = MCBinaryExpr::Div;
165209467b48Spatrick     return 6;
165309467b48Spatrick   case AsmToken::Percent:
165409467b48Spatrick     Kind = MCBinaryExpr::Mod;
165509467b48Spatrick     return 6;
165609467b48Spatrick   }
165709467b48Spatrick }
165809467b48Spatrick 
getGNUBinOpPrecedence(const MCAsmInfo & MAI,AsmToken::TokenKind K,MCBinaryExpr::Opcode & Kind,bool ShouldUseLogicalShr)1659a0747c9fSpatrick static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI,
1660a0747c9fSpatrick                                       AsmToken::TokenKind K,
166109467b48Spatrick                                       MCBinaryExpr::Opcode &Kind,
166209467b48Spatrick                                       bool ShouldUseLogicalShr) {
166309467b48Spatrick   switch (K) {
166409467b48Spatrick   default:
166509467b48Spatrick     return 0; // not a binop.
166609467b48Spatrick 
166709467b48Spatrick   // Lowest Precedence: &&, ||
166809467b48Spatrick   case AsmToken::AmpAmp:
166909467b48Spatrick     Kind = MCBinaryExpr::LAnd;
167009467b48Spatrick     return 2;
167109467b48Spatrick   case AsmToken::PipePipe:
167209467b48Spatrick     Kind = MCBinaryExpr::LOr;
167309467b48Spatrick     return 1;
167409467b48Spatrick 
167509467b48Spatrick   // Low Precedence: ==, !=, <>, <, <=, >, >=
167609467b48Spatrick   case AsmToken::EqualEqual:
167709467b48Spatrick     Kind = MCBinaryExpr::EQ;
167809467b48Spatrick     return 3;
167909467b48Spatrick   case AsmToken::ExclaimEqual:
168009467b48Spatrick   case AsmToken::LessGreater:
168109467b48Spatrick     Kind = MCBinaryExpr::NE;
168209467b48Spatrick     return 3;
168309467b48Spatrick   case AsmToken::Less:
168409467b48Spatrick     Kind = MCBinaryExpr::LT;
168509467b48Spatrick     return 3;
168609467b48Spatrick   case AsmToken::LessEqual:
168709467b48Spatrick     Kind = MCBinaryExpr::LTE;
168809467b48Spatrick     return 3;
168909467b48Spatrick   case AsmToken::Greater:
169009467b48Spatrick     Kind = MCBinaryExpr::GT;
169109467b48Spatrick     return 3;
169209467b48Spatrick   case AsmToken::GreaterEqual:
169309467b48Spatrick     Kind = MCBinaryExpr::GTE;
169409467b48Spatrick     return 3;
169509467b48Spatrick 
169609467b48Spatrick   // Low Intermediate Precedence: +, -
169709467b48Spatrick   case AsmToken::Plus:
169809467b48Spatrick     Kind = MCBinaryExpr::Add;
169909467b48Spatrick     return 4;
170009467b48Spatrick   case AsmToken::Minus:
170109467b48Spatrick     Kind = MCBinaryExpr::Sub;
170209467b48Spatrick     return 4;
170309467b48Spatrick 
1704a0747c9fSpatrick   // High Intermediate Precedence: |, !, &, ^
170509467b48Spatrick   //
170609467b48Spatrick   case AsmToken::Pipe:
170709467b48Spatrick     Kind = MCBinaryExpr::Or;
170809467b48Spatrick     return 5;
1709a0747c9fSpatrick   case AsmToken::Exclaim:
1710a0747c9fSpatrick     // Hack to support ARM compatible aliases (implied 'sp' operand in 'srs*'
1711a0747c9fSpatrick     // instructions like 'srsda #31!') and not parse ! as an infix operator.
1712a0747c9fSpatrick     if (MAI.getCommentString() == "@")
1713a0747c9fSpatrick       return 0;
1714a0747c9fSpatrick     Kind = MCBinaryExpr::OrNot;
1715a0747c9fSpatrick     return 5;
171609467b48Spatrick   case AsmToken::Caret:
171709467b48Spatrick     Kind = MCBinaryExpr::Xor;
171809467b48Spatrick     return 5;
171909467b48Spatrick   case AsmToken::Amp:
172009467b48Spatrick     Kind = MCBinaryExpr::And;
172109467b48Spatrick     return 5;
172209467b48Spatrick 
172309467b48Spatrick   // Highest Precedence: *, /, %, <<, >>
172409467b48Spatrick   case AsmToken::Star:
172509467b48Spatrick     Kind = MCBinaryExpr::Mul;
172609467b48Spatrick     return 6;
172709467b48Spatrick   case AsmToken::Slash:
172809467b48Spatrick     Kind = MCBinaryExpr::Div;
172909467b48Spatrick     return 6;
173009467b48Spatrick   case AsmToken::Percent:
173109467b48Spatrick     Kind = MCBinaryExpr::Mod;
173209467b48Spatrick     return 6;
173309467b48Spatrick   case AsmToken::LessLess:
173409467b48Spatrick     Kind = MCBinaryExpr::Shl;
173509467b48Spatrick     return 6;
173609467b48Spatrick   case AsmToken::GreaterGreater:
173709467b48Spatrick     Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
173809467b48Spatrick     return 6;
173909467b48Spatrick   }
174009467b48Spatrick }
174109467b48Spatrick 
getBinOpPrecedence(AsmToken::TokenKind K,MCBinaryExpr::Opcode & Kind)174209467b48Spatrick unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
174309467b48Spatrick                                        MCBinaryExpr::Opcode &Kind) {
174409467b48Spatrick   bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
174509467b48Spatrick   return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)
1746a0747c9fSpatrick                   : getGNUBinOpPrecedence(MAI, K, Kind, ShouldUseLogicalShr);
174709467b48Spatrick }
174809467b48Spatrick 
174909467b48Spatrick /// Parse all binary operators with precedence >= 'Precedence'.
175009467b48Spatrick /// Res contains the LHS of the expression on input.
parseBinOpRHS(unsigned Precedence,const MCExpr * & Res,SMLoc & EndLoc)175109467b48Spatrick bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
175209467b48Spatrick                               SMLoc &EndLoc) {
175309467b48Spatrick   SMLoc StartLoc = Lexer.getLoc();
175409467b48Spatrick   while (true) {
175509467b48Spatrick     MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
175609467b48Spatrick     unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
175709467b48Spatrick 
175809467b48Spatrick     // If the next token is lower precedence than we are allowed to eat, return
175909467b48Spatrick     // successfully with what we ate already.
176009467b48Spatrick     if (TokPrec < Precedence)
176109467b48Spatrick       return false;
176209467b48Spatrick 
176309467b48Spatrick     Lex();
176409467b48Spatrick 
176509467b48Spatrick     // Eat the next primary expression.
176609467b48Spatrick     const MCExpr *RHS;
176709467b48Spatrick     if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
176809467b48Spatrick       return true;
176909467b48Spatrick 
177009467b48Spatrick     // If BinOp binds less tightly with RHS than the operator after RHS, let
177109467b48Spatrick     // the pending operator take RHS as its LHS.
177209467b48Spatrick     MCBinaryExpr::Opcode Dummy;
177309467b48Spatrick     unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
177409467b48Spatrick     if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
177509467b48Spatrick       return true;
177609467b48Spatrick 
177709467b48Spatrick     // Merge LHS and RHS according to operator.
177809467b48Spatrick     Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
177909467b48Spatrick   }
178009467b48Spatrick }
178109467b48Spatrick 
178209467b48Spatrick /// ParseStatement:
178309467b48Spatrick ///   ::= EndOfStatement
178409467b48Spatrick ///   ::= Label* Directive ...Operands... EndOfStatement
178509467b48Spatrick ///   ::= Label* Identifier OperandList* EndOfStatement
parseStatement(ParseStatementInfo & Info,MCAsmParserSemaCallback * SI)178609467b48Spatrick bool AsmParser::parseStatement(ParseStatementInfo &Info,
178709467b48Spatrick                                MCAsmParserSemaCallback *SI) {
178809467b48Spatrick   assert(!hasPendingError() && "parseStatement started with pending error");
178909467b48Spatrick   // Eat initial spaces and comments
179009467b48Spatrick   while (Lexer.is(AsmToken::Space))
179109467b48Spatrick     Lex();
179209467b48Spatrick   if (Lexer.is(AsmToken::EndOfStatement)) {
179309467b48Spatrick     // if this is a line comment we can drop it safely
179409467b48Spatrick     if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
179509467b48Spatrick         getTok().getString().front() == '\n')
1796*a96b3639Srobert       Out.addBlankLine();
179709467b48Spatrick     Lex();
179809467b48Spatrick     return false;
179909467b48Spatrick   }
180009467b48Spatrick   // Statements always start with an identifier.
180109467b48Spatrick   AsmToken ID = getTok();
180209467b48Spatrick   SMLoc IDLoc = ID.getLoc();
180309467b48Spatrick   StringRef IDVal;
180409467b48Spatrick   int64_t LocalLabelVal = -1;
1805a0747c9fSpatrick   StartTokLoc = ID.getLoc();
180609467b48Spatrick   if (Lexer.is(AsmToken::HashDirective))
1807097a140dSpatrick     return parseCppHashLineFilenameComment(IDLoc,
1808097a140dSpatrick                                            !isInsideMacroInstantiation());
1809097a140dSpatrick 
181009467b48Spatrick   // Allow an integer followed by a ':' as a directional local label.
181109467b48Spatrick   if (Lexer.is(AsmToken::Integer)) {
181209467b48Spatrick     LocalLabelVal = getTok().getIntVal();
181309467b48Spatrick     if (LocalLabelVal < 0) {
181409467b48Spatrick       if (!TheCondState.Ignore) {
181509467b48Spatrick         Lex(); // always eat a token
181609467b48Spatrick         return Error(IDLoc, "unexpected token at start of statement");
181709467b48Spatrick       }
181809467b48Spatrick       IDVal = "";
181909467b48Spatrick     } else {
182009467b48Spatrick       IDVal = getTok().getString();
182109467b48Spatrick       Lex(); // Consume the integer token to be used as an identifier token.
182209467b48Spatrick       if (Lexer.getKind() != AsmToken::Colon) {
182309467b48Spatrick         if (!TheCondState.Ignore) {
182409467b48Spatrick           Lex(); // always eat a token
182509467b48Spatrick           return Error(IDLoc, "unexpected token at start of statement");
182609467b48Spatrick         }
182709467b48Spatrick       }
182809467b48Spatrick     }
182909467b48Spatrick   } else if (Lexer.is(AsmToken::Dot)) {
183009467b48Spatrick     // Treat '.' as a valid identifier in this context.
183109467b48Spatrick     Lex();
183209467b48Spatrick     IDVal = ".";
183309467b48Spatrick   } else if (Lexer.is(AsmToken::LCurly)) {
183409467b48Spatrick     // Treat '{' as a valid identifier in this context.
183509467b48Spatrick     Lex();
183609467b48Spatrick     IDVal = "{";
183709467b48Spatrick 
183809467b48Spatrick   } else if (Lexer.is(AsmToken::RCurly)) {
183909467b48Spatrick     // Treat '}' as a valid identifier in this context.
184009467b48Spatrick     Lex();
184109467b48Spatrick     IDVal = "}";
184209467b48Spatrick   } else if (Lexer.is(AsmToken::Star) &&
184309467b48Spatrick              getTargetParser().starIsStartOfStatement()) {
184409467b48Spatrick     // Accept '*' as a valid start of statement.
184509467b48Spatrick     Lex();
184609467b48Spatrick     IDVal = "*";
184709467b48Spatrick   } else if (parseIdentifier(IDVal)) {
184809467b48Spatrick     if (!TheCondState.Ignore) {
184909467b48Spatrick       Lex(); // always eat a token
185009467b48Spatrick       return Error(IDLoc, "unexpected token at start of statement");
185109467b48Spatrick     }
185209467b48Spatrick     IDVal = "";
185309467b48Spatrick   }
185409467b48Spatrick 
185509467b48Spatrick   // Handle conditional assembly here before checking for skipping.  We
185609467b48Spatrick   // have to do this so that .endif isn't skipped in a ".if 0" block for
185709467b48Spatrick   // example.
185809467b48Spatrick   StringMap<DirectiveKind>::const_iterator DirKindIt =
1859097a140dSpatrick       DirectiveKindMap.find(IDVal.lower());
186009467b48Spatrick   DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
186109467b48Spatrick                               ? DK_NO_DIRECTIVE
186209467b48Spatrick                               : DirKindIt->getValue();
186309467b48Spatrick   switch (DirKind) {
186409467b48Spatrick   default:
186509467b48Spatrick     break;
186609467b48Spatrick   case DK_IF:
186709467b48Spatrick   case DK_IFEQ:
186809467b48Spatrick   case DK_IFGE:
186909467b48Spatrick   case DK_IFGT:
187009467b48Spatrick   case DK_IFLE:
187109467b48Spatrick   case DK_IFLT:
187209467b48Spatrick   case DK_IFNE:
187309467b48Spatrick     return parseDirectiveIf(IDLoc, DirKind);
187409467b48Spatrick   case DK_IFB:
187509467b48Spatrick     return parseDirectiveIfb(IDLoc, true);
187609467b48Spatrick   case DK_IFNB:
187709467b48Spatrick     return parseDirectiveIfb(IDLoc, false);
187809467b48Spatrick   case DK_IFC:
187909467b48Spatrick     return parseDirectiveIfc(IDLoc, true);
188009467b48Spatrick   case DK_IFEQS:
188109467b48Spatrick     return parseDirectiveIfeqs(IDLoc, true);
188209467b48Spatrick   case DK_IFNC:
188309467b48Spatrick     return parseDirectiveIfc(IDLoc, false);
188409467b48Spatrick   case DK_IFNES:
188509467b48Spatrick     return parseDirectiveIfeqs(IDLoc, false);
188609467b48Spatrick   case DK_IFDEF:
188709467b48Spatrick     return parseDirectiveIfdef(IDLoc, true);
188809467b48Spatrick   case DK_IFNDEF:
188909467b48Spatrick   case DK_IFNOTDEF:
189009467b48Spatrick     return parseDirectiveIfdef(IDLoc, false);
189109467b48Spatrick   case DK_ELSEIF:
189209467b48Spatrick     return parseDirectiveElseIf(IDLoc);
189309467b48Spatrick   case DK_ELSE:
189409467b48Spatrick     return parseDirectiveElse(IDLoc);
189509467b48Spatrick   case DK_ENDIF:
189609467b48Spatrick     return parseDirectiveEndIf(IDLoc);
189709467b48Spatrick   }
189809467b48Spatrick 
189909467b48Spatrick   // Ignore the statement if in the middle of inactive conditional
190009467b48Spatrick   // (e.g. ".if 0").
190109467b48Spatrick   if (TheCondState.Ignore) {
190209467b48Spatrick     eatToEndOfStatement();
190309467b48Spatrick     return false;
190409467b48Spatrick   }
190509467b48Spatrick 
190609467b48Spatrick   // FIXME: Recurse on local labels?
190709467b48Spatrick 
1908*a96b3639Srobert   // Check for a label.
1909*a96b3639Srobert   //   ::= identifier ':'
1910*a96b3639Srobert   //   ::= number ':'
1911*a96b3639Srobert   if (Lexer.is(AsmToken::Colon) && getTargetParser().isLabel(ID)) {
191209467b48Spatrick     if (checkForValidSection())
191309467b48Spatrick       return true;
191409467b48Spatrick 
1915*a96b3639Srobert     Lex(); // Consume the ':'.
191609467b48Spatrick 
191709467b48Spatrick     // Diagnose attempt to use '.' as a label.
191809467b48Spatrick     if (IDVal == ".")
191909467b48Spatrick       return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
192009467b48Spatrick 
192109467b48Spatrick     // Diagnose attempt to use a variable as a label.
192209467b48Spatrick     //
192309467b48Spatrick     // FIXME: Diagnostics. Note the location of the definition as a label.
192409467b48Spatrick     // FIXME: This doesn't diagnose assignment to a symbol which has been
192509467b48Spatrick     // implicitly marked as external.
192609467b48Spatrick     MCSymbol *Sym;
192709467b48Spatrick     if (LocalLabelVal == -1) {
1928097a140dSpatrick       if (ParsingMSInlineAsm && SI) {
192909467b48Spatrick         StringRef RewrittenLabel =
193009467b48Spatrick             SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
193109467b48Spatrick         assert(!RewrittenLabel.empty() &&
193209467b48Spatrick                "We should have an internal name here.");
193309467b48Spatrick         Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
193409467b48Spatrick                                        RewrittenLabel);
193509467b48Spatrick         IDVal = RewrittenLabel;
193609467b48Spatrick       }
193709467b48Spatrick       Sym = getContext().getOrCreateSymbol(IDVal);
193809467b48Spatrick     } else
193909467b48Spatrick       Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
194009467b48Spatrick     // End of Labels should be treated as end of line for lexing
194109467b48Spatrick     // purposes but that information is not available to the Lexer who
194209467b48Spatrick     // does not understand Labels. This may cause us to see a Hash
194309467b48Spatrick     // here instead of a preprocessor line comment.
194409467b48Spatrick     if (getTok().is(AsmToken::Hash)) {
194509467b48Spatrick       StringRef CommentStr = parseStringToEndOfStatement();
194609467b48Spatrick       Lexer.Lex();
194709467b48Spatrick       Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
194809467b48Spatrick     }
194909467b48Spatrick 
195009467b48Spatrick     // Consume any end of statement token, if present, to avoid spurious
1951*a96b3639Srobert     // addBlankLine calls().
195209467b48Spatrick     if (getTok().is(AsmToken::EndOfStatement)) {
195309467b48Spatrick       Lex();
195409467b48Spatrick     }
195509467b48Spatrick 
1956a0747c9fSpatrick     if (discardLTOSymbol(IDVal))
1957a0747c9fSpatrick       return false;
1958a0747c9fSpatrick 
1959*a96b3639Srobert     getTargetParser().doBeforeLabelEmit(Sym, IDLoc);
196009467b48Spatrick 
196109467b48Spatrick     // Emit the label.
1962097a140dSpatrick     if (!getTargetParser().isParsingMSInlineAsm())
1963097a140dSpatrick       Out.emitLabel(Sym, IDLoc);
196409467b48Spatrick 
196509467b48Spatrick     // If we are generating dwarf for assembly source files then gather the
196609467b48Spatrick     // info to make a dwarf label entry for this label if needed.
196709467b48Spatrick     if (enabledGenDwarfForAssembly())
196809467b48Spatrick       MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
196909467b48Spatrick                                  IDLoc);
197009467b48Spatrick 
197109467b48Spatrick     getTargetParser().onLabelParsed(Sym);
197209467b48Spatrick 
197309467b48Spatrick     return false;
197409467b48Spatrick   }
197509467b48Spatrick 
1976*a96b3639Srobert   // Check for an assignment statement.
1977*a96b3639Srobert   //   ::= identifier '='
1978*a96b3639Srobert   if (Lexer.is(AsmToken::Equal) && getTargetParser().equalIsAsmAssignment()) {
197909467b48Spatrick     Lex();
1980*a96b3639Srobert     return parseAssignment(IDVal, AssignmentKind::Equal);
198109467b48Spatrick   }
198209467b48Spatrick 
198309467b48Spatrick   // If macros are enabled, check to see if this is a macro instantiation.
198409467b48Spatrick   if (areMacrosEnabled())
198509467b48Spatrick     if (const MCAsmMacro *M = getContext().lookupMacro(IDVal)) {
198609467b48Spatrick       return handleMacroEntry(M, IDLoc);
198709467b48Spatrick     }
198809467b48Spatrick 
198909467b48Spatrick   // Otherwise, we have a normal instruction or directive.
199009467b48Spatrick 
199109467b48Spatrick   // Directives start with "."
199209467b48Spatrick   if (IDVal.startswith(".") && IDVal != ".") {
199309467b48Spatrick     // There are several entities interested in parsing directives:
199409467b48Spatrick     //
199509467b48Spatrick     // 1. The target-specific assembly parser. Some directives are target
199609467b48Spatrick     //    specific or may potentially behave differently on certain targets.
199709467b48Spatrick     // 2. Asm parser extensions. For example, platform-specific parsers
199809467b48Spatrick     //    (like the ELF parser) register themselves as extensions.
199909467b48Spatrick     // 3. The generic directive parser implemented by this class. These are
200009467b48Spatrick     //    all the directives that behave in a target and platform independent
200109467b48Spatrick     //    manner, or at least have a default behavior that's shared between
200209467b48Spatrick     //    all targets and platforms.
200309467b48Spatrick 
200409467b48Spatrick     getTargetParser().flushPendingInstructions(getStreamer());
200509467b48Spatrick 
200609467b48Spatrick     SMLoc StartTokLoc = getTok().getLoc();
200709467b48Spatrick     bool TPDirectiveReturn = getTargetParser().ParseDirective(ID);
200809467b48Spatrick 
200909467b48Spatrick     if (hasPendingError())
201009467b48Spatrick       return true;
201109467b48Spatrick     // Currently the return value should be true if we are
201209467b48Spatrick     // uninterested but as this is at odds with the standard parsing
201309467b48Spatrick     // convention (return true = error) we have instances of a parsed
201409467b48Spatrick     // directive that fails returning true as an error. Catch these
201509467b48Spatrick     // cases as best as possible errors here.
201609467b48Spatrick     if (TPDirectiveReturn && StartTokLoc != getTok().getLoc())
201709467b48Spatrick       return true;
201809467b48Spatrick     // Return if we did some parsing or believe we succeeded.
201909467b48Spatrick     if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc())
202009467b48Spatrick       return false;
202109467b48Spatrick 
202209467b48Spatrick     // Next, check the extension directive map to see if any extension has
202309467b48Spatrick     // registered itself to parse this directive.
202409467b48Spatrick     std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
202509467b48Spatrick         ExtensionDirectiveMap.lookup(IDVal);
202609467b48Spatrick     if (Handler.first)
202709467b48Spatrick       return (*Handler.second)(Handler.first, IDVal, IDLoc);
202809467b48Spatrick 
202909467b48Spatrick     // Finally, if no one else is interested in this directive, it must be
203009467b48Spatrick     // generic and familiar to this class.
203109467b48Spatrick     switch (DirKind) {
203209467b48Spatrick     default:
203309467b48Spatrick       break;
203409467b48Spatrick     case DK_SET:
203509467b48Spatrick     case DK_EQU:
2036*a96b3639Srobert       return parseDirectiveSet(IDVal, AssignmentKind::Set);
203709467b48Spatrick     case DK_EQUIV:
2038*a96b3639Srobert       return parseDirectiveSet(IDVal, AssignmentKind::Equiv);
2039*a96b3639Srobert     case DK_LTO_SET_CONDITIONAL:
2040*a96b3639Srobert       return parseDirectiveSet(IDVal, AssignmentKind::LTOSetConditional);
204109467b48Spatrick     case DK_ASCII:
204209467b48Spatrick       return parseDirectiveAscii(IDVal, false);
204309467b48Spatrick     case DK_ASCIZ:
204409467b48Spatrick     case DK_STRING:
204509467b48Spatrick       return parseDirectiveAscii(IDVal, true);
204609467b48Spatrick     case DK_BYTE:
204709467b48Spatrick     case DK_DC_B:
204809467b48Spatrick       return parseDirectiveValue(IDVal, 1);
204909467b48Spatrick     case DK_DC:
205009467b48Spatrick     case DK_DC_W:
205109467b48Spatrick     case DK_SHORT:
205209467b48Spatrick     case DK_VALUE:
205309467b48Spatrick     case DK_2BYTE:
205409467b48Spatrick       return parseDirectiveValue(IDVal, 2);
205509467b48Spatrick     case DK_LONG:
205609467b48Spatrick     case DK_INT:
205709467b48Spatrick     case DK_4BYTE:
205809467b48Spatrick     case DK_DC_L:
205909467b48Spatrick       return parseDirectiveValue(IDVal, 4);
206009467b48Spatrick     case DK_QUAD:
206109467b48Spatrick     case DK_8BYTE:
206209467b48Spatrick       return parseDirectiveValue(IDVal, 8);
206309467b48Spatrick     case DK_DC_A:
206409467b48Spatrick       return parseDirectiveValue(
206509467b48Spatrick           IDVal, getContext().getAsmInfo()->getCodePointerSize());
206609467b48Spatrick     case DK_OCTA:
206709467b48Spatrick       return parseDirectiveOctaValue(IDVal);
206809467b48Spatrick     case DK_SINGLE:
206909467b48Spatrick     case DK_FLOAT:
207009467b48Spatrick     case DK_DC_S:
207109467b48Spatrick       return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());
207209467b48Spatrick     case DK_DOUBLE:
207309467b48Spatrick     case DK_DC_D:
207409467b48Spatrick       return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());
207509467b48Spatrick     case DK_ALIGN: {
207609467b48Spatrick       bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
207709467b48Spatrick       return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);
207809467b48Spatrick     }
207909467b48Spatrick     case DK_ALIGN32: {
208009467b48Spatrick       bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
208109467b48Spatrick       return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);
208209467b48Spatrick     }
208309467b48Spatrick     case DK_BALIGN:
208409467b48Spatrick       return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
208509467b48Spatrick     case DK_BALIGNW:
208609467b48Spatrick       return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
208709467b48Spatrick     case DK_BALIGNL:
208809467b48Spatrick       return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
208909467b48Spatrick     case DK_P2ALIGN:
209009467b48Spatrick       return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
209109467b48Spatrick     case DK_P2ALIGNW:
209209467b48Spatrick       return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
209309467b48Spatrick     case DK_P2ALIGNL:
209409467b48Spatrick       return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
209509467b48Spatrick     case DK_ORG:
209609467b48Spatrick       return parseDirectiveOrg();
209709467b48Spatrick     case DK_FILL:
209809467b48Spatrick       return parseDirectiveFill();
209909467b48Spatrick     case DK_ZERO:
210009467b48Spatrick       return parseDirectiveZero();
210109467b48Spatrick     case DK_EXTERN:
210209467b48Spatrick       eatToEndOfStatement(); // .extern is the default, ignore it.
210309467b48Spatrick       return false;
210409467b48Spatrick     case DK_GLOBL:
210509467b48Spatrick     case DK_GLOBAL:
210609467b48Spatrick       return parseDirectiveSymbolAttribute(MCSA_Global);
210709467b48Spatrick     case DK_LAZY_REFERENCE:
210809467b48Spatrick       return parseDirectiveSymbolAttribute(MCSA_LazyReference);
210909467b48Spatrick     case DK_NO_DEAD_STRIP:
211009467b48Spatrick       return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
211109467b48Spatrick     case DK_SYMBOL_RESOLVER:
211209467b48Spatrick       return parseDirectiveSymbolAttribute(MCSA_SymbolResolver);
211309467b48Spatrick     case DK_PRIVATE_EXTERN:
211409467b48Spatrick       return parseDirectiveSymbolAttribute(MCSA_PrivateExtern);
211509467b48Spatrick     case DK_REFERENCE:
211609467b48Spatrick       return parseDirectiveSymbolAttribute(MCSA_Reference);
211709467b48Spatrick     case DK_WEAK_DEFINITION:
211809467b48Spatrick       return parseDirectiveSymbolAttribute(MCSA_WeakDefinition);
211909467b48Spatrick     case DK_WEAK_REFERENCE:
212009467b48Spatrick       return parseDirectiveSymbolAttribute(MCSA_WeakReference);
212109467b48Spatrick     case DK_WEAK_DEF_CAN_BE_HIDDEN:
212209467b48Spatrick       return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
212309467b48Spatrick     case DK_COLD:
212409467b48Spatrick       return parseDirectiveSymbolAttribute(MCSA_Cold);
212509467b48Spatrick     case DK_COMM:
212609467b48Spatrick     case DK_COMMON:
212709467b48Spatrick       return parseDirectiveComm(/*IsLocal=*/false);
212809467b48Spatrick     case DK_LCOMM:
212909467b48Spatrick       return parseDirectiveComm(/*IsLocal=*/true);
213009467b48Spatrick     case DK_ABORT:
213109467b48Spatrick       return parseDirectiveAbort();
213209467b48Spatrick     case DK_INCLUDE:
213309467b48Spatrick       return parseDirectiveInclude();
213409467b48Spatrick     case DK_INCBIN:
213509467b48Spatrick       return parseDirectiveIncbin();
213609467b48Spatrick     case DK_CODE16:
213709467b48Spatrick     case DK_CODE16GCC:
213809467b48Spatrick       return TokError(Twine(IDVal) +
213909467b48Spatrick                       " not currently supported for this target");
214009467b48Spatrick     case DK_REPT:
214109467b48Spatrick       return parseDirectiveRept(IDLoc, IDVal);
214209467b48Spatrick     case DK_IRP:
214309467b48Spatrick       return parseDirectiveIrp(IDLoc);
214409467b48Spatrick     case DK_IRPC:
214509467b48Spatrick       return parseDirectiveIrpc(IDLoc);
214609467b48Spatrick     case DK_ENDR:
214709467b48Spatrick       return parseDirectiveEndr(IDLoc);
214809467b48Spatrick     case DK_BUNDLE_ALIGN_MODE:
214909467b48Spatrick       return parseDirectiveBundleAlignMode();
215009467b48Spatrick     case DK_BUNDLE_LOCK:
215109467b48Spatrick       return parseDirectiveBundleLock();
215209467b48Spatrick     case DK_BUNDLE_UNLOCK:
215309467b48Spatrick       return parseDirectiveBundleUnlock();
215409467b48Spatrick     case DK_SLEB128:
215509467b48Spatrick       return parseDirectiveLEB128(true);
215609467b48Spatrick     case DK_ULEB128:
215709467b48Spatrick       return parseDirectiveLEB128(false);
215809467b48Spatrick     case DK_SPACE:
215909467b48Spatrick     case DK_SKIP:
216009467b48Spatrick       return parseDirectiveSpace(IDVal);
216109467b48Spatrick     case DK_FILE:
216209467b48Spatrick       return parseDirectiveFile(IDLoc);
216309467b48Spatrick     case DK_LINE:
216409467b48Spatrick       return parseDirectiveLine();
216509467b48Spatrick     case DK_LOC:
216609467b48Spatrick       return parseDirectiveLoc();
216709467b48Spatrick     case DK_STABS:
216809467b48Spatrick       return parseDirectiveStabs();
216909467b48Spatrick     case DK_CV_FILE:
217009467b48Spatrick       return parseDirectiveCVFile();
217109467b48Spatrick     case DK_CV_FUNC_ID:
217209467b48Spatrick       return parseDirectiveCVFuncId();
217309467b48Spatrick     case DK_CV_INLINE_SITE_ID:
217409467b48Spatrick       return parseDirectiveCVInlineSiteId();
217509467b48Spatrick     case DK_CV_LOC:
217609467b48Spatrick       return parseDirectiveCVLoc();
217709467b48Spatrick     case DK_CV_LINETABLE:
217809467b48Spatrick       return parseDirectiveCVLinetable();
217909467b48Spatrick     case DK_CV_INLINE_LINETABLE:
218009467b48Spatrick       return parseDirectiveCVInlineLinetable();
218109467b48Spatrick     case DK_CV_DEF_RANGE:
218209467b48Spatrick       return parseDirectiveCVDefRange();
218309467b48Spatrick     case DK_CV_STRING:
218409467b48Spatrick       return parseDirectiveCVString();
218509467b48Spatrick     case DK_CV_STRINGTABLE:
218609467b48Spatrick       return parseDirectiveCVStringTable();
218709467b48Spatrick     case DK_CV_FILECHECKSUMS:
218809467b48Spatrick       return parseDirectiveCVFileChecksums();
218909467b48Spatrick     case DK_CV_FILECHECKSUM_OFFSET:
219009467b48Spatrick       return parseDirectiveCVFileChecksumOffset();
219109467b48Spatrick     case DK_CV_FPO_DATA:
219209467b48Spatrick       return parseDirectiveCVFPOData();
219309467b48Spatrick     case DK_CFI_SECTIONS:
219409467b48Spatrick       return parseDirectiveCFISections();
219509467b48Spatrick     case DK_CFI_STARTPROC:
219609467b48Spatrick       return parseDirectiveCFIStartProc();
219709467b48Spatrick     case DK_CFI_ENDPROC:
219809467b48Spatrick       return parseDirectiveCFIEndProc();
219909467b48Spatrick     case DK_CFI_DEF_CFA:
220009467b48Spatrick       return parseDirectiveCFIDefCfa(IDLoc);
220109467b48Spatrick     case DK_CFI_DEF_CFA_OFFSET:
220209467b48Spatrick       return parseDirectiveCFIDefCfaOffset();
220309467b48Spatrick     case DK_CFI_ADJUST_CFA_OFFSET:
220409467b48Spatrick       return parseDirectiveCFIAdjustCfaOffset();
220509467b48Spatrick     case DK_CFI_DEF_CFA_REGISTER:
220609467b48Spatrick       return parseDirectiveCFIDefCfaRegister(IDLoc);
2207a0747c9fSpatrick     case DK_CFI_LLVM_DEF_ASPACE_CFA:
2208a0747c9fSpatrick       return parseDirectiveCFILLVMDefAspaceCfa(IDLoc);
220909467b48Spatrick     case DK_CFI_OFFSET:
221009467b48Spatrick       return parseDirectiveCFIOffset(IDLoc);
221109467b48Spatrick     case DK_CFI_REL_OFFSET:
221209467b48Spatrick       return parseDirectiveCFIRelOffset(IDLoc);
221309467b48Spatrick     case DK_CFI_PERSONALITY:
221409467b48Spatrick       return parseDirectiveCFIPersonalityOrLsda(true);
221509467b48Spatrick     case DK_CFI_LSDA:
221609467b48Spatrick       return parseDirectiveCFIPersonalityOrLsda(false);
221709467b48Spatrick     case DK_CFI_REMEMBER_STATE:
221809467b48Spatrick       return parseDirectiveCFIRememberState();
221909467b48Spatrick     case DK_CFI_RESTORE_STATE:
222009467b48Spatrick       return parseDirectiveCFIRestoreState();
222109467b48Spatrick     case DK_CFI_SAME_VALUE:
222209467b48Spatrick       return parseDirectiveCFISameValue(IDLoc);
222309467b48Spatrick     case DK_CFI_RESTORE:
222409467b48Spatrick       return parseDirectiveCFIRestore(IDLoc);
222509467b48Spatrick     case DK_CFI_ESCAPE:
222609467b48Spatrick       return parseDirectiveCFIEscape();
222709467b48Spatrick     case DK_CFI_RETURN_COLUMN:
222809467b48Spatrick       return parseDirectiveCFIReturnColumn(IDLoc);
222909467b48Spatrick     case DK_CFI_SIGNAL_FRAME:
223009467b48Spatrick       return parseDirectiveCFISignalFrame();
223109467b48Spatrick     case DK_CFI_UNDEFINED:
223209467b48Spatrick       return parseDirectiveCFIUndefined(IDLoc);
223309467b48Spatrick     case DK_CFI_REGISTER:
223409467b48Spatrick       return parseDirectiveCFIRegister(IDLoc);
223509467b48Spatrick     case DK_CFI_WINDOW_SAVE:
223609467b48Spatrick       return parseDirectiveCFIWindowSave();
223709467b48Spatrick     case DK_MACROS_ON:
223809467b48Spatrick     case DK_MACROS_OFF:
223909467b48Spatrick       return parseDirectiveMacrosOnOff(IDVal);
224009467b48Spatrick     case DK_MACRO:
224109467b48Spatrick       return parseDirectiveMacro(IDLoc);
224209467b48Spatrick     case DK_ALTMACRO:
224309467b48Spatrick     case DK_NOALTMACRO:
224409467b48Spatrick       return parseDirectiveAltmacro(IDVal);
224509467b48Spatrick     case DK_EXITM:
224609467b48Spatrick       return parseDirectiveExitMacro(IDVal);
224709467b48Spatrick     case DK_ENDM:
224809467b48Spatrick     case DK_ENDMACRO:
224909467b48Spatrick       return parseDirectiveEndMacro(IDVal);
225009467b48Spatrick     case DK_PURGEM:
225109467b48Spatrick       return parseDirectivePurgeMacro(IDLoc);
225209467b48Spatrick     case DK_END:
225309467b48Spatrick       return parseDirectiveEnd(IDLoc);
225409467b48Spatrick     case DK_ERR:
225509467b48Spatrick       return parseDirectiveError(IDLoc, false);
225609467b48Spatrick     case DK_ERROR:
225709467b48Spatrick       return parseDirectiveError(IDLoc, true);
225809467b48Spatrick     case DK_WARNING:
225909467b48Spatrick       return parseDirectiveWarning(IDLoc);
226009467b48Spatrick     case DK_RELOC:
226109467b48Spatrick       return parseDirectiveReloc(IDLoc);
226209467b48Spatrick     case DK_DCB:
226309467b48Spatrick     case DK_DCB_W:
226409467b48Spatrick       return parseDirectiveDCB(IDVal, 2);
226509467b48Spatrick     case DK_DCB_B:
226609467b48Spatrick       return parseDirectiveDCB(IDVal, 1);
226709467b48Spatrick     case DK_DCB_D:
226809467b48Spatrick       return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble());
226909467b48Spatrick     case DK_DCB_L:
227009467b48Spatrick       return parseDirectiveDCB(IDVal, 4);
227109467b48Spatrick     case DK_DCB_S:
227209467b48Spatrick       return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle());
227309467b48Spatrick     case DK_DC_X:
227409467b48Spatrick     case DK_DCB_X:
227509467b48Spatrick       return TokError(Twine(IDVal) +
227609467b48Spatrick                       " not currently supported for this target");
227709467b48Spatrick     case DK_DS:
227809467b48Spatrick     case DK_DS_W:
227909467b48Spatrick       return parseDirectiveDS(IDVal, 2);
228009467b48Spatrick     case DK_DS_B:
228109467b48Spatrick       return parseDirectiveDS(IDVal, 1);
228209467b48Spatrick     case DK_DS_D:
228309467b48Spatrick       return parseDirectiveDS(IDVal, 8);
228409467b48Spatrick     case DK_DS_L:
228509467b48Spatrick     case DK_DS_S:
228609467b48Spatrick       return parseDirectiveDS(IDVal, 4);
228709467b48Spatrick     case DK_DS_P:
228809467b48Spatrick     case DK_DS_X:
228909467b48Spatrick       return parseDirectiveDS(IDVal, 12);
229009467b48Spatrick     case DK_PRINT:
229109467b48Spatrick       return parseDirectivePrint(IDLoc);
229209467b48Spatrick     case DK_ADDRSIG:
229309467b48Spatrick       return parseDirectiveAddrsig();
229409467b48Spatrick     case DK_ADDRSIG_SYM:
229509467b48Spatrick       return parseDirectiveAddrsigSym();
2296a0747c9fSpatrick     case DK_PSEUDO_PROBE:
2297a0747c9fSpatrick       return parseDirectivePseudoProbe();
2298a0747c9fSpatrick     case DK_LTO_DISCARD:
2299a0747c9fSpatrick       return parseDirectiveLTODiscard();
2300*a96b3639Srobert     case DK_MEMTAG:
2301*a96b3639Srobert       return parseDirectiveSymbolAttribute(MCSA_Memtag);
230209467b48Spatrick     }
230309467b48Spatrick 
230409467b48Spatrick     return Error(IDLoc, "unknown directive");
230509467b48Spatrick   }
230609467b48Spatrick 
230709467b48Spatrick   // __asm _emit or __asm __emit
2308097a140dSpatrick   if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
230909467b48Spatrick                              IDVal == "_EMIT" || IDVal == "__EMIT"))
231009467b48Spatrick     return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
231109467b48Spatrick 
231209467b48Spatrick   // __asm align
2313097a140dSpatrick   if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
231409467b48Spatrick     return parseDirectiveMSAlign(IDLoc, Info);
231509467b48Spatrick 
2316097a140dSpatrick   if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
231709467b48Spatrick     Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
231809467b48Spatrick   if (checkForValidSection())
231909467b48Spatrick     return true;
232009467b48Spatrick 
2321a0747c9fSpatrick   return parseAndMatchAndEmitTargetInstruction(Info, IDVal, ID, IDLoc);
2322a0747c9fSpatrick }
2323a0747c9fSpatrick 
parseAndMatchAndEmitTargetInstruction(ParseStatementInfo & Info,StringRef IDVal,AsmToken ID,SMLoc IDLoc)2324a0747c9fSpatrick bool AsmParser::parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,
2325a0747c9fSpatrick                                                       StringRef IDVal,
2326a0747c9fSpatrick                                                       AsmToken ID,
2327a0747c9fSpatrick                                                       SMLoc IDLoc) {
232809467b48Spatrick   // Canonicalize the opcode to lower case.
232909467b48Spatrick   std::string OpcodeStr = IDVal.lower();
233009467b48Spatrick   ParseInstructionInfo IInfo(Info.AsmRewrites);
233109467b48Spatrick   bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
233209467b48Spatrick                                                           Info.ParsedOperands);
233309467b48Spatrick   Info.ParseError = ParseHadError;
233409467b48Spatrick 
233509467b48Spatrick   // Dump the parsed representation, if requested.
233609467b48Spatrick   if (getShowParsedOperands()) {
233709467b48Spatrick     SmallString<256> Str;
233809467b48Spatrick     raw_svector_ostream OS(Str);
233909467b48Spatrick     OS << "parsed instruction: [";
234009467b48Spatrick     for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
234109467b48Spatrick       if (i != 0)
234209467b48Spatrick         OS << ", ";
234309467b48Spatrick       Info.ParsedOperands[i]->print(OS);
234409467b48Spatrick     }
234509467b48Spatrick     OS << "]";
234609467b48Spatrick 
234709467b48Spatrick     printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
234809467b48Spatrick   }
234909467b48Spatrick 
235009467b48Spatrick   // Fail even if ParseInstruction erroneously returns false.
235109467b48Spatrick   if (hasPendingError() || ParseHadError)
235209467b48Spatrick     return true;
235309467b48Spatrick 
235409467b48Spatrick   // If we are generating dwarf for the current section then generate a .loc
235509467b48Spatrick   // directive for the instruction.
235609467b48Spatrick   if (!ParseHadError && enabledGenDwarfForAssembly() &&
235709467b48Spatrick       getContext().getGenDwarfSectionSyms().count(
235809467b48Spatrick           getStreamer().getCurrentSectionOnly())) {
235909467b48Spatrick     unsigned Line;
236009467b48Spatrick     if (ActiveMacros.empty())
236109467b48Spatrick       Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
236209467b48Spatrick     else
236309467b48Spatrick       Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
236409467b48Spatrick                                    ActiveMacros.front()->ExitBuffer);
236509467b48Spatrick 
236609467b48Spatrick     // If we previously parsed a cpp hash file line comment then make sure the
236709467b48Spatrick     // current Dwarf File is for the CppHashFilename if not then emit the
236809467b48Spatrick     // Dwarf File table for it and adjust the line number for the .loc.
236909467b48Spatrick     if (!CppHashInfo.Filename.empty()) {
2370097a140dSpatrick       unsigned FileNumber = getStreamer().emitDwarfFileDirective(
237109467b48Spatrick           0, StringRef(), CppHashInfo.Filename);
237209467b48Spatrick       getContext().setGenDwarfFileNumber(FileNumber);
237309467b48Spatrick 
237409467b48Spatrick       unsigned CppHashLocLineNo =
237509467b48Spatrick         SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
237609467b48Spatrick       Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
237709467b48Spatrick     }
237809467b48Spatrick 
2379097a140dSpatrick     getStreamer().emitDwarfLocDirective(
238009467b48Spatrick         getContext().getGenDwarfFileNumber(), Line, 0,
238109467b48Spatrick         DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
238209467b48Spatrick         StringRef());
238309467b48Spatrick   }
238409467b48Spatrick 
238509467b48Spatrick   // If parsing succeeded, match the instruction.
238609467b48Spatrick   if (!ParseHadError) {
238709467b48Spatrick     uint64_t ErrorInfo;
238809467b48Spatrick     if (getTargetParser().MatchAndEmitInstruction(
238909467b48Spatrick             IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
2390097a140dSpatrick             getTargetParser().isParsingMSInlineAsm()))
239109467b48Spatrick       return true;
239209467b48Spatrick   }
239309467b48Spatrick   return false;
239409467b48Spatrick }
239509467b48Spatrick 
239609467b48Spatrick // Parse and erase curly braces marking block start/end
239709467b48Spatrick bool
parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> & AsmStrRewrites)239809467b48Spatrick AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
239909467b48Spatrick   // Identify curly brace marking block start/end
240009467b48Spatrick   if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
240109467b48Spatrick     return false;
240209467b48Spatrick 
240309467b48Spatrick   SMLoc StartLoc = Lexer.getLoc();
240409467b48Spatrick   Lex(); // Eat the brace
240509467b48Spatrick   if (Lexer.is(AsmToken::EndOfStatement))
240609467b48Spatrick     Lex(); // Eat EndOfStatement following the brace
240709467b48Spatrick 
240809467b48Spatrick   // Erase the block start/end brace from the output asm string
240909467b48Spatrick   AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
241009467b48Spatrick                                                   StartLoc.getPointer());
241109467b48Spatrick   return true;
241209467b48Spatrick }
241309467b48Spatrick 
241409467b48Spatrick /// parseCppHashLineFilenameComment as this:
241509467b48Spatrick ///   ::= # number "filename"
parseCppHashLineFilenameComment(SMLoc L,bool SaveLocInfo)2416097a140dSpatrick bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) {
241709467b48Spatrick   Lex(); // Eat the hash token.
241809467b48Spatrick   // Lexer only ever emits HashDirective if it fully formed if it's
241909467b48Spatrick   // done the checking already so this is an internal error.
242009467b48Spatrick   assert(getTok().is(AsmToken::Integer) &&
242109467b48Spatrick          "Lexing Cpp line comment: Expected Integer");
242209467b48Spatrick   int64_t LineNumber = getTok().getIntVal();
242309467b48Spatrick   Lex();
242409467b48Spatrick   assert(getTok().is(AsmToken::String) &&
242509467b48Spatrick          "Lexing Cpp line comment: Expected String");
242609467b48Spatrick   StringRef Filename = getTok().getString();
242709467b48Spatrick   Lex();
242809467b48Spatrick 
2429097a140dSpatrick   if (!SaveLocInfo)
2430097a140dSpatrick     return false;
2431097a140dSpatrick 
243209467b48Spatrick   // Get rid of the enclosing quotes.
243309467b48Spatrick   Filename = Filename.substr(1, Filename.size() - 2);
243409467b48Spatrick 
243509467b48Spatrick   // Save the SMLoc, Filename and LineNumber for later use by diagnostics
243609467b48Spatrick   // and possibly DWARF file info.
243709467b48Spatrick   CppHashInfo.Loc = L;
243809467b48Spatrick   CppHashInfo.Filename = Filename;
243909467b48Spatrick   CppHashInfo.LineNumber = LineNumber;
244009467b48Spatrick   CppHashInfo.Buf = CurBuffer;
244109467b48Spatrick   if (FirstCppHashFilename.empty())
244209467b48Spatrick     FirstCppHashFilename = Filename;
244309467b48Spatrick   return false;
244409467b48Spatrick }
244509467b48Spatrick 
244609467b48Spatrick /// will use the last parsed cpp hash line filename comment
244709467b48Spatrick /// for the Filename and LineNo if any in the diagnostic.
DiagHandler(const SMDiagnostic & Diag,void * Context)244809467b48Spatrick void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
2449a0747c9fSpatrick   auto *Parser = static_cast<AsmParser *>(Context);
245009467b48Spatrick   raw_ostream &OS = errs();
245109467b48Spatrick 
245209467b48Spatrick   const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
245309467b48Spatrick   SMLoc DiagLoc = Diag.getLoc();
245409467b48Spatrick   unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
245509467b48Spatrick   unsigned CppHashBuf =
245609467b48Spatrick       Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
245709467b48Spatrick 
245809467b48Spatrick   // Like SourceMgr::printMessage() we need to print the include stack if any
245909467b48Spatrick   // before printing the message.
246009467b48Spatrick   unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
246109467b48Spatrick   if (!Parser->SavedDiagHandler && DiagCurBuffer &&
246209467b48Spatrick       DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
246309467b48Spatrick     SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
246409467b48Spatrick     DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
246509467b48Spatrick   }
246609467b48Spatrick 
246709467b48Spatrick   // If we have not parsed a cpp hash line filename comment or the source
246809467b48Spatrick   // manager changed or buffer changed (like in a nested include) then just
246909467b48Spatrick   // print the normal diagnostic using its Filename and LineNo.
2470a0747c9fSpatrick   if (!Parser->CppHashInfo.LineNumber || DiagBuf != CppHashBuf) {
247109467b48Spatrick     if (Parser->SavedDiagHandler)
247209467b48Spatrick       Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
247309467b48Spatrick     else
2474a0747c9fSpatrick       Parser->getContext().diagnose(Diag);
247509467b48Spatrick     return;
247609467b48Spatrick   }
247709467b48Spatrick 
247809467b48Spatrick   // Use the CppHashFilename and calculate a line number based on the
247909467b48Spatrick   // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
248009467b48Spatrick   // for the diagnostic.
2481097a140dSpatrick   const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
248209467b48Spatrick 
248309467b48Spatrick   int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
248409467b48Spatrick   int CppHashLocLineNo =
248509467b48Spatrick       Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
248609467b48Spatrick   int LineNo =
248709467b48Spatrick       Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
248809467b48Spatrick 
248909467b48Spatrick   SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
249009467b48Spatrick                        Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
249109467b48Spatrick                        Diag.getLineContents(), Diag.getRanges());
249209467b48Spatrick 
249309467b48Spatrick   if (Parser->SavedDiagHandler)
2494a0747c9fSpatrick     Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
249509467b48Spatrick   else
2496a0747c9fSpatrick     Parser->getContext().diagnose(NewDiag);
249709467b48Spatrick }
249809467b48Spatrick 
249909467b48Spatrick // FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The
250009467b48Spatrick // difference being that that function accepts '@' as part of identifiers and
250109467b48Spatrick // we can't do that. AsmLexer.cpp should probably be changed to handle
250209467b48Spatrick // '@' as a special case when needed.
isIdentifierChar(char c)250309467b48Spatrick static bool isIdentifierChar(char c) {
250409467b48Spatrick   return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||
250509467b48Spatrick          c == '.';
250609467b48Spatrick }
250709467b48Spatrick 
expandMacro(raw_svector_ostream & OS,StringRef Body,ArrayRef<MCAsmMacroParameter> Parameters,ArrayRef<MCAsmMacroArgument> A,bool EnableAtPseudoVariable,SMLoc L)250809467b48Spatrick bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
250909467b48Spatrick                             ArrayRef<MCAsmMacroParameter> Parameters,
251009467b48Spatrick                             ArrayRef<MCAsmMacroArgument> A,
251109467b48Spatrick                             bool EnableAtPseudoVariable, SMLoc L) {
251209467b48Spatrick   unsigned NParameters = Parameters.size();
251309467b48Spatrick   bool HasVararg = NParameters ? Parameters.back().Vararg : false;
251409467b48Spatrick   if ((!IsDarwin || NParameters != 0) && NParameters != A.size())
251509467b48Spatrick     return Error(L, "Wrong number of arguments");
251609467b48Spatrick 
251709467b48Spatrick   // A macro without parameters is handled differently on Darwin:
251809467b48Spatrick   // gas accepts no arguments and does no substitutions
251909467b48Spatrick   while (!Body.empty()) {
252009467b48Spatrick     // Scan for the next substitution.
252109467b48Spatrick     std::size_t End = Body.size(), Pos = 0;
252209467b48Spatrick     for (; Pos != End; ++Pos) {
252309467b48Spatrick       // Check for a substitution or escape.
252409467b48Spatrick       if (IsDarwin && !NParameters) {
252509467b48Spatrick         // This macro has no parameters, look for $0, $1, etc.
252609467b48Spatrick         if (Body[Pos] != '$' || Pos + 1 == End)
252709467b48Spatrick           continue;
252809467b48Spatrick 
252909467b48Spatrick         char Next = Body[Pos + 1];
253009467b48Spatrick         if (Next == '$' || Next == 'n' ||
253109467b48Spatrick             isdigit(static_cast<unsigned char>(Next)))
253209467b48Spatrick           break;
253309467b48Spatrick       } else {
253409467b48Spatrick         // This macro has parameters, look for \foo, \bar, etc.
253509467b48Spatrick         if (Body[Pos] == '\\' && Pos + 1 != End)
253609467b48Spatrick           break;
253709467b48Spatrick       }
253809467b48Spatrick     }
253909467b48Spatrick 
254009467b48Spatrick     // Add the prefix.
254109467b48Spatrick     OS << Body.slice(0, Pos);
254209467b48Spatrick 
254309467b48Spatrick     // Check if we reached the end.
254409467b48Spatrick     if (Pos == End)
254509467b48Spatrick       break;
254609467b48Spatrick 
254709467b48Spatrick     if (IsDarwin && !NParameters) {
254809467b48Spatrick       switch (Body[Pos + 1]) {
254909467b48Spatrick       // $$ => $
255009467b48Spatrick       case '$':
255109467b48Spatrick         OS << '$';
255209467b48Spatrick         break;
255309467b48Spatrick 
255409467b48Spatrick       // $n => number of arguments
255509467b48Spatrick       case 'n':
255609467b48Spatrick         OS << A.size();
255709467b48Spatrick         break;
255809467b48Spatrick 
255909467b48Spatrick       // $[0-9] => argument
256009467b48Spatrick       default: {
256109467b48Spatrick         // Missing arguments are ignored.
256209467b48Spatrick         unsigned Index = Body[Pos + 1] - '0';
256309467b48Spatrick         if (Index >= A.size())
256409467b48Spatrick           break;
256509467b48Spatrick 
256609467b48Spatrick         // Otherwise substitute with the token values, with spaces eliminated.
256709467b48Spatrick         for (const AsmToken &Token : A[Index])
256809467b48Spatrick           OS << Token.getString();
256909467b48Spatrick         break;
257009467b48Spatrick       }
257109467b48Spatrick       }
257209467b48Spatrick       Pos += 2;
257309467b48Spatrick     } else {
257409467b48Spatrick       unsigned I = Pos + 1;
257509467b48Spatrick 
257609467b48Spatrick       // Check for the \@ pseudo-variable.
257709467b48Spatrick       if (EnableAtPseudoVariable && Body[I] == '@' && I + 1 != End)
257809467b48Spatrick         ++I;
257909467b48Spatrick       else
258009467b48Spatrick         while (isIdentifierChar(Body[I]) && I + 1 != End)
258109467b48Spatrick           ++I;
258209467b48Spatrick 
258309467b48Spatrick       const char *Begin = Body.data() + Pos + 1;
258409467b48Spatrick       StringRef Argument(Begin, I - (Pos + 1));
258509467b48Spatrick       unsigned Index = 0;
258609467b48Spatrick 
258709467b48Spatrick       if (Argument == "@") {
258809467b48Spatrick         OS << NumOfMacroInstantiations;
258909467b48Spatrick         Pos += 2;
259009467b48Spatrick       } else {
259109467b48Spatrick         for (; Index < NParameters; ++Index)
259209467b48Spatrick           if (Parameters[Index].Name == Argument)
259309467b48Spatrick             break;
259409467b48Spatrick 
259509467b48Spatrick         if (Index == NParameters) {
259609467b48Spatrick           if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
259709467b48Spatrick             Pos += 3;
259809467b48Spatrick           else {
259909467b48Spatrick             OS << '\\' << Argument;
260009467b48Spatrick             Pos = I;
260109467b48Spatrick           }
260209467b48Spatrick         } else {
260309467b48Spatrick           bool VarargParameter = HasVararg && Index == (NParameters - 1);
260409467b48Spatrick           for (const AsmToken &Token : A[Index])
260509467b48Spatrick             // For altmacro mode, you can write '%expr'.
260609467b48Spatrick             // The prefix '%' evaluates the expression 'expr'
260709467b48Spatrick             // and uses the result as a string (e.g. replace %(1+2) with the
260809467b48Spatrick             // string "3").
260909467b48Spatrick             // Here, we identify the integer token which is the result of the
261009467b48Spatrick             // absolute expression evaluation and replace it with its string
261109467b48Spatrick             // representation.
261209467b48Spatrick             if (AltMacroMode && Token.getString().front() == '%' &&
261309467b48Spatrick                 Token.is(AsmToken::Integer))
261409467b48Spatrick               // Emit an integer value to the buffer.
261509467b48Spatrick               OS << Token.getIntVal();
261609467b48Spatrick             // Only Token that was validated as a string and begins with '<'
261709467b48Spatrick             // is considered altMacroString!!!
261809467b48Spatrick             else if (AltMacroMode && Token.getString().front() == '<' &&
261909467b48Spatrick                      Token.is(AsmToken::String)) {
2620097a140dSpatrick               OS << angleBracketString(Token.getStringContents());
262109467b48Spatrick             }
262209467b48Spatrick             // We expect no quotes around the string's contents when
262309467b48Spatrick             // parsing for varargs.
262409467b48Spatrick             else if (Token.isNot(AsmToken::String) || VarargParameter)
262509467b48Spatrick               OS << Token.getString();
262609467b48Spatrick             else
262709467b48Spatrick               OS << Token.getStringContents();
262809467b48Spatrick 
262909467b48Spatrick           Pos += 1 + Argument.size();
263009467b48Spatrick         }
263109467b48Spatrick       }
263209467b48Spatrick     }
263309467b48Spatrick     // Update the scan point.
263409467b48Spatrick     Body = Body.substr(Pos);
263509467b48Spatrick   }
263609467b48Spatrick 
263709467b48Spatrick   return false;
263809467b48Spatrick }
263909467b48Spatrick 
isOperator(AsmToken::TokenKind kind)264009467b48Spatrick static bool isOperator(AsmToken::TokenKind kind) {
264109467b48Spatrick   switch (kind) {
264209467b48Spatrick   default:
264309467b48Spatrick     return false;
264409467b48Spatrick   case AsmToken::Plus:
264509467b48Spatrick   case AsmToken::Minus:
264609467b48Spatrick   case AsmToken::Tilde:
264709467b48Spatrick   case AsmToken::Slash:
264809467b48Spatrick   case AsmToken::Star:
264909467b48Spatrick   case AsmToken::Dot:
265009467b48Spatrick   case AsmToken::Equal:
265109467b48Spatrick   case AsmToken::EqualEqual:
265209467b48Spatrick   case AsmToken::Pipe:
265309467b48Spatrick   case AsmToken::PipePipe:
265409467b48Spatrick   case AsmToken::Caret:
265509467b48Spatrick   case AsmToken::Amp:
265609467b48Spatrick   case AsmToken::AmpAmp:
265709467b48Spatrick   case AsmToken::Exclaim:
265809467b48Spatrick   case AsmToken::ExclaimEqual:
265909467b48Spatrick   case AsmToken::Less:
266009467b48Spatrick   case AsmToken::LessEqual:
266109467b48Spatrick   case AsmToken::LessLess:
266209467b48Spatrick   case AsmToken::LessGreater:
266309467b48Spatrick   case AsmToken::Greater:
266409467b48Spatrick   case AsmToken::GreaterEqual:
266509467b48Spatrick   case AsmToken::GreaterGreater:
266609467b48Spatrick     return true;
266709467b48Spatrick   }
266809467b48Spatrick }
266909467b48Spatrick 
267009467b48Spatrick namespace {
267109467b48Spatrick 
267209467b48Spatrick class AsmLexerSkipSpaceRAII {
267309467b48Spatrick public:
AsmLexerSkipSpaceRAII(AsmLexer & Lexer,bool SkipSpace)267409467b48Spatrick   AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
267509467b48Spatrick     Lexer.setSkipSpace(SkipSpace);
267609467b48Spatrick   }
267709467b48Spatrick 
~AsmLexerSkipSpaceRAII()267809467b48Spatrick   ~AsmLexerSkipSpaceRAII() {
267909467b48Spatrick     Lexer.setSkipSpace(true);
268009467b48Spatrick   }
268109467b48Spatrick 
268209467b48Spatrick private:
268309467b48Spatrick   AsmLexer &Lexer;
268409467b48Spatrick };
268509467b48Spatrick 
268609467b48Spatrick } // end anonymous namespace
268709467b48Spatrick 
parseMacroArgument(MCAsmMacroArgument & MA,bool Vararg)268809467b48Spatrick bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
268909467b48Spatrick 
269009467b48Spatrick   if (Vararg) {
269109467b48Spatrick     if (Lexer.isNot(AsmToken::EndOfStatement)) {
269209467b48Spatrick       StringRef Str = parseStringToEndOfStatement();
269309467b48Spatrick       MA.emplace_back(AsmToken::String, Str);
269409467b48Spatrick     }
269509467b48Spatrick     return false;
269609467b48Spatrick   }
269709467b48Spatrick 
269809467b48Spatrick   unsigned ParenLevel = 0;
269909467b48Spatrick 
270009467b48Spatrick   // Darwin doesn't use spaces to delmit arguments.
270109467b48Spatrick   AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
270209467b48Spatrick 
270309467b48Spatrick   bool SpaceEaten;
270409467b48Spatrick 
270509467b48Spatrick   while (true) {
270609467b48Spatrick     SpaceEaten = false;
270709467b48Spatrick     if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
270809467b48Spatrick       return TokError("unexpected token in macro instantiation");
270909467b48Spatrick 
271009467b48Spatrick     if (ParenLevel == 0) {
271109467b48Spatrick 
271209467b48Spatrick       if (Lexer.is(AsmToken::Comma))
271309467b48Spatrick         break;
271409467b48Spatrick 
271509467b48Spatrick       if (Lexer.is(AsmToken::Space)) {
271609467b48Spatrick         SpaceEaten = true;
271709467b48Spatrick         Lexer.Lex(); // Eat spaces
271809467b48Spatrick       }
271909467b48Spatrick 
272009467b48Spatrick       // Spaces can delimit parameters, but could also be part an expression.
272109467b48Spatrick       // If the token after a space is an operator, add the token and the next
272209467b48Spatrick       // one into this argument
272309467b48Spatrick       if (!IsDarwin) {
272409467b48Spatrick         if (isOperator(Lexer.getKind())) {
272509467b48Spatrick           MA.push_back(getTok());
272609467b48Spatrick           Lexer.Lex();
272709467b48Spatrick 
272809467b48Spatrick           // Whitespace after an operator can be ignored.
272909467b48Spatrick           if (Lexer.is(AsmToken::Space))
273009467b48Spatrick             Lexer.Lex();
273109467b48Spatrick 
273209467b48Spatrick           continue;
273309467b48Spatrick         }
273409467b48Spatrick       }
273509467b48Spatrick       if (SpaceEaten)
273609467b48Spatrick         break;
273709467b48Spatrick     }
273809467b48Spatrick 
273909467b48Spatrick     // handleMacroEntry relies on not advancing the lexer here
274009467b48Spatrick     // to be able to fill in the remaining default parameter values
274109467b48Spatrick     if (Lexer.is(AsmToken::EndOfStatement))
274209467b48Spatrick       break;
274309467b48Spatrick 
274409467b48Spatrick     // Adjust the current parentheses level.
274509467b48Spatrick     if (Lexer.is(AsmToken::LParen))
274609467b48Spatrick       ++ParenLevel;
274709467b48Spatrick     else if (Lexer.is(AsmToken::RParen) && ParenLevel)
274809467b48Spatrick       --ParenLevel;
274909467b48Spatrick 
275009467b48Spatrick     // Append the token to the current argument list.
275109467b48Spatrick     MA.push_back(getTok());
275209467b48Spatrick     Lexer.Lex();
275309467b48Spatrick   }
275409467b48Spatrick 
275509467b48Spatrick   if (ParenLevel != 0)
275609467b48Spatrick     return TokError("unbalanced parentheses in macro argument");
275709467b48Spatrick   return false;
275809467b48Spatrick }
275909467b48Spatrick 
276009467b48Spatrick // Parse the macro instantiation arguments.
parseMacroArguments(const MCAsmMacro * M,MCAsmMacroArguments & A)276109467b48Spatrick bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
276209467b48Spatrick                                     MCAsmMacroArguments &A) {
276309467b48Spatrick   const unsigned NParameters = M ? M->Parameters.size() : 0;
276409467b48Spatrick   bool NamedParametersFound = false;
276509467b48Spatrick   SmallVector<SMLoc, 4> FALocs;
276609467b48Spatrick 
276709467b48Spatrick   A.resize(NParameters);
276809467b48Spatrick   FALocs.resize(NParameters);
276909467b48Spatrick 
277009467b48Spatrick   // Parse two kinds of macro invocations:
277109467b48Spatrick   // - macros defined without any parameters accept an arbitrary number of them
277209467b48Spatrick   // - macros defined with parameters accept at most that many of them
277309467b48Spatrick   bool HasVararg = NParameters ? M->Parameters.back().Vararg : false;
277409467b48Spatrick   for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
277509467b48Spatrick        ++Parameter) {
277609467b48Spatrick     SMLoc IDLoc = Lexer.getLoc();
277709467b48Spatrick     MCAsmMacroParameter FA;
277809467b48Spatrick 
277909467b48Spatrick     if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
278009467b48Spatrick       if (parseIdentifier(FA.Name))
278109467b48Spatrick         return Error(IDLoc, "invalid argument identifier for formal argument");
278209467b48Spatrick 
278309467b48Spatrick       if (Lexer.isNot(AsmToken::Equal))
278409467b48Spatrick         return TokError("expected '=' after formal parameter identifier");
278509467b48Spatrick 
278609467b48Spatrick       Lex();
278709467b48Spatrick 
278809467b48Spatrick       NamedParametersFound = true;
278909467b48Spatrick     }
279009467b48Spatrick     bool Vararg = HasVararg && Parameter == (NParameters - 1);
279109467b48Spatrick 
279209467b48Spatrick     if (NamedParametersFound && FA.Name.empty())
279309467b48Spatrick       return Error(IDLoc, "cannot mix positional and keyword arguments");
279409467b48Spatrick 
279509467b48Spatrick     SMLoc StrLoc = Lexer.getLoc();
279609467b48Spatrick     SMLoc EndLoc;
279709467b48Spatrick     if (AltMacroMode && Lexer.is(AsmToken::Percent)) {
279809467b48Spatrick       const MCExpr *AbsoluteExp;
279909467b48Spatrick       int64_t Value;
280009467b48Spatrick       /// Eat '%'
280109467b48Spatrick       Lex();
280209467b48Spatrick       if (parseExpression(AbsoluteExp, EndLoc))
280309467b48Spatrick         return false;
280409467b48Spatrick       if (!AbsoluteExp->evaluateAsAbsolute(Value,
280509467b48Spatrick                                            getStreamer().getAssemblerPtr()))
280609467b48Spatrick         return Error(StrLoc, "expected absolute expression");
280709467b48Spatrick       const char *StrChar = StrLoc.getPointer();
280809467b48Spatrick       const char *EndChar = EndLoc.getPointer();
280909467b48Spatrick       AsmToken newToken(AsmToken::Integer,
281009467b48Spatrick                         StringRef(StrChar, EndChar - StrChar), Value);
281109467b48Spatrick       FA.Value.push_back(newToken);
281209467b48Spatrick     } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
2813097a140dSpatrick                isAngleBracketString(StrLoc, EndLoc)) {
281409467b48Spatrick       const char *StrChar = StrLoc.getPointer();
281509467b48Spatrick       const char *EndChar = EndLoc.getPointer();
281609467b48Spatrick       jumpToLoc(EndLoc, CurBuffer);
281709467b48Spatrick       /// Eat from '<' to '>'
281809467b48Spatrick       Lex();
281909467b48Spatrick       AsmToken newToken(AsmToken::String,
282009467b48Spatrick                         StringRef(StrChar, EndChar - StrChar));
282109467b48Spatrick       FA.Value.push_back(newToken);
282209467b48Spatrick     } else if(parseMacroArgument(FA.Value, Vararg))
282309467b48Spatrick       return true;
282409467b48Spatrick 
282509467b48Spatrick     unsigned PI = Parameter;
282609467b48Spatrick     if (!FA.Name.empty()) {
282709467b48Spatrick       unsigned FAI = 0;
282809467b48Spatrick       for (FAI = 0; FAI < NParameters; ++FAI)
282909467b48Spatrick         if (M->Parameters[FAI].Name == FA.Name)
283009467b48Spatrick           break;
283109467b48Spatrick 
283209467b48Spatrick       if (FAI >= NParameters) {
283309467b48Spatrick         assert(M && "expected macro to be defined");
283409467b48Spatrick         return Error(IDLoc, "parameter named '" + FA.Name +
283509467b48Spatrick                                 "' does not exist for macro '" + M->Name + "'");
283609467b48Spatrick       }
283709467b48Spatrick       PI = FAI;
283809467b48Spatrick     }
283909467b48Spatrick 
284009467b48Spatrick     if (!FA.Value.empty()) {
284109467b48Spatrick       if (A.size() <= PI)
284209467b48Spatrick         A.resize(PI + 1);
284309467b48Spatrick       A[PI] = FA.Value;
284409467b48Spatrick 
284509467b48Spatrick       if (FALocs.size() <= PI)
284609467b48Spatrick         FALocs.resize(PI + 1);
284709467b48Spatrick 
284809467b48Spatrick       FALocs[PI] = Lexer.getLoc();
284909467b48Spatrick     }
285009467b48Spatrick 
285109467b48Spatrick     // At the end of the statement, fill in remaining arguments that have
285209467b48Spatrick     // default values. If there aren't any, then the next argument is
285309467b48Spatrick     // required but missing
285409467b48Spatrick     if (Lexer.is(AsmToken::EndOfStatement)) {
285509467b48Spatrick       bool Failure = false;
285609467b48Spatrick       for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
285709467b48Spatrick         if (A[FAI].empty()) {
285809467b48Spatrick           if (M->Parameters[FAI].Required) {
285909467b48Spatrick             Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
286009467b48Spatrick                   "missing value for required parameter "
286109467b48Spatrick                   "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
286209467b48Spatrick             Failure = true;
286309467b48Spatrick           }
286409467b48Spatrick 
286509467b48Spatrick           if (!M->Parameters[FAI].Value.empty())
286609467b48Spatrick             A[FAI] = M->Parameters[FAI].Value;
286709467b48Spatrick         }
286809467b48Spatrick       }
286909467b48Spatrick       return Failure;
287009467b48Spatrick     }
287109467b48Spatrick 
287209467b48Spatrick     if (Lexer.is(AsmToken::Comma))
287309467b48Spatrick       Lex();
287409467b48Spatrick   }
287509467b48Spatrick 
287609467b48Spatrick   return TokError("too many positional arguments");
287709467b48Spatrick }
287809467b48Spatrick 
handleMacroEntry(const MCAsmMacro * M,SMLoc NameLoc)287909467b48Spatrick bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
288009467b48Spatrick   // Arbitrarily limit macro nesting depth (default matches 'as'). We can
288109467b48Spatrick   // eliminate this, although we should protect against infinite loops.
288209467b48Spatrick   unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
288309467b48Spatrick   if (ActiveMacros.size() == MaxNestingDepth) {
288409467b48Spatrick     std::ostringstream MaxNestingDepthError;
288509467b48Spatrick     MaxNestingDepthError << "macros cannot be nested more than "
288609467b48Spatrick                          << MaxNestingDepth << " levels deep."
288709467b48Spatrick                          << " Use -asm-macro-max-nesting-depth to increase "
288809467b48Spatrick                             "this limit.";
288909467b48Spatrick     return TokError(MaxNestingDepthError.str());
289009467b48Spatrick   }
289109467b48Spatrick 
289209467b48Spatrick   MCAsmMacroArguments A;
289309467b48Spatrick   if (parseMacroArguments(M, A))
289409467b48Spatrick     return true;
289509467b48Spatrick 
289609467b48Spatrick   // Macro instantiation is lexical, unfortunately. We construct a new buffer
289709467b48Spatrick   // to hold the macro body with substitutions.
289809467b48Spatrick   SmallString<256> Buf;
289909467b48Spatrick   StringRef Body = M->Body;
290009467b48Spatrick   raw_svector_ostream OS(Buf);
290109467b48Spatrick 
290209467b48Spatrick   if (expandMacro(OS, Body, M->Parameters, A, true, getTok().getLoc()))
290309467b48Spatrick     return true;
290409467b48Spatrick 
290509467b48Spatrick   // We include the .endmacro in the buffer as our cue to exit the macro
290609467b48Spatrick   // instantiation.
290709467b48Spatrick   OS << ".endmacro\n";
290809467b48Spatrick 
290909467b48Spatrick   std::unique_ptr<MemoryBuffer> Instantiation =
291009467b48Spatrick       MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
291109467b48Spatrick 
291209467b48Spatrick   // Create the macro instantiation object and add to the current macro
291309467b48Spatrick   // instantiation stack.
291409467b48Spatrick   MacroInstantiation *MI = new MacroInstantiation{
291509467b48Spatrick       NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
291609467b48Spatrick   ActiveMacros.push_back(MI);
291709467b48Spatrick 
291809467b48Spatrick   ++NumOfMacroInstantiations;
291909467b48Spatrick 
292009467b48Spatrick   // Jump to the macro instantiation and prime the lexer.
292109467b48Spatrick   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
292209467b48Spatrick   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
292309467b48Spatrick   Lex();
292409467b48Spatrick 
292509467b48Spatrick   return false;
292609467b48Spatrick }
292709467b48Spatrick 
handleMacroExit()292809467b48Spatrick void AsmParser::handleMacroExit() {
292909467b48Spatrick   // Jump to the EndOfStatement we should return to, and consume it.
293009467b48Spatrick   jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
293109467b48Spatrick   Lex();
293209467b48Spatrick 
293309467b48Spatrick   // Pop the instantiation entry.
293409467b48Spatrick   delete ActiveMacros.back();
293509467b48Spatrick   ActiveMacros.pop_back();
293609467b48Spatrick }
293709467b48Spatrick 
parseAssignment(StringRef Name,AssignmentKind Kind)2938*a96b3639Srobert bool AsmParser::parseAssignment(StringRef Name, AssignmentKind Kind) {
293909467b48Spatrick   MCSymbol *Sym;
294009467b48Spatrick   const MCExpr *Value;
2941*a96b3639Srobert   SMLoc ExprLoc = getTok().getLoc();
2942*a96b3639Srobert   bool AllowRedef =
2943*a96b3639Srobert       Kind == AssignmentKind::Set || Kind == AssignmentKind::Equal;
2944*a96b3639Srobert   if (MCParserUtils::parseAssignmentExpression(Name, AllowRedef, *this, Sym,
294509467b48Spatrick                                                Value))
294609467b48Spatrick     return true;
294709467b48Spatrick 
294809467b48Spatrick   if (!Sym) {
294909467b48Spatrick     // In the case where we parse an expression starting with a '.', we will
295009467b48Spatrick     // not generate an error, nor will we create a symbol.  In this case we
295109467b48Spatrick     // should just return out.
295209467b48Spatrick     return false;
295309467b48Spatrick   }
295409467b48Spatrick 
2955a0747c9fSpatrick   if (discardLTOSymbol(Name))
2956a0747c9fSpatrick     return false;
2957a0747c9fSpatrick 
295809467b48Spatrick   // Do the assignment.
2959*a96b3639Srobert   switch (Kind) {
2960*a96b3639Srobert   case AssignmentKind::Equal:
2961097a140dSpatrick     Out.emitAssignment(Sym, Value);
2962*a96b3639Srobert     break;
2963*a96b3639Srobert   case AssignmentKind::Set:
2964*a96b3639Srobert   case AssignmentKind::Equiv:
2965*a96b3639Srobert     Out.emitAssignment(Sym, Value);
2966097a140dSpatrick     Out.emitSymbolAttribute(Sym, MCSA_NoDeadStrip);
2967*a96b3639Srobert     break;
2968*a96b3639Srobert   case AssignmentKind::LTOSetConditional:
2969*a96b3639Srobert     if (Value->getKind() != MCExpr::SymbolRef)
2970*a96b3639Srobert       return Error(ExprLoc, "expected identifier");
2971*a96b3639Srobert 
2972*a96b3639Srobert     Out.emitConditionalAssignment(Sym, Value);
2973*a96b3639Srobert     break;
2974*a96b3639Srobert   }
297509467b48Spatrick 
297609467b48Spatrick   return false;
297709467b48Spatrick }
297809467b48Spatrick 
297909467b48Spatrick /// parseIdentifier:
298009467b48Spatrick ///   ::= identifier
298109467b48Spatrick ///   ::= string
parseIdentifier(StringRef & Res)298209467b48Spatrick bool AsmParser::parseIdentifier(StringRef &Res) {
298309467b48Spatrick   // The assembler has relaxed rules for accepting identifiers, in particular we
298409467b48Spatrick   // allow things like '.globl $foo' and '.def @feat.00', which would normally be
298509467b48Spatrick   // separate tokens. At this level, we have already lexed so we cannot (currently)
298609467b48Spatrick   // handle this as a context dependent token, instead we detect adjacent tokens
298709467b48Spatrick   // and return the combined identifier.
298809467b48Spatrick   if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
298909467b48Spatrick     SMLoc PrefixLoc = getLexer().getLoc();
299009467b48Spatrick 
299109467b48Spatrick     // Consume the prefix character, and check for a following identifier.
299209467b48Spatrick 
299309467b48Spatrick     AsmToken Buf[1];
299409467b48Spatrick     Lexer.peekTokens(Buf, false);
299509467b48Spatrick 
2996097a140dSpatrick     if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer))
299709467b48Spatrick       return true;
299809467b48Spatrick 
2999097a140dSpatrick     // We have a '$' or '@' followed by an identifier or integer token, make
3000097a140dSpatrick     // sure they are adjacent.
300109467b48Spatrick     if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())
300209467b48Spatrick       return true;
300309467b48Spatrick 
300409467b48Spatrick     // eat $ or @
300509467b48Spatrick     Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
300609467b48Spatrick     // Construct the joined identifier and consume the token.
3007097a140dSpatrick     Res = StringRef(PrefixLoc.getPointer(), getTok().getString().size() + 1);
300809467b48Spatrick     Lex(); // Parser Lex to maintain invariants.
300909467b48Spatrick     return false;
301009467b48Spatrick   }
301109467b48Spatrick 
301209467b48Spatrick   if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
301309467b48Spatrick     return true;
301409467b48Spatrick 
301509467b48Spatrick   Res = getTok().getIdentifier();
301609467b48Spatrick 
301709467b48Spatrick   Lex(); // Consume the identifier token.
301809467b48Spatrick 
301909467b48Spatrick   return false;
302009467b48Spatrick }
302109467b48Spatrick 
302209467b48Spatrick /// parseDirectiveSet:
302309467b48Spatrick ///   ::= .equ identifier ',' expression
302409467b48Spatrick ///   ::= .equiv identifier ',' expression
302509467b48Spatrick ///   ::= .set identifier ',' expression
3026*a96b3639Srobert ///   ::= .lto_set_conditional identifier ',' expression
parseDirectiveSet(StringRef IDVal,AssignmentKind Kind)3027*a96b3639Srobert bool AsmParser::parseDirectiveSet(StringRef IDVal, AssignmentKind Kind) {
302809467b48Spatrick   StringRef Name;
3029a0747c9fSpatrick   if (check(parseIdentifier(Name), "expected identifier") || parseComma() ||
3030*a96b3639Srobert       parseAssignment(Name, Kind))
3031a0747c9fSpatrick     return true;
303209467b48Spatrick   return false;
303309467b48Spatrick }
303409467b48Spatrick 
parseEscapedString(std::string & Data)303509467b48Spatrick bool AsmParser::parseEscapedString(std::string &Data) {
303609467b48Spatrick   if (check(getTok().isNot(AsmToken::String), "expected string"))
303709467b48Spatrick     return true;
303809467b48Spatrick 
303909467b48Spatrick   Data = "";
304009467b48Spatrick   StringRef Str = getTok().getStringContents();
304109467b48Spatrick   for (unsigned i = 0, e = Str.size(); i != e; ++i) {
304209467b48Spatrick     if (Str[i] != '\\') {
304309467b48Spatrick       Data += Str[i];
304409467b48Spatrick       continue;
304509467b48Spatrick     }
304609467b48Spatrick 
304709467b48Spatrick     // Recognize escaped characters. Note that this escape semantics currently
304809467b48Spatrick     // loosely follows Darwin 'as'.
304909467b48Spatrick     ++i;
305009467b48Spatrick     if (i == e)
305109467b48Spatrick       return TokError("unexpected backslash at end of string");
305209467b48Spatrick 
305309467b48Spatrick     // Recognize hex sequences similarly to GNU 'as'.
305409467b48Spatrick     if (Str[i] == 'x' || Str[i] == 'X') {
305509467b48Spatrick       size_t length = Str.size();
305609467b48Spatrick       if (i + 1 >= length || !isHexDigit(Str[i + 1]))
305709467b48Spatrick         return TokError("invalid hexadecimal escape sequence");
305809467b48Spatrick 
305909467b48Spatrick       // Consume hex characters. GNU 'as' reads all hexadecimal characters and
306009467b48Spatrick       // then truncates to the lower 16 bits. Seems reasonable.
306109467b48Spatrick       unsigned Value = 0;
306209467b48Spatrick       while (i + 1 < length && isHexDigit(Str[i + 1]))
306309467b48Spatrick         Value = Value * 16 + hexDigitValue(Str[++i]);
306409467b48Spatrick 
306509467b48Spatrick       Data += (unsigned char)(Value & 0xFF);
306609467b48Spatrick       continue;
306709467b48Spatrick     }
306809467b48Spatrick 
306909467b48Spatrick     // Recognize octal sequences.
307009467b48Spatrick     if ((unsigned)(Str[i] - '0') <= 7) {
307109467b48Spatrick       // Consume up to three octal characters.
307209467b48Spatrick       unsigned Value = Str[i] - '0';
307309467b48Spatrick 
307409467b48Spatrick       if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
307509467b48Spatrick         ++i;
307609467b48Spatrick         Value = Value * 8 + (Str[i] - '0');
307709467b48Spatrick 
307809467b48Spatrick         if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
307909467b48Spatrick           ++i;
308009467b48Spatrick           Value = Value * 8 + (Str[i] - '0');
308109467b48Spatrick         }
308209467b48Spatrick       }
308309467b48Spatrick 
308409467b48Spatrick       if (Value > 255)
308509467b48Spatrick         return TokError("invalid octal escape sequence (out of range)");
308609467b48Spatrick 
308709467b48Spatrick       Data += (unsigned char)Value;
308809467b48Spatrick       continue;
308909467b48Spatrick     }
309009467b48Spatrick 
309109467b48Spatrick     // Otherwise recognize individual escapes.
309209467b48Spatrick     switch (Str[i]) {
309309467b48Spatrick     default:
309409467b48Spatrick       // Just reject invalid escape sequences for now.
309509467b48Spatrick       return TokError("invalid escape sequence (unrecognized character)");
309609467b48Spatrick 
309709467b48Spatrick     case 'b': Data += '\b'; break;
309809467b48Spatrick     case 'f': Data += '\f'; break;
309909467b48Spatrick     case 'n': Data += '\n'; break;
310009467b48Spatrick     case 'r': Data += '\r'; break;
310109467b48Spatrick     case 't': Data += '\t'; break;
310209467b48Spatrick     case '"': Data += '"'; break;
310309467b48Spatrick     case '\\': Data += '\\'; break;
310409467b48Spatrick     }
310509467b48Spatrick   }
310609467b48Spatrick 
310709467b48Spatrick   Lex();
310809467b48Spatrick   return false;
310909467b48Spatrick }
311009467b48Spatrick 
parseAngleBracketString(std::string & Data)3111097a140dSpatrick bool AsmParser::parseAngleBracketString(std::string &Data) {
3112097a140dSpatrick   SMLoc EndLoc, StartLoc = getTok().getLoc();
3113097a140dSpatrick   if (isAngleBracketString(StartLoc, EndLoc)) {
3114097a140dSpatrick     const char *StartChar = StartLoc.getPointer() + 1;
3115097a140dSpatrick     const char *EndChar = EndLoc.getPointer() - 1;
3116097a140dSpatrick     jumpToLoc(EndLoc, CurBuffer);
3117097a140dSpatrick     /// Eat from '<' to '>'
3118097a140dSpatrick     Lex();
3119097a140dSpatrick 
3120097a140dSpatrick     Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
3121097a140dSpatrick     return false;
3122097a140dSpatrick   }
3123097a140dSpatrick   return true;
3124097a140dSpatrick }
3125097a140dSpatrick 
312609467b48Spatrick /// parseDirectiveAscii:
3127a0747c9fSpatrick //    ::= .ascii [ "string"+ ( , "string"+ )* ]
3128a0747c9fSpatrick ///   ::= ( .asciz | .string ) [ "string" ( , "string" )* ]
parseDirectiveAscii(StringRef IDVal,bool ZeroTerminated)312909467b48Spatrick bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
313009467b48Spatrick   auto parseOp = [&]() -> bool {
313109467b48Spatrick     std::string Data;
3132a0747c9fSpatrick     if (checkForValidSection())
3133a0747c9fSpatrick       return true;
3134a0747c9fSpatrick     // Only support spaces as separators for .ascii directive for now. See the
3135a0747c9fSpatrick     // discusssion at https://reviews.llvm.org/D91460 for more details.
3136a0747c9fSpatrick     do {
3137a0747c9fSpatrick       if (parseEscapedString(Data))
313809467b48Spatrick         return true;
3139097a140dSpatrick       getStreamer().emitBytes(Data);
3140a0747c9fSpatrick     } while (!ZeroTerminated && getTok().is(AsmToken::String));
314109467b48Spatrick     if (ZeroTerminated)
3142097a140dSpatrick       getStreamer().emitBytes(StringRef("\0", 1));
314309467b48Spatrick     return false;
314409467b48Spatrick   };
314509467b48Spatrick 
3146a0747c9fSpatrick   return parseMany(parseOp);
314709467b48Spatrick }
314809467b48Spatrick 
314909467b48Spatrick /// parseDirectiveReloc
315009467b48Spatrick ///  ::= .reloc expression , identifier [ , expression ]
parseDirectiveReloc(SMLoc DirectiveLoc)315109467b48Spatrick bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
315209467b48Spatrick   const MCExpr *Offset;
315309467b48Spatrick   const MCExpr *Expr = nullptr;
315409467b48Spatrick   SMLoc OffsetLoc = Lexer.getTok().getLoc();
315509467b48Spatrick 
315609467b48Spatrick   if (parseExpression(Offset))
315709467b48Spatrick     return true;
3158a0747c9fSpatrick   if (parseComma() ||
3159097a140dSpatrick       check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
316009467b48Spatrick     return true;
316109467b48Spatrick 
316209467b48Spatrick   SMLoc NameLoc = Lexer.getTok().getLoc();
316309467b48Spatrick   StringRef Name = Lexer.getTok().getIdentifier();
316409467b48Spatrick   Lex();
316509467b48Spatrick 
316609467b48Spatrick   if (Lexer.is(AsmToken::Comma)) {
316709467b48Spatrick     Lex();
316809467b48Spatrick     SMLoc ExprLoc = Lexer.getLoc();
316909467b48Spatrick     if (parseExpression(Expr))
317009467b48Spatrick       return true;
317109467b48Spatrick 
317209467b48Spatrick     MCValue Value;
317309467b48Spatrick     if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr))
317409467b48Spatrick       return Error(ExprLoc, "expression must be relocatable");
317509467b48Spatrick   }
317609467b48Spatrick 
3177a0747c9fSpatrick   if (parseEOL())
317809467b48Spatrick     return true;
317909467b48Spatrick 
318009467b48Spatrick   const MCTargetAsmParser &MCT = getTargetParser();
318109467b48Spatrick   const MCSubtargetInfo &STI = MCT.getSTI();
3182*a96b3639Srobert   if (std::optional<std::pair<bool, std::string>> Err =
3183097a140dSpatrick           getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc,
3184097a140dSpatrick                                            STI))
3185097a140dSpatrick     return Error(Err->first ? NameLoc : OffsetLoc, Err->second);
318609467b48Spatrick 
318709467b48Spatrick   return false;
318809467b48Spatrick }
318909467b48Spatrick 
319009467b48Spatrick /// parseDirectiveValue
319109467b48Spatrick ///  ::= (.byte | .short | ... ) [ expression (, expression)* ]
parseDirectiveValue(StringRef IDVal,unsigned Size)319209467b48Spatrick bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
319309467b48Spatrick   auto parseOp = [&]() -> bool {
319409467b48Spatrick     const MCExpr *Value;
319509467b48Spatrick     SMLoc ExprLoc = getLexer().getLoc();
319609467b48Spatrick     if (checkForValidSection() || parseExpression(Value))
319709467b48Spatrick       return true;
319809467b48Spatrick     // Special case constant expressions to match code generator.
319909467b48Spatrick     if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
320009467b48Spatrick       assert(Size <= 8 && "Invalid size");
320109467b48Spatrick       uint64_t IntValue = MCE->getValue();
320209467b48Spatrick       if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
320309467b48Spatrick         return Error(ExprLoc, "out of range literal value");
3204097a140dSpatrick       getStreamer().emitIntValue(IntValue, Size);
320509467b48Spatrick     } else
3206097a140dSpatrick       getStreamer().emitValue(Value, Size, ExprLoc);
320709467b48Spatrick     return false;
320809467b48Spatrick   };
320909467b48Spatrick 
3210a0747c9fSpatrick   return parseMany(parseOp);
321109467b48Spatrick }
321209467b48Spatrick 
parseHexOcta(AsmParser & Asm,uint64_t & hi,uint64_t & lo)321309467b48Spatrick static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {
321409467b48Spatrick   if (Asm.getTok().isNot(AsmToken::Integer) &&
321509467b48Spatrick       Asm.getTok().isNot(AsmToken::BigNum))
321609467b48Spatrick     return Asm.TokError("unknown token in expression");
321709467b48Spatrick   SMLoc ExprLoc = Asm.getTok().getLoc();
321809467b48Spatrick   APInt IntValue = Asm.getTok().getAPIntVal();
321909467b48Spatrick   Asm.Lex();
322009467b48Spatrick   if (!IntValue.isIntN(128))
322109467b48Spatrick     return Asm.Error(ExprLoc, "out of range literal value");
322209467b48Spatrick   if (!IntValue.isIntN(64)) {
322309467b48Spatrick     hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
322409467b48Spatrick     lo = IntValue.getLoBits(64).getZExtValue();
322509467b48Spatrick   } else {
322609467b48Spatrick     hi = 0;
322709467b48Spatrick     lo = IntValue.getZExtValue();
322809467b48Spatrick   }
322909467b48Spatrick   return false;
323009467b48Spatrick }
323109467b48Spatrick 
323209467b48Spatrick /// ParseDirectiveOctaValue
323309467b48Spatrick ///  ::= .octa [ hexconstant (, hexconstant)* ]
323409467b48Spatrick 
parseDirectiveOctaValue(StringRef IDVal)323509467b48Spatrick bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
323609467b48Spatrick   auto parseOp = [&]() -> bool {
323709467b48Spatrick     if (checkForValidSection())
323809467b48Spatrick       return true;
323909467b48Spatrick     uint64_t hi, lo;
324009467b48Spatrick     if (parseHexOcta(*this, hi, lo))
324109467b48Spatrick       return true;
324209467b48Spatrick     if (MAI.isLittleEndian()) {
3243097a140dSpatrick       getStreamer().emitInt64(lo);
3244097a140dSpatrick       getStreamer().emitInt64(hi);
324509467b48Spatrick     } else {
3246097a140dSpatrick       getStreamer().emitInt64(hi);
3247097a140dSpatrick       getStreamer().emitInt64(lo);
324809467b48Spatrick     }
324909467b48Spatrick     return false;
325009467b48Spatrick   };
325109467b48Spatrick 
3252a0747c9fSpatrick   return parseMany(parseOp);
325309467b48Spatrick }
325409467b48Spatrick 
parseRealValue(const fltSemantics & Semantics,APInt & Res)325509467b48Spatrick bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
325609467b48Spatrick   // We don't truly support arithmetic on floating point expressions, so we
325709467b48Spatrick   // have to manually parse unary prefixes.
325809467b48Spatrick   bool IsNeg = false;
325909467b48Spatrick   if (getLexer().is(AsmToken::Minus)) {
326009467b48Spatrick     Lexer.Lex();
326109467b48Spatrick     IsNeg = true;
326209467b48Spatrick   } else if (getLexer().is(AsmToken::Plus))
326309467b48Spatrick     Lexer.Lex();
326409467b48Spatrick 
326509467b48Spatrick   if (Lexer.is(AsmToken::Error))
326609467b48Spatrick     return TokError(Lexer.getErr());
326709467b48Spatrick   if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
326809467b48Spatrick       Lexer.isNot(AsmToken::Identifier))
326909467b48Spatrick     return TokError("unexpected token in directive");
327009467b48Spatrick 
327109467b48Spatrick   // Convert to an APFloat.
327209467b48Spatrick   APFloat Value(Semantics);
327309467b48Spatrick   StringRef IDVal = getTok().getString();
327409467b48Spatrick   if (getLexer().is(AsmToken::Identifier)) {
3275a0747c9fSpatrick     if (!IDVal.compare_insensitive("infinity") ||
3276a0747c9fSpatrick         !IDVal.compare_insensitive("inf"))
327709467b48Spatrick       Value = APFloat::getInf(Semantics);
3278a0747c9fSpatrick     else if (!IDVal.compare_insensitive("nan"))
327909467b48Spatrick       Value = APFloat::getNaN(Semantics, false, ~0);
328009467b48Spatrick     else
328109467b48Spatrick       return TokError("invalid floating point literal");
328209467b48Spatrick   } else if (errorToBool(
328309467b48Spatrick                  Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
328409467b48Spatrick                      .takeError()))
328509467b48Spatrick     return TokError("invalid floating point literal");
328609467b48Spatrick   if (IsNeg)
328709467b48Spatrick     Value.changeSign();
328809467b48Spatrick 
328909467b48Spatrick   // Consume the numeric token.
329009467b48Spatrick   Lex();
329109467b48Spatrick 
329209467b48Spatrick   Res = Value.bitcastToAPInt();
329309467b48Spatrick 
329409467b48Spatrick   return false;
329509467b48Spatrick }
329609467b48Spatrick 
329709467b48Spatrick /// parseDirectiveRealValue
329809467b48Spatrick ///  ::= (.single | .double) [ expression (, expression)* ]
parseDirectiveRealValue(StringRef IDVal,const fltSemantics & Semantics)329909467b48Spatrick bool AsmParser::parseDirectiveRealValue(StringRef IDVal,
330009467b48Spatrick                                         const fltSemantics &Semantics) {
330109467b48Spatrick   auto parseOp = [&]() -> bool {
330209467b48Spatrick     APInt AsInt;
330309467b48Spatrick     if (checkForValidSection() || parseRealValue(Semantics, AsInt))
330409467b48Spatrick       return true;
3305097a140dSpatrick     getStreamer().emitIntValue(AsInt.getLimitedValue(),
330609467b48Spatrick                                AsInt.getBitWidth() / 8);
330709467b48Spatrick     return false;
330809467b48Spatrick   };
330909467b48Spatrick 
3310a0747c9fSpatrick   return parseMany(parseOp);
331109467b48Spatrick }
331209467b48Spatrick 
331309467b48Spatrick /// parseDirectiveZero
331409467b48Spatrick ///  ::= .zero expression
parseDirectiveZero()331509467b48Spatrick bool AsmParser::parseDirectiveZero() {
331609467b48Spatrick   SMLoc NumBytesLoc = Lexer.getLoc();
331709467b48Spatrick   const MCExpr *NumBytes;
331809467b48Spatrick   if (checkForValidSection() || parseExpression(NumBytes))
331909467b48Spatrick     return true;
332009467b48Spatrick 
332109467b48Spatrick   int64_t Val = 0;
332209467b48Spatrick   if (getLexer().is(AsmToken::Comma)) {
332309467b48Spatrick     Lex();
332409467b48Spatrick     if (parseAbsoluteExpression(Val))
332509467b48Spatrick       return true;
332609467b48Spatrick   }
332709467b48Spatrick 
3328a0747c9fSpatrick   if (parseEOL())
332909467b48Spatrick     return true;
333009467b48Spatrick   getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);
333109467b48Spatrick 
333209467b48Spatrick   return false;
333309467b48Spatrick }
333409467b48Spatrick 
333509467b48Spatrick /// parseDirectiveFill
333609467b48Spatrick ///  ::= .fill expression [ , expression [ , expression ] ]
parseDirectiveFill()333709467b48Spatrick bool AsmParser::parseDirectiveFill() {
333809467b48Spatrick   SMLoc NumValuesLoc = Lexer.getLoc();
333909467b48Spatrick   const MCExpr *NumValues;
334009467b48Spatrick   if (checkForValidSection() || parseExpression(NumValues))
334109467b48Spatrick     return true;
334209467b48Spatrick 
334309467b48Spatrick   int64_t FillSize = 1;
334409467b48Spatrick   int64_t FillExpr = 0;
334509467b48Spatrick 
334609467b48Spatrick   SMLoc SizeLoc, ExprLoc;
334709467b48Spatrick 
334809467b48Spatrick   if (parseOptionalToken(AsmToken::Comma)) {
334909467b48Spatrick     SizeLoc = getTok().getLoc();
335009467b48Spatrick     if (parseAbsoluteExpression(FillSize))
335109467b48Spatrick       return true;
335209467b48Spatrick     if (parseOptionalToken(AsmToken::Comma)) {
335309467b48Spatrick       ExprLoc = getTok().getLoc();
335409467b48Spatrick       if (parseAbsoluteExpression(FillExpr))
335509467b48Spatrick         return true;
335609467b48Spatrick     }
335709467b48Spatrick   }
3358a0747c9fSpatrick   if (parseEOL())
335909467b48Spatrick     return true;
336009467b48Spatrick 
336109467b48Spatrick   if (FillSize < 0) {
336209467b48Spatrick     Warning(SizeLoc, "'.fill' directive with negative size has no effect");
336309467b48Spatrick     return false;
336409467b48Spatrick   }
336509467b48Spatrick   if (FillSize > 8) {
336609467b48Spatrick     Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
336709467b48Spatrick     FillSize = 8;
336809467b48Spatrick   }
336909467b48Spatrick 
337009467b48Spatrick   if (!isUInt<32>(FillExpr) && FillSize > 4)
337109467b48Spatrick     Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
337209467b48Spatrick 
337309467b48Spatrick   getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);
337409467b48Spatrick 
337509467b48Spatrick   return false;
337609467b48Spatrick }
337709467b48Spatrick 
337809467b48Spatrick /// parseDirectiveOrg
337909467b48Spatrick ///  ::= .org expression [ , expression ]
parseDirectiveOrg()338009467b48Spatrick bool AsmParser::parseDirectiveOrg() {
338109467b48Spatrick   const MCExpr *Offset;
338209467b48Spatrick   SMLoc OffsetLoc = Lexer.getLoc();
338309467b48Spatrick   if (checkForValidSection() || parseExpression(Offset))
338409467b48Spatrick     return true;
338509467b48Spatrick 
338609467b48Spatrick   // Parse optional fill expression.
338709467b48Spatrick   int64_t FillExpr = 0;
338809467b48Spatrick   if (parseOptionalToken(AsmToken::Comma))
338909467b48Spatrick     if (parseAbsoluteExpression(FillExpr))
3390a0747c9fSpatrick       return true;
3391a0747c9fSpatrick   if (parseEOL())
3392a0747c9fSpatrick     return true;
339309467b48Spatrick 
339409467b48Spatrick   getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
339509467b48Spatrick   return false;
339609467b48Spatrick }
339709467b48Spatrick 
339809467b48Spatrick /// parseDirectiveAlign
339909467b48Spatrick ///  ::= {.align, ...} expression [ , expression [ , expression ]]
parseDirectiveAlign(bool IsPow2,unsigned ValueSize)340009467b48Spatrick bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
340109467b48Spatrick   SMLoc AlignmentLoc = getLexer().getLoc();
340209467b48Spatrick   int64_t Alignment;
340309467b48Spatrick   SMLoc MaxBytesLoc;
340409467b48Spatrick   bool HasFillExpr = false;
340509467b48Spatrick   int64_t FillExpr = 0;
340609467b48Spatrick   int64_t MaxBytesToFill = 0;
340709467b48Spatrick 
340809467b48Spatrick   auto parseAlign = [&]() -> bool {
340909467b48Spatrick     if (parseAbsoluteExpression(Alignment))
341009467b48Spatrick       return true;
341109467b48Spatrick     if (parseOptionalToken(AsmToken::Comma)) {
341209467b48Spatrick       // The fill expression can be omitted while specifying a maximum number of
341309467b48Spatrick       // alignment bytes, e.g:
341409467b48Spatrick       //  .align 3,,4
341509467b48Spatrick       if (getTok().isNot(AsmToken::Comma)) {
341609467b48Spatrick         HasFillExpr = true;
341709467b48Spatrick         if (parseAbsoluteExpression(FillExpr))
341809467b48Spatrick           return true;
341909467b48Spatrick       }
342009467b48Spatrick       if (parseOptionalToken(AsmToken::Comma))
342109467b48Spatrick         if (parseTokenLoc(MaxBytesLoc) ||
342209467b48Spatrick             parseAbsoluteExpression(MaxBytesToFill))
342309467b48Spatrick           return true;
342409467b48Spatrick     }
3425a0747c9fSpatrick     return parseEOL();
342609467b48Spatrick   };
342709467b48Spatrick 
342809467b48Spatrick   if (checkForValidSection())
3429a0747c9fSpatrick     return true;
343009467b48Spatrick   // Ignore empty '.p2align' directives for GNU-as compatibility
343109467b48Spatrick   if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
343209467b48Spatrick     Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
3433a0747c9fSpatrick     return parseEOL();
343409467b48Spatrick   }
343509467b48Spatrick   if (parseAlign())
3436a0747c9fSpatrick     return true;
343709467b48Spatrick 
343809467b48Spatrick   // Always emit an alignment here even if we thrown an error.
343909467b48Spatrick   bool ReturnVal = false;
344009467b48Spatrick 
344109467b48Spatrick   // Compute alignment in bytes.
344209467b48Spatrick   if (IsPow2) {
344309467b48Spatrick     // FIXME: Diagnose overflow.
344409467b48Spatrick     if (Alignment >= 32) {
344509467b48Spatrick       ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
344609467b48Spatrick       Alignment = 31;
344709467b48Spatrick     }
344809467b48Spatrick 
344909467b48Spatrick     Alignment = 1ULL << Alignment;
345009467b48Spatrick   } else {
345109467b48Spatrick     // Reject alignments that aren't either a power of two or zero,
345209467b48Spatrick     // for gas compatibility. Alignment of zero is silently rounded
345309467b48Spatrick     // up to one.
345409467b48Spatrick     if (Alignment == 0)
345509467b48Spatrick       Alignment = 1;
3456*a96b3639Srobert     else if (!isPowerOf2_64(Alignment)) {
345709467b48Spatrick       ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
3458*a96b3639Srobert       Alignment = PowerOf2Floor(Alignment);
3459*a96b3639Srobert     }
3460*a96b3639Srobert     if (!isUInt<32>(Alignment)) {
3461a0747c9fSpatrick       ReturnVal |= Error(AlignmentLoc, "alignment must be smaller than 2**32");
3462*a96b3639Srobert       Alignment = 1u << 31;
3463*a96b3639Srobert     }
346409467b48Spatrick   }
346509467b48Spatrick 
346609467b48Spatrick   // Diagnose non-sensical max bytes to align.
346709467b48Spatrick   if (MaxBytesLoc.isValid()) {
346809467b48Spatrick     if (MaxBytesToFill < 1) {
346909467b48Spatrick       ReturnVal |= Error(MaxBytesLoc,
347009467b48Spatrick                          "alignment directive can never be satisfied in this "
347109467b48Spatrick                          "many bytes, ignoring maximum bytes expression");
347209467b48Spatrick       MaxBytesToFill = 0;
347309467b48Spatrick     }
347409467b48Spatrick 
347509467b48Spatrick     if (MaxBytesToFill >= Alignment) {
347609467b48Spatrick       Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
347709467b48Spatrick                            "has no effect");
347809467b48Spatrick       MaxBytesToFill = 0;
347909467b48Spatrick     }
348009467b48Spatrick   }
348109467b48Spatrick 
348209467b48Spatrick   // Check whether we should use optimal code alignment for this .align
348309467b48Spatrick   // directive.
348409467b48Spatrick   const MCSection *Section = getStreamer().getCurrentSectionOnly();
348509467b48Spatrick   assert(Section && "must have section to emit alignment");
3486*a96b3639Srobert   bool useCodeAlign = Section->useCodeAlign();
348709467b48Spatrick   if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
3488*a96b3639Srobert       ValueSize == 1 && useCodeAlign) {
3489*a96b3639Srobert     getStreamer().emitCodeAlignment(
3490*a96b3639Srobert         Align(Alignment), &getTargetParser().getSTI(), MaxBytesToFill);
349109467b48Spatrick   } else {
349209467b48Spatrick     // FIXME: Target specific behavior about how the "extra" bytes are filled.
3493*a96b3639Srobert     getStreamer().emitValueToAlignment(Align(Alignment), FillExpr, ValueSize,
349409467b48Spatrick                                        MaxBytesToFill);
349509467b48Spatrick   }
349609467b48Spatrick 
349709467b48Spatrick   return ReturnVal;
349809467b48Spatrick }
349909467b48Spatrick 
350009467b48Spatrick /// parseDirectiveFile
350109467b48Spatrick /// ::= .file filename
350209467b48Spatrick /// ::= .file number [directory] filename [md5 checksum] [source source-text]
parseDirectiveFile(SMLoc DirectiveLoc)350309467b48Spatrick bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
350409467b48Spatrick   // FIXME: I'm not sure what this is.
350509467b48Spatrick   int64_t FileNumber = -1;
350609467b48Spatrick   if (getLexer().is(AsmToken::Integer)) {
350709467b48Spatrick     FileNumber = getTok().getIntVal();
350809467b48Spatrick     Lex();
350909467b48Spatrick 
351009467b48Spatrick     if (FileNumber < 0)
351109467b48Spatrick       return TokError("negative file number");
351209467b48Spatrick   }
351309467b48Spatrick 
351409467b48Spatrick   std::string Path;
351509467b48Spatrick 
351609467b48Spatrick   // Usually the directory and filename together, otherwise just the directory.
351709467b48Spatrick   // Allow the strings to have escaped octal character sequence.
3518a0747c9fSpatrick   if (parseEscapedString(Path))
351909467b48Spatrick     return true;
352009467b48Spatrick 
352109467b48Spatrick   StringRef Directory;
352209467b48Spatrick   StringRef Filename;
352309467b48Spatrick   std::string FilenameData;
352409467b48Spatrick   if (getLexer().is(AsmToken::String)) {
352509467b48Spatrick     if (check(FileNumber == -1,
352609467b48Spatrick               "explicit path specified, but no file number") ||
352709467b48Spatrick         parseEscapedString(FilenameData))
352809467b48Spatrick       return true;
352909467b48Spatrick     Filename = FilenameData;
353009467b48Spatrick     Directory = Path;
353109467b48Spatrick   } else {
353209467b48Spatrick     Filename = Path;
353309467b48Spatrick   }
353409467b48Spatrick 
353509467b48Spatrick   uint64_t MD5Hi, MD5Lo;
353609467b48Spatrick   bool HasMD5 = false;
353709467b48Spatrick 
3538*a96b3639Srobert   std::optional<StringRef> Source;
353909467b48Spatrick   bool HasSource = false;
354009467b48Spatrick   std::string SourceString;
354109467b48Spatrick 
354209467b48Spatrick   while (!parseOptionalToken(AsmToken::EndOfStatement)) {
354309467b48Spatrick     StringRef Keyword;
354409467b48Spatrick     if (check(getTok().isNot(AsmToken::Identifier),
354509467b48Spatrick               "unexpected token in '.file' directive") ||
354609467b48Spatrick         parseIdentifier(Keyword))
354709467b48Spatrick       return true;
354809467b48Spatrick     if (Keyword == "md5") {
354909467b48Spatrick       HasMD5 = true;
355009467b48Spatrick       if (check(FileNumber == -1,
355109467b48Spatrick                 "MD5 checksum specified, but no file number") ||
355209467b48Spatrick           parseHexOcta(*this, MD5Hi, MD5Lo))
355309467b48Spatrick         return true;
355409467b48Spatrick     } else if (Keyword == "source") {
355509467b48Spatrick       HasSource = true;
355609467b48Spatrick       if (check(FileNumber == -1,
355709467b48Spatrick                 "source specified, but no file number") ||
355809467b48Spatrick           check(getTok().isNot(AsmToken::String),
355909467b48Spatrick                 "unexpected token in '.file' directive") ||
356009467b48Spatrick           parseEscapedString(SourceString))
356109467b48Spatrick         return true;
356209467b48Spatrick     } else {
356309467b48Spatrick       return TokError("unexpected token in '.file' directive");
356409467b48Spatrick     }
356509467b48Spatrick   }
356609467b48Spatrick 
356709467b48Spatrick   if (FileNumber == -1) {
356809467b48Spatrick     // Ignore the directive if there is no number and the target doesn't support
356909467b48Spatrick     // numberless .file directives. This allows some portability of assembler
357009467b48Spatrick     // between different object file formats.
357109467b48Spatrick     if (getContext().getAsmInfo()->hasSingleParameterDotFile())
3572097a140dSpatrick       getStreamer().emitFileDirective(Filename);
357309467b48Spatrick   } else {
357409467b48Spatrick     // In case there is a -g option as well as debug info from directive .file,
357509467b48Spatrick     // we turn off the -g option, directly use the existing debug info instead.
357609467b48Spatrick     // Throw away any implicit file table for the assembler source.
357709467b48Spatrick     if (Ctx.getGenDwarfForAssembly()) {
357809467b48Spatrick       Ctx.getMCDwarfLineTable(0).resetFileTable();
357909467b48Spatrick       Ctx.setGenDwarfForAssembly(false);
358009467b48Spatrick     }
358109467b48Spatrick 
3582*a96b3639Srobert     std::optional<MD5::MD5Result> CKMem;
358309467b48Spatrick     if (HasMD5) {
358409467b48Spatrick       MD5::MD5Result Sum;
358509467b48Spatrick       for (unsigned i = 0; i != 8; ++i) {
3586*a96b3639Srobert         Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
3587*a96b3639Srobert         Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
358809467b48Spatrick       }
358909467b48Spatrick       CKMem = Sum;
359009467b48Spatrick     }
359109467b48Spatrick     if (HasSource) {
359209467b48Spatrick       char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
359309467b48Spatrick       memcpy(SourceBuf, SourceString.data(), SourceString.size());
359409467b48Spatrick       Source = StringRef(SourceBuf, SourceString.size());
359509467b48Spatrick     }
359609467b48Spatrick     if (FileNumber == 0) {
3597a0747c9fSpatrick       // Upgrade to Version 5 for assembly actions like clang -c a.s.
359809467b48Spatrick       if (Ctx.getDwarfVersion() < 5)
3599a0747c9fSpatrick         Ctx.setDwarfVersion(5);
360009467b48Spatrick       getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
360109467b48Spatrick     } else {
360209467b48Spatrick       Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
360309467b48Spatrick           FileNumber, Directory, Filename, CKMem, Source);
360409467b48Spatrick       if (!FileNumOrErr)
360509467b48Spatrick         return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
360609467b48Spatrick     }
360709467b48Spatrick     // Alert the user if there are some .file directives with MD5 and some not.
360809467b48Spatrick     // But only do that once.
360909467b48Spatrick     if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
361009467b48Spatrick       ReportedInconsistentMD5 = true;
361109467b48Spatrick       return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
361209467b48Spatrick     }
361309467b48Spatrick   }
361409467b48Spatrick 
361509467b48Spatrick   return false;
361609467b48Spatrick }
361709467b48Spatrick 
361809467b48Spatrick /// parseDirectiveLine
361909467b48Spatrick /// ::= .line [number]
parseDirectiveLine()362009467b48Spatrick bool AsmParser::parseDirectiveLine() {
362109467b48Spatrick   int64_t LineNumber;
362209467b48Spatrick   if (getLexer().is(AsmToken::Integer)) {
362309467b48Spatrick     if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
362409467b48Spatrick       return true;
362509467b48Spatrick     (void)LineNumber;
362609467b48Spatrick     // FIXME: Do something with the .line.
362709467b48Spatrick   }
3628a0747c9fSpatrick   return parseEOL();
362909467b48Spatrick }
363009467b48Spatrick 
363109467b48Spatrick /// parseDirectiveLoc
363209467b48Spatrick /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
363309467b48Spatrick ///                                [epilogue_begin] [is_stmt VALUE] [isa VALUE]
363409467b48Spatrick /// The first number is a file number, must have been previously assigned with
363509467b48Spatrick /// a .file directive, the second number is the line number and optionally the
363609467b48Spatrick /// third number is a column position (zero if not specified).  The remaining
363709467b48Spatrick /// optional items are .loc sub-directives.
parseDirectiveLoc()363809467b48Spatrick bool AsmParser::parseDirectiveLoc() {
363909467b48Spatrick   int64_t FileNumber = 0, LineNumber = 0;
364009467b48Spatrick   SMLoc Loc = getTok().getLoc();
364109467b48Spatrick   if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
364209467b48Spatrick       check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
364309467b48Spatrick             "file number less than one in '.loc' directive") ||
364409467b48Spatrick       check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
364509467b48Spatrick             "unassigned file number in '.loc' directive"))
364609467b48Spatrick     return true;
364709467b48Spatrick 
364809467b48Spatrick   // optional
364909467b48Spatrick   if (getLexer().is(AsmToken::Integer)) {
365009467b48Spatrick     LineNumber = getTok().getIntVal();
365109467b48Spatrick     if (LineNumber < 0)
365209467b48Spatrick       return TokError("line number less than zero in '.loc' directive");
365309467b48Spatrick     Lex();
365409467b48Spatrick   }
365509467b48Spatrick 
365609467b48Spatrick   int64_t ColumnPos = 0;
365709467b48Spatrick   if (getLexer().is(AsmToken::Integer)) {
365809467b48Spatrick     ColumnPos = getTok().getIntVal();
365909467b48Spatrick     if (ColumnPos < 0)
366009467b48Spatrick       return TokError("column position less than zero in '.loc' directive");
366109467b48Spatrick     Lex();
366209467b48Spatrick   }
366309467b48Spatrick 
3664097a140dSpatrick   auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
3665097a140dSpatrick   unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
366609467b48Spatrick   unsigned Isa = 0;
366709467b48Spatrick   int64_t Discriminator = 0;
366809467b48Spatrick 
366909467b48Spatrick   auto parseLocOp = [&]() -> bool {
367009467b48Spatrick     StringRef Name;
367109467b48Spatrick     SMLoc Loc = getTok().getLoc();
367209467b48Spatrick     if (parseIdentifier(Name))
367309467b48Spatrick       return TokError("unexpected token in '.loc' directive");
367409467b48Spatrick 
367509467b48Spatrick     if (Name == "basic_block")
367609467b48Spatrick       Flags |= DWARF2_FLAG_BASIC_BLOCK;
367709467b48Spatrick     else if (Name == "prologue_end")
367809467b48Spatrick       Flags |= DWARF2_FLAG_PROLOGUE_END;
367909467b48Spatrick     else if (Name == "epilogue_begin")
368009467b48Spatrick       Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
368109467b48Spatrick     else if (Name == "is_stmt") {
368209467b48Spatrick       Loc = getTok().getLoc();
368309467b48Spatrick       const MCExpr *Value;
368409467b48Spatrick       if (parseExpression(Value))
368509467b48Spatrick         return true;
368609467b48Spatrick       // The expression must be the constant 0 or 1.
368709467b48Spatrick       if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
368809467b48Spatrick         int Value = MCE->getValue();
368909467b48Spatrick         if (Value == 0)
369009467b48Spatrick           Flags &= ~DWARF2_FLAG_IS_STMT;
369109467b48Spatrick         else if (Value == 1)
369209467b48Spatrick           Flags |= DWARF2_FLAG_IS_STMT;
369309467b48Spatrick         else
369409467b48Spatrick           return Error(Loc, "is_stmt value not 0 or 1");
369509467b48Spatrick       } else {
369609467b48Spatrick         return Error(Loc, "is_stmt value not the constant value of 0 or 1");
369709467b48Spatrick       }
369809467b48Spatrick     } else if (Name == "isa") {
369909467b48Spatrick       Loc = getTok().getLoc();
370009467b48Spatrick       const MCExpr *Value;
370109467b48Spatrick       if (parseExpression(Value))
370209467b48Spatrick         return true;
370309467b48Spatrick       // The expression must be a constant greater or equal to 0.
370409467b48Spatrick       if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
370509467b48Spatrick         int Value = MCE->getValue();
370609467b48Spatrick         if (Value < 0)
370709467b48Spatrick           return Error(Loc, "isa number less than zero");
370809467b48Spatrick         Isa = Value;
370909467b48Spatrick       } else {
371009467b48Spatrick         return Error(Loc, "isa number not a constant value");
371109467b48Spatrick       }
371209467b48Spatrick     } else if (Name == "discriminator") {
371309467b48Spatrick       if (parseAbsoluteExpression(Discriminator))
371409467b48Spatrick         return true;
371509467b48Spatrick     } else {
371609467b48Spatrick       return Error(Loc, "unknown sub-directive in '.loc' directive");
371709467b48Spatrick     }
371809467b48Spatrick     return false;
371909467b48Spatrick   };
372009467b48Spatrick 
372109467b48Spatrick   if (parseMany(parseLocOp, false /*hasComma*/))
372209467b48Spatrick     return true;
372309467b48Spatrick 
3724097a140dSpatrick   getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
372509467b48Spatrick                                       Isa, Discriminator, StringRef());
372609467b48Spatrick 
372709467b48Spatrick   return false;
372809467b48Spatrick }
372909467b48Spatrick 
373009467b48Spatrick /// parseDirectiveStabs
373109467b48Spatrick /// ::= .stabs string, number, number, number
parseDirectiveStabs()373209467b48Spatrick bool AsmParser::parseDirectiveStabs() {
373309467b48Spatrick   return TokError("unsupported directive '.stabs'");
373409467b48Spatrick }
373509467b48Spatrick 
373609467b48Spatrick /// parseDirectiveCVFile
373709467b48Spatrick /// ::= .cv_file number filename [checksum] [checksumkind]
parseDirectiveCVFile()373809467b48Spatrick bool AsmParser::parseDirectiveCVFile() {
373909467b48Spatrick   SMLoc FileNumberLoc = getTok().getLoc();
374009467b48Spatrick   int64_t FileNumber;
374109467b48Spatrick   std::string Filename;
374209467b48Spatrick   std::string Checksum;
374309467b48Spatrick   int64_t ChecksumKind = 0;
374409467b48Spatrick 
374509467b48Spatrick   if (parseIntToken(FileNumber,
374609467b48Spatrick                     "expected file number in '.cv_file' directive") ||
374709467b48Spatrick       check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
374809467b48Spatrick       check(getTok().isNot(AsmToken::String),
374909467b48Spatrick             "unexpected token in '.cv_file' directive") ||
375009467b48Spatrick       parseEscapedString(Filename))
375109467b48Spatrick     return true;
375209467b48Spatrick   if (!parseOptionalToken(AsmToken::EndOfStatement)) {
375309467b48Spatrick     if (check(getTok().isNot(AsmToken::String),
375409467b48Spatrick               "unexpected token in '.cv_file' directive") ||
375509467b48Spatrick         parseEscapedString(Checksum) ||
375609467b48Spatrick         parseIntToken(ChecksumKind,
375709467b48Spatrick                       "expected checksum kind in '.cv_file' directive") ||
3758*a96b3639Srobert         parseEOL())
375909467b48Spatrick       return true;
376009467b48Spatrick   }
376109467b48Spatrick 
376209467b48Spatrick   Checksum = fromHex(Checksum);
376309467b48Spatrick   void *CKMem = Ctx.allocate(Checksum.size(), 1);
376409467b48Spatrick   memcpy(CKMem, Checksum.data(), Checksum.size());
376509467b48Spatrick   ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
376609467b48Spatrick                                     Checksum.size());
376709467b48Spatrick 
3768*a96b3639Srobert   if (!getStreamer().emitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
376909467b48Spatrick                                          static_cast<uint8_t>(ChecksumKind)))
377009467b48Spatrick     return Error(FileNumberLoc, "file number already allocated");
377109467b48Spatrick 
377209467b48Spatrick   return false;
377309467b48Spatrick }
377409467b48Spatrick 
parseCVFunctionId(int64_t & FunctionId,StringRef DirectiveName)377509467b48Spatrick bool AsmParser::parseCVFunctionId(int64_t &FunctionId,
377609467b48Spatrick                                   StringRef DirectiveName) {
377709467b48Spatrick   SMLoc Loc;
377809467b48Spatrick   return parseTokenLoc(Loc) ||
377909467b48Spatrick          parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
378009467b48Spatrick                                        "' directive") ||
378109467b48Spatrick          check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
378209467b48Spatrick                "expected function id within range [0, UINT_MAX)");
378309467b48Spatrick }
378409467b48Spatrick 
parseCVFileId(int64_t & FileNumber,StringRef DirectiveName)378509467b48Spatrick bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
378609467b48Spatrick   SMLoc Loc;
378709467b48Spatrick   return parseTokenLoc(Loc) ||
378809467b48Spatrick          parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
378909467b48Spatrick                                        "' directive") ||
379009467b48Spatrick          check(FileNumber < 1, Loc, "file number less than one in '" +
379109467b48Spatrick                                         DirectiveName + "' directive") ||
379209467b48Spatrick          check(!getCVContext().isValidFileNumber(FileNumber), Loc,
379309467b48Spatrick                "unassigned file number in '" + DirectiveName + "' directive");
379409467b48Spatrick }
379509467b48Spatrick 
379609467b48Spatrick /// parseDirectiveCVFuncId
379709467b48Spatrick /// ::= .cv_func_id FunctionId
379809467b48Spatrick ///
379909467b48Spatrick /// Introduces a function ID that can be used with .cv_loc.
parseDirectiveCVFuncId()380009467b48Spatrick bool AsmParser::parseDirectiveCVFuncId() {
380109467b48Spatrick   SMLoc FunctionIdLoc = getTok().getLoc();
380209467b48Spatrick   int64_t FunctionId;
380309467b48Spatrick 
3804*a96b3639Srobert   if (parseCVFunctionId(FunctionId, ".cv_func_id") || parseEOL())
380509467b48Spatrick     return true;
380609467b48Spatrick 
3807*a96b3639Srobert   if (!getStreamer().emitCVFuncIdDirective(FunctionId))
380809467b48Spatrick     return Error(FunctionIdLoc, "function id already allocated");
380909467b48Spatrick 
381009467b48Spatrick   return false;
381109467b48Spatrick }
381209467b48Spatrick 
381309467b48Spatrick /// parseDirectiveCVInlineSiteId
381409467b48Spatrick /// ::= .cv_inline_site_id FunctionId
381509467b48Spatrick ///         "within" IAFunc
381609467b48Spatrick ///         "inlined_at" IAFile IALine [IACol]
381709467b48Spatrick ///
381809467b48Spatrick /// Introduces a function ID that can be used with .cv_loc. Includes "inlined
381909467b48Spatrick /// at" source location information for use in the line table of the caller,
382009467b48Spatrick /// whether the caller is a real function or another inlined call site.
parseDirectiveCVInlineSiteId()382109467b48Spatrick bool AsmParser::parseDirectiveCVInlineSiteId() {
382209467b48Spatrick   SMLoc FunctionIdLoc = getTok().getLoc();
382309467b48Spatrick   int64_t FunctionId;
382409467b48Spatrick   int64_t IAFunc;
382509467b48Spatrick   int64_t IAFile;
382609467b48Spatrick   int64_t IALine;
382709467b48Spatrick   int64_t IACol = 0;
382809467b48Spatrick 
382909467b48Spatrick   // FunctionId
383009467b48Spatrick   if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
383109467b48Spatrick     return true;
383209467b48Spatrick 
383309467b48Spatrick   // "within"
383409467b48Spatrick   if (check((getLexer().isNot(AsmToken::Identifier) ||
383509467b48Spatrick              getTok().getIdentifier() != "within"),
383609467b48Spatrick             "expected 'within' identifier in '.cv_inline_site_id' directive"))
383709467b48Spatrick     return true;
383809467b48Spatrick   Lex();
383909467b48Spatrick 
384009467b48Spatrick   // IAFunc
384109467b48Spatrick   if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
384209467b48Spatrick     return true;
384309467b48Spatrick 
384409467b48Spatrick   // "inlined_at"
384509467b48Spatrick   if (check((getLexer().isNot(AsmToken::Identifier) ||
384609467b48Spatrick              getTok().getIdentifier() != "inlined_at"),
384709467b48Spatrick             "expected 'inlined_at' identifier in '.cv_inline_site_id' "
384809467b48Spatrick             "directive") )
384909467b48Spatrick     return true;
385009467b48Spatrick   Lex();
385109467b48Spatrick 
385209467b48Spatrick   // IAFile IALine
385309467b48Spatrick   if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
385409467b48Spatrick       parseIntToken(IALine, "expected line number after 'inlined_at'"))
385509467b48Spatrick     return true;
385609467b48Spatrick 
385709467b48Spatrick   // [IACol]
385809467b48Spatrick   if (getLexer().is(AsmToken::Integer)) {
385909467b48Spatrick     IACol = getTok().getIntVal();
386009467b48Spatrick     Lex();
386109467b48Spatrick   }
386209467b48Spatrick 
3863*a96b3639Srobert   if (parseEOL())
386409467b48Spatrick     return true;
386509467b48Spatrick 
3866*a96b3639Srobert   if (!getStreamer().emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
386709467b48Spatrick                                                  IALine, IACol, FunctionIdLoc))
386809467b48Spatrick     return Error(FunctionIdLoc, "function id already allocated");
386909467b48Spatrick 
387009467b48Spatrick   return false;
387109467b48Spatrick }
387209467b48Spatrick 
387309467b48Spatrick /// parseDirectiveCVLoc
387409467b48Spatrick /// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
387509467b48Spatrick ///                                [is_stmt VALUE]
387609467b48Spatrick /// The first number is a file number, must have been previously assigned with
387709467b48Spatrick /// a .file directive, the second number is the line number and optionally the
387809467b48Spatrick /// third number is a column position (zero if not specified).  The remaining
387909467b48Spatrick /// optional items are .loc sub-directives.
parseDirectiveCVLoc()388009467b48Spatrick bool AsmParser::parseDirectiveCVLoc() {
388109467b48Spatrick   SMLoc DirectiveLoc = getTok().getLoc();
388209467b48Spatrick   int64_t FunctionId, FileNumber;
388309467b48Spatrick   if (parseCVFunctionId(FunctionId, ".cv_loc") ||
388409467b48Spatrick       parseCVFileId(FileNumber, ".cv_loc"))
388509467b48Spatrick     return true;
388609467b48Spatrick 
388709467b48Spatrick   int64_t LineNumber = 0;
388809467b48Spatrick   if (getLexer().is(AsmToken::Integer)) {
388909467b48Spatrick     LineNumber = getTok().getIntVal();
389009467b48Spatrick     if (LineNumber < 0)
389109467b48Spatrick       return TokError("line number less than zero in '.cv_loc' directive");
389209467b48Spatrick     Lex();
389309467b48Spatrick   }
389409467b48Spatrick 
389509467b48Spatrick   int64_t ColumnPos = 0;
389609467b48Spatrick   if (getLexer().is(AsmToken::Integer)) {
389709467b48Spatrick     ColumnPos = getTok().getIntVal();
389809467b48Spatrick     if (ColumnPos < 0)
389909467b48Spatrick       return TokError("column position less than zero in '.cv_loc' directive");
390009467b48Spatrick     Lex();
390109467b48Spatrick   }
390209467b48Spatrick 
390309467b48Spatrick   bool PrologueEnd = false;
390409467b48Spatrick   uint64_t IsStmt = 0;
390509467b48Spatrick 
390609467b48Spatrick   auto parseOp = [&]() -> bool {
390709467b48Spatrick     StringRef Name;
390809467b48Spatrick     SMLoc Loc = getTok().getLoc();
390909467b48Spatrick     if (parseIdentifier(Name))
391009467b48Spatrick       return TokError("unexpected token in '.cv_loc' directive");
391109467b48Spatrick     if (Name == "prologue_end")
391209467b48Spatrick       PrologueEnd = true;
391309467b48Spatrick     else if (Name == "is_stmt") {
391409467b48Spatrick       Loc = getTok().getLoc();
391509467b48Spatrick       const MCExpr *Value;
391609467b48Spatrick       if (parseExpression(Value))
391709467b48Spatrick         return true;
391809467b48Spatrick       // The expression must be the constant 0 or 1.
391909467b48Spatrick       IsStmt = ~0ULL;
392009467b48Spatrick       if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
392109467b48Spatrick         IsStmt = MCE->getValue();
392209467b48Spatrick 
392309467b48Spatrick       if (IsStmt > 1)
392409467b48Spatrick         return Error(Loc, "is_stmt value not 0 or 1");
392509467b48Spatrick     } else {
392609467b48Spatrick       return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
392709467b48Spatrick     }
392809467b48Spatrick     return false;
392909467b48Spatrick   };
393009467b48Spatrick 
393109467b48Spatrick   if (parseMany(parseOp, false /*hasComma*/))
393209467b48Spatrick     return true;
393309467b48Spatrick 
3934097a140dSpatrick   getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
393509467b48Spatrick                                    ColumnPos, PrologueEnd, IsStmt, StringRef(),
393609467b48Spatrick                                    DirectiveLoc);
393709467b48Spatrick   return false;
393809467b48Spatrick }
393909467b48Spatrick 
394009467b48Spatrick /// parseDirectiveCVLinetable
394109467b48Spatrick /// ::= .cv_linetable FunctionId, FnStart, FnEnd
parseDirectiveCVLinetable()394209467b48Spatrick bool AsmParser::parseDirectiveCVLinetable() {
394309467b48Spatrick   int64_t FunctionId;
394409467b48Spatrick   StringRef FnStartName, FnEndName;
394509467b48Spatrick   SMLoc Loc = getTok().getLoc();
3946a0747c9fSpatrick   if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() ||
3947a0747c9fSpatrick       parseTokenLoc(Loc) ||
3948a0747c9fSpatrick       check(parseIdentifier(FnStartName), Loc,
394909467b48Spatrick             "expected identifier in directive") ||
3950a0747c9fSpatrick       parseComma() || parseTokenLoc(Loc) ||
3951a0747c9fSpatrick       check(parseIdentifier(FnEndName), Loc,
395209467b48Spatrick             "expected identifier in directive"))
395309467b48Spatrick     return true;
395409467b48Spatrick 
395509467b48Spatrick   MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
395609467b48Spatrick   MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
395709467b48Spatrick 
3958097a140dSpatrick   getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
395909467b48Spatrick   return false;
396009467b48Spatrick }
396109467b48Spatrick 
396209467b48Spatrick /// parseDirectiveCVInlineLinetable
396309467b48Spatrick /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
parseDirectiveCVInlineLinetable()396409467b48Spatrick bool AsmParser::parseDirectiveCVInlineLinetable() {
396509467b48Spatrick   int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
396609467b48Spatrick   StringRef FnStartName, FnEndName;
396709467b48Spatrick   SMLoc Loc = getTok().getLoc();
396809467b48Spatrick   if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
396909467b48Spatrick       parseTokenLoc(Loc) ||
397009467b48Spatrick       parseIntToken(
397109467b48Spatrick           SourceFileId,
397209467b48Spatrick           "expected SourceField in '.cv_inline_linetable' directive") ||
397309467b48Spatrick       check(SourceFileId <= 0, Loc,
397409467b48Spatrick             "File id less than zero in '.cv_inline_linetable' directive") ||
397509467b48Spatrick       parseTokenLoc(Loc) ||
397609467b48Spatrick       parseIntToken(
397709467b48Spatrick           SourceLineNum,
397809467b48Spatrick           "expected SourceLineNum in '.cv_inline_linetable' directive") ||
397909467b48Spatrick       check(SourceLineNum < 0, Loc,
398009467b48Spatrick             "Line number less than zero in '.cv_inline_linetable' directive") ||
398109467b48Spatrick       parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
398209467b48Spatrick                                   "expected identifier in directive") ||
398309467b48Spatrick       parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
398409467b48Spatrick                                   "expected identifier in directive"))
398509467b48Spatrick     return true;
398609467b48Spatrick 
3987*a96b3639Srobert   if (parseEOL())
398809467b48Spatrick     return true;
398909467b48Spatrick 
399009467b48Spatrick   MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
399109467b48Spatrick   MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
3992097a140dSpatrick   getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
399309467b48Spatrick                                                SourceLineNum, FnStartSym,
399409467b48Spatrick                                                FnEndSym);
399509467b48Spatrick   return false;
399609467b48Spatrick }
399709467b48Spatrick 
initializeCVDefRangeTypeMap()399809467b48Spatrick void AsmParser::initializeCVDefRangeTypeMap() {
399909467b48Spatrick   CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
400009467b48Spatrick   CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
400109467b48Spatrick   CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
400209467b48Spatrick   CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
400309467b48Spatrick }
400409467b48Spatrick 
400509467b48Spatrick /// parseDirectiveCVDefRange
400609467b48Spatrick /// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
parseDirectiveCVDefRange()400709467b48Spatrick bool AsmParser::parseDirectiveCVDefRange() {
400809467b48Spatrick   SMLoc Loc;
400909467b48Spatrick   std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
401009467b48Spatrick   while (getLexer().is(AsmToken::Identifier)) {
401109467b48Spatrick     Loc = getLexer().getLoc();
401209467b48Spatrick     StringRef GapStartName;
401309467b48Spatrick     if (parseIdentifier(GapStartName))
401409467b48Spatrick       return Error(Loc, "expected identifier in directive");
401509467b48Spatrick     MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
401609467b48Spatrick 
401709467b48Spatrick     Loc = getLexer().getLoc();
401809467b48Spatrick     StringRef GapEndName;
401909467b48Spatrick     if (parseIdentifier(GapEndName))
402009467b48Spatrick       return Error(Loc, "expected identifier in directive");
402109467b48Spatrick     MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
402209467b48Spatrick 
402309467b48Spatrick     Ranges.push_back({GapStartSym, GapEndSym});
402409467b48Spatrick   }
402509467b48Spatrick 
402609467b48Spatrick   StringRef CVDefRangeTypeStr;
402709467b48Spatrick   if (parseToken(
402809467b48Spatrick           AsmToken::Comma,
402909467b48Spatrick           "expected comma before def_range type in .cv_def_range directive") ||
403009467b48Spatrick       parseIdentifier(CVDefRangeTypeStr))
403109467b48Spatrick     return Error(Loc, "expected def_range type in directive");
403209467b48Spatrick 
403309467b48Spatrick   StringMap<CVDefRangeType>::const_iterator CVTypeIt =
403409467b48Spatrick       CVDefRangeTypeMap.find(CVDefRangeTypeStr);
403509467b48Spatrick   CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
403609467b48Spatrick                                 ? CVDR_DEFRANGE
403709467b48Spatrick                                 : CVTypeIt->getValue();
403809467b48Spatrick   switch (CVDRType) {
403909467b48Spatrick   case CVDR_DEFRANGE_REGISTER: {
404009467b48Spatrick     int64_t DRRegister;
404109467b48Spatrick     if (parseToken(AsmToken::Comma, "expected comma before register number in "
404209467b48Spatrick                                     ".cv_def_range directive") ||
404309467b48Spatrick         parseAbsoluteExpression(DRRegister))
404409467b48Spatrick       return Error(Loc, "expected register number");
404509467b48Spatrick 
404609467b48Spatrick     codeview::DefRangeRegisterHeader DRHdr;
404709467b48Spatrick     DRHdr.Register = DRRegister;
404809467b48Spatrick     DRHdr.MayHaveNoName = 0;
4049097a140dSpatrick     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
405009467b48Spatrick     break;
405109467b48Spatrick   }
405209467b48Spatrick   case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
405309467b48Spatrick     int64_t DROffset;
405409467b48Spatrick     if (parseToken(AsmToken::Comma,
405509467b48Spatrick                    "expected comma before offset in .cv_def_range directive") ||
405609467b48Spatrick         parseAbsoluteExpression(DROffset))
405709467b48Spatrick       return Error(Loc, "expected offset value");
405809467b48Spatrick 
405909467b48Spatrick     codeview::DefRangeFramePointerRelHeader DRHdr;
406009467b48Spatrick     DRHdr.Offset = DROffset;
4061097a140dSpatrick     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
406209467b48Spatrick     break;
406309467b48Spatrick   }
406409467b48Spatrick   case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
406509467b48Spatrick     int64_t DRRegister;
406609467b48Spatrick     int64_t DROffsetInParent;
406709467b48Spatrick     if (parseToken(AsmToken::Comma, "expected comma before register number in "
406809467b48Spatrick                                     ".cv_def_range directive") ||
406909467b48Spatrick         parseAbsoluteExpression(DRRegister))
407009467b48Spatrick       return Error(Loc, "expected register number");
407109467b48Spatrick     if (parseToken(AsmToken::Comma,
407209467b48Spatrick                    "expected comma before offset in .cv_def_range directive") ||
407309467b48Spatrick         parseAbsoluteExpression(DROffsetInParent))
407409467b48Spatrick       return Error(Loc, "expected offset value");
407509467b48Spatrick 
407609467b48Spatrick     codeview::DefRangeSubfieldRegisterHeader DRHdr;
407709467b48Spatrick     DRHdr.Register = DRRegister;
407809467b48Spatrick     DRHdr.MayHaveNoName = 0;
407909467b48Spatrick     DRHdr.OffsetInParent = DROffsetInParent;
4080097a140dSpatrick     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
408109467b48Spatrick     break;
408209467b48Spatrick   }
408309467b48Spatrick   case CVDR_DEFRANGE_REGISTER_REL: {
408409467b48Spatrick     int64_t DRRegister;
408509467b48Spatrick     int64_t DRFlags;
408609467b48Spatrick     int64_t DRBasePointerOffset;
408709467b48Spatrick     if (parseToken(AsmToken::Comma, "expected comma before register number in "
408809467b48Spatrick                                     ".cv_def_range directive") ||
408909467b48Spatrick         parseAbsoluteExpression(DRRegister))
409009467b48Spatrick       return Error(Loc, "expected register value");
409109467b48Spatrick     if (parseToken(
409209467b48Spatrick             AsmToken::Comma,
409309467b48Spatrick             "expected comma before flag value in .cv_def_range directive") ||
409409467b48Spatrick         parseAbsoluteExpression(DRFlags))
409509467b48Spatrick       return Error(Loc, "expected flag value");
409609467b48Spatrick     if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
409709467b48Spatrick                                     "in .cv_def_range directive") ||
409809467b48Spatrick         parseAbsoluteExpression(DRBasePointerOffset))
409909467b48Spatrick       return Error(Loc, "expected base pointer offset value");
410009467b48Spatrick 
410109467b48Spatrick     codeview::DefRangeRegisterRelHeader DRHdr;
410209467b48Spatrick     DRHdr.Register = DRRegister;
410309467b48Spatrick     DRHdr.Flags = DRFlags;
410409467b48Spatrick     DRHdr.BasePointerOffset = DRBasePointerOffset;
4105097a140dSpatrick     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
410609467b48Spatrick     break;
410709467b48Spatrick   }
410809467b48Spatrick   default:
410909467b48Spatrick     return Error(Loc, "unexpected def_range type in .cv_def_range directive");
411009467b48Spatrick   }
411109467b48Spatrick   return true;
411209467b48Spatrick }
411309467b48Spatrick 
411409467b48Spatrick /// parseDirectiveCVString
411509467b48Spatrick /// ::= .cv_stringtable "string"
parseDirectiveCVString()411609467b48Spatrick bool AsmParser::parseDirectiveCVString() {
411709467b48Spatrick   std::string Data;
411809467b48Spatrick   if (checkForValidSection() || parseEscapedString(Data))
4119a0747c9fSpatrick     return true;
412009467b48Spatrick 
412109467b48Spatrick   // Put the string in the table and emit the offset.
412209467b48Spatrick   std::pair<StringRef, unsigned> Insertion =
412309467b48Spatrick       getCVContext().addToStringTable(Data);
4124097a140dSpatrick   getStreamer().emitInt32(Insertion.second);
412509467b48Spatrick   return false;
412609467b48Spatrick }
412709467b48Spatrick 
412809467b48Spatrick /// parseDirectiveCVStringTable
412909467b48Spatrick /// ::= .cv_stringtable
parseDirectiveCVStringTable()413009467b48Spatrick bool AsmParser::parseDirectiveCVStringTable() {
4131097a140dSpatrick   getStreamer().emitCVStringTableDirective();
413209467b48Spatrick   return false;
413309467b48Spatrick }
413409467b48Spatrick 
413509467b48Spatrick /// parseDirectiveCVFileChecksums
413609467b48Spatrick /// ::= .cv_filechecksums
parseDirectiveCVFileChecksums()413709467b48Spatrick bool AsmParser::parseDirectiveCVFileChecksums() {
4138097a140dSpatrick   getStreamer().emitCVFileChecksumsDirective();
413909467b48Spatrick   return false;
414009467b48Spatrick }
414109467b48Spatrick 
414209467b48Spatrick /// parseDirectiveCVFileChecksumOffset
414309467b48Spatrick /// ::= .cv_filechecksumoffset fileno
parseDirectiveCVFileChecksumOffset()414409467b48Spatrick bool AsmParser::parseDirectiveCVFileChecksumOffset() {
414509467b48Spatrick   int64_t FileNo;
414609467b48Spatrick   if (parseIntToken(FileNo, "expected identifier in directive"))
414709467b48Spatrick     return true;
4148*a96b3639Srobert   if (parseEOL())
414909467b48Spatrick     return true;
4150097a140dSpatrick   getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
415109467b48Spatrick   return false;
415209467b48Spatrick }
415309467b48Spatrick 
415409467b48Spatrick /// parseDirectiveCVFPOData
415509467b48Spatrick /// ::= .cv_fpo_data procsym
parseDirectiveCVFPOData()415609467b48Spatrick bool AsmParser::parseDirectiveCVFPOData() {
415709467b48Spatrick   SMLoc DirLoc = getLexer().getLoc();
415809467b48Spatrick   StringRef ProcName;
415909467b48Spatrick   if (parseIdentifier(ProcName))
416009467b48Spatrick     return TokError("expected symbol name");
4161a0747c9fSpatrick   if (parseEOL())
4162a0747c9fSpatrick     return true;
416309467b48Spatrick   MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
4164*a96b3639Srobert   getStreamer().emitCVFPOData(ProcSym, DirLoc);
416509467b48Spatrick   return false;
416609467b48Spatrick }
416709467b48Spatrick 
416809467b48Spatrick /// parseDirectiveCFISections
416909467b48Spatrick /// ::= .cfi_sections section [, section]
parseDirectiveCFISections()417009467b48Spatrick bool AsmParser::parseDirectiveCFISections() {
417109467b48Spatrick   StringRef Name;
417209467b48Spatrick   bool EH = false;
417309467b48Spatrick   bool Debug = false;
417409467b48Spatrick 
4175a0747c9fSpatrick   if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4176a0747c9fSpatrick     for (;;) {
417709467b48Spatrick       if (parseIdentifier(Name))
4178a0747c9fSpatrick         return TokError("expected .eh_frame or .debug_frame");
417909467b48Spatrick       if (Name == ".eh_frame")
418009467b48Spatrick         EH = true;
418109467b48Spatrick       else if (Name == ".debug_frame")
418209467b48Spatrick         Debug = true;
4183a0747c9fSpatrick       if (parseOptionalToken(AsmToken::EndOfStatement))
4184a0747c9fSpatrick         break;
4185a0747c9fSpatrick       if (parseComma())
4186a0747c9fSpatrick         return true;
418709467b48Spatrick     }
4188a0747c9fSpatrick   }
4189097a140dSpatrick   getStreamer().emitCFISections(EH, Debug);
419009467b48Spatrick   return false;
419109467b48Spatrick }
419209467b48Spatrick 
419309467b48Spatrick /// parseDirectiveCFIStartProc
419409467b48Spatrick /// ::= .cfi_startproc [simple]
parseDirectiveCFIStartProc()419509467b48Spatrick bool AsmParser::parseDirectiveCFIStartProc() {
419609467b48Spatrick   StringRef Simple;
419709467b48Spatrick   if (!parseOptionalToken(AsmToken::EndOfStatement)) {
419809467b48Spatrick     if (check(parseIdentifier(Simple) || Simple != "simple",
419909467b48Spatrick               "unexpected token") ||
4200a0747c9fSpatrick         parseEOL())
4201a0747c9fSpatrick       return true;
420209467b48Spatrick   }
420309467b48Spatrick 
420409467b48Spatrick   // TODO(kristina): Deal with a corner case of incorrect diagnostic context
420509467b48Spatrick   // being produced if this directive is emitted as part of preprocessor macro
420609467b48Spatrick   // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
420709467b48Spatrick   // Tools like llvm-mc on the other hand are not affected by it, and report
420809467b48Spatrick   // correct context information.
4209097a140dSpatrick   getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
421009467b48Spatrick   return false;
421109467b48Spatrick }
421209467b48Spatrick 
421309467b48Spatrick /// parseDirectiveCFIEndProc
421409467b48Spatrick /// ::= .cfi_endproc
parseDirectiveCFIEndProc()421509467b48Spatrick bool AsmParser::parseDirectiveCFIEndProc() {
4216a0747c9fSpatrick   if (parseEOL())
4217a0747c9fSpatrick     return true;
4218097a140dSpatrick   getStreamer().emitCFIEndProc();
421909467b48Spatrick   return false;
422009467b48Spatrick }
422109467b48Spatrick 
422209467b48Spatrick /// parse register name or number.
parseRegisterOrRegisterNumber(int64_t & Register,SMLoc DirectiveLoc)422309467b48Spatrick bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
422409467b48Spatrick                                               SMLoc DirectiveLoc) {
4225*a96b3639Srobert   MCRegister RegNo;
422609467b48Spatrick 
422709467b48Spatrick   if (getLexer().isNot(AsmToken::Integer)) {
4228*a96b3639Srobert     if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc))
422909467b48Spatrick       return true;
423009467b48Spatrick     Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
423109467b48Spatrick   } else
423209467b48Spatrick     return parseAbsoluteExpression(Register);
423309467b48Spatrick 
423409467b48Spatrick   return false;
423509467b48Spatrick }
423609467b48Spatrick 
423709467b48Spatrick /// parseDirectiveCFIDefCfa
423809467b48Spatrick /// ::= .cfi_def_cfa register,  offset
parseDirectiveCFIDefCfa(SMLoc DirectiveLoc)423909467b48Spatrick bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
424009467b48Spatrick   int64_t Register = 0, Offset = 0;
4241a0747c9fSpatrick   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4242a0747c9fSpatrick       parseAbsoluteExpression(Offset) || parseEOL())
424309467b48Spatrick     return true;
424409467b48Spatrick 
4245097a140dSpatrick   getStreamer().emitCFIDefCfa(Register, Offset);
424609467b48Spatrick   return false;
424709467b48Spatrick }
424809467b48Spatrick 
424909467b48Spatrick /// parseDirectiveCFIDefCfaOffset
425009467b48Spatrick /// ::= .cfi_def_cfa_offset offset
parseDirectiveCFIDefCfaOffset()425109467b48Spatrick bool AsmParser::parseDirectiveCFIDefCfaOffset() {
425209467b48Spatrick   int64_t Offset = 0;
4253a0747c9fSpatrick   if (parseAbsoluteExpression(Offset) || parseEOL())
425409467b48Spatrick     return true;
425509467b48Spatrick 
4256097a140dSpatrick   getStreamer().emitCFIDefCfaOffset(Offset);
425709467b48Spatrick   return false;
425809467b48Spatrick }
425909467b48Spatrick 
426009467b48Spatrick /// parseDirectiveCFIRegister
426109467b48Spatrick /// ::= .cfi_register register, register
parseDirectiveCFIRegister(SMLoc DirectiveLoc)426209467b48Spatrick bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
426309467b48Spatrick   int64_t Register1 = 0, Register2 = 0;
4264a0747c9fSpatrick   if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || parseComma() ||
4265a0747c9fSpatrick       parseRegisterOrRegisterNumber(Register2, DirectiveLoc) || parseEOL())
426609467b48Spatrick     return true;
426709467b48Spatrick 
4268097a140dSpatrick   getStreamer().emitCFIRegister(Register1, Register2);
426909467b48Spatrick   return false;
427009467b48Spatrick }
427109467b48Spatrick 
427209467b48Spatrick /// parseDirectiveCFIWindowSave
427309467b48Spatrick /// ::= .cfi_window_save
parseDirectiveCFIWindowSave()427409467b48Spatrick bool AsmParser::parseDirectiveCFIWindowSave() {
4275a0747c9fSpatrick   if (parseEOL())
4276a0747c9fSpatrick     return true;
4277097a140dSpatrick   getStreamer().emitCFIWindowSave();
427809467b48Spatrick   return false;
427909467b48Spatrick }
428009467b48Spatrick 
428109467b48Spatrick /// parseDirectiveCFIAdjustCfaOffset
428209467b48Spatrick /// ::= .cfi_adjust_cfa_offset adjustment
parseDirectiveCFIAdjustCfaOffset()428309467b48Spatrick bool AsmParser::parseDirectiveCFIAdjustCfaOffset() {
428409467b48Spatrick   int64_t Adjustment = 0;
4285a0747c9fSpatrick   if (parseAbsoluteExpression(Adjustment) || parseEOL())
428609467b48Spatrick     return true;
428709467b48Spatrick 
4288097a140dSpatrick   getStreamer().emitCFIAdjustCfaOffset(Adjustment);
428909467b48Spatrick   return false;
429009467b48Spatrick }
429109467b48Spatrick 
429209467b48Spatrick /// parseDirectiveCFIDefCfaRegister
429309467b48Spatrick /// ::= .cfi_def_cfa_register register
parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc)429409467b48Spatrick bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
429509467b48Spatrick   int64_t Register = 0;
4296a0747c9fSpatrick   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
429709467b48Spatrick     return true;
429809467b48Spatrick 
4299097a140dSpatrick   getStreamer().emitCFIDefCfaRegister(Register);
430009467b48Spatrick   return false;
430109467b48Spatrick }
430209467b48Spatrick 
4303a0747c9fSpatrick /// parseDirectiveCFILLVMDefAspaceCfa
4304a0747c9fSpatrick /// ::= .cfi_llvm_def_aspace_cfa register, offset, address_space
parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc)4305a0747c9fSpatrick bool AsmParser::parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc) {
4306a0747c9fSpatrick   int64_t Register = 0, Offset = 0, AddressSpace = 0;
4307a0747c9fSpatrick   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4308a0747c9fSpatrick       parseAbsoluteExpression(Offset) || parseComma() ||
4309a0747c9fSpatrick       parseAbsoluteExpression(AddressSpace) || parseEOL())
4310a0747c9fSpatrick     return true;
4311a0747c9fSpatrick 
4312a0747c9fSpatrick   getStreamer().emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace);
4313a0747c9fSpatrick   return false;
4314a0747c9fSpatrick }
4315a0747c9fSpatrick 
431609467b48Spatrick /// parseDirectiveCFIOffset
431709467b48Spatrick /// ::= .cfi_offset register, offset
parseDirectiveCFIOffset(SMLoc DirectiveLoc)431809467b48Spatrick bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
431909467b48Spatrick   int64_t Register = 0;
432009467b48Spatrick   int64_t Offset = 0;
432109467b48Spatrick 
4322a0747c9fSpatrick   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4323a0747c9fSpatrick       parseAbsoluteExpression(Offset) || parseEOL())
432409467b48Spatrick     return true;
432509467b48Spatrick 
4326097a140dSpatrick   getStreamer().emitCFIOffset(Register, Offset);
432709467b48Spatrick   return false;
432809467b48Spatrick }
432909467b48Spatrick 
433009467b48Spatrick /// parseDirectiveCFIRelOffset
433109467b48Spatrick /// ::= .cfi_rel_offset register, offset
parseDirectiveCFIRelOffset(SMLoc DirectiveLoc)433209467b48Spatrick bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
433309467b48Spatrick   int64_t Register = 0, Offset = 0;
433409467b48Spatrick 
4335a0747c9fSpatrick   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4336a0747c9fSpatrick       parseAbsoluteExpression(Offset) || parseEOL())
433709467b48Spatrick     return true;
433809467b48Spatrick 
4339097a140dSpatrick   getStreamer().emitCFIRelOffset(Register, Offset);
434009467b48Spatrick   return false;
434109467b48Spatrick }
434209467b48Spatrick 
isValidEncoding(int64_t Encoding)434309467b48Spatrick static bool isValidEncoding(int64_t Encoding) {
434409467b48Spatrick   if (Encoding & ~0xff)
434509467b48Spatrick     return false;
434609467b48Spatrick 
434709467b48Spatrick   if (Encoding == dwarf::DW_EH_PE_omit)
434809467b48Spatrick     return true;
434909467b48Spatrick 
435009467b48Spatrick   const unsigned Format = Encoding & 0xf;
435109467b48Spatrick   if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
435209467b48Spatrick       Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
435309467b48Spatrick       Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
435409467b48Spatrick       Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
435509467b48Spatrick     return false;
435609467b48Spatrick 
435709467b48Spatrick   const unsigned Application = Encoding & 0x70;
435809467b48Spatrick   if (Application != dwarf::DW_EH_PE_absptr &&
435909467b48Spatrick       Application != dwarf::DW_EH_PE_pcrel)
436009467b48Spatrick     return false;
436109467b48Spatrick 
436209467b48Spatrick   return true;
436309467b48Spatrick }
436409467b48Spatrick 
436509467b48Spatrick /// parseDirectiveCFIPersonalityOrLsda
436609467b48Spatrick /// IsPersonality true for cfi_personality, false for cfi_lsda
436709467b48Spatrick /// ::= .cfi_personality encoding, [symbol_name]
436809467b48Spatrick /// ::= .cfi_lsda encoding, [symbol_name]
parseDirectiveCFIPersonalityOrLsda(bool IsPersonality)436909467b48Spatrick bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
437009467b48Spatrick   int64_t Encoding = 0;
437109467b48Spatrick   if (parseAbsoluteExpression(Encoding))
437209467b48Spatrick     return true;
437309467b48Spatrick   if (Encoding == dwarf::DW_EH_PE_omit)
437409467b48Spatrick     return false;
437509467b48Spatrick 
437609467b48Spatrick   StringRef Name;
437709467b48Spatrick   if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
4378a0747c9fSpatrick       parseComma() ||
4379a0747c9fSpatrick       check(parseIdentifier(Name), "expected identifier in directive") ||
4380a0747c9fSpatrick       parseEOL())
438109467b48Spatrick     return true;
438209467b48Spatrick 
438309467b48Spatrick   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
438409467b48Spatrick 
438509467b48Spatrick   if (IsPersonality)
4386097a140dSpatrick     getStreamer().emitCFIPersonality(Sym, Encoding);
438709467b48Spatrick   else
4388097a140dSpatrick     getStreamer().emitCFILsda(Sym, Encoding);
438909467b48Spatrick   return false;
439009467b48Spatrick }
439109467b48Spatrick 
439209467b48Spatrick /// parseDirectiveCFIRememberState
439309467b48Spatrick /// ::= .cfi_remember_state
parseDirectiveCFIRememberState()439409467b48Spatrick bool AsmParser::parseDirectiveCFIRememberState() {
4395a0747c9fSpatrick   if (parseEOL())
4396a0747c9fSpatrick     return true;
4397097a140dSpatrick   getStreamer().emitCFIRememberState();
439809467b48Spatrick   return false;
439909467b48Spatrick }
440009467b48Spatrick 
440109467b48Spatrick /// parseDirectiveCFIRestoreState
440209467b48Spatrick /// ::= .cfi_remember_state
parseDirectiveCFIRestoreState()440309467b48Spatrick bool AsmParser::parseDirectiveCFIRestoreState() {
4404a0747c9fSpatrick   if (parseEOL())
4405a0747c9fSpatrick     return true;
4406097a140dSpatrick   getStreamer().emitCFIRestoreState();
440709467b48Spatrick   return false;
440809467b48Spatrick }
440909467b48Spatrick 
441009467b48Spatrick /// parseDirectiveCFISameValue
441109467b48Spatrick /// ::= .cfi_same_value register
parseDirectiveCFISameValue(SMLoc DirectiveLoc)441209467b48Spatrick bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
441309467b48Spatrick   int64_t Register = 0;
441409467b48Spatrick 
4415a0747c9fSpatrick   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
441609467b48Spatrick     return true;
441709467b48Spatrick 
4418097a140dSpatrick   getStreamer().emitCFISameValue(Register);
441909467b48Spatrick   return false;
442009467b48Spatrick }
442109467b48Spatrick 
442209467b48Spatrick /// parseDirectiveCFIRestore
442309467b48Spatrick /// ::= .cfi_restore register
parseDirectiveCFIRestore(SMLoc DirectiveLoc)442409467b48Spatrick bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
442509467b48Spatrick   int64_t Register = 0;
4426a0747c9fSpatrick   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
442709467b48Spatrick     return true;
442809467b48Spatrick 
4429097a140dSpatrick   getStreamer().emitCFIRestore(Register);
443009467b48Spatrick   return false;
443109467b48Spatrick }
443209467b48Spatrick 
443309467b48Spatrick /// parseDirectiveCFIEscape
443409467b48Spatrick /// ::= .cfi_escape expression[,...]
parseDirectiveCFIEscape()443509467b48Spatrick bool AsmParser::parseDirectiveCFIEscape() {
443609467b48Spatrick   std::string Values;
443709467b48Spatrick   int64_t CurrValue;
443809467b48Spatrick   if (parseAbsoluteExpression(CurrValue))
443909467b48Spatrick     return true;
444009467b48Spatrick 
444109467b48Spatrick   Values.push_back((uint8_t)CurrValue);
444209467b48Spatrick 
444309467b48Spatrick   while (getLexer().is(AsmToken::Comma)) {
444409467b48Spatrick     Lex();
444509467b48Spatrick 
444609467b48Spatrick     if (parseAbsoluteExpression(CurrValue))
444709467b48Spatrick       return true;
444809467b48Spatrick 
444909467b48Spatrick     Values.push_back((uint8_t)CurrValue);
445009467b48Spatrick   }
445109467b48Spatrick 
4452097a140dSpatrick   getStreamer().emitCFIEscape(Values);
445309467b48Spatrick   return false;
445409467b48Spatrick }
445509467b48Spatrick 
445609467b48Spatrick /// parseDirectiveCFIReturnColumn
445709467b48Spatrick /// ::= .cfi_return_column register
parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc)445809467b48Spatrick bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
445909467b48Spatrick   int64_t Register = 0;
4460a0747c9fSpatrick   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
446109467b48Spatrick     return true;
4462097a140dSpatrick   getStreamer().emitCFIReturnColumn(Register);
446309467b48Spatrick   return false;
446409467b48Spatrick }
446509467b48Spatrick 
446609467b48Spatrick /// parseDirectiveCFISignalFrame
446709467b48Spatrick /// ::= .cfi_signal_frame
parseDirectiveCFISignalFrame()446809467b48Spatrick bool AsmParser::parseDirectiveCFISignalFrame() {
4469a0747c9fSpatrick   if (parseEOL())
447009467b48Spatrick     return true;
447109467b48Spatrick 
4472097a140dSpatrick   getStreamer().emitCFISignalFrame();
447309467b48Spatrick   return false;
447409467b48Spatrick }
447509467b48Spatrick 
447609467b48Spatrick /// parseDirectiveCFIUndefined
447709467b48Spatrick /// ::= .cfi_undefined register
parseDirectiveCFIUndefined(SMLoc DirectiveLoc)447809467b48Spatrick bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
447909467b48Spatrick   int64_t Register = 0;
448009467b48Spatrick 
4481a0747c9fSpatrick   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
448209467b48Spatrick     return true;
448309467b48Spatrick 
4484097a140dSpatrick   getStreamer().emitCFIUndefined(Register);
448509467b48Spatrick   return false;
448609467b48Spatrick }
448709467b48Spatrick 
448809467b48Spatrick /// parseDirectiveAltmacro
448909467b48Spatrick /// ::= .altmacro
449009467b48Spatrick /// ::= .noaltmacro
parseDirectiveAltmacro(StringRef Directive)449109467b48Spatrick bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
4492a0747c9fSpatrick   if (parseEOL())
4493a0747c9fSpatrick     return true;
449409467b48Spatrick   AltMacroMode = (Directive == ".altmacro");
449509467b48Spatrick   return false;
449609467b48Spatrick }
449709467b48Spatrick 
449809467b48Spatrick /// parseDirectiveMacrosOnOff
449909467b48Spatrick /// ::= .macros_on
450009467b48Spatrick /// ::= .macros_off
parseDirectiveMacrosOnOff(StringRef Directive)450109467b48Spatrick bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
4502a0747c9fSpatrick   if (parseEOL())
450309467b48Spatrick     return true;
450409467b48Spatrick   setMacrosEnabled(Directive == ".macros_on");
450509467b48Spatrick   return false;
450609467b48Spatrick }
450709467b48Spatrick 
450809467b48Spatrick /// parseDirectiveMacro
450909467b48Spatrick /// ::= .macro name[,] [parameters]
parseDirectiveMacro(SMLoc DirectiveLoc)451009467b48Spatrick bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
451109467b48Spatrick   StringRef Name;
451209467b48Spatrick   if (parseIdentifier(Name))
451309467b48Spatrick     return TokError("expected identifier in '.macro' directive");
451409467b48Spatrick 
451509467b48Spatrick   if (getLexer().is(AsmToken::Comma))
451609467b48Spatrick     Lex();
451709467b48Spatrick 
451809467b48Spatrick   MCAsmMacroParameters Parameters;
451909467b48Spatrick   while (getLexer().isNot(AsmToken::EndOfStatement)) {
452009467b48Spatrick 
452109467b48Spatrick     if (!Parameters.empty() && Parameters.back().Vararg)
4522097a140dSpatrick       return Error(Lexer.getLoc(), "vararg parameter '" +
4523097a140dSpatrick                                        Parameters.back().Name +
4524097a140dSpatrick                                        "' should be the last parameter");
452509467b48Spatrick 
452609467b48Spatrick     MCAsmMacroParameter Parameter;
452709467b48Spatrick     if (parseIdentifier(Parameter.Name))
452809467b48Spatrick       return TokError("expected identifier in '.macro' directive");
452909467b48Spatrick 
453009467b48Spatrick     // Emit an error if two (or more) named parameters share the same name
453109467b48Spatrick     for (const MCAsmMacroParameter& CurrParam : Parameters)
453209467b48Spatrick       if (CurrParam.Name.equals(Parameter.Name))
453309467b48Spatrick         return TokError("macro '" + Name + "' has multiple parameters"
453409467b48Spatrick                         " named '" + Parameter.Name + "'");
453509467b48Spatrick 
453609467b48Spatrick     if (Lexer.is(AsmToken::Colon)) {
453709467b48Spatrick       Lex();  // consume ':'
453809467b48Spatrick 
453909467b48Spatrick       SMLoc QualLoc;
454009467b48Spatrick       StringRef Qualifier;
454109467b48Spatrick 
454209467b48Spatrick       QualLoc = Lexer.getLoc();
454309467b48Spatrick       if (parseIdentifier(Qualifier))
454409467b48Spatrick         return Error(QualLoc, "missing parameter qualifier for "
454509467b48Spatrick                      "'" + Parameter.Name + "' in macro '" + Name + "'");
454609467b48Spatrick 
454709467b48Spatrick       if (Qualifier == "req")
454809467b48Spatrick         Parameter.Required = true;
454909467b48Spatrick       else if (Qualifier == "vararg")
455009467b48Spatrick         Parameter.Vararg = true;
455109467b48Spatrick       else
455209467b48Spatrick         return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
455309467b48Spatrick                      "for '" + Parameter.Name + "' in macro '" + Name + "'");
455409467b48Spatrick     }
455509467b48Spatrick 
455609467b48Spatrick     if (getLexer().is(AsmToken::Equal)) {
455709467b48Spatrick       Lex();
455809467b48Spatrick 
455909467b48Spatrick       SMLoc ParamLoc;
456009467b48Spatrick 
456109467b48Spatrick       ParamLoc = Lexer.getLoc();
456209467b48Spatrick       if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
456309467b48Spatrick         return true;
456409467b48Spatrick 
456509467b48Spatrick       if (Parameter.Required)
456609467b48Spatrick         Warning(ParamLoc, "pointless default value for required parameter "
456709467b48Spatrick                 "'" + Parameter.Name + "' in macro '" + Name + "'");
456809467b48Spatrick     }
456909467b48Spatrick 
457009467b48Spatrick     Parameters.push_back(std::move(Parameter));
457109467b48Spatrick 
457209467b48Spatrick     if (getLexer().is(AsmToken::Comma))
457309467b48Spatrick       Lex();
457409467b48Spatrick   }
457509467b48Spatrick 
457609467b48Spatrick   // Eat just the end of statement.
457709467b48Spatrick   Lexer.Lex();
457809467b48Spatrick 
457909467b48Spatrick   // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors
458009467b48Spatrick   AsmToken EndToken, StartToken = getTok();
458109467b48Spatrick   unsigned MacroDepth = 0;
458209467b48Spatrick   // Lex the macro definition.
458309467b48Spatrick   while (true) {
458409467b48Spatrick     // Ignore Lexing errors in macros.
458509467b48Spatrick     while (Lexer.is(AsmToken::Error)) {
458609467b48Spatrick       Lexer.Lex();
458709467b48Spatrick     }
458809467b48Spatrick 
458909467b48Spatrick     // Check whether we have reached the end of the file.
459009467b48Spatrick     if (getLexer().is(AsmToken::Eof))
459109467b48Spatrick       return Error(DirectiveLoc, "no matching '.endmacro' in definition");
459209467b48Spatrick 
4593097a140dSpatrick     // Otherwise, check whether we have reach the .endmacro or the start of a
4594097a140dSpatrick     // preprocessor line marker.
459509467b48Spatrick     if (getLexer().is(AsmToken::Identifier)) {
459609467b48Spatrick       if (getTok().getIdentifier() == ".endm" ||
459709467b48Spatrick           getTok().getIdentifier() == ".endmacro") {
459809467b48Spatrick         if (MacroDepth == 0) { // Outermost macro.
459909467b48Spatrick           EndToken = getTok();
460009467b48Spatrick           Lexer.Lex();
460109467b48Spatrick           if (getLexer().isNot(AsmToken::EndOfStatement))
460209467b48Spatrick             return TokError("unexpected token in '" + EndToken.getIdentifier() +
460309467b48Spatrick                             "' directive");
460409467b48Spatrick           break;
460509467b48Spatrick         } else {
460609467b48Spatrick           // Otherwise we just found the end of an inner macro.
460709467b48Spatrick           --MacroDepth;
460809467b48Spatrick         }
460909467b48Spatrick       } else if (getTok().getIdentifier() == ".macro") {
461009467b48Spatrick         // We allow nested macros. Those aren't instantiated until the outermost
461109467b48Spatrick         // macro is expanded so just ignore them for now.
461209467b48Spatrick         ++MacroDepth;
461309467b48Spatrick       }
4614097a140dSpatrick     } else if (Lexer.is(AsmToken::HashDirective)) {
4615097a140dSpatrick       (void)parseCppHashLineFilenameComment(getLexer().getLoc());
461609467b48Spatrick     }
461709467b48Spatrick 
461809467b48Spatrick     // Otherwise, scan til the end of the statement.
461909467b48Spatrick     eatToEndOfStatement();
462009467b48Spatrick   }
462109467b48Spatrick 
462209467b48Spatrick   if (getContext().lookupMacro(Name)) {
462309467b48Spatrick     return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
462409467b48Spatrick   }
462509467b48Spatrick 
462609467b48Spatrick   const char *BodyStart = StartToken.getLoc().getPointer();
462709467b48Spatrick   const char *BodyEnd = EndToken.getLoc().getPointer();
462809467b48Spatrick   StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
462909467b48Spatrick   checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
463009467b48Spatrick   MCAsmMacro Macro(Name, Body, std::move(Parameters));
463109467b48Spatrick   DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
463209467b48Spatrick                   Macro.dump());
463309467b48Spatrick   getContext().defineMacro(Name, std::move(Macro));
463409467b48Spatrick   return false;
463509467b48Spatrick }
463609467b48Spatrick 
463709467b48Spatrick /// checkForBadMacro
463809467b48Spatrick ///
463909467b48Spatrick /// With the support added for named parameters there may be code out there that
464009467b48Spatrick /// is transitioning from positional parameters.  In versions of gas that did
464109467b48Spatrick /// not support named parameters they would be ignored on the macro definition.
464209467b48Spatrick /// But to support both styles of parameters this is not possible so if a macro
464309467b48Spatrick /// definition has named parameters but does not use them and has what appears
464409467b48Spatrick /// to be positional parameters, strings like $1, $2, ... and $n, then issue a
464509467b48Spatrick /// warning that the positional parameter found in body which have no effect.
464609467b48Spatrick /// Hoping the developer will either remove the named parameters from the macro
464709467b48Spatrick /// definition so the positional parameters get used if that was what was
464809467b48Spatrick /// intended or change the macro to use the named parameters.  It is possible
464909467b48Spatrick /// this warning will trigger when the none of the named parameters are used
465009467b48Spatrick /// and the strings like $1 are infact to simply to be passed trough unchanged.
checkForBadMacro(SMLoc DirectiveLoc,StringRef Name,StringRef Body,ArrayRef<MCAsmMacroParameter> Parameters)465109467b48Spatrick void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
465209467b48Spatrick                                  StringRef Body,
465309467b48Spatrick                                  ArrayRef<MCAsmMacroParameter> Parameters) {
465409467b48Spatrick   // If this macro is not defined with named parameters the warning we are
465509467b48Spatrick   // checking for here doesn't apply.
465609467b48Spatrick   unsigned NParameters = Parameters.size();
465709467b48Spatrick   if (NParameters == 0)
465809467b48Spatrick     return;
465909467b48Spatrick 
466009467b48Spatrick   bool NamedParametersFound = false;
466109467b48Spatrick   bool PositionalParametersFound = false;
466209467b48Spatrick 
466309467b48Spatrick   // Look at the body of the macro for use of both the named parameters and what
466409467b48Spatrick   // are likely to be positional parameters.  This is what expandMacro() is
466509467b48Spatrick   // doing when it finds the parameters in the body.
466609467b48Spatrick   while (!Body.empty()) {
466709467b48Spatrick     // Scan for the next possible parameter.
466809467b48Spatrick     std::size_t End = Body.size(), Pos = 0;
466909467b48Spatrick     for (; Pos != End; ++Pos) {
467009467b48Spatrick       // Check for a substitution or escape.
467109467b48Spatrick       // This macro is defined with parameters, look for \foo, \bar, etc.
467209467b48Spatrick       if (Body[Pos] == '\\' && Pos + 1 != End)
467309467b48Spatrick         break;
467409467b48Spatrick 
467509467b48Spatrick       // This macro should have parameters, but look for $0, $1, ..., $n too.
467609467b48Spatrick       if (Body[Pos] != '$' || Pos + 1 == End)
467709467b48Spatrick         continue;
467809467b48Spatrick       char Next = Body[Pos + 1];
467909467b48Spatrick       if (Next == '$' || Next == 'n' ||
468009467b48Spatrick           isdigit(static_cast<unsigned char>(Next)))
468109467b48Spatrick         break;
468209467b48Spatrick     }
468309467b48Spatrick 
468409467b48Spatrick     // Check if we reached the end.
468509467b48Spatrick     if (Pos == End)
468609467b48Spatrick       break;
468709467b48Spatrick 
468809467b48Spatrick     if (Body[Pos] == '$') {
468909467b48Spatrick       switch (Body[Pos + 1]) {
469009467b48Spatrick       // $$ => $
469109467b48Spatrick       case '$':
469209467b48Spatrick         break;
469309467b48Spatrick 
469409467b48Spatrick       // $n => number of arguments
469509467b48Spatrick       case 'n':
469609467b48Spatrick         PositionalParametersFound = true;
469709467b48Spatrick         break;
469809467b48Spatrick 
469909467b48Spatrick       // $[0-9] => argument
470009467b48Spatrick       default: {
470109467b48Spatrick         PositionalParametersFound = true;
470209467b48Spatrick         break;
470309467b48Spatrick       }
470409467b48Spatrick       }
470509467b48Spatrick       Pos += 2;
470609467b48Spatrick     } else {
470709467b48Spatrick       unsigned I = Pos + 1;
470809467b48Spatrick       while (isIdentifierChar(Body[I]) && I + 1 != End)
470909467b48Spatrick         ++I;
471009467b48Spatrick 
471109467b48Spatrick       const char *Begin = Body.data() + Pos + 1;
471209467b48Spatrick       StringRef Argument(Begin, I - (Pos + 1));
471309467b48Spatrick       unsigned Index = 0;
471409467b48Spatrick       for (; Index < NParameters; ++Index)
471509467b48Spatrick         if (Parameters[Index].Name == Argument)
471609467b48Spatrick           break;
471709467b48Spatrick 
471809467b48Spatrick       if (Index == NParameters) {
471909467b48Spatrick         if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
472009467b48Spatrick           Pos += 3;
472109467b48Spatrick         else {
472209467b48Spatrick           Pos = I;
472309467b48Spatrick         }
472409467b48Spatrick       } else {
472509467b48Spatrick         NamedParametersFound = true;
472609467b48Spatrick         Pos += 1 + Argument.size();
472709467b48Spatrick       }
472809467b48Spatrick     }
472909467b48Spatrick     // Update the scan point.
473009467b48Spatrick     Body = Body.substr(Pos);
473109467b48Spatrick   }
473209467b48Spatrick 
473309467b48Spatrick   if (!NamedParametersFound && PositionalParametersFound)
473409467b48Spatrick     Warning(DirectiveLoc, "macro defined with named parameters which are not "
473509467b48Spatrick                           "used in macro body, possible positional parameter "
473609467b48Spatrick                           "found in body which will have no effect");
473709467b48Spatrick }
473809467b48Spatrick 
473909467b48Spatrick /// parseDirectiveExitMacro
474009467b48Spatrick /// ::= .exitm
parseDirectiveExitMacro(StringRef Directive)474109467b48Spatrick bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
4742a0747c9fSpatrick   if (parseEOL())
474309467b48Spatrick     return true;
474409467b48Spatrick 
474509467b48Spatrick   if (!isInsideMacroInstantiation())
474609467b48Spatrick     return TokError("unexpected '" + Directive + "' in file, "
474709467b48Spatrick                                                  "no current macro definition");
474809467b48Spatrick 
474909467b48Spatrick   // Exit all conditionals that are active in the current macro.
475009467b48Spatrick   while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
475109467b48Spatrick     TheCondState = TheCondStack.back();
475209467b48Spatrick     TheCondStack.pop_back();
475309467b48Spatrick   }
475409467b48Spatrick 
475509467b48Spatrick   handleMacroExit();
475609467b48Spatrick   return false;
475709467b48Spatrick }
475809467b48Spatrick 
475909467b48Spatrick /// parseDirectiveEndMacro
476009467b48Spatrick /// ::= .endm
476109467b48Spatrick /// ::= .endmacro
parseDirectiveEndMacro(StringRef Directive)476209467b48Spatrick bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
476309467b48Spatrick   if (getLexer().isNot(AsmToken::EndOfStatement))
476409467b48Spatrick     return TokError("unexpected token in '" + Directive + "' directive");
476509467b48Spatrick 
476609467b48Spatrick   // If we are inside a macro instantiation, terminate the current
476709467b48Spatrick   // instantiation.
476809467b48Spatrick   if (isInsideMacroInstantiation()) {
476909467b48Spatrick     handleMacroExit();
477009467b48Spatrick     return false;
477109467b48Spatrick   }
477209467b48Spatrick 
477309467b48Spatrick   // Otherwise, this .endmacro is a stray entry in the file; well formed
477409467b48Spatrick   // .endmacro directives are handled during the macro definition parsing.
477509467b48Spatrick   return TokError("unexpected '" + Directive + "' in file, "
477609467b48Spatrick                                                "no current macro definition");
477709467b48Spatrick }
477809467b48Spatrick 
477909467b48Spatrick /// parseDirectivePurgeMacro
4780a0747c9fSpatrick /// ::= .purgem name
parseDirectivePurgeMacro(SMLoc DirectiveLoc)478109467b48Spatrick bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
478209467b48Spatrick   StringRef Name;
478309467b48Spatrick   SMLoc Loc;
478409467b48Spatrick   if (parseTokenLoc(Loc) ||
478509467b48Spatrick       check(parseIdentifier(Name), Loc,
478609467b48Spatrick             "expected identifier in '.purgem' directive") ||
4787a0747c9fSpatrick       parseEOL())
478809467b48Spatrick     return true;
478909467b48Spatrick 
479009467b48Spatrick   if (!getContext().lookupMacro(Name))
479109467b48Spatrick     return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
479209467b48Spatrick 
479309467b48Spatrick   getContext().undefineMacro(Name);
479409467b48Spatrick   DEBUG_WITH_TYPE("asm-macros", dbgs()
479509467b48Spatrick                                     << "Un-defining macro: " << Name << "\n");
479609467b48Spatrick   return false;
479709467b48Spatrick }
479809467b48Spatrick 
479909467b48Spatrick /// parseDirectiveBundleAlignMode
480009467b48Spatrick /// ::= {.bundle_align_mode} expression
parseDirectiveBundleAlignMode()480109467b48Spatrick bool AsmParser::parseDirectiveBundleAlignMode() {
480209467b48Spatrick   // Expect a single argument: an expression that evaluates to a constant
480309467b48Spatrick   // in the inclusive range 0-30.
480409467b48Spatrick   SMLoc ExprLoc = getLexer().getLoc();
480509467b48Spatrick   int64_t AlignSizePow2;
480609467b48Spatrick   if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||
4807a0747c9fSpatrick       parseEOL() ||
480809467b48Spatrick       check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc,
480909467b48Spatrick             "invalid bundle alignment size (expected between 0 and 30)"))
481009467b48Spatrick     return true;
481109467b48Spatrick 
4812*a96b3639Srobert   getStreamer().emitBundleAlignMode(Align(1ULL << AlignSizePow2));
481309467b48Spatrick   return false;
481409467b48Spatrick }
481509467b48Spatrick 
481609467b48Spatrick /// parseDirectiveBundleLock
481709467b48Spatrick /// ::= {.bundle_lock} [align_to_end]
parseDirectiveBundleLock()481809467b48Spatrick bool AsmParser::parseDirectiveBundleLock() {
481909467b48Spatrick   if (checkForValidSection())
482009467b48Spatrick     return true;
482109467b48Spatrick   bool AlignToEnd = false;
482209467b48Spatrick 
482309467b48Spatrick   StringRef Option;
482409467b48Spatrick   SMLoc Loc = getTok().getLoc();
482509467b48Spatrick   const char *kInvalidOptionError =
482609467b48Spatrick       "invalid option for '.bundle_lock' directive";
482709467b48Spatrick 
482809467b48Spatrick   if (!parseOptionalToken(AsmToken::EndOfStatement)) {
482909467b48Spatrick     if (check(parseIdentifier(Option), Loc, kInvalidOptionError) ||
4830a0747c9fSpatrick         check(Option != "align_to_end", Loc, kInvalidOptionError) || parseEOL())
483109467b48Spatrick       return true;
483209467b48Spatrick     AlignToEnd = true;
483309467b48Spatrick   }
483409467b48Spatrick 
4835097a140dSpatrick   getStreamer().emitBundleLock(AlignToEnd);
483609467b48Spatrick   return false;
483709467b48Spatrick }
483809467b48Spatrick 
483909467b48Spatrick /// parseDirectiveBundleLock
484009467b48Spatrick /// ::= {.bundle_lock}
parseDirectiveBundleUnlock()484109467b48Spatrick bool AsmParser::parseDirectiveBundleUnlock() {
4842a0747c9fSpatrick   if (checkForValidSection() || parseEOL())
484309467b48Spatrick     return true;
484409467b48Spatrick 
4845097a140dSpatrick   getStreamer().emitBundleUnlock();
484609467b48Spatrick   return false;
484709467b48Spatrick }
484809467b48Spatrick 
484909467b48Spatrick /// parseDirectiveSpace
485009467b48Spatrick /// ::= (.skip | .space) expression [ , expression ]
parseDirectiveSpace(StringRef IDVal)485109467b48Spatrick bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
485209467b48Spatrick   SMLoc NumBytesLoc = Lexer.getLoc();
485309467b48Spatrick   const MCExpr *NumBytes;
485409467b48Spatrick   if (checkForValidSection() || parseExpression(NumBytes))
485509467b48Spatrick     return true;
485609467b48Spatrick 
485709467b48Spatrick   int64_t FillExpr = 0;
485809467b48Spatrick   if (parseOptionalToken(AsmToken::Comma))
485909467b48Spatrick     if (parseAbsoluteExpression(FillExpr))
4860a0747c9fSpatrick       return true;
4861a0747c9fSpatrick   if (parseEOL())
4862a0747c9fSpatrick     return true;
486309467b48Spatrick 
486409467b48Spatrick   // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
486509467b48Spatrick   getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
486609467b48Spatrick 
486709467b48Spatrick   return false;
486809467b48Spatrick }
486909467b48Spatrick 
487009467b48Spatrick /// parseDirectiveDCB
487109467b48Spatrick /// ::= .dcb.{b, l, w} expression, expression
parseDirectiveDCB(StringRef IDVal,unsigned Size)487209467b48Spatrick bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
487309467b48Spatrick   SMLoc NumValuesLoc = Lexer.getLoc();
487409467b48Spatrick   int64_t NumValues;
487509467b48Spatrick   if (checkForValidSection() || parseAbsoluteExpression(NumValues))
487609467b48Spatrick     return true;
487709467b48Spatrick 
487809467b48Spatrick   if (NumValues < 0) {
487909467b48Spatrick     Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
488009467b48Spatrick     return false;
488109467b48Spatrick   }
488209467b48Spatrick 
4883a0747c9fSpatrick   if (parseComma())
488409467b48Spatrick     return true;
488509467b48Spatrick 
488609467b48Spatrick   const MCExpr *Value;
488709467b48Spatrick   SMLoc ExprLoc = getLexer().getLoc();
488809467b48Spatrick   if (parseExpression(Value))
488909467b48Spatrick     return true;
489009467b48Spatrick 
489109467b48Spatrick   // Special case constant expressions to match code generator.
489209467b48Spatrick   if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
489309467b48Spatrick     assert(Size <= 8 && "Invalid size");
489409467b48Spatrick     uint64_t IntValue = MCE->getValue();
489509467b48Spatrick     if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
489609467b48Spatrick       return Error(ExprLoc, "literal value out of range for directive");
489709467b48Spatrick     for (uint64_t i = 0, e = NumValues; i != e; ++i)
4898097a140dSpatrick       getStreamer().emitIntValue(IntValue, Size);
489909467b48Spatrick   } else {
490009467b48Spatrick     for (uint64_t i = 0, e = NumValues; i != e; ++i)
4901097a140dSpatrick       getStreamer().emitValue(Value, Size, ExprLoc);
490209467b48Spatrick   }
490309467b48Spatrick 
4904a0747c9fSpatrick   return parseEOL();
490509467b48Spatrick }
490609467b48Spatrick 
490709467b48Spatrick /// parseDirectiveRealDCB
490809467b48Spatrick /// ::= .dcb.{d, s} expression, expression
parseDirectiveRealDCB(StringRef IDVal,const fltSemantics & Semantics)490909467b48Spatrick bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {
491009467b48Spatrick   SMLoc NumValuesLoc = Lexer.getLoc();
491109467b48Spatrick   int64_t NumValues;
491209467b48Spatrick   if (checkForValidSection() || parseAbsoluteExpression(NumValues))
491309467b48Spatrick     return true;
491409467b48Spatrick 
491509467b48Spatrick   if (NumValues < 0) {
491609467b48Spatrick     Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
491709467b48Spatrick     return false;
491809467b48Spatrick   }
491909467b48Spatrick 
4920a0747c9fSpatrick   if (parseComma())
492109467b48Spatrick     return true;
492209467b48Spatrick 
492309467b48Spatrick   APInt AsInt;
4924a0747c9fSpatrick   if (parseRealValue(Semantics, AsInt) || parseEOL())
492509467b48Spatrick     return true;
492609467b48Spatrick 
492709467b48Spatrick   for (uint64_t i = 0, e = NumValues; i != e; ++i)
4928097a140dSpatrick     getStreamer().emitIntValue(AsInt.getLimitedValue(),
492909467b48Spatrick                                AsInt.getBitWidth() / 8);
493009467b48Spatrick 
493109467b48Spatrick   return false;
493209467b48Spatrick }
493309467b48Spatrick 
493409467b48Spatrick /// parseDirectiveDS
493509467b48Spatrick /// ::= .ds.{b, d, l, p, s, w, x} expression
parseDirectiveDS(StringRef IDVal,unsigned Size)493609467b48Spatrick bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {
493709467b48Spatrick   SMLoc NumValuesLoc = Lexer.getLoc();
493809467b48Spatrick   int64_t NumValues;
4939a0747c9fSpatrick   if (checkForValidSection() || parseAbsoluteExpression(NumValues) ||
4940a0747c9fSpatrick       parseEOL())
494109467b48Spatrick     return true;
494209467b48Spatrick 
494309467b48Spatrick   if (NumValues < 0) {
494409467b48Spatrick     Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
494509467b48Spatrick     return false;
494609467b48Spatrick   }
494709467b48Spatrick 
494809467b48Spatrick   for (uint64_t i = 0, e = NumValues; i != e; ++i)
494909467b48Spatrick     getStreamer().emitFill(Size, 0);
495009467b48Spatrick 
495109467b48Spatrick   return false;
495209467b48Spatrick }
495309467b48Spatrick 
495409467b48Spatrick /// parseDirectiveLEB128
495509467b48Spatrick /// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
parseDirectiveLEB128(bool Signed)495609467b48Spatrick bool AsmParser::parseDirectiveLEB128(bool Signed) {
495709467b48Spatrick   if (checkForValidSection())
495809467b48Spatrick     return true;
495909467b48Spatrick 
496009467b48Spatrick   auto parseOp = [&]() -> bool {
496109467b48Spatrick     const MCExpr *Value;
496209467b48Spatrick     if (parseExpression(Value))
496309467b48Spatrick       return true;
496409467b48Spatrick     if (Signed)
4965097a140dSpatrick       getStreamer().emitSLEB128Value(Value);
496609467b48Spatrick     else
4967097a140dSpatrick       getStreamer().emitULEB128Value(Value);
496809467b48Spatrick     return false;
496909467b48Spatrick   };
497009467b48Spatrick 
4971a0747c9fSpatrick   return parseMany(parseOp);
497209467b48Spatrick }
497309467b48Spatrick 
497409467b48Spatrick /// parseDirectiveSymbolAttribute
497509467b48Spatrick ///  ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
parseDirectiveSymbolAttribute(MCSymbolAttr Attr)497609467b48Spatrick bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
497709467b48Spatrick   auto parseOp = [&]() -> bool {
497809467b48Spatrick     StringRef Name;
497909467b48Spatrick     SMLoc Loc = getTok().getLoc();
498009467b48Spatrick     if (parseIdentifier(Name))
498109467b48Spatrick       return Error(Loc, "expected identifier");
4982a0747c9fSpatrick 
4983a0747c9fSpatrick     if (discardLTOSymbol(Name))
4984a0747c9fSpatrick       return false;
4985a0747c9fSpatrick 
498609467b48Spatrick     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
498709467b48Spatrick 
4988*a96b3639Srobert     // Assembler local symbols don't make any sense here, except for directives
4989*a96b3639Srobert     // that the symbol should be tagged.
4990*a96b3639Srobert     if (Sym->isTemporary() && Attr != MCSA_Memtag)
499109467b48Spatrick       return Error(Loc, "non-local symbol required");
499209467b48Spatrick 
4993097a140dSpatrick     if (!getStreamer().emitSymbolAttribute(Sym, Attr))
499409467b48Spatrick       return Error(Loc, "unable to emit symbol attribute");
499509467b48Spatrick     return false;
499609467b48Spatrick   };
499709467b48Spatrick 
4998a0747c9fSpatrick   return parseMany(parseOp);
499909467b48Spatrick }
500009467b48Spatrick 
500109467b48Spatrick /// parseDirectiveComm
500209467b48Spatrick ///  ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
parseDirectiveComm(bool IsLocal)500309467b48Spatrick bool AsmParser::parseDirectiveComm(bool IsLocal) {
500409467b48Spatrick   if (checkForValidSection())
500509467b48Spatrick     return true;
500609467b48Spatrick 
500709467b48Spatrick   SMLoc IDLoc = getLexer().getLoc();
500809467b48Spatrick   StringRef Name;
500909467b48Spatrick   if (parseIdentifier(Name))
501009467b48Spatrick     return TokError("expected identifier in directive");
501109467b48Spatrick 
501209467b48Spatrick   // Handle the identifier as the key symbol.
501309467b48Spatrick   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
501409467b48Spatrick 
5015a0747c9fSpatrick   if (parseComma())
5016a0747c9fSpatrick     return true;
501709467b48Spatrick 
501809467b48Spatrick   int64_t Size;
501909467b48Spatrick   SMLoc SizeLoc = getLexer().getLoc();
502009467b48Spatrick   if (parseAbsoluteExpression(Size))
502109467b48Spatrick     return true;
502209467b48Spatrick 
502309467b48Spatrick   int64_t Pow2Alignment = 0;
502409467b48Spatrick   SMLoc Pow2AlignmentLoc;
502509467b48Spatrick   if (getLexer().is(AsmToken::Comma)) {
502609467b48Spatrick     Lex();
502709467b48Spatrick     Pow2AlignmentLoc = getLexer().getLoc();
502809467b48Spatrick     if (parseAbsoluteExpression(Pow2Alignment))
502909467b48Spatrick       return true;
503009467b48Spatrick 
503109467b48Spatrick     LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
503209467b48Spatrick     if (IsLocal && LCOMM == LCOMM::NoAlignment)
503309467b48Spatrick       return Error(Pow2AlignmentLoc, "alignment not supported on this target");
503409467b48Spatrick 
503509467b48Spatrick     // If this target takes alignments in bytes (not log) validate and convert.
503609467b48Spatrick     if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
503709467b48Spatrick         (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
503809467b48Spatrick       if (!isPowerOf2_64(Pow2Alignment))
503909467b48Spatrick         return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
504009467b48Spatrick       Pow2Alignment = Log2_64(Pow2Alignment);
504109467b48Spatrick     }
504209467b48Spatrick   }
504309467b48Spatrick 
5044a0747c9fSpatrick   if (parseEOL())
504509467b48Spatrick     return true;
504609467b48Spatrick 
504709467b48Spatrick   // NOTE: a size of zero for a .comm should create a undefined symbol
504809467b48Spatrick   // but a size of .lcomm creates a bss symbol of size zero.
504909467b48Spatrick   if (Size < 0)
5050*a96b3639Srobert     return Error(SizeLoc, "size must be non-negative");
505109467b48Spatrick 
505209467b48Spatrick   Sym->redefineIfPossible();
505309467b48Spatrick   if (!Sym->isUndefined())
505409467b48Spatrick     return Error(IDLoc, "invalid symbol redefinition");
505509467b48Spatrick 
505609467b48Spatrick   // Create the Symbol as a common or local common with Size and Pow2Alignment
505709467b48Spatrick   if (IsLocal) {
5058*a96b3639Srobert     getStreamer().emitLocalCommonSymbol(Sym, Size,
5059*a96b3639Srobert                                         Align(1ULL << Pow2Alignment));
506009467b48Spatrick     return false;
506109467b48Spatrick   }
506209467b48Spatrick 
5063*a96b3639Srobert   getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));
506409467b48Spatrick   return false;
506509467b48Spatrick }
506609467b48Spatrick 
506709467b48Spatrick /// parseDirectiveAbort
506809467b48Spatrick ///  ::= .abort [... message ...]
parseDirectiveAbort()506909467b48Spatrick bool AsmParser::parseDirectiveAbort() {
507009467b48Spatrick   // FIXME: Use loc from directive.
507109467b48Spatrick   SMLoc Loc = getLexer().getLoc();
507209467b48Spatrick 
507309467b48Spatrick   StringRef Str = parseStringToEndOfStatement();
5074a0747c9fSpatrick   if (parseEOL())
507509467b48Spatrick     return true;
507609467b48Spatrick 
507709467b48Spatrick   if (Str.empty())
507809467b48Spatrick     return Error(Loc, ".abort detected. Assembly stopping.");
507909467b48Spatrick   else
508009467b48Spatrick     return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
508109467b48Spatrick   // FIXME: Actually abort assembly here.
508209467b48Spatrick 
508309467b48Spatrick   return false;
508409467b48Spatrick }
508509467b48Spatrick 
508609467b48Spatrick /// parseDirectiveInclude
508709467b48Spatrick ///  ::= .include "filename"
parseDirectiveInclude()508809467b48Spatrick bool AsmParser::parseDirectiveInclude() {
508909467b48Spatrick   // Allow the strings to have escaped octal character sequence.
509009467b48Spatrick   std::string Filename;
509109467b48Spatrick   SMLoc IncludeLoc = getTok().getLoc();
509209467b48Spatrick 
509309467b48Spatrick   if (check(getTok().isNot(AsmToken::String),
509409467b48Spatrick             "expected string in '.include' directive") ||
509509467b48Spatrick       parseEscapedString(Filename) ||
509609467b48Spatrick       check(getTok().isNot(AsmToken::EndOfStatement),
509709467b48Spatrick             "unexpected token in '.include' directive") ||
509809467b48Spatrick       // Attempt to switch the lexer to the included file before consuming the
509909467b48Spatrick       // end of statement to avoid losing it when we switch.
510009467b48Spatrick       check(enterIncludeFile(Filename), IncludeLoc,
510109467b48Spatrick             "Could not find include file '" + Filename + "'"))
510209467b48Spatrick     return true;
510309467b48Spatrick 
510409467b48Spatrick   return false;
510509467b48Spatrick }
510609467b48Spatrick 
510709467b48Spatrick /// parseDirectiveIncbin
510809467b48Spatrick ///  ::= .incbin "filename" [ , skip [ , count ] ]
parseDirectiveIncbin()510909467b48Spatrick bool AsmParser::parseDirectiveIncbin() {
511009467b48Spatrick   // Allow the strings to have escaped octal character sequence.
511109467b48Spatrick   std::string Filename;
511209467b48Spatrick   SMLoc IncbinLoc = getTok().getLoc();
511309467b48Spatrick   if (check(getTok().isNot(AsmToken::String),
511409467b48Spatrick             "expected string in '.incbin' directive") ||
511509467b48Spatrick       parseEscapedString(Filename))
511609467b48Spatrick     return true;
511709467b48Spatrick 
511809467b48Spatrick   int64_t Skip = 0;
511909467b48Spatrick   const MCExpr *Count = nullptr;
512009467b48Spatrick   SMLoc SkipLoc, CountLoc;
512109467b48Spatrick   if (parseOptionalToken(AsmToken::Comma)) {
512209467b48Spatrick     // The skip expression can be omitted while specifying the count, e.g:
512309467b48Spatrick     //  .incbin "filename",,4
512409467b48Spatrick     if (getTok().isNot(AsmToken::Comma)) {
512509467b48Spatrick       if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))
512609467b48Spatrick         return true;
512709467b48Spatrick     }
512809467b48Spatrick     if (parseOptionalToken(AsmToken::Comma)) {
512909467b48Spatrick       CountLoc = getTok().getLoc();
513009467b48Spatrick       if (parseExpression(Count))
513109467b48Spatrick         return true;
513209467b48Spatrick     }
513309467b48Spatrick   }
513409467b48Spatrick 
5135a0747c9fSpatrick   if (parseEOL())
513609467b48Spatrick     return true;
513709467b48Spatrick 
513809467b48Spatrick   if (check(Skip < 0, SkipLoc, "skip is negative"))
513909467b48Spatrick     return true;
514009467b48Spatrick 
514109467b48Spatrick   // Attempt to process the included file.
514209467b48Spatrick   if (processIncbinFile(Filename, Skip, Count, CountLoc))
514309467b48Spatrick     return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
514409467b48Spatrick   return false;
514509467b48Spatrick }
514609467b48Spatrick 
514709467b48Spatrick /// parseDirectiveIf
514809467b48Spatrick /// ::= .if{,eq,ge,gt,le,lt,ne} expression
parseDirectiveIf(SMLoc DirectiveLoc,DirectiveKind DirKind)514909467b48Spatrick bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
515009467b48Spatrick   TheCondStack.push_back(TheCondState);
515109467b48Spatrick   TheCondState.TheCond = AsmCond::IfCond;
515209467b48Spatrick   if (TheCondState.Ignore) {
515309467b48Spatrick     eatToEndOfStatement();
515409467b48Spatrick   } else {
515509467b48Spatrick     int64_t ExprValue;
5156a0747c9fSpatrick     if (parseAbsoluteExpression(ExprValue) || parseEOL())
515709467b48Spatrick       return true;
515809467b48Spatrick 
515909467b48Spatrick     switch (DirKind) {
516009467b48Spatrick     default:
516109467b48Spatrick       llvm_unreachable("unsupported directive");
516209467b48Spatrick     case DK_IF:
516309467b48Spatrick     case DK_IFNE:
516409467b48Spatrick       break;
516509467b48Spatrick     case DK_IFEQ:
516609467b48Spatrick       ExprValue = ExprValue == 0;
516709467b48Spatrick       break;
516809467b48Spatrick     case DK_IFGE:
516909467b48Spatrick       ExprValue = ExprValue >= 0;
517009467b48Spatrick       break;
517109467b48Spatrick     case DK_IFGT:
517209467b48Spatrick       ExprValue = ExprValue > 0;
517309467b48Spatrick       break;
517409467b48Spatrick     case DK_IFLE:
517509467b48Spatrick       ExprValue = ExprValue <= 0;
517609467b48Spatrick       break;
517709467b48Spatrick     case DK_IFLT:
517809467b48Spatrick       ExprValue = ExprValue < 0;
517909467b48Spatrick       break;
518009467b48Spatrick     }
518109467b48Spatrick 
518209467b48Spatrick     TheCondState.CondMet = ExprValue;
518309467b48Spatrick     TheCondState.Ignore = !TheCondState.CondMet;
518409467b48Spatrick   }
518509467b48Spatrick 
518609467b48Spatrick   return false;
518709467b48Spatrick }
518809467b48Spatrick 
518909467b48Spatrick /// parseDirectiveIfb
519009467b48Spatrick /// ::= .ifb string
parseDirectiveIfb(SMLoc DirectiveLoc,bool ExpectBlank)519109467b48Spatrick bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
519209467b48Spatrick   TheCondStack.push_back(TheCondState);
519309467b48Spatrick   TheCondState.TheCond = AsmCond::IfCond;
519409467b48Spatrick 
519509467b48Spatrick   if (TheCondState.Ignore) {
519609467b48Spatrick     eatToEndOfStatement();
519709467b48Spatrick   } else {
519809467b48Spatrick     StringRef Str = parseStringToEndOfStatement();
519909467b48Spatrick 
5200a0747c9fSpatrick     if (parseEOL())
520109467b48Spatrick       return true;
520209467b48Spatrick 
520309467b48Spatrick     TheCondState.CondMet = ExpectBlank == Str.empty();
520409467b48Spatrick     TheCondState.Ignore = !TheCondState.CondMet;
520509467b48Spatrick   }
520609467b48Spatrick 
520709467b48Spatrick   return false;
520809467b48Spatrick }
520909467b48Spatrick 
521009467b48Spatrick /// parseDirectiveIfc
521109467b48Spatrick /// ::= .ifc string1, string2
521209467b48Spatrick /// ::= .ifnc string1, string2
parseDirectiveIfc(SMLoc DirectiveLoc,bool ExpectEqual)521309467b48Spatrick bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
521409467b48Spatrick   TheCondStack.push_back(TheCondState);
521509467b48Spatrick   TheCondState.TheCond = AsmCond::IfCond;
521609467b48Spatrick 
521709467b48Spatrick   if (TheCondState.Ignore) {
521809467b48Spatrick     eatToEndOfStatement();
521909467b48Spatrick   } else {
522009467b48Spatrick     StringRef Str1 = parseStringToComma();
522109467b48Spatrick 
5222a0747c9fSpatrick     if (parseComma())
522309467b48Spatrick       return true;
522409467b48Spatrick 
522509467b48Spatrick     StringRef Str2 = parseStringToEndOfStatement();
522609467b48Spatrick 
5227a0747c9fSpatrick     if (parseEOL())
522809467b48Spatrick       return true;
522909467b48Spatrick 
523009467b48Spatrick     TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
523109467b48Spatrick     TheCondState.Ignore = !TheCondState.CondMet;
523209467b48Spatrick   }
523309467b48Spatrick 
523409467b48Spatrick   return false;
523509467b48Spatrick }
523609467b48Spatrick 
523709467b48Spatrick /// parseDirectiveIfeqs
523809467b48Spatrick ///   ::= .ifeqs string1, string2
parseDirectiveIfeqs(SMLoc DirectiveLoc,bool ExpectEqual)523909467b48Spatrick bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
524009467b48Spatrick   if (Lexer.isNot(AsmToken::String)) {
524109467b48Spatrick     if (ExpectEqual)
524209467b48Spatrick       return TokError("expected string parameter for '.ifeqs' directive");
524309467b48Spatrick     return TokError("expected string parameter for '.ifnes' directive");
524409467b48Spatrick   }
524509467b48Spatrick 
524609467b48Spatrick   StringRef String1 = getTok().getStringContents();
524709467b48Spatrick   Lex();
524809467b48Spatrick 
524909467b48Spatrick   if (Lexer.isNot(AsmToken::Comma)) {
525009467b48Spatrick     if (ExpectEqual)
525109467b48Spatrick       return TokError(
525209467b48Spatrick           "expected comma after first string for '.ifeqs' directive");
525309467b48Spatrick     return TokError("expected comma after first string for '.ifnes' directive");
525409467b48Spatrick   }
525509467b48Spatrick 
525609467b48Spatrick   Lex();
525709467b48Spatrick 
525809467b48Spatrick   if (Lexer.isNot(AsmToken::String)) {
525909467b48Spatrick     if (ExpectEqual)
526009467b48Spatrick       return TokError("expected string parameter for '.ifeqs' directive");
526109467b48Spatrick     return TokError("expected string parameter for '.ifnes' directive");
526209467b48Spatrick   }
526309467b48Spatrick 
526409467b48Spatrick   StringRef String2 = getTok().getStringContents();
526509467b48Spatrick   Lex();
526609467b48Spatrick 
526709467b48Spatrick   TheCondStack.push_back(TheCondState);
526809467b48Spatrick   TheCondState.TheCond = AsmCond::IfCond;
526909467b48Spatrick   TheCondState.CondMet = ExpectEqual == (String1 == String2);
527009467b48Spatrick   TheCondState.Ignore = !TheCondState.CondMet;
527109467b48Spatrick 
527209467b48Spatrick   return false;
527309467b48Spatrick }
527409467b48Spatrick 
527509467b48Spatrick /// parseDirectiveIfdef
527609467b48Spatrick /// ::= .ifdef symbol
parseDirectiveIfdef(SMLoc DirectiveLoc,bool expect_defined)527709467b48Spatrick bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
527809467b48Spatrick   StringRef Name;
527909467b48Spatrick   TheCondStack.push_back(TheCondState);
528009467b48Spatrick   TheCondState.TheCond = AsmCond::IfCond;
528109467b48Spatrick 
528209467b48Spatrick   if (TheCondState.Ignore) {
528309467b48Spatrick     eatToEndOfStatement();
528409467b48Spatrick   } else {
528509467b48Spatrick     if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
5286a0747c9fSpatrick         parseEOL())
528709467b48Spatrick       return true;
528809467b48Spatrick 
528909467b48Spatrick     MCSymbol *Sym = getContext().lookupSymbol(Name);
529009467b48Spatrick 
529109467b48Spatrick     if (expect_defined)
529209467b48Spatrick       TheCondState.CondMet = (Sym && !Sym->isUndefined(false));
529309467b48Spatrick     else
529409467b48Spatrick       TheCondState.CondMet = (!Sym || Sym->isUndefined(false));
529509467b48Spatrick     TheCondState.Ignore = !TheCondState.CondMet;
529609467b48Spatrick   }
529709467b48Spatrick 
529809467b48Spatrick   return false;
529909467b48Spatrick }
530009467b48Spatrick 
530109467b48Spatrick /// parseDirectiveElseIf
530209467b48Spatrick /// ::= .elseif expression
parseDirectiveElseIf(SMLoc DirectiveLoc)530309467b48Spatrick bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
530409467b48Spatrick   if (TheCondState.TheCond != AsmCond::IfCond &&
530509467b48Spatrick       TheCondState.TheCond != AsmCond::ElseIfCond)
530609467b48Spatrick     return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
530709467b48Spatrick                                " .if or  an .elseif");
530809467b48Spatrick   TheCondState.TheCond = AsmCond::ElseIfCond;
530909467b48Spatrick 
531009467b48Spatrick   bool LastIgnoreState = false;
531109467b48Spatrick   if (!TheCondStack.empty())
531209467b48Spatrick     LastIgnoreState = TheCondStack.back().Ignore;
531309467b48Spatrick   if (LastIgnoreState || TheCondState.CondMet) {
531409467b48Spatrick     TheCondState.Ignore = true;
531509467b48Spatrick     eatToEndOfStatement();
531609467b48Spatrick   } else {
531709467b48Spatrick     int64_t ExprValue;
531809467b48Spatrick     if (parseAbsoluteExpression(ExprValue))
531909467b48Spatrick       return true;
532009467b48Spatrick 
5321a0747c9fSpatrick     if (parseEOL())
532209467b48Spatrick       return true;
532309467b48Spatrick 
532409467b48Spatrick     TheCondState.CondMet = ExprValue;
532509467b48Spatrick     TheCondState.Ignore = !TheCondState.CondMet;
532609467b48Spatrick   }
532709467b48Spatrick 
532809467b48Spatrick   return false;
532909467b48Spatrick }
533009467b48Spatrick 
533109467b48Spatrick /// parseDirectiveElse
533209467b48Spatrick /// ::= .else
parseDirectiveElse(SMLoc DirectiveLoc)533309467b48Spatrick bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
5334a0747c9fSpatrick   if (parseEOL())
533509467b48Spatrick     return true;
533609467b48Spatrick 
533709467b48Spatrick   if (TheCondState.TheCond != AsmCond::IfCond &&
533809467b48Spatrick       TheCondState.TheCond != AsmCond::ElseIfCond)
533909467b48Spatrick     return Error(DirectiveLoc, "Encountered a .else that doesn't follow "
534009467b48Spatrick                                " an .if or an .elseif");
534109467b48Spatrick   TheCondState.TheCond = AsmCond::ElseCond;
534209467b48Spatrick   bool LastIgnoreState = false;
534309467b48Spatrick   if (!TheCondStack.empty())
534409467b48Spatrick     LastIgnoreState = TheCondStack.back().Ignore;
534509467b48Spatrick   if (LastIgnoreState || TheCondState.CondMet)
534609467b48Spatrick     TheCondState.Ignore = true;
534709467b48Spatrick   else
534809467b48Spatrick     TheCondState.Ignore = false;
534909467b48Spatrick 
535009467b48Spatrick   return false;
535109467b48Spatrick }
535209467b48Spatrick 
535309467b48Spatrick /// parseDirectiveEnd
535409467b48Spatrick /// ::= .end
parseDirectiveEnd(SMLoc DirectiveLoc)535509467b48Spatrick bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5356a0747c9fSpatrick   if (parseEOL())
535709467b48Spatrick     return true;
535809467b48Spatrick 
535909467b48Spatrick   while (Lexer.isNot(AsmToken::Eof))
536009467b48Spatrick     Lexer.Lex();
536109467b48Spatrick 
536209467b48Spatrick   return false;
536309467b48Spatrick }
536409467b48Spatrick 
536509467b48Spatrick /// parseDirectiveError
536609467b48Spatrick ///   ::= .err
536709467b48Spatrick ///   ::= .error [string]
parseDirectiveError(SMLoc L,bool WithMessage)536809467b48Spatrick bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
536909467b48Spatrick   if (!TheCondStack.empty()) {
537009467b48Spatrick     if (TheCondStack.back().Ignore) {
537109467b48Spatrick       eatToEndOfStatement();
537209467b48Spatrick       return false;
537309467b48Spatrick     }
537409467b48Spatrick   }
537509467b48Spatrick 
537609467b48Spatrick   if (!WithMessage)
537709467b48Spatrick     return Error(L, ".err encountered");
537809467b48Spatrick 
537909467b48Spatrick   StringRef Message = ".error directive invoked in source file";
538009467b48Spatrick   if (Lexer.isNot(AsmToken::EndOfStatement)) {
538109467b48Spatrick     if (Lexer.isNot(AsmToken::String))
538209467b48Spatrick       return TokError(".error argument must be a string");
538309467b48Spatrick 
538409467b48Spatrick     Message = getTok().getStringContents();
538509467b48Spatrick     Lex();
538609467b48Spatrick   }
538709467b48Spatrick 
538809467b48Spatrick   return Error(L, Message);
538909467b48Spatrick }
539009467b48Spatrick 
539109467b48Spatrick /// parseDirectiveWarning
539209467b48Spatrick ///   ::= .warning [string]
parseDirectiveWarning(SMLoc L)539309467b48Spatrick bool AsmParser::parseDirectiveWarning(SMLoc L) {
539409467b48Spatrick   if (!TheCondStack.empty()) {
539509467b48Spatrick     if (TheCondStack.back().Ignore) {
539609467b48Spatrick       eatToEndOfStatement();
539709467b48Spatrick       return false;
539809467b48Spatrick     }
539909467b48Spatrick   }
540009467b48Spatrick 
540109467b48Spatrick   StringRef Message = ".warning directive invoked in source file";
540209467b48Spatrick 
540309467b48Spatrick   if (!parseOptionalToken(AsmToken::EndOfStatement)) {
540409467b48Spatrick     if (Lexer.isNot(AsmToken::String))
540509467b48Spatrick       return TokError(".warning argument must be a string");
540609467b48Spatrick 
540709467b48Spatrick     Message = getTok().getStringContents();
540809467b48Spatrick     Lex();
5409a0747c9fSpatrick     if (parseEOL())
541009467b48Spatrick       return true;
541109467b48Spatrick   }
541209467b48Spatrick 
541309467b48Spatrick   return Warning(L, Message);
541409467b48Spatrick }
541509467b48Spatrick 
541609467b48Spatrick /// parseDirectiveEndIf
541709467b48Spatrick /// ::= .endif
parseDirectiveEndIf(SMLoc DirectiveLoc)541809467b48Spatrick bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5419a0747c9fSpatrick   if (parseEOL())
542009467b48Spatrick     return true;
542109467b48Spatrick 
542209467b48Spatrick   if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
542309467b48Spatrick     return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
542409467b48Spatrick                                "an .if or .else");
542509467b48Spatrick   if (!TheCondStack.empty()) {
542609467b48Spatrick     TheCondState = TheCondStack.back();
542709467b48Spatrick     TheCondStack.pop_back();
542809467b48Spatrick   }
542909467b48Spatrick 
543009467b48Spatrick   return false;
543109467b48Spatrick }
543209467b48Spatrick 
initializeDirectiveKindMap()543309467b48Spatrick void AsmParser::initializeDirectiveKindMap() {
5434097a140dSpatrick   /* Lookup will be done with the directive
5435097a140dSpatrick    * converted to lower case, so all these
5436097a140dSpatrick    * keys should be lower case.
5437097a140dSpatrick    * (target specific directives are handled
5438097a140dSpatrick    *  elsewhere)
5439097a140dSpatrick    */
544009467b48Spatrick   DirectiveKindMap[".set"] = DK_SET;
544109467b48Spatrick   DirectiveKindMap[".equ"] = DK_EQU;
544209467b48Spatrick   DirectiveKindMap[".equiv"] = DK_EQUIV;
544309467b48Spatrick   DirectiveKindMap[".ascii"] = DK_ASCII;
544409467b48Spatrick   DirectiveKindMap[".asciz"] = DK_ASCIZ;
544509467b48Spatrick   DirectiveKindMap[".string"] = DK_STRING;
544609467b48Spatrick   DirectiveKindMap[".byte"] = DK_BYTE;
544709467b48Spatrick   DirectiveKindMap[".short"] = DK_SHORT;
544809467b48Spatrick   DirectiveKindMap[".value"] = DK_VALUE;
544909467b48Spatrick   DirectiveKindMap[".2byte"] = DK_2BYTE;
545009467b48Spatrick   DirectiveKindMap[".long"] = DK_LONG;
545109467b48Spatrick   DirectiveKindMap[".int"] = DK_INT;
545209467b48Spatrick   DirectiveKindMap[".4byte"] = DK_4BYTE;
545309467b48Spatrick   DirectiveKindMap[".quad"] = DK_QUAD;
545409467b48Spatrick   DirectiveKindMap[".8byte"] = DK_8BYTE;
545509467b48Spatrick   DirectiveKindMap[".octa"] = DK_OCTA;
545609467b48Spatrick   DirectiveKindMap[".single"] = DK_SINGLE;
545709467b48Spatrick   DirectiveKindMap[".float"] = DK_FLOAT;
545809467b48Spatrick   DirectiveKindMap[".double"] = DK_DOUBLE;
545909467b48Spatrick   DirectiveKindMap[".align"] = DK_ALIGN;
546009467b48Spatrick   DirectiveKindMap[".align32"] = DK_ALIGN32;
546109467b48Spatrick   DirectiveKindMap[".balign"] = DK_BALIGN;
546209467b48Spatrick   DirectiveKindMap[".balignw"] = DK_BALIGNW;
546309467b48Spatrick   DirectiveKindMap[".balignl"] = DK_BALIGNL;
546409467b48Spatrick   DirectiveKindMap[".p2align"] = DK_P2ALIGN;
546509467b48Spatrick   DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
546609467b48Spatrick   DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
546709467b48Spatrick   DirectiveKindMap[".org"] = DK_ORG;
546809467b48Spatrick   DirectiveKindMap[".fill"] = DK_FILL;
546909467b48Spatrick   DirectiveKindMap[".zero"] = DK_ZERO;
547009467b48Spatrick   DirectiveKindMap[".extern"] = DK_EXTERN;
547109467b48Spatrick   DirectiveKindMap[".globl"] = DK_GLOBL;
547209467b48Spatrick   DirectiveKindMap[".global"] = DK_GLOBAL;
547309467b48Spatrick   DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
547409467b48Spatrick   DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
547509467b48Spatrick   DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
547609467b48Spatrick   DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
547709467b48Spatrick   DirectiveKindMap[".reference"] = DK_REFERENCE;
547809467b48Spatrick   DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
547909467b48Spatrick   DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
548009467b48Spatrick   DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
548109467b48Spatrick   DirectiveKindMap[".cold"] = DK_COLD;
548209467b48Spatrick   DirectiveKindMap[".comm"] = DK_COMM;
548309467b48Spatrick   DirectiveKindMap[".common"] = DK_COMMON;
548409467b48Spatrick   DirectiveKindMap[".lcomm"] = DK_LCOMM;
548509467b48Spatrick   DirectiveKindMap[".abort"] = DK_ABORT;
548609467b48Spatrick   DirectiveKindMap[".include"] = DK_INCLUDE;
548709467b48Spatrick   DirectiveKindMap[".incbin"] = DK_INCBIN;
548809467b48Spatrick   DirectiveKindMap[".code16"] = DK_CODE16;
548909467b48Spatrick   DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
549009467b48Spatrick   DirectiveKindMap[".rept"] = DK_REPT;
549109467b48Spatrick   DirectiveKindMap[".rep"] = DK_REPT;
549209467b48Spatrick   DirectiveKindMap[".irp"] = DK_IRP;
549309467b48Spatrick   DirectiveKindMap[".irpc"] = DK_IRPC;
549409467b48Spatrick   DirectiveKindMap[".endr"] = DK_ENDR;
549509467b48Spatrick   DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE;
549609467b48Spatrick   DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK;
549709467b48Spatrick   DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK;
549809467b48Spatrick   DirectiveKindMap[".if"] = DK_IF;
549909467b48Spatrick   DirectiveKindMap[".ifeq"] = DK_IFEQ;
550009467b48Spatrick   DirectiveKindMap[".ifge"] = DK_IFGE;
550109467b48Spatrick   DirectiveKindMap[".ifgt"] = DK_IFGT;
550209467b48Spatrick   DirectiveKindMap[".ifle"] = DK_IFLE;
550309467b48Spatrick   DirectiveKindMap[".iflt"] = DK_IFLT;
550409467b48Spatrick   DirectiveKindMap[".ifne"] = DK_IFNE;
550509467b48Spatrick   DirectiveKindMap[".ifb"] = DK_IFB;
550609467b48Spatrick   DirectiveKindMap[".ifnb"] = DK_IFNB;
550709467b48Spatrick   DirectiveKindMap[".ifc"] = DK_IFC;
550809467b48Spatrick   DirectiveKindMap[".ifeqs"] = DK_IFEQS;
550909467b48Spatrick   DirectiveKindMap[".ifnc"] = DK_IFNC;
551009467b48Spatrick   DirectiveKindMap[".ifnes"] = DK_IFNES;
551109467b48Spatrick   DirectiveKindMap[".ifdef"] = DK_IFDEF;
551209467b48Spatrick   DirectiveKindMap[".ifndef"] = DK_IFNDEF;
551309467b48Spatrick   DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
551409467b48Spatrick   DirectiveKindMap[".elseif"] = DK_ELSEIF;
551509467b48Spatrick   DirectiveKindMap[".else"] = DK_ELSE;
551609467b48Spatrick   DirectiveKindMap[".end"] = DK_END;
551709467b48Spatrick   DirectiveKindMap[".endif"] = DK_ENDIF;
551809467b48Spatrick   DirectiveKindMap[".skip"] = DK_SKIP;
551909467b48Spatrick   DirectiveKindMap[".space"] = DK_SPACE;
552009467b48Spatrick   DirectiveKindMap[".file"] = DK_FILE;
552109467b48Spatrick   DirectiveKindMap[".line"] = DK_LINE;
552209467b48Spatrick   DirectiveKindMap[".loc"] = DK_LOC;
552309467b48Spatrick   DirectiveKindMap[".stabs"] = DK_STABS;
552409467b48Spatrick   DirectiveKindMap[".cv_file"] = DK_CV_FILE;
552509467b48Spatrick   DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
552609467b48Spatrick   DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
552709467b48Spatrick   DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
552809467b48Spatrick   DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
552909467b48Spatrick   DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
553009467b48Spatrick   DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
553109467b48Spatrick   DirectiveKindMap[".cv_string"] = DK_CV_STRING;
553209467b48Spatrick   DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
553309467b48Spatrick   DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
553409467b48Spatrick   DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
553509467b48Spatrick   DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
553609467b48Spatrick   DirectiveKindMap[".sleb128"] = DK_SLEB128;
553709467b48Spatrick   DirectiveKindMap[".uleb128"] = DK_ULEB128;
553809467b48Spatrick   DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
553909467b48Spatrick   DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
554009467b48Spatrick   DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
554109467b48Spatrick   DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
554209467b48Spatrick   DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
554309467b48Spatrick   DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
554409467b48Spatrick   DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
5545a0747c9fSpatrick   DirectiveKindMap[".cfi_llvm_def_aspace_cfa"] = DK_CFI_LLVM_DEF_ASPACE_CFA;
554609467b48Spatrick   DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
554709467b48Spatrick   DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
554809467b48Spatrick   DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
554909467b48Spatrick   DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
555009467b48Spatrick   DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
555109467b48Spatrick   DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
555209467b48Spatrick   DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
555309467b48Spatrick   DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
555409467b48Spatrick   DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
555509467b48Spatrick   DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
555609467b48Spatrick   DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
555709467b48Spatrick   DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
555809467b48Spatrick   DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
555909467b48Spatrick   DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
556009467b48Spatrick   DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
5561*a96b3639Srobert   DirectiveKindMap[".cfi_mte_tagged_frame"] = DK_CFI_MTE_TAGGED_FRAME;
556209467b48Spatrick   DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
556309467b48Spatrick   DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
556409467b48Spatrick   DirectiveKindMap[".macro"] = DK_MACRO;
556509467b48Spatrick   DirectiveKindMap[".exitm"] = DK_EXITM;
556609467b48Spatrick   DirectiveKindMap[".endm"] = DK_ENDM;
556709467b48Spatrick   DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
556809467b48Spatrick   DirectiveKindMap[".purgem"] = DK_PURGEM;
556909467b48Spatrick   DirectiveKindMap[".err"] = DK_ERR;
557009467b48Spatrick   DirectiveKindMap[".error"] = DK_ERROR;
557109467b48Spatrick   DirectiveKindMap[".warning"] = DK_WARNING;
557209467b48Spatrick   DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
557309467b48Spatrick   DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
557409467b48Spatrick   DirectiveKindMap[".reloc"] = DK_RELOC;
557509467b48Spatrick   DirectiveKindMap[".dc"] = DK_DC;
557609467b48Spatrick   DirectiveKindMap[".dc.a"] = DK_DC_A;
557709467b48Spatrick   DirectiveKindMap[".dc.b"] = DK_DC_B;
557809467b48Spatrick   DirectiveKindMap[".dc.d"] = DK_DC_D;
557909467b48Spatrick   DirectiveKindMap[".dc.l"] = DK_DC_L;
558009467b48Spatrick   DirectiveKindMap[".dc.s"] = DK_DC_S;
558109467b48Spatrick   DirectiveKindMap[".dc.w"] = DK_DC_W;
558209467b48Spatrick   DirectiveKindMap[".dc.x"] = DK_DC_X;
558309467b48Spatrick   DirectiveKindMap[".dcb"] = DK_DCB;
558409467b48Spatrick   DirectiveKindMap[".dcb.b"] = DK_DCB_B;
558509467b48Spatrick   DirectiveKindMap[".dcb.d"] = DK_DCB_D;
558609467b48Spatrick   DirectiveKindMap[".dcb.l"] = DK_DCB_L;
558709467b48Spatrick   DirectiveKindMap[".dcb.s"] = DK_DCB_S;
558809467b48Spatrick   DirectiveKindMap[".dcb.w"] = DK_DCB_W;
558909467b48Spatrick   DirectiveKindMap[".dcb.x"] = DK_DCB_X;
559009467b48Spatrick   DirectiveKindMap[".ds"] = DK_DS;
559109467b48Spatrick   DirectiveKindMap[".ds.b"] = DK_DS_B;
559209467b48Spatrick   DirectiveKindMap[".ds.d"] = DK_DS_D;
559309467b48Spatrick   DirectiveKindMap[".ds.l"] = DK_DS_L;
559409467b48Spatrick   DirectiveKindMap[".ds.p"] = DK_DS_P;
559509467b48Spatrick   DirectiveKindMap[".ds.s"] = DK_DS_S;
559609467b48Spatrick   DirectiveKindMap[".ds.w"] = DK_DS_W;
559709467b48Spatrick   DirectiveKindMap[".ds.x"] = DK_DS_X;
559809467b48Spatrick   DirectiveKindMap[".print"] = DK_PRINT;
559909467b48Spatrick   DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
560009467b48Spatrick   DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
5601a0747c9fSpatrick   DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE;
5602a0747c9fSpatrick   DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD;
5603*a96b3639Srobert   DirectiveKindMap[".lto_set_conditional"] = DK_LTO_SET_CONDITIONAL;
5604*a96b3639Srobert   DirectiveKindMap[".memtag"] = DK_MEMTAG;
560509467b48Spatrick }
560609467b48Spatrick 
parseMacroLikeBody(SMLoc DirectiveLoc)560709467b48Spatrick MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
560809467b48Spatrick   AsmToken EndToken, StartToken = getTok();
560909467b48Spatrick 
561009467b48Spatrick   unsigned NestLevel = 0;
561109467b48Spatrick   while (true) {
561209467b48Spatrick     // Check whether we have reached the end of the file.
561309467b48Spatrick     if (getLexer().is(AsmToken::Eof)) {
561409467b48Spatrick       printError(DirectiveLoc, "no matching '.endr' in definition");
561509467b48Spatrick       return nullptr;
561609467b48Spatrick     }
561709467b48Spatrick 
561809467b48Spatrick     if (Lexer.is(AsmToken::Identifier) &&
561909467b48Spatrick         (getTok().getIdentifier() == ".rep" ||
562009467b48Spatrick          getTok().getIdentifier() == ".rept" ||
562109467b48Spatrick          getTok().getIdentifier() == ".irp" ||
562209467b48Spatrick          getTok().getIdentifier() == ".irpc")) {
562309467b48Spatrick       ++NestLevel;
562409467b48Spatrick     }
562509467b48Spatrick 
562609467b48Spatrick     // Otherwise, check whether we have reached the .endr.
562709467b48Spatrick     if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") {
562809467b48Spatrick       if (NestLevel == 0) {
562909467b48Spatrick         EndToken = getTok();
563009467b48Spatrick         Lex();
563109467b48Spatrick         if (Lexer.isNot(AsmToken::EndOfStatement)) {
563209467b48Spatrick           printError(getTok().getLoc(),
563309467b48Spatrick                      "unexpected token in '.endr' directive");
563409467b48Spatrick           return nullptr;
563509467b48Spatrick         }
563609467b48Spatrick         break;
563709467b48Spatrick       }
563809467b48Spatrick       --NestLevel;
563909467b48Spatrick     }
564009467b48Spatrick 
564109467b48Spatrick     // Otherwise, scan till the end of the statement.
564209467b48Spatrick     eatToEndOfStatement();
564309467b48Spatrick   }
564409467b48Spatrick 
564509467b48Spatrick   const char *BodyStart = StartToken.getLoc().getPointer();
564609467b48Spatrick   const char *BodyEnd = EndToken.getLoc().getPointer();
564709467b48Spatrick   StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
564809467b48Spatrick 
564909467b48Spatrick   // We Are Anonymous.
565009467b48Spatrick   MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
565109467b48Spatrick   return &MacroLikeBodies.back();
565209467b48Spatrick }
565309467b48Spatrick 
instantiateMacroLikeBody(MCAsmMacro * M,SMLoc DirectiveLoc,raw_svector_ostream & OS)565409467b48Spatrick void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
565509467b48Spatrick                                          raw_svector_ostream &OS) {
565609467b48Spatrick   OS << ".endr\n";
565709467b48Spatrick 
565809467b48Spatrick   std::unique_ptr<MemoryBuffer> Instantiation =
565909467b48Spatrick       MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
566009467b48Spatrick 
566109467b48Spatrick   // Create the macro instantiation object and add to the current macro
566209467b48Spatrick   // instantiation stack.
566309467b48Spatrick   MacroInstantiation *MI = new MacroInstantiation{
566409467b48Spatrick       DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
566509467b48Spatrick   ActiveMacros.push_back(MI);
566609467b48Spatrick 
566709467b48Spatrick   // Jump to the macro instantiation and prime the lexer.
566809467b48Spatrick   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
566909467b48Spatrick   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
567009467b48Spatrick   Lex();
567109467b48Spatrick }
567209467b48Spatrick 
567309467b48Spatrick /// parseDirectiveRept
567409467b48Spatrick ///   ::= .rep | .rept count
parseDirectiveRept(SMLoc DirectiveLoc,StringRef Dir)567509467b48Spatrick bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
567609467b48Spatrick   const MCExpr *CountExpr;
567709467b48Spatrick   SMLoc CountLoc = getTok().getLoc();
567809467b48Spatrick   if (parseExpression(CountExpr))
567909467b48Spatrick     return true;
568009467b48Spatrick 
568109467b48Spatrick   int64_t Count;
568209467b48Spatrick   if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
568309467b48Spatrick     return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
568409467b48Spatrick   }
568509467b48Spatrick 
5686a0747c9fSpatrick   if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())
568709467b48Spatrick     return true;
568809467b48Spatrick 
568909467b48Spatrick   // Lex the rept definition.
569009467b48Spatrick   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
569109467b48Spatrick   if (!M)
569209467b48Spatrick     return true;
569309467b48Spatrick 
569409467b48Spatrick   // Macro instantiation is lexical, unfortunately. We construct a new buffer
569509467b48Spatrick   // to hold the macro body with substitutions.
569609467b48Spatrick   SmallString<256> Buf;
569709467b48Spatrick   raw_svector_ostream OS(Buf);
569809467b48Spatrick   while (Count--) {
569909467b48Spatrick     // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
5700*a96b3639Srobert     if (expandMacro(OS, M->Body, std::nullopt, std::nullopt, false,
5701*a96b3639Srobert                     getTok().getLoc()))
570209467b48Spatrick       return true;
570309467b48Spatrick   }
570409467b48Spatrick   instantiateMacroLikeBody(M, DirectiveLoc, OS);
570509467b48Spatrick 
570609467b48Spatrick   return false;
570709467b48Spatrick }
570809467b48Spatrick 
570909467b48Spatrick /// parseDirectiveIrp
571009467b48Spatrick /// ::= .irp symbol,values
parseDirectiveIrp(SMLoc DirectiveLoc)571109467b48Spatrick bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
571209467b48Spatrick   MCAsmMacroParameter Parameter;
571309467b48Spatrick   MCAsmMacroArguments A;
571409467b48Spatrick   if (check(parseIdentifier(Parameter.Name),
571509467b48Spatrick             "expected identifier in '.irp' directive") ||
5716a0747c9fSpatrick       parseComma() || parseMacroArguments(nullptr, A) || parseEOL())
571709467b48Spatrick     return true;
571809467b48Spatrick 
571909467b48Spatrick   // Lex the irp definition.
572009467b48Spatrick   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
572109467b48Spatrick   if (!M)
572209467b48Spatrick     return true;
572309467b48Spatrick 
572409467b48Spatrick   // Macro instantiation is lexical, unfortunately. We construct a new buffer
572509467b48Spatrick   // to hold the macro body with substitutions.
572609467b48Spatrick   SmallString<256> Buf;
572709467b48Spatrick   raw_svector_ostream OS(Buf);
572809467b48Spatrick 
572909467b48Spatrick   for (const MCAsmMacroArgument &Arg : A) {
573009467b48Spatrick     // Note that the AtPseudoVariable is enabled for instantiations of .irp.
573109467b48Spatrick     // This is undocumented, but GAS seems to support it.
573209467b48Spatrick     if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
573309467b48Spatrick       return true;
573409467b48Spatrick   }
573509467b48Spatrick 
573609467b48Spatrick   instantiateMacroLikeBody(M, DirectiveLoc, OS);
573709467b48Spatrick 
573809467b48Spatrick   return false;
573909467b48Spatrick }
574009467b48Spatrick 
574109467b48Spatrick /// parseDirectiveIrpc
574209467b48Spatrick /// ::= .irpc symbol,values
parseDirectiveIrpc(SMLoc DirectiveLoc)574309467b48Spatrick bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
574409467b48Spatrick   MCAsmMacroParameter Parameter;
574509467b48Spatrick   MCAsmMacroArguments A;
574609467b48Spatrick 
574709467b48Spatrick   if (check(parseIdentifier(Parameter.Name),
574809467b48Spatrick             "expected identifier in '.irpc' directive") ||
5749a0747c9fSpatrick       parseComma() || parseMacroArguments(nullptr, A))
575009467b48Spatrick     return true;
575109467b48Spatrick 
575209467b48Spatrick   if (A.size() != 1 || A.front().size() != 1)
575309467b48Spatrick     return TokError("unexpected token in '.irpc' directive");
5754a0747c9fSpatrick   if (parseEOL())
575509467b48Spatrick     return true;
575609467b48Spatrick 
575709467b48Spatrick   // Lex the irpc definition.
575809467b48Spatrick   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
575909467b48Spatrick   if (!M)
576009467b48Spatrick     return true;
576109467b48Spatrick 
576209467b48Spatrick   // Macro instantiation is lexical, unfortunately. We construct a new buffer
576309467b48Spatrick   // to hold the macro body with substitutions.
576409467b48Spatrick   SmallString<256> Buf;
576509467b48Spatrick   raw_svector_ostream OS(Buf);
576609467b48Spatrick 
576709467b48Spatrick   StringRef Values = A.front().front().getString();
576809467b48Spatrick   for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
576909467b48Spatrick     MCAsmMacroArgument Arg;
577009467b48Spatrick     Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
577109467b48Spatrick 
577209467b48Spatrick     // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
577309467b48Spatrick     // This is undocumented, but GAS seems to support it.
577409467b48Spatrick     if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
577509467b48Spatrick       return true;
577609467b48Spatrick   }
577709467b48Spatrick 
577809467b48Spatrick   instantiateMacroLikeBody(M, DirectiveLoc, OS);
577909467b48Spatrick 
578009467b48Spatrick   return false;
578109467b48Spatrick }
578209467b48Spatrick 
parseDirectiveEndr(SMLoc DirectiveLoc)578309467b48Spatrick bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
578409467b48Spatrick   if (ActiveMacros.empty())
578509467b48Spatrick     return TokError("unmatched '.endr' directive");
578609467b48Spatrick 
578709467b48Spatrick   // The only .repl that should get here are the ones created by
578809467b48Spatrick   // instantiateMacroLikeBody.
578909467b48Spatrick   assert(getLexer().is(AsmToken::EndOfStatement));
579009467b48Spatrick 
579109467b48Spatrick   handleMacroExit();
579209467b48Spatrick   return false;
579309467b48Spatrick }
579409467b48Spatrick 
parseDirectiveMSEmit(SMLoc IDLoc,ParseStatementInfo & Info,size_t Len)579509467b48Spatrick bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
579609467b48Spatrick                                      size_t Len) {
579709467b48Spatrick   const MCExpr *Value;
579809467b48Spatrick   SMLoc ExprLoc = getLexer().getLoc();
579909467b48Spatrick   if (parseExpression(Value))
580009467b48Spatrick     return true;
580109467b48Spatrick   const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
580209467b48Spatrick   if (!MCE)
580309467b48Spatrick     return Error(ExprLoc, "unexpected expression in _emit");
580409467b48Spatrick   uint64_t IntValue = MCE->getValue();
580509467b48Spatrick   if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
580609467b48Spatrick     return Error(ExprLoc, "literal value out of range for directive");
580709467b48Spatrick 
580809467b48Spatrick   Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
580909467b48Spatrick   return false;
581009467b48Spatrick }
581109467b48Spatrick 
parseDirectiveMSAlign(SMLoc IDLoc,ParseStatementInfo & Info)581209467b48Spatrick bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
581309467b48Spatrick   const MCExpr *Value;
581409467b48Spatrick   SMLoc ExprLoc = getLexer().getLoc();
581509467b48Spatrick   if (parseExpression(Value))
581609467b48Spatrick     return true;
581709467b48Spatrick   const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
581809467b48Spatrick   if (!MCE)
581909467b48Spatrick     return Error(ExprLoc, "unexpected expression in align");
582009467b48Spatrick   uint64_t IntValue = MCE->getValue();
582109467b48Spatrick   if (!isPowerOf2_64(IntValue))
582209467b48Spatrick     return Error(ExprLoc, "literal value not a power of two greater then zero");
582309467b48Spatrick 
582409467b48Spatrick   Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
582509467b48Spatrick   return false;
582609467b48Spatrick }
582709467b48Spatrick 
parseDirectivePrint(SMLoc DirectiveLoc)582809467b48Spatrick bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
582909467b48Spatrick   const AsmToken StrTok = getTok();
583009467b48Spatrick   Lex();
583109467b48Spatrick   if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
583209467b48Spatrick     return Error(DirectiveLoc, "expected double quoted string after .print");
5833a0747c9fSpatrick   if (parseEOL())
583409467b48Spatrick     return true;
583509467b48Spatrick   llvm::outs() << StrTok.getStringContents() << '\n';
583609467b48Spatrick   return false;
583709467b48Spatrick }
583809467b48Spatrick 
parseDirectiveAddrsig()583909467b48Spatrick bool AsmParser::parseDirectiveAddrsig() {
5840a0747c9fSpatrick   if (parseEOL())
5841a0747c9fSpatrick     return true;
5842097a140dSpatrick   getStreamer().emitAddrsig();
584309467b48Spatrick   return false;
584409467b48Spatrick }
584509467b48Spatrick 
parseDirectiveAddrsigSym()584609467b48Spatrick bool AsmParser::parseDirectiveAddrsigSym() {
584709467b48Spatrick   StringRef Name;
5848a0747c9fSpatrick   if (check(parseIdentifier(Name), "expected identifier") || parseEOL())
584909467b48Spatrick     return true;
585009467b48Spatrick   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5851097a140dSpatrick   getStreamer().emitAddrsigSym(Sym);
585209467b48Spatrick   return false;
585309467b48Spatrick }
585409467b48Spatrick 
parseDirectivePseudoProbe()5855a0747c9fSpatrick bool AsmParser::parseDirectivePseudoProbe() {
5856a0747c9fSpatrick   int64_t Guid;
5857a0747c9fSpatrick   int64_t Index;
5858a0747c9fSpatrick   int64_t Type;
5859a0747c9fSpatrick   int64_t Attr;
5860a0747c9fSpatrick 
5861a0747c9fSpatrick   if (getLexer().is(AsmToken::Integer)) {
5862a0747c9fSpatrick     if (parseIntToken(Guid, "unexpected token in '.pseudoprobe' directive"))
5863a0747c9fSpatrick       return true;
5864a0747c9fSpatrick   }
5865a0747c9fSpatrick 
5866a0747c9fSpatrick   if (getLexer().is(AsmToken::Integer)) {
5867a0747c9fSpatrick     if (parseIntToken(Index, "unexpected token in '.pseudoprobe' directive"))
5868a0747c9fSpatrick       return true;
5869a0747c9fSpatrick   }
5870a0747c9fSpatrick 
5871a0747c9fSpatrick   if (getLexer().is(AsmToken::Integer)) {
5872a0747c9fSpatrick     if (parseIntToken(Type, "unexpected token in '.pseudoprobe' directive"))
5873a0747c9fSpatrick       return true;
5874a0747c9fSpatrick   }
5875a0747c9fSpatrick 
5876a0747c9fSpatrick   if (getLexer().is(AsmToken::Integer)) {
5877a0747c9fSpatrick     if (parseIntToken(Attr, "unexpected token in '.pseudoprobe' directive"))
5878a0747c9fSpatrick       return true;
5879a0747c9fSpatrick   }
5880a0747c9fSpatrick 
5881a0747c9fSpatrick   // Parse inline stack like @ GUID:11:12 @ GUID:1:11 @ GUID:3:21
5882a0747c9fSpatrick   MCPseudoProbeInlineStack InlineStack;
5883a0747c9fSpatrick 
5884a0747c9fSpatrick   while (getLexer().is(AsmToken::At)) {
5885a0747c9fSpatrick     // eat @
5886a0747c9fSpatrick     Lex();
5887a0747c9fSpatrick 
5888a0747c9fSpatrick     int64_t CallerGuid = 0;
5889a0747c9fSpatrick     if (getLexer().is(AsmToken::Integer)) {
5890a0747c9fSpatrick       if (parseIntToken(CallerGuid,
5891a0747c9fSpatrick                         "unexpected token in '.pseudoprobe' directive"))
5892a0747c9fSpatrick         return true;
5893a0747c9fSpatrick     }
5894a0747c9fSpatrick 
5895a0747c9fSpatrick     // eat colon
5896a0747c9fSpatrick     if (getLexer().is(AsmToken::Colon))
5897a0747c9fSpatrick       Lex();
5898a0747c9fSpatrick 
5899a0747c9fSpatrick     int64_t CallerProbeId = 0;
5900a0747c9fSpatrick     if (getLexer().is(AsmToken::Integer)) {
5901a0747c9fSpatrick       if (parseIntToken(CallerProbeId,
5902a0747c9fSpatrick                         "unexpected token in '.pseudoprobe' directive"))
5903a0747c9fSpatrick         return true;
5904a0747c9fSpatrick     }
5905a0747c9fSpatrick 
5906a0747c9fSpatrick     InlineSite Site(CallerGuid, CallerProbeId);
5907a0747c9fSpatrick     InlineStack.push_back(Site);
5908a0747c9fSpatrick   }
5909a0747c9fSpatrick 
5910*a96b3639Srobert   // Parse function entry name
5911*a96b3639Srobert   StringRef FnName;
5912*a96b3639Srobert   if (parseIdentifier(FnName))
5913*a96b3639Srobert     return Error(getLexer().getLoc(), "unexpected token in '.pseudoprobe' directive");
5914*a96b3639Srobert   MCSymbol *FnSym = getContext().lookupSymbol(FnName);
5915*a96b3639Srobert 
5916a0747c9fSpatrick   if (parseEOL())
5917a0747c9fSpatrick     return true;
5918a0747c9fSpatrick 
5919*a96b3639Srobert   getStreamer().emitPseudoProbe(Guid, Index, Type, Attr, InlineStack, FnSym);
5920a0747c9fSpatrick   return false;
5921a0747c9fSpatrick }
5922a0747c9fSpatrick 
5923a0747c9fSpatrick /// parseDirectiveLTODiscard
5924a0747c9fSpatrick ///  ::= ".lto_discard" [ identifier ( , identifier )* ]
5925a0747c9fSpatrick /// The LTO library emits this directive to discard non-prevailing symbols.
5926a0747c9fSpatrick /// We ignore symbol assignments and attribute changes for the specified
5927a0747c9fSpatrick /// symbols.
parseDirectiveLTODiscard()5928a0747c9fSpatrick bool AsmParser::parseDirectiveLTODiscard() {
5929a0747c9fSpatrick   auto ParseOp = [&]() -> bool {
5930a0747c9fSpatrick     StringRef Name;
5931a0747c9fSpatrick     SMLoc Loc = getTok().getLoc();
5932a0747c9fSpatrick     if (parseIdentifier(Name))
5933a0747c9fSpatrick       return Error(Loc, "expected identifier");
5934a0747c9fSpatrick     LTODiscardSymbols.insert(Name);
5935a0747c9fSpatrick     return false;
5936a0747c9fSpatrick   };
5937a0747c9fSpatrick 
5938a0747c9fSpatrick   LTODiscardSymbols.clear();
5939a0747c9fSpatrick   return parseMany(ParseOp);
5940a0747c9fSpatrick }
5941a0747c9fSpatrick 
594209467b48Spatrick // We are comparing pointers, but the pointers are relative to a single string.
594309467b48Spatrick // Thus, this should always be deterministic.
rewritesSort(const AsmRewrite * AsmRewriteA,const AsmRewrite * AsmRewriteB)594409467b48Spatrick static int rewritesSort(const AsmRewrite *AsmRewriteA,
594509467b48Spatrick                         const AsmRewrite *AsmRewriteB) {
594609467b48Spatrick   if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
594709467b48Spatrick     return -1;
594809467b48Spatrick   if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
594909467b48Spatrick     return 1;
595009467b48Spatrick 
595109467b48Spatrick   // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
595209467b48Spatrick   // rewrite to the same location.  Make sure the SizeDirective rewrite is
595309467b48Spatrick   // performed first, then the Imm/ImmPrefix and finally the Input/Output.  This
595409467b48Spatrick   // ensures the sort algorithm is stable.
595509467b48Spatrick   if (AsmRewritePrecedence[AsmRewriteA->Kind] >
595609467b48Spatrick       AsmRewritePrecedence[AsmRewriteB->Kind])
595709467b48Spatrick     return -1;
595809467b48Spatrick 
595909467b48Spatrick   if (AsmRewritePrecedence[AsmRewriteA->Kind] <
596009467b48Spatrick       AsmRewritePrecedence[AsmRewriteB->Kind])
596109467b48Spatrick     return 1;
596209467b48Spatrick   llvm_unreachable("Unstable rewrite sort.");
596309467b48Spatrick }
596409467b48Spatrick 
parseMSInlineAsm(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)596509467b48Spatrick bool AsmParser::parseMSInlineAsm(
5966a0747c9fSpatrick     std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,
5967a0747c9fSpatrick     SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
596809467b48Spatrick     SmallVectorImpl<std::string> &Constraints,
596909467b48Spatrick     SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
597009467b48Spatrick     const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
597109467b48Spatrick   SmallVector<void *, 4> InputDecls;
597209467b48Spatrick   SmallVector<void *, 4> OutputDecls;
597309467b48Spatrick   SmallVector<bool, 4> InputDeclsAddressOf;
597409467b48Spatrick   SmallVector<bool, 4> OutputDeclsAddressOf;
597509467b48Spatrick   SmallVector<std::string, 4> InputConstraints;
597609467b48Spatrick   SmallVector<std::string, 4> OutputConstraints;
597709467b48Spatrick   SmallVector<unsigned, 4> ClobberRegs;
597809467b48Spatrick 
597909467b48Spatrick   SmallVector<AsmRewrite, 4> AsmStrRewrites;
598009467b48Spatrick 
598109467b48Spatrick   // Prime the lexer.
598209467b48Spatrick   Lex();
598309467b48Spatrick 
598409467b48Spatrick   // While we have input, parse each statement.
598509467b48Spatrick   unsigned InputIdx = 0;
598609467b48Spatrick   unsigned OutputIdx = 0;
598709467b48Spatrick   while (getLexer().isNot(AsmToken::Eof)) {
598809467b48Spatrick     // Parse curly braces marking block start/end
598909467b48Spatrick     if (parseCurlyBlockScope(AsmStrRewrites))
599009467b48Spatrick       continue;
599109467b48Spatrick 
599209467b48Spatrick     ParseStatementInfo Info(&AsmStrRewrites);
599309467b48Spatrick     bool StatementErr = parseStatement(Info, &SI);
599409467b48Spatrick 
599509467b48Spatrick     if (StatementErr || Info.ParseError) {
599609467b48Spatrick       // Emit pending errors if any exist.
599709467b48Spatrick       printPendingErrors();
599809467b48Spatrick       return true;
599909467b48Spatrick     }
600009467b48Spatrick 
600109467b48Spatrick     // No pending error should exist here.
600209467b48Spatrick     assert(!hasPendingError() && "unexpected error from parseStatement");
600309467b48Spatrick 
600409467b48Spatrick     if (Info.Opcode == ~0U)
600509467b48Spatrick       continue;
600609467b48Spatrick 
600709467b48Spatrick     const MCInstrDesc &Desc = MII->get(Info.Opcode);
600809467b48Spatrick 
600909467b48Spatrick     // Build the list of clobbers, outputs and inputs.
601009467b48Spatrick     for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
601109467b48Spatrick       MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
601209467b48Spatrick 
601309467b48Spatrick       // Register operand.
601409467b48Spatrick       if (Operand.isReg() && !Operand.needAddressOf() &&
601509467b48Spatrick           !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
601609467b48Spatrick         unsigned NumDefs = Desc.getNumDefs();
601709467b48Spatrick         // Clobber.
601809467b48Spatrick         if (NumDefs && Operand.getMCOperandNum() < NumDefs)
601909467b48Spatrick           ClobberRegs.push_back(Operand.getReg());
602009467b48Spatrick         continue;
602109467b48Spatrick       }
602209467b48Spatrick 
602309467b48Spatrick       // Expr/Input or Output.
602409467b48Spatrick       StringRef SymName = Operand.getSymName();
602509467b48Spatrick       if (SymName.empty())
602609467b48Spatrick         continue;
602709467b48Spatrick 
602809467b48Spatrick       void *OpDecl = Operand.getOpDecl();
602909467b48Spatrick       if (!OpDecl)
603009467b48Spatrick         continue;
603109467b48Spatrick 
603209467b48Spatrick       StringRef Constraint = Operand.getConstraint();
603309467b48Spatrick       if (Operand.isImm()) {
603409467b48Spatrick         // Offset as immediate
603509467b48Spatrick         if (Operand.isOffsetOfLocal())
603609467b48Spatrick           Constraint = "r";
603709467b48Spatrick         else
603809467b48Spatrick           Constraint = "i";
603909467b48Spatrick       }
604009467b48Spatrick 
604109467b48Spatrick       bool isOutput = (i == 1) && Desc.mayStore();
6042*a96b3639Srobert       bool Restricted = Operand.isMemUseUpRegs();
604309467b48Spatrick       SMLoc Start = SMLoc::getFromPointer(SymName.data());
604409467b48Spatrick       if (isOutput) {
604509467b48Spatrick         ++InputIdx;
604609467b48Spatrick         OutputDecls.push_back(OpDecl);
604709467b48Spatrick         OutputDeclsAddressOf.push_back(Operand.needAddressOf());
604809467b48Spatrick         OutputConstraints.push_back(("=" + Constraint).str());
6049*a96b3639Srobert         AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size(), 0,
6050*a96b3639Srobert                                     Restricted);
605109467b48Spatrick       } else {
605209467b48Spatrick         InputDecls.push_back(OpDecl);
605309467b48Spatrick         InputDeclsAddressOf.push_back(Operand.needAddressOf());
605409467b48Spatrick         InputConstraints.push_back(Constraint.str());
6055*a96b3639Srobert         if (Desc.operands()[i - 1].isBranchTarget())
6056*a96b3639Srobert           AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size(), 0,
6057*a96b3639Srobert                                       Restricted);
605809467b48Spatrick         else
6059*a96b3639Srobert           AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size(), 0,
6060*a96b3639Srobert                                       Restricted);
606109467b48Spatrick       }
606209467b48Spatrick     }
606309467b48Spatrick 
606409467b48Spatrick     // Consider implicit defs to be clobbers.  Think of cpuid and push.
6065*a96b3639Srobert     llvm::append_range(ClobberRegs, Desc.implicit_defs());
606609467b48Spatrick   }
606709467b48Spatrick 
606809467b48Spatrick   // Set the number of Outputs and Inputs.
606909467b48Spatrick   NumOutputs = OutputDecls.size();
607009467b48Spatrick   NumInputs = InputDecls.size();
607109467b48Spatrick 
607209467b48Spatrick   // Set the unique clobbers.
607309467b48Spatrick   array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
607409467b48Spatrick   ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
607509467b48Spatrick                     ClobberRegs.end());
607609467b48Spatrick   Clobbers.assign(ClobberRegs.size(), std::string());
607709467b48Spatrick   for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
607809467b48Spatrick     raw_string_ostream OS(Clobbers[I]);
607909467b48Spatrick     IP->printRegName(OS, ClobberRegs[I]);
608009467b48Spatrick   }
608109467b48Spatrick 
608209467b48Spatrick   // Merge the various outputs and inputs.  Output are expected first.
608309467b48Spatrick   if (NumOutputs || NumInputs) {
608409467b48Spatrick     unsigned NumExprs = NumOutputs + NumInputs;
608509467b48Spatrick     OpDecls.resize(NumExprs);
608609467b48Spatrick     Constraints.resize(NumExprs);
608709467b48Spatrick     for (unsigned i = 0; i < NumOutputs; ++i) {
608809467b48Spatrick       OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
608909467b48Spatrick       Constraints[i] = OutputConstraints[i];
609009467b48Spatrick     }
609109467b48Spatrick     for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
609209467b48Spatrick       OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
609309467b48Spatrick       Constraints[j] = InputConstraints[i];
609409467b48Spatrick     }
609509467b48Spatrick   }
609609467b48Spatrick 
609709467b48Spatrick   // Build the IR assembly string.
609809467b48Spatrick   std::string AsmStringIR;
609909467b48Spatrick   raw_string_ostream OS(AsmStringIR);
610009467b48Spatrick   StringRef ASMString =
610109467b48Spatrick       SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
610209467b48Spatrick   const char *AsmStart = ASMString.begin();
610309467b48Spatrick   const char *AsmEnd = ASMString.end();
610409467b48Spatrick   array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
610509467b48Spatrick   for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) {
610609467b48Spatrick     const AsmRewrite &AR = *it;
610709467b48Spatrick     // Check if this has already been covered by another rewrite...
610809467b48Spatrick     if (AR.Done)
610909467b48Spatrick       continue;
611009467b48Spatrick     AsmRewriteKind Kind = AR.Kind;
611109467b48Spatrick 
611209467b48Spatrick     const char *Loc = AR.Loc.getPointer();
611309467b48Spatrick     assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
611409467b48Spatrick 
611509467b48Spatrick     // Emit everything up to the immediate/expression.
611609467b48Spatrick     if (unsigned Len = Loc - AsmStart)
611709467b48Spatrick       OS << StringRef(AsmStart, Len);
611809467b48Spatrick 
611909467b48Spatrick     // Skip the original expression.
612009467b48Spatrick     if (Kind == AOK_Skip) {
612109467b48Spatrick       AsmStart = Loc + AR.Len;
612209467b48Spatrick       continue;
612309467b48Spatrick     }
612409467b48Spatrick 
612509467b48Spatrick     unsigned AdditionalSkip = 0;
612609467b48Spatrick     // Rewrite expressions in $N notation.
612709467b48Spatrick     switch (Kind) {
612809467b48Spatrick     default:
612909467b48Spatrick       break;
613009467b48Spatrick     case AOK_IntelExpr:
613109467b48Spatrick       assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
613209467b48Spatrick       if (AR.IntelExp.NeedBracs)
613309467b48Spatrick         OS << "[";
613409467b48Spatrick       if (AR.IntelExp.hasBaseReg())
613509467b48Spatrick         OS << AR.IntelExp.BaseReg;
613609467b48Spatrick       if (AR.IntelExp.hasIndexReg())
613709467b48Spatrick         OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
613809467b48Spatrick            << AR.IntelExp.IndexReg;
613909467b48Spatrick       if (AR.IntelExp.Scale > 1)
614009467b48Spatrick         OS << " * $$" << AR.IntelExp.Scale;
614109467b48Spatrick       if (AR.IntelExp.hasOffset()) {
614209467b48Spatrick         if (AR.IntelExp.hasRegs())
614309467b48Spatrick           OS << " + ";
614409467b48Spatrick         // Fuse this rewrite with a rewrite of the offset name, if present.
614509467b48Spatrick         StringRef OffsetName = AR.IntelExp.OffsetName;
614609467b48Spatrick         SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
614709467b48Spatrick         size_t OffsetLen = OffsetName.size();
614809467b48Spatrick         auto rewrite_it = std::find_if(
614909467b48Spatrick             it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
615009467b48Spatrick               return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
615109467b48Spatrick                      (FusingAR.Kind == AOK_Input ||
615209467b48Spatrick                       FusingAR.Kind == AOK_CallInput);
615309467b48Spatrick             });
615409467b48Spatrick         if (rewrite_it == AsmStrRewrites.end()) {
615509467b48Spatrick           OS << "offset " << OffsetName;
615609467b48Spatrick         } else if (rewrite_it->Kind == AOK_CallInput) {
615709467b48Spatrick           OS << "${" << InputIdx++ << ":P}";
615809467b48Spatrick           rewrite_it->Done = true;
615909467b48Spatrick         } else {
616009467b48Spatrick           OS << '$' << InputIdx++;
616109467b48Spatrick           rewrite_it->Done = true;
616209467b48Spatrick         }
616309467b48Spatrick       }
616409467b48Spatrick       if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
616509467b48Spatrick         OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
616609467b48Spatrick       if (AR.IntelExp.NeedBracs)
616709467b48Spatrick         OS << "]";
616809467b48Spatrick       break;
616909467b48Spatrick     case AOK_Label:
617009467b48Spatrick       OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
617109467b48Spatrick       break;
617209467b48Spatrick     case AOK_Input:
6173*a96b3639Srobert       if (AR.IntelExpRestricted)
6174*a96b3639Srobert         OS << "${" << InputIdx++ << ":P}";
6175*a96b3639Srobert       else
617609467b48Spatrick         OS << '$' << InputIdx++;
617709467b48Spatrick       break;
617809467b48Spatrick     case AOK_CallInput:
617909467b48Spatrick       OS << "${" << InputIdx++ << ":P}";
618009467b48Spatrick       break;
618109467b48Spatrick     case AOK_Output:
6182*a96b3639Srobert       if (AR.IntelExpRestricted)
6183*a96b3639Srobert         OS << "${" << OutputIdx++ << ":P}";
6184*a96b3639Srobert       else
618509467b48Spatrick         OS << '$' << OutputIdx++;
618609467b48Spatrick       break;
618709467b48Spatrick     case AOK_SizeDirective:
618809467b48Spatrick       switch (AR.Val) {
618909467b48Spatrick       default: break;
619009467b48Spatrick       case 8:  OS << "byte ptr "; break;
619109467b48Spatrick       case 16: OS << "word ptr "; break;
619209467b48Spatrick       case 32: OS << "dword ptr "; break;
619309467b48Spatrick       case 64: OS << "qword ptr "; break;
619409467b48Spatrick       case 80: OS << "xword ptr "; break;
619509467b48Spatrick       case 128: OS << "xmmword ptr "; break;
619609467b48Spatrick       case 256: OS << "ymmword ptr "; break;
619709467b48Spatrick       }
619809467b48Spatrick       break;
619909467b48Spatrick     case AOK_Emit:
620009467b48Spatrick       OS << ".byte";
620109467b48Spatrick       break;
620209467b48Spatrick     case AOK_Align: {
620309467b48Spatrick       // MS alignment directives are measured in bytes. If the native assembler
620409467b48Spatrick       // measures alignment in bytes, we can pass it straight through.
620509467b48Spatrick       OS << ".align";
620609467b48Spatrick       if (getContext().getAsmInfo()->getAlignmentIsInBytes())
620709467b48Spatrick         break;
620809467b48Spatrick 
620909467b48Spatrick       // Alignment is in log2 form, so print that instead and skip the original
621009467b48Spatrick       // immediate.
621109467b48Spatrick       unsigned Val = AR.Val;
621209467b48Spatrick       OS << ' ' << Val;
621309467b48Spatrick       assert(Val < 10 && "Expected alignment less then 2^10.");
621409467b48Spatrick       AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
621509467b48Spatrick       break;
621609467b48Spatrick     }
621709467b48Spatrick     case AOK_EVEN:
621809467b48Spatrick       OS << ".even";
621909467b48Spatrick       break;
622009467b48Spatrick     case AOK_EndOfStatement:
622109467b48Spatrick       OS << "\n\t";
622209467b48Spatrick       break;
622309467b48Spatrick     }
622409467b48Spatrick 
622509467b48Spatrick     // Skip the original expression.
622609467b48Spatrick     AsmStart = Loc + AR.Len + AdditionalSkip;
622709467b48Spatrick   }
622809467b48Spatrick 
622909467b48Spatrick   // Emit the remainder of the asm string.
623009467b48Spatrick   if (AsmStart != AsmEnd)
623109467b48Spatrick     OS << StringRef(AsmStart, AsmEnd - AsmStart);
623209467b48Spatrick 
623309467b48Spatrick   AsmString = OS.str();
623409467b48Spatrick   return false;
623509467b48Spatrick }
623609467b48Spatrick 
parseAsHLASMLabel(ParseStatementInfo & Info,MCAsmParserSemaCallback * SI)6237a0747c9fSpatrick bool HLASMAsmParser::parseAsHLASMLabel(ParseStatementInfo &Info,
6238a0747c9fSpatrick                                        MCAsmParserSemaCallback *SI) {
6239a0747c9fSpatrick   AsmToken LabelTok = getTok();
6240a0747c9fSpatrick   SMLoc LabelLoc = LabelTok.getLoc();
6241a0747c9fSpatrick   StringRef LabelVal;
6242a0747c9fSpatrick 
6243a0747c9fSpatrick   if (parseIdentifier(LabelVal))
6244a0747c9fSpatrick     return Error(LabelLoc, "The HLASM Label has to be an Identifier");
6245a0747c9fSpatrick 
6246a0747c9fSpatrick   // We have validated whether the token is an Identifier.
6247a0747c9fSpatrick   // Now we have to validate whether the token is a
6248a0747c9fSpatrick   // valid HLASM Label.
6249a0747c9fSpatrick   if (!getTargetParser().isLabel(LabelTok) || checkForValidSection())
6250a0747c9fSpatrick     return true;
6251a0747c9fSpatrick 
6252a0747c9fSpatrick   // Lex leading spaces to get to the next operand.
6253a0747c9fSpatrick   lexLeadingSpaces();
6254a0747c9fSpatrick 
6255a0747c9fSpatrick   // We shouldn't emit the label if there is nothing else after the label.
6256a0747c9fSpatrick   // i.e asm("<token>\n")
6257a0747c9fSpatrick   if (getTok().is(AsmToken::EndOfStatement))
6258a0747c9fSpatrick     return Error(LabelLoc,
6259a0747c9fSpatrick                  "Cannot have just a label for an HLASM inline asm statement");
6260a0747c9fSpatrick 
6261a0747c9fSpatrick   MCSymbol *Sym = getContext().getOrCreateSymbol(
6262a0747c9fSpatrick       getContext().getAsmInfo()->shouldEmitLabelsInUpperCase()
6263a0747c9fSpatrick           ? LabelVal.upper()
6264a0747c9fSpatrick           : LabelVal);
6265a0747c9fSpatrick 
6266*a96b3639Srobert   getTargetParser().doBeforeLabelEmit(Sym, LabelLoc);
6267a0747c9fSpatrick 
6268a0747c9fSpatrick   // Emit the label.
6269a0747c9fSpatrick   Out.emitLabel(Sym, LabelLoc);
6270a0747c9fSpatrick 
6271a0747c9fSpatrick   // If we are generating dwarf for assembly source files then gather the
6272a0747c9fSpatrick   // info to make a dwarf label entry for this label if needed.
6273a0747c9fSpatrick   if (enabledGenDwarfForAssembly())
6274a0747c9fSpatrick     MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
6275a0747c9fSpatrick                                LabelLoc);
6276a0747c9fSpatrick 
6277a0747c9fSpatrick   getTargetParser().onLabelParsed(Sym);
6278a0747c9fSpatrick 
6279a0747c9fSpatrick   return false;
6280a0747c9fSpatrick }
6281a0747c9fSpatrick 
parseAsMachineInstruction(ParseStatementInfo & Info,MCAsmParserSemaCallback * SI)6282a0747c9fSpatrick bool HLASMAsmParser::parseAsMachineInstruction(ParseStatementInfo &Info,
6283a0747c9fSpatrick                                                MCAsmParserSemaCallback *SI) {
6284a0747c9fSpatrick   AsmToken OperationEntryTok = Lexer.getTok();
6285a0747c9fSpatrick   SMLoc OperationEntryLoc = OperationEntryTok.getLoc();
6286a0747c9fSpatrick   StringRef OperationEntryVal;
6287a0747c9fSpatrick 
6288a0747c9fSpatrick   // Attempt to parse the first token as an Identifier
6289a0747c9fSpatrick   if (parseIdentifier(OperationEntryVal))
6290a0747c9fSpatrick     return Error(OperationEntryLoc, "unexpected token at start of statement");
6291a0747c9fSpatrick 
6292a0747c9fSpatrick   // Once we've parsed the operation entry successfully, lex
6293a0747c9fSpatrick   // any spaces to get to the OperandEntries.
6294a0747c9fSpatrick   lexLeadingSpaces();
6295a0747c9fSpatrick 
6296a0747c9fSpatrick   return parseAndMatchAndEmitTargetInstruction(
6297a0747c9fSpatrick       Info, OperationEntryVal, OperationEntryTok, OperationEntryLoc);
6298a0747c9fSpatrick }
6299a0747c9fSpatrick 
parseStatement(ParseStatementInfo & Info,MCAsmParserSemaCallback * SI)6300a0747c9fSpatrick bool HLASMAsmParser::parseStatement(ParseStatementInfo &Info,
6301a0747c9fSpatrick                                     MCAsmParserSemaCallback *SI) {
6302a0747c9fSpatrick   assert(!hasPendingError() && "parseStatement started with pending error");
6303a0747c9fSpatrick 
6304a0747c9fSpatrick   // Should the first token be interpreted as a HLASM Label.
6305a0747c9fSpatrick   bool ShouldParseAsHLASMLabel = false;
6306a0747c9fSpatrick 
6307a0747c9fSpatrick   // If a Name Entry exists, it should occur at the very
6308a0747c9fSpatrick   // start of the string. In this case, we should parse the
6309a0747c9fSpatrick   // first non-space token as a Label.
6310a0747c9fSpatrick   // If the Name entry is missing (i.e. there's some other
6311a0747c9fSpatrick   // token), then we attempt to parse the first non-space
6312a0747c9fSpatrick   // token as a Machine Instruction.
6313a0747c9fSpatrick   if (getTok().isNot(AsmToken::Space))
6314a0747c9fSpatrick     ShouldParseAsHLASMLabel = true;
6315a0747c9fSpatrick 
6316a0747c9fSpatrick   // If we have an EndOfStatement (which includes the target's comment
6317a0747c9fSpatrick   // string) we can appropriately lex it early on)
6318a0747c9fSpatrick   if (Lexer.is(AsmToken::EndOfStatement)) {
6319a0747c9fSpatrick     // if this is a line comment we can drop it safely
6320a0747c9fSpatrick     if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
6321a0747c9fSpatrick         getTok().getString().front() == '\n')
6322*a96b3639Srobert       Out.addBlankLine();
6323a0747c9fSpatrick     Lex();
6324a0747c9fSpatrick     return false;
6325a0747c9fSpatrick   }
6326a0747c9fSpatrick 
6327a0747c9fSpatrick   // We have established how to parse the inline asm statement.
6328a0747c9fSpatrick   // Now we can safely lex any leading spaces to get to the
6329a0747c9fSpatrick   // first token.
6330a0747c9fSpatrick   lexLeadingSpaces();
6331a0747c9fSpatrick 
6332a0747c9fSpatrick   // If we see a new line or carriage return as the first operand,
6333a0747c9fSpatrick   // after lexing leading spaces, emit the new line and lex the
6334a0747c9fSpatrick   // EndOfStatement token.
6335a0747c9fSpatrick   if (Lexer.is(AsmToken::EndOfStatement)) {
6336a0747c9fSpatrick     if (getTok().getString().front() == '\n' ||
6337a0747c9fSpatrick         getTok().getString().front() == '\r') {
6338*a96b3639Srobert       Out.addBlankLine();
6339a0747c9fSpatrick       Lex();
6340a0747c9fSpatrick       return false;
6341a0747c9fSpatrick     }
6342a0747c9fSpatrick   }
6343a0747c9fSpatrick 
6344a0747c9fSpatrick   // Handle the label first if we have to before processing the rest
6345a0747c9fSpatrick   // of the tokens as a machine instruction.
6346a0747c9fSpatrick   if (ShouldParseAsHLASMLabel) {
6347a0747c9fSpatrick     // If there were any errors while handling and emitting the label,
6348a0747c9fSpatrick     // early return.
6349a0747c9fSpatrick     if (parseAsHLASMLabel(Info, SI)) {
6350a0747c9fSpatrick       // If we know we've failed in parsing, simply eat until end of the
6351a0747c9fSpatrick       // statement. This ensures that we don't process any other statements.
6352a0747c9fSpatrick       eatToEndOfStatement();
6353a0747c9fSpatrick       return true;
6354a0747c9fSpatrick     }
6355a0747c9fSpatrick   }
6356a0747c9fSpatrick 
6357a0747c9fSpatrick   return parseAsMachineInstruction(Info, SI);
6358a0747c9fSpatrick }
6359a0747c9fSpatrick 
636009467b48Spatrick namespace llvm {
636109467b48Spatrick namespace MCParserUtils {
636209467b48Spatrick 
636309467b48Spatrick /// Returns whether the given symbol is used anywhere in the given expression,
636409467b48Spatrick /// or subexpressions.
isSymbolUsedInExpression(const MCSymbol * Sym,const MCExpr * Value)636509467b48Spatrick static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
636609467b48Spatrick   switch (Value->getKind()) {
636709467b48Spatrick   case MCExpr::Binary: {
636809467b48Spatrick     const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
636909467b48Spatrick     return isSymbolUsedInExpression(Sym, BE->getLHS()) ||
637009467b48Spatrick            isSymbolUsedInExpression(Sym, BE->getRHS());
637109467b48Spatrick   }
637209467b48Spatrick   case MCExpr::Target:
637309467b48Spatrick   case MCExpr::Constant:
637409467b48Spatrick     return false;
637509467b48Spatrick   case MCExpr::SymbolRef: {
637609467b48Spatrick     const MCSymbol &S =
637709467b48Spatrick         static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
637809467b48Spatrick     if (S.isVariable())
637909467b48Spatrick       return isSymbolUsedInExpression(Sym, S.getVariableValue());
638009467b48Spatrick     return &S == Sym;
638109467b48Spatrick   }
638209467b48Spatrick   case MCExpr::Unary:
638309467b48Spatrick     return isSymbolUsedInExpression(
638409467b48Spatrick         Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
638509467b48Spatrick   }
638609467b48Spatrick 
638709467b48Spatrick   llvm_unreachable("Unknown expr kind!");
638809467b48Spatrick }
638909467b48Spatrick 
parseAssignmentExpression(StringRef Name,bool allow_redef,MCAsmParser & Parser,MCSymbol * & Sym,const MCExpr * & Value)639009467b48Spatrick bool parseAssignmentExpression(StringRef Name, bool allow_redef,
639109467b48Spatrick                                MCAsmParser &Parser, MCSymbol *&Sym,
639209467b48Spatrick                                const MCExpr *&Value) {
639309467b48Spatrick 
639409467b48Spatrick   // FIXME: Use better location, we should use proper tokens.
639509467b48Spatrick   SMLoc EqualLoc = Parser.getTok().getLoc();
639609467b48Spatrick   if (Parser.parseExpression(Value))
639709467b48Spatrick     return Parser.TokError("missing expression");
639809467b48Spatrick 
639909467b48Spatrick   // Note: we don't count b as used in "a = b". This is to allow
640009467b48Spatrick   // a = b
640109467b48Spatrick   // b = c
640209467b48Spatrick 
6403a0747c9fSpatrick   if (Parser.parseEOL())
640409467b48Spatrick     return true;
640509467b48Spatrick 
640609467b48Spatrick   // Validate that the LHS is allowed to be a variable (either it has not been
640709467b48Spatrick   // used as a symbol, or it is an absolute symbol).
640809467b48Spatrick   Sym = Parser.getContext().lookupSymbol(Name);
640909467b48Spatrick   if (Sym) {
641009467b48Spatrick     // Diagnose assignment to a label.
641109467b48Spatrick     //
641209467b48Spatrick     // FIXME: Diagnostics. Note the location of the definition as a label.
641309467b48Spatrick     // FIXME: Diagnose assignment to protected identifier (e.g., register name).
641409467b48Spatrick     if (isSymbolUsedInExpression(Sym, Value))
641509467b48Spatrick       return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'");
641609467b48Spatrick     else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() &&
641709467b48Spatrick              !Sym->isVariable())
641809467b48Spatrick       ; // Allow redefinitions of undefined symbols only used in directives.
641909467b48Spatrick     else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
642009467b48Spatrick       ; // Allow redefinitions of variables that haven't yet been used.
642109467b48Spatrick     else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
642209467b48Spatrick       return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
642309467b48Spatrick     else if (!Sym->isVariable())
642409467b48Spatrick       return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'");
642509467b48Spatrick     else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
642609467b48Spatrick       return Parser.Error(EqualLoc,
642709467b48Spatrick                           "invalid reassignment of non-absolute variable '" +
642809467b48Spatrick                               Name + "'");
642909467b48Spatrick   } else if (Name == ".") {
643009467b48Spatrick     Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
643109467b48Spatrick     return false;
643209467b48Spatrick   } else
643309467b48Spatrick     Sym = Parser.getContext().getOrCreateSymbol(Name);
643409467b48Spatrick 
643509467b48Spatrick   Sym->setRedefinable(allow_redef);
643609467b48Spatrick 
643709467b48Spatrick   return false;
643809467b48Spatrick }
643909467b48Spatrick 
644009467b48Spatrick } // end namespace MCParserUtils
644109467b48Spatrick } // end namespace llvm
644209467b48Spatrick 
644309467b48Spatrick /// Create an MCAsmParser instance.
createMCAsmParser(SourceMgr & SM,MCContext & C,MCStreamer & Out,const MCAsmInfo & MAI,unsigned CB)644409467b48Spatrick MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
644509467b48Spatrick                                      MCStreamer &Out, const MCAsmInfo &MAI,
644609467b48Spatrick                                      unsigned CB) {
6447a0747c9fSpatrick   if (C.getTargetTriple().isSystemZ() && C.getTargetTriple().isOSzOS())
6448a0747c9fSpatrick     return new HLASMAsmParser(SM, C, Out, MAI, CB);
6449a0747c9fSpatrick 
645009467b48Spatrick   return new AsmParser(SM, C, Out, MAI, CB);
645109467b48Spatrick }
6452