1 //===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This class implements a parser for assembly files similar to gas syntax.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ADT/APFloat.h"
14 #include "llvm/ADT/APInt.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/SmallSet.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/StringMap.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/ADT/Twine.h"
24 #include "llvm/BinaryFormat/Dwarf.h"
25 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
26 #include "llvm/MC/MCAsmInfo.h"
27 #include "llvm/MC/MCCodeView.h"
28 #include "llvm/MC/MCContext.h"
29 #include "llvm/MC/MCDirectives.h"
30 #include "llvm/MC/MCDwarf.h"
31 #include "llvm/MC/MCExpr.h"
32 #include "llvm/MC/MCInstPrinter.h"
33 #include "llvm/MC/MCInstrDesc.h"
34 #include "llvm/MC/MCInstrInfo.h"
35 #include "llvm/MC/MCParser/AsmCond.h"
36 #include "llvm/MC/MCParser/AsmLexer.h"
37 #include "llvm/MC/MCParser/MCAsmLexer.h"
38 #include "llvm/MC/MCParser/MCAsmParser.h"
39 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
40 #include "llvm/MC/MCParser/MCAsmParserUtils.h"
41 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
42 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
43 #include "llvm/MC/MCRegisterInfo.h"
44 #include "llvm/MC/MCSection.h"
45 #include "llvm/MC/MCStreamer.h"
46 #include "llvm/MC/MCSymbol.h"
47 #include "llvm/MC/MCSymbolMachO.h"
48 #include "llvm/MC/MCTargetOptions.h"
49 #include "llvm/MC/MCValue.h"
50 #include "llvm/Support/Casting.h"
51 #include "llvm/Support/CommandLine.h"
52 #include "llvm/Support/ErrorHandling.h"
53 #include "llvm/Support/MD5.h"
54 #include "llvm/Support/MathExtras.h"
55 #include "llvm/Support/MemoryBuffer.h"
56 #include "llvm/Support/SMLoc.h"
57 #include "llvm/Support/SourceMgr.h"
58 #include "llvm/Support/raw_ostream.h"
76 MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;
80 /// Helper types for tracking macro definitions.
81 typedef std::vector<AsmToken> MCAsmMacroArgument;
82 typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
84 /// Helper class for storing information about an active macro
86 struct MacroInstantiation {
87 /// The location of the instantiation.
88 SMLoc InstantiationLoc;
90 /// The buffer where parsing should resume upon instantiation completion.
93 /// The location where parsing should resume upon instantiation completion.
96 /// The depth of TheCondStack at the start of the instantiation.
97 size_t CondStackDepth;
100 struct ParseStatementInfo {
101 /// The parsed operands from the last parsed statement.
102 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
104 /// The opcode from the last parsed instruction.
105 unsigned Opcode = ~0U;
107 /// Was there an error parsing the inline assembly?
108 bool ParseError = false;
110 SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
112 ParseStatementInfo() = delete;
113 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
114 : AsmRewrites(rewrites) {}
117 /// The concrete assembly parser instance.
118 class AsmParser : public MCAsmParser {
123 const MCAsmInfo &MAI;
125 SourceMgr::DiagHandlerTy SavedDiagHandler;
126 void *SavedDiagContext;
127 std::unique_ptr<MCAsmParserExtension> PlatformParser;
129 std::optional<SMLoc> CFIStartProcLoc;
131 /// This is the current buffer index we're lexing from as managed by the
132 /// SourceMgr object.
135 AsmCond TheCondState;
136 std::vector<AsmCond> TheCondStack;
138 /// maps directive names to handler methods in parser
139 /// extensions. Extensions register themselves in this map by calling
140 /// addDirectiveHandler.
141 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
143 /// Stack of active macro instantiations.
144 std::vector<MacroInstantiation*> ActiveMacros;
146 /// List of bodies of anonymous macros.
147 std::deque<MCAsmMacro> MacroLikeBodies;
149 /// Boolean tracking whether macro substitution is enabled.
150 unsigned MacrosEnabledFlag : 1;
152 /// Keeps track of how many .macro's have been instantiated.
153 unsigned NumOfMacroInstantiations;
155 /// The values from the last parsed cpp hash file line comment if any.
156 struct CppHashInfoTy {
161 CppHashInfoTy() : LineNumber(0), Buf(0) {}
163 CppHashInfoTy CppHashInfo;
165 /// The filename from the first cpp hash file line comment, if any.
166 StringRef FirstCppHashFilename;
168 /// List of forward directional labels for diagnosis at the end.
169 SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
171 SmallSet<StringRef, 2> LTODiscardSymbols;
173 /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
174 unsigned AssemblerDialect = ~0U;
176 /// is Darwin compatibility enabled?
177 bool IsDarwin = false;
179 /// Are we parsing ms-style inline assembly?
180 bool ParsingMSInlineAsm = false;
182 /// Did we already inform the user about inconsistent MD5 usage?
183 bool ReportedInconsistentMD5 = false;
185 // Is alt macro mode enabled.
186 bool AltMacroMode = false;
189 virtual bool parseStatement(ParseStatementInfo &Info,
190 MCAsmParserSemaCallback *SI);
192 /// This routine uses the target specific ParseInstruction function to
193 /// parse an instruction into Operands, and then call the target specific
194 /// MatchAndEmit function to match and emit the instruction.
195 bool parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,
196 StringRef IDVal, AsmToken ID,
199 /// Should we emit DWARF describing this assembler source? (Returns false if
200 /// the source has .file directives, which means we don't want to generate
201 /// info describing the assembler source itself.)
202 bool enabledGenDwarfForAssembly();
205 AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
206 const MCAsmInfo &MAI, unsigned CB);
207 AsmParser(const AsmParser &) = delete;
208 AsmParser &operator=(const AsmParser &) = delete;
209 ~AsmParser() override;
211 bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
213 void addDirectiveHandler(StringRef Directive,
214 ExtensionDirectiveHandler Handler) override {
215 ExtensionDirectiveMap[Directive] = Handler;
218 void addAliasForDirective(StringRef Directive, StringRef Alias) override {
219 DirectiveKindMap[Directive.lower()] = DirectiveKindMap[Alias.lower()];
222 /// @name MCAsmParser Interface
225 SourceMgr &getSourceManager() override { return SrcMgr; }
226 MCAsmLexer &getLexer() override { return Lexer; }
227 MCContext &getContext() override { return Ctx; }
228 MCStreamer &getStreamer() override { return Out; }
230 CodeViewContext &getCVContext() { return Ctx.getCVContext(); }
232 unsigned getAssemblerDialect() override {
233 if (AssemblerDialect == ~0U)
234 return MAI.getAssemblerDialect();
236 return AssemblerDialect;
238 void setAssemblerDialect(unsigned i) override {
239 AssemblerDialect = i;
242 void Note(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) override;
243 bool Warning(SMLoc L, const Twine &Msg,
244 SMRange Range = std::nullopt) override;
245 bool printError(SMLoc L, const Twine &Msg,
246 SMRange Range = std::nullopt) override;
248 const AsmToken &Lex() override;
250 void setParsingMSInlineAsm(bool V) override {
251 ParsingMSInlineAsm = V;
252 // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
253 // hex integer literals.
254 Lexer.setLexMasmIntegers(V);
256 bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
258 bool discardLTOSymbol(StringRef Name) const override {
259 return LTODiscardSymbols.contains(Name);
262 bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs,
264 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
265 SmallVectorImpl<std::string> &Constraints,
266 SmallVectorImpl<std::string> &Clobbers,
267 const MCInstrInfo *MII, const MCInstPrinter *IP,
268 MCAsmParserSemaCallback &SI) override;
270 bool parseExpression(const MCExpr *&Res);
271 bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
272 bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
273 AsmTypeInfo *TypeInfo) override;
274 bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
275 bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
276 SMLoc &EndLoc) override;
277 bool parseAbsoluteExpression(int64_t &Res) override;
279 /// Parse a floating point expression using the float \p Semantics
280 /// and set \p Res to the value.
281 bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
283 /// Parse an identifier or string (as a quoted identifier)
284 /// and set \p Res to the identifier contents.
285 bool parseIdentifier(StringRef &Res) override;
286 void eatToEndOfStatement() override;
288 bool checkForValidSection() override;
293 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
294 bool parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo = true);
296 void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
297 ArrayRef<MCAsmMacroParameter> Parameters);
298 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
299 ArrayRef<MCAsmMacroParameter> Parameters,
300 ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable,
303 /// Are macros enabled in the parser?
304 bool areMacrosEnabled() {return MacrosEnabledFlag;}
306 /// Control a flag in the parser that enables or disables macros.
307 void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
309 /// Are we inside a macro instantiation?
310 bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
312 /// Handle entry to macro instantiation.
314 /// \param M The macro.
315 /// \param NameLoc Instantiation location.
316 bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
318 /// Handle exit from macro instantiation.
319 void handleMacroExit();
321 /// Extract AsmTokens for a macro argument.
322 bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
324 /// Parse all macro arguments for a given macro.
325 bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
327 void printMacroInstantiations();
328 void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
329 SMRange Range = std::nullopt) const {
330 ArrayRef<SMRange> Ranges(Range);
331 SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
333 static void DiagHandler(const SMDiagnostic &Diag, void *Context);
335 /// Enter the specified file. This returns true on failure.
336 bool enterIncludeFile(const std::string &Filename);
338 /// Process the specified file for the .incbin directive.
339 /// This returns true on failure.
340 bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,
341 const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());
343 /// Reset the current lexer position to that given by \p Loc. The
344 /// current token is not set; clients should ensure Lex() is called
347 /// \param InBuffer If not 0, should be the known buffer id that contains the
349 void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);
351 /// Parse up to the end of statement and a return the contents from the
352 /// current token until the end of the statement; the current token on exit
353 /// will be either the EndOfStatement or EOF.
354 StringRef parseStringToEndOfStatement() override;
356 /// Parse until the end of a statement or a comma is encountered,
357 /// return the contents from the current token up to the end or comma.
358 StringRef parseStringToComma();
360 enum class AssignmentKind {
367 bool parseAssignment(StringRef Name, AssignmentKind Kind);
369 unsigned getBinOpPrecedence(AsmToken::TokenKind K,
370 MCBinaryExpr::Opcode &Kind);
372 bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
373 bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
374 bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
376 bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
378 bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);
379 bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);
381 // Generic (target and platform independent) directive parsing.
383 DK_NO_DIRECTIVE, // Placeholder
438 DK_BUNDLE_ALIGN_MODE,
452 DK_WEAK_DEF_CAN_BE_HIDDEN,
492 DK_CV_INLINE_SITE_ID,
495 DK_CV_INLINE_LINETABLE,
500 DK_CV_FILECHECKSUM_OFFSET,
506 DK_CFI_DEF_CFA_OFFSET,
507 DK_CFI_ADJUST_CFA_OFFSET,
508 DK_CFI_DEF_CFA_REGISTER,
509 DK_CFI_LLVM_DEF_ASPACE_CFA,
514 DK_CFI_REMEMBER_STATE,
515 DK_CFI_RESTORE_STATE,
519 DK_CFI_RETURN_COLUMN,
544 DK_LTO_SET_CONDITIONAL,
545 DK_CFI_MTE_TAGGED_FRAME,
550 /// Maps directive name --> DirectiveKind enum, for
551 /// directives parsed by this class.
552 StringMap<DirectiveKind> DirectiveKindMap;
554 // Codeview def_range type parsing.
555 enum CVDefRangeType {
556 CVDR_DEFRANGE = 0, // Placeholder
557 CVDR_DEFRANGE_REGISTER,
558 CVDR_DEFRANGE_FRAMEPOINTER_REL,
559 CVDR_DEFRANGE_SUBFIELD_REGISTER,
560 CVDR_DEFRANGE_REGISTER_REL
563 /// Maps Codeview def_range types --> CVDefRangeType enum, for
564 /// Codeview def_range types parsed by this class.
565 StringMap<CVDefRangeType> CVDefRangeTypeMap;
567 // ".ascii", ".asciz", ".string"
568 bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
569 bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
570 bool parseDirectiveValue(StringRef IDVal,
571 unsigned Size); // ".byte", ".long", ...
572 bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ...
573 bool parseDirectiveRealValue(StringRef IDVal,
574 const fltSemantics &); // ".single", ...
575 bool parseDirectiveFill(); // ".fill"
576 bool parseDirectiveZero(); // ".zero"
577 // ".set", ".equ", ".equiv", ".lto_set_conditional"
578 bool parseDirectiveSet(StringRef IDVal, AssignmentKind Kind);
579 bool parseDirectiveOrg(); // ".org"
580 // ".align{,32}", ".p2align{,w,l}"
581 bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);
583 // ".file", ".line", ".loc", ".stabs"
584 bool parseDirectiveFile(SMLoc DirectiveLoc);
585 bool parseDirectiveLine();
586 bool parseDirectiveLoc();
587 bool parseDirectiveStabs();
589 // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
590 // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
591 bool parseDirectiveCVFile();
592 bool parseDirectiveCVFuncId();
593 bool parseDirectiveCVInlineSiteId();
594 bool parseDirectiveCVLoc();
595 bool parseDirectiveCVLinetable();
596 bool parseDirectiveCVInlineLinetable();
597 bool parseDirectiveCVDefRange();
598 bool parseDirectiveCVString();
599 bool parseDirectiveCVStringTable();
600 bool parseDirectiveCVFileChecksums();
601 bool parseDirectiveCVFileChecksumOffset();
602 bool parseDirectiveCVFPOData();
605 bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
606 bool parseDirectiveCFIWindowSave(SMLoc DirectiveLoc);
607 bool parseDirectiveCFISections();
608 bool parseDirectiveCFIStartProc();
609 bool parseDirectiveCFIEndProc();
610 bool parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc);
611 bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
612 bool parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc);
613 bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
614 bool parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc);
615 bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
616 bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
617 bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
618 bool parseDirectiveCFIRememberState(SMLoc DirectiveLoc);
619 bool parseDirectiveCFIRestoreState(SMLoc DirectiveLoc);
620 bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
621 bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
622 bool parseDirectiveCFIEscape(SMLoc DirectiveLoc);
623 bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
624 bool parseDirectiveCFISignalFrame(SMLoc DirectiveLoc);
625 bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
628 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
629 bool parseDirectiveExitMacro(StringRef Directive);
630 bool parseDirectiveEndMacro(StringRef Directive);
631 bool parseDirectiveMacro(SMLoc DirectiveLoc);
632 bool parseDirectiveMacrosOnOff(StringRef Directive);
633 // alternate macro mode directives
634 bool parseDirectiveAltmacro(StringRef Directive);
635 // ".bundle_align_mode"
636 bool parseDirectiveBundleAlignMode();
638 bool parseDirectiveBundleLock();
640 bool parseDirectiveBundleUnlock();
643 bool parseDirectiveSpace(StringRef IDVal);
646 bool parseDirectiveDCB(StringRef IDVal, unsigned Size);
647 bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &);
649 bool parseDirectiveDS(StringRef IDVal, unsigned Size);
651 // .sleb128 (Signed=true) and .uleb128 (Signed=false)
652 bool parseDirectiveLEB128(bool Signed);
654 /// Parse a directive like ".globl" which
655 /// accepts a single symbol (which should be a label or an external).
656 bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
658 bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
660 bool parseDirectiveAbort(); // ".abort"
661 bool parseDirectiveInclude(); // ".include"
662 bool parseDirectiveIncbin(); // ".incbin"
664 // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"
665 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
666 // ".ifb" or ".ifnb", depending on ExpectBlank.
667 bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
668 // ".ifc" or ".ifnc", depending on ExpectEqual.
669 bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
670 // ".ifeqs" or ".ifnes", depending on ExpectEqual.
671 bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);
672 // ".ifdef" or ".ifndef", depending on expect_defined
673 bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
674 bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
675 bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
676 bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
677 bool parseEscapedString(std::string &Data) override;
678 bool parseAngleBracketString(std::string &Data) override;
680 const MCExpr *applyModifierToExpr(const MCExpr *E,
681 MCSymbolRefExpr::VariantKind Variant);
683 // Macro-like directives
684 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
685 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
686 raw_svector_ostream &OS);
687 bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);
688 bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
689 bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
690 bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
692 // "_emit" or "__emit"
693 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
697 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
700 bool parseDirectiveEnd(SMLoc DirectiveLoc);
702 // ".err" or ".error"
703 bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
706 bool parseDirectiveWarning(SMLoc DirectiveLoc);
708 // .print <double-quotes-string>
709 bool parseDirectivePrint(SMLoc DirectiveLoc);
712 bool parseDirectivePseudoProbe();
715 bool parseDirectiveLTODiscard();
717 // Directives to support address-significance tables.
718 bool parseDirectiveAddrsig();
719 bool parseDirectiveAddrsigSym();
721 void initializeDirectiveKindMap();
722 void initializeCVDefRangeTypeMap();
725 class HLASMAsmParser final : public AsmParser {
730 void lexLeadingSpaces() {
731 while (Lexer.is(AsmToken::Space))
735 bool parseAsHLASMLabel(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI);
736 bool parseAsMachineInstruction(ParseStatementInfo &Info,
737 MCAsmParserSemaCallback *SI);
740 HLASMAsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
741 const MCAsmInfo &MAI, unsigned CB = 0)
742 : AsmParser(SM, Ctx, Out, MAI, CB), Lexer(getLexer()), Out(Out) {
743 Lexer.setSkipSpace(false);
744 Lexer.setAllowHashInIdentifier(true);
745 Lexer.setLexHLASMIntegers(true);
746 Lexer.setLexHLASMStrings(true);
749 ~HLASMAsmParser() { Lexer.setSkipSpace(true); }
751 bool parseStatement(ParseStatementInfo &Info,
752 MCAsmParserSemaCallback *SI) override;
755 } // end anonymous namespace
759 extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
761 extern MCAsmParserExtension *createDarwinAsmParser();
762 extern MCAsmParserExtension *createELFAsmParser();
763 extern MCAsmParserExtension *createCOFFAsmParser();
764 extern MCAsmParserExtension *createGOFFAsmParser();
765 extern MCAsmParserExtension *createXCOFFAsmParser();
766 extern MCAsmParserExtension *createWasmAsmParser();
768 } // end namespace llvm
770 enum { DEFAULT_ADDRSPACE = 0 };
772 AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
773 const MCAsmInfo &MAI, unsigned CB = 0)
774 : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
775 CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {
777 // Save the old handler.
778 SavedDiagHandler = SrcMgr.getDiagHandler();
779 SavedDiagContext = SrcMgr.getDiagContext();
780 // Set our own handler which calls the saved handler.
781 SrcMgr.setDiagHandler(DiagHandler, this);
782 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
783 // Make MCStreamer aware of the StartTokLoc for locations in diagnostics.
784 Out.setStartTokLocPtr(&StartTokLoc);
786 // Initialize the platform / file format parser.
787 switch (Ctx.getObjectFileType()) {
788 case MCContext::IsCOFF:
789 PlatformParser.reset(createCOFFAsmParser());
791 case MCContext::IsMachO:
792 PlatformParser.reset(createDarwinAsmParser());
795 case MCContext::IsELF:
796 PlatformParser.reset(createELFAsmParser());
798 case MCContext::IsGOFF:
799 PlatformParser.reset(createGOFFAsmParser());
801 case MCContext::IsSPIRV:
803 "Need to implement createSPIRVAsmParser for SPIRV format.");
805 case MCContext::IsWasm:
806 PlatformParser.reset(createWasmAsmParser());
808 case MCContext::IsXCOFF:
809 PlatformParser.reset(createXCOFFAsmParser());
811 case MCContext::IsDXContainer:
812 report_fatal_error("DXContainer is not supported yet");
816 PlatformParser->Initialize(*this);
817 initializeDirectiveKindMap();
818 initializeCVDefRangeTypeMap();
820 NumOfMacroInstantiations = 0;
823 AsmParser::~AsmParser() {
824 assert((HadError || ActiveMacros.empty()) &&
825 "Unexpected active macro instantiation!");
827 // Remove MCStreamer's reference to the parser SMLoc.
828 Out.setStartTokLocPtr(nullptr);
829 // Restore the saved diagnostics handler and context for use during
831 SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
834 void AsmParser::printMacroInstantiations() {
835 // Print the active macro instantiation stack.
836 for (std::vector<MacroInstantiation *>::const_reverse_iterator
837 it = ActiveMacros.rbegin(),
838 ie = ActiveMacros.rend();
840 printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
841 "while in macro instantiation");
844 void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
845 printPendingErrors();
846 printMessage(L, SourceMgr::DK_Note, Msg, Range);
847 printMacroInstantiations();
850 bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
851 if(getTargetParser().getTargetOptions().MCNoWarn)
853 if (getTargetParser().getTargetOptions().MCFatalWarnings)
854 return Error(L, Msg, Range);
855 printMessage(L, SourceMgr::DK_Warning, Msg, Range);
856 printMacroInstantiations();
860 bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
862 printMessage(L, SourceMgr::DK_Error, Msg, Range);
863 printMacroInstantiations();
867 bool AsmParser::enterIncludeFile(const std::string &Filename) {
868 std::string IncludedFile;
870 SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
875 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
879 /// Process the specified .incbin file by searching for it in the include paths
880 /// then just emitting the byte contents of the file to the streamer. This
881 /// returns true on failure.
882 bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
883 const MCExpr *Count, SMLoc Loc) {
884 std::string IncludedFile;
886 SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
890 // Pick up the bytes from the file and emit them.
891 StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();
892 Bytes = Bytes.drop_front(Skip);
895 if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
896 return Error(Loc, "expected absolute expression");
898 return Warning(Loc, "negative count has no effect");
899 Bytes = Bytes.take_front(Res);
901 getStreamer().emitBytes(Bytes);
905 void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
906 CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
907 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
911 const AsmToken &AsmParser::Lex() {
912 if (Lexer.getTok().is(AsmToken::Error))
913 Error(Lexer.getErrLoc(), Lexer.getErr());
915 // if it's a end of statement with a comment in it
916 if (getTok().is(AsmToken::EndOfStatement)) {
917 // if this is a line comment output it.
918 if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
919 getTok().getString().front() != '\r' && MAI.preserveAsmComments())
920 Out.addExplicitComment(Twine(getTok().getString()));
923 const AsmToken *tok = &Lexer.Lex();
925 // Parse comments here to be deferred until end of next statement.
926 while (tok->is(AsmToken::Comment)) {
927 if (MAI.preserveAsmComments())
928 Out.addExplicitComment(Twine(tok->getString()));
932 if (tok->is(AsmToken::Eof)) {
933 // If this is the end of an included file, pop the parent file off the
935 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
936 if (ParentIncludeLoc != SMLoc()) {
937 jumpToLoc(ParentIncludeLoc);
945 bool AsmParser::enabledGenDwarfForAssembly() {
946 // Check whether the user specified -g.
947 if (!getContext().getGenDwarfForAssembly())
949 // If we haven't encountered any .file directives (which would imply that
950 // the assembler source was produced with debug info already) then emit one
951 // describing the assembler source file itself.
952 if (getContext().getGenDwarfFileNumber() == 0) {
953 // Use the first #line directive for this, if any. It's preprocessed, so
954 // there is no checksum, and of course no source directive.
955 if (!FirstCppHashFilename.empty())
956 getContext().setMCLineTableRootFile(
957 /*CUID=*/0, getContext().getCompilationDir(), FirstCppHashFilename,
958 /*Cksum=*/std::nullopt, /*Source=*/std::nullopt);
959 const MCDwarfFile &RootFile =
960 getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
961 getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
962 /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
963 RootFile.Checksum, RootFile.Source));
968 bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
969 LTODiscardSymbols.clear();
971 // Create the initial section, if requested.
972 if (!NoInitialTextSection)
973 Out.initSections(false, getTargetParser().getSTI());
979 AsmCond StartingCondState = TheCondState;
980 SmallVector<AsmRewrite, 4> AsmStrRewrites;
982 // If we are generating dwarf for assembly source files save the initial text
983 // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't
984 // emitting any actual debug info yet and haven't had a chance to parse any
985 // embedded .file directives.)
986 if (getContext().getGenDwarfForAssembly()) {
987 MCSection *Sec = getStreamer().getCurrentSectionOnly();
988 if (!Sec->getBeginSymbol()) {
989 MCSymbol *SectionStartSym = getContext().createTempSymbol();
990 getStreamer().emitLabel(SectionStartSym);
991 Sec->setBeginSymbol(SectionStartSym);
993 bool InsertResult = getContext().addGenDwarfSection(Sec);
994 assert(InsertResult && ".text section should not have debug info yet");
998 getTargetParser().onBeginOfFile();
1000 // While we have input, parse each statement.
1001 while (Lexer.isNot(AsmToken::Eof)) {
1002 ParseStatementInfo Info(&AsmStrRewrites);
1003 bool Parsed = parseStatement(Info, nullptr);
1005 // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
1006 // for printing ErrMsg via Lex() only if no (presumably better) parser error
1008 if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
1012 // parseStatement returned true so may need to emit an error.
1013 printPendingErrors();
1015 // Skipping to the next line if needed.
1016 if (Parsed && !getLexer().isAtStartOfStatement())
1017 eatToEndOfStatement();
1020 getTargetParser().onEndOfFile();
1021 printPendingErrors();
1023 // All errors should have been emitted.
1024 assert(!hasPendingError() && "unexpected error from parseStatement");
1026 getTargetParser().flushPendingInstructions(getStreamer());
1028 if (TheCondState.TheCond != StartingCondState.TheCond ||
1029 TheCondState.Ignore != StartingCondState.Ignore)
1030 printError(getTok().getLoc(), "unmatched .ifs or .elses");
1031 // Check to see there are no empty DwarfFile slots.
1032 const auto &LineTables = getContext().getMCDwarfLineTables();
1033 if (!LineTables.empty()) {
1035 for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {
1036 if (File.Name.empty() && Index != 0)
1037 printError(getTok().getLoc(), "unassigned file number: " +
1039 " for .file directives");
1044 // Check to see that all assembler local symbols were actually defined.
1045 // Targets that don't do subsections via symbols may not want this, though,
1046 // so conservatively exclude them. Only do this if we're finalizing, though,
1047 // as otherwise we won't necessarilly have seen everything yet.
1049 if (MAI.hasSubsectionsViaSymbols()) {
1050 for (const auto &TableEntry : getContext().getSymbols()) {
1051 MCSymbol *Sym = TableEntry.getValue();
1052 // Variable symbols may not be marked as defined, so check those
1053 // explicitly. If we know it's a variable, we have a definition for
1054 // the purposes of this check.
1055 if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
1056 // FIXME: We would really like to refer back to where the symbol was
1057 // first referenced for a source location. We need to add something
1058 // to track that. Currently, we just point to the end of the file.
1059 printError(getTok().getLoc(), "assembler local symbol '" +
1060 Sym->getName() + "' not defined");
1064 // Temporary symbols like the ones for directional jumps don't go in the
1065 // symbol table. They also need to be diagnosed in all (final) cases.
1066 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1067 if (std::get<2>(LocSym)->isUndefined()) {
1068 // Reset the state of any "# line file" directives we've seen to the
1069 // context as it was at the diagnostic site.
1070 CppHashInfo = std::get<1>(LocSym);
1071 printError(std::get<0>(LocSym), "directional label undefined");
1075 // Finalize the output stream if there are no errors and if the client wants
1077 if (!HadError && !NoFinalize) {
1078 if (auto *TS = Out.getTargetStreamer())
1079 TS->emitConstantPools();
1081 Out.finish(Lexer.getLoc());
1084 return HadError || getContext().hadError();
1087 bool AsmParser::checkForValidSection() {
1088 if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
1089 Out.initSections(false, getTargetParser().getSTI());
1090 return Error(getTok().getLoc(),
1091 "expected section directive before assembly directive");
1096 /// Throw away the rest of the line for testing purposes.
1097 void AsmParser::eatToEndOfStatement() {
1098 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
1102 if (Lexer.is(AsmToken::EndOfStatement))
1106 StringRef AsmParser::parseStringToEndOfStatement() {
1107 const char *Start = getTok().getLoc().getPointer();
1109 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
1112 const char *End = getTok().getLoc().getPointer();
1113 return StringRef(Start, End - Start);
1116 StringRef AsmParser::parseStringToComma() {
1117 const char *Start = getTok().getLoc().getPointer();
1119 while (Lexer.isNot(AsmToken::EndOfStatement) &&
1120 Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof))
1123 const char *End = getTok().getLoc().getPointer();
1124 return StringRef(Start, End - Start);
1127 /// Parse a paren expression and return it.
1128 /// NOTE: This assumes the leading '(' has already been consumed.
1130 /// parenexpr ::= expr)
1132 bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1133 if (parseExpression(Res))
1135 EndLoc = Lexer.getTok().getEndLoc();
1136 return parseRParen();
1139 /// Parse a bracket expression and return it.
1140 /// NOTE: This assumes the leading '[' has already been consumed.
1142 /// bracketexpr ::= expr]
1144 bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1145 if (parseExpression(Res))
1147 EndLoc = getTok().getEndLoc();
1148 if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
1153 /// Parse a primary expression and return it.
1154 /// primaryexpr ::= (parenexpr
1155 /// primaryexpr ::= symbol
1156 /// primaryexpr ::= number
1157 /// primaryexpr ::= '.'
1158 /// primaryexpr ::= ~,+,- primaryexpr
1159 bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
1160 AsmTypeInfo *TypeInfo) {
1161 SMLoc FirstTokenLoc = getLexer().getLoc();
1162 AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
1163 switch (FirstTokenKind) {
1165 return TokError("unknown token in expression");
1166 // If we have an error assume that we've already handled it.
1167 case AsmToken::Error:
1169 case AsmToken::Exclaim:
1170 Lex(); // Eat the operator.
1171 if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
1173 Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
1175 case AsmToken::Dollar:
1176 case AsmToken::Star:
1178 case AsmToken::String:
1179 case AsmToken::Identifier: {
1180 StringRef Identifier;
1181 if (parseIdentifier(Identifier)) {
1182 // We may have failed but '$'|'*' may be a valid token in context of
1184 if (getTok().is(AsmToken::Dollar) || getTok().is(AsmToken::Star)) {
1185 bool ShouldGenerateTempSymbol = false;
1186 if ((getTok().is(AsmToken::Dollar) && MAI.getDollarIsPC()) ||
1187 (getTok().is(AsmToken::Star) && MAI.getStarIsPC()))
1188 ShouldGenerateTempSymbol = true;
1190 if (!ShouldGenerateTempSymbol)
1191 return Error(FirstTokenLoc, "invalid token in expression");
1193 // Eat the '$'|'*' token.
1195 // This is either a '$'|'*' reference, which references the current PC.
1196 // Emit a temporary label to the streamer and refer to it.
1197 MCSymbol *Sym = Ctx.createTempSymbol();
1199 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
1201 EndLoc = FirstTokenLoc;
1205 // Parse symbol variant
1206 std::pair<StringRef, StringRef> Split;
1207 if (!MAI.useParensForSymbolVariant()) {
1208 if (FirstTokenKind == AsmToken::String) {
1209 if (Lexer.is(AsmToken::At)) {
1211 SMLoc AtLoc = getLexer().getLoc();
1213 if (parseIdentifier(VName))
1214 return Error(AtLoc, "expected symbol variant after '@'");
1216 Split = std::make_pair(Identifier, VName);
1219 Split = Identifier.split('@');
1221 } else if (Lexer.is(AsmToken::LParen)) {
1224 parseIdentifier(VName);
1227 Split = std::make_pair(Identifier, VName);
1230 EndLoc = SMLoc::getFromPointer(Identifier.end());
1232 // This is a symbol reference.
1233 StringRef SymbolName = Identifier;
1234 if (SymbolName.empty())
1235 return Error(getLexer().getLoc(), "expected a symbol reference");
1237 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
1239 // Lookup the symbol variant if used.
1240 if (!Split.second.empty()) {
1241 Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
1242 if (Variant != MCSymbolRefExpr::VK_Invalid) {
1243 SymbolName = Split.first;
1244 } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
1245 Variant = MCSymbolRefExpr::VK_None;
1247 return Error(SMLoc::getFromPointer(Split.second.begin()),
1248 "invalid variant '" + Split.second + "'");
1252 MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
1254 Sym = getContext().getOrCreateSymbol(
1255 MAI.shouldEmitLabelsInUpperCase() ? SymbolName.upper() : SymbolName);
1257 // If this is an absolute variable reference, substitute it now to preserve
1258 // semantics in the face of reassignment.
1259 if (Sym->isVariable()) {
1260 auto V = Sym->getVariableValue(/*SetUsed*/ false);
1261 bool DoInline = isa<MCConstantExpr>(V) && !Variant;
1262 if (auto TV = dyn_cast<MCTargetExpr>(V))
1263 DoInline = TV->inlineAssignedExpr();
1266 return Error(EndLoc, "unexpected modifier on variable reference");
1267 Res = Sym->getVariableValue(/*SetUsed*/ false);
1272 // Otherwise create a symbol ref.
1273 Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
1276 case AsmToken::BigNum:
1277 return TokError("literal value out of range for directive");
1278 case AsmToken::Integer: {
1279 SMLoc Loc = getTok().getLoc();
1280 int64_t IntVal = getTok().getIntVal();
1281 Res = MCConstantExpr::create(IntVal, getContext());
1282 EndLoc = Lexer.getTok().getEndLoc();
1283 Lex(); // Eat token.
1284 // Look for 'b' or 'f' following an Integer as a directional label
1285 if (Lexer.getKind() == AsmToken::Identifier) {
1286 StringRef IDVal = getTok().getString();
1287 // Lookup the symbol variant if used.
1288 std::pair<StringRef, StringRef> Split = IDVal.split('@');
1289 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
1290 if (Split.first.size() != IDVal.size()) {
1291 Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
1292 if (Variant == MCSymbolRefExpr::VK_Invalid)
1293 return TokError("invalid variant '" + Split.second + "'");
1294 IDVal = Split.first;
1296 if (IDVal == "f" || IDVal == "b") {
1298 Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
1299 Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
1300 if (IDVal == "b" && Sym->isUndefined())
1301 return Error(Loc, "directional label undefined");
1302 DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
1303 EndLoc = Lexer.getTok().getEndLoc();
1304 Lex(); // Eat identifier.
1309 case AsmToken::Real: {
1310 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1311 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
1312 Res = MCConstantExpr::create(IntVal, getContext());
1313 EndLoc = Lexer.getTok().getEndLoc();
1314 Lex(); // Eat token.
1317 case AsmToken::Dot: {
1318 if (!MAI.getDotIsPC())
1319 return TokError("cannot use . as current PC");
1321 // This is a '.' reference, which references the current PC. Emit a
1322 // temporary label to the streamer and refer to it.
1323 MCSymbol *Sym = Ctx.createTempSymbol();
1325 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1326 EndLoc = Lexer.getTok().getEndLoc();
1327 Lex(); // Eat identifier.
1330 case AsmToken::LParen:
1331 Lex(); // Eat the '('.
1332 return parseParenExpr(Res, EndLoc);
1333 case AsmToken::LBrac:
1334 if (!PlatformParser->HasBracketExpressions())
1335 return TokError("brackets expression not supported on this target");
1336 Lex(); // Eat the '['.
1337 return parseBracketExpr(Res, EndLoc);
1338 case AsmToken::Minus:
1339 Lex(); // Eat the operator.
1340 if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
1342 Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
1344 case AsmToken::Plus:
1345 Lex(); // Eat the operator.
1346 if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
1348 Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
1350 case AsmToken::Tilde:
1351 Lex(); // Eat the operator.
1352 if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
1354 Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
1356 // MIPS unary expression operators. The lexer won't generate these tokens if
1357 // MCAsmInfo::HasMipsExpressions is false for the target.
1358 case AsmToken::PercentCall16:
1359 case AsmToken::PercentCall_Hi:
1360 case AsmToken::PercentCall_Lo:
1361 case AsmToken::PercentDtprel_Hi:
1362 case AsmToken::PercentDtprel_Lo:
1363 case AsmToken::PercentGot:
1364 case AsmToken::PercentGot_Disp:
1365 case AsmToken::PercentGot_Hi:
1366 case AsmToken::PercentGot_Lo:
1367 case AsmToken::PercentGot_Ofst:
1368 case AsmToken::PercentGot_Page:
1369 case AsmToken::PercentGottprel:
1370 case AsmToken::PercentGp_Rel:
1371 case AsmToken::PercentHi:
1372 case AsmToken::PercentHigher:
1373 case AsmToken::PercentHighest:
1374 case AsmToken::PercentLo:
1375 case AsmToken::PercentNeg:
1376 case AsmToken::PercentPcrel_Hi:
1377 case AsmToken::PercentPcrel_Lo:
1378 case AsmToken::PercentTlsgd:
1379 case AsmToken::PercentTlsldm:
1380 case AsmToken::PercentTprel_Hi:
1381 case AsmToken::PercentTprel_Lo:
1382 Lex(); // Eat the operator.
1383 if (Lexer.isNot(AsmToken::LParen))
1384 return TokError("expected '(' after operator");
1385 Lex(); // Eat the operator.
1386 if (parseExpression(Res, EndLoc))
1390 Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
1395 bool AsmParser::parseExpression(const MCExpr *&Res) {
1397 return parseExpression(Res, EndLoc);
1401 AsmParser::applyModifierToExpr(const MCExpr *E,
1402 MCSymbolRefExpr::VariantKind Variant) {
1403 // Ask the target implementation about this expression first.
1404 const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx);
1407 // Recurse over the given expression, rebuilding it to apply the given variant
1408 // if there is exactly one symbol.
1409 switch (E->getKind()) {
1410 case MCExpr::Target:
1411 case MCExpr::Constant:
1414 case MCExpr::SymbolRef: {
1415 const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
1417 if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
1418 TokError("invalid variant on expression '" + getTok().getIdentifier() +
1419 "' (already modified)");
1423 return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext());
1426 case MCExpr::Unary: {
1427 const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
1428 const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant);
1431 return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext());
1434 case MCExpr::Binary: {
1435 const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
1436 const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant);
1437 const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant);
1447 return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext());
1451 llvm_unreachable("Invalid expression kind!");
1454 /// This function checks if the next token is <string> type or arithmetic.
1455 /// string that begin with character '<' must end with character '>'.
1456 /// otherwise it is arithmetics.
1457 /// If the function returns a 'true' value,
1458 /// the End argument will be filled with the last location pointed to the '>'
1461 /// There is a gap between the AltMacro's documentation and the single quote
1462 /// implementation. GCC does not fully support this feature and so we will not
1464 /// TODO: Adding single quote as a string.
1465 static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
1466 assert((StrLoc.getPointer() != nullptr) &&
1467 "Argument to the function cannot be a NULL value");
1468 const char *CharPtr = StrLoc.getPointer();
1469 while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
1470 (*CharPtr != '\0')) {
1471 if (*CharPtr == '!')
1475 if (*CharPtr == '>') {
1476 EndLoc = StrLoc.getFromPointer(CharPtr + 1);
1482 /// creating a string without the escape characters '!'.
1483 static std::string angleBracketString(StringRef AltMacroStr) {
1485 for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
1486 if (AltMacroStr[Pos] == '!')
1488 Res += AltMacroStr[Pos];
1493 /// Parse an expression and return it.
1495 /// expr ::= expr &&,|| expr -> lowest.
1496 /// expr ::= expr |,^,&,! expr
1497 /// expr ::= expr ==,!=,<>,<,<=,>,>= expr
1498 /// expr ::= expr <<,>> expr
1499 /// expr ::= expr +,- expr
1500 /// expr ::= expr *,/,% expr -> highest.
1501 /// expr ::= primaryexpr
1503 bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
1504 // Parse the expression.
1506 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1507 parseBinOpRHS(1, Res, EndLoc))
1510 // As a special case, we support 'a op b @ modifier' by rewriting the
1511 // expression to include the modifier. This is inefficient, but in general we
1512 // expect users to use 'a@modifier op b'.
1513 if (Lexer.getKind() == AsmToken::At) {
1516 if (Lexer.isNot(AsmToken::Identifier))
1517 return TokError("unexpected symbol modifier following '@'");
1519 MCSymbolRefExpr::VariantKind Variant =
1520 MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
1521 if (Variant == MCSymbolRefExpr::VK_Invalid)
1522 return TokError("invalid variant '" + getTok().getIdentifier() + "'");
1524 const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant);
1526 return TokError("invalid modifier '" + getTok().getIdentifier() +
1527 "' (no symbols present)");
1534 // Try to constant fold it up front, if possible. Do not exploit
1537 if (Res->evaluateAsAbsolute(Value))
1538 Res = MCConstantExpr::create(Value, getContext());
1543 bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
1545 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1548 bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
1550 if (parseParenExpr(Res, EndLoc))
1553 for (; ParenDepth > 0; --ParenDepth) {
1554 if (parseBinOpRHS(1, Res, EndLoc))
1557 // We don't Lex() the last RParen.
1558 // This is the same behavior as parseParenExpression().
1559 if (ParenDepth - 1 > 0) {
1560 EndLoc = getTok().getEndLoc();
1568 bool AsmParser::parseAbsoluteExpression(int64_t &Res) {
1571 SMLoc StartLoc = Lexer.getLoc();
1572 if (parseExpression(Expr))
1575 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1576 return Error(StartLoc, "expected absolute expression");
1581 static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K,
1582 MCBinaryExpr::Opcode &Kind,
1583 bool ShouldUseLogicalShr) {
1586 return 0; // not a binop.
1588 // Lowest Precedence: &&, ||
1589 case AsmToken::AmpAmp:
1590 Kind = MCBinaryExpr::LAnd;
1592 case AsmToken::PipePipe:
1593 Kind = MCBinaryExpr::LOr;
1596 // Low Precedence: |, &, ^
1597 case AsmToken::Pipe:
1598 Kind = MCBinaryExpr::Or;
1600 case AsmToken::Caret:
1601 Kind = MCBinaryExpr::Xor;
1604 Kind = MCBinaryExpr::And;
1607 // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
1608 case AsmToken::EqualEqual:
1609 Kind = MCBinaryExpr::EQ;
1611 case AsmToken::ExclaimEqual:
1612 case AsmToken::LessGreater:
1613 Kind = MCBinaryExpr::NE;
1615 case AsmToken::Less:
1616 Kind = MCBinaryExpr::LT;
1618 case AsmToken::LessEqual:
1619 Kind = MCBinaryExpr::LTE;
1621 case AsmToken::Greater:
1622 Kind = MCBinaryExpr::GT;
1624 case AsmToken::GreaterEqual:
1625 Kind = MCBinaryExpr::GTE;
1628 // Intermediate Precedence: <<, >>
1629 case AsmToken::LessLess:
1630 Kind = MCBinaryExpr::Shl;
1632 case AsmToken::GreaterGreater:
1633 Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
1636 // High Intermediate Precedence: +, -
1637 case AsmToken::Plus:
1638 Kind = MCBinaryExpr::Add;
1640 case AsmToken::Minus:
1641 Kind = MCBinaryExpr::Sub;
1644 // Highest Precedence: *, /, %
1645 case AsmToken::Star:
1646 Kind = MCBinaryExpr::Mul;
1648 case AsmToken::Slash:
1649 Kind = MCBinaryExpr::Div;
1651 case AsmToken::Percent:
1652 Kind = MCBinaryExpr::Mod;
1657 static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI,
1658 AsmToken::TokenKind K,
1659 MCBinaryExpr::Opcode &Kind,
1660 bool ShouldUseLogicalShr) {
1663 return 0; // not a binop.
1665 // Lowest Precedence: &&, ||
1666 case AsmToken::AmpAmp:
1667 Kind = MCBinaryExpr::LAnd;
1669 case AsmToken::PipePipe:
1670 Kind = MCBinaryExpr::LOr;
1673 // Low Precedence: ==, !=, <>, <, <=, >, >=
1674 case AsmToken::EqualEqual:
1675 Kind = MCBinaryExpr::EQ;
1677 case AsmToken::ExclaimEqual:
1678 case AsmToken::LessGreater:
1679 Kind = MCBinaryExpr::NE;
1681 case AsmToken::Less:
1682 Kind = MCBinaryExpr::LT;
1684 case AsmToken::LessEqual:
1685 Kind = MCBinaryExpr::LTE;
1687 case AsmToken::Greater:
1688 Kind = MCBinaryExpr::GT;
1690 case AsmToken::GreaterEqual:
1691 Kind = MCBinaryExpr::GTE;
1694 // Low Intermediate Precedence: +, -
1695 case AsmToken::Plus:
1696 Kind = MCBinaryExpr::Add;
1698 case AsmToken::Minus:
1699 Kind = MCBinaryExpr::Sub;
1702 // High Intermediate Precedence: |, !, &, ^
1704 case AsmToken::Pipe:
1705 Kind = MCBinaryExpr::Or;
1707 case AsmToken::Exclaim:
1708 // Hack to support ARM compatible aliases (implied 'sp' operand in 'srs*'
1709 // instructions like 'srsda #31!') and not parse ! as an infix operator.
1710 if (MAI.getCommentString() == "@")
1712 Kind = MCBinaryExpr::OrNot;
1714 case AsmToken::Caret:
1715 Kind = MCBinaryExpr::Xor;
1718 Kind = MCBinaryExpr::And;
1721 // Highest Precedence: *, /, %, <<, >>
1722 case AsmToken::Star:
1723 Kind = MCBinaryExpr::Mul;
1725 case AsmToken::Slash:
1726 Kind = MCBinaryExpr::Div;
1728 case AsmToken::Percent:
1729 Kind = MCBinaryExpr::Mod;
1731 case AsmToken::LessLess:
1732 Kind = MCBinaryExpr::Shl;
1734 case AsmToken::GreaterGreater:
1735 Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
1740 unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
1741 MCBinaryExpr::Opcode &Kind) {
1742 bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
1743 return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)
1744 : getGNUBinOpPrecedence(MAI, K, Kind, ShouldUseLogicalShr);
1747 /// Parse all binary operators with precedence >= 'Precedence'.
1748 /// Res contains the LHS of the expression on input.
1749 bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
1751 SMLoc StartLoc = Lexer.getLoc();
1753 MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
1754 unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
1756 // If the next token is lower precedence than we are allowed to eat, return
1757 // successfully with what we ate already.
1758 if (TokPrec < Precedence)
1763 // Eat the next primary expression.
1765 if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
1768 // If BinOp binds less tightly with RHS than the operator after RHS, let
1769 // the pending operator take RHS as its LHS.
1770 MCBinaryExpr::Opcode Dummy;
1771 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1772 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
1775 // Merge LHS and RHS according to operator.
1776 Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
1781 /// ::= EndOfStatement
1782 /// ::= Label* Directive ...Operands... EndOfStatement
1783 /// ::= Label* Identifier OperandList* EndOfStatement
1784 bool AsmParser::parseStatement(ParseStatementInfo &Info,
1785 MCAsmParserSemaCallback *SI) {
1786 assert(!hasPendingError() && "parseStatement started with pending error");
1787 // Eat initial spaces and comments
1788 while (Lexer.is(AsmToken::Space))
1790 if (Lexer.is(AsmToken::EndOfStatement)) {
1791 // if this is a line comment we can drop it safely
1792 if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
1793 getTok().getString().front() == '\n')
1798 // Statements always start with an identifier.
1799 AsmToken ID = getTok();
1800 SMLoc IDLoc = ID.getLoc();
1802 int64_t LocalLabelVal = -1;
1803 StartTokLoc = ID.getLoc();
1804 if (Lexer.is(AsmToken::HashDirective))
1805 return parseCppHashLineFilenameComment(IDLoc,
1806 !isInsideMacroInstantiation());
1808 // Allow an integer followed by a ':' as a directional local label.
1809 if (Lexer.is(AsmToken::Integer)) {
1810 LocalLabelVal = getTok().getIntVal();
1811 if (LocalLabelVal < 0) {
1812 if (!TheCondState.Ignore) {
1813 Lex(); // always eat a token
1814 return Error(IDLoc, "unexpected token at start of statement");
1818 IDVal = getTok().getString();
1819 Lex(); // Consume the integer token to be used as an identifier token.
1820 if (Lexer.getKind() != AsmToken::Colon) {
1821 if (!TheCondState.Ignore) {
1822 Lex(); // always eat a token
1823 return Error(IDLoc, "unexpected token at start of statement");
1827 } else if (Lexer.is(AsmToken::Dot)) {
1828 // Treat '.' as a valid identifier in this context.
1831 } else if (Lexer.is(AsmToken::LCurly)) {
1832 // Treat '{' as a valid identifier in this context.
1836 } else if (Lexer.is(AsmToken::RCurly)) {
1837 // Treat '}' as a valid identifier in this context.
1840 } else if (Lexer.is(AsmToken::Star) &&
1841 getTargetParser().starIsStartOfStatement()) {
1842 // Accept '*' as a valid start of statement.
1845 } else if (parseIdentifier(IDVal)) {
1846 if (!TheCondState.Ignore) {
1847 Lex(); // always eat a token
1848 return Error(IDLoc, "unexpected token at start of statement");
1853 // Handle conditional assembly here before checking for skipping. We
1854 // have to do this so that .endif isn't skipped in a ".if 0" block for
1856 StringMap<DirectiveKind>::const_iterator DirKindIt =
1857 DirectiveKindMap.find(IDVal.lower());
1858 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1860 : DirKindIt->getValue();
1871 return parseDirectiveIf(IDLoc, DirKind);
1873 return parseDirectiveIfb(IDLoc, true);
1875 return parseDirectiveIfb(IDLoc, false);
1877 return parseDirectiveIfc(IDLoc, true);
1879 return parseDirectiveIfeqs(IDLoc, true);
1881 return parseDirectiveIfc(IDLoc, false);
1883 return parseDirectiveIfeqs(IDLoc, false);
1885 return parseDirectiveIfdef(IDLoc, true);
1888 return parseDirectiveIfdef(IDLoc, false);
1890 return parseDirectiveElseIf(IDLoc);
1892 return parseDirectiveElse(IDLoc);
1894 return parseDirectiveEndIf(IDLoc);
1897 // Ignore the statement if in the middle of inactive conditional
1899 if (TheCondState.Ignore) {
1900 eatToEndOfStatement();
1904 // FIXME: Recurse on local labels?
1906 // Check for a label.
1907 // ::= identifier ':'
1909 if (Lexer.is(AsmToken::Colon) && getTargetParser().isLabel(ID)) {
1910 if (checkForValidSection())
1913 Lex(); // Consume the ':'.
1915 // Diagnose attempt to use '.' as a label.
1917 return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
1919 // Diagnose attempt to use a variable as a label.
1921 // FIXME: Diagnostics. Note the location of the definition as a label.
1922 // FIXME: This doesn't diagnose assignment to a symbol which has been
1923 // implicitly marked as external.
1925 if (LocalLabelVal == -1) {
1926 if (ParsingMSInlineAsm && SI) {
1927 StringRef RewrittenLabel =
1928 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
1929 assert(!RewrittenLabel.empty() &&
1930 "We should have an internal name here.");
1931 Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
1933 IDVal = RewrittenLabel;
1935 Sym = getContext().getOrCreateSymbol(IDVal);
1937 Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
1938 // End of Labels should be treated as end of line for lexing
1939 // purposes but that information is not available to the Lexer who
1940 // does not understand Labels. This may cause us to see a Hash
1941 // here instead of a preprocessor line comment.
1942 if (getTok().is(AsmToken::Hash)) {
1943 StringRef CommentStr = parseStringToEndOfStatement();
1945 Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
1948 // Consume any end of statement token, if present, to avoid spurious
1949 // addBlankLine calls().
1950 if (getTok().is(AsmToken::EndOfStatement)) {
1954 if (MAI.hasSubsectionsViaSymbols() && CFIStartProcLoc &&
1955 Sym->isExternal() && !cast<MCSymbolMachO>(Sym)->isAltEntry())
1956 return Error(StartTokLoc, "non-private labels cannot appear between "
1957 ".cfi_startproc / .cfi_endproc pairs") &&
1958 Error(*CFIStartProcLoc, "previous .cfi_startproc was here");
1960 if (discardLTOSymbol(IDVal))
1963 getTargetParser().doBeforeLabelEmit(Sym, IDLoc);
1966 if (!getTargetParser().isParsingMSInlineAsm())
1967 Out.emitLabel(Sym, IDLoc);
1969 // If we are generating dwarf for assembly source files then gather the
1970 // info to make a dwarf label entry for this label if needed.
1971 if (enabledGenDwarfForAssembly())
1972 MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
1975 getTargetParser().onLabelParsed(Sym);
1980 // Check for an assignment statement.
1981 // ::= identifier '='
1982 if (Lexer.is(AsmToken::Equal) && getTargetParser().equalIsAsmAssignment()) {
1984 return parseAssignment(IDVal, AssignmentKind::Equal);
1987 // If macros are enabled, check to see if this is a macro instantiation.
1988 if (areMacrosEnabled())
1989 if (const MCAsmMacro *M = getContext().lookupMacro(IDVal)) {
1990 return handleMacroEntry(M, IDLoc);
1993 // Otherwise, we have a normal instruction or directive.
1995 // Directives start with "."
1996 if (IDVal.starts_with(".") && IDVal != ".") {
1997 // There are several entities interested in parsing directives:
1999 // 1. The target-specific assembly parser. Some directives are target
2000 // specific or may potentially behave differently on certain targets.
2001 // 2. Asm parser extensions. For example, platform-specific parsers
2002 // (like the ELF parser) register themselves as extensions.
2003 // 3. The generic directive parser implemented by this class. These are
2004 // all the directives that behave in a target and platform independent
2005 // manner, or at least have a default behavior that's shared between
2006 // all targets and platforms.
2008 getTargetParser().flushPendingInstructions(getStreamer());
2010 ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);
2011 assert(TPDirectiveReturn.isFailure() == hasPendingError() &&
2012 "Should only return Failure iff there was an error");
2013 if (TPDirectiveReturn.isFailure())
2015 if (TPDirectiveReturn.isSuccess())
2018 // Next, check the extension directive map to see if any extension has
2019 // registered itself to parse this directive.
2020 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2021 ExtensionDirectiveMap.lookup(IDVal);
2023 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2025 // Finally, if no one else is interested in this directive, it must be
2026 // generic and familiar to this class.
2032 return parseDirectiveSet(IDVal, AssignmentKind::Set);
2034 return parseDirectiveSet(IDVal, AssignmentKind::Equiv);
2035 case DK_LTO_SET_CONDITIONAL:
2036 return parseDirectiveSet(IDVal, AssignmentKind::LTOSetConditional);
2038 return parseDirectiveAscii(IDVal, false);
2041 return parseDirectiveAscii(IDVal, true);
2044 return parseDirectiveValue(IDVal, 1);
2050 return parseDirectiveValue(IDVal, 2);
2055 return parseDirectiveValue(IDVal, 4);
2058 return parseDirectiveValue(IDVal, 8);
2060 return parseDirectiveValue(
2061 IDVal, getContext().getAsmInfo()->getCodePointerSize());
2063 return parseDirectiveOctaValue(IDVal);
2067 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());
2070 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());
2072 bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
2073 return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);
2076 bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
2077 return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);
2080 return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
2082 return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
2084 return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
2086 return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
2088 return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
2090 return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
2092 return parseDirectiveOrg();
2094 return parseDirectiveFill();
2096 return parseDirectiveZero();
2098 eatToEndOfStatement(); // .extern is the default, ignore it.
2102 return parseDirectiveSymbolAttribute(MCSA_Global);
2103 case DK_LAZY_REFERENCE:
2104 return parseDirectiveSymbolAttribute(MCSA_LazyReference);
2105 case DK_NO_DEAD_STRIP:
2106 return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
2107 case DK_SYMBOL_RESOLVER:
2108 return parseDirectiveSymbolAttribute(MCSA_SymbolResolver);
2109 case DK_PRIVATE_EXTERN:
2110 return parseDirectiveSymbolAttribute(MCSA_PrivateExtern);
2112 return parseDirectiveSymbolAttribute(MCSA_Reference);
2113 case DK_WEAK_DEFINITION:
2114 return parseDirectiveSymbolAttribute(MCSA_WeakDefinition);
2115 case DK_WEAK_REFERENCE:
2116 return parseDirectiveSymbolAttribute(MCSA_WeakReference);
2117 case DK_WEAK_DEF_CAN_BE_HIDDEN:
2118 return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
2120 return parseDirectiveSymbolAttribute(MCSA_Cold);
2123 return parseDirectiveComm(/*IsLocal=*/false);
2125 return parseDirectiveComm(/*IsLocal=*/true);
2127 return parseDirectiveAbort();
2129 return parseDirectiveInclude();
2131 return parseDirectiveIncbin();
2134 return TokError(Twine(IDVal) +
2135 " not currently supported for this target");
2137 return parseDirectiveRept(IDLoc, IDVal);
2139 return parseDirectiveIrp(IDLoc);
2141 return parseDirectiveIrpc(IDLoc);
2143 return parseDirectiveEndr(IDLoc);
2144 case DK_BUNDLE_ALIGN_MODE:
2145 return parseDirectiveBundleAlignMode();
2146 case DK_BUNDLE_LOCK:
2147 return parseDirectiveBundleLock();
2148 case DK_BUNDLE_UNLOCK:
2149 return parseDirectiveBundleUnlock();
2151 return parseDirectiveLEB128(true);
2153 return parseDirectiveLEB128(false);
2156 return parseDirectiveSpace(IDVal);
2158 return parseDirectiveFile(IDLoc);
2160 return parseDirectiveLine();
2162 return parseDirectiveLoc();
2164 return parseDirectiveStabs();
2166 return parseDirectiveCVFile();
2168 return parseDirectiveCVFuncId();
2169 case DK_CV_INLINE_SITE_ID:
2170 return parseDirectiveCVInlineSiteId();
2172 return parseDirectiveCVLoc();
2173 case DK_CV_LINETABLE:
2174 return parseDirectiveCVLinetable();
2175 case DK_CV_INLINE_LINETABLE:
2176 return parseDirectiveCVInlineLinetable();
2177 case DK_CV_DEF_RANGE:
2178 return parseDirectiveCVDefRange();
2180 return parseDirectiveCVString();
2181 case DK_CV_STRINGTABLE:
2182 return parseDirectiveCVStringTable();
2183 case DK_CV_FILECHECKSUMS:
2184 return parseDirectiveCVFileChecksums();
2185 case DK_CV_FILECHECKSUM_OFFSET:
2186 return parseDirectiveCVFileChecksumOffset();
2187 case DK_CV_FPO_DATA:
2188 return parseDirectiveCVFPOData();
2189 case DK_CFI_SECTIONS:
2190 return parseDirectiveCFISections();
2191 case DK_CFI_STARTPROC:
2192 return parseDirectiveCFIStartProc();
2193 case DK_CFI_ENDPROC:
2194 return parseDirectiveCFIEndProc();
2195 case DK_CFI_DEF_CFA:
2196 return parseDirectiveCFIDefCfa(IDLoc);
2197 case DK_CFI_DEF_CFA_OFFSET:
2198 return parseDirectiveCFIDefCfaOffset(IDLoc);
2199 case DK_CFI_ADJUST_CFA_OFFSET:
2200 return parseDirectiveCFIAdjustCfaOffset(IDLoc);
2201 case DK_CFI_DEF_CFA_REGISTER:
2202 return parseDirectiveCFIDefCfaRegister(IDLoc);
2203 case DK_CFI_LLVM_DEF_ASPACE_CFA:
2204 return parseDirectiveCFILLVMDefAspaceCfa(IDLoc);
2206 return parseDirectiveCFIOffset(IDLoc);
2207 case DK_CFI_REL_OFFSET:
2208 return parseDirectiveCFIRelOffset(IDLoc);
2209 case DK_CFI_PERSONALITY:
2210 return parseDirectiveCFIPersonalityOrLsda(true);
2212 return parseDirectiveCFIPersonalityOrLsda(false);
2213 case DK_CFI_REMEMBER_STATE:
2214 return parseDirectiveCFIRememberState(IDLoc);
2215 case DK_CFI_RESTORE_STATE:
2216 return parseDirectiveCFIRestoreState(IDLoc);
2217 case DK_CFI_SAME_VALUE:
2218 return parseDirectiveCFISameValue(IDLoc);
2219 case DK_CFI_RESTORE:
2220 return parseDirectiveCFIRestore(IDLoc);
2222 return parseDirectiveCFIEscape(IDLoc);
2223 case DK_CFI_RETURN_COLUMN:
2224 return parseDirectiveCFIReturnColumn(IDLoc);
2225 case DK_CFI_SIGNAL_FRAME:
2226 return parseDirectiveCFISignalFrame(IDLoc);
2227 case DK_CFI_UNDEFINED:
2228 return parseDirectiveCFIUndefined(IDLoc);
2229 case DK_CFI_REGISTER:
2230 return parseDirectiveCFIRegister(IDLoc);
2231 case DK_CFI_WINDOW_SAVE:
2232 return parseDirectiveCFIWindowSave(IDLoc);
2235 return parseDirectiveMacrosOnOff(IDVal);
2237 return parseDirectiveMacro(IDLoc);
2240 return parseDirectiveAltmacro(IDVal);
2242 return parseDirectiveExitMacro(IDVal);
2245 return parseDirectiveEndMacro(IDVal);
2247 return parseDirectivePurgeMacro(IDLoc);
2249 return parseDirectiveEnd(IDLoc);
2251 return parseDirectiveError(IDLoc, false);
2253 return parseDirectiveError(IDLoc, true);
2255 return parseDirectiveWarning(IDLoc);
2257 return parseDirectiveReloc(IDLoc);
2260 return parseDirectiveDCB(IDVal, 2);
2262 return parseDirectiveDCB(IDVal, 1);
2264 return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble());
2266 return parseDirectiveDCB(IDVal, 4);
2268 return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle());
2271 return TokError(Twine(IDVal) +
2272 " not currently supported for this target");
2275 return parseDirectiveDS(IDVal, 2);
2277 return parseDirectiveDS(IDVal, 1);
2279 return parseDirectiveDS(IDVal, 8);
2282 return parseDirectiveDS(IDVal, 4);
2285 return parseDirectiveDS(IDVal, 12);
2287 return parseDirectivePrint(IDLoc);
2289 return parseDirectiveAddrsig();
2290 case DK_ADDRSIG_SYM:
2291 return parseDirectiveAddrsigSym();
2292 case DK_PSEUDO_PROBE:
2293 return parseDirectivePseudoProbe();
2294 case DK_LTO_DISCARD:
2295 return parseDirectiveLTODiscard();
2297 return parseDirectiveSymbolAttribute(MCSA_Memtag);
2300 return Error(IDLoc, "unknown directive");
2303 // __asm _emit or __asm __emit
2304 if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
2305 IDVal == "_EMIT" || IDVal == "__EMIT"))
2306 return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
2309 if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
2310 return parseDirectiveMSAlign(IDLoc, Info);
2312 if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
2313 Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
2314 if (checkForValidSection())
2317 return parseAndMatchAndEmitTargetInstruction(Info, IDVal, ID, IDLoc);
2320 bool AsmParser::parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,
2324 // Canonicalize the opcode to lower case.
2325 std::string OpcodeStr = IDVal.lower();
2326 ParseInstructionInfo IInfo(Info.AsmRewrites);
2327 bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
2328 Info.ParsedOperands);
2329 Info.ParseError = ParseHadError;
2331 // Dump the parsed representation, if requested.
2332 if (getShowParsedOperands()) {
2333 SmallString<256> Str;
2334 raw_svector_ostream OS(Str);
2335 OS << "parsed instruction: [";
2336 for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
2339 Info.ParsedOperands[i]->print(OS);
2343 printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
2346 // Fail even if ParseInstruction erroneously returns false.
2347 if (hasPendingError() || ParseHadError)
2350 // If we are generating dwarf for the current section then generate a .loc
2351 // directive for the instruction.
2352 if (!ParseHadError && enabledGenDwarfForAssembly() &&
2353 getContext().getGenDwarfSectionSyms().count(
2354 getStreamer().getCurrentSectionOnly())) {
2356 if (ActiveMacros.empty())
2357 Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
2359 Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
2360 ActiveMacros.front()->ExitBuffer);
2362 // If we previously parsed a cpp hash file line comment then make sure the
2363 // current Dwarf File is for the CppHashFilename if not then emit the
2364 // Dwarf File table for it and adjust the line number for the .loc.
2365 if (!CppHashInfo.Filename.empty()) {
2366 unsigned FileNumber = getStreamer().emitDwarfFileDirective(
2367 0, StringRef(), CppHashInfo.Filename);
2368 getContext().setGenDwarfFileNumber(FileNumber);
2370 unsigned CppHashLocLineNo =
2371 SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
2372 Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
2375 getStreamer().emitDwarfLocDirective(
2376 getContext().getGenDwarfFileNumber(), Line, 0,
2377 DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
2381 // If parsing succeeded, match the instruction.
2382 if (!ParseHadError) {
2384 if (getTargetParser().MatchAndEmitInstruction(
2385 IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
2386 getTargetParser().isParsingMSInlineAsm()))
2392 // Parse and erase curly braces marking block start/end
2394 AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2395 // Identify curly brace marking block start/end
2396 if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
2399 SMLoc StartLoc = Lexer.getLoc();
2400 Lex(); // Eat the brace
2401 if (Lexer.is(AsmToken::EndOfStatement))
2402 Lex(); // Eat EndOfStatement following the brace
2404 // Erase the block start/end brace from the output asm string
2405 AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
2406 StartLoc.getPointer());
2410 /// parseCppHashLineFilenameComment as this:
2411 /// ::= # number "filename"
2412 bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) {
2413 Lex(); // Eat the hash token.
2414 // Lexer only ever emits HashDirective if it fully formed if it's
2415 // done the checking already so this is an internal error.
2416 assert(getTok().is(AsmToken::Integer) &&
2417 "Lexing Cpp line comment: Expected Integer");
2418 int64_t LineNumber = getTok().getIntVal();
2420 assert(getTok().is(AsmToken::String) &&
2421 "Lexing Cpp line comment: Expected String");
2422 StringRef Filename = getTok().getString();
2428 // Get rid of the enclosing quotes.
2429 Filename = Filename.substr(1, Filename.size() - 2);
2431 // Save the SMLoc, Filename and LineNumber for later use by diagnostics
2432 // and possibly DWARF file info.
2433 CppHashInfo.Loc = L;
2434 CppHashInfo.Filename = Filename;
2435 CppHashInfo.LineNumber = LineNumber;
2436 CppHashInfo.Buf = CurBuffer;
2437 if (FirstCppHashFilename.empty())
2438 FirstCppHashFilename = Filename;
2442 /// will use the last parsed cpp hash line filename comment
2443 /// for the Filename and LineNo if any in the diagnostic.
2444 void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
2445 auto *Parser = static_cast<AsmParser *>(Context);
2446 raw_ostream &OS = errs();
2448 const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
2449 SMLoc DiagLoc = Diag.getLoc();
2450 unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
2451 unsigned CppHashBuf =
2452 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2454 // Like SourceMgr::printMessage() we need to print the include stack if any
2455 // before printing the message.
2456 unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
2457 if (!Parser->SavedDiagHandler && DiagCurBuffer &&
2458 DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
2459 SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
2460 DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
2463 // If we have not parsed a cpp hash line filename comment or the source
2464 // manager changed or buffer changed (like in a nested include) then just
2465 // print the normal diagnostic using its Filename and LineNo.
2466 if (!Parser->CppHashInfo.LineNumber || DiagBuf != CppHashBuf) {
2467 if (Parser->SavedDiagHandler)
2468 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2470 Parser->getContext().diagnose(Diag);
2474 // Use the CppHashFilename and calculate a line number based on the
2475 // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
2476 // for the diagnostic.
2477 const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
2479 int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
2480 int CppHashLocLineNo =
2481 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2483 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2485 SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
2486 Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
2487 Diag.getLineContents(), Diag.getRanges());
2489 if (Parser->SavedDiagHandler)
2490 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2492 Parser->getContext().diagnose(NewDiag);
2495 // FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The
2496 // difference being that that function accepts '@' as part of identifiers and
2497 // we can't do that. AsmLexer.cpp should probably be changed to handle
2498 // '@' as a special case when needed.
2499 static bool isIdentifierChar(char c) {
2500 return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||
2504 bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2505 ArrayRef<MCAsmMacroParameter> Parameters,
2506 ArrayRef<MCAsmMacroArgument> A,
2507 bool EnableAtPseudoVariable, SMLoc L) {
2508 unsigned NParameters = Parameters.size();
2509 bool HasVararg = NParameters ? Parameters.back().Vararg : false;
2510 if ((!IsDarwin || NParameters != 0) && NParameters != A.size())
2511 return Error(L, "Wrong number of arguments");
2513 // A macro without parameters is handled differently on Darwin:
2514 // gas accepts no arguments and does no substitutions
2515 while (!Body.empty()) {
2516 // Scan for the next substitution.
2517 std::size_t End = Body.size(), Pos = 0;
2518 for (; Pos != End; ++Pos) {
2519 // Check for a substitution or escape.
2520 if (IsDarwin && !NParameters) {
2521 // This macro has no parameters, look for $0, $1, etc.
2522 if (Body[Pos] != '$' || Pos + 1 == End)
2525 char Next = Body[Pos + 1];
2526 if (Next == '$' || Next == 'n' ||
2527 isdigit(static_cast<unsigned char>(Next)))
2530 // This macro has parameters, look for \foo, \bar, etc.
2531 if (Body[Pos] == '\\' && Pos + 1 != End)
2537 OS << Body.slice(0, Pos);
2539 // Check if we reached the end.
2543 if (IsDarwin && !NParameters) {
2544 switch (Body[Pos + 1]) {
2550 // $n => number of arguments
2555 // $[0-9] => argument
2557 // Missing arguments are ignored.
2558 unsigned Index = Body[Pos + 1] - '0';
2559 if (Index >= A.size())
2562 // Otherwise substitute with the token values, with spaces eliminated.
2563 for (const AsmToken &Token : A[Index])
2564 OS << Token.getString();
2570 unsigned I = Pos + 1;
2572 // Check for the \@ pseudo-variable.
2573 if (EnableAtPseudoVariable && Body[I] == '@' && I + 1 != End)
2576 while (isIdentifierChar(Body[I]) && I + 1 != End)
2579 const char *Begin = Body.data() + Pos + 1;
2580 StringRef Argument(Begin, I - (Pos + 1));
2583 if (Argument == "@") {
2584 OS << NumOfMacroInstantiations;
2587 for (; Index < NParameters; ++Index)
2588 if (Parameters[Index].Name == Argument)
2591 if (Index == NParameters) {
2592 if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
2595 OS << '\\' << Argument;
2599 bool VarargParameter = HasVararg && Index == (NParameters - 1);
2600 for (const AsmToken &Token : A[Index])
2601 // For altmacro mode, you can write '%expr'.
2602 // The prefix '%' evaluates the expression 'expr'
2603 // and uses the result as a string (e.g. replace %(1+2) with the
2605 // Here, we identify the integer token which is the result of the
2606 // absolute expression evaluation and replace it with its string
2608 if (AltMacroMode && Token.getString().front() == '%' &&
2609 Token.is(AsmToken::Integer))
2610 // Emit an integer value to the buffer.
2611 OS << Token.getIntVal();
2612 // Only Token that was validated as a string and begins with '<'
2613 // is considered altMacroString!!!
2614 else if (AltMacroMode && Token.getString().front() == '<' &&
2615 Token.is(AsmToken::String)) {
2616 OS << angleBracketString(Token.getStringContents());
2618 // We expect no quotes around the string's contents when
2619 // parsing for varargs.
2620 else if (Token.isNot(AsmToken::String) || VarargParameter)
2621 OS << Token.getString();
2623 OS << Token.getStringContents();
2625 Pos += 1 + Argument.size();
2629 // Update the scan point.
2630 Body = Body.substr(Pos);
2636 static bool isOperator(AsmToken::TokenKind kind) {
2640 case AsmToken::Plus:
2641 case AsmToken::Minus:
2642 case AsmToken::Tilde:
2643 case AsmToken::Slash:
2644 case AsmToken::Star:
2646 case AsmToken::Equal:
2647 case AsmToken::EqualEqual:
2648 case AsmToken::Pipe:
2649 case AsmToken::PipePipe:
2650 case AsmToken::Caret:
2652 case AsmToken::AmpAmp:
2653 case AsmToken::Exclaim:
2654 case AsmToken::ExclaimEqual:
2655 case AsmToken::Less:
2656 case AsmToken::LessEqual:
2657 case AsmToken::LessLess:
2658 case AsmToken::LessGreater:
2659 case AsmToken::Greater:
2660 case AsmToken::GreaterEqual:
2661 case AsmToken::GreaterGreater:
2668 class AsmLexerSkipSpaceRAII {
2670 AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
2671 Lexer.setSkipSpace(SkipSpace);
2674 ~AsmLexerSkipSpaceRAII() {
2675 Lexer.setSkipSpace(true);
2682 } // end anonymous namespace
2684 bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
2687 if (Lexer.isNot(AsmToken::EndOfStatement)) {
2688 StringRef Str = parseStringToEndOfStatement();
2689 MA.emplace_back(AsmToken::String, Str);
2694 unsigned ParenLevel = 0;
2696 // Darwin doesn't use spaces to delmit arguments.
2697 AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
2703 if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
2704 return TokError("unexpected token in macro instantiation");
2706 if (ParenLevel == 0) {
2708 if (Lexer.is(AsmToken::Comma))
2711 if (Lexer.is(AsmToken::Space)) {
2713 Lexer.Lex(); // Eat spaces
2716 // Spaces can delimit parameters, but could also be part an expression.
2717 // If the token after a space is an operator, add the token and the next
2718 // one into this argument
2720 if (isOperator(Lexer.getKind())) {
2721 MA.push_back(getTok());
2724 // Whitespace after an operator can be ignored.
2725 if (Lexer.is(AsmToken::Space))
2735 // handleMacroEntry relies on not advancing the lexer here
2736 // to be able to fill in the remaining default parameter values
2737 if (Lexer.is(AsmToken::EndOfStatement))
2740 // Adjust the current parentheses level.
2741 if (Lexer.is(AsmToken::LParen))
2743 else if (Lexer.is(AsmToken::RParen) && ParenLevel)
2746 // Append the token to the current argument list.
2747 MA.push_back(getTok());
2751 if (ParenLevel != 0)
2752 return TokError("unbalanced parentheses in macro argument");
2756 // Parse the macro instantiation arguments.
2757 bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
2758 MCAsmMacroArguments &A) {
2759 const unsigned NParameters = M ? M->Parameters.size() : 0;
2760 bool NamedParametersFound = false;
2761 SmallVector<SMLoc, 4> FALocs;
2763 A.resize(NParameters);
2764 FALocs.resize(NParameters);
2766 // Parse two kinds of macro invocations:
2767 // - macros defined without any parameters accept an arbitrary number of them
2768 // - macros defined with parameters accept at most that many of them
2769 bool HasVararg = NParameters ? M->Parameters.back().Vararg : false;
2770 for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
2772 SMLoc IDLoc = Lexer.getLoc();
2773 MCAsmMacroParameter FA;
2775 if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
2776 if (parseIdentifier(FA.Name))
2777 return Error(IDLoc, "invalid argument identifier for formal argument");
2779 if (Lexer.isNot(AsmToken::Equal))
2780 return TokError("expected '=' after formal parameter identifier");
2784 NamedParametersFound = true;
2786 bool Vararg = HasVararg && Parameter == (NParameters - 1);
2788 if (NamedParametersFound && FA.Name.empty())
2789 return Error(IDLoc, "cannot mix positional and keyword arguments");
2791 SMLoc StrLoc = Lexer.getLoc();
2793 if (AltMacroMode && Lexer.is(AsmToken::Percent)) {
2794 const MCExpr *AbsoluteExp;
2798 if (parseExpression(AbsoluteExp, EndLoc))
2800 if (!AbsoluteExp->evaluateAsAbsolute(Value,
2801 getStreamer().getAssemblerPtr()))
2802 return Error(StrLoc, "expected absolute expression");
2803 const char *StrChar = StrLoc.getPointer();
2804 const char *EndChar = EndLoc.getPointer();
2805 AsmToken newToken(AsmToken::Integer,
2806 StringRef(StrChar, EndChar - StrChar), Value);
2807 FA.Value.push_back(newToken);
2808 } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
2809 isAngleBracketString(StrLoc, EndLoc)) {
2810 const char *StrChar = StrLoc.getPointer();
2811 const char *EndChar = EndLoc.getPointer();
2812 jumpToLoc(EndLoc, CurBuffer);
2813 /// Eat from '<' to '>'
2815 AsmToken newToken(AsmToken::String,
2816 StringRef(StrChar, EndChar - StrChar));
2817 FA.Value.push_back(newToken);
2818 } else if(parseMacroArgument(FA.Value, Vararg))
2821 unsigned PI = Parameter;
2822 if (!FA.Name.empty()) {
2824 for (FAI = 0; FAI < NParameters; ++FAI)
2825 if (M->Parameters[FAI].Name == FA.Name)
2828 if (FAI >= NParameters) {
2829 assert(M && "expected macro to be defined");
2830 return Error(IDLoc, "parameter named '" + FA.Name +
2831 "' does not exist for macro '" + M->Name + "'");
2836 if (!FA.Value.empty()) {
2841 if (FALocs.size() <= PI)
2842 FALocs.resize(PI + 1);
2844 FALocs[PI] = Lexer.getLoc();
2847 // At the end of the statement, fill in remaining arguments that have
2848 // default values. If there aren't any, then the next argument is
2849 // required but missing
2850 if (Lexer.is(AsmToken::EndOfStatement)) {
2851 bool Failure = false;
2852 for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
2853 if (A[FAI].empty()) {
2854 if (M->Parameters[FAI].Required) {
2855 Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
2856 "missing value for required parameter "
2857 "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
2861 if (!M->Parameters[FAI].Value.empty())
2862 A[FAI] = M->Parameters[FAI].Value;
2868 if (Lexer.is(AsmToken::Comma))
2872 return TokError("too many positional arguments");
2875 bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
2876 // Arbitrarily limit macro nesting depth (default matches 'as'). We can
2877 // eliminate this, although we should protect against infinite loops.
2878 unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
2879 if (ActiveMacros.size() == MaxNestingDepth) {
2880 std::ostringstream MaxNestingDepthError;
2881 MaxNestingDepthError << "macros cannot be nested more than "
2882 << MaxNestingDepth << " levels deep."
2883 << " Use -asm-macro-max-nesting-depth to increase "
2885 return TokError(MaxNestingDepthError.str());
2888 MCAsmMacroArguments A;
2889 if (parseMacroArguments(M, A))
2892 // Macro instantiation is lexical, unfortunately. We construct a new buffer
2893 // to hold the macro body with substitutions.
2894 SmallString<256> Buf;
2895 StringRef Body = M->Body;
2896 raw_svector_ostream OS(Buf);
2898 if (expandMacro(OS, Body, M->Parameters, A, true, getTok().getLoc()))
2901 // We include the .endmacro in the buffer as our cue to exit the macro
2903 OS << ".endmacro\n";
2905 std::unique_ptr<MemoryBuffer> Instantiation =
2906 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
2908 // Create the macro instantiation object and add to the current macro
2909 // instantiation stack.
2910 MacroInstantiation *MI = new MacroInstantiation{
2911 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2912 ActiveMacros.push_back(MI);
2914 ++NumOfMacroInstantiations;
2916 // Jump to the macro instantiation and prime the lexer.
2917 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
2918 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
2924 void AsmParser::handleMacroExit() {
2925 // Jump to the EndOfStatement we should return to, and consume it.
2926 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
2929 // Pop the instantiation entry.
2930 delete ActiveMacros.back();
2931 ActiveMacros.pop_back();
2934 bool AsmParser::parseAssignment(StringRef Name, AssignmentKind Kind) {
2936 const MCExpr *Value;
2937 SMLoc ExprLoc = getTok().getLoc();
2939 Kind == AssignmentKind::Set || Kind == AssignmentKind::Equal;
2940 if (MCParserUtils::parseAssignmentExpression(Name, AllowRedef, *this, Sym,
2945 // In the case where we parse an expression starting with a '.', we will
2946 // not generate an error, nor will we create a symbol. In this case we
2947 // should just return out.
2951 if (discardLTOSymbol(Name))
2954 // Do the assignment.
2956 case AssignmentKind::Equal:
2957 Out.emitAssignment(Sym, Value);
2959 case AssignmentKind::Set:
2960 case AssignmentKind::Equiv:
2961 Out.emitAssignment(Sym, Value);
2962 Out.emitSymbolAttribute(Sym, MCSA_NoDeadStrip);
2964 case AssignmentKind::LTOSetConditional:
2965 if (Value->getKind() != MCExpr::SymbolRef)
2966 return Error(ExprLoc, "expected identifier");
2968 Out.emitConditionalAssignment(Sym, Value);
2975 /// parseIdentifier:
2978 bool AsmParser::parseIdentifier(StringRef &Res) {
2979 // The assembler has relaxed rules for accepting identifiers, in particular we
2980 // allow things like '.globl $foo' and '.def @feat.00', which would normally be
2981 // separate tokens. At this level, we have already lexed so we cannot (currently)
2982 // handle this as a context dependent token, instead we detect adjacent tokens
2983 // and return the combined identifier.
2984 if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
2985 SMLoc PrefixLoc = getLexer().getLoc();
2987 // Consume the prefix character, and check for a following identifier.
2990 Lexer.peekTokens(Buf, false);
2992 if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer))
2995 // We have a '$' or '@' followed by an identifier or integer token, make
2996 // sure they are adjacent.
2997 if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())
3001 Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
3002 // Construct the joined identifier and consume the token.
3003 Res = StringRef(PrefixLoc.getPointer(), getTok().getString().size() + 1);
3004 Lex(); // Parser Lex to maintain invariants.
3008 if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
3011 Res = getTok().getIdentifier();
3013 Lex(); // Consume the identifier token.
3018 /// parseDirectiveSet:
3019 /// ::= .equ identifier ',' expression
3020 /// ::= .equiv identifier ',' expression
3021 /// ::= .set identifier ',' expression
3022 /// ::= .lto_set_conditional identifier ',' expression
3023 bool AsmParser::parseDirectiveSet(StringRef IDVal, AssignmentKind Kind) {
3025 if (check(parseIdentifier(Name), "expected identifier") || parseComma() ||
3026 parseAssignment(Name, Kind))
3031 bool AsmParser::parseEscapedString(std::string &Data) {
3032 if (check(getTok().isNot(AsmToken::String), "expected string"))
3036 StringRef Str = getTok().getStringContents();
3037 for (unsigned i = 0, e = Str.size(); i != e; ++i) {
3038 if (Str[i] != '\\') {
3043 // Recognize escaped characters. Note that this escape semantics currently
3044 // loosely follows Darwin 'as'.
3047 return TokError("unexpected backslash at end of string");
3049 // Recognize hex sequences similarly to GNU 'as'.
3050 if (Str[i] == 'x' || Str[i] == 'X') {
3051 size_t length = Str.size();
3052 if (i + 1 >= length || !isHexDigit(Str[i + 1]))
3053 return TokError("invalid hexadecimal escape sequence");
3055 // Consume hex characters. GNU 'as' reads all hexadecimal characters and
3056 // then truncates to the lower 16 bits. Seems reasonable.
3058 while (i + 1 < length && isHexDigit(Str[i + 1]))
3059 Value = Value * 16 + hexDigitValue(Str[++i]);
3061 Data += (unsigned char)(Value & 0xFF);
3065 // Recognize octal sequences.
3066 if ((unsigned)(Str[i] - '0') <= 7) {
3067 // Consume up to three octal characters.
3068 unsigned Value = Str[i] - '0';
3070 if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
3072 Value = Value * 8 + (Str[i] - '0');
3074 if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
3076 Value = Value * 8 + (Str[i] - '0');
3081 return TokError("invalid octal escape sequence (out of range)");
3083 Data += (unsigned char)Value;
3087 // Otherwise recognize individual escapes.
3090 // Just reject invalid escape sequences for now.
3091 return TokError("invalid escape sequence (unrecognized character)");
3093 case 'b': Data += '\b'; break;
3094 case 'f': Data += '\f'; break;
3095 case 'n': Data += '\n'; break;
3096 case 'r': Data += '\r'; break;
3097 case 't': Data += '\t'; break;
3098 case '"': Data += '"'; break;
3099 case '\\': Data += '\\'; break;
3107 bool AsmParser::parseAngleBracketString(std::string &Data) {
3108 SMLoc EndLoc, StartLoc = getTok().getLoc();
3109 if (isAngleBracketString(StartLoc, EndLoc)) {
3110 const char *StartChar = StartLoc.getPointer() + 1;
3111 const char *EndChar = EndLoc.getPointer() - 1;
3112 jumpToLoc(EndLoc, CurBuffer);
3113 /// Eat from '<' to '>'
3116 Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
3122 /// parseDirectiveAscii:
3123 // ::= .ascii [ "string"+ ( , "string"+ )* ]
3124 /// ::= ( .asciz | .string ) [ "string" ( , "string" )* ]
3125 bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
3126 auto parseOp = [&]() -> bool {
3128 if (checkForValidSection())
3130 // Only support spaces as separators for .ascii directive for now. See the
3131 // discusssion at https://reviews.llvm.org/D91460 for more details.
3133 if (parseEscapedString(Data))
3135 getStreamer().emitBytes(Data);
3136 } while (!ZeroTerminated && getTok().is(AsmToken::String));
3138 getStreamer().emitBytes(StringRef("\0", 1));
3142 return parseMany(parseOp);
3145 /// parseDirectiveReloc
3146 /// ::= .reloc expression , identifier [ , expression ]
3147 bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
3148 const MCExpr *Offset;
3149 const MCExpr *Expr = nullptr;
3150 SMLoc OffsetLoc = Lexer.getTok().getLoc();
3152 if (parseExpression(Offset))
3155 check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
3158 SMLoc NameLoc = Lexer.getTok().getLoc();
3159 StringRef Name = Lexer.getTok().getIdentifier();
3162 if (Lexer.is(AsmToken::Comma)) {
3164 SMLoc ExprLoc = Lexer.getLoc();
3165 if (parseExpression(Expr))
3169 if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr))
3170 return Error(ExprLoc, "expression must be relocatable");
3176 const MCTargetAsmParser &MCT = getTargetParser();
3177 const MCSubtargetInfo &STI = MCT.getSTI();
3178 if (std::optional<std::pair<bool, std::string>> Err =
3179 getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc,
3181 return Error(Err->first ? NameLoc : OffsetLoc, Err->second);
3186 /// parseDirectiveValue
3187 /// ::= (.byte | .short | ... ) [ expression (, expression)* ]
3188 bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
3189 auto parseOp = [&]() -> bool {
3190 const MCExpr *Value;
3191 SMLoc ExprLoc = getLexer().getLoc();
3192 if (checkForValidSection() || parseExpression(Value))
3194 // Special case constant expressions to match code generator.
3195 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3196 assert(Size <= 8 && "Invalid size");
3197 uint64_t IntValue = MCE->getValue();
3198 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
3199 return Error(ExprLoc, "out of range literal value");
3200 getStreamer().emitIntValue(IntValue, Size);
3202 getStreamer().emitValue(Value, Size, ExprLoc);
3206 return parseMany(parseOp);
3209 static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {
3210 if (Asm.getTok().isNot(AsmToken::Integer) &&
3211 Asm.getTok().isNot(AsmToken::BigNum))
3212 return Asm.TokError("unknown token in expression");
3213 SMLoc ExprLoc = Asm.getTok().getLoc();
3214 APInt IntValue = Asm.getTok().getAPIntVal();
3216 if (!IntValue.isIntN(128))
3217 return Asm.Error(ExprLoc, "out of range literal value");
3218 if (!IntValue.isIntN(64)) {
3219 hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
3220 lo = IntValue.getLoBits(64).getZExtValue();
3223 lo = IntValue.getZExtValue();
3228 /// ParseDirectiveOctaValue
3229 /// ::= .octa [ hexconstant (, hexconstant)* ]
3231 bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
3232 auto parseOp = [&]() -> bool {
3233 if (checkForValidSection())
3236 if (parseHexOcta(*this, hi, lo))
3238 if (MAI.isLittleEndian()) {
3239 getStreamer().emitInt64(lo);
3240 getStreamer().emitInt64(hi);
3242 getStreamer().emitInt64(hi);
3243 getStreamer().emitInt64(lo);
3248 return parseMany(parseOp);
3251 bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
3252 // We don't truly support arithmetic on floating point expressions, so we
3253 // have to manually parse unary prefixes.
3255 if (getLexer().is(AsmToken::Minus)) {
3258 } else if (getLexer().is(AsmToken::Plus))
3261 if (Lexer.is(AsmToken::Error))
3262 return TokError(Lexer.getErr());
3263 if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
3264 Lexer.isNot(AsmToken::Identifier))
3265 return TokError("unexpected token in directive");
3267 // Convert to an APFloat.
3268 APFloat Value(Semantics);
3269 StringRef IDVal = getTok().getString();
3270 if (getLexer().is(AsmToken::Identifier)) {
3271 if (!IDVal.compare_insensitive("infinity") ||
3272 !IDVal.compare_insensitive("inf"))
3273 Value = APFloat::getInf(Semantics);
3274 else if (!IDVal.compare_insensitive("nan"))
3275 Value = APFloat::getNaN(Semantics, false, ~0);
3277 return TokError("invalid floating point literal");
3278 } else if (errorToBool(
3279 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3281 return TokError("invalid floating point literal");
3285 // Consume the numeric token.
3288 Res = Value.bitcastToAPInt();
3293 /// parseDirectiveRealValue
3294 /// ::= (.single | .double) [ expression (, expression)* ]
3295 bool AsmParser::parseDirectiveRealValue(StringRef IDVal,
3296 const fltSemantics &Semantics) {
3297 auto parseOp = [&]() -> bool {
3299 if (checkForValidSection() || parseRealValue(Semantics, AsInt))
3301 getStreamer().emitIntValue(AsInt.getLimitedValue(),
3302 AsInt.getBitWidth() / 8);
3306 return parseMany(parseOp);
3309 /// parseDirectiveZero
3310 /// ::= .zero expression
3311 bool AsmParser::parseDirectiveZero() {
3312 SMLoc NumBytesLoc = Lexer.getLoc();
3313 const MCExpr *NumBytes;
3314 if (checkForValidSection() || parseExpression(NumBytes))
3318 if (getLexer().is(AsmToken::Comma)) {
3320 if (parseAbsoluteExpression(Val))
3326 getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);
3331 /// parseDirectiveFill
3332 /// ::= .fill expression [ , expression [ , expression ] ]
3333 bool AsmParser::parseDirectiveFill() {
3334 SMLoc NumValuesLoc = Lexer.getLoc();
3335 const MCExpr *NumValues;
3336 if (checkForValidSection() || parseExpression(NumValues))
3339 int64_t FillSize = 1;
3340 int64_t FillExpr = 0;
3342 SMLoc SizeLoc, ExprLoc;
3344 if (parseOptionalToken(AsmToken::Comma)) {
3345 SizeLoc = getTok().getLoc();
3346 if (parseAbsoluteExpression(FillSize))
3348 if (parseOptionalToken(AsmToken::Comma)) {
3349 ExprLoc = getTok().getLoc();
3350 if (parseAbsoluteExpression(FillExpr))
3358 Warning(SizeLoc, "'.fill' directive with negative size has no effect");
3362 Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
3366 if (!isUInt<32>(FillExpr) && FillSize > 4)
3367 Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
3369 getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);
3374 /// parseDirectiveOrg
3375 /// ::= .org expression [ , expression ]
3376 bool AsmParser::parseDirectiveOrg() {
3377 const MCExpr *Offset;
3378 SMLoc OffsetLoc = Lexer.getLoc();
3379 if (checkForValidSection() || parseExpression(Offset))
3382 // Parse optional fill expression.
3383 int64_t FillExpr = 0;
3384 if (parseOptionalToken(AsmToken::Comma))
3385 if (parseAbsoluteExpression(FillExpr))
3390 getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
3394 /// parseDirectiveAlign
3395 /// ::= {.align, ...} expression [ , expression [ , expression ]]
3396 bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
3397 SMLoc AlignmentLoc = getLexer().getLoc();
3400 bool HasFillExpr = false;
3401 int64_t FillExpr = 0;
3402 int64_t MaxBytesToFill = 0;
3405 auto parseAlign = [&]() -> bool {
3406 if (parseAbsoluteExpression(Alignment))
3408 if (parseOptionalToken(AsmToken::Comma)) {
3409 // The fill expression can be omitted while specifying a maximum number of
3410 // alignment bytes, e.g:
3412 if (getTok().isNot(AsmToken::Comma)) {
3414 if (parseTokenLoc(FillExprLoc) || parseAbsoluteExpression(FillExpr))
3417 if (parseOptionalToken(AsmToken::Comma))
3418 if (parseTokenLoc(MaxBytesLoc) ||
3419 parseAbsoluteExpression(MaxBytesToFill))
3425 if (checkForValidSection())
3427 // Ignore empty '.p2align' directives for GNU-as compatibility
3428 if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
3429 Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
3435 // Always emit an alignment here even if we thrown an error.
3436 bool ReturnVal = false;
3438 // Compute alignment in bytes.
3440 // FIXME: Diagnose overflow.
3441 if (Alignment >= 32) {
3442 ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
3446 Alignment = 1ULL << Alignment;
3448 // Reject alignments that aren't either a power of two or zero,
3449 // for gas compatibility. Alignment of zero is silently rounded
3453 else if (!isPowerOf2_64(Alignment)) {
3454 ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
3455 Alignment = llvm::bit_floor<uint64_t>(Alignment);
3457 if (!isUInt<32>(Alignment)) {
3458 ReturnVal |= Error(AlignmentLoc, "alignment must be smaller than 2**32");
3459 Alignment = 1u << 31;
3463 if (HasFillExpr && FillExpr != 0) {
3464 MCSection *Sec = getStreamer().getCurrentSectionOnly();
3465 if (Sec && Sec->isVirtualSection()) {
3467 Warning(FillExprLoc, "ignoring non-zero fill value in " +
3468 Sec->getVirtualSectionKind() + " section '" +
3469 Sec->getName() + "'");
3474 // Diagnose non-sensical max bytes to align.
3475 if (MaxBytesLoc.isValid()) {
3476 if (MaxBytesToFill < 1) {
3477 ReturnVal |= Error(MaxBytesLoc,
3478 "alignment directive can never be satisfied in this "
3479 "many bytes, ignoring maximum bytes expression");
3483 if (MaxBytesToFill >= Alignment) {
3484 Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
3490 // Check whether we should use optimal code alignment for this .align
3492 const MCSection *Section = getStreamer().getCurrentSectionOnly();
3493 assert(Section && "must have section to emit alignment");
3494 bool useCodeAlign = Section->useCodeAlign();
3495 if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
3496 ValueSize == 1 && useCodeAlign) {
3497 getStreamer().emitCodeAlignment(
3498 Align(Alignment), &getTargetParser().getSTI(), MaxBytesToFill);
3500 // FIXME: Target specific behavior about how the "extra" bytes are filled.
3501 getStreamer().emitValueToAlignment(Align(Alignment), FillExpr, ValueSize,
3508 /// parseDirectiveFile
3509 /// ::= .file filename
3510 /// ::= .file number [directory] filename [md5 checksum] [source source-text]
3511 bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
3512 // FIXME: I'm not sure what this is.
3513 int64_t FileNumber = -1;
3514 if (getLexer().is(AsmToken::Integer)) {
3515 FileNumber = getTok().getIntVal();
3519 return TokError("negative file number");
3524 // Usually the directory and filename together, otherwise just the directory.
3525 // Allow the strings to have escaped octal character sequence.
3526 if (parseEscapedString(Path))
3529 StringRef Directory;
3531 std::string FilenameData;
3532 if (getLexer().is(AsmToken::String)) {
3533 if (check(FileNumber == -1,
3534 "explicit path specified, but no file number") ||
3535 parseEscapedString(FilenameData))
3537 Filename = FilenameData;
3543 uint64_t MD5Hi, MD5Lo;
3544 bool HasMD5 = false;
3546 std::optional<StringRef> Source;
3547 bool HasSource = false;
3548 std::string SourceString;
3550 while (!parseOptionalToken(AsmToken::EndOfStatement)) {
3552 if (check(getTok().isNot(AsmToken::Identifier),
3553 "unexpected token in '.file' directive") ||
3554 parseIdentifier(Keyword))
3556 if (Keyword == "md5") {
3558 if (check(FileNumber == -1,
3559 "MD5 checksum specified, but no file number") ||
3560 parseHexOcta(*this, MD5Hi, MD5Lo))
3562 } else if (Keyword == "source") {
3564 if (check(FileNumber == -1,
3565 "source specified, but no file number") ||
3566 check(getTok().isNot(AsmToken::String),
3567 "unexpected token in '.file' directive") ||
3568 parseEscapedString(SourceString))
3571 return TokError("unexpected token in '.file' directive");
3575 if (FileNumber == -1) {
3576 // Ignore the directive if there is no number and the target doesn't support
3577 // numberless .file directives. This allows some portability of assembler
3578 // between different object file formats.
3579 if (getContext().getAsmInfo()->hasSingleParameterDotFile())
3580 getStreamer().emitFileDirective(Filename);
3582 // In case there is a -g option as well as debug info from directive .file,
3583 // we turn off the -g option, directly use the existing debug info instead.
3584 // Throw away any implicit file table for the assembler source.
3585 if (Ctx.getGenDwarfForAssembly()) {
3586 Ctx.getMCDwarfLineTable(0).resetFileTable();
3587 Ctx.setGenDwarfForAssembly(false);
3590 std::optional<MD5::MD5Result> CKMem;
3593 for (unsigned i = 0; i != 8; ++i) {
3594 Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
3595 Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
3600 char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
3601 memcpy(SourceBuf, SourceString.data(), SourceString.size());
3602 Source = StringRef(SourceBuf, SourceString.size());
3604 if (FileNumber == 0) {
3605 // Upgrade to Version 5 for assembly actions like clang -c a.s.
3606 if (Ctx.getDwarfVersion() < 5)
3607 Ctx.setDwarfVersion(5);
3608 getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
3610 Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
3611 FileNumber, Directory, Filename, CKMem, Source);
3613 return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
3615 // Alert the user if there are some .file directives with MD5 and some not.
3616 // But only do that once.
3617 if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
3618 ReportedInconsistentMD5 = true;
3619 return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
3626 /// parseDirectiveLine
3627 /// ::= .line [number]
3628 bool AsmParser::parseDirectiveLine() {
3630 if (getLexer().is(AsmToken::Integer)) {
3631 if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
3634 // FIXME: Do something with the .line.
3639 /// parseDirectiveLoc
3640 /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
3641 /// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
3642 /// The first number is a file number, must have been previously assigned with
3643 /// a .file directive, the second number is the line number and optionally the
3644 /// third number is a column position (zero if not specified). The remaining
3645 /// optional items are .loc sub-directives.
3646 bool AsmParser::parseDirectiveLoc() {
3647 int64_t FileNumber = 0, LineNumber = 0;
3648 SMLoc Loc = getTok().getLoc();
3649 if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
3650 check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
3651 "file number less than one in '.loc' directive") ||
3652 check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
3653 "unassigned file number in '.loc' directive"))
3657 if (getLexer().is(AsmToken::Integer)) {
3658 LineNumber = getTok().getIntVal();
3660 return TokError("line number less than zero in '.loc' directive");
3664 int64_t ColumnPos = 0;
3665 if (getLexer().is(AsmToken::Integer)) {
3666 ColumnPos = getTok().getIntVal();
3668 return TokError("column position less than zero in '.loc' directive");
3672 auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
3673 unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
3675 int64_t Discriminator = 0;
3677 auto parseLocOp = [&]() -> bool {
3679 SMLoc Loc = getTok().getLoc();
3680 if (parseIdentifier(Name))
3681 return TokError("unexpected token in '.loc' directive");
3683 if (Name == "basic_block")
3684 Flags |= DWARF2_FLAG_BASIC_BLOCK;
3685 else if (Name == "prologue_end")
3686 Flags |= DWARF2_FLAG_PROLOGUE_END;
3687 else if (Name == "epilogue_begin")
3688 Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
3689 else if (Name == "is_stmt") {
3690 Loc = getTok().getLoc();
3691 const MCExpr *Value;
3692 if (parseExpression(Value))
3694 // The expression must be the constant 0 or 1.
3695 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3696 int Value = MCE->getValue();
3698 Flags &= ~DWARF2_FLAG_IS_STMT;
3699 else if (Value == 1)
3700 Flags |= DWARF2_FLAG_IS_STMT;
3702 return Error(Loc, "is_stmt value not 0 or 1");
3704 return Error(Loc, "is_stmt value not the constant value of 0 or 1");
3706 } else if (Name == "isa") {
3707 Loc = getTok().getLoc();
3708 const MCExpr *Value;
3709 if (parseExpression(Value))
3711 // The expression must be a constant greater or equal to 0.
3712 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3713 int Value = MCE->getValue();
3715 return Error(Loc, "isa number less than zero");
3718 return Error(Loc, "isa number not a constant value");
3720 } else if (Name == "discriminator") {
3721 if (parseAbsoluteExpression(Discriminator))
3724 return Error(Loc, "unknown sub-directive in '.loc' directive");
3729 if (parseMany(parseLocOp, false /*hasComma*/))
3732 getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
3733 Isa, Discriminator, StringRef());
3738 /// parseDirectiveStabs
3739 /// ::= .stabs string, number, number, number
3740 bool AsmParser::parseDirectiveStabs() {
3741 return TokError("unsupported directive '.stabs'");
3744 /// parseDirectiveCVFile
3745 /// ::= .cv_file number filename [checksum] [checksumkind]
3746 bool AsmParser::parseDirectiveCVFile() {
3747 SMLoc FileNumberLoc = getTok().getLoc();
3749 std::string Filename;
3750 std::string Checksum;
3751 int64_t ChecksumKind = 0;
3753 if (parseIntToken(FileNumber,
3754 "expected file number in '.cv_file' directive") ||
3755 check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
3756 check(getTok().isNot(AsmToken::String),
3757 "unexpected token in '.cv_file' directive") ||
3758 parseEscapedString(Filename))
3760 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
3761 if (check(getTok().isNot(AsmToken::String),
3762 "unexpected token in '.cv_file' directive") ||
3763 parseEscapedString(Checksum) ||
3764 parseIntToken(ChecksumKind,
3765 "expected checksum kind in '.cv_file' directive") ||
3770 Checksum = fromHex(Checksum);
3771 void *CKMem = Ctx.allocate(Checksum.size(), 1);
3772 memcpy(CKMem, Checksum.data(), Checksum.size());
3773 ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
3776 if (!getStreamer().emitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
3777 static_cast<uint8_t>(ChecksumKind)))
3778 return Error(FileNumberLoc, "file number already allocated");
3783 bool AsmParser::parseCVFunctionId(int64_t &FunctionId,
3784 StringRef DirectiveName) {
3786 return parseTokenLoc(Loc) ||
3787 parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
3789 check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
3790 "expected function id within range [0, UINT_MAX)");
3793 bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
3795 return parseTokenLoc(Loc) ||
3796 parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
3798 check(FileNumber < 1, Loc, "file number less than one in '" +
3799 DirectiveName + "' directive") ||
3800 check(!getCVContext().isValidFileNumber(FileNumber), Loc,
3801 "unassigned file number in '" + DirectiveName + "' directive");
3804 /// parseDirectiveCVFuncId
3805 /// ::= .cv_func_id FunctionId
3807 /// Introduces a function ID that can be used with .cv_loc.
3808 bool AsmParser::parseDirectiveCVFuncId() {
3809 SMLoc FunctionIdLoc = getTok().getLoc();
3812 if (parseCVFunctionId(FunctionId, ".cv_func_id") || parseEOL())
3815 if (!getStreamer().emitCVFuncIdDirective(FunctionId))
3816 return Error(FunctionIdLoc, "function id already allocated");
3821 /// parseDirectiveCVInlineSiteId
3822 /// ::= .cv_inline_site_id FunctionId
3824 /// "inlined_at" IAFile IALine [IACol]
3826 /// Introduces a function ID that can be used with .cv_loc. Includes "inlined
3827 /// at" source location information for use in the line table of the caller,
3828 /// whether the caller is a real function or another inlined call site.
3829 bool AsmParser::parseDirectiveCVInlineSiteId() {
3830 SMLoc FunctionIdLoc = getTok().getLoc();
3838 if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
3842 if (check((getLexer().isNot(AsmToken::Identifier) ||
3843 getTok().getIdentifier() != "within"),
3844 "expected 'within' identifier in '.cv_inline_site_id' directive"))
3849 if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
3853 if (check((getLexer().isNot(AsmToken::Identifier) ||
3854 getTok().getIdentifier() != "inlined_at"),
3855 "expected 'inlined_at' identifier in '.cv_inline_site_id' "
3861 if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
3862 parseIntToken(IALine, "expected line number after 'inlined_at'"))
3866 if (getLexer().is(AsmToken::Integer)) {
3867 IACol = getTok().getIntVal();
3874 if (!getStreamer().emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
3875 IALine, IACol, FunctionIdLoc))
3876 return Error(FunctionIdLoc, "function id already allocated");
3881 /// parseDirectiveCVLoc
3882 /// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
3884 /// The first number is a file number, must have been previously assigned with
3885 /// a .file directive, the second number is the line number and optionally the
3886 /// third number is a column position (zero if not specified). The remaining
3887 /// optional items are .loc sub-directives.
3888 bool AsmParser::parseDirectiveCVLoc() {
3889 SMLoc DirectiveLoc = getTok().getLoc();
3890 int64_t FunctionId, FileNumber;
3891 if (parseCVFunctionId(FunctionId, ".cv_loc") ||
3892 parseCVFileId(FileNumber, ".cv_loc"))
3895 int64_t LineNumber = 0;
3896 if (getLexer().is(AsmToken::Integer)) {
3897 LineNumber = getTok().getIntVal();
3899 return TokError("line number less than zero in '.cv_loc' directive");
3903 int64_t ColumnPos = 0;
3904 if (getLexer().is(AsmToken::Integer)) {
3905 ColumnPos = getTok().getIntVal();
3907 return TokError("column position less than zero in '.cv_loc' directive");
3911 bool PrologueEnd = false;
3912 uint64_t IsStmt = 0;
3914 auto parseOp = [&]() -> bool {
3916 SMLoc Loc = getTok().getLoc();
3917 if (parseIdentifier(Name))
3918 return TokError("unexpected token in '.cv_loc' directive");
3919 if (Name == "prologue_end")
3921 else if (Name == "is_stmt") {
3922 Loc = getTok().getLoc();
3923 const MCExpr *Value;
3924 if (parseExpression(Value))
3926 // The expression must be the constant 0 or 1.
3928 if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
3929 IsStmt = MCE->getValue();
3932 return Error(Loc, "is_stmt value not 0 or 1");
3934 return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
3939 if (parseMany(parseOp, false /*hasComma*/))
3942 getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
3943 ColumnPos, PrologueEnd, IsStmt, StringRef(),
3948 /// parseDirectiveCVLinetable
3949 /// ::= .cv_linetable FunctionId, FnStart, FnEnd
3950 bool AsmParser::parseDirectiveCVLinetable() {
3952 StringRef FnStartName, FnEndName;
3953 SMLoc Loc = getTok().getLoc();
3954 if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() ||
3955 parseTokenLoc(Loc) ||
3956 check(parseIdentifier(FnStartName), Loc,
3957 "expected identifier in directive") ||
3958 parseComma() || parseTokenLoc(Loc) ||
3959 check(parseIdentifier(FnEndName), Loc,
3960 "expected identifier in directive"))
3963 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
3964 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
3966 getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
3970 /// parseDirectiveCVInlineLinetable
3971 /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
3972 bool AsmParser::parseDirectiveCVInlineLinetable() {
3973 int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
3974 StringRef FnStartName, FnEndName;
3975 SMLoc Loc = getTok().getLoc();
3976 if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
3977 parseTokenLoc(Loc) ||
3980 "expected SourceField in '.cv_inline_linetable' directive") ||
3981 check(SourceFileId <= 0, Loc,
3982 "File id less than zero in '.cv_inline_linetable' directive") ||
3983 parseTokenLoc(Loc) ||
3986 "expected SourceLineNum in '.cv_inline_linetable' directive") ||
3987 check(SourceLineNum < 0, Loc,
3988 "Line number less than zero in '.cv_inline_linetable' directive") ||
3989 parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
3990 "expected identifier in directive") ||
3991 parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
3992 "expected identifier in directive"))
3998 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
3999 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
4000 getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
4001 SourceLineNum, FnStartSym,
4006 void AsmParser::initializeCVDefRangeTypeMap() {
4007 CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
4008 CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
4009 CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
4010 CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
4013 /// parseDirectiveCVDefRange
4014 /// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
4015 bool AsmParser::parseDirectiveCVDefRange() {
4017 std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
4018 while (getLexer().is(AsmToken::Identifier)) {
4019 Loc = getLexer().getLoc();
4020 StringRef GapStartName;
4021 if (parseIdentifier(GapStartName))
4022 return Error(Loc, "expected identifier in directive");
4023 MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
4025 Loc = getLexer().getLoc();
4026 StringRef GapEndName;
4027 if (parseIdentifier(GapEndName))
4028 return Error(Loc, "expected identifier in directive");
4029 MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
4031 Ranges.push_back({GapStartSym, GapEndSym});
4034 StringRef CVDefRangeTypeStr;
4037 "expected comma before def_range type in .cv_def_range directive") ||
4038 parseIdentifier(CVDefRangeTypeStr))
4039 return Error(Loc, "expected def_range type in directive");
4041 StringMap<CVDefRangeType>::const_iterator CVTypeIt =
4042 CVDefRangeTypeMap.find(CVDefRangeTypeStr);
4043 CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
4045 : CVTypeIt->getValue();
4047 case CVDR_DEFRANGE_REGISTER: {
4049 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4050 ".cv_def_range directive") ||
4051 parseAbsoluteExpression(DRRegister))
4052 return Error(Loc, "expected register number");
4054 codeview::DefRangeRegisterHeader DRHdr;
4055 DRHdr.Register = DRRegister;
4056 DRHdr.MayHaveNoName = 0;
4057 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4060 case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
4062 if (parseToken(AsmToken::Comma,
4063 "expected comma before offset in .cv_def_range directive") ||
4064 parseAbsoluteExpression(DROffset))
4065 return Error(Loc, "expected offset value");
4067 codeview::DefRangeFramePointerRelHeader DRHdr;
4068 DRHdr.Offset = DROffset;
4069 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4072 case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
4074 int64_t DROffsetInParent;
4075 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4076 ".cv_def_range directive") ||
4077 parseAbsoluteExpression(DRRegister))
4078 return Error(Loc, "expected register number");
4079 if (parseToken(AsmToken::Comma,
4080 "expected comma before offset in .cv_def_range directive") ||
4081 parseAbsoluteExpression(DROffsetInParent))
4082 return Error(Loc, "expected offset value");
4084 codeview::DefRangeSubfieldRegisterHeader DRHdr;
4085 DRHdr.Register = DRRegister;
4086 DRHdr.MayHaveNoName = 0;
4087 DRHdr.OffsetInParent = DROffsetInParent;
4088 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4091 case CVDR_DEFRANGE_REGISTER_REL: {
4094 int64_t DRBasePointerOffset;
4095 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4096 ".cv_def_range directive") ||
4097 parseAbsoluteExpression(DRRegister))
4098 return Error(Loc, "expected register value");
4101 "expected comma before flag value in .cv_def_range directive") ||
4102 parseAbsoluteExpression(DRFlags))
4103 return Error(Loc, "expected flag value");
4104 if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
4105 "in .cv_def_range directive") ||
4106 parseAbsoluteExpression(DRBasePointerOffset))
4107 return Error(Loc, "expected base pointer offset value");
4109 codeview::DefRangeRegisterRelHeader DRHdr;
4110 DRHdr.Register = DRRegister;
4111 DRHdr.Flags = DRFlags;
4112 DRHdr.BasePointerOffset = DRBasePointerOffset;
4113 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4117 return Error(Loc, "unexpected def_range type in .cv_def_range directive");
4122 /// parseDirectiveCVString
4123 /// ::= .cv_stringtable "string"
4124 bool AsmParser::parseDirectiveCVString() {
4126 if (checkForValidSection() || parseEscapedString(Data))
4129 // Put the string in the table and emit the offset.
4130 std::pair<StringRef, unsigned> Insertion =
4131 getCVContext().addToStringTable(Data);
4132 getStreamer().emitInt32(Insertion.second);
4136 /// parseDirectiveCVStringTable
4137 /// ::= .cv_stringtable
4138 bool AsmParser::parseDirectiveCVStringTable() {
4139 getStreamer().emitCVStringTableDirective();
4143 /// parseDirectiveCVFileChecksums
4144 /// ::= .cv_filechecksums
4145 bool AsmParser::parseDirectiveCVFileChecksums() {
4146 getStreamer().emitCVFileChecksumsDirective();
4150 /// parseDirectiveCVFileChecksumOffset
4151 /// ::= .cv_filechecksumoffset fileno
4152 bool AsmParser::parseDirectiveCVFileChecksumOffset() {
4154 if (parseIntToken(FileNo, "expected identifier in directive"))
4158 getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
4162 /// parseDirectiveCVFPOData
4163 /// ::= .cv_fpo_data procsym
4164 bool AsmParser::parseDirectiveCVFPOData() {
4165 SMLoc DirLoc = getLexer().getLoc();
4167 if (parseIdentifier(ProcName))
4168 return TokError("expected symbol name");
4171 MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
4172 getStreamer().emitCVFPOData(ProcSym, DirLoc);
4176 /// parseDirectiveCFISections
4177 /// ::= .cfi_sections section [, section]
4178 bool AsmParser::parseDirectiveCFISections() {
4183 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4185 if (parseIdentifier(Name))
4186 return TokError("expected .eh_frame or .debug_frame");
4187 if (Name == ".eh_frame")
4189 else if (Name == ".debug_frame")
4191 if (parseOptionalToken(AsmToken::EndOfStatement))
4197 getStreamer().emitCFISections(EH, Debug);
4201 /// parseDirectiveCFIStartProc
4202 /// ::= .cfi_startproc [simple]
4203 bool AsmParser::parseDirectiveCFIStartProc() {
4204 CFIStartProcLoc = StartTokLoc;
4207 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4208 if (check(parseIdentifier(Simple) || Simple != "simple",
4209 "unexpected token") ||
4214 // TODO(kristina): Deal with a corner case of incorrect diagnostic context
4215 // being produced if this directive is emitted as part of preprocessor macro
4216 // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
4217 // Tools like llvm-mc on the other hand are not affected by it, and report
4218 // correct context information.
4219 getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
4223 /// parseDirectiveCFIEndProc
4224 /// ::= .cfi_endproc
4225 bool AsmParser::parseDirectiveCFIEndProc() {
4226 CFIStartProcLoc = std::nullopt;
4231 getStreamer().emitCFIEndProc();
4235 /// parse register name or number.
4236 bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
4237 SMLoc DirectiveLoc) {
4240 if (getLexer().isNot(AsmToken::Integer)) {
4241 if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc))
4243 Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
4245 return parseAbsoluteExpression(Register);
4250 /// parseDirectiveCFIDefCfa
4251 /// ::= .cfi_def_cfa register, offset
4252 bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
4253 int64_t Register = 0, Offset = 0;
4254 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4255 parseAbsoluteExpression(Offset) || parseEOL())
4258 getStreamer().emitCFIDefCfa(Register, Offset, DirectiveLoc);
4262 /// parseDirectiveCFIDefCfaOffset
4263 /// ::= .cfi_def_cfa_offset offset
4264 bool AsmParser::parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc) {
4266 if (parseAbsoluteExpression(Offset) || parseEOL())
4269 getStreamer().emitCFIDefCfaOffset(Offset, DirectiveLoc);
4273 /// parseDirectiveCFIRegister
4274 /// ::= .cfi_register register, register
4275 bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
4276 int64_t Register1 = 0, Register2 = 0;
4277 if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || parseComma() ||
4278 parseRegisterOrRegisterNumber(Register2, DirectiveLoc) || parseEOL())
4281 getStreamer().emitCFIRegister(Register1, Register2, DirectiveLoc);
4285 /// parseDirectiveCFIWindowSave
4286 /// ::= .cfi_window_save
4287 bool AsmParser::parseDirectiveCFIWindowSave(SMLoc DirectiveLoc) {
4290 getStreamer().emitCFIWindowSave(DirectiveLoc);
4294 /// parseDirectiveCFIAdjustCfaOffset
4295 /// ::= .cfi_adjust_cfa_offset adjustment
4296 bool AsmParser::parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc) {
4297 int64_t Adjustment = 0;
4298 if (parseAbsoluteExpression(Adjustment) || parseEOL())
4301 getStreamer().emitCFIAdjustCfaOffset(Adjustment, DirectiveLoc);
4305 /// parseDirectiveCFIDefCfaRegister
4306 /// ::= .cfi_def_cfa_register register
4307 bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
4308 int64_t Register = 0;
4309 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4312 getStreamer().emitCFIDefCfaRegister(Register, DirectiveLoc);
4316 /// parseDirectiveCFILLVMDefAspaceCfa
4317 /// ::= .cfi_llvm_def_aspace_cfa register, offset, address_space
4318 bool AsmParser::parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc) {
4319 int64_t Register = 0, Offset = 0, AddressSpace = 0;
4320 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4321 parseAbsoluteExpression(Offset) || parseComma() ||
4322 parseAbsoluteExpression(AddressSpace) || parseEOL())
4325 getStreamer().emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace,
4330 /// parseDirectiveCFIOffset
4331 /// ::= .cfi_offset register, offset
4332 bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
4333 int64_t Register = 0;
4336 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4337 parseAbsoluteExpression(Offset) || parseEOL())
4340 getStreamer().emitCFIOffset(Register, Offset, DirectiveLoc);
4344 /// parseDirectiveCFIRelOffset
4345 /// ::= .cfi_rel_offset register, offset
4346 bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
4347 int64_t Register = 0, Offset = 0;
4349 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4350 parseAbsoluteExpression(Offset) || parseEOL())
4353 getStreamer().emitCFIRelOffset(Register, Offset, DirectiveLoc);
4357 static bool isValidEncoding(int64_t Encoding) {
4358 if (Encoding & ~0xff)
4361 if (Encoding == dwarf::DW_EH_PE_omit)
4364 const unsigned Format = Encoding & 0xf;
4365 if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
4366 Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
4367 Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
4368 Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
4371 const unsigned Application = Encoding & 0x70;
4372 if (Application != dwarf::DW_EH_PE_absptr &&
4373 Application != dwarf::DW_EH_PE_pcrel)
4379 /// parseDirectiveCFIPersonalityOrLsda
4380 /// IsPersonality true for cfi_personality, false for cfi_lsda
4381 /// ::= .cfi_personality encoding, [symbol_name]
4382 /// ::= .cfi_lsda encoding, [symbol_name]
4383 bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
4384 int64_t Encoding = 0;
4385 if (parseAbsoluteExpression(Encoding))
4387 if (Encoding == dwarf::DW_EH_PE_omit)
4391 if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
4393 check(parseIdentifier(Name), "expected identifier in directive") ||
4397 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4400 getStreamer().emitCFIPersonality(Sym, Encoding);
4402 getStreamer().emitCFILsda(Sym, Encoding);
4406 /// parseDirectiveCFIRememberState
4407 /// ::= .cfi_remember_state
4408 bool AsmParser::parseDirectiveCFIRememberState(SMLoc DirectiveLoc) {
4411 getStreamer().emitCFIRememberState(DirectiveLoc);
4415 /// parseDirectiveCFIRestoreState
4416 /// ::= .cfi_remember_state
4417 bool AsmParser::parseDirectiveCFIRestoreState(SMLoc DirectiveLoc) {
4420 getStreamer().emitCFIRestoreState(DirectiveLoc);
4424 /// parseDirectiveCFISameValue
4425 /// ::= .cfi_same_value register
4426 bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
4427 int64_t Register = 0;
4429 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4432 getStreamer().emitCFISameValue(Register, DirectiveLoc);
4436 /// parseDirectiveCFIRestore
4437 /// ::= .cfi_restore register
4438 bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
4439 int64_t Register = 0;
4440 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4443 getStreamer().emitCFIRestore(Register, DirectiveLoc);
4447 /// parseDirectiveCFIEscape
4448 /// ::= .cfi_escape expression[,...]
4449 bool AsmParser::parseDirectiveCFIEscape(SMLoc DirectiveLoc) {
4452 if (parseAbsoluteExpression(CurrValue))
4455 Values.push_back((uint8_t)CurrValue);
4457 while (getLexer().is(AsmToken::Comma)) {
4460 if (parseAbsoluteExpression(CurrValue))
4463 Values.push_back((uint8_t)CurrValue);
4466 getStreamer().emitCFIEscape(Values, DirectiveLoc);
4470 /// parseDirectiveCFIReturnColumn
4471 /// ::= .cfi_return_column register
4472 bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
4473 int64_t Register = 0;
4474 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4476 getStreamer().emitCFIReturnColumn(Register);
4480 /// parseDirectiveCFISignalFrame
4481 /// ::= .cfi_signal_frame
4482 bool AsmParser::parseDirectiveCFISignalFrame(SMLoc DirectiveLoc) {
4486 getStreamer().emitCFISignalFrame();
4490 /// parseDirectiveCFIUndefined
4491 /// ::= .cfi_undefined register
4492 bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
4493 int64_t Register = 0;
4495 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4498 getStreamer().emitCFIUndefined(Register, DirectiveLoc);
4502 /// parseDirectiveAltmacro
4505 bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
4508 AltMacroMode = (Directive == ".altmacro");
4512 /// parseDirectiveMacrosOnOff
4515 bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
4518 setMacrosEnabled(Directive == ".macros_on");
4522 /// parseDirectiveMacro
4523 /// ::= .macro name[,] [parameters]
4524 bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
4526 if (parseIdentifier(Name))
4527 return TokError("expected identifier in '.macro' directive");
4529 if (getLexer().is(AsmToken::Comma))
4532 MCAsmMacroParameters Parameters;
4533 while (getLexer().isNot(AsmToken::EndOfStatement)) {
4535 if (!Parameters.empty() && Parameters.back().Vararg)
4536 return Error(Lexer.getLoc(), "vararg parameter '" +
4537 Parameters.back().Name +
4538 "' should be the last parameter");
4540 MCAsmMacroParameter Parameter;
4541 if (parseIdentifier(Parameter.Name))
4542 return TokError("expected identifier in '.macro' directive");
4544 // Emit an error if two (or more) named parameters share the same name
4545 for (const MCAsmMacroParameter& CurrParam : Parameters)
4546 if (CurrParam.Name.equals(Parameter.Name))
4547 return TokError("macro '" + Name + "' has multiple parameters"
4548 " named '" + Parameter.Name + "'");
4550 if (Lexer.is(AsmToken::Colon)) {
4551 Lex(); // consume ':'
4554 StringRef Qualifier;
4556 QualLoc = Lexer.getLoc();
4557 if (parseIdentifier(Qualifier))
4558 return Error(QualLoc, "missing parameter qualifier for "
4559 "'" + Parameter.Name + "' in macro '" + Name + "'");
4561 if (Qualifier == "req")
4562 Parameter.Required = true;
4563 else if (Qualifier == "vararg")
4564 Parameter.Vararg = true;
4566 return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
4567 "for '" + Parameter.Name + "' in macro '" + Name + "'");
4570 if (getLexer().is(AsmToken::Equal)) {
4575 ParamLoc = Lexer.getLoc();
4576 if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
4579 if (Parameter.Required)
4580 Warning(ParamLoc, "pointless default value for required parameter "
4581 "'" + Parameter.Name + "' in macro '" + Name + "'");
4584 Parameters.push_back(std::move(Parameter));
4586 if (getLexer().is(AsmToken::Comma))
4590 // Eat just the end of statement.
4593 // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors
4594 AsmToken EndToken, StartToken = getTok();
4595 unsigned MacroDepth = 0;
4596 // Lex the macro definition.
4598 // Ignore Lexing errors in macros.
4599 while (Lexer.is(AsmToken::Error)) {
4603 // Check whether we have reached the end of the file.
4604 if (getLexer().is(AsmToken::Eof))
4605 return Error(DirectiveLoc, "no matching '.endmacro' in definition");
4607 // Otherwise, check whether we have reach the .endmacro or the start of a
4608 // preprocessor line marker.
4609 if (getLexer().is(AsmToken::Identifier)) {
4610 if (getTok().getIdentifier() == ".endm" ||
4611 getTok().getIdentifier() == ".endmacro") {
4612 if (MacroDepth == 0) { // Outermost macro.
4613 EndToken = getTok();
4615 if (getLexer().isNot(AsmToken::EndOfStatement))
4616 return TokError("unexpected token in '" + EndToken.getIdentifier() +
4620 // Otherwise we just found the end of an inner macro.
4623 } else if (getTok().getIdentifier() == ".macro") {
4624 // We allow nested macros. Those aren't instantiated until the outermost
4625 // macro is expanded so just ignore them for now.
4628 } else if (Lexer.is(AsmToken::HashDirective)) {
4629 (void)parseCppHashLineFilenameComment(getLexer().getLoc());
4632 // Otherwise, scan til the end of the statement.
4633 eatToEndOfStatement();
4636 if (getContext().lookupMacro(Name)) {
4637 return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
4640 const char *BodyStart = StartToken.getLoc().getPointer();
4641 const char *BodyEnd = EndToken.getLoc().getPointer();
4642 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4643 checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
4644 MCAsmMacro Macro(Name, Body, std::move(Parameters));
4645 DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
4647 getContext().defineMacro(Name, std::move(Macro));
4651 /// checkForBadMacro
4653 /// With the support added for named parameters there may be code out there that
4654 /// is transitioning from positional parameters. In versions of gas that did
4655 /// not support named parameters they would be ignored on the macro definition.
4656 /// But to support both styles of parameters this is not possible so if a macro
4657 /// definition has named parameters but does not use them and has what appears
4658 /// to be positional parameters, strings like $1, $2, ... and $n, then issue a
4659 /// warning that the positional parameter found in body which have no effect.
4660 /// Hoping the developer will either remove the named parameters from the macro
4661 /// definition so the positional parameters get used if that was what was
4662 /// intended or change the macro to use the named parameters. It is possible
4663 /// this warning will trigger when the none of the named parameters are used
4664 /// and the strings like $1 are infact to simply to be passed trough unchanged.
4665 void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
4667 ArrayRef<MCAsmMacroParameter> Parameters) {
4668 // If this macro is not defined with named parameters the warning we are
4669 // checking for here doesn't apply.
4670 unsigned NParameters = Parameters.size();
4671 if (NParameters == 0)
4674 bool NamedParametersFound = false;
4675 bool PositionalParametersFound = false;
4677 // Look at the body of the macro for use of both the named parameters and what
4678 // are likely to be positional parameters. This is what expandMacro() is
4679 // doing when it finds the parameters in the body.
4680 while (!Body.empty()) {
4681 // Scan for the next possible parameter.
4682 std::size_t End = Body.size(), Pos = 0;
4683 for (; Pos != End; ++Pos) {
4684 // Check for a substitution or escape.
4685 // This macro is defined with parameters, look for \foo, \bar, etc.
4686 if (Body[Pos] == '\\' && Pos + 1 != End)
4689 // This macro should have parameters, but look for $0, $1, ..., $n too.
4690 if (Body[Pos] != '$' || Pos + 1 == End)
4692 char Next = Body[Pos + 1];
4693 if (Next == '$' || Next == 'n' ||
4694 isdigit(static_cast<unsigned char>(Next)))
4698 // Check if we reached the end.
4702 if (Body[Pos] == '$') {
4703 switch (Body[Pos + 1]) {
4708 // $n => number of arguments
4710 PositionalParametersFound = true;
4713 // $[0-9] => argument
4715 PositionalParametersFound = true;
4721 unsigned I = Pos + 1;
4722 while (isIdentifierChar(Body[I]) && I + 1 != End)
4725 const char *Begin = Body.data() + Pos + 1;
4726 StringRef Argument(Begin, I - (Pos + 1));
4728 for (; Index < NParameters; ++Index)
4729 if (Parameters[Index].Name == Argument)
4732 if (Index == NParameters) {
4733 if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
4739 NamedParametersFound = true;
4740 Pos += 1 + Argument.size();
4743 // Update the scan point.
4744 Body = Body.substr(Pos);
4747 if (!NamedParametersFound && PositionalParametersFound)
4748 Warning(DirectiveLoc, "macro defined with named parameters which are not "
4749 "used in macro body, possible positional parameter "
4750 "found in body which will have no effect");
4753 /// parseDirectiveExitMacro
4755 bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
4759 if (!isInsideMacroInstantiation())
4760 return TokError("unexpected '" + Directive + "' in file, "
4761 "no current macro definition");
4763 // Exit all conditionals that are active in the current macro.
4764 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4765 TheCondState = TheCondStack.back();
4766 TheCondStack.pop_back();
4773 /// parseDirectiveEndMacro
4776 bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
4777 if (getLexer().isNot(AsmToken::EndOfStatement))
4778 return TokError("unexpected token in '" + Directive + "' directive");
4780 // If we are inside a macro instantiation, terminate the current
4782 if (isInsideMacroInstantiation()) {
4787 // Otherwise, this .endmacro is a stray entry in the file; well formed
4788 // .endmacro directives are handled during the macro definition parsing.
4789 return TokError("unexpected '" + Directive + "' in file, "
4790 "no current macro definition");
4793 /// parseDirectivePurgeMacro
4794 /// ::= .purgem name
4795 bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4798 if (parseTokenLoc(Loc) ||
4799 check(parseIdentifier(Name), Loc,
4800 "expected identifier in '.purgem' directive") ||
4804 if (!getContext().lookupMacro(Name))
4805 return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
4807 getContext().undefineMacro(Name);
4808 DEBUG_WITH_TYPE("asm-macros", dbgs()
4809 << "Un-defining macro: " << Name << "\n");
4813 /// parseDirectiveBundleAlignMode
4814 /// ::= {.bundle_align_mode} expression
4815 bool AsmParser::parseDirectiveBundleAlignMode() {
4816 // Expect a single argument: an expression that evaluates to a constant
4817 // in the inclusive range 0-30.
4818 SMLoc ExprLoc = getLexer().getLoc();
4819 int64_t AlignSizePow2;
4820 if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||
4822 check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc,
4823 "invalid bundle alignment size (expected between 0 and 30)"))
4826 getStreamer().emitBundleAlignMode(Align(1ULL << AlignSizePow2));
4830 /// parseDirectiveBundleLock
4831 /// ::= {.bundle_lock} [align_to_end]
4832 bool AsmParser::parseDirectiveBundleLock() {
4833 if (checkForValidSection())
4835 bool AlignToEnd = false;
4838 SMLoc Loc = getTok().getLoc();
4839 const char *kInvalidOptionError =
4840 "invalid option for '.bundle_lock' directive";
4842 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4843 if (check(parseIdentifier(Option), Loc, kInvalidOptionError) ||
4844 check(Option != "align_to_end", Loc, kInvalidOptionError) || parseEOL())
4849 getStreamer().emitBundleLock(AlignToEnd);
4853 /// parseDirectiveBundleLock
4854 /// ::= {.bundle_lock}
4855 bool AsmParser::parseDirectiveBundleUnlock() {
4856 if (checkForValidSection() || parseEOL())
4859 getStreamer().emitBundleUnlock();
4863 /// parseDirectiveSpace
4864 /// ::= (.skip | .space) expression [ , expression ]
4865 bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
4866 SMLoc NumBytesLoc = Lexer.getLoc();
4867 const MCExpr *NumBytes;
4868 if (checkForValidSection() || parseExpression(NumBytes))
4871 int64_t FillExpr = 0;
4872 if (parseOptionalToken(AsmToken::Comma))
4873 if (parseAbsoluteExpression(FillExpr))
4878 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
4879 getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
4884 /// parseDirectiveDCB
4885 /// ::= .dcb.{b, l, w} expression, expression
4886 bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
4887 SMLoc NumValuesLoc = Lexer.getLoc();
4889 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4892 if (NumValues < 0) {
4893 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4900 const MCExpr *Value;
4901 SMLoc ExprLoc = getLexer().getLoc();
4902 if (parseExpression(Value))
4905 // Special case constant expressions to match code generator.
4906 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
4907 assert(Size <= 8 && "Invalid size");
4908 uint64_t IntValue = MCE->getValue();
4909 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
4910 return Error(ExprLoc, "literal value out of range for directive");
4911 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4912 getStreamer().emitIntValue(IntValue, Size);
4914 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4915 getStreamer().emitValue(Value, Size, ExprLoc);
4921 /// parseDirectiveRealDCB
4922 /// ::= .dcb.{d, s} expression, expression
4923 bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {
4924 SMLoc NumValuesLoc = Lexer.getLoc();
4926 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4929 if (NumValues < 0) {
4930 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4938 if (parseRealValue(Semantics, AsInt) || parseEOL())
4941 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4942 getStreamer().emitIntValue(AsInt.getLimitedValue(),
4943 AsInt.getBitWidth() / 8);
4948 /// parseDirectiveDS
4949 /// ::= .ds.{b, d, l, p, s, w, x} expression
4950 bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {
4951 SMLoc NumValuesLoc = Lexer.getLoc();
4953 if (checkForValidSection() || parseAbsoluteExpression(NumValues) ||
4957 if (NumValues < 0) {
4958 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4962 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4963 getStreamer().emitFill(Size, 0);
4968 /// parseDirectiveLEB128
4969 /// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
4970 bool AsmParser::parseDirectiveLEB128(bool Signed) {
4971 if (checkForValidSection())
4974 auto parseOp = [&]() -> bool {
4975 const MCExpr *Value;
4976 if (parseExpression(Value))
4979 getStreamer().emitSLEB128Value(Value);
4981 getStreamer().emitULEB128Value(Value);
4985 return parseMany(parseOp);
4988 /// parseDirectiveSymbolAttribute
4989 /// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
4990 bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
4991 auto parseOp = [&]() -> bool {
4993 SMLoc Loc = getTok().getLoc();
4994 if (parseIdentifier(Name))
4995 return Error(Loc, "expected identifier");
4997 if (discardLTOSymbol(Name))
5000 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5002 // Assembler local symbols don't make any sense here, except for directives
5003 // that the symbol should be tagged.
5004 if (Sym->isTemporary() && Attr != MCSA_Memtag)
5005 return Error(Loc, "non-local symbol required");
5007 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
5008 return Error(Loc, "unable to emit symbol attribute");
5012 return parseMany(parseOp);
5015 /// parseDirectiveComm
5016 /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
5017 bool AsmParser::parseDirectiveComm(bool IsLocal) {
5018 if (checkForValidSection())
5021 SMLoc IDLoc = getLexer().getLoc();
5023 if (parseIdentifier(Name))
5024 return TokError("expected identifier in directive");
5026 // Handle the identifier as the key symbol.
5027 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5033 SMLoc SizeLoc = getLexer().getLoc();
5034 if (parseAbsoluteExpression(Size))
5037 int64_t Pow2Alignment = 0;
5038 SMLoc Pow2AlignmentLoc;
5039 if (getLexer().is(AsmToken::Comma)) {
5041 Pow2AlignmentLoc = getLexer().getLoc();
5042 if (parseAbsoluteExpression(Pow2Alignment))
5045 LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
5046 if (IsLocal && LCOMM == LCOMM::NoAlignment)
5047 return Error(Pow2AlignmentLoc, "alignment not supported on this target");
5049 // If this target takes alignments in bytes (not log) validate and convert.
5050 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
5051 (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
5052 if (!isPowerOf2_64(Pow2Alignment))
5053 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
5054 Pow2Alignment = Log2_64(Pow2Alignment);
5061 // NOTE: a size of zero for a .comm should create a undefined symbol
5062 // but a size of .lcomm creates a bss symbol of size zero.
5064 return Error(SizeLoc, "size must be non-negative");
5066 Sym->redefineIfPossible();
5067 if (!Sym->isUndefined())
5068 return Error(IDLoc, "invalid symbol redefinition");
5070 // Create the Symbol as a common or local common with Size and Pow2Alignment
5072 getStreamer().emitLocalCommonSymbol(Sym, Size,
5073 Align(1ULL << Pow2Alignment));
5077 getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));
5081 /// parseDirectiveAbort
5082 /// ::= .abort [... message ...]
5083 bool AsmParser::parseDirectiveAbort() {
5084 // FIXME: Use loc from directive.
5085 SMLoc Loc = getLexer().getLoc();
5087 StringRef Str = parseStringToEndOfStatement();
5092 return Error(Loc, ".abort detected. Assembly stopping.");
5094 return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
5095 // FIXME: Actually abort assembly here.
5100 /// parseDirectiveInclude
5101 /// ::= .include "filename"
5102 bool AsmParser::parseDirectiveInclude() {
5103 // Allow the strings to have escaped octal character sequence.
5104 std::string Filename;
5105 SMLoc IncludeLoc = getTok().getLoc();
5107 if (check(getTok().isNot(AsmToken::String),
5108 "expected string in '.include' directive") ||
5109 parseEscapedString(Filename) ||
5110 check(getTok().isNot(AsmToken::EndOfStatement),
5111 "unexpected token in '.include' directive") ||
5112 // Attempt to switch the lexer to the included file before consuming the
5113 // end of statement to avoid losing it when we switch.
5114 check(enterIncludeFile(Filename), IncludeLoc,
5115 "Could not find include file '" + Filename + "'"))
5121 /// parseDirectiveIncbin
5122 /// ::= .incbin "filename" [ , skip [ , count ] ]
5123 bool AsmParser::parseDirectiveIncbin() {
5124 // Allow the strings to have escaped octal character sequence.
5125 std::string Filename;
5126 SMLoc IncbinLoc = getTok().getLoc();
5127 if (check(getTok().isNot(AsmToken::String),
5128 "expected string in '.incbin' directive") ||
5129 parseEscapedString(Filename))
5133 const MCExpr *Count = nullptr;
5134 SMLoc SkipLoc, CountLoc;
5135 if (parseOptionalToken(AsmToken::Comma)) {
5136 // The skip expression can be omitted while specifying the count, e.g:
5137 // .incbin "filename",,4
5138 if (getTok().isNot(AsmToken::Comma)) {
5139 if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))
5142 if (parseOptionalToken(AsmToken::Comma)) {
5143 CountLoc = getTok().getLoc();
5144 if (parseExpression(Count))
5152 if (check(Skip < 0, SkipLoc, "skip is negative"))
5155 // Attempt to process the included file.
5156 if (processIncbinFile(Filename, Skip, Count, CountLoc))
5157 return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
5161 /// parseDirectiveIf
5162 /// ::= .if{,eq,ge,gt,le,lt,ne} expression
5163 bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
5164 TheCondStack.push_back(TheCondState);
5165 TheCondState.TheCond = AsmCond::IfCond;
5166 if (TheCondState.Ignore) {
5167 eatToEndOfStatement();
5170 if (parseAbsoluteExpression(ExprValue) || parseEOL())
5175 llvm_unreachable("unsupported directive");
5180 ExprValue = ExprValue == 0;
5183 ExprValue = ExprValue >= 0;
5186 ExprValue = ExprValue > 0;
5189 ExprValue = ExprValue <= 0;
5192 ExprValue = ExprValue < 0;
5196 TheCondState.CondMet = ExprValue;
5197 TheCondState.Ignore = !TheCondState.CondMet;
5203 /// parseDirectiveIfb
5205 bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
5206 TheCondStack.push_back(TheCondState);
5207 TheCondState.TheCond = AsmCond::IfCond;
5209 if (TheCondState.Ignore) {
5210 eatToEndOfStatement();
5212 StringRef Str = parseStringToEndOfStatement();
5217 TheCondState.CondMet = ExpectBlank == Str.empty();
5218 TheCondState.Ignore = !TheCondState.CondMet;
5224 /// parseDirectiveIfc
5225 /// ::= .ifc string1, string2
5226 /// ::= .ifnc string1, string2
5227 bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
5228 TheCondStack.push_back(TheCondState);
5229 TheCondState.TheCond = AsmCond::IfCond;
5231 if (TheCondState.Ignore) {
5232 eatToEndOfStatement();
5234 StringRef Str1 = parseStringToComma();
5239 StringRef Str2 = parseStringToEndOfStatement();
5244 TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
5245 TheCondState.Ignore = !TheCondState.CondMet;
5251 /// parseDirectiveIfeqs
5252 /// ::= .ifeqs string1, string2
5253 bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
5254 if (Lexer.isNot(AsmToken::String)) {
5256 return TokError("expected string parameter for '.ifeqs' directive");
5257 return TokError("expected string parameter for '.ifnes' directive");
5260 StringRef String1 = getTok().getStringContents();
5263 if (Lexer.isNot(AsmToken::Comma)) {
5266 "expected comma after first string for '.ifeqs' directive");
5267 return TokError("expected comma after first string for '.ifnes' directive");
5272 if (Lexer.isNot(AsmToken::String)) {
5274 return TokError("expected string parameter for '.ifeqs' directive");
5275 return TokError("expected string parameter for '.ifnes' directive");
5278 StringRef String2 = getTok().getStringContents();
5281 TheCondStack.push_back(TheCondState);
5282 TheCondState.TheCond = AsmCond::IfCond;
5283 TheCondState.CondMet = ExpectEqual == (String1 == String2);
5284 TheCondState.Ignore = !TheCondState.CondMet;
5289 /// parseDirectiveIfdef
5290 /// ::= .ifdef symbol
5291 bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
5293 TheCondStack.push_back(TheCondState);
5294 TheCondState.TheCond = AsmCond::IfCond;
5296 if (TheCondState.Ignore) {
5297 eatToEndOfStatement();
5299 if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
5303 MCSymbol *Sym = getContext().lookupSymbol(Name);
5306 TheCondState.CondMet = (Sym && !Sym->isUndefined(false));
5308 TheCondState.CondMet = (!Sym || Sym->isUndefined(false));
5309 TheCondState.Ignore = !TheCondState.CondMet;
5315 /// parseDirectiveElseIf
5316 /// ::= .elseif expression
5317 bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
5318 if (TheCondState.TheCond != AsmCond::IfCond &&
5319 TheCondState.TheCond != AsmCond::ElseIfCond)
5320 return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
5321 " .if or an .elseif");
5322 TheCondState.TheCond = AsmCond::ElseIfCond;
5324 bool LastIgnoreState = false;
5325 if (!TheCondStack.empty())
5326 LastIgnoreState = TheCondStack.back().Ignore;
5327 if (LastIgnoreState || TheCondState.CondMet) {
5328 TheCondState.Ignore = true;
5329 eatToEndOfStatement();
5332 if (parseAbsoluteExpression(ExprValue))
5338 TheCondState.CondMet = ExprValue;
5339 TheCondState.Ignore = !TheCondState.CondMet;
5345 /// parseDirectiveElse
5347 bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
5351 if (TheCondState.TheCond != AsmCond::IfCond &&
5352 TheCondState.TheCond != AsmCond::ElseIfCond)
5353 return Error(DirectiveLoc, "Encountered a .else that doesn't follow "
5354 " an .if or an .elseif");
5355 TheCondState.TheCond = AsmCond::ElseCond;
5356 bool LastIgnoreState = false;
5357 if (!TheCondStack.empty())
5358 LastIgnoreState = TheCondStack.back().Ignore;
5359 if (LastIgnoreState || TheCondState.CondMet)
5360 TheCondState.Ignore = true;
5362 TheCondState.Ignore = false;
5367 /// parseDirectiveEnd
5369 bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5373 while (Lexer.isNot(AsmToken::Eof))
5379 /// parseDirectiveError
5381 /// ::= .error [string]
5382 bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
5383 if (!TheCondStack.empty()) {
5384 if (TheCondStack.back().Ignore) {
5385 eatToEndOfStatement();
5391 return Error(L, ".err encountered");
5393 StringRef Message = ".error directive invoked in source file";
5394 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5395 if (Lexer.isNot(AsmToken::String))
5396 return TokError(".error argument must be a string");
5398 Message = getTok().getStringContents();
5402 return Error(L, Message);
5405 /// parseDirectiveWarning
5406 /// ::= .warning [string]
5407 bool AsmParser::parseDirectiveWarning(SMLoc L) {
5408 if (!TheCondStack.empty()) {
5409 if (TheCondStack.back().Ignore) {
5410 eatToEndOfStatement();
5415 StringRef Message = ".warning directive invoked in source file";
5417 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
5418 if (Lexer.isNot(AsmToken::String))
5419 return TokError(".warning argument must be a string");
5421 Message = getTok().getStringContents();
5427 return Warning(L, Message);
5430 /// parseDirectiveEndIf
5432 bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5436 if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
5437 return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
5439 if (!TheCondStack.empty()) {
5440 TheCondState = TheCondStack.back();
5441 TheCondStack.pop_back();
5447 void AsmParser::initializeDirectiveKindMap() {
5448 /* Lookup will be done with the directive
5449 * converted to lower case, so all these
5450 * keys should be lower case.
5451 * (target specific directives are handled
5454 DirectiveKindMap[".set"] = DK_SET;
5455 DirectiveKindMap[".equ"] = DK_EQU;
5456 DirectiveKindMap[".equiv"] = DK_EQUIV;
5457 DirectiveKindMap[".ascii"] = DK_ASCII;
5458 DirectiveKindMap[".asciz"] = DK_ASCIZ;
5459 DirectiveKindMap[".string"] = DK_STRING;
5460 DirectiveKindMap[".byte"] = DK_BYTE;
5461 DirectiveKindMap[".short"] = DK_SHORT;
5462 DirectiveKindMap[".value"] = DK_VALUE;
5463 DirectiveKindMap[".2byte"] = DK_2BYTE;
5464 DirectiveKindMap[".long"] = DK_LONG;
5465 DirectiveKindMap[".int"] = DK_INT;
5466 DirectiveKindMap[".4byte"] = DK_4BYTE;
5467 DirectiveKindMap[".quad"] = DK_QUAD;
5468 DirectiveKindMap[".8byte"] = DK_8BYTE;
5469 DirectiveKindMap[".octa"] = DK_OCTA;
5470 DirectiveKindMap[".single"] = DK_SINGLE;
5471 DirectiveKindMap[".float"] = DK_FLOAT;
5472 DirectiveKindMap[".double"] = DK_DOUBLE;
5473 DirectiveKindMap[".align"] = DK_ALIGN;
5474 DirectiveKindMap[".align32"] = DK_ALIGN32;
5475 DirectiveKindMap[".balign"] = DK_BALIGN;
5476 DirectiveKindMap[".balignw"] = DK_BALIGNW;
5477 DirectiveKindMap[".balignl"] = DK_BALIGNL;
5478 DirectiveKindMap[".p2align"] = DK_P2ALIGN;
5479 DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
5480 DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
5481 DirectiveKindMap[".org"] = DK_ORG;
5482 DirectiveKindMap[".fill"] = DK_FILL;
5483 DirectiveKindMap[".zero"] = DK_ZERO;
5484 DirectiveKindMap[".extern"] = DK_EXTERN;
5485 DirectiveKindMap[".globl"] = DK_GLOBL;
5486 DirectiveKindMap[".global"] = DK_GLOBAL;
5487 DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
5488 DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
5489 DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
5490 DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
5491 DirectiveKindMap[".reference"] = DK_REFERENCE;
5492 DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
5493 DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
5494 DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
5495 DirectiveKindMap[".cold"] = DK_COLD;
5496 DirectiveKindMap[".comm"] = DK_COMM;
5497 DirectiveKindMap[".common"] = DK_COMMON;
5498 DirectiveKindMap[".lcomm"] = DK_LCOMM;
5499 DirectiveKindMap[".abort"] = DK_ABORT;
5500 DirectiveKindMap[".include"] = DK_INCLUDE;
5501 DirectiveKindMap[".incbin"] = DK_INCBIN;
5502 DirectiveKindMap[".code16"] = DK_CODE16;
5503 DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
5504 DirectiveKindMap[".rept"] = DK_REPT;
5505 DirectiveKindMap[".rep"] = DK_REPT;
5506 DirectiveKindMap[".irp"] = DK_IRP;
5507 DirectiveKindMap[".irpc"] = DK_IRPC;
5508 DirectiveKindMap[".endr"] = DK_ENDR;
5509 DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE;
5510 DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK;
5511 DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK;
5512 DirectiveKindMap[".if"] = DK_IF;
5513 DirectiveKindMap[".ifeq"] = DK_IFEQ;
5514 DirectiveKindMap[".ifge"] = DK_IFGE;
5515 DirectiveKindMap[".ifgt"] = DK_IFGT;
5516 DirectiveKindMap[".ifle"] = DK_IFLE;
5517 DirectiveKindMap[".iflt"] = DK_IFLT;
5518 DirectiveKindMap[".ifne"] = DK_IFNE;
5519 DirectiveKindMap[".ifb"] = DK_IFB;
5520 DirectiveKindMap[".ifnb"] = DK_IFNB;
5521 DirectiveKindMap[".ifc"] = DK_IFC;
5522 DirectiveKindMap[".ifeqs"] = DK_IFEQS;
5523 DirectiveKindMap[".ifnc"] = DK_IFNC;
5524 DirectiveKindMap[".ifnes"] = DK_IFNES;
5525 DirectiveKindMap[".ifdef"] = DK_IFDEF;
5526 DirectiveKindMap[".ifndef"] = DK_IFNDEF;
5527 DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
5528 DirectiveKindMap[".elseif"] = DK_ELSEIF;
5529 DirectiveKindMap[".else"] = DK_ELSE;
5530 DirectiveKindMap[".end"] = DK_END;
5531 DirectiveKindMap[".endif"] = DK_ENDIF;
5532 DirectiveKindMap[".skip"] = DK_SKIP;
5533 DirectiveKindMap[".space"] = DK_SPACE;
5534 DirectiveKindMap[".file"] = DK_FILE;
5535 DirectiveKindMap[".line"] = DK_LINE;
5536 DirectiveKindMap[".loc"] = DK_LOC;
5537 DirectiveKindMap[".stabs"] = DK_STABS;
5538 DirectiveKindMap[".cv_file"] = DK_CV_FILE;
5539 DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
5540 DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
5541 DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
5542 DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
5543 DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
5544 DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
5545 DirectiveKindMap[".cv_string"] = DK_CV_STRING;
5546 DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
5547 DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
5548 DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
5549 DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
5550 DirectiveKindMap[".sleb128"] = DK_SLEB128;
5551 DirectiveKindMap[".uleb128"] = DK_ULEB128;
5552 DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
5553 DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
5554 DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
5555 DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
5556 DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
5557 DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
5558 DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
5559 DirectiveKindMap[".cfi_llvm_def_aspace_cfa"] = DK_CFI_LLVM_DEF_ASPACE_CFA;
5560 DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
5561 DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
5562 DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
5563 DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
5564 DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
5565 DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
5566 DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
5567 DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
5568 DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
5569 DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
5570 DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
5571 DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
5572 DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
5573 DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
5574 DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
5575 DirectiveKindMap[".cfi_mte_tagged_frame"] = DK_CFI_MTE_TAGGED_FRAME;
5576 DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
5577 DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
5578 DirectiveKindMap[".macro"] = DK_MACRO;
5579 DirectiveKindMap[".exitm"] = DK_EXITM;
5580 DirectiveKindMap[".endm"] = DK_ENDM;
5581 DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
5582 DirectiveKindMap[".purgem"] = DK_PURGEM;
5583 DirectiveKindMap[".err"] = DK_ERR;
5584 DirectiveKindMap[".error"] = DK_ERROR;
5585 DirectiveKindMap[".warning"] = DK_WARNING;
5586 DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
5587 DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
5588 DirectiveKindMap[".reloc"] = DK_RELOC;
5589 DirectiveKindMap[".dc"] = DK_DC;
5590 DirectiveKindMap[".dc.a"] = DK_DC_A;
5591 DirectiveKindMap[".dc.b"] = DK_DC_B;
5592 DirectiveKindMap[".dc.d"] = DK_DC_D;
5593 DirectiveKindMap[".dc.l"] = DK_DC_L;
5594 DirectiveKindMap[".dc.s"] = DK_DC_S;
5595 DirectiveKindMap[".dc.w"] = DK_DC_W;
5596 DirectiveKindMap[".dc.x"] = DK_DC_X;
5597 DirectiveKindMap[".dcb"] = DK_DCB;
5598 DirectiveKindMap[".dcb.b"] = DK_DCB_B;
5599 DirectiveKindMap[".dcb.d"] = DK_DCB_D;
5600 DirectiveKindMap[".dcb.l"] = DK_DCB_L;
5601 DirectiveKindMap[".dcb.s"] = DK_DCB_S;
5602 DirectiveKindMap[".dcb.w"] = DK_DCB_W;
5603 DirectiveKindMap[".dcb.x"] = DK_DCB_X;
5604 DirectiveKindMap[".ds"] = DK_DS;
5605 DirectiveKindMap[".ds.b"] = DK_DS_B;
5606 DirectiveKindMap[".ds.d"] = DK_DS_D;
5607 DirectiveKindMap[".ds.l"] = DK_DS_L;
5608 DirectiveKindMap[".ds.p"] = DK_DS_P;
5609 DirectiveKindMap[".ds.s"] = DK_DS_S;
5610 DirectiveKindMap[".ds.w"] = DK_DS_W;
5611 DirectiveKindMap[".ds.x"] = DK_DS_X;
5612 DirectiveKindMap[".print"] = DK_PRINT;
5613 DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
5614 DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
5615 DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE;
5616 DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD;
5617 DirectiveKindMap[".lto_set_conditional"] = DK_LTO_SET_CONDITIONAL;
5618 DirectiveKindMap[".memtag"] = DK_MEMTAG;
5621 MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5622 AsmToken EndToken, StartToken = getTok();
5624 unsigned NestLevel = 0;
5626 // Check whether we have reached the end of the file.
5627 if (getLexer().is(AsmToken::Eof)) {
5628 printError(DirectiveLoc, "no matching '.endr' in definition");
5632 if (Lexer.is(AsmToken::Identifier) &&
5633 (getTok().getIdentifier() == ".rep" ||
5634 getTok().getIdentifier() == ".rept" ||
5635 getTok().getIdentifier() == ".irp" ||
5636 getTok().getIdentifier() == ".irpc")) {
5640 // Otherwise, check whether we have reached the .endr.
5641 if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") {
5642 if (NestLevel == 0) {
5643 EndToken = getTok();
5645 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5646 printError(getTok().getLoc(),
5647 "unexpected token in '.endr' directive");
5655 // Otherwise, scan till the end of the statement.
5656 eatToEndOfStatement();
5659 const char *BodyStart = StartToken.getLoc().getPointer();
5660 const char *BodyEnd = EndToken.getLoc().getPointer();
5661 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5663 // We Are Anonymous.
5664 MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
5665 return &MacroLikeBodies.back();
5668 void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5669 raw_svector_ostream &OS) {
5672 std::unique_ptr<MemoryBuffer> Instantiation =
5673 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
5675 // Create the macro instantiation object and add to the current macro
5676 // instantiation stack.
5677 MacroInstantiation *MI = new MacroInstantiation{
5678 DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
5679 ActiveMacros.push_back(MI);
5681 // Jump to the macro instantiation and prime the lexer.
5682 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
5683 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
5687 /// parseDirectiveRept
5688 /// ::= .rep | .rept count
5689 bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
5690 const MCExpr *CountExpr;
5691 SMLoc CountLoc = getTok().getLoc();
5692 if (parseExpression(CountExpr))
5696 if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
5697 return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
5700 if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())
5703 // Lex the rept definition.
5704 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5708 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5709 // to hold the macro body with substitutions.
5710 SmallString<256> Buf;
5711 raw_svector_ostream OS(Buf);
5713 // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
5714 if (expandMacro(OS, M->Body, std::nullopt, std::nullopt, false,
5718 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5723 /// parseDirectiveIrp
5724 /// ::= .irp symbol,values
5725 bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
5726 MCAsmMacroParameter Parameter;
5727 MCAsmMacroArguments A;
5728 if (check(parseIdentifier(Parameter.Name),
5729 "expected identifier in '.irp' directive") ||
5730 parseComma() || parseMacroArguments(nullptr, A) || parseEOL())
5733 // Lex the irp definition.
5734 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5738 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5739 // to hold the macro body with substitutions.
5740 SmallString<256> Buf;
5741 raw_svector_ostream OS(Buf);
5743 for (const MCAsmMacroArgument &Arg : A) {
5744 // Note that the AtPseudoVariable is enabled for instantiations of .irp.
5745 // This is undocumented, but GAS seems to support it.
5746 if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
5750 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5755 /// parseDirectiveIrpc
5756 /// ::= .irpc symbol,values
5757 bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
5758 MCAsmMacroParameter Parameter;
5759 MCAsmMacroArguments A;
5761 if (check(parseIdentifier(Parameter.Name),
5762 "expected identifier in '.irpc' directive") ||
5763 parseComma() || parseMacroArguments(nullptr, A))
5766 if (A.size() != 1 || A.front().size() != 1)
5767 return TokError("unexpected token in '.irpc' directive");
5771 // Lex the irpc definition.
5772 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5776 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5777 // to hold the macro body with substitutions.
5778 SmallString<256> Buf;
5779 raw_svector_ostream OS(Buf);
5781 StringRef Values = A.front().front().getString();
5782 for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
5783 MCAsmMacroArgument Arg;
5784 Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
5786 // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
5787 // This is undocumented, but GAS seems to support it.
5788 if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
5792 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5797 bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
5798 if (ActiveMacros.empty())
5799 return TokError("unmatched '.endr' directive");
5801 // The only .repl that should get here are the ones created by
5802 // instantiateMacroLikeBody.
5803 assert(getLexer().is(AsmToken::EndOfStatement));
5809 bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5811 const MCExpr *Value;
5812 SMLoc ExprLoc = getLexer().getLoc();
5813 if (parseExpression(Value))
5815 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5817 return Error(ExprLoc, "unexpected expression in _emit");
5818 uint64_t IntValue = MCE->getValue();
5819 if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
5820 return Error(ExprLoc, "literal value out of range for directive");
5822 Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
5826 bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5827 const MCExpr *Value;
5828 SMLoc ExprLoc = getLexer().getLoc();
5829 if (parseExpression(Value))
5831 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5833 return Error(ExprLoc, "unexpected expression in align");
5834 uint64_t IntValue = MCE->getValue();
5835 if (!isPowerOf2_64(IntValue))
5836 return Error(ExprLoc, "literal value not a power of two greater then zero");
5838 Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
5842 bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
5843 const AsmToken StrTok = getTok();
5845 if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
5846 return Error(DirectiveLoc, "expected double quoted string after .print");
5849 llvm::outs() << StrTok.getStringContents() << '\n';
5853 bool AsmParser::parseDirectiveAddrsig() {
5856 getStreamer().emitAddrsig();
5860 bool AsmParser::parseDirectiveAddrsigSym() {
5862 if (check(parseIdentifier(Name), "expected identifier") || parseEOL())
5864 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5865 getStreamer().emitAddrsigSym(Sym);
5869 bool AsmParser::parseDirectivePseudoProbe() {
5874 int64_t Discriminator = 0;
5876 if (parseIntToken(Guid, "unexpected token in '.pseudoprobe' directive"))
5879 if (parseIntToken(Index, "unexpected token in '.pseudoprobe' directive"))
5882 if (parseIntToken(Type, "unexpected token in '.pseudoprobe' directive"))
5885 if (parseIntToken(Attr, "unexpected token in '.pseudoprobe' directive"))
5888 if (hasDiscriminator(Attr)) {
5889 if (parseIntToken(Discriminator,
5890 "unexpected token in '.pseudoprobe' directive"))
5894 // Parse inline stack like @ GUID:11:12 @ GUID:1:11 @ GUID:3:21
5895 MCPseudoProbeInlineStack InlineStack;
5897 while (getLexer().is(AsmToken::At)) {
5901 int64_t CallerGuid = 0;
5902 if (getLexer().is(AsmToken::Integer)) {
5903 if (parseIntToken(CallerGuid,
5904 "unexpected token in '.pseudoprobe' directive"))
5909 if (getLexer().is(AsmToken::Colon))
5912 int64_t CallerProbeId = 0;
5913 if (getLexer().is(AsmToken::Integer)) {
5914 if (parseIntToken(CallerProbeId,
5915 "unexpected token in '.pseudoprobe' directive"))
5919 InlineSite Site(CallerGuid, CallerProbeId);
5920 InlineStack.push_back(Site);
5923 // Parse function entry name
5925 if (parseIdentifier(FnName))
5926 return Error(getLexer().getLoc(), "unexpected token in '.pseudoprobe' directive");
5927 MCSymbol *FnSym = getContext().lookupSymbol(FnName);
5932 getStreamer().emitPseudoProbe(Guid, Index, Type, Attr, Discriminator,
5933 InlineStack, FnSym);
5937 /// parseDirectiveLTODiscard
5938 /// ::= ".lto_discard" [ identifier ( , identifier )* ]
5939 /// The LTO library emits this directive to discard non-prevailing symbols.
5940 /// We ignore symbol assignments and attribute changes for the specified
5942 bool AsmParser::parseDirectiveLTODiscard() {
5943 auto ParseOp = [&]() -> bool {
5945 SMLoc Loc = getTok().getLoc();
5946 if (parseIdentifier(Name))
5947 return Error(Loc, "expected identifier");
5948 LTODiscardSymbols.insert(Name);
5952 LTODiscardSymbols.clear();
5953 return parseMany(ParseOp);
5956 // We are comparing pointers, but the pointers are relative to a single string.
5957 // Thus, this should always be deterministic.
5958 static int rewritesSort(const AsmRewrite *AsmRewriteA,
5959 const AsmRewrite *AsmRewriteB) {
5960 if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
5962 if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
5965 // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
5966 // rewrite to the same location. Make sure the SizeDirective rewrite is
5967 // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
5968 // ensures the sort algorithm is stable.
5969 if (AsmRewritePrecedence[AsmRewriteA->Kind] >
5970 AsmRewritePrecedence[AsmRewriteB->Kind])
5973 if (AsmRewritePrecedence[AsmRewriteA->Kind] <
5974 AsmRewritePrecedence[AsmRewriteB->Kind])
5976 llvm_unreachable("Unstable rewrite sort.");
5979 bool AsmParser::parseMSInlineAsm(
5980 std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,
5981 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5982 SmallVectorImpl<std::string> &Constraints,
5983 SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
5984 const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5985 SmallVector<void *, 4> InputDecls;
5986 SmallVector<void *, 4> OutputDecls;
5987 SmallVector<bool, 4> InputDeclsAddressOf;
5988 SmallVector<bool, 4> OutputDeclsAddressOf;
5989 SmallVector<std::string, 4> InputConstraints;
5990 SmallVector<std::string, 4> OutputConstraints;
5991 SmallVector<unsigned, 4> ClobberRegs;
5993 SmallVector<AsmRewrite, 4> AsmStrRewrites;
5998 // While we have input, parse each statement.
5999 unsigned InputIdx = 0;
6000 unsigned OutputIdx = 0;
6001 while (getLexer().isNot(AsmToken::Eof)) {
6002 // Parse curly braces marking block start/end
6003 if (parseCurlyBlockScope(AsmStrRewrites))
6006 ParseStatementInfo Info(&AsmStrRewrites);
6007 bool StatementErr = parseStatement(Info, &SI);
6009 if (StatementErr || Info.ParseError) {
6010 // Emit pending errors if any exist.
6011 printPendingErrors();
6015 // No pending error should exist here.
6016 assert(!hasPendingError() && "unexpected error from parseStatement");
6018 if (Info.Opcode == ~0U)
6021 const MCInstrDesc &Desc = MII->get(Info.Opcode);
6023 // Build the list of clobbers, outputs and inputs.
6024 for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
6025 MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
6027 // Register operand.
6028 if (Operand.isReg() && !Operand.needAddressOf() &&
6029 !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
6030 unsigned NumDefs = Desc.getNumDefs();
6032 if (NumDefs && Operand.getMCOperandNum() < NumDefs)
6033 ClobberRegs.push_back(Operand.getReg());
6037 // Expr/Input or Output.
6038 StringRef SymName = Operand.getSymName();
6039 if (SymName.empty())
6042 void *OpDecl = Operand.getOpDecl();
6046 StringRef Constraint = Operand.getConstraint();
6047 if (Operand.isImm()) {
6048 // Offset as immediate
6049 if (Operand.isOffsetOfLocal())
6055 bool isOutput = (i == 1) && Desc.mayStore();
6056 bool Restricted = Operand.isMemUseUpRegs();
6057 SMLoc Start = SMLoc::getFromPointer(SymName.data());
6060 OutputDecls.push_back(OpDecl);
6061 OutputDeclsAddressOf.push_back(Operand.needAddressOf());
6062 OutputConstraints.push_back(("=" + Constraint).str());
6063 AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size(), 0,
6066 InputDecls.push_back(OpDecl);
6067 InputDeclsAddressOf.push_back(Operand.needAddressOf());
6068 InputConstraints.push_back(Constraint.str());
6069 if (Desc.operands()[i - 1].isBranchTarget())
6070 AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size(), 0,
6073 AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size(), 0,
6078 // Consider implicit defs to be clobbers. Think of cpuid and push.
6079 llvm::append_range(ClobberRegs, Desc.implicit_defs());
6082 // Set the number of Outputs and Inputs.
6083 NumOutputs = OutputDecls.size();
6084 NumInputs = InputDecls.size();
6086 // Set the unique clobbers.
6087 array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
6088 ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
6090 Clobbers.assign(ClobberRegs.size(), std::string());
6091 for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
6092 raw_string_ostream OS(Clobbers[I]);
6093 IP->printRegName(OS, ClobberRegs[I]);
6096 // Merge the various outputs and inputs. Output are expected first.
6097 if (NumOutputs || NumInputs) {
6098 unsigned NumExprs = NumOutputs + NumInputs;
6099 OpDecls.resize(NumExprs);
6100 Constraints.resize(NumExprs);
6101 for (unsigned i = 0; i < NumOutputs; ++i) {
6102 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
6103 Constraints[i] = OutputConstraints[i];
6105 for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
6106 OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6107 Constraints[j] = InputConstraints[i];
6111 // Build the IR assembly string.
6112 std::string AsmStringIR;
6113 raw_string_ostream OS(AsmStringIR);
6114 StringRef ASMString =
6115 SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
6116 const char *AsmStart = ASMString.begin();
6117 const char *AsmEnd = ASMString.end();
6118 array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
6119 for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) {
6120 const AsmRewrite &AR = *it;
6121 // Check if this has already been covered by another rewrite...
6124 AsmRewriteKind Kind = AR.Kind;
6126 const char *Loc = AR.Loc.getPointer();
6127 assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
6129 // Emit everything up to the immediate/expression.
6130 if (unsigned Len = Loc - AsmStart)
6131 OS << StringRef(AsmStart, Len);
6133 // Skip the original expression.
6134 if (Kind == AOK_Skip) {
6135 AsmStart = Loc + AR.Len;
6139 unsigned AdditionalSkip = 0;
6140 // Rewrite expressions in $N notation.
6145 assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
6146 if (AR.IntelExp.NeedBracs)
6148 if (AR.IntelExp.hasBaseReg())
6149 OS << AR.IntelExp.BaseReg;
6150 if (AR.IntelExp.hasIndexReg())
6151 OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
6152 << AR.IntelExp.IndexReg;
6153 if (AR.IntelExp.Scale > 1)
6154 OS << " * $$" << AR.IntelExp.Scale;
6155 if (AR.IntelExp.hasOffset()) {
6156 if (AR.IntelExp.hasRegs())
6158 // Fuse this rewrite with a rewrite of the offset name, if present.
6159 StringRef OffsetName = AR.IntelExp.OffsetName;
6160 SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
6161 size_t OffsetLen = OffsetName.size();
6162 auto rewrite_it = std::find_if(
6163 it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
6164 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6165 (FusingAR.Kind == AOK_Input ||
6166 FusingAR.Kind == AOK_CallInput);
6168 if (rewrite_it == AsmStrRewrites.end()) {
6169 OS << "offset " << OffsetName;
6170 } else if (rewrite_it->Kind == AOK_CallInput) {
6171 OS << "${" << InputIdx++ << ":P}";
6172 rewrite_it->Done = true;
6174 OS << '$' << InputIdx++;
6175 rewrite_it->Done = true;
6178 if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
6179 OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
6180 if (AR.IntelExp.NeedBracs)
6184 OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
6187 if (AR.IntelExpRestricted)
6188 OS << "${" << InputIdx++ << ":P}";
6190 OS << '$' << InputIdx++;
6193 OS << "${" << InputIdx++ << ":P}";
6196 if (AR.IntelExpRestricted)
6197 OS << "${" << OutputIdx++ << ":P}";
6199 OS << '$' << OutputIdx++;
6201 case AOK_SizeDirective:
6204 case 8: OS << "byte ptr "; break;
6205 case 16: OS << "word ptr "; break;
6206 case 32: OS << "dword ptr "; break;
6207 case 64: OS << "qword ptr "; break;
6208 case 80: OS << "xword ptr "; break;
6209 case 128: OS << "xmmword ptr "; break;
6210 case 256: OS << "ymmword ptr "; break;
6217 // MS alignment directives are measured in bytes. If the native assembler
6218 // measures alignment in bytes, we can pass it straight through.
6220 if (getContext().getAsmInfo()->getAlignmentIsInBytes())
6223 // Alignment is in log2 form, so print that instead and skip the original
6225 unsigned Val = AR.Val;
6227 assert(Val < 10 && "Expected alignment less then 2^10.");
6228 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6234 case AOK_EndOfStatement:
6239 // Skip the original expression.
6240 AsmStart = Loc + AR.Len + AdditionalSkip;
6243 // Emit the remainder of the asm string.
6244 if (AsmStart != AsmEnd)
6245 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6247 AsmString = OS.str();
6251 bool HLASMAsmParser::parseAsHLASMLabel(ParseStatementInfo &Info,
6252 MCAsmParserSemaCallback *SI) {
6253 AsmToken LabelTok = getTok();
6254 SMLoc LabelLoc = LabelTok.getLoc();
6257 if (parseIdentifier(LabelVal))
6258 return Error(LabelLoc, "The HLASM Label has to be an Identifier");
6260 // We have validated whether the token is an Identifier.
6261 // Now we have to validate whether the token is a
6262 // valid HLASM Label.
6263 if (!getTargetParser().isLabel(LabelTok) || checkForValidSection())
6266 // Lex leading spaces to get to the next operand.
6269 // We shouldn't emit the label if there is nothing else after the label.
6270 // i.e asm("<token>\n")
6271 if (getTok().is(AsmToken::EndOfStatement))
6272 return Error(LabelLoc,
6273 "Cannot have just a label for an HLASM inline asm statement");
6275 MCSymbol *Sym = getContext().getOrCreateSymbol(
6276 getContext().getAsmInfo()->shouldEmitLabelsInUpperCase()
6280 getTargetParser().doBeforeLabelEmit(Sym, LabelLoc);
6283 Out.emitLabel(Sym, LabelLoc);
6285 // If we are generating dwarf for assembly source files then gather the
6286 // info to make a dwarf label entry for this label if needed.
6287 if (enabledGenDwarfForAssembly())
6288 MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
6291 getTargetParser().onLabelParsed(Sym);
6296 bool HLASMAsmParser::parseAsMachineInstruction(ParseStatementInfo &Info,
6297 MCAsmParserSemaCallback *SI) {
6298 AsmToken OperationEntryTok = Lexer.getTok();
6299 SMLoc OperationEntryLoc = OperationEntryTok.getLoc();
6300 StringRef OperationEntryVal;
6302 // Attempt to parse the first token as an Identifier
6303 if (parseIdentifier(OperationEntryVal))
6304 return Error(OperationEntryLoc, "unexpected token at start of statement");
6306 // Once we've parsed the operation entry successfully, lex
6307 // any spaces to get to the OperandEntries.
6310 return parseAndMatchAndEmitTargetInstruction(
6311 Info, OperationEntryVal, OperationEntryTok, OperationEntryLoc);
6314 bool HLASMAsmParser::parseStatement(ParseStatementInfo &Info,
6315 MCAsmParserSemaCallback *SI) {
6316 assert(!hasPendingError() && "parseStatement started with pending error");
6318 // Should the first token be interpreted as a HLASM Label.
6319 bool ShouldParseAsHLASMLabel = false;
6321 // If a Name Entry exists, it should occur at the very
6322 // start of the string. In this case, we should parse the
6323 // first non-space token as a Label.
6324 // If the Name entry is missing (i.e. there's some other
6325 // token), then we attempt to parse the first non-space
6326 // token as a Machine Instruction.
6327 if (getTok().isNot(AsmToken::Space))
6328 ShouldParseAsHLASMLabel = true;
6330 // If we have an EndOfStatement (which includes the target's comment
6331 // string) we can appropriately lex it early on)
6332 if (Lexer.is(AsmToken::EndOfStatement)) {
6333 // if this is a line comment we can drop it safely
6334 if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
6335 getTok().getString().front() == '\n')
6341 // We have established how to parse the inline asm statement.
6342 // Now we can safely lex any leading spaces to get to the
6346 // If we see a new line or carriage return as the first operand,
6347 // after lexing leading spaces, emit the new line and lex the
6348 // EndOfStatement token.
6349 if (Lexer.is(AsmToken::EndOfStatement)) {
6350 if (getTok().getString().front() == '\n' ||
6351 getTok().getString().front() == '\r') {
6358 // Handle the label first if we have to before processing the rest
6359 // of the tokens as a machine instruction.
6360 if (ShouldParseAsHLASMLabel) {
6361 // If there were any errors while handling and emitting the label,
6363 if (parseAsHLASMLabel(Info, SI)) {
6364 // If we know we've failed in parsing, simply eat until end of the
6365 // statement. This ensures that we don't process any other statements.
6366 eatToEndOfStatement();
6371 return parseAsMachineInstruction(Info, SI);
6375 namespace MCParserUtils {
6377 /// Returns whether the given symbol is used anywhere in the given expression,
6378 /// or subexpressions.
6379 static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
6380 switch (Value->getKind()) {
6381 case MCExpr::Binary: {
6382 const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
6383 return isSymbolUsedInExpression(Sym, BE->getLHS()) ||
6384 isSymbolUsedInExpression(Sym, BE->getRHS());
6386 case MCExpr::Target:
6387 case MCExpr::Constant:
6389 case MCExpr::SymbolRef: {
6391 static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
6392 if (S.isVariable() && !S.isWeakExternal())
6393 return isSymbolUsedInExpression(Sym, S.getVariableValue());
6397 return isSymbolUsedInExpression(
6398 Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
6401 llvm_unreachable("Unknown expr kind!");
6404 bool parseAssignmentExpression(StringRef Name, bool allow_redef,
6405 MCAsmParser &Parser, MCSymbol *&Sym,
6406 const MCExpr *&Value) {
6408 // FIXME: Use better location, we should use proper tokens.
6409 SMLoc EqualLoc = Parser.getTok().getLoc();
6410 if (Parser.parseExpression(Value))
6411 return Parser.TokError("missing expression");
6413 // Note: we don't count b as used in "a = b". This is to allow
6417 if (Parser.parseEOL())
6420 // Validate that the LHS is allowed to be a variable (either it has not been
6421 // used as a symbol, or it is an absolute symbol).
6422 Sym = Parser.getContext().lookupSymbol(Name);
6424 // Diagnose assignment to a label.
6426 // FIXME: Diagnostics. Note the location of the definition as a label.
6427 // FIXME: Diagnose assignment to protected identifier (e.g., register name).
6428 if (isSymbolUsedInExpression(Sym, Value))
6429 return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'");
6430 else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() &&
6432 ; // Allow redefinitions of undefined symbols only used in directives.
6433 else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
6434 ; // Allow redefinitions of variables that haven't yet been used.
6435 else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
6436 return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
6437 else if (!Sym->isVariable())
6438 return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'");
6439 else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
6440 return Parser.Error(EqualLoc,
6441 "invalid reassignment of non-absolute variable '" +
6443 } else if (Name == ".") {
6444 Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
6447 Sym = Parser.getContext().getOrCreateSymbol(Name);
6449 Sym->setRedefinable(allow_redef);
6454 } // end namespace MCParserUtils
6455 } // end namespace llvm
6457 /// Create an MCAsmParser instance.
6458 MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
6459 MCStreamer &Out, const MCAsmInfo &MAI,
6461 if (C.getTargetTriple().isSystemZ() && C.getTargetTriple().isOSzOS())
6462 return new HLASMAsmParser(SM, C, Out, MAI, CB);
6464 return new AsmParser(SM, C, Out, MAI, CB);