LLVM 17.0.0git
AsmParser.cpp
Go to the documentation of this file.
1//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This class implements a parser for assembly files similar to gas syntax.
10//
11//===----------------------------------------------------------------------===//
12
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"
21#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/ADT/Twine.h"
26#include "llvm/MC/MCAsmInfo.h"
27#include "llvm/MC/MCCodeView.h"
28#include "llvm/MC/MCContext.h"
30#include "llvm/MC/MCDwarf.h"
31#include "llvm/MC/MCExpr.h"
33#include "llvm/MC/MCInstrDesc.h"
34#include "llvm/MC/MCInstrInfo.h"
44#include "llvm/MC/MCSection.h"
45#include "llvm/MC/MCStreamer.h"
46#include "llvm/MC/MCSymbol.h"
48#include "llvm/MC/MCValue.h"
52#include "llvm/Support/MD5.h"
55#include "llvm/Support/SMLoc.h"
58#include <algorithm>
59#include <cassert>
60#include <cctype>
61#include <climits>
62#include <cstddef>
63#include <cstdint>
64#include <deque>
65#include <memory>
66#include <optional>
67#include <sstream>
68#include <string>
69#include <tuple>
70#include <utility>
71#include <vector>
72
73using namespace llvm;
74
76
77namespace {
78
79/// Helper types for tracking macro definitions.
80typedef std::vector<AsmToken> MCAsmMacroArgument;
81typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
82
83/// Helper class for storing information about an active macro
84/// instantiation.
85struct MacroInstantiation {
86 /// The location of the instantiation.
87 SMLoc InstantiationLoc;
88
89 /// The buffer where parsing should resume upon instantiation completion.
90 unsigned ExitBuffer;
91
92 /// The location where parsing should resume upon instantiation completion.
93 SMLoc ExitLoc;
94
95 /// The depth of TheCondStack at the start of the instantiation.
96 size_t CondStackDepth;
97};
98
99struct ParseStatementInfo {
100 /// The parsed operands from the last parsed statement.
102
103 /// The opcode from the last parsed instruction.
104 unsigned Opcode = ~0U;
105
106 /// Was there an error parsing the inline assembly?
107 bool ParseError = false;
108
109 SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
110
111 ParseStatementInfo() = delete;
112 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
113 : AsmRewrites(rewrites) {}
114};
115
116/// The concrete assembly parser instance.
117class AsmParser : public MCAsmParser {
118private:
119 AsmLexer Lexer;
120 MCContext &Ctx;
121 MCStreamer &Out;
122 const MCAsmInfo &MAI;
124 SourceMgr::DiagHandlerTy SavedDiagHandler;
125 void *SavedDiagContext;
126 std::unique_ptr<MCAsmParserExtension> PlatformParser;
127 SMLoc StartTokLoc;
128
129 /// This is the current buffer index we're lexing from as managed by the
130 /// SourceMgr object.
131 unsigned CurBuffer;
132
133 AsmCond TheCondState;
134 std::vector<AsmCond> TheCondStack;
135
136 /// maps directive names to handler methods in parser
137 /// extensions. Extensions register themselves in this map by calling
138 /// addDirectiveHandler.
139 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
140
141 /// Stack of active macro instantiations.
142 std::vector<MacroInstantiation*> ActiveMacros;
143
144 /// List of bodies of anonymous macros.
145 std::deque<MCAsmMacro> MacroLikeBodies;
146
147 /// Boolean tracking whether macro substitution is enabled.
148 unsigned MacrosEnabledFlag : 1;
149
150 /// Keeps track of how many .macro's have been instantiated.
151 unsigned NumOfMacroInstantiations;
152
153 /// The values from the last parsed cpp hash file line comment if any.
154 struct CppHashInfoTy {
156 int64_t LineNumber;
157 SMLoc Loc;
158 unsigned Buf;
159 CppHashInfoTy() : LineNumber(0), Buf(0) {}
160 };
161 CppHashInfoTy CppHashInfo;
162
163 /// The filename from the first cpp hash file line comment, if any.
164 StringRef FirstCppHashFilename;
165
166 /// List of forward directional labels for diagnosis at the end.
168
169 SmallSet<StringRef, 2> LTODiscardSymbols;
170
171 /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
172 unsigned AssemblerDialect = ~0U;
173
174 /// is Darwin compatibility enabled?
175 bool IsDarwin = false;
176
177 /// Are we parsing ms-style inline assembly?
178 bool ParsingMSInlineAsm = false;
179
180 /// Did we already inform the user about inconsistent MD5 usage?
181 bool ReportedInconsistentMD5 = false;
182
183 // Is alt macro mode enabled.
184 bool AltMacroMode = false;
185
186protected:
187 virtual bool parseStatement(ParseStatementInfo &Info,
189
190 /// This routine uses the target specific ParseInstruction function to
191 /// parse an instruction into Operands, and then call the target specific
192 /// MatchAndEmit function to match and emit the instruction.
193 bool parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,
194 StringRef IDVal, AsmToken ID,
195 SMLoc IDLoc);
196
197 /// Should we emit DWARF describing this assembler source? (Returns false if
198 /// the source has .file directives, which means we don't want to generate
199 /// info describing the assembler source itself.)
200 bool enabledGenDwarfForAssembly();
201
202public:
203 AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
204 const MCAsmInfo &MAI, unsigned CB);
205 AsmParser(const AsmParser &) = delete;
206 AsmParser &operator=(const AsmParser &) = delete;
207 ~AsmParser() override;
208
209 bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
210
212 ExtensionDirectiveHandler Handler) override {
213 ExtensionDirectiveMap[Directive] = Handler;
214 }
215
216 void addAliasForDirective(StringRef Directive, StringRef Alias) override {
217 DirectiveKindMap[Directive.lower()] = DirectiveKindMap[Alias.lower()];
218 }
219
220 /// @name MCAsmParser Interface
221 /// {
222
223 SourceMgr &getSourceManager() override { return SrcMgr; }
224 MCAsmLexer &getLexer() override { return Lexer; }
225 MCContext &getContext() override { return Ctx; }
226 MCStreamer &getStreamer() override { return Out; }
227
228 CodeViewContext &getCVContext() { return Ctx.getCVContext(); }
229
230 unsigned getAssemblerDialect() override {
231 if (AssemblerDialect == ~0U)
232 return MAI.getAssemblerDialect();
233 else
234 return AssemblerDialect;
235 }
236 void setAssemblerDialect(unsigned i) override {
237 AssemblerDialect = i;
238 }
239
240 void Note(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) override;
241 bool Warning(SMLoc L, const Twine &Msg,
242 SMRange Range = std::nullopt) override;
243 bool printError(SMLoc L, const Twine &Msg,
244 SMRange Range = std::nullopt) override;
245
246 const AsmToken &Lex() override;
247
248 void setParsingMSInlineAsm(bool V) override {
249 ParsingMSInlineAsm = V;
250 // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
251 // hex integer literals.
252 Lexer.setLexMasmIntegers(V);
253 }
254 bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
255
256 bool discardLTOSymbol(StringRef Name) const override {
257 return LTODiscardSymbols.contains(Name);
258 }
259
260 bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs,
261 unsigned &NumInputs,
262 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
263 SmallVectorImpl<std::string> &Constraints,
265 const MCInstrInfo *MII, const MCInstPrinter *IP,
266 MCAsmParserSemaCallback &SI) override;
267
268 bool parseExpression(const MCExpr *&Res);
269 bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
270 bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
271 AsmTypeInfo *TypeInfo) override;
272 bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
273 bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
274 SMLoc &EndLoc) override;
275 bool parseAbsoluteExpression(int64_t &Res) override;
276
277 /// Parse a floating point expression using the float \p Semantics
278 /// and set \p Res to the value.
279 bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
280
281 /// Parse an identifier or string (as a quoted identifier)
282 /// and set \p Res to the identifier contents.
283 bool parseIdentifier(StringRef &Res) override;
284 void eatToEndOfStatement() override;
285
286 bool checkForValidSection() override;
287
288 /// }
289
290private:
291 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
292 bool parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo = true);
293
294 void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
296 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
298 ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable,
299 SMLoc L);
300
301 /// Are macros enabled in the parser?
302 bool areMacrosEnabled() {return MacrosEnabledFlag;}
303
304 /// Control a flag in the parser that enables or disables macros.
305 void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
306
307 /// Are we inside a macro instantiation?
308 bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
309
310 /// Handle entry to macro instantiation.
311 ///
312 /// \param M The macro.
313 /// \param NameLoc Instantiation location.
314 bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
315
316 /// Handle exit from macro instantiation.
317 void handleMacroExit();
318
319 /// Extract AsmTokens for a macro argument.
320 bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
321
322 /// Parse all macro arguments for a given macro.
323 bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
324
325 void printMacroInstantiations();
326 void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
327 SMRange Range = std::nullopt) const {
329 SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
330 }
331 static void DiagHandler(const SMDiagnostic &Diag, void *Context);
332
333 /// Enter the specified file. This returns true on failure.
334 bool enterIncludeFile(const std::string &Filename);
335
336 /// Process the specified file for the .incbin directive.
337 /// This returns true on failure.
338 bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,
339 const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());
340
341 /// Reset the current lexer position to that given by \p Loc. The
342 /// current token is not set; clients should ensure Lex() is called
343 /// subsequently.
344 ///
345 /// \param InBuffer If not 0, should be the known buffer id that contains the
346 /// location.
347 void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);
348
349 /// Parse up to the end of statement and a return the contents from the
350 /// current token until the end of the statement; the current token on exit
351 /// will be either the EndOfStatement or EOF.
353
354 /// Parse until the end of a statement or a comma is encountered,
355 /// return the contents from the current token up to the end or comma.
356 StringRef parseStringToComma();
357
358 enum class AssignmentKind {
359 Set,
360 Equiv,
361 Equal,
362 LTOSetConditional,
363 };
364
365 bool parseAssignment(StringRef Name, AssignmentKind Kind);
366
367 unsigned getBinOpPrecedence(AsmToken::TokenKind K,
369
370 bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
371 bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
372 bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
373
374 bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
375
376 bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);
377 bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);
378
379 // Generic (target and platform independent) directive parsing.
380 enum DirectiveKind {
381 DK_NO_DIRECTIVE, // Placeholder
382 DK_SET,
383 DK_EQU,
384 DK_EQUIV,
385 DK_ASCII,
386 DK_ASCIZ,
387 DK_STRING,
388 DK_BYTE,
389 DK_SHORT,
390 DK_RELOC,
391 DK_VALUE,
392 DK_2BYTE,
393 DK_LONG,
394 DK_INT,
395 DK_4BYTE,
396 DK_QUAD,
397 DK_8BYTE,
398 DK_OCTA,
399 DK_DC,
400 DK_DC_A,
401 DK_DC_B,
402 DK_DC_D,
403 DK_DC_L,
404 DK_DC_S,
405 DK_DC_W,
406 DK_DC_X,
407 DK_DCB,
408 DK_DCB_B,
409 DK_DCB_D,
410 DK_DCB_L,
411 DK_DCB_S,
412 DK_DCB_W,
413 DK_DCB_X,
414 DK_DS,
415 DK_DS_B,
416 DK_DS_D,
417 DK_DS_L,
418 DK_DS_P,
419 DK_DS_S,
420 DK_DS_W,
421 DK_DS_X,
422 DK_SINGLE,
423 DK_FLOAT,
424 DK_DOUBLE,
425 DK_ALIGN,
426 DK_ALIGN32,
427 DK_BALIGN,
428 DK_BALIGNW,
429 DK_BALIGNL,
430 DK_P2ALIGN,
431 DK_P2ALIGNW,
432 DK_P2ALIGNL,
433 DK_ORG,
434 DK_FILL,
435 DK_ENDR,
436 DK_BUNDLE_ALIGN_MODE,
437 DK_BUNDLE_LOCK,
438 DK_BUNDLE_UNLOCK,
439 DK_ZERO,
440 DK_EXTERN,
441 DK_GLOBL,
442 DK_GLOBAL,
443 DK_LAZY_REFERENCE,
444 DK_NO_DEAD_STRIP,
445 DK_SYMBOL_RESOLVER,
446 DK_PRIVATE_EXTERN,
447 DK_REFERENCE,
448 DK_WEAK_DEFINITION,
449 DK_WEAK_REFERENCE,
450 DK_WEAK_DEF_CAN_BE_HIDDEN,
451 DK_COLD,
452 DK_COMM,
453 DK_COMMON,
454 DK_LCOMM,
455 DK_ABORT,
456 DK_INCLUDE,
457 DK_INCBIN,
458 DK_CODE16,
459 DK_CODE16GCC,
460 DK_REPT,
461 DK_IRP,
462 DK_IRPC,
463 DK_IF,
464 DK_IFEQ,
465 DK_IFGE,
466 DK_IFGT,
467 DK_IFLE,
468 DK_IFLT,
469 DK_IFNE,
470 DK_IFB,
471 DK_IFNB,
472 DK_IFC,
473 DK_IFEQS,
474 DK_IFNC,
475 DK_IFNES,
476 DK_IFDEF,
477 DK_IFNDEF,
478 DK_IFNOTDEF,
479 DK_ELSEIF,
480 DK_ELSE,
481 DK_ENDIF,
482 DK_SPACE,
483 DK_SKIP,
484 DK_FILE,
485 DK_LINE,
486 DK_LOC,
487 DK_STABS,
488 DK_CV_FILE,
489 DK_CV_FUNC_ID,
490 DK_CV_INLINE_SITE_ID,
491 DK_CV_LOC,
492 DK_CV_LINETABLE,
493 DK_CV_INLINE_LINETABLE,
494 DK_CV_DEF_RANGE,
495 DK_CV_STRINGTABLE,
496 DK_CV_STRING,
497 DK_CV_FILECHECKSUMS,
498 DK_CV_FILECHECKSUM_OFFSET,
499 DK_CV_FPO_DATA,
500 DK_CFI_SECTIONS,
501 DK_CFI_STARTPROC,
502 DK_CFI_ENDPROC,
503 DK_CFI_DEF_CFA,
504 DK_CFI_DEF_CFA_OFFSET,
505 DK_CFI_ADJUST_CFA_OFFSET,
506 DK_CFI_DEF_CFA_REGISTER,
507 DK_CFI_LLVM_DEF_ASPACE_CFA,
508 DK_CFI_OFFSET,
509 DK_CFI_REL_OFFSET,
510 DK_CFI_PERSONALITY,
511 DK_CFI_LSDA,
512 DK_CFI_REMEMBER_STATE,
513 DK_CFI_RESTORE_STATE,
514 DK_CFI_SAME_VALUE,
515 DK_CFI_RESTORE,
516 DK_CFI_ESCAPE,
517 DK_CFI_RETURN_COLUMN,
518 DK_CFI_SIGNAL_FRAME,
519 DK_CFI_UNDEFINED,
520 DK_CFI_REGISTER,
521 DK_CFI_WINDOW_SAVE,
522 DK_CFI_B_KEY_FRAME,
523 DK_MACROS_ON,
524 DK_MACROS_OFF,
525 DK_ALTMACRO,
526 DK_NOALTMACRO,
527 DK_MACRO,
528 DK_EXITM,
529 DK_ENDM,
530 DK_ENDMACRO,
531 DK_PURGEM,
532 DK_SLEB128,
533 DK_ULEB128,
534 DK_ERR,
535 DK_ERROR,
536 DK_WARNING,
537 DK_PRINT,
538 DK_ADDRSIG,
539 DK_ADDRSIG_SYM,
540 DK_PSEUDO_PROBE,
541 DK_LTO_DISCARD,
542 DK_LTO_SET_CONDITIONAL,
543 DK_CFI_MTE_TAGGED_FRAME,
544 DK_MEMTAG,
545 DK_END
546 };
547
548 /// Maps directive name --> DirectiveKind enum, for
549 /// directives parsed by this class.
550 StringMap<DirectiveKind> DirectiveKindMap;
551
552 // Codeview def_range type parsing.
553 enum CVDefRangeType {
554 CVDR_DEFRANGE = 0, // Placeholder
555 CVDR_DEFRANGE_REGISTER,
556 CVDR_DEFRANGE_FRAMEPOINTER_REL,
557 CVDR_DEFRANGE_SUBFIELD_REGISTER,
558 CVDR_DEFRANGE_REGISTER_REL
559 };
560
561 /// Maps Codeview def_range types --> CVDefRangeType enum, for
562 /// Codeview def_range types parsed by this class.
563 StringMap<CVDefRangeType> CVDefRangeTypeMap;
564
565 // ".ascii", ".asciz", ".string"
566 bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
567 bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
568 bool parseDirectiveValue(StringRef IDVal,
569 unsigned Size); // ".byte", ".long", ...
570 bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ...
571 bool parseDirectiveRealValue(StringRef IDVal,
572 const fltSemantics &); // ".single", ...
573 bool parseDirectiveFill(); // ".fill"
574 bool parseDirectiveZero(); // ".zero"
575 // ".set", ".equ", ".equiv", ".lto_set_conditional"
576 bool parseDirectiveSet(StringRef IDVal, AssignmentKind Kind);
577 bool parseDirectiveOrg(); // ".org"
578 // ".align{,32}", ".p2align{,w,l}"
579 bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);
580
581 // ".file", ".line", ".loc", ".stabs"
582 bool parseDirectiveFile(SMLoc DirectiveLoc);
583 bool parseDirectiveLine();
584 bool parseDirectiveLoc();
585 bool parseDirectiveStabs();
586
587 // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
588 // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
589 bool parseDirectiveCVFile();
590 bool parseDirectiveCVFuncId();
591 bool parseDirectiveCVInlineSiteId();
592 bool parseDirectiveCVLoc();
593 bool parseDirectiveCVLinetable();
594 bool parseDirectiveCVInlineLinetable();
595 bool parseDirectiveCVDefRange();
596 bool parseDirectiveCVString();
597 bool parseDirectiveCVStringTable();
598 bool parseDirectiveCVFileChecksums();
599 bool parseDirectiveCVFileChecksumOffset();
600 bool parseDirectiveCVFPOData();
601
602 // .cfi directives
603 bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
604 bool parseDirectiveCFIWindowSave();
605 bool parseDirectiveCFISections();
606 bool parseDirectiveCFIStartProc();
607 bool parseDirectiveCFIEndProc();
608 bool parseDirectiveCFIDefCfaOffset();
609 bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
610 bool parseDirectiveCFIAdjustCfaOffset();
611 bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
612 bool parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc);
613 bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
614 bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
615 bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
616 bool parseDirectiveCFIRememberState();
617 bool parseDirectiveCFIRestoreState();
618 bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
619 bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
620 bool parseDirectiveCFIEscape();
621 bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
622 bool parseDirectiveCFISignalFrame();
623 bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
624
625 // macro directives
626 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
627 bool parseDirectiveExitMacro(StringRef Directive);
628 bool parseDirectiveEndMacro(StringRef Directive);
629 bool parseDirectiveMacro(SMLoc DirectiveLoc);
630 bool parseDirectiveMacrosOnOff(StringRef Directive);
631 // alternate macro mode directives
632 bool parseDirectiveAltmacro(StringRef Directive);
633 // ".bundle_align_mode"
634 bool parseDirectiveBundleAlignMode();
635 // ".bundle_lock"
636 bool parseDirectiveBundleLock();
637 // ".bundle_unlock"
638 bool parseDirectiveBundleUnlock();
639
640 // ".space", ".skip"
641 bool parseDirectiveSpace(StringRef IDVal);
642
643 // ".dcb"
644 bool parseDirectiveDCB(StringRef IDVal, unsigned Size);
645 bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &);
646 // ".ds"
647 bool parseDirectiveDS(StringRef IDVal, unsigned Size);
648
649 // .sleb128 (Signed=true) and .uleb128 (Signed=false)
650 bool parseDirectiveLEB128(bool Signed);
651
652 /// Parse a directive like ".globl" which
653 /// accepts a single symbol (which should be a label or an external).
654 bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
655
656 bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
657
658 bool parseDirectiveAbort(); // ".abort"
659 bool parseDirectiveInclude(); // ".include"
660 bool parseDirectiveIncbin(); // ".incbin"
661
662 // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"
663 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
664 // ".ifb" or ".ifnb", depending on ExpectBlank.
665 bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
666 // ".ifc" or ".ifnc", depending on ExpectEqual.
667 bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
668 // ".ifeqs" or ".ifnes", depending on ExpectEqual.
669 bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);
670 // ".ifdef" or ".ifndef", depending on expect_defined
671 bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
672 bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
673 bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
674 bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
675 bool parseEscapedString(std::string &Data) override;
676 bool parseAngleBracketString(std::string &Data) override;
677
678 const MCExpr *applyModifierToExpr(const MCExpr *E,
680
681 // Macro-like directives
682 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
683 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
685 bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);
686 bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
687 bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
688 bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
689
690 // "_emit" or "__emit"
691 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
692 size_t Len);
693
694 // "align"
695 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
696
697 // "end"
698 bool parseDirectiveEnd(SMLoc DirectiveLoc);
699
700 // ".err" or ".error"
701 bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
702
703 // ".warning"
704 bool parseDirectiveWarning(SMLoc DirectiveLoc);
705
706 // .print <double-quotes-string>
707 bool parseDirectivePrint(SMLoc DirectiveLoc);
708
709 // .pseudoprobe
710 bool parseDirectivePseudoProbe();
711
712 // ".lto_discard"
713 bool parseDirectiveLTODiscard();
714
715 // Directives to support address-significance tables.
716 bool parseDirectiveAddrsig();
717 bool parseDirectiveAddrsigSym();
718
719 void initializeDirectiveKindMap();
720 void initializeCVDefRangeTypeMap();
721};
722
723class HLASMAsmParser final : public AsmParser {
724private:
725 MCAsmLexer &Lexer;
726 MCStreamer &Out;
727
728 void lexLeadingSpaces() {
729 while (Lexer.is(AsmToken::Space))
730 Lexer.Lex();
731 }
732
733 bool parseAsHLASMLabel(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI);
734 bool parseAsMachineInstruction(ParseStatementInfo &Info,
736
737public:
738 HLASMAsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
739 const MCAsmInfo &MAI, unsigned CB = 0)
740 : AsmParser(SM, Ctx, Out, MAI, CB), Lexer(getLexer()), Out(Out) {
741 Lexer.setSkipSpace(false);
742 Lexer.setAllowHashInIdentifier(true);
743 Lexer.setLexHLASMIntegers(true);
744 Lexer.setLexHLASMStrings(true);
745 }
746
747 ~HLASMAsmParser() { Lexer.setSkipSpace(true); }
748
749 bool parseStatement(ParseStatementInfo &Info,
750 MCAsmParserSemaCallback *SI) override;
751};
752
753} // end anonymous namespace
754
755namespace llvm {
756
758
765
766} // end namespace llvm
767
768enum { DEFAULT_ADDRSPACE = 0 };
769
770AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
771 const MCAsmInfo &MAI, unsigned CB = 0)
772 : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
773 CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {
774 HadError = false;
775 // Save the old handler.
776 SavedDiagHandler = SrcMgr.getDiagHandler();
777 SavedDiagContext = SrcMgr.getDiagContext();
778 // Set our own handler which calls the saved handler.
780 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
781 // Make MCStreamer aware of the StartTokLoc for locations in diagnostics.
782 Out.setStartTokLocPtr(&StartTokLoc);
783
784 // Initialize the platform / file format parser.
785 switch (Ctx.getObjectFileType()) {
787 PlatformParser.reset(createCOFFAsmParser());
788 break;
790 PlatformParser.reset(createDarwinAsmParser());
791 IsDarwin = true;
792 break;
793 case MCContext::IsELF:
794 PlatformParser.reset(createELFAsmParser());
795 break;
797 PlatformParser.reset(createGOFFAsmParser());
798 break;
801 "Need to implement createSPIRVAsmParser for SPIRV format.");
802 break;
804 PlatformParser.reset(createWasmAsmParser());
805 break;
807 PlatformParser.reset(createXCOFFAsmParser());
808 break;
810 llvm_unreachable("DXContainer is not supported yet");
811 break;
812 }
813
814 PlatformParser->Initialize(*this);
815 initializeDirectiveKindMap();
816 initializeCVDefRangeTypeMap();
817
818 NumOfMacroInstantiations = 0;
819}
820
821AsmParser::~AsmParser() {
822 assert((HadError || ActiveMacros.empty()) &&
823 "Unexpected active macro instantiation!");
824
825 // Remove MCStreamer's reference to the parser SMLoc.
826 Out.setStartTokLocPtr(nullptr);
827 // Restore the saved diagnostics handler and context for use during
828 // finalization.
829 SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
830}
831
832void AsmParser::printMacroInstantiations() {
833 // Print the active macro instantiation stack.
834 for (std::vector<MacroInstantiation *>::const_reverse_iterator
835 it = ActiveMacros.rbegin(),
836 ie = ActiveMacros.rend();
837 it != ie; ++it)
838 printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
839 "while in macro instantiation");
840}
841
842void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
843 printPendingErrors();
844 printMessage(L, SourceMgr::DK_Note, Msg, Range);
845 printMacroInstantiations();
846}
847
848bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
849 if(getTargetParser().getTargetOptions().MCNoWarn)
850 return false;
851 if (getTargetParser().getTargetOptions().MCFatalWarnings)
852 return Error(L, Msg, Range);
853 printMessage(L, SourceMgr::DK_Warning, Msg, Range);
854 printMacroInstantiations();
855 return false;
856}
857
858bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
859 HadError = true;
860 printMessage(L, SourceMgr::DK_Error, Msg, Range);
861 printMacroInstantiations();
862 return true;
863}
864
865bool AsmParser::enterIncludeFile(const std::string &Filename) {
866 std::string IncludedFile;
867 unsigned NewBuf =
868 SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
869 if (!NewBuf)
870 return true;
871
872 CurBuffer = NewBuf;
873 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
874 return false;
875}
876
877/// Process the specified .incbin file by searching for it in the include paths
878/// then just emitting the byte contents of the file to the streamer. This
879/// returns true on failure.
880bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
881 const MCExpr *Count, SMLoc Loc) {
882 std::string IncludedFile;
883 unsigned NewBuf =
884 SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
885 if (!NewBuf)
886 return true;
887
888 // Pick up the bytes from the file and emit them.
889 StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();
890 Bytes = Bytes.drop_front(Skip);
891 if (Count) {
892 int64_t Res;
893 if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
894 return Error(Loc, "expected absolute expression");
895 if (Res < 0)
896 return Warning(Loc, "negative count has no effect");
897 Bytes = Bytes.take_front(Res);
898 }
899 getStreamer().emitBytes(Bytes);
900 return false;
901}
902
903void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
904 CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
905 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
906 Loc.getPointer());
907}
908
909const AsmToken &AsmParser::Lex() {
910 if (Lexer.getTok().is(AsmToken::Error))
911 Error(Lexer.getErrLoc(), Lexer.getErr());
912
913 // if it's a end of statement with a comment in it
914 if (getTok().is(AsmToken::EndOfStatement)) {
915 // if this is a line comment output it.
916 if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
917 getTok().getString().front() != '\r' && MAI.preserveAsmComments())
918 Out.addExplicitComment(Twine(getTok().getString()));
919 }
920
921 const AsmToken *tok = &Lexer.Lex();
922
923 // Parse comments here to be deferred until end of next statement.
924 while (tok->is(AsmToken::Comment)) {
925 if (MAI.preserveAsmComments())
927 tok = &Lexer.Lex();
928 }
929
930 if (tok->is(AsmToken::Eof)) {
931 // If this is the end of an included file, pop the parent file off the
932 // include stack.
933 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
934 if (ParentIncludeLoc != SMLoc()) {
935 jumpToLoc(ParentIncludeLoc);
936 return Lex();
937 }
938 }
939
940 return *tok;
941}
942
943bool AsmParser::enabledGenDwarfForAssembly() {
944 // Check whether the user specified -g.
945 if (!getContext().getGenDwarfForAssembly())
946 return false;
947 // If we haven't encountered any .file directives (which would imply that
948 // the assembler source was produced with debug info already) then emit one
949 // describing the assembler source file itself.
950 if (getContext().getGenDwarfFileNumber() == 0) {
951 // Use the first #line directive for this, if any. It's preprocessed, so
952 // there is no checksum, and of course no source directive.
953 if (!FirstCppHashFilename.empty())
954 getContext().setMCLineTableRootFile(
955 /*CUID=*/0, getContext().getCompilationDir(), FirstCppHashFilename,
956 /*Cksum=*/std::nullopt, /*Source=*/std::nullopt);
957 const MCDwarfFile &RootFile =
958 getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
959 getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
960 /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
961 RootFile.Checksum, RootFile.Source));
962 }
963 return true;
964}
965
966bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
967 LTODiscardSymbols.clear();
968
969 // Create the initial section, if requested.
970 if (!NoInitialTextSection)
971 Out.initSections(false, getTargetParser().getSTI());
972
973 // Prime the lexer.
974 Lex();
975
976 HadError = false;
977 AsmCond StartingCondState = TheCondState;
978 SmallVector<AsmRewrite, 4> AsmStrRewrites;
979
980 // If we are generating dwarf for assembly source files save the initial text
981 // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't
982 // emitting any actual debug info yet and haven't had a chance to parse any
983 // embedded .file directives.)
984 if (getContext().getGenDwarfForAssembly()) {
985 MCSection *Sec = getStreamer().getCurrentSectionOnly();
986 if (!Sec->getBeginSymbol()) {
987 MCSymbol *SectionStartSym = getContext().createTempSymbol();
988 getStreamer().emitLabel(SectionStartSym);
989 Sec->setBeginSymbol(SectionStartSym);
990 }
991 bool InsertResult = getContext().addGenDwarfSection(Sec);
992 assert(InsertResult && ".text section should not have debug info yet");
993 (void)InsertResult;
994 }
995
996 getTargetParser().onBeginOfFile();
997
998 // While we have input, parse each statement.
999 while (Lexer.isNot(AsmToken::Eof)) {
1000 ParseStatementInfo Info(&AsmStrRewrites);
1001 bool Parsed = parseStatement(Info, nullptr);
1002
1003 // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
1004 // for printing ErrMsg via Lex() only if no (presumably better) parser error
1005 // exists.
1006 if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
1007 Lex();
1008 }
1009
1010 // parseStatement returned true so may need to emit an error.
1011 printPendingErrors();
1012
1013 // Skipping to the next line if needed.
1014 if (Parsed && !getLexer().isAtStartOfStatement())
1015 eatToEndOfStatement();
1016 }
1017
1018 getTargetParser().onEndOfFile();
1019 printPendingErrors();
1020
1021 // All errors should have been emitted.
1022 assert(!hasPendingError() && "unexpected error from parseStatement");
1023
1024 getTargetParser().flushPendingInstructions(getStreamer());
1025
1026 if (TheCondState.TheCond != StartingCondState.TheCond ||
1027 TheCondState.Ignore != StartingCondState.Ignore)
1028 printError(getTok().getLoc(), "unmatched .ifs or .elses");
1029 // Check to see there are no empty DwarfFile slots.
1030 const auto &LineTables = getContext().getMCDwarfLineTables();
1031 if (!LineTables.empty()) {
1032 unsigned Index = 0;
1033 for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {
1034 if (File.Name.empty() && Index != 0)
1035 printError(getTok().getLoc(), "unassigned file number: " +
1036 Twine(Index) +
1037 " for .file directives");
1038 ++Index;
1039 }
1040 }
1041
1042 // Check to see that all assembler local symbols were actually defined.
1043 // Targets that don't do subsections via symbols may not want this, though,
1044 // so conservatively exclude them. Only do this if we're finalizing, though,
1045 // as otherwise we won't necessarilly have seen everything yet.
1046 if (!NoFinalize) {
1047 if (MAI.hasSubsectionsViaSymbols()) {
1048 for (const auto &TableEntry : getContext().getSymbols()) {
1049 MCSymbol *Sym = TableEntry.getValue();
1050 // Variable symbols may not be marked as defined, so check those
1051 // explicitly. If we know it's a variable, we have a definition for
1052 // the purposes of this check.
1053 if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
1054 // FIXME: We would really like to refer back to where the symbol was
1055 // first referenced for a source location. We need to add something
1056 // to track that. Currently, we just point to the end of the file.
1057 printError(getTok().getLoc(), "assembler local symbol '" +
1058 Sym->getName() + "' not defined");
1059 }
1060 }
1061
1062 // Temporary symbols like the ones for directional jumps don't go in the
1063 // symbol table. They also need to be diagnosed in all (final) cases.
1064 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1065 if (std::get<2>(LocSym)->isUndefined()) {
1066 // Reset the state of any "# line file" directives we've seen to the
1067 // context as it was at the diagnostic site.
1068 CppHashInfo = std::get<1>(LocSym);
1069 printError(std::get<0>(LocSym), "directional label undefined");
1070 }
1071 }
1072 }
1073 // Finalize the output stream if there are no errors and if the client wants
1074 // us to.
1075 if (!HadError && !NoFinalize) {
1076 if (auto *TS = Out.getTargetStreamer())
1077 TS->emitConstantPools();
1078
1079 Out.finish(Lexer.getLoc());
1080 }
1081
1082 return HadError || getContext().hadError();
1083}
1084
1085bool AsmParser::checkForValidSection() {
1086 if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
1087 Out.initSections(false, getTargetParser().getSTI());
1088 return Error(getTok().getLoc(),
1089 "expected section directive before assembly directive");
1090 }
1091 return false;
1092}
1093
1094/// Throw away the rest of the line for testing purposes.
1095void AsmParser::eatToEndOfStatement() {
1096 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
1097 Lexer.Lex();
1098
1099 // Eat EOL.
1100 if (Lexer.is(AsmToken::EndOfStatement))
1101 Lexer.Lex();
1102}
1103
1104StringRef AsmParser::parseStringToEndOfStatement() {
1105 const char *Start = getTok().getLoc().getPointer();
1106
1107 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
1108 Lexer.Lex();
1109
1110 const char *End = getTok().getLoc().getPointer();
1111 return StringRef(Start, End - Start);
1112}
1113
1114StringRef AsmParser::parseStringToComma() {
1115 const char *Start = getTok().getLoc().getPointer();
1116
1117 while (Lexer.isNot(AsmToken::EndOfStatement) &&
1118 Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof))
1119 Lexer.Lex();
1120
1121 const char *End = getTok().getLoc().getPointer();
1122 return StringRef(Start, End - Start);
1123}
1124
1125/// Parse a paren expression and return it.
1126/// NOTE: This assumes the leading '(' has already been consumed.
1127///
1128/// parenexpr ::= expr)
1129///
1130bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1131 if (parseExpression(Res))
1132 return true;
1133 EndLoc = Lexer.getTok().getEndLoc();
1134 return parseRParen();
1135}
1136
1137/// Parse a bracket expression and return it.
1138/// NOTE: This assumes the leading '[' has already been consumed.
1139///
1140/// bracketexpr ::= expr]
1141///
1142bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1143 if (parseExpression(Res))
1144 return true;
1145 EndLoc = getTok().getEndLoc();
1146 if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
1147 return true;
1148 return false;
1149}
1150
1151/// Parse a primary expression and return it.
1152/// primaryexpr ::= (parenexpr
1153/// primaryexpr ::= symbol
1154/// primaryexpr ::= number
1155/// primaryexpr ::= '.'
1156/// primaryexpr ::= ~,+,- primaryexpr
1157bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
1158 AsmTypeInfo *TypeInfo) {
1159 SMLoc FirstTokenLoc = getLexer().getLoc();
1160 AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
1161 switch (FirstTokenKind) {
1162 default:
1163 return TokError("unknown token in expression");
1164 // If we have an error assume that we've already handled it.
1165 case AsmToken::Error:
1166 return true;
1167 case AsmToken::Exclaim:
1168 Lex(); // Eat the operator.
1169 if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
1170 return true;
1171 Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
1172 return false;
1173 case AsmToken::Dollar:
1174 case AsmToken::Star:
1175 case AsmToken::At:
1176 case AsmToken::String:
1177 case AsmToken::Identifier: {
1179 if (parseIdentifier(Identifier)) {
1180 // We may have failed but '$'|'*' may be a valid token in context of
1181 // the current PC.
1182 if (getTok().is(AsmToken::Dollar) || getTok().is(AsmToken::Star)) {
1183 bool ShouldGenerateTempSymbol = false;
1184 if ((getTok().is(AsmToken::Dollar) && MAI.getDollarIsPC()) ||
1185 (getTok().is(AsmToken::Star) && MAI.getStarIsPC()))
1186 ShouldGenerateTempSymbol = true;
1187
1188 if (!ShouldGenerateTempSymbol)
1189 return Error(FirstTokenLoc, "invalid token in expression");
1190
1191 // Eat the '$'|'*' token.
1192 Lex();
1193 // This is either a '$'|'*' reference, which references the current PC.
1194 // Emit a temporary label to the streamer and refer to it.
1195 MCSymbol *Sym = Ctx.createTempSymbol();
1196 Out.emitLabel(Sym);
1198 getContext());
1199 EndLoc = FirstTokenLoc;
1200 return false;
1201 }
1202 }
1203 // Parse symbol variant
1204 std::pair<StringRef, StringRef> Split;
1205 if (!MAI.useParensForSymbolVariant()) {
1206 if (FirstTokenKind == AsmToken::String) {
1207 if (Lexer.is(AsmToken::At)) {
1208 Lex(); // eat @
1209 SMLoc AtLoc = getLexer().getLoc();
1210 StringRef VName;
1211 if (parseIdentifier(VName))
1212 return Error(AtLoc, "expected symbol variant after '@'");
1213
1214 Split = std::make_pair(Identifier, VName);
1215 }
1216 } else {
1217 Split = Identifier.split('@');
1218 }
1219 } else if (Lexer.is(AsmToken::LParen)) {
1220 Lex(); // eat '('.
1221 StringRef VName;
1222 parseIdentifier(VName);
1223 if (parseRParen())
1224 return true;
1225 Split = std::make_pair(Identifier, VName);
1226 }
1227
1228 EndLoc = SMLoc::getFromPointer(Identifier.end());
1229
1230 // This is a symbol reference.
1232 if (SymbolName.empty())
1233 return Error(getLexer().getLoc(), "expected a symbol reference");
1234
1236
1237 // Lookup the symbol variant if used.
1238 if (!Split.second.empty()) {
1240 if (Variant != MCSymbolRefExpr::VK_Invalid) {
1241 SymbolName = Split.first;
1242 } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
1244 } else {
1245 return Error(SMLoc::getFromPointer(Split.second.begin()),
1246 "invalid variant '" + Split.second + "'");
1247 }
1248 }
1249
1250 MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
1251 if (!Sym)
1252 Sym = getContext().getOrCreateSymbol(
1253 MAI.shouldEmitLabelsInUpperCase() ? SymbolName.upper() : SymbolName);
1254
1255 // If this is an absolute variable reference, substitute it now to preserve
1256 // semantics in the face of reassignment.
1257 if (Sym->isVariable()) {
1258 auto V = Sym->getVariableValue(/*SetUsed*/ false);
1259 bool DoInline = isa<MCConstantExpr>(V) && !Variant;
1260 if (auto TV = dyn_cast<MCTargetExpr>(V))
1261 DoInline = TV->inlineAssignedExpr();
1262 if (DoInline) {
1263 if (Variant)
1264 return Error(EndLoc, "unexpected modifier on variable reference");
1265 Res = Sym->getVariableValue(/*SetUsed*/ false);
1266 return false;
1267 }
1268 }
1269
1270 // Otherwise create a symbol ref.
1271 Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
1272 return false;
1273 }
1274 case AsmToken::BigNum:
1275 return TokError("literal value out of range for directive");
1276 case AsmToken::Integer: {
1277 SMLoc Loc = getTok().getLoc();
1278 int64_t IntVal = getTok().getIntVal();
1279 Res = MCConstantExpr::create(IntVal, getContext());
1280 EndLoc = Lexer.getTok().getEndLoc();
1281 Lex(); // Eat token.
1282 // Look for 'b' or 'f' following an Integer as a directional label
1283 if (Lexer.getKind() == AsmToken::Identifier) {
1284 StringRef IDVal = getTok().getString();
1285 // Lookup the symbol variant if used.
1286 std::pair<StringRef, StringRef> Split = IDVal.split('@');
1288 if (Split.first.size() != IDVal.size()) {
1290 if (Variant == MCSymbolRefExpr::VK_Invalid)
1291 return TokError("invalid variant '" + Split.second + "'");
1292 IDVal = Split.first;
1293 }
1294 if (IDVal == "f" || IDVal == "b") {
1295 MCSymbol *Sym =
1296 Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
1297 Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
1298 if (IDVal == "b" && Sym->isUndefined())
1299 return Error(Loc, "directional label undefined");
1300 DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
1301 EndLoc = Lexer.getTok().getEndLoc();
1302 Lex(); // Eat identifier.
1303 }
1304 }
1305 return false;
1306 }
1307 case AsmToken::Real: {
1308 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1309 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
1310 Res = MCConstantExpr::create(IntVal, getContext());
1311 EndLoc = Lexer.getTok().getEndLoc();
1312 Lex(); // Eat token.
1313 return false;
1314 }
1315 case AsmToken::Dot: {
1316 if (!MAI.getDotIsPC())
1317 return TokError("cannot use . as current PC");
1318
1319 // This is a '.' reference, which references the current PC. Emit a
1320 // temporary label to the streamer and refer to it.
1321 MCSymbol *Sym = Ctx.createTempSymbol();
1322 Out.emitLabel(Sym);
1324 EndLoc = Lexer.getTok().getEndLoc();
1325 Lex(); // Eat identifier.
1326 return false;
1327 }
1328 case AsmToken::LParen:
1329 Lex(); // Eat the '('.
1330 return parseParenExpr(Res, EndLoc);
1331 case AsmToken::LBrac:
1332 if (!PlatformParser->HasBracketExpressions())
1333 return TokError("brackets expression not supported on this target");
1334 Lex(); // Eat the '['.
1335 return parseBracketExpr(Res, EndLoc);
1336 case AsmToken::Minus:
1337 Lex(); // Eat the operator.
1338 if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
1339 return true;
1340 Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
1341 return false;
1342 case AsmToken::Plus:
1343 Lex(); // Eat the operator.
1344 if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
1345 return true;
1346 Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
1347 return false;
1348 case AsmToken::Tilde:
1349 Lex(); // Eat the operator.
1350 if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
1351 return true;
1352 Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
1353 return false;
1354 // MIPS unary expression operators. The lexer won't generate these tokens if
1355 // MCAsmInfo::HasMipsExpressions is false for the target.
1380 Lex(); // Eat the operator.
1381 if (Lexer.isNot(AsmToken::LParen))
1382 return TokError("expected '(' after operator");
1383 Lex(); // Eat the operator.
1384 if (parseExpression(Res, EndLoc))
1385 return true;
1386 if (parseRParen())
1387 return true;
1388 Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
1389 return !Res;
1390 }
1391}
1392
1393bool AsmParser::parseExpression(const MCExpr *&Res) {
1394 SMLoc EndLoc;
1395 return parseExpression(Res, EndLoc);
1396}
1397
1398const MCExpr *
1399AsmParser::applyModifierToExpr(const MCExpr *E,
1401 // Ask the target implementation about this expression first.
1402 const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx);
1403 if (NewE)
1404 return NewE;
1405 // Recurse over the given expression, rebuilding it to apply the given variant
1406 // if there is exactly one symbol.
1407 switch (E->getKind()) {
1408 case MCExpr::Target:
1409 case MCExpr::Constant:
1410 return nullptr;
1411
1412 case MCExpr::SymbolRef: {
1413 const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
1414
1415 if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
1416 TokError("invalid variant on expression '" + getTok().getIdentifier() +
1417 "' (already modified)");
1418 return E;
1419 }
1420
1421 return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext());
1422 }
1423
1424 case MCExpr::Unary: {
1425 const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
1426 const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant);
1427 if (!Sub)
1428 return nullptr;
1429 return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext());
1430 }
1431
1432 case MCExpr::Binary: {
1433 const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
1434 const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant);
1435 const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant);
1436
1437 if (!LHS && !RHS)
1438 return nullptr;
1439
1440 if (!LHS)
1441 LHS = BE->getLHS();
1442 if (!RHS)
1443 RHS = BE->getRHS();
1444
1445 return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext());
1446 }
1447 }
1448
1449 llvm_unreachable("Invalid expression kind!");
1450}
1451
1452/// This function checks if the next token is <string> type or arithmetic.
1453/// string that begin with character '<' must end with character '>'.
1454/// otherwise it is arithmetics.
1455/// If the function returns a 'true' value,
1456/// the End argument will be filled with the last location pointed to the '>'
1457/// character.
1458
1459/// There is a gap between the AltMacro's documentation and the single quote
1460/// implementation. GCC does not fully support this feature and so we will not
1461/// support it.
1462/// TODO: Adding single quote as a string.
1463static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
1464 assert((StrLoc.getPointer() != nullptr) &&
1465 "Argument to the function cannot be a NULL value");
1466 const char *CharPtr = StrLoc.getPointer();
1467 while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
1468 (*CharPtr != '\0')) {
1469 if (*CharPtr == '!')
1470 CharPtr++;
1471 CharPtr++;
1472 }
1473 if (*CharPtr == '>') {
1474 EndLoc = StrLoc.getFromPointer(CharPtr + 1);
1475 return true;
1476 }
1477 return false;
1478}
1479
1480/// creating a string without the escape characters '!'.
1481static std::string angleBracketString(StringRef AltMacroStr) {
1482 std::string Res;
1483 for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
1484 if (AltMacroStr[Pos] == '!')
1485 Pos++;
1486 Res += AltMacroStr[Pos];
1487 }
1488 return Res;
1489}
1490
1491/// Parse an expression and return it.
1492///
1493/// expr ::= expr &&,|| expr -> lowest.
1494/// expr ::= expr |,^,&,! expr
1495/// expr ::= expr ==,!=,<>,<,<=,>,>= expr
1496/// expr ::= expr <<,>> expr
1497/// expr ::= expr +,- expr
1498/// expr ::= expr *,/,% expr -> highest.
1499/// expr ::= primaryexpr
1500///
1501bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
1502 // Parse the expression.
1503 Res = nullptr;
1504 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1505 parseBinOpRHS(1, Res, EndLoc))
1506 return true;
1507
1508 // As a special case, we support 'a op b @ modifier' by rewriting the
1509 // expression to include the modifier. This is inefficient, but in general we
1510 // expect users to use 'a@modifier op b'.
1511 if (Lexer.getKind() == AsmToken::At) {
1512 Lex();
1513
1514 if (Lexer.isNot(AsmToken::Identifier))
1515 return TokError("unexpected symbol modifier following '@'");
1516
1518 MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
1519 if (Variant == MCSymbolRefExpr::VK_Invalid)
1520 return TokError("invalid variant '" + getTok().getIdentifier() + "'");
1521
1522 const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant);
1523 if (!ModifiedRes) {
1524 return TokError("invalid modifier '" + getTok().getIdentifier() +
1525 "' (no symbols present)");
1526 }
1527
1528 Res = ModifiedRes;
1529 Lex();
1530 }
1531
1532 // Try to constant fold it up front, if possible. Do not exploit
1533 // assembler here.
1534 int64_t Value;
1535 if (Res->evaluateAsAbsolute(Value))
1536 Res = MCConstantExpr::create(Value, getContext());
1537
1538 return false;
1539}
1540
1541bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
1542 Res = nullptr;
1543 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1544}
1545
1546bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
1547 SMLoc &EndLoc) {
1548 if (parseParenExpr(Res, EndLoc))
1549 return true;
1550
1551 for (; ParenDepth > 0; --ParenDepth) {
1552 if (parseBinOpRHS(1, Res, EndLoc))
1553 return true;
1554
1555 // We don't Lex() the last RParen.
1556 // This is the same behavior as parseParenExpression().
1557 if (ParenDepth - 1 > 0) {
1558 EndLoc = getTok().getEndLoc();
1559 if (parseRParen())
1560 return true;
1561 }
1562 }
1563 return false;
1564}
1565
1566bool AsmParser::parseAbsoluteExpression(int64_t &Res) {
1567 const MCExpr *Expr;
1568
1569 SMLoc StartLoc = Lexer.getLoc();
1570 if (parseExpression(Expr))
1571 return true;
1572
1573 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1574 return Error(StartLoc, "expected absolute expression");
1575
1576 return false;
1577}
1578
1581 bool ShouldUseLogicalShr) {
1582 switch (K) {
1583 default:
1584 return 0; // not a binop.
1585
1586 // Lowest Precedence: &&, ||
1587 case AsmToken::AmpAmp:
1588 Kind = MCBinaryExpr::LAnd;
1589 return 1;
1590 case AsmToken::PipePipe:
1591 Kind = MCBinaryExpr::LOr;
1592 return 1;
1593
1594 // Low Precedence: |, &, ^
1595 case AsmToken::Pipe:
1596 Kind = MCBinaryExpr::Or;
1597 return 2;
1598 case AsmToken::Caret:
1599 Kind = MCBinaryExpr::Xor;
1600 return 2;
1601 case AsmToken::Amp:
1602 Kind = MCBinaryExpr::And;
1603 return 2;
1604
1605 // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
1607 Kind = MCBinaryExpr::EQ;
1608 return 3;
1611 Kind = MCBinaryExpr::NE;
1612 return 3;
1613 case AsmToken::Less:
1614 Kind = MCBinaryExpr::LT;
1615 return 3;
1617 Kind = MCBinaryExpr::LTE;
1618 return 3;
1619 case AsmToken::Greater:
1620 Kind = MCBinaryExpr::GT;
1621 return 3;
1623 Kind = MCBinaryExpr::GTE;
1624 return 3;
1625
1626 // Intermediate Precedence: <<, >>
1627 case AsmToken::LessLess:
1628 Kind = MCBinaryExpr::Shl;
1629 return 4;
1631 Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
1632 return 4;
1633
1634 // High Intermediate Precedence: +, -
1635 case AsmToken::Plus:
1636 Kind = MCBinaryExpr::Add;
1637 return 5;
1638 case AsmToken::Minus:
1639 Kind = MCBinaryExpr::Sub;
1640 return 5;
1641
1642 // Highest Precedence: *, /, %
1643 case AsmToken::Star:
1644 Kind = MCBinaryExpr::Mul;
1645 return 6;
1646 case AsmToken::Slash:
1647 Kind = MCBinaryExpr::Div;
1648 return 6;
1649 case AsmToken::Percent:
1650 Kind = MCBinaryExpr::Mod;
1651 return 6;
1652 }
1653}
1654
1655static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI,
1658 bool ShouldUseLogicalShr) {
1659 switch (K) {
1660 default:
1661 return 0; // not a binop.
1662
1663 // Lowest Precedence: &&, ||
1664 case AsmToken::AmpAmp:
1665 Kind = MCBinaryExpr::LAnd;
1666 return 2;
1667 case AsmToken::PipePipe:
1668 Kind = MCBinaryExpr::LOr;
1669 return 1;
1670
1671 // Low Precedence: ==, !=, <>, <, <=, >, >=
1673 Kind = MCBinaryExpr::EQ;
1674 return 3;
1677 Kind = MCBinaryExpr::NE;
1678 return 3;
1679 case AsmToken::Less:
1680 Kind = MCBinaryExpr::LT;
1681 return 3;
1683 Kind = MCBinaryExpr::LTE;
1684 return 3;
1685 case AsmToken::Greater:
1686 Kind = MCBinaryExpr::GT;
1687 return 3;
1689 Kind = MCBinaryExpr::GTE;
1690 return 3;
1691
1692 // Low Intermediate Precedence: +, -
1693 case AsmToken::Plus:
1694 Kind = MCBinaryExpr::Add;
1695 return 4;
1696 case AsmToken::Minus:
1697 Kind = MCBinaryExpr::Sub;
1698 return 4;
1699
1700 // High Intermediate Precedence: |, !, &, ^
1701 //
1702 case AsmToken::Pipe:
1703 Kind = MCBinaryExpr::Or;
1704 return 5;
1705 case AsmToken::Exclaim:
1706 // Hack to support ARM compatible aliases (implied 'sp' operand in 'srs*'
1707 // instructions like 'srsda #31!') and not parse ! as an infix operator.
1708 if (MAI.getCommentString() == "@")
1709 return 0;
1710 Kind = MCBinaryExpr::OrNot;
1711 return 5;
1712 case AsmToken::Caret:
1713 Kind = MCBinaryExpr::Xor;
1714 return 5;
1715 case AsmToken::Amp:
1716 Kind = MCBinaryExpr::And;
1717 return 5;
1718
1719 // Highest Precedence: *, /, %, <<, >>
1720 case AsmToken::Star:
1721 Kind = MCBinaryExpr::Mul;
1722 return 6;
1723 case AsmToken::Slash:
1724 Kind = MCBinaryExpr::Div;
1725 return 6;
1726 case AsmToken::Percent:
1727 Kind = MCBinaryExpr::Mod;
1728 return 6;
1729 case AsmToken::LessLess:
1730 Kind = MCBinaryExpr::Shl;
1731 return 6;
1733 Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
1734 return 6;
1735 }
1736}
1737
1738unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
1739 MCBinaryExpr::Opcode &Kind) {
1740 bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
1741 return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)
1742 : getGNUBinOpPrecedence(MAI, K, Kind, ShouldUseLogicalShr);
1743}
1744
1745/// Parse all binary operators with precedence >= 'Precedence'.
1746/// Res contains the LHS of the expression on input.
1747bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
1748 SMLoc &EndLoc) {
1749 SMLoc StartLoc = Lexer.getLoc();
1750 while (true) {
1752 unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
1753
1754 // If the next token is lower precedence than we are allowed to eat, return
1755 // successfully with what we ate already.
1756 if (TokPrec < Precedence)
1757 return false;
1758
1759 Lex();
1760
1761 // Eat the next primary expression.
1762 const MCExpr *RHS;
1763 if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
1764 return true;
1765
1766 // If BinOp binds less tightly with RHS than the operator after RHS, let
1767 // the pending operator take RHS as its LHS.
1769 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1770 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
1771 return true;
1772
1773 // Merge LHS and RHS according to operator.
1774 Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
1775 }
1776}
1777
1778/// ParseStatement:
1779/// ::= EndOfStatement
1780/// ::= Label* Directive ...Operands... EndOfStatement
1781/// ::= Label* Identifier OperandList* EndOfStatement
1782bool AsmParser::parseStatement(ParseStatementInfo &Info,
1784 assert(!hasPendingError() && "parseStatement started with pending error");
1785 // Eat initial spaces and comments
1786 while (Lexer.is(AsmToken::Space))
1787 Lex();
1788 if (Lexer.is(AsmToken::EndOfStatement)) {
1789 // if this is a line comment we can drop it safely
1790 if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
1791 getTok().getString().front() == '\n')
1792 Out.addBlankLine();
1793 Lex();
1794 return false;
1795 }
1796 // Statements always start with an identifier.
1797 AsmToken ID = getTok();
1798 SMLoc IDLoc = ID.getLoc();
1799 StringRef IDVal;
1800 int64_t LocalLabelVal = -1;
1801 StartTokLoc = ID.getLoc();
1802 if (Lexer.is(AsmToken::HashDirective))
1803 return parseCppHashLineFilenameComment(IDLoc,
1804 !isInsideMacroInstantiation());
1805
1806 // Allow an integer followed by a ':' as a directional local label.
1807 if (Lexer.is(AsmToken::Integer)) {
1808 LocalLabelVal = getTok().getIntVal();
1809 if (LocalLabelVal < 0) {
1810 if (!TheCondState.Ignore) {
1811 Lex(); // always eat a token
1812 return Error(IDLoc, "unexpected token at start of statement");
1813 }
1814 IDVal = "";
1815 } else {
1816 IDVal = getTok().getString();
1817 Lex(); // Consume the integer token to be used as an identifier token.
1818 if (Lexer.getKind() != AsmToken::Colon) {
1819 if (!TheCondState.Ignore) {
1820 Lex(); // always eat a token
1821 return Error(IDLoc, "unexpected token at start of statement");
1822 }
1823 }
1824 }
1825 } else if (Lexer.is(AsmToken::Dot)) {
1826 // Treat '.' as a valid identifier in this context.
1827 Lex();
1828 IDVal = ".";
1829 } else if (Lexer.is(AsmToken::LCurly)) {
1830 // Treat '{' as a valid identifier in this context.
1831 Lex();
1832 IDVal = "{";
1833
1834 } else if (Lexer.is(AsmToken::RCurly)) {
1835 // Treat '}' as a valid identifier in this context.
1836 Lex();
1837 IDVal = "}";
1838 } else if (Lexer.is(AsmToken::Star) &&
1839 getTargetParser().starIsStartOfStatement()) {
1840 // Accept '*' as a valid start of statement.
1841 Lex();
1842 IDVal = "*";
1843 } else if (parseIdentifier(IDVal)) {
1844 if (!TheCondState.Ignore) {
1845 Lex(); // always eat a token
1846 return Error(IDLoc, "unexpected token at start of statement");
1847 }
1848 IDVal = "";
1849 }
1850
1851 // Handle conditional assembly here before checking for skipping. We
1852 // have to do this so that .endif isn't skipped in a ".if 0" block for
1853 // example.
1855 DirectiveKindMap.find(IDVal.lower());
1856 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1857 ? DK_NO_DIRECTIVE
1858 : DirKindIt->getValue();
1859 switch (DirKind) {
1860 default:
1861 break;
1862 case DK_IF:
1863 case DK_IFEQ:
1864 case DK_IFGE:
1865 case DK_IFGT:
1866 case DK_IFLE:
1867 case DK_IFLT:
1868 case DK_IFNE:
1869 return parseDirectiveIf(IDLoc, DirKind);
1870 case DK_IFB:
1871 return parseDirectiveIfb(IDLoc, true);
1872 case DK_IFNB:
1873 return parseDirectiveIfb(IDLoc, false);
1874 case DK_IFC:
1875 return parseDirectiveIfc(IDLoc, true);
1876 case DK_IFEQS:
1877 return parseDirectiveIfeqs(IDLoc, true);
1878 case DK_IFNC:
1879 return parseDirectiveIfc(IDLoc, false);
1880 case DK_IFNES:
1881 return parseDirectiveIfeqs(IDLoc, false);
1882 case DK_IFDEF:
1883 return parseDirectiveIfdef(IDLoc, true);
1884 case DK_IFNDEF:
1885 case DK_IFNOTDEF:
1886 return parseDirectiveIfdef(IDLoc, false);
1887 case DK_ELSEIF:
1888 return parseDirectiveElseIf(IDLoc);
1889 case DK_ELSE:
1890 return parseDirectiveElse(IDLoc);
1891 case DK_ENDIF:
1892 return parseDirectiveEndIf(IDLoc);
1893 }
1894
1895 // Ignore the statement if in the middle of inactive conditional
1896 // (e.g. ".if 0").
1897 if (TheCondState.Ignore) {
1898 eatToEndOfStatement();
1899 return false;
1900 }
1901
1902 // FIXME: Recurse on local labels?
1903
1904 // Check for a label.
1905 // ::= identifier ':'
1906 // ::= number ':'
1907 if (Lexer.is(AsmToken::Colon) && getTargetParser().isLabel(ID)) {
1908 if (checkForValidSection())
1909 return true;
1910
1911 Lex(); // Consume the ':'.
1912
1913 // Diagnose attempt to use '.' as a label.
1914 if (IDVal == ".")
1915 return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
1916
1917 // Diagnose attempt to use a variable as a label.
1918 //
1919 // FIXME: Diagnostics. Note the location of the definition as a label.
1920 // FIXME: This doesn't diagnose assignment to a symbol which has been
1921 // implicitly marked as external.
1922 MCSymbol *Sym;
1923 if (LocalLabelVal == -1) {
1924 if (ParsingMSInlineAsm && SI) {
1925 StringRef RewrittenLabel =
1926 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
1927 assert(!RewrittenLabel.empty() &&
1928 "We should have an internal name here.");
1929 Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
1930 RewrittenLabel);
1931 IDVal = RewrittenLabel;
1932 }
1933 Sym = getContext().getOrCreateSymbol(IDVal);
1934 } else
1935 Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
1936 // End of Labels should be treated as end of line for lexing
1937 // purposes but that information is not available to the Lexer who
1938 // does not understand Labels. This may cause us to see a Hash
1939 // here instead of a preprocessor line comment.
1940 if (getTok().is(AsmToken::Hash)) {
1941 StringRef CommentStr = parseStringToEndOfStatement();
1942 Lexer.Lex();
1943 Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
1944 }
1945
1946 // Consume any end of statement token, if present, to avoid spurious
1947 // addBlankLine calls().
1948 if (getTok().is(AsmToken::EndOfStatement)) {
1949 Lex();
1950 }
1951
1952 if (discardLTOSymbol(IDVal))
1953 return false;
1954
1955 getTargetParser().doBeforeLabelEmit(Sym, IDLoc);
1956
1957 // Emit the label.
1958 if (!getTargetParser().isParsingMSInlineAsm())
1959 Out.emitLabel(Sym, IDLoc);
1960
1961 // If we are generating dwarf for assembly source files then gather the
1962 // info to make a dwarf label entry for this label if needed.
1963 if (enabledGenDwarfForAssembly())
1964 MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
1965 IDLoc);
1966
1967 getTargetParser().onLabelParsed(Sym);
1968
1969 return false;
1970 }
1971
1972 // Check for an assignment statement.
1973 // ::= identifier '='
1974 if (Lexer.is(AsmToken::Equal) && getTargetParser().equalIsAsmAssignment()) {
1975 Lex();
1976 return parseAssignment(IDVal, AssignmentKind::Equal);
1977 }
1978
1979 // If macros are enabled, check to see if this is a macro instantiation.
1980 if (areMacrosEnabled())
1981 if (const MCAsmMacro *M = getContext().lookupMacro(IDVal)) {
1982 return handleMacroEntry(M, IDLoc);
1983 }
1984
1985 // Otherwise, we have a normal instruction or directive.
1986
1987 // Directives start with "."
1988 if (IDVal.startswith(".") && IDVal != ".") {
1989 // There are several entities interested in parsing directives:
1990 //
1991 // 1. The target-specific assembly parser. Some directives are target
1992 // specific or may potentially behave differently on certain targets.
1993 // 2. Asm parser extensions. For example, platform-specific parsers
1994 // (like the ELF parser) register themselves as extensions.
1995 // 3. The generic directive parser implemented by this class. These are
1996 // all the directives that behave in a target and platform independent
1997 // manner, or at least have a default behavior that's shared between
1998 // all targets and platforms.
1999
2000 getTargetParser().flushPendingInstructions(getStreamer());
2001
2002 SMLoc StartTokLoc = getTok().getLoc();
2003 bool TPDirectiveReturn = getTargetParser().ParseDirective(ID);
2004
2005 if (hasPendingError())
2006 return true;
2007 // Currently the return value should be true if we are
2008 // uninterested but as this is at odds with the standard parsing
2009 // convention (return true = error) we have instances of a parsed
2010 // directive that fails returning true as an error. Catch these
2011 // cases as best as possible errors here.
2012 if (TPDirectiveReturn && StartTokLoc != getTok().getLoc())
2013 return true;
2014 // Return if we did some parsing or believe we succeeded.
2015 if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc())
2016 return false;
2017
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);
2022 if (Handler.first)
2023 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2024
2025 // Finally, if no one else is interested in this directive, it must be
2026 // generic and familiar to this class.
2027 switch (DirKind) {
2028 default:
2029 break;
2030 case DK_SET:
2031 case DK_EQU:
2032 return parseDirectiveSet(IDVal, AssignmentKind::Set);
2033 case DK_EQUIV:
2034 return parseDirectiveSet(IDVal, AssignmentKind::Equiv);
2035 case DK_LTO_SET_CONDITIONAL:
2036 return parseDirectiveSet(IDVal, AssignmentKind::LTOSetConditional);
2037 case DK_ASCII:
2038 return parseDirectiveAscii(IDVal, false);
2039 case DK_ASCIZ:
2040 case DK_STRING:
2041 return parseDirectiveAscii(IDVal, true);
2042 case DK_BYTE:
2043 case DK_DC_B:
2044 return parseDirectiveValue(IDVal, 1);
2045 case DK_DC:
2046 case DK_DC_W:
2047 case DK_SHORT:
2048 case DK_VALUE:
2049 case DK_2BYTE:
2050 return parseDirectiveValue(IDVal, 2);
2051 case DK_LONG:
2052 case DK_INT:
2053 case DK_4BYTE:
2054 case DK_DC_L:
2055 return parseDirectiveValue(IDVal, 4);
2056 case DK_QUAD:
2057 case DK_8BYTE:
2058 return parseDirectiveValue(IDVal, 8);
2059 case DK_DC_A:
2060 return parseDirectiveValue(
2061 IDVal, getContext().getAsmInfo()->getCodePointerSize());
2062 case DK_OCTA:
2063 return parseDirectiveOctaValue(IDVal);
2064 case DK_SINGLE:
2065 case DK_FLOAT:
2066 case DK_DC_S:
2067 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());
2068 case DK_DOUBLE:
2069 case DK_DC_D:
2070 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());
2071 case DK_ALIGN: {
2072 bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
2073 return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);
2074 }
2075 case DK_ALIGN32: {
2076 bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
2077 return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);
2078 }
2079 case DK_BALIGN:
2080 return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
2081 case DK_BALIGNW:
2082 return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
2083 case DK_BALIGNL:
2084 return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
2085 case DK_P2ALIGN:
2086 return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
2087 case DK_P2ALIGNW:
2088 return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
2089 case DK_P2ALIGNL:
2090 return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
2091 case DK_ORG:
2092 return parseDirectiveOrg();
2093 case DK_FILL:
2094 return parseDirectiveFill();
2095 case DK_ZERO:
2096 return parseDirectiveZero();
2097 case DK_EXTERN:
2098 eatToEndOfStatement(); // .extern is the default, ignore it.
2099 return false;
2100 case DK_GLOBL:
2101 case DK_GLOBAL:
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);
2111 case DK_REFERENCE:
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);
2119 case DK_COLD:
2120 return parseDirectiveSymbolAttribute(MCSA_Cold);
2121 case DK_COMM:
2122 case DK_COMMON:
2123 return parseDirectiveComm(/*IsLocal=*/false);
2124 case DK_LCOMM:
2125 return parseDirectiveComm(/*IsLocal=*/true);
2126 case DK_ABORT:
2127 return parseDirectiveAbort();
2128 case DK_INCLUDE:
2129 return parseDirectiveInclude();
2130 case DK_INCBIN:
2131 return parseDirectiveIncbin();
2132 case DK_CODE16:
2133 case DK_CODE16GCC:
2134 return TokError(Twine(IDVal) +
2135 " not currently supported for this target");
2136 case DK_REPT:
2137 return parseDirectiveRept(IDLoc, IDVal);
2138 case DK_IRP:
2139 return parseDirectiveIrp(IDLoc);
2140 case DK_IRPC:
2141 return parseDirectiveIrpc(IDLoc);
2142 case DK_ENDR:
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();
2150 case DK_SLEB128:
2151 return parseDirectiveLEB128(true);
2152 case DK_ULEB128:
2153 return parseDirectiveLEB128(false);
2154 case DK_SPACE:
2155 case DK_SKIP:
2156 return parseDirectiveSpace(IDVal);
2157 case DK_FILE:
2158 return parseDirectiveFile(IDLoc);
2159 case DK_LINE:
2160 return parseDirectiveLine();
2161 case DK_LOC:
2162 return parseDirectiveLoc();
2163 case DK_STABS:
2164 return parseDirectiveStabs();
2165 case DK_CV_FILE:
2166 return parseDirectiveCVFile();
2167 case DK_CV_FUNC_ID:
2168 return parseDirectiveCVFuncId();
2169 case DK_CV_INLINE_SITE_ID:
2170 return parseDirectiveCVInlineSiteId();
2171 case DK_CV_LOC:
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();
2179 case DK_CV_STRING:
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();
2199 case DK_CFI_ADJUST_CFA_OFFSET:
2200 return parseDirectiveCFIAdjustCfaOffset();
2201 case DK_CFI_DEF_CFA_REGISTER:
2202 return parseDirectiveCFIDefCfaRegister(IDLoc);
2203 case DK_CFI_LLVM_DEF_ASPACE_CFA:
2204 return parseDirectiveCFILLVMDefAspaceCfa(IDLoc);
2205 case DK_CFI_OFFSET:
2206 return parseDirectiveCFIOffset(IDLoc);
2207 case DK_CFI_REL_OFFSET:
2208 return parseDirectiveCFIRelOffset(IDLoc);
2209 case DK_CFI_PERSONALITY:
2210 return parseDirectiveCFIPersonalityOrLsda(true);
2211 case DK_CFI_LSDA:
2212 return parseDirectiveCFIPersonalityOrLsda(false);
2213 case DK_CFI_REMEMBER_STATE:
2214 return parseDirectiveCFIRememberState();
2215 case DK_CFI_RESTORE_STATE:
2216 return parseDirectiveCFIRestoreState();
2217 case DK_CFI_SAME_VALUE:
2218 return parseDirectiveCFISameValue(IDLoc);
2219 case DK_CFI_RESTORE:
2220 return parseDirectiveCFIRestore(IDLoc);
2221 case DK_CFI_ESCAPE:
2222 return parseDirectiveCFIEscape();
2223 case DK_CFI_RETURN_COLUMN:
2224 return parseDirectiveCFIReturnColumn(IDLoc);
2225 case DK_CFI_SIGNAL_FRAME:
2226 return parseDirectiveCFISignalFrame();
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();
2233 case DK_MACROS_ON:
2234 case DK_MACROS_OFF:
2235 return parseDirectiveMacrosOnOff(IDVal);
2236 case DK_MACRO:
2237 return parseDirectiveMacro(IDLoc);
2238 case DK_ALTMACRO:
2239 case DK_NOALTMACRO:
2240 return parseDirectiveAltmacro(IDVal);
2241 case DK_EXITM:
2242 return parseDirectiveExitMacro(IDVal);
2243 case DK_ENDM:
2244 case DK_ENDMACRO:
2245 return parseDirectiveEndMacro(IDVal);
2246 case DK_PURGEM:
2247 return parseDirectivePurgeMacro(IDLoc);
2248 case DK_END:
2249 return parseDirectiveEnd(IDLoc);
2250 case DK_ERR:
2251 return parseDirectiveError(IDLoc, false);
2252 case DK_ERROR:
2253 return parseDirectiveError(IDLoc, true);
2254 case DK_WARNING:
2255 return parseDirectiveWarning(IDLoc);
2256 case DK_RELOC:
2257 return parseDirectiveReloc(IDLoc);
2258 case DK_DCB:
2259 case DK_DCB_W:
2260 return parseDirectiveDCB(IDVal, 2);
2261 case DK_DCB_B:
2262 return parseDirectiveDCB(IDVal, 1);
2263 case DK_DCB_D:
2264 return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble());
2265 case DK_DCB_L:
2266 return parseDirectiveDCB(IDVal, 4);
2267 case DK_DCB_S:
2268 return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle());
2269 case DK_DC_X:
2270 case DK_DCB_X:
2271 return TokError(Twine(IDVal) +
2272 " not currently supported for this target");
2273 case DK_DS:
2274 case DK_DS_W:
2275 return parseDirectiveDS(IDVal, 2);
2276 case DK_DS_B:
2277 return parseDirectiveDS(IDVal, 1);
2278 case DK_DS_D:
2279 return parseDirectiveDS(IDVal, 8);
2280 case DK_DS_L:
2281 case DK_DS_S:
2282 return parseDirectiveDS(IDVal, 4);
2283 case DK_DS_P:
2284 case DK_DS_X:
2285 return parseDirectiveDS(IDVal, 12);
2286 case DK_PRINT:
2287 return parseDirectivePrint(IDLoc);
2288 case DK_ADDRSIG:
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();
2296 case DK_MEMTAG:
2297 return parseDirectiveSymbolAttribute(MCSA_Memtag);
2298 }
2299
2300 return Error(IDLoc, "unknown directive");
2301 }
2302
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());
2307
2308 // __asm align
2309 if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
2310 return parseDirectiveMSAlign(IDLoc, Info);
2311
2312 if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
2313 Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
2314 if (checkForValidSection())
2315 return true;
2316
2317 return parseAndMatchAndEmitTargetInstruction(Info, IDVal, ID, IDLoc);
2318}
2319
2320bool AsmParser::parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,
2321 StringRef IDVal,
2322 AsmToken ID,
2323 SMLoc IDLoc) {
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;
2330
2331 // Dump the parsed representation, if requested.
2332 if (getShowParsedOperands()) {
2333 SmallString<256> Str;
2335 OS << "parsed instruction: [";
2336 for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
2337 if (i != 0)
2338 OS << ", ";
2339 Info.ParsedOperands[i]->print(OS);
2340 }
2341 OS << "]";
2342
2343 printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
2344 }
2345
2346 // Fail even if ParseInstruction erroneously returns false.
2347 if (hasPendingError() || ParseHadError)
2348 return true;
2349
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())) {
2355 unsigned Line;
2356 if (ActiveMacros.empty())
2357 Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
2358 else
2359 Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
2360 ActiveMacros.front()->ExitBuffer);
2361
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);
2369
2370 unsigned CppHashLocLineNo =
2371 SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
2372 Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
2373 }
2374
2375 getStreamer().emitDwarfLocDirective(
2376 getContext().getGenDwarfFileNumber(), Line, 0,
2378 StringRef());
2379 }
2380
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()))
2387 return true;
2388 }
2389 return false;
2390}
2391
2392// Parse and erase curly braces marking block start/end
2393bool
2394AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2395 // Identify curly brace marking block start/end
2396 if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
2397 return false;
2398
2399 SMLoc StartLoc = Lexer.getLoc();
2400 Lex(); // Eat the brace
2401 if (Lexer.is(AsmToken::EndOfStatement))
2402 Lex(); // Eat EndOfStatement following the brace
2403
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());
2407 return true;
2408}
2409
2410/// parseCppHashLineFilenameComment as this:
2411/// ::= # number "filename"
2412bool 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();
2419 Lex();
2420 assert(getTok().is(AsmToken::String) &&
2421 "Lexing Cpp line comment: Expected String");
2422 StringRef Filename = getTok().getString();
2423 Lex();
2424
2425 if (!SaveLocInfo)
2426 return false;
2427
2428 // Get rid of the enclosing quotes.
2429 Filename = Filename.substr(1, Filename.size() - 2);
2430
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;
2439 return false;
2440}
2441
2442/// will use the last parsed cpp hash line filename comment
2443/// for the Filename and LineNo if any in the diagnostic.
2444void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
2445 auto *Parser = static_cast<AsmParser *>(Context);
2446 raw_ostream &OS = errs();
2447
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);
2453
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);
2461 }
2462
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);
2469 else
2470 Parser->getContext().diagnose(Diag);
2471 return;
2472 }
2473
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);
2478
2479 int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
2480 int CppHashLocLineNo =
2481 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2482 int LineNo =
2483 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2484
2485 SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
2486 Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
2487 Diag.getLineContents(), Diag.getRanges());
2488
2489 if (Parser->SavedDiagHandler)
2490 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2491 else
2492 Parser->getContext().diagnose(NewDiag);
2493}
2494
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.
2499static bool isIdentifierChar(char c) {
2500 return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||
2501 c == '.';
2502}
2503
2504bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
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");
2512
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)
2523 continue;
2524
2525 char Next = Body[Pos + 1];
2526 if (Next == '$' || Next == 'n' ||
2527 isdigit(static_cast<unsigned char>(Next)))
2528 break;
2529 } else {
2530 // This macro has parameters, look for \foo, \bar, etc.
2531 if (Body[Pos] == '\\' && Pos + 1 != End)
2532 break;
2533 }
2534 }
2535
2536 // Add the prefix.
2537 OS << Body.slice(0, Pos);
2538
2539 // Check if we reached the end.
2540 if (Pos == End)
2541 break;
2542
2543 if (IsDarwin && !NParameters) {
2544 switch (Body[Pos + 1]) {
2545 // $$ => $
2546 case '$':
2547 OS << '$';
2548 break;
2549
2550 // $n => number of arguments
2551 case 'n':
2552 OS << A.size();
2553 break;
2554
2555 // $[0-9] => argument
2556 default: {
2557 // Missing arguments are ignored.
2558 unsigned Index = Body[Pos + 1] - '0';
2559 if (Index >= A.size())
2560 break;
2561
2562 // Otherwise substitute with the token values, with spaces eliminated.
2563 for (const AsmToken &Token : A[Index])
2564 OS << Token.getString();
2565 break;
2566 }
2567 }
2568 Pos += 2;
2569 } else {
2570 unsigned I = Pos + 1;
2571
2572 // Check for the \@ pseudo-variable.
2573 if (EnableAtPseudoVariable && Body[I] == '@' && I + 1 != End)
2574 ++I;
2575 else
2576 while (isIdentifierChar(Body[I]) && I + 1 != End)
2577 ++I;
2578
2579 const char *Begin = Body.data() + Pos + 1;
2580 StringRef Argument(Begin, I - (Pos + 1));
2581 unsigned Index = 0;
2582
2583 if (Argument == "@") {
2584 OS << NumOfMacroInstantiations;
2585 Pos += 2;
2586 } else {
2587 for (; Index < NParameters; ++Index)
2588 if (Parameters[Index].Name == Argument)
2589 break;
2590
2591 if (Index == NParameters) {
2592 if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
2593 Pos += 3;
2594 else {
2595 OS << '\\' << Argument;
2596 Pos = I;
2597 }
2598 } else {
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
2604 // string "3").
2605 // Here, we identify the integer token which is the result of the
2606 // absolute expression evaluation and replace it with its string
2607 // representation.
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());
2617 }
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();
2622 else
2623 OS << Token.getStringContents();
2624
2625 Pos += 1 + Argument.size();
2626 }
2627 }
2628 }
2629 // Update the scan point.
2630 Body = Body.substr(Pos);
2631 }
2632
2633 return false;
2634}
2635
2637 switch (kind) {
2638 default:
2639 return false;
2640 case AsmToken::Plus:
2641 case AsmToken::Minus:
2642 case AsmToken::Tilde:
2643 case AsmToken::Slash:
2644 case AsmToken::Star:
2645 case AsmToken::Dot:
2646 case AsmToken::Equal:
2648 case AsmToken::Pipe:
2649 case AsmToken::PipePipe:
2650 case AsmToken::Caret:
2651 case AsmToken::Amp:
2652 case AsmToken::AmpAmp:
2653 case AsmToken::Exclaim:
2655 case AsmToken::Less:
2657 case AsmToken::LessLess:
2659 case AsmToken::Greater:
2662 return true;
2663 }
2664}
2665
2666namespace {
2667
2668class AsmLexerSkipSpaceRAII {
2669public:
2670 AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
2671 Lexer.setSkipSpace(SkipSpace);
2672 }
2673
2674 ~AsmLexerSkipSpaceRAII() {
2675 Lexer.setSkipSpace(true);
2676 }
2677
2678private:
2679 AsmLexer &Lexer;
2680};
2681
2682} // end anonymous namespace
2683
2684bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
2685
2686 if (Vararg) {
2687 if (Lexer.isNot(AsmToken::EndOfStatement)) {
2688 StringRef Str = parseStringToEndOfStatement();
2689 MA.emplace_back(AsmToken::String, Str);
2690 }
2691 return false;
2692 }
2693
2694 unsigned ParenLevel = 0;
2695
2696 // Darwin doesn't use spaces to delmit arguments.
2697 AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
2698
2699 bool SpaceEaten;
2700
2701 while (true) {
2702 SpaceEaten = false;
2703 if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
2704 return TokError("unexpected token in macro instantiation");
2705
2706 if (ParenLevel == 0) {
2707
2708 if (Lexer.is(AsmToken::Comma))
2709 break;
2710
2711 if (Lexer.is(AsmToken::Space)) {
2712 SpaceEaten = true;
2713 Lexer.Lex(); // Eat spaces
2714 }
2715
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
2719 if (!IsDarwin) {
2720 if (isOperator(Lexer.getKind())) {
2721 MA.push_back(getTok());
2722 Lexer.Lex();
2723
2724 // Whitespace after an operator can be ignored.
2725 if (Lexer.is(AsmToken::Space))
2726 Lexer.Lex();
2727
2728 continue;
2729 }
2730 }
2731 if (SpaceEaten)
2732 break;
2733 }
2734
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))
2738 break;
2739
2740 // Adjust the current parentheses level.
2741 if (Lexer.is(AsmToken::LParen))
2742 ++ParenLevel;
2743 else if (Lexer.is(AsmToken::RParen) && ParenLevel)
2744 --ParenLevel;
2745
2746 // Append the token to the current argument list.
2747 MA.push_back(getTok());
2748 Lexer.Lex();
2749 }
2750
2751 if (ParenLevel != 0)
2752 return TokError("unbalanced parentheses in macro argument");
2753 return false;
2754}
2755
2756// Parse the macro instantiation arguments.
2757bool 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;
2762
2763 A.resize(NParameters);
2764 FALocs.resize(NParameters);
2765
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;
2771 ++Parameter) {
2772 SMLoc IDLoc = Lexer.getLoc();
2774
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");
2778
2779 if (Lexer.isNot(AsmToken::Equal))
2780 return TokError("expected '=' after formal parameter identifier");
2781
2782 Lex();
2783
2784 NamedParametersFound = true;
2785 }
2786 bool Vararg = HasVararg && Parameter == (NParameters - 1);
2787
2788 if (NamedParametersFound && FA.Name.empty())
2789 return Error(IDLoc, "cannot mix positional and keyword arguments");
2790
2791 SMLoc StrLoc = Lexer.getLoc();
2792 SMLoc EndLoc;
2793 if (AltMacroMode && Lexer.is(AsmToken::Percent)) {
2794 const MCExpr *AbsoluteExp;
2795 int64_t Value;
2796 /// Eat '%'
2797 Lex();
2798 if (parseExpression(AbsoluteExp, EndLoc))
2799 return false;
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 '>'
2814 Lex();
2815 AsmToken newToken(AsmToken::String,
2816 StringRef(StrChar, EndChar - StrChar));
2817 FA.Value.push_back(newToken);
2818 } else if(parseMacroArgument(FA.Value, Vararg))
2819 return true;
2820
2821 unsigned PI = Parameter;
2822 if (!FA.Name.empty()) {
2823 unsigned FAI = 0;
2824 for (FAI = 0; FAI < NParameters; ++FAI)
2825 if (M->Parameters[FAI].Name == FA.Name)
2826 break;
2827
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 + "'");
2832 }
2833 PI = FAI;
2834 }
2835
2836 if (!FA.Value.empty()) {
2837 if (A.size() <= PI)
2838 A.resize(PI + 1);
2839 A[PI] = FA.Value;
2840
2841 if (FALocs.size() <= PI)
2842 FALocs.resize(PI + 1);
2843
2844 FALocs[PI] = Lexer.getLoc();
2845 }
2846
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 + "'");
2858 Failure = true;
2859 }
2860
2861 if (!M->Parameters[FAI].Value.empty())
2862 A[FAI] = M->Parameters[FAI].Value;
2863 }
2864 }
2865 return Failure;
2866 }
2867
2868 if (Lexer.is(AsmToken::Comma))
2869 Lex();
2870 }
2871
2872 return TokError("too many positional arguments");
2873}
2874
2875bool 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 "
2884 "this limit.";
2885 return TokError(MaxNestingDepthError.str());
2886 }
2887
2888 MCAsmMacroArguments A;
2889 if (parseMacroArguments(M, A))
2890 return true;
2891
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;
2897
2898 if (expandMacro(OS, Body, M->Parameters, A, true, getTok().getLoc()))
2899 return true;
2900
2901 // We include the .endmacro in the buffer as our cue to exit the macro
2902 // instantiation.
2903 OS << ".endmacro\n";
2904
2905 std::unique_ptr<MemoryBuffer> Instantiation =
2906 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
2907
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);
2913
2914 ++NumOfMacroInstantiations;
2915
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());
2919 Lex();
2920
2921 return false;
2922}
2923
2924void AsmParser::handleMacroExit() {
2925 // Jump to the EndOfStatement we should return to, and consume it.
2926 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
2927 Lex();
2928
2929 // Pop the instantiation entry.
2930 delete ActiveMacros.back();
2931 ActiveMacros.pop_back();
2932}
2933
2934bool AsmParser::parseAssignment(StringRef Name, AssignmentKind Kind) {
2935 MCSymbol *Sym;
2936 const MCExpr *Value;
2937 SMLoc ExprLoc = getTok().getLoc();
2938 bool AllowRedef =
2939 Kind == AssignmentKind::Set || Kind == AssignmentKind::Equal;
2940 if (MCParserUtils::parseAssignmentExpression(Name, AllowRedef, *this, Sym,
2941 Value))
2942 return true;
2943
2944 if (!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.
2948 return false;
2949 }
2950
2951 if (discardLTOSymbol(Name))
2952 return false;
2953
2954 // Do the assignment.
2955 switch (Kind) {
2956 case AssignmentKind::Equal:
2957 Out.emitAssignment(Sym, Value);
2958 break;
2959 case AssignmentKind::Set:
2960 case AssignmentKind::Equiv:
2961 Out.emitAssignment(Sym, Value);
2963 break;
2964 case AssignmentKind::LTOSetConditional:
2965 if (Value->getKind() != MCExpr::SymbolRef)
2966 return Error(ExprLoc, "expected identifier");
2967
2969 break;
2970 }
2971
2972 return false;
2973}
2974
2975/// parseIdentifier:
2976/// ::= identifier
2977/// ::= string
2978bool 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();
2986
2987 // Consume the prefix character, and check for a following identifier.
2988
2989 AsmToken Buf[1];
2990 Lexer.peekTokens(Buf, false);
2991
2992 if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer))
2993 return true;
2994
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())
2998 return true;
2999
3000 // eat $ or @
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.
3005 return false;
3006 }
3007
3008 if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
3009 return true;
3010
3011 Res = getTok().getIdentifier();
3012
3013 Lex(); // Consume the identifier token.
3014
3015 return false;
3016}
3017
3018/// parseDirectiveSet:
3019/// ::= .equ identifier ',' expression
3020/// ::= .equiv identifier ',' expression
3021/// ::= .set identifier ',' expression
3022/// ::= .lto_set_conditional identifier ',' expression
3023bool AsmParser::parseDirectiveSet(StringRef IDVal, AssignmentKind Kind) {
3025 if (check(parseIdentifier(Name), "expected identifier") || parseComma() ||
3026 parseAssignment(Name, Kind))
3027 return true;
3028 return false;
3029}
3030
3031bool AsmParser::parseEscapedString(std::string &Data) {
3032 if (check(getTok().isNot(AsmToken::String), "expected string"))
3033 return true;
3034
3035 Data = "";
3036 StringRef Str = getTok().getStringContents();
3037 for (unsigned i = 0, e = Str.size(); i != e; ++i) {
3038 if (Str[i] != '\\') {
3039 Data += Str[i];
3040 continue;
3041 }
3042
3043 // Recognize escaped characters. Note that this escape semantics currently
3044 // loosely follows Darwin 'as'.
3045 ++i;
3046 if (i == e)
3047 return TokError("unexpected backslash at end of string");
3048
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");
3054
3055 // Consume hex characters. GNU 'as' reads all hexadecimal characters and
3056 // then truncates to the lower 16 bits. Seems reasonable.
3057 unsigned Value = 0;
3058 while (i + 1 < length && isHexDigit(Str[i + 1]))
3059 Value = Value * 16 + hexDigitValue(Str[++i]);
3060
3061 Data += (unsigned char)(Value & 0xFF);
3062 continue;
3063 }
3064
3065 // Recognize octal sequences.
3066 if ((unsigned)(Str[i] - '0') <= 7) {
3067 // Consume up to three octal characters.
3068 unsigned Value = Str[i] - '0';
3069
3070 if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
3071 ++i;
3072 Value = Value * 8 + (Str[i] - '0');
3073
3074 if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
3075 ++i;
3076 Value = Value * 8 + (Str[i] - '0');
3077 }
3078 }
3079
3080 if (Value > 255)
3081 return TokError("invalid octal escape sequence (out of range)");
3082
3083 Data += (unsigned char)Value;
3084 continue;
3085 }
3086
3087 // Otherwise recognize individual escapes.
3088 switch (Str[i]) {
3089 default:
3090 // Just reject invalid escape sequences for now.
3091 return TokError("invalid escape sequence (unrecognized character)");
3092
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;
3100 }
3101 }
3102
3103 Lex();
3104 return false;
3105}
3106
3107bool 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 '>'
3114 Lex();
3115
3116 Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
3117 return false;
3118 }
3119 return true;
3120}
3121
3122/// parseDirectiveAscii:
3123// ::= .ascii [ "string"+ ( , "string"+ )* ]
3124/// ::= ( .asciz | .string ) [ "string" ( , "string" )* ]
3125bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
3126 auto parseOp = [&]() -> bool {
3127 std::string Data;
3128 if (checkForValidSection())
3129 return true;
3130 // Only support spaces as separators for .ascii directive for now. See the
3131 // discusssion at https://reviews.llvm.org/D91460 for more details.
3132 do {
3133 if (parseEscapedString(Data))
3134 return true;
3135 getStreamer().emitBytes(Data);
3136 } while (!ZeroTerminated && getTok().is(AsmToken::String));
3137 if (ZeroTerminated)
3138 getStreamer().emitBytes(StringRef("\0", 1));
3139 return false;
3140 };
3141
3142 return parseMany(parseOp);
3143}
3144
3145/// parseDirectiveReloc
3146/// ::= .reloc expression , identifier [ , expression ]
3147bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
3148 const MCExpr *Offset;
3149 const MCExpr *Expr = nullptr;
3150 SMLoc OffsetLoc = Lexer.getTok().getLoc();
3151
3152 if (parseExpression(Offset))
3153 return true;
3154 if (parseComma() ||
3155 check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
3156 return true;
3157
3158 SMLoc NameLoc = Lexer.getTok().getLoc();
3159 StringRef Name = Lexer.getTok().getIdentifier();
3160 Lex();
3161
3162 if (Lexer.is(AsmToken::Comma)) {
3163 Lex();
3164 SMLoc ExprLoc = Lexer.getLoc();
3165 if (parseExpression(Expr))
3166 return true;
3167
3168 MCValue Value;
3169 if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr))
3170 return Error(ExprLoc, "expression must be relocatable");
3171 }
3172
3173 if (parseEOL())
3174 return true;
3175
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,
3180 STI))
3181 return Error(Err->first ? NameLoc : OffsetLoc, Err->second);
3182
3183 return false;
3184}
3185
3186/// parseDirectiveValue
3187/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
3188bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
3189 auto parseOp = [&]() -> bool {
3190 const MCExpr *Value;
3191 SMLoc ExprLoc = getLexer().getLoc();
3192 if (checkForValidSection() || parseExpression(Value))
3193 return true;
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);
3201 } else
3202 getStreamer().emitValue(Value, Size, ExprLoc);
3203 return false;
3204 };
3205
3206 return parseMany(parseOp);
3207}
3208
3209static 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();
3215 Asm.Lex();
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();
3221 } else {
3222 hi = 0;
3223 lo = IntValue.getZExtValue();
3224 }
3225 return false;
3226}
3227
3228/// ParseDirectiveOctaValue
3229/// ::= .octa [ hexconstant (, hexconstant)* ]
3230
3231bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
3232 auto parseOp = [&]() -> bool {
3233 if (checkForValidSection())
3234 return true;
3235 uint64_t hi, lo;
3236 if (parseHexOcta(*this, hi, lo))
3237 return true;
3238 if (MAI.isLittleEndian()) {
3239 getStreamer().emitInt64(lo);
3240 getStreamer().emitInt64(hi);
3241 } else {
3242 getStreamer().emitInt64(hi);
3243 getStreamer().emitInt64(lo);
3244 }
3245 return false;
3246 };
3247
3248 return parseMany(parseOp);
3249}
3250
3251bool 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.
3254 bool IsNeg = false;
3255 if (getLexer().is(AsmToken::Minus)) {
3256 Lexer.Lex();
3257 IsNeg = true;
3258 } else if (getLexer().is(AsmToken::Plus))
3259 Lexer.Lex();
3260
3261 if (Lexer.is(AsmToken::Error))
3262 return TokError(Lexer.getErr());
3263 if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
3265 return TokError("unexpected token in directive");
3266
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);
3276 else
3277 return TokError("invalid floating point literal");
3278 } else if (errorToBool(
3279 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3280 .takeError()))
3281 return TokError("invalid floating point literal");
3282 if (IsNeg)
3283 Value.changeSign();
3284
3285 // Consume the numeric token.
3286 Lex();
3287
3288 Res = Value.bitcastToAPInt();
3289
3290 return false;
3291}
3292
3293/// parseDirectiveRealValue
3294/// ::= (.single | .double) [ expression (, expression)* ]
3295bool AsmParser::parseDirectiveRealValue(StringRef IDVal,
3296 const fltSemantics &Semantics) {
3297 auto parseOp = [&]() -> bool {
3298 APInt AsInt;
3299 if (checkForValidSection() || parseRealValue(Semantics, AsInt))
3300 return true;
3301 getStreamer().emitIntValue(AsInt.getLimitedValue(),
3302 AsInt.getBitWidth() / 8);
3303 return false;
3304 };
3305
3306 return parseMany(parseOp);
3307}
3308
3309/// parseDirectiveZero
3310/// ::= .zero expression
3311bool AsmParser::parseDirectiveZero() {
3312 SMLoc NumBytesLoc = Lexer.getLoc();
3313 const MCExpr *NumBytes;
3314 if (checkForValidSection() || parseExpression(NumBytes))
3315 return true;
3316
3317 int64_t Val = 0;
3318 if (getLexer().is(AsmToken::Comma)) {
3319 Lex();
3320 if (parseAbsoluteExpression(Val))
3321 return true;
3322 }
3323
3324 if (parseEOL())
3325 return true;
3326 getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);
3327
3328 return false;
3329}
3330
3331/// parseDirectiveFill
3332/// ::= .fill expression [ , expression [ , expression ] ]
3333bool AsmParser::parseDirectiveFill() {
3334 SMLoc NumValuesLoc = Lexer.getLoc();
3335 const MCExpr *NumValues;
3336 if (checkForValidSection() || parseExpression(NumValues))
3337 return true;
3338
3339 int64_t FillSize = 1;
3340 int64_t FillExpr = 0;
3341
3342 SMLoc SizeLoc, ExprLoc;
3343
3344 if (parseOptionalToken(AsmToken::Comma)) {
3345 SizeLoc = getTok().getLoc();
3346 if (parseAbsoluteExpression(FillSize))
3347 return true;
3348 if (parseOptionalToken(AsmToken::Comma)) {
3349 ExprLoc = getTok().getLoc();
3350 if (parseAbsoluteExpression(FillExpr))
3351 return true;
3352 }
3353 }
3354 if (parseEOL())
3355 return true;
3356
3357 if (FillSize < 0) {
3358 Warning(SizeLoc, "'.fill' directive with negative size has no effect");
3359 return false;
3360 }
3361 if (FillSize > 8) {
3362 Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
3363 FillSize = 8;
3364 }
3365
3366 if (!isUInt<32>(FillExpr) && FillSize > 4)
3367 Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
3368
3369 getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);
3370
3371 return false;
3372}
3373
3374/// parseDirectiveOrg
3375/// ::= .org expression [ , expression ]
3376bool AsmParser::parseDirectiveOrg() {
3377 const MCExpr *Offset;
3378 SMLoc OffsetLoc = Lexer.getLoc();
3379 if (checkForValidSection() || parseExpression(Offset))
3380 return true;
3381
3382 // Parse optional fill expression.
3383 int64_t FillExpr = 0;
3384 if (parseOptionalToken(AsmToken::Comma))
3385 if (parseAbsoluteExpression(FillExpr))
3386 return true;
3387 if (parseEOL())
3388 return true;
3389
3390 getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
3391 return false;
3392}
3393
3394/// parseDirectiveAlign
3395/// ::= {.align, ...} expression [ , expression [ , expression ]]
3396bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
3397 SMLoc AlignmentLoc = getLexer().getLoc();
3398 int64_t Alignment;
3399 SMLoc MaxBytesLoc;
3400 bool HasFillExpr = false;
3401 int64_t FillExpr = 0;
3402 int64_t MaxBytesToFill = 0;
3403
3404 auto parseAlign = [&]() -> bool {
3405 if (parseAbsoluteExpression(Alignment))
3406 return true;
3407 if (parseOptionalToken(AsmToken::Comma)) {
3408 // The fill expression can be omitted while specifying a maximum number of
3409 // alignment bytes, e.g:
3410 // .align 3,,4
3411 if (getTok().isNot(AsmToken::Comma)) {
3412 HasFillExpr = true;
3413 if (parseAbsoluteExpression(FillExpr))
3414 return true;
3415 }
3416 if (parseOptionalToken(AsmToken::Comma))
3417 if (parseTokenLoc(MaxBytesLoc) ||
3418 parseAbsoluteExpression(MaxBytesToFill))
3419 return true;
3420 }
3421 return parseEOL();
3422 };
3423
3424 if (checkForValidSection())
3425 return true;
3426 // Ignore empty '.p2align' directives for GNU-as compatibility
3427 if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
3428 Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
3429 return parseEOL();
3430 }
3431 if (parseAlign())
3432 return true;
3433
3434 // Always emit an alignment here even if we thrown an error.
3435 bool ReturnVal = false;
3436
3437 // Compute alignment in bytes.
3438 if (IsPow2) {
3439 // FIXME: Diagnose overflow.
3440 if (Alignment >= 32) {
3441 ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
3442 Alignment = 31;
3443 }
3444
3445 Alignment = 1ULL << Alignment;
3446 } else {
3447 // Reject alignments that aren't either a power of two or zero,
3448 // for gas compatibility. Alignment of zero is silently rounded
3449 // up to one.
3450 if (Alignment == 0)
3451 Alignment = 1;
3452 else if (!isPowerOf2_64(Alignment)) {
3453 ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
3454 Alignment = llvm::bit_floor<uint64_t>(Alignment);
3455 }
3456 if (!isUInt<32>(Alignment)) {
3457 ReturnVal |= Error(AlignmentLoc, "alignment must be smaller than 2**32");
3458 Alignment = 1u << 31;
3459 }
3460 }
3461
3462 // Diagnose non-sensical max bytes to align.
3463 if (MaxBytesLoc.isValid()) {
3464 if (MaxBytesToFill < 1) {
3465 ReturnVal |= Error(MaxBytesLoc,
3466 "alignment directive can never be satisfied in this "
3467 "many bytes, ignoring maximum bytes expression");
3468 MaxBytesToFill = 0;
3469 }
3470
3471 if (MaxBytesToFill >= Alignment) {
3472 Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
3473 "has no effect");
3474 MaxBytesToFill = 0;
3475 }
3476 }
3477
3478 // Check whether we should use optimal code alignment for this .align
3479 // directive.
3480 const MCSection *Section = getStreamer().getCurrentSectionOnly();
3481 assert(Section && "must have section to emit alignment");
3482 bool useCodeAlign = Section->useCodeAlign();
3483 if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
3484 ValueSize == 1 && useCodeAlign) {
3485 getStreamer().emitCodeAlignment(
3486 Align(Alignment), &getTargetParser().getSTI(), MaxBytesToFill);
3487 } else {
3488 // FIXME: Target specific behavior about how the "extra" bytes are filled.
3489 getStreamer().emitValueToAlignment(Align(Alignment), FillExpr, ValueSize,
3490 MaxBytesToFill);
3491 }
3492
3493 return ReturnVal;
3494}
3495
3496/// parseDirectiveFile
3497/// ::= .file filename
3498/// ::= .file number [directory] filename [md5 checksum] [source source-text]
3499bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
3500 // FIXME: I'm not sure what this is.
3501 int64_t FileNumber = -1;
3502 if (getLexer().is(AsmToken::Integer)) {
3503 FileNumber = getTok().getIntVal();
3504 Lex();
3505
3506 if (FileNumber < 0)
3507 return TokError("negative file number");
3508 }
3509
3510 std::string Path;
3511
3512 // Usually the directory and filename together, otherwise just the directory.
3513 // Allow the strings to have escaped octal character sequence.
3514 if (parseEscapedString(Path))
3515 return true;
3516
3517 StringRef Directory;
3519 std::string FilenameData;
3520 if (getLexer().is(AsmToken::String)) {
3521 if (check(FileNumber == -1,
3522 "explicit path specified, but no file number") ||
3523 parseEscapedString(FilenameData))
3524 return true;
3525 Filename = FilenameData;
3526 Directory = Path;
3527 } else {
3528 Filename = Path;
3529 }
3530
3531 uint64_t MD5Hi, MD5Lo;
3532 bool HasMD5 = false;
3533
3534 std::optional<StringRef> Source;
3535 bool HasSource = false;
3536 std::string SourceString;
3537
3538 while (!parseOptionalToken(AsmToken::EndOfStatement)) {
3540 if (check(getTok().isNot(AsmToken::Identifier),
3541 "unexpected token in '.file' directive") ||
3542 parseIdentifier(Keyword))
3543 return true;
3544 if (Keyword == "md5") {
3545 HasMD5 = true;
3546 if (check(FileNumber == -1,
3547 "MD5 checksum specified, but no file number") ||
3548 parseHexOcta(*this, MD5Hi, MD5Lo))
3549 return true;
3550 } else if (Keyword == "source") {
3551 HasSource = true;
3552 if (check(FileNumber == -1,
3553 "source specified, but no file number") ||
3554 check(getTok().isNot(AsmToken::String),
3555 "unexpected token in '.file' directive") ||
3556 parseEscapedString(SourceString))
3557 return true;
3558 } else {
3559 return TokError("unexpected token in '.file' directive");
3560 }
3561 }
3562
3563 if (FileNumber == -1) {
3564 // Ignore the directive if there is no number and the target doesn't support
3565 // numberless .file directives. This allows some portability of assembler
3566 // between different object file formats.
3567 if (getContext().getAsmInfo()->hasSingleParameterDotFile())
3568 getStreamer().emitFileDirective(Filename);
3569 } else {
3570 // In case there is a -g option as well as debug info from directive .file,
3571 // we turn off the -g option, directly use the existing debug info instead.
3572 // Throw away any implicit file table for the assembler source.
3573 if (Ctx.getGenDwarfForAssembly()) {
3575 Ctx.setGenDwarfForAssembly(false);
3576 }
3577
3578 std::optional<MD5::MD5Result> CKMem;
3579 if (HasMD5) {
3580 MD5::MD5Result Sum;
3581 for (unsigned i = 0; i != 8; ++i) {
3582 Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
3583 Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
3584 }
3585 CKMem = Sum;
3586 }
3587 if (HasSource) {
3588 char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
3589 memcpy(SourceBuf, SourceString.data(), SourceString.size());
3590 Source = StringRef(SourceBuf, SourceString.size());
3591 }
3592 if (FileNumber == 0) {
3593 // Upgrade to Version 5 for assembly actions like clang -c a.s.
3594 if (Ctx.getDwarfVersion() < 5)
3595 Ctx.setDwarfVersion(5);
3596 getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
3597 } else {
3598 Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
3599 FileNumber, Directory, Filename, CKMem, Source);
3600 if (!FileNumOrErr)
3601 return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
3602 }
3603 // Alert the user if there are some .file directives with MD5 and some not.
3604 // But only do that once.
3605 if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
3606 ReportedInconsistentMD5 = true;
3607 return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
3608 }
3609 }
3610
3611 return false;
3612}
3613
3614/// parseDirectiveLine
3615/// ::= .line [number]
3616bool AsmParser::parseDirectiveLine() {
3617 int64_t LineNumber;
3618 if (getLexer().is(AsmToken::Integer)) {
3619 if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
3620 return true;
3621 (void)LineNumber;
3622 // FIXME: Do something with the .line.
3623 }
3624 return parseEOL();
3625}
3626
3627/// parseDirectiveLoc
3628/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
3629/// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
3630/// The first number is a file number, must have been previously assigned with
3631/// a .file directive, the second number is the line number and optionally the
3632/// third number is a column position (zero if not specified). The remaining
3633/// optional items are .loc sub-directives.
3634bool AsmParser::parseDirectiveLoc() {
3635 int64_t FileNumber = 0, LineNumber = 0;
3636 SMLoc Loc = getTok().getLoc();
3637 if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
3638 check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
3639 "file number less than one in '.loc' directive") ||
3640 check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
3641 "unassigned file number in '.loc' directive"))
3642 return true;
3643
3644 // optional
3645 if (getLexer().is(AsmToken::Integer)) {
3646 LineNumber = getTok().getIntVal();
3647 if (LineNumber < 0)
3648 return TokError("line number less than zero in '.loc' directive");
3649 Lex();
3650 }
3651
3652 int64_t ColumnPos = 0;
3653 if (getLexer().is(AsmToken::Integer)) {
3654 ColumnPos = getTok().getIntVal();
3655 if (ColumnPos < 0)
3656 return TokError("column position less than zero in '.loc' directive");
3657 Lex();
3658 }
3659
3660 auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
3661 unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
3662 unsigned Isa = 0;
3663 int64_t Discriminator = 0;
3664
3665 auto parseLocOp = [&]() -> bool {
3667 SMLoc Loc = getTok().getLoc();
3668 if (parseIdentifier(Name))
3669 return TokError("unexpected token in '.loc' directive");
3670
3671 if (Name == "basic_block")
3673 else if (Name == "prologue_end")
3675 else if (Name == "epilogue_begin")
3677 else if (Name == "is_stmt") {
3678 Loc = getTok().getLoc();
3679 const MCExpr *Value;
3680 if (parseExpression(Value))
3681 return true;
3682 // The expression must be the constant 0 or 1.
3683 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3684 int Value = MCE->getValue();
3685 if (Value == 0)
3686 Flags &= ~DWARF2_FLAG_IS_STMT;
3687 else if (Value == 1)
3689 else
3690 return Error(Loc, "is_stmt value not 0 or 1");
3691 } else {
3692 return Error(Loc, "is_stmt value not the constant value of 0 or 1");
3693 }
3694 } else if (Name == "isa") {
3695 Loc = getTok().getLoc();
3696 const MCExpr *Value;
3697 if (parseExpression(Value))
3698 return true;
3699 // The expression must be a constant greater or equal to 0.
3700 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3701 int Value = MCE->getValue();
3702 if (Value < 0)
3703 return Error(Loc, "isa number less than zero");
3704 Isa = Value;
3705 } else {
3706 return Error(Loc, "isa number not a constant value");
3707 }
3708 } else if (Name == "discriminator") {
3709 if (parseAbsoluteExpression(Discriminator))
3710 return true;
3711 } else {
3712 return Error(Loc, "unknown sub-directive in '.loc' directive");
3713 }
3714 return false;
3715 };
3716
3717 if (parseMany(parseLocOp, false /*hasComma*/))
3718 return true;
3719
3720 getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
3721 Isa, Discriminator, StringRef());
3722
3723 return false;
3724}
3725
3726/// parseDirectiveStabs
3727/// ::= .stabs string, number, number, number
3728bool AsmParser::parseDirectiveStabs() {
3729 return TokError("unsupported directive '.stabs'");
3730}
3731
3732/// parseDirectiveCVFile
3733/// ::= .cv_file number filename [checksum] [checksumkind]
3734bool AsmParser::parseDirectiveCVFile() {
3735 SMLoc FileNumberLoc = getTok().getLoc();
3736 int64_t FileNumber;
3737 std::string Filename;
3738 std::string Checksum;
3739 int64_t ChecksumKind = 0;
3740
3741 if (parseIntToken(FileNumber,
3742 "expected file number in '.cv_file' directive") ||
3743 check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
3744 check(getTok().isNot(AsmToken::String),
3745 "unexpected token in '.cv_file' directive") ||
3746 parseEscapedString(Filename))
3747 return true;
3748 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
3749 if (check(getTok().isNot(AsmToken::String),
3750 "unexpected token in '.cv_file' directive") ||
3751 parseEscapedString(Checksum) ||
3752 parseIntToken(ChecksumKind,
3753 "expected checksum kind in '.cv_file' directive") ||
3754 parseEOL())
3755 return true;
3756 }
3757
3758 Checksum = fromHex(Checksum);
3759 void *CKMem = Ctx.allocate(Checksum.size(), 1);
3760 memcpy(CKMem, Checksum.data(), Checksum.size());
3761 ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
3762 Checksum.size());
3763
3764 if (!getStreamer().emitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
3765 static_cast<uint8_t>(ChecksumKind)))
3766 return Error(FileNumberLoc, "file number already allocated");
3767
3768 return false;
3769}
3770
3771bool AsmParser::parseCVFunctionId(int64_t &FunctionId,
3772 StringRef DirectiveName) {
3773 SMLoc Loc;
3774 return parseTokenLoc(Loc) ||
3775 parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
3776 "' directive") ||
3777 check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
3778 "expected function id within range [0, UINT_MAX)");
3779}
3780
3781bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
3782 SMLoc Loc;
3783 return parseTokenLoc(Loc) ||
3784 parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
3785 "' directive") ||
3786 check(FileNumber < 1, Loc, "file number less than one in '" +
3787 DirectiveName + "' directive") ||
3788 check(!getCVContext().isValidFileNumber(FileNumber), Loc,
3789 "unassigned file number in '" + DirectiveName + "' directive");
3790}
3791
3792/// parseDirectiveCVFuncId
3793/// ::= .cv_func_id FunctionId
3794///
3795/// Introduces a function ID that can be used with .cv_loc.
3796bool AsmParser::parseDirectiveCVFuncId() {
3797 SMLoc FunctionIdLoc = getTok().getLoc();
3798 int64_t FunctionId;
3799
3800 if (parseCVFunctionId(FunctionId, ".cv_func_id") || parseEOL())
3801 return true;
3802
3803 if (!getStreamer().emitCVFuncIdDirective(FunctionId))
3804 return Error(FunctionIdLoc, "function id already allocated");
3805
3806 return false;
3807}
3808
3809/// parseDirectiveCVInlineSiteId
3810/// ::= .cv_inline_site_id FunctionId
3811/// "within" IAFunc
3812/// "inlined_at" IAFile IALine [IACol]
3813///
3814/// Introduces a function ID that can be used with .cv_loc. Includes "inlined
3815/// at" source location information for use in the line table of the caller,
3816/// whether the caller is a real function or another inlined call site.
3817bool AsmParser::parseDirectiveCVInlineSiteId() {
3818 SMLoc FunctionIdLoc = getTok().getLoc();
3819 int64_t FunctionId;
3820 int64_t IAFunc;
3821 int64_t IAFile;
3822 int64_t IALine;
3823 int64_t IACol = 0;
3824
3825 // FunctionId
3826 if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
3827 return true;
3828
3829 // "within"
3830 if (check((getLexer().isNot(AsmToken::Identifier) ||
3831 getTok().getIdentifier() != "within"),
3832 "expected 'within' identifier in '.cv_inline_site_id' directive"))
3833 return true;
3834 Lex();
3835
3836 // IAFunc
3837 if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
3838 return true;
3839
3840 // "inlined_at"
3841 if (check((getLexer().isNot(AsmToken::Identifier) ||
3842 getTok().getIdentifier() != "inlined_at"),
3843 "expected 'inlined_at' identifier in '.cv_inline_site_id' "
3844 "directive") )
3845 return true;
3846 Lex();
3847
3848 // IAFile IALine
3849 if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
3850 parseIntToken(IALine, "expected line number after 'inlined_at'"))
3851 return true;
3852
3853 // [IACol]
3854 if (getLexer().is(AsmToken::Integer)) {
3855 IACol = getTok().getIntVal();
3856 Lex();
3857 }
3858
3859 if (parseEOL())
3860 return true;
3861
3862 if (!getStreamer().emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
3863 IALine, IACol, FunctionIdLoc))
3864 return Error(FunctionIdLoc, "function id already allocated");
3865
3866 return false;
3867}
3868
3869/// parseDirectiveCVLoc
3870/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
3871/// [is_stmt VALUE]
3872/// The first number is a file number, must have been previously assigned with
3873/// a .file directive, the second number is the line number and optionally the
3874/// third number is a column position (zero if not specified). The remaining
3875/// optional items are .loc sub-directives.
3876bool AsmParser::parseDirectiveCVLoc() {
3877 SMLoc DirectiveLoc = getTok().getLoc();
3878 int64_t FunctionId, FileNumber;
3879 if (parseCVFunctionId(FunctionId, ".cv_loc") ||
3880 parseCVFileId(FileNumber, ".cv_loc"))
3881 return true;
3882
3883 int64_t LineNumber = 0;
3884 if (getLexer().is(AsmToken::Integer)) {
3885 LineNumber = getTok().getIntVal();
3886 if (LineNumber < 0)
3887 return TokError("line number less than zero in '.cv_loc' directive");
3888 Lex();
3889 }
3890
3891 int64_t ColumnPos = 0;
3892 if (getLexer().is(AsmToken::Integer)) {
3893 ColumnPos = getTok().getIntVal();
3894 if (ColumnPos < 0)
3895 return TokError("column position less than zero in '.cv_loc' directive");
3896 Lex();
3897 }
3898
3899 bool PrologueEnd = false;
3900 uint64_t IsStmt = 0;
3901
3902 auto parseOp = [&]() -> bool {
3904 SMLoc Loc = getTok().getLoc();
3905 if (parseIdentifier(Name))
3906 return TokError("unexpected token in '.cv_loc' directive");
3907 if (Name == "prologue_end")
3908 PrologueEnd = true;
3909 else if (Name == "is_stmt") {
3910 Loc = getTok().getLoc();
3911 const MCExpr *Value;
3912 if (parseExpression(Value))
3913 return true;
3914 // The expression must be the constant 0 or 1.
3915 IsStmt = ~0ULL;
3916 if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
3917 IsStmt = MCE->getValue();
3918
3919 if (IsStmt > 1)
3920 return Error(Loc, "is_stmt value not 0 or 1");
3921 } else {
3922 return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
3923 }
3924 return false;
3925 };
3926
3927 if (parseMany(parseOp, false /*hasComma*/))
3928 return true;
3929
3930 getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
3931 ColumnPos, PrologueEnd, IsStmt, StringRef(),
3932 DirectiveLoc);
3933 return false;
3934}
3935
3936/// parseDirectiveCVLinetable
3937/// ::= .cv_linetable FunctionId, FnStart, FnEnd
3938bool AsmParser::parseDirectiveCVLinetable() {
3939 int64_t FunctionId;
3940 StringRef FnStartName, FnEndName;
3941 SMLoc Loc = getTok().getLoc();
3942 if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() ||
3943 parseTokenLoc(Loc) ||
3944 check(parseIdentifier(FnStartName), Loc,
3945 "expected identifier in directive") ||
3946 parseComma() || parseTokenLoc(Loc) ||
3947 check(parseIdentifier(FnEndName), Loc,
3948 "expected identifier in directive"))
3949 return true;
3950
3951 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
3952 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
3953
3954 getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
3955 return false;
3956}
3957
3958/// parseDirectiveCVInlineLinetable
3959/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
3960bool AsmParser::parseDirectiveCVInlineLinetable() {
3961 int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
3962 StringRef FnStartName, FnEndName;
3963 SMLoc Loc = getTok().getLoc();
3964 if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
3965 parseTokenLoc(Loc) ||
3966 parseIntToken(
3967 SourceFileId,
3968 "expected SourceField in '.cv_inline_linetable' directive") ||
3969 check(SourceFileId <= 0, Loc,
3970 "File id less than zero in '.cv_inline_linetable' directive") ||
3971 parseTokenLoc(Loc) ||
3972 parseIntToken(
3973 SourceLineNum,
3974 "expected SourceLineNum in '.cv_inline_linetable' directive") ||
3975 check(SourceLineNum < 0, Loc,
3976 "Line number less than zero in '.cv_inline_linetable' directive") ||
3977 parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
3978 "expected identifier in directive") ||
3979 parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
3980 "expected identifier in directive"))
3981 return true;
3982
3983 if (parseEOL())
3984 return true;
3985
3986 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
3987 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
3988 getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
3989 SourceLineNum, FnStartSym,
3990 FnEndSym);
3991 return false;
3992}
3993
3994void AsmParser::initializeCVDefRangeTypeMap() {
3995 CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
3996 CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
3997 CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
3998 CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
3999}
4000
4001/// parseDirectiveCVDefRange
4002/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
4003bool AsmParser::parseDirectiveCVDefRange() {
4004 SMLoc Loc;
4005 std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
4006 while (getLexer().is(AsmToken::Identifier)) {
4007 Loc = getLexer().getLoc();
4008 StringRef GapStartName;
4009 if (parseIdentifier(GapStartName))
4010 return Error(Loc, "expected identifier in directive");
4011 MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
4012
4013 Loc = getLexer().getLoc();
4014 StringRef GapEndName;
4015 if (parseIdentifier(GapEndName))
4016 return Error(Loc, "expected identifier in directive");
4017 MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
4018
4019 Ranges.push_back({GapStartSym, GapEndSym});
4020 }
4021
4022 StringRef CVDefRangeTypeStr;
4023 if (parseToken(
4025 "expected comma before def_range type in .cv_def_range directive") ||
4026 parseIdentifier(CVDefRangeTypeStr))
4027 return Error(Loc, "expected def_range type in directive");
4028
4030 CVDefRangeTypeMap.find(CVDefRangeTypeStr);
4031 CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
4032 ? CVDR_DEFRANGE
4033 : CVTypeIt->getValue();
4034 switch (CVDRType) {
4035 case CVDR_DEFRANGE_REGISTER: {
4036 int64_t DRRegister;
4037 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4038 ".cv_def_range directive") ||
4039 parseAbsoluteExpression(DRRegister))
4040 return Error(Loc, "expected register number");
4041
4043 DRHdr.Register = DRRegister;
4044 DRHdr.MayHaveNoName = 0;
4045 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4046 break;
4047 }
4048 case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
4049 int64_t DROffset;
4050 if (parseToken(AsmToken::Comma,
4051 "expected comma before offset in .cv_def_range directive") ||
4052 parseAbsoluteExpression(DROffset))
4053 return Error(Loc, "expected offset value");
4054
4056 DRHdr.Offset = DROffset;
4057 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4058 break;
4059 }
4060 case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
4061 int64_t DRRegister;
4062 int64_t DROffsetInParent;
4063 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4064 ".cv_def_range directive") ||
4065 parseAbsoluteExpression(DRRegister))
4066 return Error(Loc, "expected register number");
4067 if (parseToken(AsmToken::Comma,
4068 "expected comma before offset in .cv_def_range directive") ||
4069 parseAbsoluteExpression(DROffsetInParent))
4070 return Error(Loc, "expected offset value");
4071
4073 DRHdr.Register = DRRegister;
4074 DRHdr.MayHaveNoName = 0;
4075 DRHdr.OffsetInParent = DROffsetInParent;
4076 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4077 break;
4078 }
4079 case CVDR_DEFRANGE_REGISTER_REL: {
4080 int64_t DRRegister;
4081 int64_t DRFlags;
4082 int64_t DRBasePointerOffset;
4083 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4084 ".cv_def_range directive") ||
4085 parseAbsoluteExpression(DRRegister))
4086 return Error(Loc, "expected register value");
4087 if (parseToken(
4089 "expected comma before flag value in .cv_def_range directive") ||
4090 parseAbsoluteExpression(DRFlags))
4091 return Error(Loc, "expected flag value");
4092 if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
4093 "in .cv_def_range directive") ||
4094 parseAbsoluteExpression(DRBasePointerOffset))
4095 return Error(Loc, "expected base pointer offset value");
4096
4098 DRHdr.Register = DRRegister;
4099 DRHdr.Flags = DRFlags;
4100 DRHdr.BasePointerOffset = DRBasePointerOffset;
4101 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4102 break;
4103 }
4104 default:
4105 return Error(Loc, "unexpected def_range type in .cv_def_range directive");
4106 }
4107 return true;
4108}
4109
4110/// parseDirectiveCVString
4111/// ::= .cv_stringtable "string"
4112bool AsmParser::parseDirectiveCVString() {
4113 std::string Data;
4114 if (checkForValidSection() || parseEscapedString(Data))
4115 return true;
4116
4117 // Put the string in the table and emit the offset.
4118 std::pair<StringRef, unsigned> Insertion =
4119 getCVContext().addToStringTable(Data);
4120 getStreamer().emitInt32(Insertion.second);
4121 return false;
4122}
4123
4124/// parseDirectiveCVStringTable
4125/// ::= .cv_stringtable
4126bool AsmParser::parseDirectiveCVStringTable() {
4127 getStreamer().emitCVStringTableDirective();
4128 return false;
4129}
4130
4131/// parseDirectiveCVFileChecksums
4132/// ::= .cv_filechecksums
4133bool AsmParser::parseDirectiveCVFileChecksums() {
4134 getStreamer().emitCVFileChecksumsDirective();
4135 return false;
4136}
4137
4138/// parseDirectiveCVFileChecksumOffset
4139/// ::= .cv_filechecksumoffset fileno
4140bool AsmParser::parseDirectiveCVFileChecksumOffset() {
4141 int64_t FileNo;
4142 if (parseIntToken(FileNo, "expected identifier in directive"))
4143 return true;
4144 if (parseEOL())
4145 return true;
4146 getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
4147 return false;
4148}
4149
4150/// parseDirectiveCVFPOData
4151/// ::= .cv_fpo_data procsym
4152bool AsmParser::parseDirectiveCVFPOData() {
4153 SMLoc DirLoc = getLexer().getLoc();
4154 StringRef ProcName;
4155 if (parseIdentifier(ProcName))
4156 return TokError("expected symbol name");
4157 if (parseEOL())
4158 return true;
4159 MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
4160 getStreamer().emitCVFPOData(ProcSym, DirLoc);
4161 return false;
4162}
4163
4164/// parseDirectiveCFISections
4165/// ::= .cfi_sections section [, section]
4166bool AsmParser::parseDirectiveCFISections() {
4168 bool EH = false;
4169 bool Debug = false;
4170
4171 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4172 for (;;) {
4173 if (parseIdentifier(Name))
4174 return TokError("expected .eh_frame or .debug_frame");
4175 if (Name == ".eh_frame")
4176 EH = true;
4177 else if (Name == ".debug_frame")
4178 Debug = true;
4179 if (parseOptionalToken(AsmToken::EndOfStatement))
4180 break;
4181 if (parseComma())
4182 return true;
4183 }
4184 }
4185 getStreamer().emitCFISections(EH, Debug);
4186 return false;
4187}
4188
4189/// parseDirectiveCFIStartProc
4190/// ::= .cfi_startproc [simple]
4191bool AsmParser::parseDirectiveCFIStartProc() {
4193 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4194 if (check(parseIdentifier(Simple) || Simple != "simple",
4195 "unexpected token") ||
4196 parseEOL())
4197 return true;
4198 }
4199
4200 // TODO(kristina): Deal with a corner case of incorrect diagnostic context
4201 // being produced if this directive is emitted as part of preprocessor macro
4202 // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
4203 // Tools like llvm-mc on the other hand are not affected by it, and report
4204 // correct context information.
4205 getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
4206 return false;
4207}
4208
4209/// parseDirectiveCFIEndProc
4210/// ::= .cfi_endproc
4211bool AsmParser::parseDirectiveCFIEndProc() {
4212 if (parseEOL())
4213 return true;
4214 getStreamer().emitCFIEndProc();
4215 return false;
4216}
4217
4218/// parse register name or number.
4219bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
4220 SMLoc DirectiveLoc) {
4221 MCRegister RegNo;
4222
4223 if (getLexer().isNot(AsmToken::Integer)) {
4224 if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc))
4225 return true;
4226 Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
4227 } else
4228 return parseAbsoluteExpression(Register);
4229
4230 return false;
4231}
4232
4233/// parseDirectiveCFIDefCfa
4234/// ::= .cfi_def_cfa register, offset
4235bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
4236 int64_t Register = 0, Offset = 0;
4237 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4238 parseAbsoluteExpression(Offset) || parseEOL())
4239 return true;
4240
4241 getStreamer().emitCFIDefCfa(Register, Offset);
4242 return false;
4243}
4244
4245/// parseDirectiveCFIDefCfaOffset
4246/// ::= .cfi_def_cfa_offset offset
4247bool AsmParser::parseDirectiveCFIDefCfaOffset() {
4248 int64_t Offset = 0;
4249 if (parseAbsoluteExpression(Offset) || parseEOL())
4250 return true;
4251
4252 getStreamer().emitCFIDefCfaOffset(Offset);
4253 return false;
4254}
4255
4256/// parseDirectiveCFIRegister
4257/// ::= .cfi_register register, register
4258bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
4259 int64_t Register1 = 0, Register2 = 0;
4260 if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || parseComma() ||
4261 parseRegisterOrRegisterNumber(Register2, DirectiveLoc) || parseEOL())
4262 return true;
4263
4264 getStreamer().emitCFIRegister(Register1, Register2);
4265 return false;
4266}
4267
4268/// parseDirectiveCFIWindowSave
4269/// ::= .cfi_window_save
4270bool AsmParser::parseDirectiveCFIWindowSave() {
4271 if (parseEOL())
4272 return true;
4273 getStreamer().emitCFIWindowSave();
4274 return false;
4275}
4276
4277/// parseDirectiveCFIAdjustCfaOffset
4278/// ::= .cfi_adjust_cfa_offset adjustment
4279bool AsmParser::parseDirectiveCFIAdjustCfaOffset() {
4280 int64_t Adjustment = 0;
4281 if (parseAbsoluteExpression(Adjustment) || parseEOL())
4282 return true;
4283
4284 getStreamer().emitCFIAdjustCfaOffset(Adjustment);
4285 return false;
4286}
4287
4288/// parseDirectiveCFIDefCfaRegister
4289/// ::= .cfi_def_cfa_register register
4290bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
4291 int64_t Register = 0;
4292 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4293 return true;
4294
4295 getStreamer().emitCFIDefCfaRegister(Register);
4296 return false;
4297}
4298
4299/// parseDirectiveCFILLVMDefAspaceCfa
4300/// ::= .cfi_llvm_def_aspace_cfa register, offset, address_space
4301bool AsmParser::parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc) {
4302 int64_t Register = 0, Offset = 0, AddressSpace = 0;
4303 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4304 parseAbsoluteExpression(Offset) || parseComma() ||
4305 parseAbsoluteExpression(AddressSpace) || parseEOL())
4306 return true;
4307
4308 getStreamer().emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace);
4309 return false;
4310}
4311
4312/// parseDirectiveCFIOffset
4313/// ::= .cfi_offset register, offset
4314bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
4315 int64_t Register = 0;
4316 int64_t Offset = 0;
4317
4318 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4319 parseAbsoluteExpression(Offset) || parseEOL())
4320 return true;
4321
4322 getStreamer().emitCFIOffset(Register, Offset);
4323 return false;
4324}
4325
4326/// parseDirectiveCFIRelOffset
4327/// ::= .cfi_rel_offset register, offset
4328bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
4329 int64_t Register = 0, Offset = 0;
4330
4331 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4332 parseAbsoluteExpression(Offset) || parseEOL())
4333 return true;
4334
4335 getStreamer().emitCFIRelOffset(Register, Offset);
4336 return false;
4337}
4338
4339static bool isValidEncoding(int64_t Encoding) {
4340 if (Encoding & ~0xff)
4341 return false;
4342
4343 if (Encoding == dwarf::DW_EH_PE_omit)
4344 return true;
4345
4346 const unsigned Format = Encoding & 0xf;
4347 if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
4348 Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
4349 Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
4350 Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
4351 return false;
4352
4353 const unsigned Application = Encoding & 0x70;
4354 if (Application != dwarf::DW_EH_PE_absptr &&
4355 Application != dwarf::DW_EH_PE_pcrel)
4356 return false;
4357
4358 return true;
4359}
4360
4361/// parseDirectiveCFIPersonalityOrLsda
4362/// IsPersonality true for cfi_personality, false for cfi_lsda
4363/// ::= .cfi_personality encoding, [symbol_name]
4364/// ::= .cfi_lsda encoding, [symbol_name]
4365bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
4366 int64_t Encoding = 0;
4367 if (parseAbsoluteExpression(Encoding))
4368 return true;
4369 if (Encoding == dwarf::DW_EH_PE_omit)
4370 return false;
4371
4373 if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
4374 parseComma() ||
4375 check(parseIdentifier(Name), "expected identifier in directive") ||
4376 parseEOL())
4377 return true;
4378
4379 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4380
4381 if (IsPersonality)
4382 getStreamer().emitCFIPersonality(Sym, Encoding);
4383 else
4384 getStreamer().emitCFILsda(Sym, Encoding);
4385 return false;
4386}
4387
4388/// parseDirectiveCFIRememberState
4389/// ::= .cfi_remember_state
4390bool AsmParser::parseDirectiveCFIRememberState() {
4391 if (parseEOL())
4392 return true;
4393 getStreamer().emitCFIRememberState();
4394 return false;
4395}
4396
4397/// parseDirectiveCFIRestoreState
4398/// ::= .cfi_remember_state
4399bool AsmParser::parseDirectiveCFIRestoreState() {
4400 if (parseEOL())
4401 return true;
4402 getStreamer().emitCFIRestoreState();
4403 return false;
4404}
4405
4406/// parseDirectiveCFISameValue
4407/// ::= .cfi_same_value register
4408bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
4409 int64_t Register = 0;
4410
4411 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4412 return true;
4413
4414 getStreamer().emitCFISameValue(Register);
4415 return false;
4416}
4417
4418/// parseDirectiveCFIRestore
4419/// ::= .cfi_restore register
4420bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
4421 int64_t Register = 0;
4422 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4423 return true;
4424
4425 getStreamer().emitCFIRestore(Register);
4426 return false;
4427}
4428
4429/// parseDirectiveCFIEscape
4430/// ::= .cfi_escape expression[,...]
4431bool AsmParser::parseDirectiveCFIEscape() {
4432 std::string Values;
4433 int64_t CurrValue;
4434 if (parseAbsoluteExpression(CurrValue))
4435 return true;
4436
4437 Values.push_back((uint8_t)CurrValue);
4438
4439 while (getLexer().is(AsmToken::Comma)) {
4440 Lex();
4441
4442 if (parseAbsoluteExpression(CurrValue))
4443 return true;
4444
4445 Values.push_back((uint8_t)CurrValue);
4446 }
4447
4448 getStreamer().emitCFIEscape(Values);
4449 return false;
4450}
4451
4452/// parseDirectiveCFIReturnColumn
4453/// ::= .cfi_return_column register
4454bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
4455 int64_t Register = 0;
4456 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4457 return true;
4458 getStreamer().emitCFIReturnColumn(Register);
4459 return false;
4460}
4461
4462/// parseDirectiveCFISignalFrame
4463/// ::= .cfi_signal_frame
4464bool AsmParser::parseDirectiveCFISignalFrame() {
4465 if (parseEOL())
4466 return true;
4467
4468 getStreamer().emitCFISignalFrame();
4469 return false;
4470}
4471
4472/// parseDirectiveCFIUndefined
4473/// ::= .cfi_undefined register
4474bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
4475 int64_t Register = 0;
4476
4477 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4478 return true;
4479
4480 getStreamer().emitCFIUndefined(Register);
4481 return false;
4482}
4483
4484/// parseDirectiveAltmacro
4485/// ::= .altmacro
4486/// ::= .noaltmacro
4487bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
4488 if (parseEOL())
4489 return true;
4490 AltMacroMode = (Directive == ".altmacro");
4491 return false;
4492}
4493
4494/// parseDirectiveMacrosOnOff
4495/// ::= .macros_on
4496/// ::= .macros_off
4497bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
4498 if (parseEOL())
4499 return true;
4500 setMacrosEnabled(Directive == ".macros_on");
4501 return false;
4502}
4503
4504/// parseDirectiveMacro
4505/// ::= .macro name[,] [parameters]
4506bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
4508 if (parseIdentifier(Name))
4509 return TokError("expected identifier in '.macro' directive");
4510
4511 if (getLexer().is(AsmToken::Comma))
4512 Lex();
4513
4514 MCAsmMacroParameters Parameters;
4515 while (getLexer().isNot(AsmToken::EndOfStatement)) {
4516
4517 if (!Parameters.empty() && Parameters.back().Vararg)
4518 return Error(Lexer.getLoc(), "vararg parameter '" +
4519 Parameters.back().Name +
4520 "' should be the last parameter");
4521
4522 MCAsmMacroParameter Parameter;
4523 if (parseIdentifier(Parameter.Name))
4524 return TokError("expected identifier in '.macro' directive");
4525
4526 // Emit an error if two (or more) named parameters share the same name
4527 for (const MCAsmMacroParameter& CurrParam : Parameters)
4528 if (CurrParam.Name.equals(Parameter.Name))
4529 return TokError("macro '" + Name + "' has multiple parameters"
4530 " named '" + Parameter.Name + "'");
4531
4532 if (Lexer.is(AsmToken::Colon)) {
4533 Lex(); // consume ':'
4534
4535 SMLoc QualLoc;
4537
4538 QualLoc = Lexer.getLoc();
4539 if (parseIdentifier(Qualifier))
4540 return Error(QualLoc, "missing parameter qualifier for "
4541 "'" + Parameter.Name + "' in macro '" + Name + "'");
4542
4543 if (Qualifier == "req")
4544 Parameter.Required = true;
4545 else if (Qualifier == "vararg")
4546 Parameter.Vararg = true;
4547 else
4548 return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
4549 "for '" + Parameter.Name + "' in macro '" + Name + "'");
4550 }
4551
4552 if (getLexer().is(AsmToken::Equal)) {
4553 Lex();
4554
4555 SMLoc ParamLoc;
4556
4557 ParamLoc = Lexer.getLoc();
4558 if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
4559 return true;
4560
4561 if (Parameter.Required)
4562 Warning(ParamLoc, "pointless default value for required parameter "
4563 "'" + Parameter.Name + "' in macro '" + Name + "'");
4564 }
4565
4566 Parameters.push_back(std::move(Parameter));
4567
4568 if (getLexer().is(AsmToken::Comma))
4569 Lex();
4570 }
4571
4572 // Eat just the end of statement.
4573 Lexer.Lex();
4574
4575 // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors
4576 AsmToken EndToken, StartToken = getTok();
4577 unsigned MacroDepth = 0;
4578 // Lex the macro definition.
4579 while (true) {
4580 // Ignore Lexing errors in macros.
4581 while (Lexer.is(AsmToken::Error)) {
4582 Lexer.Lex();
4583 }
4584
4585 // Check whether we have reached the end of the file.
4586 if (getLexer().is(AsmToken::Eof))
4587 return Error(DirectiveLoc, "no matching '.endmacro' in definition");
4588
4589 // Otherwise, check whether we have reach the .endmacro or the start of a
4590 // preprocessor line marker.
4591 if (getLexer().is(AsmToken::Identifier)) {
4592 if (getTok().getIdentifier() == ".endm" ||
4593 getTok().getIdentifier() == ".endmacro") {
4594 if (MacroDepth == 0) { // Outermost macro.
4595 EndToken = getTok();
4596 Lexer.Lex();
4597 if (getLexer().isNot(AsmToken::EndOfStatement))
4598 return TokError("unexpected token in '" + EndToken.getIdentifier() +
4599 "' directive");
4600 break;
4601 } else {
4602 // Otherwise we just found the end of an inner macro.
4603 --MacroDepth;
4604 }
4605 } else if (getTok().getIdentifier() == ".macro") {
4606 // We allow nested macros. Those aren't instantiated until the outermost
4607 // macro is expanded so just ignore them for now.
4608 ++MacroDepth;
4609 }
4610 } else if (Lexer.is(AsmToken::HashDirective)) {
4611 (void)parseCppHashLineFilenameComment(getLexer().getLoc());
4612 }
4613
4614 // Otherwise, scan til the end of the statement.
4615 eatToEndOfStatement();
4616 }
4617
4618 if (getContext().lookupMacro(Name)) {
4619 return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
4620 }
4621
4622 const char *BodyStart = StartToken.getLoc().getPointer();
4623 const char *BodyEnd = EndToken.getLoc().getPointer();
4624 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4625 checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
4626 MCAsmMacro Macro(Name, Body, std::move(Parameters));
4627 DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
4628 Macro.dump());
4629 getContext().defineMacro(Name, std::move(Macro));
4630 return false;
4631}
4632
4633/// checkForBadMacro
4634///
4635/// With the support added for named parameters there may be code out there that
4636/// is transitioning from positional parameters. In versions of gas that did
4637/// not support named parameters they would be ignored on the macro definition.
4638/// But to support both styles of parameters this is not possible so if a macro
4639/// definition has named parameters but does not use them and has what appears
4640/// to be positional parameters, strings like $1, $2, ... and $n, then issue a
4641/// warning that the positional parameter found in body which have no effect.
4642/// Hoping the developer will either remove the named parameters from the macro
4643/// definition so the positional parameters get used if that was what was
4644/// intended or change the macro to use the named parameters. It is possible
4645/// this warning will trigger when the none of the named parameters are used
4646/// and the strings like $1 are infact to simply to be passed trough unchanged.
4647void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
4648 StringRef Body,
4649 ArrayRef<MCAsmMacroParameter> Parameters) {
4650 // If this macro is not defined with named parameters the warning we are
4651 // checking for here doesn't apply.
4652 unsigned NParameters = Parameters.size();
4653 if (NParameters == 0)
4654 return;
4655
4656 bool NamedParametersFound = false;
4657 bool PositionalParametersFound = false;
4658
4659 // Look at the body of the macro for use of both the named parameters and what
4660 // are likely to be positional parameters. This is what expandMacro() is
4661 // doing when it finds the parameters in the body.
4662 while (!Body.empty()) {
4663 // Scan for the next possible parameter.
4664 std::size_t End = Body.size(), Pos = 0;
4665 for (; Pos != End; ++Pos) {
4666 // Check for a substitution or escape.
4667 // This macro is defined with parameters, look for \foo, \bar, etc.
4668 if (Body[Pos] == '\\' && Pos + 1 != End)
4669 break;
4670
4671 // This macro should have parameters, but look for $0, $1, ..., $n too.
4672 if (Body[Pos] != '$' || Pos + 1 == End)
4673 continue;
4674 char Next = Body[Pos + 1];
4675 if (Next == '$' || Next == 'n' ||
4676 isdigit(static_cast<unsigned char>(Next)))
4677 break;
4678 }
4679
4680 // Check if we reached the end.
4681 if (Pos == End)
4682 break;
4683
4684 if (Body[Pos] == '$') {
4685 switch (Body[Pos + 1]) {
4686 // $$ => $
4687 case '$':
4688 break;
4689
4690 // $n => number of arguments
4691 case 'n':
4692 PositionalParametersFound = true;
4693 break;
4694
4695 // $[0-9] => argument
4696 default: {
4697 PositionalParametersFound = true;
4698 break;
4699 }
4700 }
4701 Pos += 2;
4702 } else {
4703 unsigned I = Pos + 1;
4704 while (isIdentifierChar(Body[I]) && I + 1 != End)
4705 ++I;
4706
4707 const char *Begin = Body.data() + Pos + 1;
4708 StringRef Argument(Begin, I - (Pos + 1));
4709 unsigned Index = 0;
4710 for (; Index < NParameters; ++Index)
4711 if (Parameters[Index].Name == Argument)
4712 break;
4713
4714 if (Index == NParameters) {
4715 if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
4716 Pos += 3;
4717 else {
4718 Pos = I;
4719 }
4720 } else {
4721 NamedParametersFound = true;
4722 Pos += 1 + Argument.size();
4723 }
4724 }
4725 // Update the scan point.
4726 Body = Body.substr(Pos);
4727 }
4728
4729 if (!NamedParametersFound && PositionalParametersFound)
4730 Warning(DirectiveLoc, "macro defined with named parameters which are not "
4731 "used in macro body, possible positional parameter "
4732 "found in body which will have no effect");
4733}
4734
4735/// parseDirectiveExitMacro
4736/// ::= .exitm
4737bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
4738 if (parseEOL())
4739 return true;
4740
4741 if (!isInsideMacroInstantiation())
4742 return TokError("unexpected '" + Directive + "' in file, "
4743 "no current macro definition");
4744
4745 // Exit all conditionals that are active in the current macro.
4746 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4747 TheCondState = TheCondStack.back();
4748 TheCondStack.pop_back();
4749 }
4750
4751 handleMacroExit();
4752 return false;
4753}
4754
4755/// parseDirectiveEndMacro
4756/// ::= .endm
4757/// ::= .endmacro
4758bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
4759 if (getLexer().isNot(AsmToken::EndOfStatement))
4760 return TokError("unexpected token in '" + Directive + "' directive");
4761
4762 // If we are inside a macro instantiation, terminate the current
4763 // instantiation.
4764 if (isInsideMacroInstantiation()) {
4765 handleMacroExit();
4766 return false;
4767 }
4768
4769 // Otherwise, this .endmacro is a stray entry in the file; well formed
4770 // .endmacro directives are handled during the macro definition parsing.
4771 return TokError("unexpected '" + Directive + "' in file, "
4772 "no current macro definition");
4773}
4774
4775/// parseDirectivePurgeMacro
4776/// ::= .purgem name
4777bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4779 SMLoc Loc;
4780 if (parseTokenLoc(Loc) ||
4781 check(parseIdentifier(Name), Loc,
4782 "expected identifier in '.purgem' directive") ||
4783 parseEOL())
4784 return true;
4785
4786 if (!getContext().lookupMacro(Name))
4787 return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
4788
4789 getContext().undefineMacro(Name);
4790 DEBUG_WITH_TYPE("asm-macros", dbgs()
4791 << "Un-defining macro: " << Name << "\n");
4792 return false;
4793}
4794
4795/// parseDirectiveBundleAlignMode
4796/// ::= {.bundle_align_mode} expression
4797bool AsmParser::parseDirectiveBundleAlignMode() {
4798 // Expect a single argument: an expression that evaluates to a constant
4799 // in the inclusive range 0-30.
4800 SMLoc ExprLoc = getLexer().getLoc();
4801 int64_t AlignSizePow2;
4802 if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||
4803 parseEOL() ||
4804 check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc,
4805 "invalid bundle alignment size (expected between 0 and 30)"))
4806 return true;
4807
4808 getStreamer().emitBundleAlignMode(Align(1ULL << AlignSizePow2));
4809 return false;
4810}
4811
4812/// parseDirectiveBundleLock
4813/// ::= {.bundle_lock} [align_to_end]
4814bool AsmParser::parseDirectiveBundleLock() {
4815 if (checkForValidSection())
4816 return true;
4817 bool AlignToEnd = false;
4818
4820 SMLoc Loc = getTok().getLoc();
4821 const char *kInvalidOptionError =
4822 "invalid option for '.bundle_lock' directive";
4823
4824 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4825 if (check(parseIdentifier(Option), Loc, kInvalidOptionError) ||
4826 check(Option != "align_to_end", Loc, kInvalidOptionError) || parseEOL())
4827 return true;
4828 AlignToEnd = true;
4829 }
4830
4831 getStreamer().emitBundleLock(AlignToEnd);
4832 return false;
4833}
4834
4835/// parseDirectiveBundleLock
4836/// ::= {.bundle_lock}
4837bool AsmParser::parseDirectiveBundleUnlock() {
4838 if (checkForValidSection() || parseEOL())
4839 return true;
4840
4841 getStreamer().emitBundleUnlock();
4842 return false;
4843}
4844
4845/// parseDirectiveSpace
4846/// ::= (.skip | .space) expression [ , expression ]
4847bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
4848 SMLoc NumBytesLoc = Lexer.getLoc();
4849 const MCExpr *NumBytes;
4850 if (checkForValidSection() || parseExpression(NumBytes))
4851 return true;
4852
4853 int64_t FillExpr = 0;
4854 if (parseOptionalToken(AsmToken::Comma))
4855 if (parseAbsoluteExpression(FillExpr))
4856 return true;
4857 if (parseEOL())
4858 return true;
4859
4860 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
4861 getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
4862
4863 return false;
4864}
4865
4866/// parseDirectiveDCB
4867/// ::= .dcb.{b, l, w} expression, expression
4868bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
4869 SMLoc NumValuesLoc = Lexer.getLoc();
4870 int64_t NumValues;
4871 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4872 return true;
4873
4874 if (NumValues < 0) {
4875 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4876 return false;
4877 }
4878
4879 if (parseComma())
4880 return true;
4881
4882 const MCExpr *Value;
4883 SMLoc ExprLoc = getLexer().getLoc();
4884 if (parseExpression(Value))
4885 return true;
4886
4887 // Special case constant expressions to match code generator.
4888 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
4889 assert(Size <= 8 && "Invalid size");
4890 uint64_t IntValue = MCE->getValue();
4891 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
4892 return Error(ExprLoc, "literal value out of range for directive");
4893 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4894 getStreamer().emitIntValue(IntValue, Size);
4895 } else {
4896 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4897 getStreamer().emitValue(Value, Size, ExprLoc);
4898 }
4899
4900 return parseEOL();
4901}
4902
4903/// parseDirectiveRealDCB
4904/// ::= .dcb.{d, s} expression, expression
4905bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {
4906 SMLoc NumValuesLoc = Lexer.getLoc();
4907 int64_t NumValues;
4908 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4909 return true;
4910
4911 if (NumValues < 0) {
4912 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4913 return false;
4914 }
4915
4916 if (parseComma())
4917 return true;
4918
4919 APInt AsInt;
4920 if (parseRealValue(Semantics, AsInt) || parseEOL())
4921 return true;
4922
4923 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4924 getStreamer().emitIntValue(AsInt.getLimitedValue(),
4925 AsInt.getBitWidth() / 8);
4926
4927 return false;
4928}
4929
4930/// parseDirectiveDS
4931/// ::= .ds.{b, d, l, p, s, w, x} expression
4932bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {
4933 SMLoc NumValuesLoc = Lexer.getLoc();
4934 int64_t NumValues;
4935 if (checkForValidSection() || parseAbsoluteExpression(NumValues) ||
4936 parseEOL())
4937 return true;
4938
4939 if (NumValues < 0) {
4940 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4941 return false;
4942 }
4943
4944 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4945 getStreamer().emitFill(Size, 0);
4946
4947 return false;
4948}
4949
4950/// parseDirectiveLEB128
4951/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
4952bool AsmParser::parseDirectiveLEB128(bool Signed) {
4953 if (checkForValidSection())
4954 return true;
4955
4956 auto parseOp = [&]() -> bool {
4957 const MCExpr *Value;
4958 if (parseExpression(Value))
4959 return true;
4960 if (Signed)
4961 getStreamer().emitSLEB128Value(Value);
4962 else
4963 getStreamer().emitULEB128Value(Value);
4964 return false;
4965 };
4966
4967 return parseMany(parseOp);
4968}
4969
4970/// parseDirectiveSymbolAttribute
4971/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
4972bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
4973 auto parseOp = [&]() -> bool {
4975 SMLoc Loc = getTok().getLoc();
4976 if (parseIdentifier(Name))
4977 return Error(Loc, "expected identifier");
4978
4979 if (discardLTOSymbol(Name))
4980 return false;
4981
4982 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4983
4984 // Assembler local symbols don't make any sense here, except for directives
4985 // that the symbol should be tagged.
4986 if (Sym->isTemporary() && Attr != MCSA_Memtag)
4987 return Error(Loc, "non-local symbol required");
4988
4989 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4990 return Error(Loc, "unable to emit symbol attribute");
4991 return false;
4992 };
4993
4994 return parseMany(parseOp);
4995}
4996
4997/// parseDirectiveComm
4998/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
4999bool AsmParser::parseDirectiveComm(bool IsLocal) {
5000 if (checkForValidSection())
5001 return true;
5002
5003 SMLoc IDLoc = getLexer().getLoc();
5005 if (parseIdentifier(Name))
5006 return TokError("expected identifier in directive");
5007
5008 // Handle the identifier as the key symbol.
5009 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5010
5011 if (parseComma())
5012 return true;
5013
5014 int64_t Size;
5015 SMLoc SizeLoc = getLexer().getLoc();
5016 if (parseAbsoluteExpression(Size))
5017 return true;
5018
5019 int64_t Pow2Alignment = 0;
5020 SMLoc Pow2AlignmentLoc;
5021 if (getLexer().is(AsmToken::Comma)) {
5022 Lex();
5023 Pow2AlignmentLoc = getLexer().getLoc();
5024 if (parseAbsoluteExpression(Pow2Alignment))
5025 return true;
5026
5027 LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
5028 if (IsLocal && LCOMM == LCOMM::NoAlignment)
5029 return Error(Pow2AlignmentLoc, "alignment not supported on this target");
5030
5031 // If this target takes alignments in bytes (not log) validate and convert.
5032 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
5033 (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
5034 if (!isPowerOf2_64(Pow2Alignment))
5035 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
5036 Pow2Alignment = Log2_64(Pow2Alignment);
5037 }
5038 }
5039
5040 if (parseEOL())
5041 return true;
5042
5043 // NOTE: a size of zero for a .comm should create a undefined symbol
5044 // but a size of .lcomm creates a bss symbol of size zero.
5045 if (Size < 0)
5046 return Error(SizeLoc, "size must be non-negative");
5047
5048 Sym->redefineIfPossible();
5049 if (!Sym->isUndefined())
5050 return Error(IDLoc, "invalid symbol redefinition");
5051
5052 // Create the Symbol as a common or local common with Size and Pow2Alignment
5053 if (IsLocal) {
5054 getStreamer().emitLocalCommonSymbol(Sym, Size,
5055 Align(1ULL << Pow2Alignment));
5056 return false;
5057 }
5058
5059 getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));
5060 return false;
5061}
5062
5063/// parseDirectiveAbort
5064/// ::= .abort [... message ...]
5065bool AsmParser::parseDirectiveAbort() {
5066 // FIXME: Use loc from directive.
5067 SMLoc Loc = getLexer().getLoc();
5068
5069 StringRef Str = parseStringToEndOfStatement();
5070 if (parseEOL())
5071 return true;
5072
5073 if (Str.empty())
5074 return Error(Loc, ".abort detected. Assembly stopping.");
5075 else
5076 return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
5077 // FIXME: Actually abort assembly here.
5078
5079 return false;
5080}
5081
5082/// parseDirectiveInclude
5083/// ::= .include "filename"
5084bool AsmParser::parseDirectiveInclude() {
5085 // Allow the strings to have escaped octal character sequence.
5086 std::string Filename;
5087 SMLoc IncludeLoc = getTok().getLoc();
5088
5089 if (check(getTok().isNot(AsmToken::String),
5090 "expected string in '.include' directive") ||
5091 parseEscapedString(Filename) ||
5093 "unexpected token in '.include' directive") ||
5094 // Attempt to switch the lexer to the included file before consuming the
5095 // end of statement to avoid losing it when we switch.
5096 check(enterIncludeFile(Filename), IncludeLoc,
5097 "Could not find include file '" + Filename + "'"))
5098 return true;
5099
5100 return false;
5101}
5102
5103/// parseDirectiveIncbin
5104/// ::= .incbin "filename" [ , skip [ , count ] ]
5105bool AsmParser::parseDirectiveIncbin() {
5106 // Allow the strings to have escaped octal character sequence.
5107 std::string Filename;
5108 SMLoc IncbinLoc = getTok().getLoc();
5109 if (check(getTok().isNot(AsmToken::String),
5110 "expected string in '.incbin' directive") ||
5111 parseEscapedString(Filename))
5112 return true;
5113
5114 int64_t Skip = 0;
5115 const MCExpr *Count = nullptr;
5116 SMLoc SkipLoc, CountLoc;
5117 if (parseOptionalToken(AsmToken::Comma)) {
5118 // The skip expression can be omitted while specifying the count, e.g:
5119 // .incbin "filename",,4
5120 if (getTok().isNot(AsmToken::Comma)) {
5121 if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))
5122 return true;
5123 }
5124 if (parseOptionalToken(AsmToken::Comma)) {
5125 CountLoc = getTok().getLoc();
5126 if (parseExpression(Count))
5127 return true;
5128 }
5129 }
5130
5131 if (parseEOL())
5132 return true;
5133
5134 if (check(Skip < 0, SkipLoc, "skip is negative"))
5135 return true;
5136
5137 // Attempt to process the included file.
5138 if (processIncbinFile(Filename, Skip, Count, CountLoc))
5139 return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
5140 return false;
5141}
5142
5143/// parseDirectiveIf
5144/// ::= .if{,eq,ge,gt,le,lt,ne} expression
5145bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
5146 TheCondStack.push_back(TheCondState);
5147 TheCondState.TheCond = AsmCond::IfCond;
5148 if (TheCondState.Ignore) {
5149 eatToEndOfStatement();
5150 } else {
5151 int64_t ExprValue;
5152 if (parseAbsoluteExpression(ExprValue) || parseEOL())
5153 return true;
5154
5155 switch (DirKind) {
5156 default:
5157 llvm_unreachable("unsupported directive");
5158 case DK_IF:
5159 case DK_IFNE:
5160 break;
5161 case DK_IFEQ:
5162 ExprValue = ExprValue == 0;
5163 break;
5164 case DK_IFGE:
5165 ExprValue = ExprValue >= 0;
5166 break;
5167 case DK_IFGT:
5168 ExprValue = ExprValue > 0;
5169 break;
5170 case DK_IFLE:
5171 ExprValue = ExprValue <= 0;
5172 break;
5173 case DK_IFLT:
5174 ExprValue = ExprValue < 0;
5175 break;
5176 }
5177
5178 TheCondState.CondMet = ExprValue;
5179 TheCondState.Ignore = !TheCondState.CondMet;
5180 }
5181
5182 return false;
5183}
5184
5185/// parseDirectiveIfb
5186/// ::= .ifb string
5187bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
5188 TheCondStack.push_back(TheCondState);
5189 TheCondState.TheCond = AsmCond::IfCond;
5190
5191 if (TheCondState.Ignore) {
5192 eatToEndOfStatement();
5193 } else {
5194 StringRef Str = parseStringToEndOfStatement();
5195
5196 if (parseEOL())
5197 return true;
5198
5199 TheCondState.CondMet = ExpectBlank == Str.empty();
5200 TheCondState.Ignore = !TheCondState.CondMet;
5201 }
5202
5203 return false;
5204}
5205
5206/// parseDirectiveIfc
5207/// ::= .ifc string1, string2
5208/// ::= .ifnc string1, string2
5209bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
5210 TheCondStack.push_back(TheCondState);
5211 TheCondState.TheCond = AsmCond::IfCond;
5212
5213 if (TheCondState.Ignore) {
5214 eatToEndOfStatement();
5215 } else {
5216 StringRef Str1 = parseStringToComma();
5217
5218 if (parseComma())
5219 return true;
5220
5221 StringRef Str2 = parseStringToEndOfStatement();
5222
5223 if (parseEOL())
5224 return true;
5225
5226 TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
5227 TheCondState.Ignore = !TheCondState.CondMet;
5228 }
5229
5230 return false;
5231}
5232
5233/// parseDirectiveIfeqs
5234/// ::= .ifeqs string1, string2
5235bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
5236 if (Lexer.isNot(AsmToken::String)) {
5237 if (ExpectEqual)
5238 return TokError("expected string parameter for '.ifeqs' directive");
5239 return TokError("expected string parameter for '.ifnes' directive");
5240 }
5241
5242 StringRef String1 = getTok().getStringContents();
5243 Lex();
5244
5245 if (Lexer.isNot(AsmToken::Comma)) {
5246 if (ExpectEqual)
5247 return TokError(
5248 "expected comma after first string for '.ifeqs' directive");
5249 return TokError("expected comma after first string for '.ifnes' directive");
5250 }
5251
5252 Lex();
5253
5254 if (Lexer.isNot(AsmToken::String)) {
5255 if (ExpectEqual)
5256 return TokError("expected string parameter for '.ifeqs' directive");
5257 return TokError("expected string parameter for '.ifnes' directive");
5258 }
5259
5260 StringRef String2 = getTok().getStringContents();
5261 Lex();
5262
5263 TheCondStack.push_back(TheCondState);
5264 TheCondState.TheCond = AsmCond::IfCond;
5265 TheCondState.CondMet = ExpectEqual == (String1 == String2);
5266 TheCondState.Ignore = !TheCondState.CondMet;
5267
5268 return false;
5269}
5270
5271/// parseDirectiveIfdef
5272/// ::= .ifdef symbol
5273bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
5275 TheCondStack.push_back(TheCondState);
5276 TheCondState.TheCond = AsmCond::IfCond;
5277
5278 if (TheCondState.Ignore) {
5279 eatToEndOfStatement();
5280 } else {
5281 if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
5282 parseEOL())
5283 return true;
5284
5285 MCSymbol *Sym = getContext().lookupSymbol(Name);
5286
5287 if (expect_defined)
5288 TheCondState.CondMet = (Sym && !Sym->isUndefined(false));
5289 else
5290 TheCondState.CondMet = (!Sym || Sym->isUndefined(false));
5291 TheCondState.Ignore = !TheCondState.CondMet;
5292 }
5293
5294 return false;
5295}
5296
5297/// parseDirectiveElseIf
5298/// ::= .elseif expression
5299bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
5300 if (TheCondState.TheCond != AsmCond::IfCond &&
5301 TheCondState.TheCond != AsmCond::ElseIfCond)
5302 return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
5303 " .if or an .elseif");
5304 TheCondState.TheCond = AsmCond::ElseIfCond;
5305
5306 bool LastIgnoreState = false;
5307 if (!TheCondStack.empty())
5308 LastIgnoreState = TheCondStack.back().Ignore;
5309 if (LastIgnoreState || TheCondState.CondMet) {
5310 TheCondState.Ignore = true;
5311 eatToEndOfStatement();
5312 } else {
5313 int64_t ExprValue;
5314 if (parseAbsoluteExpression(ExprValue))
5315 return true;
5316
5317 if (parseEOL())
5318 return true;
5319
5320 TheCondState.CondMet = ExprValue;
5321 TheCondState.Ignore = !TheCondState.CondMet;
5322 }
5323
5324 return false;
5325}
5326
5327/// parseDirectiveElse
5328/// ::= .else
5329bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
5330 if (parseEOL())
5331 return true;
5332
5333 if (TheCondState.TheCond != AsmCond::IfCond &&
5334 TheCondState.TheCond != AsmCond::ElseIfCond)
5335 return Error(DirectiveLoc, "Encountered a .else that doesn't follow "
5336 " an .if or an .elseif");
5337 TheCondState.TheCond = AsmCond::ElseCond;
5338 bool LastIgnoreState = false;
5339 if (!TheCondStack.empty())
5340 LastIgnoreState = TheCondStack.back().Ignore;
5341 if (LastIgnoreState || TheCondState.CondMet)
5342 TheCondState.Ignore = true;
5343 else
5344 TheCondState.Ignore = false;
5345
5346 return false;
5347}
5348
5349/// parseDirectiveEnd
5350/// ::= .end
5351bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5352 if (parseEOL())
5353 return true;
5354
5355 while (Lexer.isNot(AsmToken::Eof))
5356 Lexer.Lex();
5357
5358 return false;
5359}
5360
5361/// parseDirectiveError
5362/// ::= .err
5363/// ::= .error [string]
5364bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
5365 if (!TheCondStack.empty()) {
5366 if (TheCondStack.back().Ignore) {
5367 eatToEndOfStatement();
5368 return false;
5369 }
5370 }
5371
5372 if (!WithMessage)
5373 return Error(L, ".err encountered");
5374
5375 StringRef Message = ".error directive invoked in source file";
5376 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5377 if (Lexer.isNot(AsmToken::String))
5378 return TokError(".error argument must be a string");
5379
5380 Message = getTok().getStringContents();
5381 Lex();
5382 }
5383
5384 return Error(L, Message);
5385}
5386
5387/// parseDirectiveWarning
5388/// ::= .warning [string]
5389bool AsmParser::parseDirectiveWarning(SMLoc L) {
5390 if (!TheCondStack.empty()) {
5391 if (TheCondStack.back().Ignore) {
5392 eatToEndOfStatement();
5393 return false;
5394 }
5395 }
5396
5397 StringRef Message = ".warning directive invoked in source file";
5398
5399 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
5400 if (Lexer.isNot(AsmToken::String))
5401 return TokError(".warning argument must be a string");
5402
5403 Message = getTok().getStringContents();
5404 Lex();
5405 if (parseEOL())
5406 return true;
5407 }
5408
5409 return Warning(L, Message);
5410}
5411
5412/// parseDirectiveEndIf
5413/// ::= .endif
5414bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5415 if (parseEOL())
5416 return true;
5417
5418 if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
5419 return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
5420 "an .if or .else");
5421 if (!TheCondStack.empty()) {
5422 TheCondState = TheCondStack.back();
5423 TheCondStack.pop_back();
5424 }
5425
5426 return false;
5427}
5428
5429void AsmParser::initializeDirectiveKindMap() {
5430 /* Lookup will be done with the directive
5431 * converted to lower case, so all these
5432 * keys should be lower case.
5433 * (target specific directives are handled
5434 * elsewhere)
5435 */
5436 DirectiveKindMap[".set"] = DK_SET;
5437 DirectiveKindMap[".equ"] = DK_EQU;
5438 DirectiveKindMap[".equiv"] = DK_EQUIV;
5439 DirectiveKindMap[".ascii"] = DK_ASCII;
5440 DirectiveKindMap[".asciz"] = DK_ASCIZ;
5441 DirectiveKindMap[".string"] = DK_STRING;
5442 DirectiveKindMap[".byte"] = DK_BYTE;
5443 DirectiveKindMap[".short"] = DK_SHORT;
5444 DirectiveKindMap[".value"] = DK_VALUE;
5445 DirectiveKindMap[".2byte"] = DK_2BYTE;
5446 DirectiveKindMap[".long"] = DK_LONG;
5447 DirectiveKindMap[".int"] = DK_INT;
5448 DirectiveKindMap[".4byte"] = DK_4BYTE;
5449 DirectiveKindMap[".quad"] = DK_QUAD;
5450 DirectiveKindMap[".8byte"] = DK_8BYTE;
5451 DirectiveKindMap[".octa"] = DK_OCTA;
5452 DirectiveKindMap[".single"] = DK_SINGLE;
5453 DirectiveKindMap[".float"] = DK_FLOAT;
5454 DirectiveKindMap[".double"] = DK_DOUBLE;
5455 DirectiveKindMap[".align"] = DK_ALIGN;
5456 DirectiveKindMap[".align32"] = DK_ALIGN32;
5457 DirectiveKindMap[".balign"] = DK_BALIGN;
5458 DirectiveKindMap[".balignw"] = DK_BALIGNW;
5459 DirectiveKindMap[".balignl"] = DK_BALIGNL;
5460 DirectiveKindMap[".p2align"] = DK_P2ALIGN;
5461 DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
5462 DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
5463 DirectiveKindMap[".org"] = DK_ORG;
5464 DirectiveKindMap[".fill"] = DK_FILL;
5465 DirectiveKindMap[".zero"] = DK_ZERO;
5466 DirectiveKindMap[".extern"] = DK_EXTERN;
5467 DirectiveKindMap[".globl"] = DK_GLOBL;
5468 DirectiveKindMap[".global"] = DK_GLOBAL;
5469 DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
5470 DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
5471 DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
5472 DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
5473 DirectiveKindMap[".reference"] = DK_REFERENCE;
5474 DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
5475 DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
5476 DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
5477 DirectiveKindMap[".cold"] = DK_COLD;
5478 DirectiveKindMap[".comm"] = DK_COMM;
5479 DirectiveKindMap[".common"] = DK_COMMON;
5480 DirectiveKindMap[".lcomm"] = DK_LCOMM;
5481 DirectiveKindMap[".abort"] = DK_ABORT;
5482 DirectiveKindMap[".include"] = DK_INCLUDE;
5483 DirectiveKindMap[".incbin"] = DK_INCBIN;
5484 DirectiveKindMap[".code16"] = DK_CODE16;
5485 DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
5486 DirectiveKindMap[".rept"] = DK_REPT;
5487 DirectiveKindMap[".rep"] = DK_REPT;
5488 DirectiveKindMap[".irp"] = DK_IRP;
5489 DirectiveKindMap[".irpc"] = DK_IRPC;
5490 DirectiveKindMap[".endr"] = DK_ENDR;
5491 DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE;
5492 DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK;
5493 DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK;
5494 DirectiveKindMap[".if"] = DK_IF;
5495 DirectiveKindMap[".ifeq"] = DK_IFEQ;
5496 DirectiveKindMap[".ifge"] = DK_IFGE;
5497 DirectiveKindMap[".ifgt"] = DK_IFGT;
5498 DirectiveKindMap[".ifle"] = DK_IFLE;
5499 DirectiveKindMap[".iflt"] = DK_IFLT;
5500 DirectiveKindMap[".ifne"] = DK_IFNE;
5501 DirectiveKindMap[".ifb"] = DK_IFB;
5502 DirectiveKindMap[".ifnb"] = DK_IFNB;
5503 DirectiveKindMap[".ifc"] = DK_IFC;
5504 DirectiveKindMap[".ifeqs"] = DK_IFEQS;
5505 DirectiveKindMap[".ifnc"] = DK_IFNC;
5506 DirectiveKindMap[".ifnes"] = DK_IFNES;
5507 DirectiveKindMap[".ifdef"] = DK_IFDEF;
5508 DirectiveKindMap[".ifndef"] = DK_IFNDEF;
5509 DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
5510 DirectiveKindMap[".elseif"] = DK_ELSEIF;
5511 DirectiveKindMap[".else"] = DK_ELSE;
5512 DirectiveKindMap[".end"] = DK_END;
5513 DirectiveKindMap[".endif"] = DK_ENDIF;
5514 DirectiveKindMap[".skip"] = DK_SKIP;
5515 DirectiveKindMap[".space"] = DK_SPACE;
5516 DirectiveKindMap[".file"] = DK_FILE;
5517 DirectiveKindMap[".line"] = DK_LINE;
5518 DirectiveKindMap[".loc"] = DK_LOC;
5519 DirectiveKindMap[".stabs"] = DK_STABS;
5520 DirectiveKindMap[".cv_file"] = DK_CV_FILE;
5521 DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
5522 DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
5523 DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
5524 DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
5525 DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
5526 DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
5527 DirectiveKindMap[".cv_string"] = DK_CV_STRING;
5528 DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
5529 DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
5530 DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
5531 DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
5532 DirectiveKindMap[".sleb128"] = DK_SLEB128;
5533 DirectiveKindMap[".uleb128"] = DK_ULEB128;
5534 DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
5535 DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
5536 DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
5537 DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
5538 DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
5539 DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
5540 DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
5541 DirectiveKindMap[".cfi_llvm_def_aspace_cfa"] = DK_CFI_LLVM_DEF_ASPACE_CFA;
5542 DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
5543 DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
5544 DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
5545 DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
5546 DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
5547 DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
5548 DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
5549 DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
5550 DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
5551 DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
5552 DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
5553 DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
5554 DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
5555 DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
5556 DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
5557 DirectiveKindMap[".cfi_mte_tagged_frame"] = DK_CFI_MTE_TAGGED_FRAME;
5558 DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
5559 DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
5560 DirectiveKindMap[".macro"] = DK_MACRO;
5561 DirectiveKindMap[".exitm"] = DK_EXITM;
5562 DirectiveKindMap[".endm"] = DK_ENDM;
5563 DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
5564 DirectiveKindMap[".purgem"] = DK_PURGEM;
5565 DirectiveKindMap[".err"] = DK_ERR;
5566 DirectiveKindMap[".error"] = DK_ERROR;
5567 DirectiveKindMap[".warning"] = DK_WARNING;
5568 DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
5569 DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
5570 DirectiveKindMap[".reloc"</