Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / lib / MC / MCParser / AsmParser.cpp
bloba66a4eb29afc6864f5e8167ec71905de86449c12
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 the parser for assembly files.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ADT/APFloat.h"
14 #include "llvm/ADT/APInt.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/None.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/StringMap.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/ADT/Twine.h"
24 #include "llvm/BinaryFormat/Dwarf.h"
25 #include "llvm/MC/MCAsmInfo.h"
26 #include "llvm/MC/MCCodeView.h"
27 #include "llvm/MC/MCContext.h"
28 #include "llvm/MC/MCDirectives.h"
29 #include "llvm/MC/MCDwarf.h"
30 #include "llvm/MC/MCExpr.h"
31 #include "llvm/MC/MCInstPrinter.h"
32 #include "llvm/MC/MCInstrDesc.h"
33 #include "llvm/MC/MCInstrInfo.h"
34 #include "llvm/MC/MCObjectFileInfo.h"
35 #include "llvm/MC/MCParser/AsmCond.h"
36 #include "llvm/MC/MCParser/AsmLexer.h"
37 #include "llvm/MC/MCParser/MCAsmLexer.h"
38 #include "llvm/MC/MCParser/MCAsmParser.h"
39 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
40 #include "llvm/MC/MCParser/MCAsmParserUtils.h"
41 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
42 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
43 #include "llvm/MC/MCRegisterInfo.h"
44 #include "llvm/MC/MCSection.h"
45 #include "llvm/MC/MCStreamer.h"
46 #include "llvm/MC/MCSymbol.h"
47 #include "llvm/MC/MCTargetOptions.h"
48 #include "llvm/MC/MCValue.h"
49 #include "llvm/Support/Casting.h"
50 #include "llvm/Support/CommandLine.h"
51 #include "llvm/Support/ErrorHandling.h"
52 #include "llvm/Support/MD5.h"
53 #include "llvm/Support/MathExtras.h"
54 #include "llvm/Support/MemoryBuffer.h"
55 #include "llvm/Support/SMLoc.h"
56 #include "llvm/Support/SourceMgr.h"
57 #include "llvm/Support/raw_ostream.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 <sstream>
67 #include <string>
68 #include <tuple>
69 #include <utility>
70 #include <vector>
72 using namespace llvm;
74 MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;
76 static cl::opt<unsigned> AsmMacroMaxNestingDepth(
77 "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,
78 cl::desc("The maximum nesting depth allowed for assembly macros."));
80 namespace {
82 /// Helper types for tracking macro definitions.
83 typedef std::vector<AsmToken> MCAsmMacroArgument;
84 typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
86 /// Helper class for storing information about an active macro
87 /// instantiation.
88 struct MacroInstantiation {
89 /// The location of the instantiation.
90 SMLoc InstantiationLoc;
92 /// The buffer where parsing should resume upon instantiation completion.
93 int ExitBuffer;
95 /// The location where parsing should resume upon instantiation completion.
96 SMLoc ExitLoc;
98 /// The depth of TheCondStack at the start of the instantiation.
99 size_t CondStackDepth;
101 public:
102 MacroInstantiation(SMLoc IL, int EB, SMLoc EL, size_t CondStackDepth);
105 struct ParseStatementInfo {
106 /// The parsed operands from the last parsed statement.
107 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
109 /// The opcode from the last parsed instruction.
110 unsigned Opcode = ~0U;
112 /// Was there an error parsing the inline assembly?
113 bool ParseError = false;
115 SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
117 ParseStatementInfo() = delete;
118 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
119 : AsmRewrites(rewrites) {}
122 /// The concrete assembly parser instance.
123 class AsmParser : public MCAsmParser {
124 private:
125 AsmLexer Lexer;
126 MCContext &Ctx;
127 MCStreamer &Out;
128 const MCAsmInfo &MAI;
129 SourceMgr &SrcMgr;
130 SourceMgr::DiagHandlerTy SavedDiagHandler;
131 void *SavedDiagContext;
132 std::unique_ptr<MCAsmParserExtension> PlatformParser;
134 /// This is the current buffer index we're lexing from as managed by the
135 /// SourceMgr object.
136 unsigned CurBuffer;
138 AsmCond TheCondState;
139 std::vector<AsmCond> TheCondStack;
141 /// maps directive names to handler methods in parser
142 /// extensions. Extensions register themselves in this map by calling
143 /// addDirectiveHandler.
144 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
146 /// Stack of active macro instantiations.
147 std::vector<MacroInstantiation*> ActiveMacros;
149 /// List of bodies of anonymous macros.
150 std::deque<MCAsmMacro> MacroLikeBodies;
152 /// Boolean tracking whether macro substitution is enabled.
153 unsigned MacrosEnabledFlag : 1;
155 /// Keeps track of how many .macro's have been instantiated.
156 unsigned NumOfMacroInstantiations;
158 /// The values from the last parsed cpp hash file line comment if any.
159 struct CppHashInfoTy {
160 StringRef Filename;
161 int64_t LineNumber;
162 SMLoc Loc;
163 unsigned Buf;
164 CppHashInfoTy() : Filename(), LineNumber(0), Loc(), Buf(0) {}
166 CppHashInfoTy CppHashInfo;
168 /// List of forward directional labels for diagnosis at the end.
169 SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
171 /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
172 unsigned AssemblerDialect = ~0U;
174 /// is Darwin compatibility enabled?
175 bool IsDarwin = false;
177 /// Are we parsing ms-style inline assembly?
178 bool ParsingInlineAsm = false;
180 /// Did we already inform the user about inconsistent MD5 usage?
181 bool ReportedInconsistentMD5 = false;
183 // Is alt macro mode enabled.
184 bool AltMacroMode = false;
186 public:
187 AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
188 const MCAsmInfo &MAI, unsigned CB);
189 AsmParser(const AsmParser &) = delete;
190 AsmParser &operator=(const AsmParser &) = delete;
191 ~AsmParser() override;
193 bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
195 void addDirectiveHandler(StringRef Directive,
196 ExtensionDirectiveHandler Handler) override {
197 ExtensionDirectiveMap[Directive] = Handler;
200 void addAliasForDirective(StringRef Directive, StringRef Alias) override {
201 DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
204 /// @name MCAsmParser Interface
205 /// {
207 SourceMgr &getSourceManager() override { return SrcMgr; }
208 MCAsmLexer &getLexer() override { return Lexer; }
209 MCContext &getContext() override { return Ctx; }
210 MCStreamer &getStreamer() override { return Out; }
212 CodeViewContext &getCVContext() { return Ctx.getCVContext(); }
214 unsigned getAssemblerDialect() override {
215 if (AssemblerDialect == ~0U)
216 return MAI.getAssemblerDialect();
217 else
218 return AssemblerDialect;
220 void setAssemblerDialect(unsigned i) override {
221 AssemblerDialect = i;
224 void Note(SMLoc L, const Twine &Msg, SMRange Range = None) override;
225 bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) override;
226 bool printError(SMLoc L, const Twine &Msg, SMRange Range = None) override;
228 const AsmToken &Lex() override;
230 void setParsingInlineAsm(bool V) override {
231 ParsingInlineAsm = V;
232 // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
233 // hex integer literals.
234 Lexer.setLexMasmIntegers(V);
236 bool isParsingInlineAsm() override { return ParsingInlineAsm; }
238 bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
239 unsigned &NumOutputs, unsigned &NumInputs,
240 SmallVectorImpl<std::pair<void *,bool>> &OpDecls,
241 SmallVectorImpl<std::string> &Constraints,
242 SmallVectorImpl<std::string> &Clobbers,
243 const MCInstrInfo *MII, const MCInstPrinter *IP,
244 MCAsmParserSemaCallback &SI) override;
246 bool parseExpression(const MCExpr *&Res);
247 bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
248 bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
249 bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
250 bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
251 SMLoc &EndLoc) override;
252 bool parseAbsoluteExpression(int64_t &Res) override;
254 /// Parse a floating point expression using the float \p Semantics
255 /// and set \p Res to the value.
256 bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
258 /// Parse an identifier or string (as a quoted identifier)
259 /// and set \p Res to the identifier contents.
260 bool parseIdentifier(StringRef &Res) override;
261 void eatToEndOfStatement() override;
263 bool checkForValidSection() override;
265 /// }
267 private:
268 bool parseStatement(ParseStatementInfo &Info,
269 MCAsmParserSemaCallback *SI);
270 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
271 bool parseCppHashLineFilenameComment(SMLoc L);
273 void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
274 ArrayRef<MCAsmMacroParameter> Parameters);
275 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
276 ArrayRef<MCAsmMacroParameter> Parameters,
277 ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable,
278 SMLoc L);
280 /// Are macros enabled in the parser?
281 bool areMacrosEnabled() {return MacrosEnabledFlag;}
283 /// Control a flag in the parser that enables or disables macros.
284 void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
286 /// Are we inside a macro instantiation?
287 bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
289 /// Handle entry to macro instantiation.
291 /// \param M The macro.
292 /// \param NameLoc Instantiation location.
293 bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
295 /// Handle exit from macro instantiation.
296 void handleMacroExit();
298 /// Extract AsmTokens for a macro argument.
299 bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
301 /// Parse all macro arguments for a given macro.
302 bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
304 void printMacroInstantiations();
305 void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
306 SMRange Range = None) const {
307 ArrayRef<SMRange> Ranges(Range);
308 SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
310 static void DiagHandler(const SMDiagnostic &Diag, void *Context);
312 /// Should we emit DWARF describing this assembler source? (Returns false if
313 /// the source has .file directives, which means we don't want to generate
314 /// info describing the assembler source itself.)
315 bool enabledGenDwarfForAssembly();
317 /// Enter the specified file. This returns true on failure.
318 bool enterIncludeFile(const std::string &Filename);
320 /// Process the specified file for the .incbin directive.
321 /// This returns true on failure.
322 bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,
323 const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());
325 /// Reset the current lexer position to that given by \p Loc. The
326 /// current token is not set; clients should ensure Lex() is called
327 /// subsequently.
329 /// \param InBuffer If not 0, should be the known buffer id that contains the
330 /// location.
331 void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);
333 /// Parse up to the end of statement and a return the contents from the
334 /// current token until the end of the statement; the current token on exit
335 /// will be either the EndOfStatement or EOF.
336 StringRef parseStringToEndOfStatement() override;
338 /// Parse until the end of a statement or a comma is encountered,
339 /// return the contents from the current token up to the end or comma.
340 StringRef parseStringToComma();
342 bool parseAssignment(StringRef Name, bool allow_redef,
343 bool NoDeadStrip = false);
345 unsigned getBinOpPrecedence(AsmToken::TokenKind K,
346 MCBinaryExpr::Opcode &Kind);
348 bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
349 bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
350 bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
352 bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
354 bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);
355 bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);
357 // Generic (target and platform independent) directive parsing.
358 enum DirectiveKind {
359 DK_NO_DIRECTIVE, // Placeholder
360 DK_SET,
361 DK_EQU,
362 DK_EQUIV,
363 DK_ASCII,
364 DK_ASCIZ,
365 DK_STRING,
366 DK_BYTE,
367 DK_SHORT,
368 DK_RELOC,
369 DK_VALUE,
370 DK_2BYTE,
371 DK_LONG,
372 DK_INT,
373 DK_4BYTE,
374 DK_QUAD,
375 DK_8BYTE,
376 DK_OCTA,
377 DK_DC,
378 DK_DC_A,
379 DK_DC_B,
380 DK_DC_D,
381 DK_DC_L,
382 DK_DC_S,
383 DK_DC_W,
384 DK_DC_X,
385 DK_DCB,
386 DK_DCB_B,
387 DK_DCB_D,
388 DK_DCB_L,
389 DK_DCB_S,
390 DK_DCB_W,
391 DK_DCB_X,
392 DK_DS,
393 DK_DS_B,
394 DK_DS_D,
395 DK_DS_L,
396 DK_DS_P,
397 DK_DS_S,
398 DK_DS_W,
399 DK_DS_X,
400 DK_SINGLE,
401 DK_FLOAT,
402 DK_DOUBLE,
403 DK_ALIGN,
404 DK_ALIGN32,
405 DK_BALIGN,
406 DK_BALIGNW,
407 DK_BALIGNL,
408 DK_P2ALIGN,
409 DK_P2ALIGNW,
410 DK_P2ALIGNL,
411 DK_ORG,
412 DK_FILL,
413 DK_ENDR,
414 DK_BUNDLE_ALIGN_MODE,
415 DK_BUNDLE_LOCK,
416 DK_BUNDLE_UNLOCK,
417 DK_ZERO,
418 DK_EXTERN,
419 DK_GLOBL,
420 DK_GLOBAL,
421 DK_LAZY_REFERENCE,
422 DK_NO_DEAD_STRIP,
423 DK_SYMBOL_RESOLVER,
424 DK_PRIVATE_EXTERN,
425 DK_REFERENCE,
426 DK_WEAK_DEFINITION,
427 DK_WEAK_REFERENCE,
428 DK_WEAK_DEF_CAN_BE_HIDDEN,
429 DK_COLD,
430 DK_COMM,
431 DK_COMMON,
432 DK_LCOMM,
433 DK_ABORT,
434 DK_INCLUDE,
435 DK_INCBIN,
436 DK_CODE16,
437 DK_CODE16GCC,
438 DK_REPT,
439 DK_IRP,
440 DK_IRPC,
441 DK_IF,
442 DK_IFEQ,
443 DK_IFGE,
444 DK_IFGT,
445 DK_IFLE,
446 DK_IFLT,
447 DK_IFNE,
448 DK_IFB,
449 DK_IFNB,
450 DK_IFC,
451 DK_IFEQS,
452 DK_IFNC,
453 DK_IFNES,
454 DK_IFDEF,
455 DK_IFNDEF,
456 DK_IFNOTDEF,
457 DK_ELSEIF,
458 DK_ELSE,
459 DK_ENDIF,
460 DK_SPACE,
461 DK_SKIP,
462 DK_FILE,
463 DK_LINE,
464 DK_LOC,
465 DK_STABS,
466 DK_CV_FILE,
467 DK_CV_FUNC_ID,
468 DK_CV_INLINE_SITE_ID,
469 DK_CV_LOC,
470 DK_CV_LINETABLE,
471 DK_CV_INLINE_LINETABLE,
472 DK_CV_DEF_RANGE,
473 DK_CV_STRINGTABLE,
474 DK_CV_STRING,
475 DK_CV_FILECHECKSUMS,
476 DK_CV_FILECHECKSUM_OFFSET,
477 DK_CV_FPO_DATA,
478 DK_CFI_SECTIONS,
479 DK_CFI_STARTPROC,
480 DK_CFI_ENDPROC,
481 DK_CFI_DEF_CFA,
482 DK_CFI_DEF_CFA_OFFSET,
483 DK_CFI_ADJUST_CFA_OFFSET,
484 DK_CFI_DEF_CFA_REGISTER,
485 DK_CFI_OFFSET,
486 DK_CFI_REL_OFFSET,
487 DK_CFI_PERSONALITY,
488 DK_CFI_LSDA,
489 DK_CFI_REMEMBER_STATE,
490 DK_CFI_RESTORE_STATE,
491 DK_CFI_SAME_VALUE,
492 DK_CFI_RESTORE,
493 DK_CFI_ESCAPE,
494 DK_CFI_RETURN_COLUMN,
495 DK_CFI_SIGNAL_FRAME,
496 DK_CFI_UNDEFINED,
497 DK_CFI_REGISTER,
498 DK_CFI_WINDOW_SAVE,
499 DK_CFI_B_KEY_FRAME,
500 DK_MACROS_ON,
501 DK_MACROS_OFF,
502 DK_ALTMACRO,
503 DK_NOALTMACRO,
504 DK_MACRO,
505 DK_EXITM,
506 DK_ENDM,
507 DK_ENDMACRO,
508 DK_PURGEM,
509 DK_SLEB128,
510 DK_ULEB128,
511 DK_ERR,
512 DK_ERROR,
513 DK_WARNING,
514 DK_PRINT,
515 DK_ADDRSIG,
516 DK_ADDRSIG_SYM,
517 DK_END
520 /// Maps directive name --> DirectiveKind enum, for
521 /// directives parsed by this class.
522 StringMap<DirectiveKind> DirectiveKindMap;
524 // ".ascii", ".asciz", ".string"
525 bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
526 bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
527 bool parseDirectiveValue(StringRef IDVal,
528 unsigned Size); // ".byte", ".long", ...
529 bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ...
530 bool parseDirectiveRealValue(StringRef IDVal,
531 const fltSemantics &); // ".single", ...
532 bool parseDirectiveFill(); // ".fill"
533 bool parseDirectiveZero(); // ".zero"
534 // ".set", ".equ", ".equiv"
535 bool parseDirectiveSet(StringRef IDVal, bool allow_redef);
536 bool parseDirectiveOrg(); // ".org"
537 // ".align{,32}", ".p2align{,w,l}"
538 bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);
540 // ".file", ".line", ".loc", ".stabs"
541 bool parseDirectiveFile(SMLoc DirectiveLoc);
542 bool parseDirectiveLine();
543 bool parseDirectiveLoc();
544 bool parseDirectiveStabs();
546 // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
547 // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
548 bool parseDirectiveCVFile();
549 bool parseDirectiveCVFuncId();
550 bool parseDirectiveCVInlineSiteId();
551 bool parseDirectiveCVLoc();
552 bool parseDirectiveCVLinetable();
553 bool parseDirectiveCVInlineLinetable();
554 bool parseDirectiveCVDefRange();
555 bool parseDirectiveCVString();
556 bool parseDirectiveCVStringTable();
557 bool parseDirectiveCVFileChecksums();
558 bool parseDirectiveCVFileChecksumOffset();
559 bool parseDirectiveCVFPOData();
561 // .cfi directives
562 bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
563 bool parseDirectiveCFIWindowSave();
564 bool parseDirectiveCFISections();
565 bool parseDirectiveCFIStartProc();
566 bool parseDirectiveCFIEndProc();
567 bool parseDirectiveCFIDefCfaOffset();
568 bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
569 bool parseDirectiveCFIAdjustCfaOffset();
570 bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
571 bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
572 bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
573 bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
574 bool parseDirectiveCFIRememberState();
575 bool parseDirectiveCFIRestoreState();
576 bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
577 bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
578 bool parseDirectiveCFIEscape();
579 bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
580 bool parseDirectiveCFISignalFrame();
581 bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
583 // macro directives
584 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
585 bool parseDirectiveExitMacro(StringRef Directive);
586 bool parseDirectiveEndMacro(StringRef Directive);
587 bool parseDirectiveMacro(SMLoc DirectiveLoc);
588 bool parseDirectiveMacrosOnOff(StringRef Directive);
589 // alternate macro mode directives
590 bool parseDirectiveAltmacro(StringRef Directive);
591 // ".bundle_align_mode"
592 bool parseDirectiveBundleAlignMode();
593 // ".bundle_lock"
594 bool parseDirectiveBundleLock();
595 // ".bundle_unlock"
596 bool parseDirectiveBundleUnlock();
598 // ".space", ".skip"
599 bool parseDirectiveSpace(StringRef IDVal);
601 // ".dcb"
602 bool parseDirectiveDCB(StringRef IDVal, unsigned Size);
603 bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &);
604 // ".ds"
605 bool parseDirectiveDS(StringRef IDVal, unsigned Size);
607 // .sleb128 (Signed=true) and .uleb128 (Signed=false)
608 bool parseDirectiveLEB128(bool Signed);
610 /// Parse a directive like ".globl" which
611 /// accepts a single symbol (which should be a label or an external).
612 bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
614 bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
616 bool parseDirectiveAbort(); // ".abort"
617 bool parseDirectiveInclude(); // ".include"
618 bool parseDirectiveIncbin(); // ".incbin"
620 // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"
621 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
622 // ".ifb" or ".ifnb", depending on ExpectBlank.
623 bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
624 // ".ifc" or ".ifnc", depending on ExpectEqual.
625 bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
626 // ".ifeqs" or ".ifnes", depending on ExpectEqual.
627 bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);
628 // ".ifdef" or ".ifndef", depending on expect_defined
629 bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
630 bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
631 bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
632 bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
633 bool parseEscapedString(std::string &Data) override;
635 const MCExpr *applyModifierToExpr(const MCExpr *E,
636 MCSymbolRefExpr::VariantKind Variant);
638 // Macro-like directives
639 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
640 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
641 raw_svector_ostream &OS);
642 bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);
643 bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
644 bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
645 bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
647 // "_emit" or "__emit"
648 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
649 size_t Len);
651 // "align"
652 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
654 // "end"
655 bool parseDirectiveEnd(SMLoc DirectiveLoc);
657 // ".err" or ".error"
658 bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
660 // ".warning"
661 bool parseDirectiveWarning(SMLoc DirectiveLoc);
663 // .print <double-quotes-string>
664 bool parseDirectivePrint(SMLoc DirectiveLoc);
666 // Directives to support address-significance tables.
667 bool parseDirectiveAddrsig();
668 bool parseDirectiveAddrsigSym();
670 void initializeDirectiveKindMap();
673 } // end anonymous namespace
675 namespace llvm {
677 extern MCAsmParserExtension *createDarwinAsmParser();
678 extern MCAsmParserExtension *createELFAsmParser();
679 extern MCAsmParserExtension *createCOFFAsmParser();
680 extern MCAsmParserExtension *createWasmAsmParser();
682 } // end namespace llvm
684 enum { DEFAULT_ADDRSPACE = 0 };
686 AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
687 const MCAsmInfo &MAI, unsigned CB = 0)
688 : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
689 CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {
690 HadError = false;
691 // Save the old handler.
692 SavedDiagHandler = SrcMgr.getDiagHandler();
693 SavedDiagContext = SrcMgr.getDiagContext();
694 // Set our own handler which calls the saved handler.
695 SrcMgr.setDiagHandler(DiagHandler, this);
696 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
698 // Initialize the platform / file format parser.
699 switch (Ctx.getObjectFileInfo()->getObjectFileType()) {
700 case MCObjectFileInfo::IsCOFF:
701 PlatformParser.reset(createCOFFAsmParser());
702 break;
703 case MCObjectFileInfo::IsMachO:
704 PlatformParser.reset(createDarwinAsmParser());
705 IsDarwin = true;
706 break;
707 case MCObjectFileInfo::IsELF:
708 PlatformParser.reset(createELFAsmParser());
709 break;
710 case MCObjectFileInfo::IsWasm:
711 PlatformParser.reset(createWasmAsmParser());
712 break;
715 PlatformParser->Initialize(*this);
716 initializeDirectiveKindMap();
718 NumOfMacroInstantiations = 0;
721 AsmParser::~AsmParser() {
722 assert((HadError || ActiveMacros.empty()) &&
723 "Unexpected active macro instantiation!");
725 // Restore the saved diagnostics handler and context for use during
726 // finalization.
727 SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
730 void AsmParser::printMacroInstantiations() {
731 // Print the active macro instantiation stack.
732 for (std::vector<MacroInstantiation *>::const_reverse_iterator
733 it = ActiveMacros.rbegin(),
734 ie = ActiveMacros.rend();
735 it != ie; ++it)
736 printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
737 "while in macro instantiation");
740 void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
741 printPendingErrors();
742 printMessage(L, SourceMgr::DK_Note, Msg, Range);
743 printMacroInstantiations();
746 bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
747 if(getTargetParser().getTargetOptions().MCNoWarn)
748 return false;
749 if (getTargetParser().getTargetOptions().MCFatalWarnings)
750 return Error(L, Msg, Range);
751 printMessage(L, SourceMgr::DK_Warning, Msg, Range);
752 printMacroInstantiations();
753 return false;
756 bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
757 HadError = true;
758 printMessage(L, SourceMgr::DK_Error, Msg, Range);
759 printMacroInstantiations();
760 return true;
763 bool AsmParser::enterIncludeFile(const std::string &Filename) {
764 std::string IncludedFile;
765 unsigned NewBuf =
766 SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
767 if (!NewBuf)
768 return true;
770 CurBuffer = NewBuf;
771 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
772 return false;
775 /// Process the specified .incbin file by searching for it in the include paths
776 /// then just emitting the byte contents of the file to the streamer. This
777 /// returns true on failure.
778 bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
779 const MCExpr *Count, SMLoc Loc) {
780 std::string IncludedFile;
781 unsigned NewBuf =
782 SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
783 if (!NewBuf)
784 return true;
786 // Pick up the bytes from the file and emit them.
787 StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();
788 Bytes = Bytes.drop_front(Skip);
789 if (Count) {
790 int64_t Res;
791 if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
792 return Error(Loc, "expected absolute expression");
793 if (Res < 0)
794 return Warning(Loc, "negative count has no effect");
795 Bytes = Bytes.take_front(Res);
797 getStreamer().EmitBytes(Bytes);
798 return false;
801 void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
802 CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
803 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
804 Loc.getPointer());
807 const AsmToken &AsmParser::Lex() {
808 if (Lexer.getTok().is(AsmToken::Error))
809 Error(Lexer.getErrLoc(), Lexer.getErr());
811 // if it's a end of statement with a comment in it
812 if (getTok().is(AsmToken::EndOfStatement)) {
813 // if this is a line comment output it.
814 if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
815 getTok().getString().front() != '\r' && MAI.preserveAsmComments())
816 Out.addExplicitComment(Twine(getTok().getString()));
819 const AsmToken *tok = &Lexer.Lex();
821 // Parse comments here to be deferred until end of next statement.
822 while (tok->is(AsmToken::Comment)) {
823 if (MAI.preserveAsmComments())
824 Out.addExplicitComment(Twine(tok->getString()));
825 tok = &Lexer.Lex();
828 if (tok->is(AsmToken::Eof)) {
829 // If this is the end of an included file, pop the parent file off the
830 // include stack.
831 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
832 if (ParentIncludeLoc != SMLoc()) {
833 jumpToLoc(ParentIncludeLoc);
834 return Lex();
838 return *tok;
841 bool AsmParser::enabledGenDwarfForAssembly() {
842 // Check whether the user specified -g.
843 if (!getContext().getGenDwarfForAssembly())
844 return false;
845 // If we haven't encountered any .file directives (which would imply that
846 // the assembler source was produced with debug info already) then emit one
847 // describing the assembler source file itself.
848 if (getContext().getGenDwarfFileNumber() == 0)
849 getContext().setGenDwarfFileNumber(getStreamer().EmitDwarfFileDirective(
850 0, StringRef(), getContext().getMainFileName()));
851 return true;
854 bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
855 // Create the initial section, if requested.
856 if (!NoInitialTextSection)
857 Out.InitSections(false);
859 // Prime the lexer.
860 Lex();
862 HadError = false;
863 AsmCond StartingCondState = TheCondState;
864 SmallVector<AsmRewrite, 4> AsmStrRewrites;
866 // If we are generating dwarf for assembly source files save the initial text
867 // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't
868 // emitting any actual debug info yet and haven't had a chance to parse any
869 // embedded .file directives.)
870 if (getContext().getGenDwarfForAssembly()) {
871 MCSection *Sec = getStreamer().getCurrentSectionOnly();
872 if (!Sec->getBeginSymbol()) {
873 MCSymbol *SectionStartSym = getContext().createTempSymbol();
874 getStreamer().EmitLabel(SectionStartSym);
875 Sec->setBeginSymbol(SectionStartSym);
877 bool InsertResult = getContext().addGenDwarfSection(Sec);
878 assert(InsertResult && ".text section should not have debug info yet");
879 (void)InsertResult;
882 // While we have input, parse each statement.
883 while (Lexer.isNot(AsmToken::Eof)) {
884 ParseStatementInfo Info(&AsmStrRewrites);
885 if (!parseStatement(Info, nullptr))
886 continue;
888 // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
889 // for printing ErrMsg via Lex() only if no (presumably better) parser error
890 // exists.
891 if (!hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
892 Lex();
895 // parseStatement returned true so may need to emit an error.
896 printPendingErrors();
898 // Skipping to the next line if needed.
899 if (!getLexer().isAtStartOfStatement())
900 eatToEndOfStatement();
903 // Make sure we get proper DWARF even for empty files.
904 (void)enabledGenDwarfForAssembly();
906 getTargetParser().onEndOfFile();
907 printPendingErrors();
909 // All errors should have been emitted.
910 assert(!hasPendingError() && "unexpected error from parseStatement");
912 getTargetParser().flushPendingInstructions(getStreamer());
914 if (TheCondState.TheCond != StartingCondState.TheCond ||
915 TheCondState.Ignore != StartingCondState.Ignore)
916 printError(getTok().getLoc(), "unmatched .ifs or .elses");
917 // Check to see there are no empty DwarfFile slots.
918 const auto &LineTables = getContext().getMCDwarfLineTables();
919 if (!LineTables.empty()) {
920 unsigned Index = 0;
921 for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {
922 if (File.Name.empty() && Index != 0)
923 printError(getTok().getLoc(), "unassigned file number: " +
924 Twine(Index) +
925 " for .file directives");
926 ++Index;
930 // Check to see that all assembler local symbols were actually defined.
931 // Targets that don't do subsections via symbols may not want this, though,
932 // so conservatively exclude them. Only do this if we're finalizing, though,
933 // as otherwise we won't necessarilly have seen everything yet.
934 if (!NoFinalize) {
935 if (MAI.hasSubsectionsViaSymbols()) {
936 for (const auto &TableEntry : getContext().getSymbols()) {
937 MCSymbol *Sym = TableEntry.getValue();
938 // Variable symbols may not be marked as defined, so check those
939 // explicitly. If we know it's a variable, we have a definition for
940 // the purposes of this check.
941 if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
942 // FIXME: We would really like to refer back to where the symbol was
943 // first referenced for a source location. We need to add something
944 // to track that. Currently, we just point to the end of the file.
945 printError(getTok().getLoc(), "assembler local symbol '" +
946 Sym->getName() + "' not defined");
950 // Temporary symbols like the ones for directional jumps don't go in the
951 // symbol table. They also need to be diagnosed in all (final) cases.
952 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
953 if (std::get<2>(LocSym)->isUndefined()) {
954 // Reset the state of any "# line file" directives we've seen to the
955 // context as it was at the diagnostic site.
956 CppHashInfo = std::get<1>(LocSym);
957 printError(std::get<0>(LocSym), "directional label undefined");
962 // Finalize the output stream if there are no errors and if the client wants
963 // us to.
964 if (!HadError && !NoFinalize)
965 Out.Finish();
967 return HadError || getContext().hadError();
970 bool AsmParser::checkForValidSection() {
971 if (!ParsingInlineAsm && !getStreamer().getCurrentSectionOnly()) {
972 Out.InitSections(false);
973 return Error(getTok().getLoc(),
974 "expected section directive before assembly directive");
976 return false;
979 /// Throw away the rest of the line for testing purposes.
980 void AsmParser::eatToEndOfStatement() {
981 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
982 Lexer.Lex();
984 // Eat EOL.
985 if (Lexer.is(AsmToken::EndOfStatement))
986 Lexer.Lex();
989 StringRef AsmParser::parseStringToEndOfStatement() {
990 const char *Start = getTok().getLoc().getPointer();
992 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
993 Lexer.Lex();
995 const char *End = getTok().getLoc().getPointer();
996 return StringRef(Start, End - Start);
999 StringRef AsmParser::parseStringToComma() {
1000 const char *Start = getTok().getLoc().getPointer();
1002 while (Lexer.isNot(AsmToken::EndOfStatement) &&
1003 Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof))
1004 Lexer.Lex();
1006 const char *End = getTok().getLoc().getPointer();
1007 return StringRef(Start, End - Start);
1010 /// Parse a paren expression and return it.
1011 /// NOTE: This assumes the leading '(' has already been consumed.
1013 /// parenexpr ::= expr)
1015 bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1016 if (parseExpression(Res))
1017 return true;
1018 if (Lexer.isNot(AsmToken::RParen))
1019 return TokError("expected ')' in parentheses expression");
1020 EndLoc = Lexer.getTok().getEndLoc();
1021 Lex();
1022 return false;
1025 /// Parse a bracket expression and return it.
1026 /// NOTE: This assumes the leading '[' has already been consumed.
1028 /// bracketexpr ::= expr]
1030 bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1031 if (parseExpression(Res))
1032 return true;
1033 EndLoc = getTok().getEndLoc();
1034 if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
1035 return true;
1036 return false;
1039 /// Parse a primary expression and return it.
1040 /// primaryexpr ::= (parenexpr
1041 /// primaryexpr ::= symbol
1042 /// primaryexpr ::= number
1043 /// primaryexpr ::= '.'
1044 /// primaryexpr ::= ~,+,- primaryexpr
1045 bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1046 SMLoc FirstTokenLoc = getLexer().getLoc();
1047 AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
1048 switch (FirstTokenKind) {
1049 default:
1050 return TokError("unknown token in expression");
1051 // If we have an error assume that we've already handled it.
1052 case AsmToken::Error:
1053 return true;
1054 case AsmToken::Exclaim:
1055 Lex(); // Eat the operator.
1056 if (parsePrimaryExpr(Res, EndLoc))
1057 return true;
1058 Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
1059 return false;
1060 case AsmToken::Dollar:
1061 case AsmToken::At:
1062 case AsmToken::String:
1063 case AsmToken::Identifier: {
1064 StringRef Identifier;
1065 if (parseIdentifier(Identifier)) {
1066 // We may have failed but $ may be a valid token.
1067 if (getTok().is(AsmToken::Dollar)) {
1068 if (Lexer.getMAI().getDollarIsPC()) {
1069 Lex();
1070 // This is a '$' reference, which references the current PC. Emit a
1071 // temporary label to the streamer and refer to it.
1072 MCSymbol *Sym = Ctx.createTempSymbol();
1073 Out.EmitLabel(Sym);
1074 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
1075 getContext());
1076 EndLoc = FirstTokenLoc;
1077 return false;
1079 return Error(FirstTokenLoc, "invalid token in expression");
1082 // Parse symbol variant
1083 std::pair<StringRef, StringRef> Split;
1084 if (!MAI.useParensForSymbolVariant()) {
1085 if (FirstTokenKind == AsmToken::String) {
1086 if (Lexer.is(AsmToken::At)) {
1087 Lex(); // eat @
1088 SMLoc AtLoc = getLexer().getLoc();
1089 StringRef VName;
1090 if (parseIdentifier(VName))
1091 return Error(AtLoc, "expected symbol variant after '@'");
1093 Split = std::make_pair(Identifier, VName);
1095 } else {
1096 Split = Identifier.split('@');
1098 } else if (Lexer.is(AsmToken::LParen)) {
1099 Lex(); // eat '('.
1100 StringRef VName;
1101 parseIdentifier(VName);
1102 // eat ')'.
1103 if (parseToken(AsmToken::RParen,
1104 "unexpected token in variant, expected ')'"))
1105 return true;
1106 Split = std::make_pair(Identifier, VName);
1109 EndLoc = SMLoc::getFromPointer(Identifier.end());
1111 // This is a symbol reference.
1112 StringRef SymbolName = Identifier;
1113 if (SymbolName.empty())
1114 return Error(getLexer().getLoc(), "expected a symbol reference");
1116 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
1118 // Lookup the symbol variant if used.
1119 if (!Split.second.empty()) {
1120 Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
1121 if (Variant != MCSymbolRefExpr::VK_Invalid) {
1122 SymbolName = Split.first;
1123 } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
1124 Variant = MCSymbolRefExpr::VK_None;
1125 } else {
1126 return Error(SMLoc::getFromPointer(Split.second.begin()),
1127 "invalid variant '" + Split.second + "'");
1131 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
1133 // If this is an absolute variable reference, substitute it now to preserve
1134 // semantics in the face of reassignment.
1135 if (Sym->isVariable()) {
1136 auto V = Sym->getVariableValue(/*SetUsed*/ false);
1137 bool DoInline = isa<MCConstantExpr>(V) && !Variant;
1138 if (auto TV = dyn_cast<MCTargetExpr>(V))
1139 DoInline = TV->inlineAssignedExpr();
1140 if (DoInline) {
1141 if (Variant)
1142 return Error(EndLoc, "unexpected modifier on variable reference");
1143 Res = Sym->getVariableValue(/*SetUsed*/ false);
1144 return false;
1148 // Otherwise create a symbol ref.
1149 Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
1150 return false;
1152 case AsmToken::BigNum:
1153 return TokError("literal value out of range for directive");
1154 case AsmToken::Integer: {
1155 SMLoc Loc = getTok().getLoc();
1156 int64_t IntVal = getTok().getIntVal();
1157 Res = MCConstantExpr::create(IntVal, getContext());
1158 EndLoc = Lexer.getTok().getEndLoc();
1159 Lex(); // Eat token.
1160 // Look for 'b' or 'f' following an Integer as a directional label
1161 if (Lexer.getKind() == AsmToken::Identifier) {
1162 StringRef IDVal = getTok().getString();
1163 // Lookup the symbol variant if used.
1164 std::pair<StringRef, StringRef> Split = IDVal.split('@');
1165 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
1166 if (Split.first.size() != IDVal.size()) {
1167 Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
1168 if (Variant == MCSymbolRefExpr::VK_Invalid)
1169 return TokError("invalid variant '" + Split.second + "'");
1170 IDVal = Split.first;
1172 if (IDVal == "f" || IDVal == "b") {
1173 MCSymbol *Sym =
1174 Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
1175 Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
1176 if (IDVal == "b" && Sym->isUndefined())
1177 return Error(Loc, "directional label undefined");
1178 DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
1179 EndLoc = Lexer.getTok().getEndLoc();
1180 Lex(); // Eat identifier.
1183 return false;
1185 case AsmToken::Real: {
1186 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1187 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
1188 Res = MCConstantExpr::create(IntVal, getContext());
1189 EndLoc = Lexer.getTok().getEndLoc();
1190 Lex(); // Eat token.
1191 return false;
1193 case AsmToken::Dot: {
1194 // This is a '.' reference, which references the current PC. Emit a
1195 // temporary label to the streamer and refer to it.
1196 MCSymbol *Sym = Ctx.createTempSymbol();
1197 Out.EmitLabel(Sym);
1198 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1199 EndLoc = Lexer.getTok().getEndLoc();
1200 Lex(); // Eat identifier.
1201 return false;
1203 case AsmToken::LParen:
1204 Lex(); // Eat the '('.
1205 return parseParenExpr(Res, EndLoc);
1206 case AsmToken::LBrac:
1207 if (!PlatformParser->HasBracketExpressions())
1208 return TokError("brackets expression not supported on this target");
1209 Lex(); // Eat the '['.
1210 return parseBracketExpr(Res, EndLoc);
1211 case AsmToken::Minus:
1212 Lex(); // Eat the operator.
1213 if (parsePrimaryExpr(Res, EndLoc))
1214 return true;
1215 Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
1216 return false;
1217 case AsmToken::Plus:
1218 Lex(); // Eat the operator.
1219 if (parsePrimaryExpr(Res, EndLoc))
1220 return true;
1221 Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
1222 return false;
1223 case AsmToken::Tilde:
1224 Lex(); // Eat the operator.
1225 if (parsePrimaryExpr(Res, EndLoc))
1226 return true;
1227 Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
1228 return false;
1229 // MIPS unary expression operators. The lexer won't generate these tokens if
1230 // MCAsmInfo::HasMipsExpressions is false for the target.
1231 case AsmToken::PercentCall16:
1232 case AsmToken::PercentCall_Hi:
1233 case AsmToken::PercentCall_Lo:
1234 case AsmToken::PercentDtprel_Hi:
1235 case AsmToken::PercentDtprel_Lo:
1236 case AsmToken::PercentGot:
1237 case AsmToken::PercentGot_Disp:
1238 case AsmToken::PercentGot_Hi:
1239 case AsmToken::PercentGot_Lo:
1240 case AsmToken::PercentGot_Ofst:
1241 case AsmToken::PercentGot_Page:
1242 case AsmToken::PercentGottprel:
1243 case AsmToken::PercentGp_Rel:
1244 case AsmToken::PercentHi:
1245 case AsmToken::PercentHigher:
1246 case AsmToken::PercentHighest:
1247 case AsmToken::PercentLo:
1248 case AsmToken::PercentNeg:
1249 case AsmToken::PercentPcrel_Hi:
1250 case AsmToken::PercentPcrel_Lo:
1251 case AsmToken::PercentTlsgd:
1252 case AsmToken::PercentTlsldm:
1253 case AsmToken::PercentTprel_Hi:
1254 case AsmToken::PercentTprel_Lo:
1255 Lex(); // Eat the operator.
1256 if (Lexer.isNot(AsmToken::LParen))
1257 return TokError("expected '(' after operator");
1258 Lex(); // Eat the operator.
1259 if (parseExpression(Res, EndLoc))
1260 return true;
1261 if (Lexer.isNot(AsmToken::RParen))
1262 return TokError("expected ')'");
1263 Lex(); // Eat the operator.
1264 Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
1265 return !Res;
1269 bool AsmParser::parseExpression(const MCExpr *&Res) {
1270 SMLoc EndLoc;
1271 return parseExpression(Res, EndLoc);
1274 const MCExpr *
1275 AsmParser::applyModifierToExpr(const MCExpr *E,
1276 MCSymbolRefExpr::VariantKind Variant) {
1277 // Ask the target implementation about this expression first.
1278 const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx);
1279 if (NewE)
1280 return NewE;
1281 // Recurse over the given expression, rebuilding it to apply the given variant
1282 // if there is exactly one symbol.
1283 switch (E->getKind()) {
1284 case MCExpr::Target:
1285 case MCExpr::Constant:
1286 return nullptr;
1288 case MCExpr::SymbolRef: {
1289 const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
1291 if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
1292 TokError("invalid variant on expression '" + getTok().getIdentifier() +
1293 "' (already modified)");
1294 return E;
1297 return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext());
1300 case MCExpr::Unary: {
1301 const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
1302 const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant);
1303 if (!Sub)
1304 return nullptr;
1305 return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext());
1308 case MCExpr::Binary: {
1309 const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
1310 const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant);
1311 const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant);
1313 if (!LHS && !RHS)
1314 return nullptr;
1316 if (!LHS)
1317 LHS = BE->getLHS();
1318 if (!RHS)
1319 RHS = BE->getRHS();
1321 return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext());
1325 llvm_unreachable("Invalid expression kind!");
1328 /// This function checks if the next token is <string> type or arithmetic.
1329 /// string that begin with character '<' must end with character '>'.
1330 /// otherwise it is arithmetics.
1331 /// If the function returns a 'true' value,
1332 /// the End argument will be filled with the last location pointed to the '>'
1333 /// character.
1335 /// There is a gap between the AltMacro's documentation and the single quote
1336 /// implementation. GCC does not fully support this feature and so we will not
1337 /// support it.
1338 /// TODO: Adding single quote as a string.
1339 static bool isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
1340 assert((StrLoc.getPointer() != nullptr) &&
1341 "Argument to the function cannot be a NULL value");
1342 const char *CharPtr = StrLoc.getPointer();
1343 while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
1344 (*CharPtr != '\0')) {
1345 if (*CharPtr == '!')
1346 CharPtr++;
1347 CharPtr++;
1349 if (*CharPtr == '>') {
1350 EndLoc = StrLoc.getFromPointer(CharPtr + 1);
1351 return true;
1353 return false;
1356 /// creating a string without the escape characters '!'.
1357 static std::string altMacroString(StringRef AltMacroStr) {
1358 std::string Res;
1359 for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
1360 if (AltMacroStr[Pos] == '!')
1361 Pos++;
1362 Res += AltMacroStr[Pos];
1364 return Res;
1367 /// Parse an expression and return it.
1369 /// expr ::= expr &&,|| expr -> lowest.
1370 /// expr ::= expr |,^,&,! expr
1371 /// expr ::= expr ==,!=,<>,<,<=,>,>= expr
1372 /// expr ::= expr <<,>> expr
1373 /// expr ::= expr +,- expr
1374 /// expr ::= expr *,/,% expr -> highest.
1375 /// expr ::= primaryexpr
1377 bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
1378 // Parse the expression.
1379 Res = nullptr;
1380 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1381 parseBinOpRHS(1, Res, EndLoc))
1382 return true;
1384 // As a special case, we support 'a op b @ modifier' by rewriting the
1385 // expression to include the modifier. This is inefficient, but in general we
1386 // expect users to use 'a@modifier op b'.
1387 if (Lexer.getKind() == AsmToken::At) {
1388 Lex();
1390 if (Lexer.isNot(AsmToken::Identifier))
1391 return TokError("unexpected symbol modifier following '@'");
1393 MCSymbolRefExpr::VariantKind Variant =
1394 MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
1395 if (Variant == MCSymbolRefExpr::VK_Invalid)
1396 return TokError("invalid variant '" + getTok().getIdentifier() + "'");
1398 const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant);
1399 if (!ModifiedRes) {
1400 return TokError("invalid modifier '" + getTok().getIdentifier() +
1401 "' (no symbols present)");
1404 Res = ModifiedRes;
1405 Lex();
1408 // Try to constant fold it up front, if possible. Do not exploit
1409 // assembler here.
1410 int64_t Value;
1411 if (Res->evaluateAsAbsolute(Value))
1412 Res = MCConstantExpr::create(Value, getContext());
1414 return false;
1417 bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
1418 Res = nullptr;
1419 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1422 bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
1423 SMLoc &EndLoc) {
1424 if (parseParenExpr(Res, EndLoc))
1425 return true;
1427 for (; ParenDepth > 0; --ParenDepth) {
1428 if (parseBinOpRHS(1, Res, EndLoc))
1429 return true;
1431 // We don't Lex() the last RParen.
1432 // This is the same behavior as parseParenExpression().
1433 if (ParenDepth - 1 > 0) {
1434 EndLoc = getTok().getEndLoc();
1435 if (parseToken(AsmToken::RParen,
1436 "expected ')' in parentheses expression"))
1437 return true;
1440 return false;
1443 bool AsmParser::parseAbsoluteExpression(int64_t &Res) {
1444 const MCExpr *Expr;
1446 SMLoc StartLoc = Lexer.getLoc();
1447 if (parseExpression(Expr))
1448 return true;
1450 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1451 return Error(StartLoc, "expected absolute expression");
1453 return false;
1456 static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K,
1457 MCBinaryExpr::Opcode &Kind,
1458 bool ShouldUseLogicalShr) {
1459 switch (K) {
1460 default:
1461 return 0; // not a binop.
1463 // Lowest Precedence: &&, ||
1464 case AsmToken::AmpAmp:
1465 Kind = MCBinaryExpr::LAnd;
1466 return 1;
1467 case AsmToken::PipePipe:
1468 Kind = MCBinaryExpr::LOr;
1469 return 1;
1471 // Low Precedence: |, &, ^
1473 // FIXME: gas seems to support '!' as an infix operator?
1474 case AsmToken::Pipe:
1475 Kind = MCBinaryExpr::Or;
1476 return 2;
1477 case AsmToken::Caret:
1478 Kind = MCBinaryExpr::Xor;
1479 return 2;
1480 case AsmToken::Amp:
1481 Kind = MCBinaryExpr::And;
1482 return 2;
1484 // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
1485 case AsmToken::EqualEqual:
1486 Kind = MCBinaryExpr::EQ;
1487 return 3;
1488 case AsmToken::ExclaimEqual:
1489 case AsmToken::LessGreater:
1490 Kind = MCBinaryExpr::NE;
1491 return 3;
1492 case AsmToken::Less:
1493 Kind = MCBinaryExpr::LT;
1494 return 3;
1495 case AsmToken::LessEqual:
1496 Kind = MCBinaryExpr::LTE;
1497 return 3;
1498 case AsmToken::Greater:
1499 Kind = MCBinaryExpr::GT;
1500 return 3;
1501 case AsmToken::GreaterEqual:
1502 Kind = MCBinaryExpr::GTE;
1503 return 3;
1505 // Intermediate Precedence: <<, >>
1506 case AsmToken::LessLess:
1507 Kind = MCBinaryExpr::Shl;
1508 return 4;
1509 case AsmToken::GreaterGreater:
1510 Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
1511 return 4;
1513 // High Intermediate Precedence: +, -
1514 case AsmToken::Plus:
1515 Kind = MCBinaryExpr::Add;
1516 return 5;
1517 case AsmToken::Minus:
1518 Kind = MCBinaryExpr::Sub;
1519 return 5;
1521 // Highest Precedence: *, /, %
1522 case AsmToken::Star:
1523 Kind = MCBinaryExpr::Mul;
1524 return 6;
1525 case AsmToken::Slash:
1526 Kind = MCBinaryExpr::Div;
1527 return 6;
1528 case AsmToken::Percent:
1529 Kind = MCBinaryExpr::Mod;
1530 return 6;
1534 static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K,
1535 MCBinaryExpr::Opcode &Kind,
1536 bool ShouldUseLogicalShr) {
1537 switch (K) {
1538 default:
1539 return 0; // not a binop.
1541 // Lowest Precedence: &&, ||
1542 case AsmToken::AmpAmp:
1543 Kind = MCBinaryExpr::LAnd;
1544 return 2;
1545 case AsmToken::PipePipe:
1546 Kind = MCBinaryExpr::LOr;
1547 return 1;
1549 // Low Precedence: ==, !=, <>, <, <=, >, >=
1550 case AsmToken::EqualEqual:
1551 Kind = MCBinaryExpr::EQ;
1552 return 3;
1553 case AsmToken::ExclaimEqual:
1554 case AsmToken::LessGreater:
1555 Kind = MCBinaryExpr::NE;
1556 return 3;
1557 case AsmToken::Less:
1558 Kind = MCBinaryExpr::LT;
1559 return 3;
1560 case AsmToken::LessEqual:
1561 Kind = MCBinaryExpr::LTE;
1562 return 3;
1563 case AsmToken::Greater:
1564 Kind = MCBinaryExpr::GT;
1565 return 3;
1566 case AsmToken::GreaterEqual:
1567 Kind = MCBinaryExpr::GTE;
1568 return 3;
1570 // Low Intermediate Precedence: +, -
1571 case AsmToken::Plus:
1572 Kind = MCBinaryExpr::Add;
1573 return 4;
1574 case AsmToken::Minus:
1575 Kind = MCBinaryExpr::Sub;
1576 return 4;
1578 // High Intermediate Precedence: |, &, ^
1580 // FIXME: gas seems to support '!' as an infix operator?
1581 case AsmToken::Pipe:
1582 Kind = MCBinaryExpr::Or;
1583 return 5;
1584 case AsmToken::Caret:
1585 Kind = MCBinaryExpr::Xor;
1586 return 5;
1587 case AsmToken::Amp:
1588 Kind = MCBinaryExpr::And;
1589 return 5;
1591 // Highest Precedence: *, /, %, <<, >>
1592 case AsmToken::Star:
1593 Kind = MCBinaryExpr::Mul;
1594 return 6;
1595 case AsmToken::Slash:
1596 Kind = MCBinaryExpr::Div;
1597 return 6;
1598 case AsmToken::Percent:
1599 Kind = MCBinaryExpr::Mod;
1600 return 6;
1601 case AsmToken::LessLess:
1602 Kind = MCBinaryExpr::Shl;
1603 return 6;
1604 case AsmToken::GreaterGreater:
1605 Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
1606 return 6;
1610 unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
1611 MCBinaryExpr::Opcode &Kind) {
1612 bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
1613 return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)
1614 : getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr);
1617 /// Parse all binary operators with precedence >= 'Precedence'.
1618 /// Res contains the LHS of the expression on input.
1619 bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
1620 SMLoc &EndLoc) {
1621 SMLoc StartLoc = Lexer.getLoc();
1622 while (true) {
1623 MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
1624 unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
1626 // If the next token is lower precedence than we are allowed to eat, return
1627 // successfully with what we ate already.
1628 if (TokPrec < Precedence)
1629 return false;
1631 Lex();
1633 // Eat the next primary expression.
1634 const MCExpr *RHS;
1635 if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
1636 return true;
1638 // If BinOp binds less tightly with RHS than the operator after RHS, let
1639 // the pending operator take RHS as its LHS.
1640 MCBinaryExpr::Opcode Dummy;
1641 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1642 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
1643 return true;
1645 // Merge LHS and RHS according to operator.
1646 Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
1650 /// ParseStatement:
1651 /// ::= EndOfStatement
1652 /// ::= Label* Directive ...Operands... EndOfStatement
1653 /// ::= Label* Identifier OperandList* EndOfStatement
1654 bool AsmParser::parseStatement(ParseStatementInfo &Info,
1655 MCAsmParserSemaCallback *SI) {
1656 assert(!hasPendingError() && "parseStatement started with pending error");
1657 // Eat initial spaces and comments
1658 while (Lexer.is(AsmToken::Space))
1659 Lex();
1660 if (Lexer.is(AsmToken::EndOfStatement)) {
1661 // if this is a line comment we can drop it safely
1662 if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
1663 getTok().getString().front() == '\n')
1664 Out.AddBlankLine();
1665 Lex();
1666 return false;
1668 // Statements always start with an identifier.
1669 AsmToken ID = getTok();
1670 SMLoc IDLoc = ID.getLoc();
1671 StringRef IDVal;
1672 int64_t LocalLabelVal = -1;
1673 if (Lexer.is(AsmToken::HashDirective))
1674 return parseCppHashLineFilenameComment(IDLoc);
1675 // Allow an integer followed by a ':' as a directional local label.
1676 if (Lexer.is(AsmToken::Integer)) {
1677 LocalLabelVal = getTok().getIntVal();
1678 if (LocalLabelVal < 0) {
1679 if (!TheCondState.Ignore) {
1680 Lex(); // always eat a token
1681 return Error(IDLoc, "unexpected token at start of statement");
1683 IDVal = "";
1684 } else {
1685 IDVal = getTok().getString();
1686 Lex(); // Consume the integer token to be used as an identifier token.
1687 if (Lexer.getKind() != AsmToken::Colon) {
1688 if (!TheCondState.Ignore) {
1689 Lex(); // always eat a token
1690 return Error(IDLoc, "unexpected token at start of statement");
1694 } else if (Lexer.is(AsmToken::Dot)) {
1695 // Treat '.' as a valid identifier in this context.
1696 Lex();
1697 IDVal = ".";
1698 } else if (Lexer.is(AsmToken::LCurly)) {
1699 // Treat '{' as a valid identifier in this context.
1700 Lex();
1701 IDVal = "{";
1703 } else if (Lexer.is(AsmToken::RCurly)) {
1704 // Treat '}' as a valid identifier in this context.
1705 Lex();
1706 IDVal = "}";
1707 } else if (Lexer.is(AsmToken::Star) &&
1708 getTargetParser().starIsStartOfStatement()) {
1709 // Accept '*' as a valid start of statement.
1710 Lex();
1711 IDVal = "*";
1712 } else if (parseIdentifier(IDVal)) {
1713 if (!TheCondState.Ignore) {
1714 Lex(); // always eat a token
1715 return Error(IDLoc, "unexpected token at start of statement");
1717 IDVal = "";
1720 // Handle conditional assembly here before checking for skipping. We
1721 // have to do this so that .endif isn't skipped in a ".if 0" block for
1722 // example.
1723 StringMap<DirectiveKind>::const_iterator DirKindIt =
1724 DirectiveKindMap.find(IDVal);
1725 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1726 ? DK_NO_DIRECTIVE
1727 : DirKindIt->getValue();
1728 switch (DirKind) {
1729 default:
1730 break;
1731 case DK_IF:
1732 case DK_IFEQ:
1733 case DK_IFGE:
1734 case DK_IFGT:
1735 case DK_IFLE:
1736 case DK_IFLT:
1737 case DK_IFNE:
1738 return parseDirectiveIf(IDLoc, DirKind);
1739 case DK_IFB:
1740 return parseDirectiveIfb(IDLoc, true);
1741 case DK_IFNB:
1742 return parseDirectiveIfb(IDLoc, false);
1743 case DK_IFC:
1744 return parseDirectiveIfc(IDLoc, true);
1745 case DK_IFEQS:
1746 return parseDirectiveIfeqs(IDLoc, true);
1747 case DK_IFNC:
1748 return parseDirectiveIfc(IDLoc, false);
1749 case DK_IFNES:
1750 return parseDirectiveIfeqs(IDLoc, false);
1751 case DK_IFDEF:
1752 return parseDirectiveIfdef(IDLoc, true);
1753 case DK_IFNDEF:
1754 case DK_IFNOTDEF:
1755 return parseDirectiveIfdef(IDLoc, false);
1756 case DK_ELSEIF:
1757 return parseDirectiveElseIf(IDLoc);
1758 case DK_ELSE:
1759 return parseDirectiveElse(IDLoc);
1760 case DK_ENDIF:
1761 return parseDirectiveEndIf(IDLoc);
1764 // Ignore the statement if in the middle of inactive conditional
1765 // (e.g. ".if 0").
1766 if (TheCondState.Ignore) {
1767 eatToEndOfStatement();
1768 return false;
1771 // FIXME: Recurse on local labels?
1773 // See what kind of statement we have.
1774 switch (Lexer.getKind()) {
1775 case AsmToken::Colon: {
1776 if (!getTargetParser().isLabel(ID))
1777 break;
1778 if (checkForValidSection())
1779 return true;
1781 // identifier ':' -> Label.
1782 Lex();
1784 // Diagnose attempt to use '.' as a label.
1785 if (IDVal == ".")
1786 return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
1788 // Diagnose attempt to use a variable as a label.
1790 // FIXME: Diagnostics. Note the location of the definition as a label.
1791 // FIXME: This doesn't diagnose assignment to a symbol which has been
1792 // implicitly marked as external.
1793 MCSymbol *Sym;
1794 if (LocalLabelVal == -1) {
1795 if (ParsingInlineAsm && SI) {
1796 StringRef RewrittenLabel =
1797 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
1798 assert(!RewrittenLabel.empty() &&
1799 "We should have an internal name here.");
1800 Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
1801 RewrittenLabel);
1802 IDVal = RewrittenLabel;
1804 Sym = getContext().getOrCreateSymbol(IDVal);
1805 } else
1806 Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
1807 // End of Labels should be treated as end of line for lexing
1808 // purposes but that information is not available to the Lexer who
1809 // does not understand Labels. This may cause us to see a Hash
1810 // here instead of a preprocessor line comment.
1811 if (getTok().is(AsmToken::Hash)) {
1812 StringRef CommentStr = parseStringToEndOfStatement();
1813 Lexer.Lex();
1814 Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
1817 // Consume any end of statement token, if present, to avoid spurious
1818 // AddBlankLine calls().
1819 if (getTok().is(AsmToken::EndOfStatement)) {
1820 Lex();
1823 getTargetParser().doBeforeLabelEmit(Sym);
1825 // Emit the label.
1826 if (!getTargetParser().isParsingInlineAsm())
1827 Out.EmitLabel(Sym, IDLoc);
1829 // If we are generating dwarf for assembly source files then gather the
1830 // info to make a dwarf label entry for this label if needed.
1831 if (enabledGenDwarfForAssembly())
1832 MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
1833 IDLoc);
1835 getTargetParser().onLabelParsed(Sym);
1837 return false;
1840 case AsmToken::Equal:
1841 if (!getTargetParser().equalIsAsmAssignment())
1842 break;
1843 // identifier '=' ... -> assignment statement
1844 Lex();
1846 return parseAssignment(IDVal, true);
1848 default: // Normal instruction or directive.
1849 break;
1852 // If macros are enabled, check to see if this is a macro instantiation.
1853 if (areMacrosEnabled())
1854 if (const MCAsmMacro *M = getContext().lookupMacro(IDVal)) {
1855 return handleMacroEntry(M, IDLoc);
1858 // Otherwise, we have a normal instruction or directive.
1860 // Directives start with "."
1861 if (IDVal.startswith(".") && IDVal != ".") {
1862 // There are several entities interested in parsing directives:
1864 // 1. The target-specific assembly parser. Some directives are target
1865 // specific or may potentially behave differently on certain targets.
1866 // 2. Asm parser extensions. For example, platform-specific parsers
1867 // (like the ELF parser) register themselves as extensions.
1868 // 3. The generic directive parser implemented by this class. These are
1869 // all the directives that behave in a target and platform independent
1870 // manner, or at least have a default behavior that's shared between
1871 // all targets and platforms.
1873 getTargetParser().flushPendingInstructions(getStreamer());
1875 SMLoc StartTokLoc = getTok().getLoc();
1876 bool TPDirectiveReturn = getTargetParser().ParseDirective(ID);
1878 if (hasPendingError())
1879 return true;
1880 // Currently the return value should be true if we are
1881 // uninterested but as this is at odds with the standard parsing
1882 // convention (return true = error) we have instances of a parsed
1883 // directive that fails returning true as an error. Catch these
1884 // cases as best as possible errors here.
1885 if (TPDirectiveReturn && StartTokLoc != getTok().getLoc())
1886 return true;
1887 // Return if we did some parsing or believe we succeeded.
1888 if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc())
1889 return false;
1891 // Next, check the extension directive map to see if any extension has
1892 // registered itself to parse this directive.
1893 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
1894 ExtensionDirectiveMap.lookup(IDVal);
1895 if (Handler.first)
1896 return (*Handler.second)(Handler.first, IDVal, IDLoc);
1898 // Finally, if no one else is interested in this directive, it must be
1899 // generic and familiar to this class.
1900 switch (DirKind) {
1901 default:
1902 break;
1903 case DK_SET:
1904 case DK_EQU:
1905 return parseDirectiveSet(IDVal, true);
1906 case DK_EQUIV:
1907 return parseDirectiveSet(IDVal, false);
1908 case DK_ASCII:
1909 return parseDirectiveAscii(IDVal, false);
1910 case DK_ASCIZ:
1911 case DK_STRING:
1912 return parseDirectiveAscii(IDVal, true);
1913 case DK_BYTE:
1914 case DK_DC_B:
1915 return parseDirectiveValue(IDVal, 1);
1916 case DK_DC:
1917 case DK_DC_W:
1918 case DK_SHORT:
1919 case DK_VALUE:
1920 case DK_2BYTE:
1921 return parseDirectiveValue(IDVal, 2);
1922 case DK_LONG:
1923 case DK_INT:
1924 case DK_4BYTE:
1925 case DK_DC_L:
1926 return parseDirectiveValue(IDVal, 4);
1927 case DK_QUAD:
1928 case DK_8BYTE:
1929 return parseDirectiveValue(IDVal, 8);
1930 case DK_DC_A:
1931 return parseDirectiveValue(
1932 IDVal, getContext().getAsmInfo()->getCodePointerSize());
1933 case DK_OCTA:
1934 return parseDirectiveOctaValue(IDVal);
1935 case DK_SINGLE:
1936 case DK_FLOAT:
1937 case DK_DC_S:
1938 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());
1939 case DK_DOUBLE:
1940 case DK_DC_D:
1941 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());
1942 case DK_ALIGN: {
1943 bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
1944 return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);
1946 case DK_ALIGN32: {
1947 bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
1948 return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);
1950 case DK_BALIGN:
1951 return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
1952 case DK_BALIGNW:
1953 return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
1954 case DK_BALIGNL:
1955 return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
1956 case DK_P2ALIGN:
1957 return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
1958 case DK_P2ALIGNW:
1959 return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
1960 case DK_P2ALIGNL:
1961 return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
1962 case DK_ORG:
1963 return parseDirectiveOrg();
1964 case DK_FILL:
1965 return parseDirectiveFill();
1966 case DK_ZERO:
1967 return parseDirectiveZero();
1968 case DK_EXTERN:
1969 eatToEndOfStatement(); // .extern is the default, ignore it.
1970 return false;
1971 case DK_GLOBL:
1972 case DK_GLOBAL:
1973 return parseDirectiveSymbolAttribute(MCSA_Global);
1974 case DK_LAZY_REFERENCE:
1975 return parseDirectiveSymbolAttribute(MCSA_LazyReference);
1976 case DK_NO_DEAD_STRIP:
1977 return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
1978 case DK_SYMBOL_RESOLVER:
1979 return parseDirectiveSymbolAttribute(MCSA_SymbolResolver);
1980 case DK_PRIVATE_EXTERN:
1981 return parseDirectiveSymbolAttribute(MCSA_PrivateExtern);
1982 case DK_REFERENCE:
1983 return parseDirectiveSymbolAttribute(MCSA_Reference);
1984 case DK_WEAK_DEFINITION:
1985 return parseDirectiveSymbolAttribute(MCSA_WeakDefinition);
1986 case DK_WEAK_REFERENCE:
1987 return parseDirectiveSymbolAttribute(MCSA_WeakReference);
1988 case DK_WEAK_DEF_CAN_BE_HIDDEN:
1989 return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
1990 case DK_COLD:
1991 return parseDirectiveSymbolAttribute(MCSA_Cold);
1992 case DK_COMM:
1993 case DK_COMMON:
1994 return parseDirectiveComm(/*IsLocal=*/false);
1995 case DK_LCOMM:
1996 return parseDirectiveComm(/*IsLocal=*/true);
1997 case DK_ABORT:
1998 return parseDirectiveAbort();
1999 case DK_INCLUDE:
2000 return parseDirectiveInclude();
2001 case DK_INCBIN:
2002 return parseDirectiveIncbin();
2003 case DK_CODE16:
2004 case DK_CODE16GCC:
2005 return TokError(Twine(IDVal) +
2006 " not currently supported for this target");
2007 case DK_REPT:
2008 return parseDirectiveRept(IDLoc, IDVal);
2009 case DK_IRP:
2010 return parseDirectiveIrp(IDLoc);
2011 case DK_IRPC:
2012 return parseDirectiveIrpc(IDLoc);
2013 case DK_ENDR:
2014 return parseDirectiveEndr(IDLoc);
2015 case DK_BUNDLE_ALIGN_MODE:
2016 return parseDirectiveBundleAlignMode();
2017 case DK_BUNDLE_LOCK:
2018 return parseDirectiveBundleLock();
2019 case DK_BUNDLE_UNLOCK:
2020 return parseDirectiveBundleUnlock();
2021 case DK_SLEB128:
2022 return parseDirectiveLEB128(true);
2023 case DK_ULEB128:
2024 return parseDirectiveLEB128(false);
2025 case DK_SPACE:
2026 case DK_SKIP:
2027 return parseDirectiveSpace(IDVal);
2028 case DK_FILE:
2029 return parseDirectiveFile(IDLoc);
2030 case DK_LINE:
2031 return parseDirectiveLine();
2032 case DK_LOC:
2033 return parseDirectiveLoc();
2034 case DK_STABS:
2035 return parseDirectiveStabs();
2036 case DK_CV_FILE:
2037 return parseDirectiveCVFile();
2038 case DK_CV_FUNC_ID:
2039 return parseDirectiveCVFuncId();
2040 case DK_CV_INLINE_SITE_ID:
2041 return parseDirectiveCVInlineSiteId();
2042 case DK_CV_LOC:
2043 return parseDirectiveCVLoc();
2044 case DK_CV_LINETABLE:
2045 return parseDirectiveCVLinetable();
2046 case DK_CV_INLINE_LINETABLE:
2047 return parseDirectiveCVInlineLinetable();
2048 case DK_CV_DEF_RANGE:
2049 return parseDirectiveCVDefRange();
2050 case DK_CV_STRING:
2051 return parseDirectiveCVString();
2052 case DK_CV_STRINGTABLE:
2053 return parseDirectiveCVStringTable();
2054 case DK_CV_FILECHECKSUMS:
2055 return parseDirectiveCVFileChecksums();
2056 case DK_CV_FILECHECKSUM_OFFSET:
2057 return parseDirectiveCVFileChecksumOffset();
2058 case DK_CV_FPO_DATA:
2059 return parseDirectiveCVFPOData();
2060 case DK_CFI_SECTIONS:
2061 return parseDirectiveCFISections();
2062 case DK_CFI_STARTPROC:
2063 return parseDirectiveCFIStartProc();
2064 case DK_CFI_ENDPROC:
2065 return parseDirectiveCFIEndProc();
2066 case DK_CFI_DEF_CFA:
2067 return parseDirectiveCFIDefCfa(IDLoc);
2068 case DK_CFI_DEF_CFA_OFFSET:
2069 return parseDirectiveCFIDefCfaOffset();
2070 case DK_CFI_ADJUST_CFA_OFFSET:
2071 return parseDirectiveCFIAdjustCfaOffset();
2072 case DK_CFI_DEF_CFA_REGISTER:
2073 return parseDirectiveCFIDefCfaRegister(IDLoc);
2074 case DK_CFI_OFFSET:
2075 return parseDirectiveCFIOffset(IDLoc);
2076 case DK_CFI_REL_OFFSET:
2077 return parseDirectiveCFIRelOffset(IDLoc);
2078 case DK_CFI_PERSONALITY:
2079 return parseDirectiveCFIPersonalityOrLsda(true);
2080 case DK_CFI_LSDA:
2081 return parseDirectiveCFIPersonalityOrLsda(false);
2082 case DK_CFI_REMEMBER_STATE:
2083 return parseDirectiveCFIRememberState();
2084 case DK_CFI_RESTORE_STATE:
2085 return parseDirectiveCFIRestoreState();
2086 case DK_CFI_SAME_VALUE:
2087 return parseDirectiveCFISameValue(IDLoc);
2088 case DK_CFI_RESTORE:
2089 return parseDirectiveCFIRestore(IDLoc);
2090 case DK_CFI_ESCAPE:
2091 return parseDirectiveCFIEscape();
2092 case DK_CFI_RETURN_COLUMN:
2093 return parseDirectiveCFIReturnColumn(IDLoc);
2094 case DK_CFI_SIGNAL_FRAME:
2095 return parseDirectiveCFISignalFrame();
2096 case DK_CFI_UNDEFINED:
2097 return parseDirectiveCFIUndefined(IDLoc);
2098 case DK_CFI_REGISTER:
2099 return parseDirectiveCFIRegister(IDLoc);
2100 case DK_CFI_WINDOW_SAVE:
2101 return parseDirectiveCFIWindowSave();
2102 case DK_MACROS_ON:
2103 case DK_MACROS_OFF:
2104 return parseDirectiveMacrosOnOff(IDVal);
2105 case DK_MACRO:
2106 return parseDirectiveMacro(IDLoc);
2107 case DK_ALTMACRO:
2108 case DK_NOALTMACRO:
2109 return parseDirectiveAltmacro(IDVal);
2110 case DK_EXITM:
2111 return parseDirectiveExitMacro(IDVal);
2112 case DK_ENDM:
2113 case DK_ENDMACRO:
2114 return parseDirectiveEndMacro(IDVal);
2115 case DK_PURGEM:
2116 return parseDirectivePurgeMacro(IDLoc);
2117 case DK_END:
2118 return parseDirectiveEnd(IDLoc);
2119 case DK_ERR:
2120 return parseDirectiveError(IDLoc, false);
2121 case DK_ERROR:
2122 return parseDirectiveError(IDLoc, true);
2123 case DK_WARNING:
2124 return parseDirectiveWarning(IDLoc);
2125 case DK_RELOC:
2126 return parseDirectiveReloc(IDLoc);
2127 case DK_DCB:
2128 case DK_DCB_W:
2129 return parseDirectiveDCB(IDVal, 2);
2130 case DK_DCB_B:
2131 return parseDirectiveDCB(IDVal, 1);
2132 case DK_DCB_D:
2133 return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble());
2134 case DK_DCB_L:
2135 return parseDirectiveDCB(IDVal, 4);
2136 case DK_DCB_S:
2137 return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle());
2138 case DK_DC_X:
2139 case DK_DCB_X:
2140 return TokError(Twine(IDVal) +
2141 " not currently supported for this target");
2142 case DK_DS:
2143 case DK_DS_W:
2144 return parseDirectiveDS(IDVal, 2);
2145 case DK_DS_B:
2146 return parseDirectiveDS(IDVal, 1);
2147 case DK_DS_D:
2148 return parseDirectiveDS(IDVal, 8);
2149 case DK_DS_L:
2150 case DK_DS_S:
2151 return parseDirectiveDS(IDVal, 4);
2152 case DK_DS_P:
2153 case DK_DS_X:
2154 return parseDirectiveDS(IDVal, 12);
2155 case DK_PRINT:
2156 return parseDirectivePrint(IDLoc);
2157 case DK_ADDRSIG:
2158 return parseDirectiveAddrsig();
2159 case DK_ADDRSIG_SYM:
2160 return parseDirectiveAddrsigSym();
2163 return Error(IDLoc, "unknown directive");
2166 // __asm _emit or __asm __emit
2167 if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
2168 IDVal == "_EMIT" || IDVal == "__EMIT"))
2169 return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
2171 // __asm align
2172 if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
2173 return parseDirectiveMSAlign(IDLoc, Info);
2175 if (ParsingInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
2176 Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
2177 if (checkForValidSection())
2178 return true;
2180 // Canonicalize the opcode to lower case.
2181 std::string OpcodeStr = IDVal.lower();
2182 ParseInstructionInfo IInfo(Info.AsmRewrites);
2183 bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
2184 Info.ParsedOperands);
2185 Info.ParseError = ParseHadError;
2187 // Dump the parsed representation, if requested.
2188 if (getShowParsedOperands()) {
2189 SmallString<256> Str;
2190 raw_svector_ostream OS(Str);
2191 OS << "parsed instruction: [";
2192 for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
2193 if (i != 0)
2194 OS << ", ";
2195 Info.ParsedOperands[i]->print(OS);
2197 OS << "]";
2199 printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
2202 // Fail even if ParseInstruction erroneously returns false.
2203 if (hasPendingError() || ParseHadError)
2204 return true;
2206 // If we are generating dwarf for the current section then generate a .loc
2207 // directive for the instruction.
2208 if (!ParseHadError && enabledGenDwarfForAssembly() &&
2209 getContext().getGenDwarfSectionSyms().count(
2210 getStreamer().getCurrentSectionOnly())) {
2211 unsigned Line;
2212 if (ActiveMacros.empty())
2213 Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
2214 else
2215 Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
2216 ActiveMacros.front()->ExitBuffer);
2218 // If we previously parsed a cpp hash file line comment then make sure the
2219 // current Dwarf File is for the CppHashFilename if not then emit the
2220 // Dwarf File table for it and adjust the line number for the .loc.
2221 if (!CppHashInfo.Filename.empty()) {
2222 unsigned FileNumber = getStreamer().EmitDwarfFileDirective(
2223 0, StringRef(), CppHashInfo.Filename);
2224 getContext().setGenDwarfFileNumber(FileNumber);
2226 unsigned CppHashLocLineNo =
2227 SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
2228 Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
2231 getStreamer().EmitDwarfLocDirective(
2232 getContext().getGenDwarfFileNumber(), Line, 0,
2233 DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
2234 StringRef());
2237 // If parsing succeeded, match the instruction.
2238 if (!ParseHadError) {
2239 uint64_t ErrorInfo;
2240 if (getTargetParser().MatchAndEmitInstruction(
2241 IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
2242 getTargetParser().isParsingInlineAsm()))
2243 return true;
2245 return false;
2248 // Parse and erase curly braces marking block start/end
2249 bool
2250 AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2251 // Identify curly brace marking block start/end
2252 if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
2253 return false;
2255 SMLoc StartLoc = Lexer.getLoc();
2256 Lex(); // Eat the brace
2257 if (Lexer.is(AsmToken::EndOfStatement))
2258 Lex(); // Eat EndOfStatement following the brace
2260 // Erase the block start/end brace from the output asm string
2261 AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
2262 StartLoc.getPointer());
2263 return true;
2266 /// parseCppHashLineFilenameComment as this:
2267 /// ::= # number "filename"
2268 bool AsmParser::parseCppHashLineFilenameComment(SMLoc L) {
2269 Lex(); // Eat the hash token.
2270 // Lexer only ever emits HashDirective if it fully formed if it's
2271 // done the checking already so this is an internal error.
2272 assert(getTok().is(AsmToken::Integer) &&
2273 "Lexing Cpp line comment: Expected Integer");
2274 int64_t LineNumber = getTok().getIntVal();
2275 Lex();
2276 assert(getTok().is(AsmToken::String) &&
2277 "Lexing Cpp line comment: Expected String");
2278 StringRef Filename = getTok().getString();
2279 Lex();
2281 // Get rid of the enclosing quotes.
2282 Filename = Filename.substr(1, Filename.size() - 2);
2284 // Save the SMLoc, Filename and LineNumber for later use by diagnostics.
2285 CppHashInfo.Loc = L;
2286 CppHashInfo.Filename = Filename;
2287 CppHashInfo.LineNumber = LineNumber;
2288 CppHashInfo.Buf = CurBuffer;
2289 return false;
2292 /// will use the last parsed cpp hash line filename comment
2293 /// for the Filename and LineNo if any in the diagnostic.
2294 void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
2295 const AsmParser *Parser = static_cast<const AsmParser *>(Context);
2296 raw_ostream &OS = errs();
2298 const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
2299 SMLoc DiagLoc = Diag.getLoc();
2300 unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
2301 unsigned CppHashBuf =
2302 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2304 // Like SourceMgr::printMessage() we need to print the include stack if any
2305 // before printing the message.
2306 unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
2307 if (!Parser->SavedDiagHandler && DiagCurBuffer &&
2308 DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
2309 SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
2310 DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
2313 // If we have not parsed a cpp hash line filename comment or the source
2314 // manager changed or buffer changed (like in a nested include) then just
2315 // print the normal diagnostic using its Filename and LineNo.
2316 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2317 DiagBuf != CppHashBuf) {
2318 if (Parser->SavedDiagHandler)
2319 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2320 else
2321 Diag.print(nullptr, OS);
2322 return;
2325 // Use the CppHashFilename and calculate a line number based on the
2326 // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
2327 // for the diagnostic.
2328 const std::string &Filename = Parser->CppHashInfo.Filename;
2330 int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
2331 int CppHashLocLineNo =
2332 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2333 int LineNo =
2334 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2336 SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
2337 Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
2338 Diag.getLineContents(), Diag.getRanges());
2340 if (Parser->SavedDiagHandler)
2341 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2342 else
2343 NewDiag.print(nullptr, OS);
2346 // FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The
2347 // difference being that that function accepts '@' as part of identifiers and
2348 // we can't do that. AsmLexer.cpp should probably be changed to handle
2349 // '@' as a special case when needed.
2350 static bool isIdentifierChar(char c) {
2351 return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||
2352 c == '.';
2355 bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2356 ArrayRef<MCAsmMacroParameter> Parameters,
2357 ArrayRef<MCAsmMacroArgument> A,
2358 bool EnableAtPseudoVariable, SMLoc L) {
2359 unsigned NParameters = Parameters.size();
2360 bool HasVararg = NParameters ? Parameters.back().Vararg : false;
2361 if ((!IsDarwin || NParameters != 0) && NParameters != A.size())
2362 return Error(L, "Wrong number of arguments");
2364 // A macro without parameters is handled differently on Darwin:
2365 // gas accepts no arguments and does no substitutions
2366 while (!Body.empty()) {
2367 // Scan for the next substitution.
2368 std::size_t End = Body.size(), Pos = 0;
2369 for (; Pos != End; ++Pos) {
2370 // Check for a substitution or escape.
2371 if (IsDarwin && !NParameters) {
2372 // This macro has no parameters, look for $0, $1, etc.
2373 if (Body[Pos] != '$' || Pos + 1 == End)
2374 continue;
2376 char Next = Body[Pos + 1];
2377 if (Next == '$' || Next == 'n' ||
2378 isdigit(static_cast<unsigned char>(Next)))
2379 break;
2380 } else {
2381 // This macro has parameters, look for \foo, \bar, etc.
2382 if (Body[Pos] == '\\' && Pos + 1 != End)
2383 break;
2387 // Add the prefix.
2388 OS << Body.slice(0, Pos);
2390 // Check if we reached the end.
2391 if (Pos == End)
2392 break;
2394 if (IsDarwin && !NParameters) {
2395 switch (Body[Pos + 1]) {
2396 // $$ => $
2397 case '$':
2398 OS << '$';
2399 break;
2401 // $n => number of arguments
2402 case 'n':
2403 OS << A.size();
2404 break;
2406 // $[0-9] => argument
2407 default: {
2408 // Missing arguments are ignored.
2409 unsigned Index = Body[Pos + 1] - '0';
2410 if (Index >= A.size())
2411 break;
2413 // Otherwise substitute with the token values, with spaces eliminated.
2414 for (const AsmToken &Token : A[Index])
2415 OS << Token.getString();
2416 break;
2419 Pos += 2;
2420 } else {
2421 unsigned I = Pos + 1;
2423 // Check for the \@ pseudo-variable.
2424 if (EnableAtPseudoVariable && Body[I] == '@' && I + 1 != End)
2425 ++I;
2426 else
2427 while (isIdentifierChar(Body[I]) && I + 1 != End)
2428 ++I;
2430 const char *Begin = Body.data() + Pos + 1;
2431 StringRef Argument(Begin, I - (Pos + 1));
2432 unsigned Index = 0;
2434 if (Argument == "@") {
2435 OS << NumOfMacroInstantiations;
2436 Pos += 2;
2437 } else {
2438 for (; Index < NParameters; ++Index)
2439 if (Parameters[Index].Name == Argument)
2440 break;
2442 if (Index == NParameters) {
2443 if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
2444 Pos += 3;
2445 else {
2446 OS << '\\' << Argument;
2447 Pos = I;
2449 } else {
2450 bool VarargParameter = HasVararg && Index == (NParameters - 1);
2451 for (const AsmToken &Token : A[Index])
2452 // For altmacro mode, you can write '%expr'.
2453 // The prefix '%' evaluates the expression 'expr'
2454 // and uses the result as a string (e.g. replace %(1+2) with the
2455 // string "3").
2456 // Here, we identify the integer token which is the result of the
2457 // absolute expression evaluation and replace it with its string
2458 // representation.
2459 if (AltMacroMode && Token.getString().front() == '%' &&
2460 Token.is(AsmToken::Integer))
2461 // Emit an integer value to the buffer.
2462 OS << Token.getIntVal();
2463 // Only Token that was validated as a string and begins with '<'
2464 // is considered altMacroString!!!
2465 else if (AltMacroMode && Token.getString().front() == '<' &&
2466 Token.is(AsmToken::String)) {
2467 OS << altMacroString(Token.getStringContents());
2469 // We expect no quotes around the string's contents when
2470 // parsing for varargs.
2471 else if (Token.isNot(AsmToken::String) || VarargParameter)
2472 OS << Token.getString();
2473 else
2474 OS << Token.getStringContents();
2476 Pos += 1 + Argument.size();
2480 // Update the scan point.
2481 Body = Body.substr(Pos);
2484 return false;
2487 MacroInstantiation::MacroInstantiation(SMLoc IL, int EB, SMLoc EL,
2488 size_t CondStackDepth)
2489 : InstantiationLoc(IL), ExitBuffer(EB), ExitLoc(EL),
2490 CondStackDepth(CondStackDepth) {}
2492 static bool isOperator(AsmToken::TokenKind kind) {
2493 switch (kind) {
2494 default:
2495 return false;
2496 case AsmToken::Plus:
2497 case AsmToken::Minus:
2498 case AsmToken::Tilde:
2499 case AsmToken::Slash:
2500 case AsmToken::Star:
2501 case AsmToken::Dot:
2502 case AsmToken::Equal:
2503 case AsmToken::EqualEqual:
2504 case AsmToken::Pipe:
2505 case AsmToken::PipePipe:
2506 case AsmToken::Caret:
2507 case AsmToken::Amp:
2508 case AsmToken::AmpAmp:
2509 case AsmToken::Exclaim:
2510 case AsmToken::ExclaimEqual:
2511 case AsmToken::Less:
2512 case AsmToken::LessEqual:
2513 case AsmToken::LessLess:
2514 case AsmToken::LessGreater:
2515 case AsmToken::Greater:
2516 case AsmToken::GreaterEqual:
2517 case AsmToken::GreaterGreater:
2518 return true;
2522 namespace {
2524 class AsmLexerSkipSpaceRAII {
2525 public:
2526 AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
2527 Lexer.setSkipSpace(SkipSpace);
2530 ~AsmLexerSkipSpaceRAII() {
2531 Lexer.setSkipSpace(true);
2534 private:
2535 AsmLexer &Lexer;
2538 } // end anonymous namespace
2540 bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
2542 if (Vararg) {
2543 if (Lexer.isNot(AsmToken::EndOfStatement)) {
2544 StringRef Str = parseStringToEndOfStatement();
2545 MA.emplace_back(AsmToken::String, Str);
2547 return false;
2550 unsigned ParenLevel = 0;
2552 // Darwin doesn't use spaces to delmit arguments.
2553 AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
2555 bool SpaceEaten;
2557 while (true) {
2558 SpaceEaten = false;
2559 if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
2560 return TokError("unexpected token in macro instantiation");
2562 if (ParenLevel == 0) {
2564 if (Lexer.is(AsmToken::Comma))
2565 break;
2567 if (Lexer.is(AsmToken::Space)) {
2568 SpaceEaten = true;
2569 Lexer.Lex(); // Eat spaces
2572 // Spaces can delimit parameters, but could also be part an expression.
2573 // If the token after a space is an operator, add the token and the next
2574 // one into this argument
2575 if (!IsDarwin) {
2576 if (isOperator(Lexer.getKind())) {
2577 MA.push_back(getTok());
2578 Lexer.Lex();
2580 // Whitespace after an operator can be ignored.
2581 if (Lexer.is(AsmToken::Space))
2582 Lexer.Lex();
2584 continue;
2587 if (SpaceEaten)
2588 break;
2591 // handleMacroEntry relies on not advancing the lexer here
2592 // to be able to fill in the remaining default parameter values
2593 if (Lexer.is(AsmToken::EndOfStatement))
2594 break;
2596 // Adjust the current parentheses level.
2597 if (Lexer.is(AsmToken::LParen))
2598 ++ParenLevel;
2599 else if (Lexer.is(AsmToken::RParen) && ParenLevel)
2600 --ParenLevel;
2602 // Append the token to the current argument list.
2603 MA.push_back(getTok());
2604 Lexer.Lex();
2607 if (ParenLevel != 0)
2608 return TokError("unbalanced parentheses in macro argument");
2609 return false;
2612 // Parse the macro instantiation arguments.
2613 bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
2614 MCAsmMacroArguments &A) {
2615 const unsigned NParameters = M ? M->Parameters.size() : 0;
2616 bool NamedParametersFound = false;
2617 SmallVector<SMLoc, 4> FALocs;
2619 A.resize(NParameters);
2620 FALocs.resize(NParameters);
2622 // Parse two kinds of macro invocations:
2623 // - macros defined without any parameters accept an arbitrary number of them
2624 // - macros defined with parameters accept at most that many of them
2625 bool HasVararg = NParameters ? M->Parameters.back().Vararg : false;
2626 for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
2627 ++Parameter) {
2628 SMLoc IDLoc = Lexer.getLoc();
2629 MCAsmMacroParameter FA;
2631 if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
2632 if (parseIdentifier(FA.Name))
2633 return Error(IDLoc, "invalid argument identifier for formal argument");
2635 if (Lexer.isNot(AsmToken::Equal))
2636 return TokError("expected '=' after formal parameter identifier");
2638 Lex();
2640 NamedParametersFound = true;
2642 bool Vararg = HasVararg && Parameter == (NParameters - 1);
2644 if (NamedParametersFound && FA.Name.empty())
2645 return Error(IDLoc, "cannot mix positional and keyword arguments");
2647 SMLoc StrLoc = Lexer.getLoc();
2648 SMLoc EndLoc;
2649 if (AltMacroMode && Lexer.is(AsmToken::Percent)) {
2650 const MCExpr *AbsoluteExp;
2651 int64_t Value;
2652 /// Eat '%'
2653 Lex();
2654 if (parseExpression(AbsoluteExp, EndLoc))
2655 return false;
2656 if (!AbsoluteExp->evaluateAsAbsolute(Value,
2657 getStreamer().getAssemblerPtr()))
2658 return Error(StrLoc, "expected absolute expression");
2659 const char *StrChar = StrLoc.getPointer();
2660 const char *EndChar = EndLoc.getPointer();
2661 AsmToken newToken(AsmToken::Integer,
2662 StringRef(StrChar, EndChar - StrChar), Value);
2663 FA.Value.push_back(newToken);
2664 } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
2665 isAltmacroString(StrLoc, EndLoc)) {
2666 const char *StrChar = StrLoc.getPointer();
2667 const char *EndChar = EndLoc.getPointer();
2668 jumpToLoc(EndLoc, CurBuffer);
2669 /// Eat from '<' to '>'
2670 Lex();
2671 AsmToken newToken(AsmToken::String,
2672 StringRef(StrChar, EndChar - StrChar));
2673 FA.Value.push_back(newToken);
2674 } else if(parseMacroArgument(FA.Value, Vararg))
2675 return true;
2677 unsigned PI = Parameter;
2678 if (!FA.Name.empty()) {
2679 unsigned FAI = 0;
2680 for (FAI = 0; FAI < NParameters; ++FAI)
2681 if (M->Parameters[FAI].Name == FA.Name)
2682 break;
2684 if (FAI >= NParameters) {
2685 assert(M && "expected macro to be defined");
2686 return Error(IDLoc, "parameter named '" + FA.Name +
2687 "' does not exist for macro '" + M->Name + "'");
2689 PI = FAI;
2692 if (!FA.Value.empty()) {
2693 if (A.size() <= PI)
2694 A.resize(PI + 1);
2695 A[PI] = FA.Value;
2697 if (FALocs.size() <= PI)
2698 FALocs.resize(PI + 1);
2700 FALocs[PI] = Lexer.getLoc();
2703 // At the end of the statement, fill in remaining arguments that have
2704 // default values. If there aren't any, then the next argument is
2705 // required but missing
2706 if (Lexer.is(AsmToken::EndOfStatement)) {
2707 bool Failure = false;
2708 for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
2709 if (A[FAI].empty()) {
2710 if (M->Parameters[FAI].Required) {
2711 Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
2712 "missing value for required parameter "
2713 "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
2714 Failure = true;
2717 if (!M->Parameters[FAI].Value.empty())
2718 A[FAI] = M->Parameters[FAI].Value;
2721 return Failure;
2724 if (Lexer.is(AsmToken::Comma))
2725 Lex();
2728 return TokError("too many positional arguments");
2731 bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
2732 // Arbitrarily limit macro nesting depth (default matches 'as'). We can
2733 // eliminate this, although we should protect against infinite loops.
2734 unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
2735 if (ActiveMacros.size() == MaxNestingDepth) {
2736 std::ostringstream MaxNestingDepthError;
2737 MaxNestingDepthError << "macros cannot be nested more than "
2738 << MaxNestingDepth << " levels deep."
2739 << " Use -asm-macro-max-nesting-depth to increase "
2740 "this limit.";
2741 return TokError(MaxNestingDepthError.str());
2744 MCAsmMacroArguments A;
2745 if (parseMacroArguments(M, A))
2746 return true;
2748 // Macro instantiation is lexical, unfortunately. We construct a new buffer
2749 // to hold the macro body with substitutions.
2750 SmallString<256> Buf;
2751 StringRef Body = M->Body;
2752 raw_svector_ostream OS(Buf);
2754 if (expandMacro(OS, Body, M->Parameters, A, true, getTok().getLoc()))
2755 return true;
2757 // We include the .endmacro in the buffer as our cue to exit the macro
2758 // instantiation.
2759 OS << ".endmacro\n";
2761 std::unique_ptr<MemoryBuffer> Instantiation =
2762 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
2764 // Create the macro instantiation object and add to the current macro
2765 // instantiation stack.
2766 MacroInstantiation *MI = new MacroInstantiation(
2767 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size());
2768 ActiveMacros.push_back(MI);
2770 ++NumOfMacroInstantiations;
2772 // Jump to the macro instantiation and prime the lexer.
2773 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
2774 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
2775 Lex();
2777 return false;
2780 void AsmParser::handleMacroExit() {
2781 // Jump to the EndOfStatement we should return to, and consume it.
2782 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
2783 Lex();
2785 // Pop the instantiation entry.
2786 delete ActiveMacros.back();
2787 ActiveMacros.pop_back();
2790 bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
2791 bool NoDeadStrip) {
2792 MCSymbol *Sym;
2793 const MCExpr *Value;
2794 if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym,
2795 Value))
2796 return true;
2798 if (!Sym) {
2799 // In the case where we parse an expression starting with a '.', we will
2800 // not generate an error, nor will we create a symbol. In this case we
2801 // should just return out.
2802 return false;
2805 // Do the assignment.
2806 Out.EmitAssignment(Sym, Value);
2807 if (NoDeadStrip)
2808 Out.EmitSymbolAttribute(Sym, MCSA_NoDeadStrip);
2810 return false;
2813 /// parseIdentifier:
2814 /// ::= identifier
2815 /// ::= string
2816 bool AsmParser::parseIdentifier(StringRef &Res) {
2817 // The assembler has relaxed rules for accepting identifiers, in particular we
2818 // allow things like '.globl $foo' and '.def @feat.00', which would normally be
2819 // separate tokens. At this level, we have already lexed so we cannot (currently)
2820 // handle this as a context dependent token, instead we detect adjacent tokens
2821 // and return the combined identifier.
2822 if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
2823 SMLoc PrefixLoc = getLexer().getLoc();
2825 // Consume the prefix character, and check for a following identifier.
2827 AsmToken Buf[1];
2828 Lexer.peekTokens(Buf, false);
2830 if (Buf[0].isNot(AsmToken::Identifier))
2831 return true;
2833 // We have a '$' or '@' followed by an identifier, make sure they are adjacent.
2834 if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())
2835 return true;
2837 // eat $ or @
2838 Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
2839 // Construct the joined identifier and consume the token.
2840 Res =
2841 StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1);
2842 Lex(); // Parser Lex to maintain invariants.
2843 return false;
2846 if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
2847 return true;
2849 Res = getTok().getIdentifier();
2851 Lex(); // Consume the identifier token.
2853 return false;
2856 /// parseDirectiveSet:
2857 /// ::= .equ identifier ',' expression
2858 /// ::= .equiv identifier ',' expression
2859 /// ::= .set identifier ',' expression
2860 bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) {
2861 StringRef Name;
2862 if (check(parseIdentifier(Name), "expected identifier") ||
2863 parseToken(AsmToken::Comma) || parseAssignment(Name, allow_redef, true))
2864 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
2865 return false;
2868 bool AsmParser::parseEscapedString(std::string &Data) {
2869 if (check(getTok().isNot(AsmToken::String), "expected string"))
2870 return true;
2872 Data = "";
2873 StringRef Str = getTok().getStringContents();
2874 for (unsigned i = 0, e = Str.size(); i != e; ++i) {
2875 if (Str[i] != '\\') {
2876 Data += Str[i];
2877 continue;
2880 // Recognize escaped characters. Note that this escape semantics currently
2881 // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes.
2882 ++i;
2883 if (i == e)
2884 return TokError("unexpected backslash at end of string");
2886 // Recognize octal sequences.
2887 if ((unsigned)(Str[i] - '0') <= 7) {
2888 // Consume up to three octal characters.
2889 unsigned Value = Str[i] - '0';
2891 if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
2892 ++i;
2893 Value = Value * 8 + (Str[i] - '0');
2895 if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
2896 ++i;
2897 Value = Value * 8 + (Str[i] - '0');
2901 if (Value > 255)
2902 return TokError("invalid octal escape sequence (out of range)");
2904 Data += (unsigned char)Value;
2905 continue;
2908 // Otherwise recognize individual escapes.
2909 switch (Str[i]) {
2910 default:
2911 // Just reject invalid escape sequences for now.
2912 return TokError("invalid escape sequence (unrecognized character)");
2914 case 'b': Data += '\b'; break;
2915 case 'f': Data += '\f'; break;
2916 case 'n': Data += '\n'; break;
2917 case 'r': Data += '\r'; break;
2918 case 't': Data += '\t'; break;
2919 case '"': Data += '"'; break;
2920 case '\\': Data += '\\'; break;
2924 Lex();
2925 return false;
2928 /// parseDirectiveAscii:
2929 /// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
2930 bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
2931 auto parseOp = [&]() -> bool {
2932 std::string Data;
2933 if (checkForValidSection() || parseEscapedString(Data))
2934 return true;
2935 getStreamer().EmitBytes(Data);
2936 if (ZeroTerminated)
2937 getStreamer().EmitBytes(StringRef("\0", 1));
2938 return false;
2941 if (parseMany(parseOp))
2942 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
2943 return false;
2946 /// parseDirectiveReloc
2947 /// ::= .reloc expression , identifier [ , expression ]
2948 bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
2949 const MCExpr *Offset;
2950 const MCExpr *Expr = nullptr;
2951 int64_t OffsetValue;
2952 SMLoc OffsetLoc = Lexer.getTok().getLoc();
2954 if (parseExpression(Offset))
2955 return true;
2957 if ((Offset->evaluateAsAbsolute(OffsetValue,
2958 getStreamer().getAssemblerPtr()) &&
2959 check(OffsetValue < 0, OffsetLoc, "expression is negative")) ||
2960 (check(Offset->getKind() != llvm::MCExpr::Constant &&
2961 Offset->getKind() != llvm::MCExpr::SymbolRef,
2962 OffsetLoc, "expected non-negative number or a label")) ||
2963 (parseToken(AsmToken::Comma, "expected comma") ||
2964 check(getTok().isNot(AsmToken::Identifier), "expected relocation name")))
2965 return true;
2967 SMLoc NameLoc = Lexer.getTok().getLoc();
2968 StringRef Name = Lexer.getTok().getIdentifier();
2969 Lex();
2971 if (Lexer.is(AsmToken::Comma)) {
2972 Lex();
2973 SMLoc ExprLoc = Lexer.getLoc();
2974 if (parseExpression(Expr))
2975 return true;
2977 MCValue Value;
2978 if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr))
2979 return Error(ExprLoc, "expression must be relocatable");
2982 if (parseToken(AsmToken::EndOfStatement,
2983 "unexpected token in .reloc directive"))
2984 return true;
2986 const MCTargetAsmParser &MCT = getTargetParser();
2987 const MCSubtargetInfo &STI = MCT.getSTI();
2988 if (getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc, STI))
2989 return Error(NameLoc, "unknown relocation name");
2991 return false;
2994 /// parseDirectiveValue
2995 /// ::= (.byte | .short | ... ) [ expression (, expression)* ]
2996 bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
2997 auto parseOp = [&]() -> bool {
2998 const MCExpr *Value;
2999 SMLoc ExprLoc = getLexer().getLoc();
3000 if (checkForValidSection() || parseExpression(Value))
3001 return true;
3002 // Special case constant expressions to match code generator.
3003 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3004 assert(Size <= 8 && "Invalid size");
3005 uint64_t IntValue = MCE->getValue();
3006 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
3007 return Error(ExprLoc, "out of range literal value");
3008 getStreamer().EmitIntValue(IntValue, Size);
3009 } else
3010 getStreamer().EmitValue(Value, Size, ExprLoc);
3011 return false;
3014 if (parseMany(parseOp))
3015 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3016 return false;
3019 static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {
3020 if (Asm.getTok().isNot(AsmToken::Integer) &&
3021 Asm.getTok().isNot(AsmToken::BigNum))
3022 return Asm.TokError("unknown token in expression");
3023 SMLoc ExprLoc = Asm.getTok().getLoc();
3024 APInt IntValue = Asm.getTok().getAPIntVal();
3025 Asm.Lex();
3026 if (!IntValue.isIntN(128))
3027 return Asm.Error(ExprLoc, "out of range literal value");
3028 if (!IntValue.isIntN(64)) {
3029 hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
3030 lo = IntValue.getLoBits(64).getZExtValue();
3031 } else {
3032 hi = 0;
3033 lo = IntValue.getZExtValue();
3035 return false;
3038 /// ParseDirectiveOctaValue
3039 /// ::= .octa [ hexconstant (, hexconstant)* ]
3041 bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
3042 auto parseOp = [&]() -> bool {
3043 if (checkForValidSection())
3044 return true;
3045 uint64_t hi, lo;
3046 if (parseHexOcta(*this, hi, lo))
3047 return true;
3048 if (MAI.isLittleEndian()) {
3049 getStreamer().EmitIntValue(lo, 8);
3050 getStreamer().EmitIntValue(hi, 8);
3051 } else {
3052 getStreamer().EmitIntValue(hi, 8);
3053 getStreamer().EmitIntValue(lo, 8);
3055 return false;
3058 if (parseMany(parseOp))
3059 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3060 return false;
3063 bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
3064 // We don't truly support arithmetic on floating point expressions, so we
3065 // have to manually parse unary prefixes.
3066 bool IsNeg = false;
3067 if (getLexer().is(AsmToken::Minus)) {
3068 Lexer.Lex();
3069 IsNeg = true;
3070 } else if (getLexer().is(AsmToken::Plus))
3071 Lexer.Lex();
3073 if (Lexer.is(AsmToken::Error))
3074 return TokError(Lexer.getErr());
3075 if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
3076 Lexer.isNot(AsmToken::Identifier))
3077 return TokError("unexpected token in directive");
3079 // Convert to an APFloat.
3080 APFloat Value(Semantics);
3081 StringRef IDVal = getTok().getString();
3082 if (getLexer().is(AsmToken::Identifier)) {
3083 if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf"))
3084 Value = APFloat::getInf(Semantics);
3085 else if (!IDVal.compare_lower("nan"))
3086 Value = APFloat::getNaN(Semantics, false, ~0);
3087 else
3088 return TokError("invalid floating point literal");
3089 } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) ==
3090 APFloat::opInvalidOp)
3091 return TokError("invalid floating point literal");
3092 if (IsNeg)
3093 Value.changeSign();
3095 // Consume the numeric token.
3096 Lex();
3098 Res = Value.bitcastToAPInt();
3100 return false;
3103 /// parseDirectiveRealValue
3104 /// ::= (.single | .double) [ expression (, expression)* ]
3105 bool AsmParser::parseDirectiveRealValue(StringRef IDVal,
3106 const fltSemantics &Semantics) {
3107 auto parseOp = [&]() -> bool {
3108 APInt AsInt;
3109 if (checkForValidSection() || parseRealValue(Semantics, AsInt))
3110 return true;
3111 getStreamer().EmitIntValue(AsInt.getLimitedValue(),
3112 AsInt.getBitWidth() / 8);
3113 return false;
3116 if (parseMany(parseOp))
3117 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3118 return false;
3121 /// parseDirectiveZero
3122 /// ::= .zero expression
3123 bool AsmParser::parseDirectiveZero() {
3124 SMLoc NumBytesLoc = Lexer.getLoc();
3125 const MCExpr *NumBytes;
3126 if (checkForValidSection() || parseExpression(NumBytes))
3127 return true;
3129 int64_t Val = 0;
3130 if (getLexer().is(AsmToken::Comma)) {
3131 Lex();
3132 if (parseAbsoluteExpression(Val))
3133 return true;
3136 if (parseToken(AsmToken::EndOfStatement,
3137 "unexpected token in '.zero' directive"))
3138 return true;
3139 getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);
3141 return false;
3144 /// parseDirectiveFill
3145 /// ::= .fill expression [ , expression [ , expression ] ]
3146 bool AsmParser::parseDirectiveFill() {
3147 SMLoc NumValuesLoc = Lexer.getLoc();
3148 const MCExpr *NumValues;
3149 if (checkForValidSection() || parseExpression(NumValues))
3150 return true;
3152 int64_t FillSize = 1;
3153 int64_t FillExpr = 0;
3155 SMLoc SizeLoc, ExprLoc;
3157 if (parseOptionalToken(AsmToken::Comma)) {
3158 SizeLoc = getTok().getLoc();
3159 if (parseAbsoluteExpression(FillSize))
3160 return true;
3161 if (parseOptionalToken(AsmToken::Comma)) {
3162 ExprLoc = getTok().getLoc();
3163 if (parseAbsoluteExpression(FillExpr))
3164 return true;
3167 if (parseToken(AsmToken::EndOfStatement,
3168 "unexpected token in '.fill' directive"))
3169 return true;
3171 if (FillSize < 0) {
3172 Warning(SizeLoc, "'.fill' directive with negative size has no effect");
3173 return false;
3175 if (FillSize > 8) {
3176 Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
3177 FillSize = 8;
3180 if (!isUInt<32>(FillExpr) && FillSize > 4)
3181 Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
3183 getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);
3185 return false;
3188 /// parseDirectiveOrg
3189 /// ::= .org expression [ , expression ]
3190 bool AsmParser::parseDirectiveOrg() {
3191 const MCExpr *Offset;
3192 SMLoc OffsetLoc = Lexer.getLoc();
3193 if (checkForValidSection() || parseExpression(Offset))
3194 return true;
3196 // Parse optional fill expression.
3197 int64_t FillExpr = 0;
3198 if (parseOptionalToken(AsmToken::Comma))
3199 if (parseAbsoluteExpression(FillExpr))
3200 return addErrorSuffix(" in '.org' directive");
3201 if (parseToken(AsmToken::EndOfStatement))
3202 return addErrorSuffix(" in '.org' directive");
3204 getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
3205 return false;
3208 /// parseDirectiveAlign
3209 /// ::= {.align, ...} expression [ , expression [ , expression ]]
3210 bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
3211 SMLoc AlignmentLoc = getLexer().getLoc();
3212 int64_t Alignment;
3213 SMLoc MaxBytesLoc;
3214 bool HasFillExpr = false;
3215 int64_t FillExpr = 0;
3216 int64_t MaxBytesToFill = 0;
3218 auto parseAlign = [&]() -> bool {
3219 if (parseAbsoluteExpression(Alignment))
3220 return true;
3221 if (parseOptionalToken(AsmToken::Comma)) {
3222 // The fill expression can be omitted while specifying a maximum number of
3223 // alignment bytes, e.g:
3224 // .align 3,,4
3225 if (getTok().isNot(AsmToken::Comma)) {
3226 HasFillExpr = true;
3227 if (parseAbsoluteExpression(FillExpr))
3228 return true;
3230 if (parseOptionalToken(AsmToken::Comma))
3231 if (parseTokenLoc(MaxBytesLoc) ||
3232 parseAbsoluteExpression(MaxBytesToFill))
3233 return true;
3235 return parseToken(AsmToken::EndOfStatement);
3238 if (checkForValidSection())
3239 return addErrorSuffix(" in directive");
3240 // Ignore empty '.p2align' directives for GNU-as compatibility
3241 if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
3242 Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
3243 return parseToken(AsmToken::EndOfStatement);
3245 if (parseAlign())
3246 return addErrorSuffix(" in directive");
3248 // Always emit an alignment here even if we thrown an error.
3249 bool ReturnVal = false;
3251 // Compute alignment in bytes.
3252 if (IsPow2) {
3253 // FIXME: Diagnose overflow.
3254 if (Alignment >= 32) {
3255 ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
3256 Alignment = 31;
3259 Alignment = 1ULL << Alignment;
3260 } else {
3261 // Reject alignments that aren't either a power of two or zero,
3262 // for gas compatibility. Alignment of zero is silently rounded
3263 // up to one.
3264 if (Alignment == 0)
3265 Alignment = 1;
3266 if (!isPowerOf2_64(Alignment))
3267 ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
3270 // Diagnose non-sensical max bytes to align.
3271 if (MaxBytesLoc.isValid()) {
3272 if (MaxBytesToFill < 1) {
3273 ReturnVal |= Error(MaxBytesLoc,
3274 "alignment directive can never be satisfied in this "
3275 "many bytes, ignoring maximum bytes expression");
3276 MaxBytesToFill = 0;
3279 if (MaxBytesToFill >= Alignment) {
3280 Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
3281 "has no effect");
3282 MaxBytesToFill = 0;
3286 // Check whether we should use optimal code alignment for this .align
3287 // directive.
3288 const MCSection *Section = getStreamer().getCurrentSectionOnly();
3289 assert(Section && "must have section to emit alignment");
3290 bool UseCodeAlign = Section->UseCodeAlign();
3291 if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
3292 ValueSize == 1 && UseCodeAlign) {
3293 getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill);
3294 } else {
3295 // FIXME: Target specific behavior about how the "extra" bytes are filled.
3296 getStreamer().EmitValueToAlignment(Alignment, FillExpr, ValueSize,
3297 MaxBytesToFill);
3300 return ReturnVal;
3303 /// parseDirectiveFile
3304 /// ::= .file filename
3305 /// ::= .file number [directory] filename [md5 checksum] [source source-text]
3306 bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
3307 // FIXME: I'm not sure what this is.
3308 int64_t FileNumber = -1;
3309 if (getLexer().is(AsmToken::Integer)) {
3310 FileNumber = getTok().getIntVal();
3311 Lex();
3313 if (FileNumber < 0)
3314 return TokError("negative file number");
3317 std::string Path;
3319 // Usually the directory and filename together, otherwise just the directory.
3320 // Allow the strings to have escaped octal character sequence.
3321 if (check(getTok().isNot(AsmToken::String),
3322 "unexpected token in '.file' directive") ||
3323 parseEscapedString(Path))
3324 return true;
3326 StringRef Directory;
3327 StringRef Filename;
3328 std::string FilenameData;
3329 if (getLexer().is(AsmToken::String)) {
3330 if (check(FileNumber == -1,
3331 "explicit path specified, but no file number") ||
3332 parseEscapedString(FilenameData))
3333 return true;
3334 Filename = FilenameData;
3335 Directory = Path;
3336 } else {
3337 Filename = Path;
3340 uint64_t MD5Hi, MD5Lo;
3341 bool HasMD5 = false;
3343 Optional<StringRef> Source;
3344 bool HasSource = false;
3345 std::string SourceString;
3347 while (!parseOptionalToken(AsmToken::EndOfStatement)) {
3348 StringRef Keyword;
3349 if (check(getTok().isNot(AsmToken::Identifier),
3350 "unexpected token in '.file' directive") ||
3351 parseIdentifier(Keyword))
3352 return true;
3353 if (Keyword == "md5") {
3354 HasMD5 = true;
3355 if (check(FileNumber == -1,
3356 "MD5 checksum specified, but no file number") ||
3357 parseHexOcta(*this, MD5Hi, MD5Lo))
3358 return true;
3359 } else if (Keyword == "source") {
3360 HasSource = true;
3361 if (check(FileNumber == -1,
3362 "source specified, but no file number") ||
3363 check(getTok().isNot(AsmToken::String),
3364 "unexpected token in '.file' directive") ||
3365 parseEscapedString(SourceString))
3366 return true;
3367 } else {
3368 return TokError("unexpected token in '.file' directive");
3372 if (FileNumber == -1) {
3373 // Ignore the directive if there is no number and the target doesn't support
3374 // numberless .file directives. This allows some portability of assembler
3375 // between different object file formats.
3376 if (getContext().getAsmInfo()->hasSingleParameterDotFile())
3377 getStreamer().EmitFileDirective(Filename);
3378 } else {
3379 // In case there is a -g option as well as debug info from directive .file,
3380 // we turn off the -g option, directly use the existing debug info instead.
3381 // Also reset any implicit ".file 0" for the assembler source.
3382 if (Ctx.getGenDwarfForAssembly()) {
3383 Ctx.getMCDwarfLineTable(0).resetRootFile();
3384 Ctx.setGenDwarfForAssembly(false);
3387 MD5::MD5Result *CKMem = nullptr;
3388 if (HasMD5) {
3389 CKMem = (MD5::MD5Result *)Ctx.allocate(sizeof(MD5::MD5Result), 1);
3390 for (unsigned i = 0; i != 8; ++i) {
3391 CKMem->Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
3392 CKMem->Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
3395 if (HasSource) {
3396 char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
3397 memcpy(SourceBuf, SourceString.data(), SourceString.size());
3398 Source = StringRef(SourceBuf, SourceString.size());
3400 if (FileNumber == 0) {
3401 if (Ctx.getDwarfVersion() < 5)
3402 return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5");
3403 getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
3404 } else {
3405 Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
3406 FileNumber, Directory, Filename, CKMem, Source);
3407 if (!FileNumOrErr)
3408 return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
3409 FileNumber = FileNumOrErr.get();
3411 // Alert the user if there are some .file directives with MD5 and some not.
3412 // But only do that once.
3413 if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
3414 ReportedInconsistentMD5 = true;
3415 return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
3419 return false;
3422 /// parseDirectiveLine
3423 /// ::= .line [number]
3424 bool AsmParser::parseDirectiveLine() {
3425 int64_t LineNumber;
3426 if (getLexer().is(AsmToken::Integer)) {
3427 if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
3428 return true;
3429 (void)LineNumber;
3430 // FIXME: Do something with the .line.
3432 if (parseToken(AsmToken::EndOfStatement,
3433 "unexpected token in '.line' directive"))
3434 return true;
3436 return false;
3439 /// parseDirectiveLoc
3440 /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
3441 /// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
3442 /// The first number is a file number, must have been previously assigned with
3443 /// a .file directive, the second number is the line number and optionally the
3444 /// third number is a column position (zero if not specified). The remaining
3445 /// optional items are .loc sub-directives.
3446 bool AsmParser::parseDirectiveLoc() {
3447 int64_t FileNumber = 0, LineNumber = 0;
3448 SMLoc Loc = getTok().getLoc();
3449 if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
3450 check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
3451 "file number less than one in '.loc' directive") ||
3452 check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
3453 "unassigned file number in '.loc' directive"))
3454 return true;
3456 // optional
3457 if (getLexer().is(AsmToken::Integer)) {
3458 LineNumber = getTok().getIntVal();
3459 if (LineNumber < 0)
3460 return TokError("line number less than zero in '.loc' directive");
3461 Lex();
3464 int64_t ColumnPos = 0;
3465 if (getLexer().is(AsmToken::Integer)) {
3466 ColumnPos = getTok().getIntVal();
3467 if (ColumnPos < 0)
3468 return TokError("column position less than zero in '.loc' directive");
3469 Lex();
3472 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
3473 unsigned Isa = 0;
3474 int64_t Discriminator = 0;
3476 auto parseLocOp = [&]() -> bool {
3477 StringRef Name;
3478 SMLoc Loc = getTok().getLoc();
3479 if (parseIdentifier(Name))
3480 return TokError("unexpected token in '.loc' directive");
3482 if (Name == "basic_block")
3483 Flags |= DWARF2_FLAG_BASIC_BLOCK;
3484 else if (Name == "prologue_end")
3485 Flags |= DWARF2_FLAG_PROLOGUE_END;
3486 else if (Name == "epilogue_begin")
3487 Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
3488 else if (Name == "is_stmt") {
3489 Loc = getTok().getLoc();
3490 const MCExpr *Value;
3491 if (parseExpression(Value))
3492 return true;
3493 // The expression must be the constant 0 or 1.
3494 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3495 int Value = MCE->getValue();
3496 if (Value == 0)
3497 Flags &= ~DWARF2_FLAG_IS_STMT;
3498 else if (Value == 1)
3499 Flags |= DWARF2_FLAG_IS_STMT;
3500 else
3501 return Error(Loc, "is_stmt value not 0 or 1");
3502 } else {
3503 return Error(Loc, "is_stmt value not the constant value of 0 or 1");
3505 } else if (Name == "isa") {
3506 Loc = getTok().getLoc();
3507 const MCExpr *Value;
3508 if (parseExpression(Value))
3509 return true;
3510 // The expression must be a constant greater or equal to 0.
3511 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3512 int Value = MCE->getValue();
3513 if (Value < 0)
3514 return Error(Loc, "isa number less than zero");
3515 Isa = Value;
3516 } else {
3517 return Error(Loc, "isa number not a constant value");
3519 } else if (Name == "discriminator") {
3520 if (parseAbsoluteExpression(Discriminator))
3521 return true;
3522 } else {
3523 return Error(Loc, "unknown sub-directive in '.loc' directive");
3525 return false;
3528 if (parseMany(parseLocOp, false /*hasComma*/))
3529 return true;
3531 getStreamer().EmitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
3532 Isa, Discriminator, StringRef());
3534 return false;
3537 /// parseDirectiveStabs
3538 /// ::= .stabs string, number, number, number
3539 bool AsmParser::parseDirectiveStabs() {
3540 return TokError("unsupported directive '.stabs'");
3543 /// parseDirectiveCVFile
3544 /// ::= .cv_file number filename [checksum] [checksumkind]
3545 bool AsmParser::parseDirectiveCVFile() {
3546 SMLoc FileNumberLoc = getTok().getLoc();
3547 int64_t FileNumber;
3548 std::string Filename;
3549 std::string Checksum;
3550 int64_t ChecksumKind = 0;
3552 if (parseIntToken(FileNumber,
3553 "expected file number in '.cv_file' directive") ||
3554 check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
3555 check(getTok().isNot(AsmToken::String),
3556 "unexpected token in '.cv_file' directive") ||
3557 parseEscapedString(Filename))
3558 return true;
3559 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
3560 if (check(getTok().isNot(AsmToken::String),
3561 "unexpected token in '.cv_file' directive") ||
3562 parseEscapedString(Checksum) ||
3563 parseIntToken(ChecksumKind,
3564 "expected checksum kind in '.cv_file' directive") ||
3565 parseToken(AsmToken::EndOfStatement,
3566 "unexpected token in '.cv_file' directive"))
3567 return true;
3570 Checksum = fromHex(Checksum);
3571 void *CKMem = Ctx.allocate(Checksum.size(), 1);
3572 memcpy(CKMem, Checksum.data(), Checksum.size());
3573 ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
3574 Checksum.size());
3576 if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
3577 static_cast<uint8_t>(ChecksumKind)))
3578 return Error(FileNumberLoc, "file number already allocated");
3580 return false;
3583 bool AsmParser::parseCVFunctionId(int64_t &FunctionId,
3584 StringRef DirectiveName) {
3585 SMLoc Loc;
3586 return parseTokenLoc(Loc) ||
3587 parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
3588 "' directive") ||
3589 check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
3590 "expected function id within range [0, UINT_MAX)");
3593 bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
3594 SMLoc Loc;
3595 return parseTokenLoc(Loc) ||
3596 parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
3597 "' directive") ||
3598 check(FileNumber < 1, Loc, "file number less than one in '" +
3599 DirectiveName + "' directive") ||
3600 check(!getCVContext().isValidFileNumber(FileNumber), Loc,
3601 "unassigned file number in '" + DirectiveName + "' directive");
3604 /// parseDirectiveCVFuncId
3605 /// ::= .cv_func_id FunctionId
3607 /// Introduces a function ID that can be used with .cv_loc.
3608 bool AsmParser::parseDirectiveCVFuncId() {
3609 SMLoc FunctionIdLoc = getTok().getLoc();
3610 int64_t FunctionId;
3612 if (parseCVFunctionId(FunctionId, ".cv_func_id") ||
3613 parseToken(AsmToken::EndOfStatement,
3614 "unexpected token in '.cv_func_id' directive"))
3615 return true;
3617 if (!getStreamer().EmitCVFuncIdDirective(FunctionId))
3618 return Error(FunctionIdLoc, "function id already allocated");
3620 return false;
3623 /// parseDirectiveCVInlineSiteId
3624 /// ::= .cv_inline_site_id FunctionId
3625 /// "within" IAFunc
3626 /// "inlined_at" IAFile IALine [IACol]
3628 /// Introduces a function ID that can be used with .cv_loc. Includes "inlined
3629 /// at" source location information for use in the line table of the caller,
3630 /// whether the caller is a real function or another inlined call site.
3631 bool AsmParser::parseDirectiveCVInlineSiteId() {
3632 SMLoc FunctionIdLoc = getTok().getLoc();
3633 int64_t FunctionId;
3634 int64_t IAFunc;
3635 int64_t IAFile;
3636 int64_t IALine;
3637 int64_t IACol = 0;
3639 // FunctionId
3640 if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
3641 return true;
3643 // "within"
3644 if (check((getLexer().isNot(AsmToken::Identifier) ||
3645 getTok().getIdentifier() != "within"),
3646 "expected 'within' identifier in '.cv_inline_site_id' directive"))
3647 return true;
3648 Lex();
3650 // IAFunc
3651 if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
3652 return true;
3654 // "inlined_at"
3655 if (check((getLexer().isNot(AsmToken::Identifier) ||
3656 getTok().getIdentifier() != "inlined_at"),
3657 "expected 'inlined_at' identifier in '.cv_inline_site_id' "
3658 "directive") )
3659 return true;
3660 Lex();
3662 // IAFile IALine
3663 if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
3664 parseIntToken(IALine, "expected line number after 'inlined_at'"))
3665 return true;
3667 // [IACol]
3668 if (getLexer().is(AsmToken::Integer)) {
3669 IACol = getTok().getIntVal();
3670 Lex();
3673 if (parseToken(AsmToken::EndOfStatement,
3674 "unexpected token in '.cv_inline_site_id' directive"))
3675 return true;
3677 if (!getStreamer().EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
3678 IALine, IACol, FunctionIdLoc))
3679 return Error(FunctionIdLoc, "function id already allocated");
3681 return false;
3684 /// parseDirectiveCVLoc
3685 /// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
3686 /// [is_stmt VALUE]
3687 /// The first number is a file number, must have been previously assigned with
3688 /// a .file directive, the second number is the line number and optionally the
3689 /// third number is a column position (zero if not specified). The remaining
3690 /// optional items are .loc sub-directives.
3691 bool AsmParser::parseDirectiveCVLoc() {
3692 SMLoc DirectiveLoc = getTok().getLoc();
3693 int64_t FunctionId, FileNumber;
3694 if (parseCVFunctionId(FunctionId, ".cv_loc") ||
3695 parseCVFileId(FileNumber, ".cv_loc"))
3696 return true;
3698 int64_t LineNumber = 0;
3699 if (getLexer().is(AsmToken::Integer)) {
3700 LineNumber = getTok().getIntVal();
3701 if (LineNumber < 0)
3702 return TokError("line number less than zero in '.cv_loc' directive");
3703 Lex();
3706 int64_t ColumnPos = 0;
3707 if (getLexer().is(AsmToken::Integer)) {
3708 ColumnPos = getTok().getIntVal();
3709 if (ColumnPos < 0)
3710 return TokError("column position less than zero in '.cv_loc' directive");
3711 Lex();
3714 bool PrologueEnd = false;
3715 uint64_t IsStmt = 0;
3717 auto parseOp = [&]() -> bool {
3718 StringRef Name;
3719 SMLoc Loc = getTok().getLoc();
3720 if (parseIdentifier(Name))
3721 return TokError("unexpected token in '.cv_loc' directive");
3722 if (Name == "prologue_end")
3723 PrologueEnd = true;
3724 else if (Name == "is_stmt") {
3725 Loc = getTok().getLoc();
3726 const MCExpr *Value;
3727 if (parseExpression(Value))
3728 return true;
3729 // The expression must be the constant 0 or 1.
3730 IsStmt = ~0ULL;
3731 if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
3732 IsStmt = MCE->getValue();
3734 if (IsStmt > 1)
3735 return Error(Loc, "is_stmt value not 0 or 1");
3736 } else {
3737 return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
3739 return false;
3742 if (parseMany(parseOp, false /*hasComma*/))
3743 return true;
3745 getStreamer().EmitCVLocDirective(FunctionId, FileNumber, LineNumber,
3746 ColumnPos, PrologueEnd, IsStmt, StringRef(),
3747 DirectiveLoc);
3748 return false;
3751 /// parseDirectiveCVLinetable
3752 /// ::= .cv_linetable FunctionId, FnStart, FnEnd
3753 bool AsmParser::parseDirectiveCVLinetable() {
3754 int64_t FunctionId;
3755 StringRef FnStartName, FnEndName;
3756 SMLoc Loc = getTok().getLoc();
3757 if (parseCVFunctionId(FunctionId, ".cv_linetable") ||
3758 parseToken(AsmToken::Comma,
3759 "unexpected token in '.cv_linetable' directive") ||
3760 parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
3761 "expected identifier in directive") ||
3762 parseToken(AsmToken::Comma,
3763 "unexpected token in '.cv_linetable' directive") ||
3764 parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
3765 "expected identifier in directive"))
3766 return true;
3768 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
3769 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
3771 getStreamer().EmitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
3772 return false;
3775 /// parseDirectiveCVInlineLinetable
3776 /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
3777 bool AsmParser::parseDirectiveCVInlineLinetable() {
3778 int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
3779 StringRef FnStartName, FnEndName;
3780 SMLoc Loc = getTok().getLoc();
3781 if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
3782 parseTokenLoc(Loc) ||
3783 parseIntToken(
3784 SourceFileId,
3785 "expected SourceField in '.cv_inline_linetable' directive") ||
3786 check(SourceFileId <= 0, Loc,
3787 "File id less than zero in '.cv_inline_linetable' directive") ||
3788 parseTokenLoc(Loc) ||
3789 parseIntToken(
3790 SourceLineNum,
3791 "expected SourceLineNum in '.cv_inline_linetable' directive") ||
3792 check(SourceLineNum < 0, Loc,
3793 "Line number less than zero in '.cv_inline_linetable' directive") ||
3794 parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
3795 "expected identifier in directive") ||
3796 parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
3797 "expected identifier in directive"))
3798 return true;
3800 if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
3801 return true;
3803 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
3804 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
3805 getStreamer().EmitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
3806 SourceLineNum, FnStartSym,
3807 FnEndSym);
3808 return false;
3811 /// parseDirectiveCVDefRange
3812 /// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
3813 bool AsmParser::parseDirectiveCVDefRange() {
3814 SMLoc Loc;
3815 std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
3816 while (getLexer().is(AsmToken::Identifier)) {
3817 Loc = getLexer().getLoc();
3818 StringRef GapStartName;
3819 if (parseIdentifier(GapStartName))
3820 return Error(Loc, "expected identifier in directive");
3821 MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
3823 Loc = getLexer().getLoc();
3824 StringRef GapEndName;
3825 if (parseIdentifier(GapEndName))
3826 return Error(Loc, "expected identifier in directive");
3827 MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
3829 Ranges.push_back({GapStartSym, GapEndSym});
3832 std::string FixedSizePortion;
3833 if (parseToken(AsmToken::Comma, "unexpected token in directive") ||
3834 parseEscapedString(FixedSizePortion))
3835 return true;
3837 getStreamer().EmitCVDefRangeDirective(Ranges, FixedSizePortion);
3838 return false;
3841 /// parseDirectiveCVString
3842 /// ::= .cv_stringtable "string"
3843 bool AsmParser::parseDirectiveCVString() {
3844 std::string Data;
3845 if (checkForValidSection() || parseEscapedString(Data))
3846 return addErrorSuffix(" in '.cv_string' directive");
3848 // Put the string in the table and emit the offset.
3849 std::pair<StringRef, unsigned> Insertion =
3850 getCVContext().addToStringTable(Data);
3851 getStreamer().EmitIntValue(Insertion.second, 4);
3852 return false;
3855 /// parseDirectiveCVStringTable
3856 /// ::= .cv_stringtable
3857 bool AsmParser::parseDirectiveCVStringTable() {
3858 getStreamer().EmitCVStringTableDirective();
3859 return false;
3862 /// parseDirectiveCVFileChecksums
3863 /// ::= .cv_filechecksums
3864 bool AsmParser::parseDirectiveCVFileChecksums() {
3865 getStreamer().EmitCVFileChecksumsDirective();
3866 return false;
3869 /// parseDirectiveCVFileChecksumOffset
3870 /// ::= .cv_filechecksumoffset fileno
3871 bool AsmParser::parseDirectiveCVFileChecksumOffset() {
3872 int64_t FileNo;
3873 if (parseIntToken(FileNo, "expected identifier in directive"))
3874 return true;
3875 if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
3876 return true;
3877 getStreamer().EmitCVFileChecksumOffsetDirective(FileNo);
3878 return false;
3881 /// parseDirectiveCVFPOData
3882 /// ::= .cv_fpo_data procsym
3883 bool AsmParser::parseDirectiveCVFPOData() {
3884 SMLoc DirLoc = getLexer().getLoc();
3885 StringRef ProcName;
3886 if (parseIdentifier(ProcName))
3887 return TokError("expected symbol name");
3888 if (parseEOL("unexpected tokens"))
3889 return addErrorSuffix(" in '.cv_fpo_data' directive");
3890 MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
3891 getStreamer().EmitCVFPOData(ProcSym, DirLoc);
3892 return false;
3895 /// parseDirectiveCFISections
3896 /// ::= .cfi_sections section [, section]
3897 bool AsmParser::parseDirectiveCFISections() {
3898 StringRef Name;
3899 bool EH = false;
3900 bool Debug = false;
3902 if (parseIdentifier(Name))
3903 return TokError("Expected an identifier");
3905 if (Name == ".eh_frame")
3906 EH = true;
3907 else if (Name == ".debug_frame")
3908 Debug = true;
3910 if (getLexer().is(AsmToken::Comma)) {
3911 Lex();
3913 if (parseIdentifier(Name))
3914 return TokError("Expected an identifier");
3916 if (Name == ".eh_frame")
3917 EH = true;
3918 else if (Name == ".debug_frame")
3919 Debug = true;
3922 getStreamer().EmitCFISections(EH, Debug);
3923 return false;
3926 /// parseDirectiveCFIStartProc
3927 /// ::= .cfi_startproc [simple]
3928 bool AsmParser::parseDirectiveCFIStartProc() {
3929 StringRef Simple;
3930 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
3931 if (check(parseIdentifier(Simple) || Simple != "simple",
3932 "unexpected token") ||
3933 parseToken(AsmToken::EndOfStatement))
3934 return addErrorSuffix(" in '.cfi_startproc' directive");
3937 // TODO(kristina): Deal with a corner case of incorrect diagnostic context
3938 // being produced if this directive is emitted as part of preprocessor macro
3939 // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
3940 // Tools like llvm-mc on the other hand are not affected by it, and report
3941 // correct context information.
3942 getStreamer().EmitCFIStartProc(!Simple.empty(), Lexer.getLoc());
3943 return false;
3946 /// parseDirectiveCFIEndProc
3947 /// ::= .cfi_endproc
3948 bool AsmParser::parseDirectiveCFIEndProc() {
3949 getStreamer().EmitCFIEndProc();
3950 return false;
3953 /// parse register name or number.
3954 bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
3955 SMLoc DirectiveLoc) {
3956 unsigned RegNo;
3958 if (getLexer().isNot(AsmToken::Integer)) {
3959 if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc))
3960 return true;
3961 Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
3962 } else
3963 return parseAbsoluteExpression(Register);
3965 return false;
3968 /// parseDirectiveCFIDefCfa
3969 /// ::= .cfi_def_cfa register, offset
3970 bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
3971 int64_t Register = 0, Offset = 0;
3972 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
3973 parseToken(AsmToken::Comma, "unexpected token in directive") ||
3974 parseAbsoluteExpression(Offset))
3975 return true;
3977 getStreamer().EmitCFIDefCfa(Register, Offset);
3978 return false;
3981 /// parseDirectiveCFIDefCfaOffset
3982 /// ::= .cfi_def_cfa_offset offset
3983 bool AsmParser::parseDirectiveCFIDefCfaOffset() {
3984 int64_t Offset = 0;
3985 if (parseAbsoluteExpression(Offset))
3986 return true;
3988 getStreamer().EmitCFIDefCfaOffset(Offset);
3989 return false;
3992 /// parseDirectiveCFIRegister
3993 /// ::= .cfi_register register, register
3994 bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
3995 int64_t Register1 = 0, Register2 = 0;
3996 if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) ||
3997 parseToken(AsmToken::Comma, "unexpected token in directive") ||
3998 parseRegisterOrRegisterNumber(Register2, DirectiveLoc))
3999 return true;
4001 getStreamer().EmitCFIRegister(Register1, Register2);
4002 return false;
4005 /// parseDirectiveCFIWindowSave
4006 /// ::= .cfi_window_save
4007 bool AsmParser::parseDirectiveCFIWindowSave() {
4008 getStreamer().EmitCFIWindowSave();
4009 return false;
4012 /// parseDirectiveCFIAdjustCfaOffset
4013 /// ::= .cfi_adjust_cfa_offset adjustment
4014 bool AsmParser::parseDirectiveCFIAdjustCfaOffset() {
4015 int64_t Adjustment = 0;
4016 if (parseAbsoluteExpression(Adjustment))
4017 return true;
4019 getStreamer().EmitCFIAdjustCfaOffset(Adjustment);
4020 return false;
4023 /// parseDirectiveCFIDefCfaRegister
4024 /// ::= .cfi_def_cfa_register register
4025 bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
4026 int64_t Register = 0;
4027 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
4028 return true;
4030 getStreamer().EmitCFIDefCfaRegister(Register);
4031 return false;
4034 /// parseDirectiveCFIOffset
4035 /// ::= .cfi_offset register, offset
4036 bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
4037 int64_t Register = 0;
4038 int64_t Offset = 0;
4040 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
4041 parseToken(AsmToken::Comma, "unexpected token in directive") ||
4042 parseAbsoluteExpression(Offset))
4043 return true;
4045 getStreamer().EmitCFIOffset(Register, Offset);
4046 return false;
4049 /// parseDirectiveCFIRelOffset
4050 /// ::= .cfi_rel_offset register, offset
4051 bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
4052 int64_t Register = 0, Offset = 0;
4054 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
4055 parseToken(AsmToken::Comma, "unexpected token in directive") ||
4056 parseAbsoluteExpression(Offset))
4057 return true;
4059 getStreamer().EmitCFIRelOffset(Register, Offset);
4060 return false;
4063 static bool isValidEncoding(int64_t Encoding) {
4064 if (Encoding & ~0xff)
4065 return false;
4067 if (Encoding == dwarf::DW_EH_PE_omit)
4068 return true;
4070 const unsigned Format = Encoding & 0xf;
4071 if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
4072 Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
4073 Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
4074 Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
4075 return false;
4077 const unsigned Application = Encoding & 0x70;
4078 if (Application != dwarf::DW_EH_PE_absptr &&
4079 Application != dwarf::DW_EH_PE_pcrel)
4080 return false;
4082 return true;
4085 /// parseDirectiveCFIPersonalityOrLsda
4086 /// IsPersonality true for cfi_personality, false for cfi_lsda
4087 /// ::= .cfi_personality encoding, [symbol_name]
4088 /// ::= .cfi_lsda encoding, [symbol_name]
4089 bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
4090 int64_t Encoding = 0;
4091 if (parseAbsoluteExpression(Encoding))
4092 return true;
4093 if (Encoding == dwarf::DW_EH_PE_omit)
4094 return false;
4096 StringRef Name;
4097 if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
4098 parseToken(AsmToken::Comma, "unexpected token in directive") ||
4099 check(parseIdentifier(Name), "expected identifier in directive"))
4100 return true;
4102 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4104 if (IsPersonality)
4105 getStreamer().EmitCFIPersonality(Sym, Encoding);
4106 else
4107 getStreamer().EmitCFILsda(Sym, Encoding);
4108 return false;
4111 /// parseDirectiveCFIRememberState
4112 /// ::= .cfi_remember_state
4113 bool AsmParser::parseDirectiveCFIRememberState() {
4114 getStreamer().EmitCFIRememberState();
4115 return false;
4118 /// parseDirectiveCFIRestoreState
4119 /// ::= .cfi_remember_state
4120 bool AsmParser::parseDirectiveCFIRestoreState() {
4121 getStreamer().EmitCFIRestoreState();
4122 return false;
4125 /// parseDirectiveCFISameValue
4126 /// ::= .cfi_same_value register
4127 bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
4128 int64_t Register = 0;
4130 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
4131 return true;
4133 getStreamer().EmitCFISameValue(Register);
4134 return false;
4137 /// parseDirectiveCFIRestore
4138 /// ::= .cfi_restore register
4139 bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
4140 int64_t Register = 0;
4141 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
4142 return true;
4144 getStreamer().EmitCFIRestore(Register);
4145 return false;
4148 /// parseDirectiveCFIEscape
4149 /// ::= .cfi_escape expression[,...]
4150 bool AsmParser::parseDirectiveCFIEscape() {
4151 std::string Values;
4152 int64_t CurrValue;
4153 if (parseAbsoluteExpression(CurrValue))
4154 return true;
4156 Values.push_back((uint8_t)CurrValue);
4158 while (getLexer().is(AsmToken::Comma)) {
4159 Lex();
4161 if (parseAbsoluteExpression(CurrValue))
4162 return true;
4164 Values.push_back((uint8_t)CurrValue);
4167 getStreamer().EmitCFIEscape(Values);
4168 return false;
4171 /// parseDirectiveCFIReturnColumn
4172 /// ::= .cfi_return_column register
4173 bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
4174 int64_t Register = 0;
4175 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
4176 return true;
4177 getStreamer().EmitCFIReturnColumn(Register);
4178 return false;
4181 /// parseDirectiveCFISignalFrame
4182 /// ::= .cfi_signal_frame
4183 bool AsmParser::parseDirectiveCFISignalFrame() {
4184 if (parseToken(AsmToken::EndOfStatement,
4185 "unexpected token in '.cfi_signal_frame'"))
4186 return true;
4188 getStreamer().EmitCFISignalFrame();
4189 return false;
4192 /// parseDirectiveCFIUndefined
4193 /// ::= .cfi_undefined register
4194 bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
4195 int64_t Register = 0;
4197 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
4198 return true;
4200 getStreamer().EmitCFIUndefined(Register);
4201 return false;
4204 /// parseDirectiveAltmacro
4205 /// ::= .altmacro
4206 /// ::= .noaltmacro
4207 bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
4208 if (getLexer().isNot(AsmToken::EndOfStatement))
4209 return TokError("unexpected token in '" + Directive + "' directive");
4210 AltMacroMode = (Directive == ".altmacro");
4211 return false;
4214 /// parseDirectiveMacrosOnOff
4215 /// ::= .macros_on
4216 /// ::= .macros_off
4217 bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
4218 if (parseToken(AsmToken::EndOfStatement,
4219 "unexpected token in '" + Directive + "' directive"))
4220 return true;
4222 setMacrosEnabled(Directive == ".macros_on");
4223 return false;
4226 /// parseDirectiveMacro
4227 /// ::= .macro name[,] [parameters]
4228 bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
4229 StringRef Name;
4230 if (parseIdentifier(Name))
4231 return TokError("expected identifier in '.macro' directive");
4233 if (getLexer().is(AsmToken::Comma))
4234 Lex();
4236 MCAsmMacroParameters Parameters;
4237 while (getLexer().isNot(AsmToken::EndOfStatement)) {
4239 if (!Parameters.empty() && Parameters.back().Vararg)
4240 return Error(Lexer.getLoc(),
4241 "Vararg parameter '" + Parameters.back().Name +
4242 "' should be last one in the list of parameters.");
4244 MCAsmMacroParameter Parameter;
4245 if (parseIdentifier(Parameter.Name))
4246 return TokError("expected identifier in '.macro' directive");
4248 // Emit an error if two (or more) named parameters share the same name
4249 for (const MCAsmMacroParameter& CurrParam : Parameters)
4250 if (CurrParam.Name.equals(Parameter.Name))
4251 return TokError("macro '" + Name + "' has multiple parameters"
4252 " named '" + Parameter.Name + "'");
4254 if (Lexer.is(AsmToken::Colon)) {
4255 Lex(); // consume ':'
4257 SMLoc QualLoc;
4258 StringRef Qualifier;
4260 QualLoc = Lexer.getLoc();
4261 if (parseIdentifier(Qualifier))
4262 return Error(QualLoc, "missing parameter qualifier for "
4263 "'" + Parameter.Name + "' in macro '" + Name + "'");
4265 if (Qualifier == "req")
4266 Parameter.Required = true;
4267 else if (Qualifier == "vararg")
4268 Parameter.Vararg = true;
4269 else
4270 return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
4271 "for '" + Parameter.Name + "' in macro '" + Name + "'");
4274 if (getLexer().is(AsmToken::Equal)) {
4275 Lex();
4277 SMLoc ParamLoc;
4279 ParamLoc = Lexer.getLoc();
4280 if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
4281 return true;
4283 if (Parameter.Required)
4284 Warning(ParamLoc, "pointless default value for required parameter "
4285 "'" + Parameter.Name + "' in macro '" + Name + "'");
4288 Parameters.push_back(std::move(Parameter));
4290 if (getLexer().is(AsmToken::Comma))
4291 Lex();
4294 // Eat just the end of statement.
4295 Lexer.Lex();
4297 // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors
4298 AsmToken EndToken, StartToken = getTok();
4299 unsigned MacroDepth = 0;
4300 // Lex the macro definition.
4301 while (true) {
4302 // Ignore Lexing errors in macros.
4303 while (Lexer.is(AsmToken::Error)) {
4304 Lexer.Lex();
4307 // Check whether we have reached the end of the file.
4308 if (getLexer().is(AsmToken::Eof))
4309 return Error(DirectiveLoc, "no matching '.endmacro' in definition");
4311 // Otherwise, check whether we have reach the .endmacro.
4312 if (getLexer().is(AsmToken::Identifier)) {
4313 if (getTok().getIdentifier() == ".endm" ||
4314 getTok().getIdentifier() == ".endmacro") {
4315 if (MacroDepth == 0) { // Outermost macro.
4316 EndToken = getTok();
4317 Lexer.Lex();
4318 if (getLexer().isNot(AsmToken::EndOfStatement))
4319 return TokError("unexpected token in '" + EndToken.getIdentifier() +
4320 "' directive");
4321 break;
4322 } else {
4323 // Otherwise we just found the end of an inner macro.
4324 --MacroDepth;
4326 } else if (getTok().getIdentifier() == ".macro") {
4327 // We allow nested macros. Those aren't instantiated until the outermost
4328 // macro is expanded so just ignore them for now.
4329 ++MacroDepth;
4333 // Otherwise, scan til the end of the statement.
4334 eatToEndOfStatement();
4337 if (getContext().lookupMacro(Name)) {
4338 return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
4341 const char *BodyStart = StartToken.getLoc().getPointer();
4342 const char *BodyEnd = EndToken.getLoc().getPointer();
4343 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4344 checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
4345 MCAsmMacro Macro(Name, Body, std::move(Parameters));
4346 DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
4347 Macro.dump());
4348 getContext().defineMacro(Name, std::move(Macro));
4349 return false;
4352 /// checkForBadMacro
4354 /// With the support added for named parameters there may be code out there that
4355 /// is transitioning from positional parameters. In versions of gas that did
4356 /// not support named parameters they would be ignored on the macro definition.
4357 /// But to support both styles of parameters this is not possible so if a macro
4358 /// definition has named parameters but does not use them and has what appears
4359 /// to be positional parameters, strings like $1, $2, ... and $n, then issue a
4360 /// warning that the positional parameter found in body which have no effect.
4361 /// Hoping the developer will either remove the named parameters from the macro
4362 /// definition so the positional parameters get used if that was what was
4363 /// intended or change the macro to use the named parameters. It is possible
4364 /// this warning will trigger when the none of the named parameters are used
4365 /// and the strings like $1 are infact to simply to be passed trough unchanged.
4366 void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
4367 StringRef Body,
4368 ArrayRef<MCAsmMacroParameter> Parameters) {
4369 // If this macro is not defined with named parameters the warning we are
4370 // checking for here doesn't apply.
4371 unsigned NParameters = Parameters.size();
4372 if (NParameters == 0)
4373 return;
4375 bool NamedParametersFound = false;
4376 bool PositionalParametersFound = false;
4378 // Look at the body of the macro for use of both the named parameters and what
4379 // are likely to be positional parameters. This is what expandMacro() is
4380 // doing when it finds the parameters in the body.
4381 while (!Body.empty()) {
4382 // Scan for the next possible parameter.
4383 std::size_t End = Body.size(), Pos = 0;
4384 for (; Pos != End; ++Pos) {
4385 // Check for a substitution or escape.
4386 // This macro is defined with parameters, look for \foo, \bar, etc.
4387 if (Body[Pos] == '\\' && Pos + 1 != End)
4388 break;
4390 // This macro should have parameters, but look for $0, $1, ..., $n too.
4391 if (Body[Pos] != '$' || Pos + 1 == End)
4392 continue;
4393 char Next = Body[Pos + 1];
4394 if (Next == '$' || Next == 'n' ||
4395 isdigit(static_cast<unsigned char>(Next)))
4396 break;
4399 // Check if we reached the end.
4400 if (Pos == End)
4401 break;
4403 if (Body[Pos] == '$') {
4404 switch (Body[Pos + 1]) {
4405 // $$ => $
4406 case '$':
4407 break;
4409 // $n => number of arguments
4410 case 'n':
4411 PositionalParametersFound = true;
4412 break;
4414 // $[0-9] => argument
4415 default: {
4416 PositionalParametersFound = true;
4417 break;
4420 Pos += 2;
4421 } else {
4422 unsigned I = Pos + 1;
4423 while (isIdentifierChar(Body[I]) && I + 1 != End)
4424 ++I;
4426 const char *Begin = Body.data() + Pos + 1;
4427 StringRef Argument(Begin, I - (Pos + 1));
4428 unsigned Index = 0;
4429 for (; Index < NParameters; ++Index)
4430 if (Parameters[Index].Name == Argument)
4431 break;
4433 if (Index == NParameters) {
4434 if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
4435 Pos += 3;
4436 else {
4437 Pos = I;
4439 } else {
4440 NamedParametersFound = true;
4441 Pos += 1 + Argument.size();
4444 // Update the scan point.
4445 Body = Body.substr(Pos);
4448 if (!NamedParametersFound && PositionalParametersFound)
4449 Warning(DirectiveLoc, "macro defined with named parameters which are not "
4450 "used in macro body, possible positional parameter "
4451 "found in body which will have no effect");
4454 /// parseDirectiveExitMacro
4455 /// ::= .exitm
4456 bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
4457 if (parseToken(AsmToken::EndOfStatement,
4458 "unexpected token in '" + Directive + "' directive"))
4459 return true;
4461 if (!isInsideMacroInstantiation())
4462 return TokError("unexpected '" + Directive + "' in file, "
4463 "no current macro definition");
4465 // Exit all conditionals that are active in the current macro.
4466 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4467 TheCondState = TheCondStack.back();
4468 TheCondStack.pop_back();
4471 handleMacroExit();
4472 return false;
4475 /// parseDirectiveEndMacro
4476 /// ::= .endm
4477 /// ::= .endmacro
4478 bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
4479 if (getLexer().isNot(AsmToken::EndOfStatement))
4480 return TokError("unexpected token in '" + Directive + "' directive");
4482 // If we are inside a macro instantiation, terminate the current
4483 // instantiation.
4484 if (isInsideMacroInstantiation()) {
4485 handleMacroExit();
4486 return false;
4489 // Otherwise, this .endmacro is a stray entry in the file; well formed
4490 // .endmacro directives are handled during the macro definition parsing.
4491 return TokError("unexpected '" + Directive + "' in file, "
4492 "no current macro definition");
4495 /// parseDirectivePurgeMacro
4496 /// ::= .purgem
4497 bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4498 StringRef Name;
4499 SMLoc Loc;
4500 if (parseTokenLoc(Loc) ||
4501 check(parseIdentifier(Name), Loc,
4502 "expected identifier in '.purgem' directive") ||
4503 parseToken(AsmToken::EndOfStatement,
4504 "unexpected token in '.purgem' directive"))
4505 return true;
4507 if (!getContext().lookupMacro(Name))
4508 return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
4510 getContext().undefineMacro(Name);
4511 DEBUG_WITH_TYPE("asm-macros", dbgs()
4512 << "Un-defining macro: " << Name << "\n");
4513 return false;
4516 /// parseDirectiveBundleAlignMode
4517 /// ::= {.bundle_align_mode} expression
4518 bool AsmParser::parseDirectiveBundleAlignMode() {
4519 // Expect a single argument: an expression that evaluates to a constant
4520 // in the inclusive range 0-30.
4521 SMLoc ExprLoc = getLexer().getLoc();
4522 int64_t AlignSizePow2;
4523 if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||
4524 parseToken(AsmToken::EndOfStatement, "unexpected token after expression "
4525 "in '.bundle_align_mode' "
4526 "directive") ||
4527 check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc,
4528 "invalid bundle alignment size (expected between 0 and 30)"))
4529 return true;
4531 // Because of AlignSizePow2's verified range we can safely truncate it to
4532 // unsigned.
4533 getStreamer().EmitBundleAlignMode(static_cast<unsigned>(AlignSizePow2));
4534 return false;
4537 /// parseDirectiveBundleLock
4538 /// ::= {.bundle_lock} [align_to_end]
4539 bool AsmParser::parseDirectiveBundleLock() {
4540 if (checkForValidSection())
4541 return true;
4542 bool AlignToEnd = false;
4544 StringRef Option;
4545 SMLoc Loc = getTok().getLoc();
4546 const char *kInvalidOptionError =
4547 "invalid option for '.bundle_lock' directive";
4549 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4550 if (check(parseIdentifier(Option), Loc, kInvalidOptionError) ||
4551 check(Option != "align_to_end", Loc, kInvalidOptionError) ||
4552 parseToken(AsmToken::EndOfStatement,
4553 "unexpected token after '.bundle_lock' directive option"))
4554 return true;
4555 AlignToEnd = true;
4558 getStreamer().EmitBundleLock(AlignToEnd);
4559 return false;
4562 /// parseDirectiveBundleLock
4563 /// ::= {.bundle_lock}
4564 bool AsmParser::parseDirectiveBundleUnlock() {
4565 if (checkForValidSection() ||
4566 parseToken(AsmToken::EndOfStatement,
4567 "unexpected token in '.bundle_unlock' directive"))
4568 return true;
4570 getStreamer().EmitBundleUnlock();
4571 return false;
4574 /// parseDirectiveSpace
4575 /// ::= (.skip | .space) expression [ , expression ]
4576 bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
4577 SMLoc NumBytesLoc = Lexer.getLoc();
4578 const MCExpr *NumBytes;
4579 if (checkForValidSection() || parseExpression(NumBytes))
4580 return true;
4582 int64_t FillExpr = 0;
4583 if (parseOptionalToken(AsmToken::Comma))
4584 if (parseAbsoluteExpression(FillExpr))
4585 return addErrorSuffix("in '" + Twine(IDVal) + "' directive");
4586 if (parseToken(AsmToken::EndOfStatement))
4587 return addErrorSuffix("in '" + Twine(IDVal) + "' directive");
4589 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
4590 getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
4592 return false;
4595 /// parseDirectiveDCB
4596 /// ::= .dcb.{b, l, w} expression, expression
4597 bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
4598 SMLoc NumValuesLoc = Lexer.getLoc();
4599 int64_t NumValues;
4600 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4601 return true;
4603 if (NumValues < 0) {
4604 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4605 return false;
4608 if (parseToken(AsmToken::Comma,
4609 "unexpected token in '" + Twine(IDVal) + "' directive"))
4610 return true;
4612 const MCExpr *Value;
4613 SMLoc ExprLoc = getLexer().getLoc();
4614 if (parseExpression(Value))
4615 return true;
4617 // Special case constant expressions to match code generator.
4618 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
4619 assert(Size <= 8 && "Invalid size");
4620 uint64_t IntValue = MCE->getValue();
4621 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
4622 return Error(ExprLoc, "literal value out of range for directive");
4623 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4624 getStreamer().EmitIntValue(IntValue, Size);
4625 } else {
4626 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4627 getStreamer().EmitValue(Value, Size, ExprLoc);
4630 if (parseToken(AsmToken::EndOfStatement,
4631 "unexpected token in '" + Twine(IDVal) + "' directive"))
4632 return true;
4634 return false;
4637 /// parseDirectiveRealDCB
4638 /// ::= .dcb.{d, s} expression, expression
4639 bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {
4640 SMLoc NumValuesLoc = Lexer.getLoc();
4641 int64_t NumValues;
4642 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4643 return true;
4645 if (NumValues < 0) {
4646 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4647 return false;
4650 if (parseToken(AsmToken::Comma,
4651 "unexpected token in '" + Twine(IDVal) + "' directive"))
4652 return true;
4654 APInt AsInt;
4655 if (parseRealValue(Semantics, AsInt))
4656 return true;
4658 if (parseToken(AsmToken::EndOfStatement,
4659 "unexpected token in '" + Twine(IDVal) + "' directive"))
4660 return true;
4662 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4663 getStreamer().EmitIntValue(AsInt.getLimitedValue(),
4664 AsInt.getBitWidth() / 8);
4666 return false;
4669 /// parseDirectiveDS
4670 /// ::= .ds.{b, d, l, p, s, w, x} expression
4671 bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {
4672 SMLoc NumValuesLoc = Lexer.getLoc();
4673 int64_t NumValues;
4674 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4675 return true;
4677 if (NumValues < 0) {
4678 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4679 return false;
4682 if (parseToken(AsmToken::EndOfStatement,
4683 "unexpected token in '" + Twine(IDVal) + "' directive"))
4684 return true;
4686 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4687 getStreamer().emitFill(Size, 0);
4689 return false;
4692 /// parseDirectiveLEB128
4693 /// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
4694 bool AsmParser::parseDirectiveLEB128(bool Signed) {
4695 if (checkForValidSection())
4696 return true;
4698 auto parseOp = [&]() -> bool {
4699 const MCExpr *Value;
4700 if (parseExpression(Value))
4701 return true;
4702 if (Signed)
4703 getStreamer().EmitSLEB128Value(Value);
4704 else
4705 getStreamer().EmitULEB128Value(Value);
4706 return false;
4709 if (parseMany(parseOp))
4710 return addErrorSuffix(" in directive");
4712 return false;
4715 /// parseDirectiveSymbolAttribute
4716 /// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
4717 bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
4718 auto parseOp = [&]() -> bool {
4719 StringRef Name;
4720 SMLoc Loc = getTok().getLoc();
4721 if (parseIdentifier(Name))
4722 return Error(Loc, "expected identifier");
4723 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4725 // Assembler local symbols don't make any sense here. Complain loudly.
4726 if (Sym->isTemporary())
4727 return Error(Loc, "non-local symbol required");
4729 if (!getStreamer().EmitSymbolAttribute(Sym, Attr))
4730 return Error(Loc, "unable to emit symbol attribute");
4731 return false;
4734 if (parseMany(parseOp))
4735 return addErrorSuffix(" in directive");
4736 return false;
4739 /// parseDirectiveComm
4740 /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
4741 bool AsmParser::parseDirectiveComm(bool IsLocal) {
4742 if (checkForValidSection())
4743 return true;
4745 SMLoc IDLoc = getLexer().getLoc();
4746 StringRef Name;
4747 if (parseIdentifier(Name))
4748 return TokError("expected identifier in directive");
4750 // Handle the identifier as the key symbol.
4751 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4753 if (getLexer().isNot(AsmToken::Comma))
4754 return TokError("unexpected token in directive");
4755 Lex();
4757 int64_t Size;
4758 SMLoc SizeLoc = getLexer().getLoc();
4759 if (parseAbsoluteExpression(Size))
4760 return true;
4762 int64_t Pow2Alignment = 0;
4763 SMLoc Pow2AlignmentLoc;
4764 if (getLexer().is(AsmToken::Comma)) {
4765 Lex();
4766 Pow2AlignmentLoc = getLexer().getLoc();
4767 if (parseAbsoluteExpression(Pow2Alignment))
4768 return true;
4770 LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
4771 if (IsLocal && LCOMM == LCOMM::NoAlignment)
4772 return Error(Pow2AlignmentLoc, "alignment not supported on this target");
4774 // If this target takes alignments in bytes (not log) validate and convert.
4775 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4776 (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
4777 if (!isPowerOf2_64(Pow2Alignment))
4778 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
4779 Pow2Alignment = Log2_64(Pow2Alignment);
4783 if (parseToken(AsmToken::EndOfStatement,
4784 "unexpected token in '.comm' or '.lcomm' directive"))
4785 return true;
4787 // NOTE: a size of zero for a .comm should create a undefined symbol
4788 // but a size of .lcomm creates a bss symbol of size zero.
4789 if (Size < 0)
4790 return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
4791 "be less than zero");
4793 // NOTE: The alignment in the directive is a power of 2 value, the assembler
4794 // may internally end up wanting an alignment in bytes.
4795 // FIXME: Diagnose overflow.
4796 if (Pow2Alignment < 0)
4797 return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
4798 "alignment, can't be less than zero");
4800 Sym->redefineIfPossible();
4801 if (!Sym->isUndefined())
4802 return Error(IDLoc, "invalid symbol redefinition");
4804 // Create the Symbol as a common or local common with Size and Pow2Alignment
4805 if (IsLocal) {
4806 getStreamer().EmitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
4807 return false;
4810 getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
4811 return false;
4814 /// parseDirectiveAbort
4815 /// ::= .abort [... message ...]
4816 bool AsmParser::parseDirectiveAbort() {
4817 // FIXME: Use loc from directive.
4818 SMLoc Loc = getLexer().getLoc();
4820 StringRef Str = parseStringToEndOfStatement();
4821 if (parseToken(AsmToken::EndOfStatement,
4822 "unexpected token in '.abort' directive"))
4823 return true;
4825 if (Str.empty())
4826 return Error(Loc, ".abort detected. Assembly stopping.");
4827 else
4828 return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
4829 // FIXME: Actually abort assembly here.
4831 return false;
4834 /// parseDirectiveInclude
4835 /// ::= .include "filename"
4836 bool AsmParser::parseDirectiveInclude() {
4837 // Allow the strings to have escaped octal character sequence.
4838 std::string Filename;
4839 SMLoc IncludeLoc = getTok().getLoc();
4841 if (check(getTok().isNot(AsmToken::String),
4842 "expected string in '.include' directive") ||
4843 parseEscapedString(Filename) ||
4844 check(getTok().isNot(AsmToken::EndOfStatement),
4845 "unexpected token in '.include' directive") ||
4846 // Attempt to switch the lexer to the included file before consuming the
4847 // end of statement to avoid losing it when we switch.
4848 check(enterIncludeFile(Filename), IncludeLoc,
4849 "Could not find include file '" + Filename + "'"))
4850 return true;
4852 return false;
4855 /// parseDirectiveIncbin
4856 /// ::= .incbin "filename" [ , skip [ , count ] ]
4857 bool AsmParser::parseDirectiveIncbin() {
4858 // Allow the strings to have escaped octal character sequence.
4859 std::string Filename;
4860 SMLoc IncbinLoc = getTok().getLoc();
4861 if (check(getTok().isNot(AsmToken::String),
4862 "expected string in '.incbin' directive") ||
4863 parseEscapedString(Filename))
4864 return true;
4866 int64_t Skip = 0;
4867 const MCExpr *Count = nullptr;
4868 SMLoc SkipLoc, CountLoc;
4869 if (parseOptionalToken(AsmToken::Comma)) {
4870 // The skip expression can be omitted while specifying the count, e.g:
4871 // .incbin "filename",,4
4872 if (getTok().isNot(AsmToken::Comma)) {
4873 if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))
4874 return true;
4876 if (parseOptionalToken(AsmToken::Comma)) {
4877 CountLoc = getTok().getLoc();
4878 if (parseExpression(Count))
4879 return true;
4883 if (parseToken(AsmToken::EndOfStatement,
4884 "unexpected token in '.incbin' directive"))
4885 return true;
4887 if (check(Skip < 0, SkipLoc, "skip is negative"))
4888 return true;
4890 // Attempt to process the included file.
4891 if (processIncbinFile(Filename, Skip, Count, CountLoc))
4892 return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
4893 return false;
4896 /// parseDirectiveIf
4897 /// ::= .if{,eq,ge,gt,le,lt,ne} expression
4898 bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4899 TheCondStack.push_back(TheCondState);
4900 TheCondState.TheCond = AsmCond::IfCond;
4901 if (TheCondState.Ignore) {
4902 eatToEndOfStatement();
4903 } else {
4904 int64_t ExprValue;
4905 if (parseAbsoluteExpression(ExprValue) ||
4906 parseToken(AsmToken::EndOfStatement,
4907 "unexpected token in '.if' directive"))
4908 return true;
4910 switch (DirKind) {
4911 default:
4912 llvm_unreachable("unsupported directive");
4913 case DK_IF:
4914 case DK_IFNE:
4915 break;
4916 case DK_IFEQ:
4917 ExprValue = ExprValue == 0;
4918 break;
4919 case DK_IFGE:
4920 ExprValue = ExprValue >= 0;
4921 break;
4922 case DK_IFGT:
4923 ExprValue = ExprValue > 0;
4924 break;
4925 case DK_IFLE:
4926 ExprValue = ExprValue <= 0;
4927 break;
4928 case DK_IFLT:
4929 ExprValue = ExprValue < 0;
4930 break;
4933 TheCondState.CondMet = ExprValue;
4934 TheCondState.Ignore = !TheCondState.CondMet;
4937 return false;
4940 /// parseDirectiveIfb
4941 /// ::= .ifb string
4942 bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
4943 TheCondStack.push_back(TheCondState);
4944 TheCondState.TheCond = AsmCond::IfCond;
4946 if (TheCondState.Ignore) {
4947 eatToEndOfStatement();
4948 } else {
4949 StringRef Str = parseStringToEndOfStatement();
4951 if (parseToken(AsmToken::EndOfStatement,
4952 "unexpected token in '.ifb' directive"))
4953 return true;
4955 TheCondState.CondMet = ExpectBlank == Str.empty();
4956 TheCondState.Ignore = !TheCondState.CondMet;
4959 return false;
4962 /// parseDirectiveIfc
4963 /// ::= .ifc string1, string2
4964 /// ::= .ifnc string1, string2
4965 bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
4966 TheCondStack.push_back(TheCondState);
4967 TheCondState.TheCond = AsmCond::IfCond;
4969 if (TheCondState.Ignore) {
4970 eatToEndOfStatement();
4971 } else {
4972 StringRef Str1 = parseStringToComma();
4974 if (parseToken(AsmToken::Comma, "unexpected token in '.ifc' directive"))
4975 return true;
4977 StringRef Str2 = parseStringToEndOfStatement();
4979 if (parseToken(AsmToken::EndOfStatement,
4980 "unexpected token in '.ifc' directive"))
4981 return true;
4983 TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
4984 TheCondState.Ignore = !TheCondState.CondMet;
4987 return false;
4990 /// parseDirectiveIfeqs
4991 /// ::= .ifeqs string1, string2
4992 bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
4993 if (Lexer.isNot(AsmToken::String)) {
4994 if (ExpectEqual)
4995 return TokError("expected string parameter for '.ifeqs' directive");
4996 return TokError("expected string parameter for '.ifnes' directive");
4999 StringRef String1 = getTok().getStringContents();
5000 Lex();
5002 if (Lexer.isNot(AsmToken::Comma)) {
5003 if (ExpectEqual)
5004 return TokError(
5005 "expected comma after first string for '.ifeqs' directive");
5006 return TokError("expected comma after first string for '.ifnes' directive");
5009 Lex();
5011 if (Lexer.isNot(AsmToken::String)) {
5012 if (ExpectEqual)
5013 return TokError("expected string parameter for '.ifeqs' directive");
5014 return TokError("expected string parameter for '.ifnes' directive");
5017 StringRef String2 = getTok().getStringContents();
5018 Lex();
5020 TheCondStack.push_back(TheCondState);
5021 TheCondState.TheCond = AsmCond::IfCond;
5022 TheCondState.CondMet = ExpectEqual == (String1 == String2);
5023 TheCondState.Ignore = !TheCondState.CondMet;
5025 return false;
5028 /// parseDirectiveIfdef
5029 /// ::= .ifdef symbol
5030 bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
5031 StringRef Name;
5032 TheCondStack.push_back(TheCondState);
5033 TheCondState.TheCond = AsmCond::IfCond;
5035 if (TheCondState.Ignore) {
5036 eatToEndOfStatement();
5037 } else {
5038 if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
5039 parseToken(AsmToken::EndOfStatement, "unexpected token in '.ifdef'"))
5040 return true;
5042 MCSymbol *Sym = getContext().lookupSymbol(Name);
5044 if (expect_defined)
5045 TheCondState.CondMet = (Sym && !Sym->isUndefined(false));
5046 else
5047 TheCondState.CondMet = (!Sym || Sym->isUndefined(false));
5048 TheCondState.Ignore = !TheCondState.CondMet;
5051 return false;
5054 /// parseDirectiveElseIf
5055 /// ::= .elseif expression
5056 bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
5057 if (TheCondState.TheCond != AsmCond::IfCond &&
5058 TheCondState.TheCond != AsmCond::ElseIfCond)
5059 return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
5060 " .if or an .elseif");
5061 TheCondState.TheCond = AsmCond::ElseIfCond;
5063 bool LastIgnoreState = false;
5064 if (!TheCondStack.empty())
5065 LastIgnoreState = TheCondStack.back().Ignore;
5066 if (LastIgnoreState || TheCondState.CondMet) {
5067 TheCondState.Ignore = true;
5068 eatToEndOfStatement();
5069 } else {
5070 int64_t ExprValue;
5071 if (parseAbsoluteExpression(ExprValue))
5072 return true;
5074 if (parseToken(AsmToken::EndOfStatement,
5075 "unexpected token in '.elseif' directive"))
5076 return true;
5078 TheCondState.CondMet = ExprValue;
5079 TheCondState.Ignore = !TheCondState.CondMet;
5082 return false;
5085 /// parseDirectiveElse
5086 /// ::= .else
5087 bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
5088 if (parseToken(AsmToken::EndOfStatement,
5089 "unexpected token in '.else' directive"))
5090 return true;
5092 if (TheCondState.TheCond != AsmCond::IfCond &&
5093 TheCondState.TheCond != AsmCond::ElseIfCond)
5094 return Error(DirectiveLoc, "Encountered a .else that doesn't follow "
5095 " an .if or an .elseif");
5096 TheCondState.TheCond = AsmCond::ElseCond;
5097 bool LastIgnoreState = false;
5098 if (!TheCondStack.empty())
5099 LastIgnoreState = TheCondStack.back().Ignore;
5100 if (LastIgnoreState || TheCondState.CondMet)
5101 TheCondState.Ignore = true;
5102 else
5103 TheCondState.Ignore = false;
5105 return false;
5108 /// parseDirectiveEnd
5109 /// ::= .end
5110 bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5111 if (parseToken(AsmToken::EndOfStatement,
5112 "unexpected token in '.end' directive"))
5113 return true;
5115 while (Lexer.isNot(AsmToken::Eof))
5116 Lexer.Lex();
5118 return false;
5121 /// parseDirectiveError
5122 /// ::= .err
5123 /// ::= .error [string]
5124 bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
5125 if (!TheCondStack.empty()) {
5126 if (TheCondStack.back().Ignore) {
5127 eatToEndOfStatement();
5128 return false;
5132 if (!WithMessage)
5133 return Error(L, ".err encountered");
5135 StringRef Message = ".error directive invoked in source file";
5136 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5137 if (Lexer.isNot(AsmToken::String))
5138 return TokError(".error argument must be a string");
5140 Message = getTok().getStringContents();
5141 Lex();
5144 return Error(L, Message);
5147 /// parseDirectiveWarning
5148 /// ::= .warning [string]
5149 bool AsmParser::parseDirectiveWarning(SMLoc L) {
5150 if (!TheCondStack.empty()) {
5151 if (TheCondStack.back().Ignore) {
5152 eatToEndOfStatement();
5153 return false;
5157 StringRef Message = ".warning directive invoked in source file";
5159 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
5160 if (Lexer.isNot(AsmToken::String))
5161 return TokError(".warning argument must be a string");
5163 Message = getTok().getStringContents();
5164 Lex();
5165 if (parseToken(AsmToken::EndOfStatement,
5166 "expected end of statement in '.warning' directive"))
5167 return true;
5170 return Warning(L, Message);
5173 /// parseDirectiveEndIf
5174 /// ::= .endif
5175 bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5176 if (parseToken(AsmToken::EndOfStatement,
5177 "unexpected token in '.endif' directive"))
5178 return true;
5180 if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
5181 return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
5182 "an .if or .else");
5183 if (!TheCondStack.empty()) {
5184 TheCondState = TheCondStack.back();
5185 TheCondStack.pop_back();
5188 return false;
5191 void AsmParser::initializeDirectiveKindMap() {
5192 DirectiveKindMap[".set"] = DK_SET;
5193 DirectiveKindMap[".equ"] = DK_EQU;
5194 DirectiveKindMap[".equiv"] = DK_EQUIV;
5195 DirectiveKindMap[".ascii"] = DK_ASCII;
5196 DirectiveKindMap[".asciz"] = DK_ASCIZ;
5197 DirectiveKindMap[".string"] = DK_STRING;
5198 DirectiveKindMap[".byte"] = DK_BYTE;
5199 DirectiveKindMap[".short"] = DK_SHORT;
5200 DirectiveKindMap[".value"] = DK_VALUE;
5201 DirectiveKindMap[".2byte"] = DK_2BYTE;
5202 DirectiveKindMap[".long"] = DK_LONG;
5203 DirectiveKindMap[".int"] = DK_INT;
5204 DirectiveKindMap[".4byte"] = DK_4BYTE;
5205 DirectiveKindMap[".quad"] = DK_QUAD;
5206 DirectiveKindMap[".8byte"] = DK_8BYTE;
5207 DirectiveKindMap[".octa"] = DK_OCTA;
5208 DirectiveKindMap[".single"] = DK_SINGLE;
5209 DirectiveKindMap[".float"] = DK_FLOAT;
5210 DirectiveKindMap[".double"] = DK_DOUBLE;
5211 DirectiveKindMap[".align"] = DK_ALIGN;
5212 DirectiveKindMap[".align32"] = DK_ALIGN32;
5213 DirectiveKindMap[".balign"] = DK_BALIGN;
5214 DirectiveKindMap[".balignw"] = DK_BALIGNW;
5215 DirectiveKindMap[".balignl"] = DK_BALIGNL;
5216 DirectiveKindMap[".p2align"] = DK_P2ALIGN;
5217 DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
5218 DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
5219 DirectiveKindMap[".org"] = DK_ORG;
5220 DirectiveKindMap[".fill"] = DK_FILL;
5221 DirectiveKindMap[".zero"] = DK_ZERO;
5222 DirectiveKindMap[".extern"] = DK_EXTERN;
5223 DirectiveKindMap[".globl"] = DK_GLOBL;
5224 DirectiveKindMap[".global"] = DK_GLOBAL;
5225 DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
5226 DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
5227 DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
5228 DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
5229 DirectiveKindMap[".reference"] = DK_REFERENCE;
5230 DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
5231 DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
5232 DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
5233 DirectiveKindMap[".cold"] = DK_COLD;
5234 DirectiveKindMap[".comm"] = DK_COMM;
5235 DirectiveKindMap[".common"] = DK_COMMON;
5236 DirectiveKindMap[".lcomm"] = DK_LCOMM;
5237 DirectiveKindMap[".abort"] = DK_ABORT;
5238 DirectiveKindMap[".include"] = DK_INCLUDE;
5239 DirectiveKindMap[".incbin"] = DK_INCBIN;
5240 DirectiveKindMap[".code16"] = DK_CODE16;
5241 DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
5242 DirectiveKindMap[".rept"] = DK_REPT;
5243 DirectiveKindMap[".rep"] = DK_REPT;
5244 DirectiveKindMap[".irp"] = DK_IRP;
5245 DirectiveKindMap[".irpc"] = DK_IRPC;
5246 DirectiveKindMap[".endr"] = DK_ENDR;
5247 DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE;
5248 DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK;
5249 DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK;
5250 DirectiveKindMap[".if"] = DK_IF;
5251 DirectiveKindMap[".ifeq"] = DK_IFEQ;
5252 DirectiveKindMap[".ifge"] = DK_IFGE;
5253 DirectiveKindMap[".ifgt"] = DK_IFGT;
5254 DirectiveKindMap[".ifle"] = DK_IFLE;
5255 DirectiveKindMap[".iflt"] = DK_IFLT;
5256 DirectiveKindMap[".ifne"] = DK_IFNE;
5257 DirectiveKindMap[".ifb"] = DK_IFB;
5258 DirectiveKindMap[".ifnb"] = DK_IFNB;
5259 DirectiveKindMap[".ifc"] = DK_IFC;
5260 DirectiveKindMap[".ifeqs"] = DK_IFEQS;
5261 DirectiveKindMap[".ifnc"] = DK_IFNC;
5262 DirectiveKindMap[".ifnes"] = DK_IFNES;
5263 DirectiveKindMap[".ifdef"] = DK_IFDEF;
5264 DirectiveKindMap[".ifndef"] = DK_IFNDEF;
5265 DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
5266 DirectiveKindMap[".elseif"] = DK_ELSEIF;
5267 DirectiveKindMap[".else"] = DK_ELSE;
5268 DirectiveKindMap[".end"] = DK_END;
5269 DirectiveKindMap[".endif"] = DK_ENDIF;
5270 DirectiveKindMap[".skip"] = DK_SKIP;
5271 DirectiveKindMap[".space"] = DK_SPACE;
5272 DirectiveKindMap[".file"] = DK_FILE;
5273 DirectiveKindMap[".line"] = DK_LINE;
5274 DirectiveKindMap[".loc"] = DK_LOC;
5275 DirectiveKindMap[".stabs"] = DK_STABS;
5276 DirectiveKindMap[".cv_file"] = DK_CV_FILE;
5277 DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
5278 DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
5279 DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
5280 DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
5281 DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
5282 DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
5283 DirectiveKindMap[".cv_string"] = DK_CV_STRING;
5284 DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
5285 DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
5286 DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
5287 DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
5288 DirectiveKindMap[".sleb128"] = DK_SLEB128;
5289 DirectiveKindMap[".uleb128"] = DK_ULEB128;
5290 DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
5291 DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
5292 DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
5293 DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
5294 DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
5295 DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
5296 DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
5297 DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
5298 DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
5299 DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
5300 DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
5301 DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
5302 DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
5303 DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
5304 DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
5305 DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
5306 DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
5307 DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
5308 DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
5309 DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
5310 DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
5311 DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
5312 DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
5313 DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
5314 DirectiveKindMap[".macro"] = DK_MACRO;
5315 DirectiveKindMap[".exitm"] = DK_EXITM;
5316 DirectiveKindMap[".endm"] = DK_ENDM;
5317 DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
5318 DirectiveKindMap[".purgem"] = DK_PURGEM;
5319 DirectiveKindMap[".err"] = DK_ERR;
5320 DirectiveKindMap[".error"] = DK_ERROR;
5321 DirectiveKindMap[".warning"] = DK_WARNING;
5322 DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
5323 DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
5324 DirectiveKindMap[".reloc"] = DK_RELOC;
5325 DirectiveKindMap[".dc"] = DK_DC;
5326 DirectiveKindMap[".dc.a"] = DK_DC_A;
5327 DirectiveKindMap[".dc.b"] = DK_DC_B;
5328 DirectiveKindMap[".dc.d"] = DK_DC_D;
5329 DirectiveKindMap[".dc.l"] = DK_DC_L;
5330 DirectiveKindMap[".dc.s"] = DK_DC_S;
5331 DirectiveKindMap[".dc.w"] = DK_DC_W;
5332 DirectiveKindMap[".dc.x"] = DK_DC_X;
5333 DirectiveKindMap[".dcb"] = DK_DCB;
5334 DirectiveKindMap[".dcb.b"] = DK_DCB_B;
5335 DirectiveKindMap[".dcb.d"] = DK_DCB_D;
5336 DirectiveKindMap[".dcb.l"] = DK_DCB_L;
5337 DirectiveKindMap[".dcb.s"] = DK_DCB_S;
5338 DirectiveKindMap[".dcb.w"] = DK_DCB_W;
5339 DirectiveKindMap[".dcb.x"] = DK_DCB_X;
5340 DirectiveKindMap[".ds"] = DK_DS;
5341 DirectiveKindMap[".ds.b"] = DK_DS_B;
5342 DirectiveKindMap[".ds.d"] = DK_DS_D;
5343 DirectiveKindMap[".ds.l"] = DK_DS_L;
5344 DirectiveKindMap[".ds.p"] = DK_DS_P;
5345 DirectiveKindMap[".ds.s"] = DK_DS_S;
5346 DirectiveKindMap[".ds.w"] = DK_DS_W;
5347 DirectiveKindMap[".ds.x"] = DK_DS_X;
5348 DirectiveKindMap[".print"] = DK_PRINT;
5349 DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
5350 DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
5353 MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5354 AsmToken EndToken, StartToken = getTok();
5356 unsigned NestLevel = 0;
5357 while (true) {
5358 // Check whether we have reached the end of the file.
5359 if (getLexer().is(AsmToken::Eof)) {
5360 printError(DirectiveLoc, "no matching '.endr' in definition");
5361 return nullptr;
5364 if (Lexer.is(AsmToken::Identifier) &&
5365 (getTok().getIdentifier() == ".rep" ||
5366 getTok().getIdentifier() == ".rept" ||
5367 getTok().getIdentifier() == ".irp" ||
5368 getTok().getIdentifier() == ".irpc")) {
5369 ++NestLevel;
5372 // Otherwise, check whether we have reached the .endr.
5373 if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") {
5374 if (NestLevel == 0) {
5375 EndToken = getTok();
5376 Lex();
5377 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5378 printError(getTok().getLoc(),
5379 "unexpected token in '.endr' directive");
5380 return nullptr;
5382 break;
5384 --NestLevel;
5387 // Otherwise, scan till the end of the statement.
5388 eatToEndOfStatement();
5391 const char *BodyStart = StartToken.getLoc().getPointer();
5392 const char *BodyEnd = EndToken.getLoc().getPointer();
5393 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5395 // We Are Anonymous.
5396 MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
5397 return &MacroLikeBodies.back();
5400 void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5401 raw_svector_ostream &OS) {
5402 OS << ".endr\n";
5404 std::unique_ptr<MemoryBuffer> Instantiation =
5405 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
5407 // Create the macro instantiation object and add to the current macro
5408 // instantiation stack.
5409 MacroInstantiation *MI = new MacroInstantiation(
5410 DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size());
5411 ActiveMacros.push_back(MI);
5413 // Jump to the macro instantiation and prime the lexer.
5414 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
5415 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
5416 Lex();
5419 /// parseDirectiveRept
5420 /// ::= .rep | .rept count
5421 bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
5422 const MCExpr *CountExpr;
5423 SMLoc CountLoc = getTok().getLoc();
5424 if (parseExpression(CountExpr))
5425 return true;
5427 int64_t Count;
5428 if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
5429 return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
5432 if (check(Count < 0, CountLoc, "Count is negative") ||
5433 parseToken(AsmToken::EndOfStatement,
5434 "unexpected token in '" + Dir + "' directive"))
5435 return true;
5437 // Lex the rept definition.
5438 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5439 if (!M)
5440 return true;
5442 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5443 // to hold the macro body with substitutions.
5444 SmallString<256> Buf;
5445 raw_svector_ostream OS(Buf);
5446 while (Count--) {
5447 // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
5448 if (expandMacro(OS, M->Body, None, None, false, getTok().getLoc()))
5449 return true;
5451 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5453 return false;
5456 /// parseDirectiveIrp
5457 /// ::= .irp symbol,values
5458 bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
5459 MCAsmMacroParameter Parameter;
5460 MCAsmMacroArguments A;
5461 if (check(parseIdentifier(Parameter.Name),
5462 "expected identifier in '.irp' directive") ||
5463 parseToken(AsmToken::Comma, "expected comma in '.irp' directive") ||
5464 parseMacroArguments(nullptr, A) ||
5465 parseToken(AsmToken::EndOfStatement, "expected End of Statement"))
5466 return true;
5468 // Lex the irp definition.
5469 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5470 if (!M)
5471 return true;
5473 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5474 // to hold the macro body with substitutions.
5475 SmallString<256> Buf;
5476 raw_svector_ostream OS(Buf);
5478 for (const MCAsmMacroArgument &Arg : A) {
5479 // Note that the AtPseudoVariable is enabled for instantiations of .irp.
5480 // This is undocumented, but GAS seems to support it.
5481 if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
5482 return true;
5485 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5487 return false;
5490 /// parseDirectiveIrpc
5491 /// ::= .irpc symbol,values
5492 bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
5493 MCAsmMacroParameter Parameter;
5494 MCAsmMacroArguments A;
5496 if (check(parseIdentifier(Parameter.Name),
5497 "expected identifier in '.irpc' directive") ||
5498 parseToken(AsmToken::Comma, "expected comma in '.irpc' directive") ||
5499 parseMacroArguments(nullptr, A))
5500 return true;
5502 if (A.size() != 1 || A.front().size() != 1)
5503 return TokError("unexpected token in '.irpc' directive");
5505 // Eat the end of statement.
5506 if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
5507 return true;
5509 // Lex the irpc definition.
5510 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5511 if (!M)
5512 return true;
5514 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5515 // to hold the macro body with substitutions.
5516 SmallString<256> Buf;
5517 raw_svector_ostream OS(Buf);
5519 StringRef Values = A.front().front().getString();
5520 for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
5521 MCAsmMacroArgument Arg;
5522 Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
5524 // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
5525 // This is undocumented, but GAS seems to support it.
5526 if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
5527 return true;
5530 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5532 return false;
5535 bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
5536 if (ActiveMacros.empty())
5537 return TokError("unmatched '.endr' directive");
5539 // The only .repl that should get here are the ones created by
5540 // instantiateMacroLikeBody.
5541 assert(getLexer().is(AsmToken::EndOfStatement));
5543 handleMacroExit();
5544 return false;
5547 bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5548 size_t Len) {
5549 const MCExpr *Value;
5550 SMLoc ExprLoc = getLexer().getLoc();
5551 if (parseExpression(Value))
5552 return true;
5553 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5554 if (!MCE)
5555 return Error(ExprLoc, "unexpected expression in _emit");
5556 uint64_t IntValue = MCE->getValue();
5557 if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
5558 return Error(ExprLoc, "literal value out of range for directive");
5560 Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
5561 return false;
5564 bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5565 const MCExpr *Value;
5566 SMLoc ExprLoc = getLexer().getLoc();
5567 if (parseExpression(Value))
5568 return true;
5569 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5570 if (!MCE)
5571 return Error(ExprLoc, "unexpected expression in align");
5572 uint64_t IntValue = MCE->getValue();
5573 if (!isPowerOf2_64(IntValue))
5574 return Error(ExprLoc, "literal value not a power of two greater then zero");
5576 Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
5577 return false;
5580 bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
5581 const AsmToken StrTok = getTok();
5582 Lex();
5583 if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
5584 return Error(DirectiveLoc, "expected double quoted string after .print");
5585 if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
5586 return true;
5587 llvm::outs() << StrTok.getStringContents() << '\n';
5588 return false;
5591 bool AsmParser::parseDirectiveAddrsig() {
5592 getStreamer().EmitAddrsig();
5593 return false;
5596 bool AsmParser::parseDirectiveAddrsigSym() {
5597 StringRef Name;
5598 if (check(parseIdentifier(Name),
5599 "expected identifier in '.addrsig_sym' directive"))
5600 return true;
5601 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5602 getStreamer().EmitAddrsigSym(Sym);
5603 return false;
5606 // We are comparing pointers, but the pointers are relative to a single string.
5607 // Thus, this should always be deterministic.
5608 static int rewritesSort(const AsmRewrite *AsmRewriteA,
5609 const AsmRewrite *AsmRewriteB) {
5610 if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
5611 return -1;
5612 if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
5613 return 1;
5615 // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
5616 // rewrite to the same location. Make sure the SizeDirective rewrite is
5617 // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
5618 // ensures the sort algorithm is stable.
5619 if (AsmRewritePrecedence[AsmRewriteA->Kind] >
5620 AsmRewritePrecedence[AsmRewriteB->Kind])
5621 return -1;
5623 if (AsmRewritePrecedence[AsmRewriteA->Kind] <
5624 AsmRewritePrecedence[AsmRewriteB->Kind])
5625 return 1;
5626 llvm_unreachable("Unstable rewrite sort.");
5629 bool AsmParser::parseMSInlineAsm(
5630 void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
5631 unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5632 SmallVectorImpl<std::string> &Constraints,
5633 SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
5634 const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5635 SmallVector<void *, 4> InputDecls;
5636 SmallVector<void *, 4> OutputDecls;
5637 SmallVector<bool, 4> InputDeclsAddressOf;
5638 SmallVector<bool, 4> OutputDeclsAddressOf;
5639 SmallVector<std::string, 4> InputConstraints;
5640 SmallVector<std::string, 4> OutputConstraints;
5641 SmallVector<unsigned, 4> ClobberRegs;
5643 SmallVector<AsmRewrite, 4> AsmStrRewrites;
5645 // Prime the lexer.
5646 Lex();
5648 // While we have input, parse each statement.
5649 unsigned InputIdx = 0;
5650 unsigned OutputIdx = 0;
5651 while (getLexer().isNot(AsmToken::Eof)) {
5652 // Parse curly braces marking block start/end
5653 if (parseCurlyBlockScope(AsmStrRewrites))
5654 continue;
5656 ParseStatementInfo Info(&AsmStrRewrites);
5657 bool StatementErr = parseStatement(Info, &SI);
5659 if (StatementErr || Info.ParseError) {
5660 // Emit pending errors if any exist.
5661 printPendingErrors();
5662 return true;
5665 // No pending error should exist here.
5666 assert(!hasPendingError() && "unexpected error from parseStatement");
5668 if (Info.Opcode == ~0U)
5669 continue;
5671 const MCInstrDesc &Desc = MII->get(Info.Opcode);
5673 // Build the list of clobbers, outputs and inputs.
5674 for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
5675 MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
5677 // Immediate.
5678 if (Operand.isImm())
5679 continue;
5681 // Register operand.
5682 if (Operand.isReg() && !Operand.needAddressOf() &&
5683 !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
5684 unsigned NumDefs = Desc.getNumDefs();
5685 // Clobber.
5686 if (NumDefs && Operand.getMCOperandNum() < NumDefs)
5687 ClobberRegs.push_back(Operand.getReg());
5688 continue;
5691 // Expr/Input or Output.
5692 StringRef SymName = Operand.getSymName();
5693 if (SymName.empty())
5694 continue;
5696 void *OpDecl = Operand.getOpDecl();
5697 if (!OpDecl)
5698 continue;
5700 bool isOutput = (i == 1) && Desc.mayStore();
5701 SMLoc Start = SMLoc::getFromPointer(SymName.data());
5702 if (isOutput) {
5703 ++InputIdx;
5704 OutputDecls.push_back(OpDecl);
5705 OutputDeclsAddressOf.push_back(Operand.needAddressOf());
5706 OutputConstraints.push_back(("=" + Operand.getConstraint()).str());
5707 AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
5708 } else {
5709 InputDecls.push_back(OpDecl);
5710 InputDeclsAddressOf.push_back(Operand.needAddressOf());
5711 InputConstraints.push_back(Operand.getConstraint().str());
5712 AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
5716 // Consider implicit defs to be clobbers. Think of cpuid and push.
5717 ArrayRef<MCPhysReg> ImpDefs(Desc.getImplicitDefs(),
5718 Desc.getNumImplicitDefs());
5719 ClobberRegs.insert(ClobberRegs.end(), ImpDefs.begin(), ImpDefs.end());
5722 // Set the number of Outputs and Inputs.
5723 NumOutputs = OutputDecls.size();
5724 NumInputs = InputDecls.size();
5726 // Set the unique clobbers.
5727 array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
5728 ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
5729 ClobberRegs.end());
5730 Clobbers.assign(ClobberRegs.size(), std::string());
5731 for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
5732 raw_string_ostream OS(Clobbers[I]);
5733 IP->printRegName(OS, ClobberRegs[I]);
5736 // Merge the various outputs and inputs. Output are expected first.
5737 if (NumOutputs || NumInputs) {
5738 unsigned NumExprs = NumOutputs + NumInputs;
5739 OpDecls.resize(NumExprs);
5740 Constraints.resize(NumExprs);
5741 for (unsigned i = 0; i < NumOutputs; ++i) {
5742 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
5743 Constraints[i] = OutputConstraints[i];
5745 for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
5746 OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
5747 Constraints[j] = InputConstraints[i];
5751 // Build the IR assembly string.
5752 std::string AsmStringIR;
5753 raw_string_ostream OS(AsmStringIR);
5754 StringRef ASMString =
5755 SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
5756 const char *AsmStart = ASMString.begin();
5757 const char *AsmEnd = ASMString.end();
5758 array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
5759 for (const AsmRewrite &AR : AsmStrRewrites) {
5760 AsmRewriteKind Kind = AR.Kind;
5762 const char *Loc = AR.Loc.getPointer();
5763 assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
5765 // Emit everything up to the immediate/expression.
5766 if (unsigned Len = Loc - AsmStart)
5767 OS << StringRef(AsmStart, Len);
5769 // Skip the original expression.
5770 if (Kind == AOK_Skip) {
5771 AsmStart = Loc + AR.Len;
5772 continue;
5775 unsigned AdditionalSkip = 0;
5776 // Rewrite expressions in $N notation.
5777 switch (Kind) {
5778 default:
5779 break;
5780 case AOK_IntelExpr:
5781 assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
5782 if (AR.IntelExp.NeedBracs)
5783 OS << "[";
5784 if (AR.IntelExp.hasBaseReg())
5785 OS << AR.IntelExp.BaseReg;
5786 if (AR.IntelExp.hasIndexReg())
5787 OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
5788 << AR.IntelExp.IndexReg;
5789 if (AR.IntelExp.Scale > 1)
5790 OS << " * $$" << AR.IntelExp.Scale;
5791 if (AR.IntelExp.Imm || !AR.IntelExp.hasRegs())
5792 OS << (AR.IntelExp.hasRegs() ? " + $$" : "$$") << AR.IntelExp.Imm;
5793 if (AR.IntelExp.NeedBracs)
5794 OS << "]";
5795 break;
5796 case AOK_Label:
5797 OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
5798 break;
5799 case AOK_Input:
5800 OS << '$' << InputIdx++;
5801 break;
5802 case AOK_Output:
5803 OS << '$' << OutputIdx++;
5804 break;
5805 case AOK_SizeDirective:
5806 switch (AR.Val) {
5807 default: break;
5808 case 8: OS << "byte ptr "; break;
5809 case 16: OS << "word ptr "; break;
5810 case 32: OS << "dword ptr "; break;
5811 case 64: OS << "qword ptr "; break;
5812 case 80: OS << "xword ptr "; break;
5813 case 128: OS << "xmmword ptr "; break;
5814 case 256: OS << "ymmword ptr "; break;
5816 break;
5817 case AOK_Emit:
5818 OS << ".byte";
5819 break;
5820 case AOK_Align: {
5821 // MS alignment directives are measured in bytes. If the native assembler
5822 // measures alignment in bytes, we can pass it straight through.
5823 OS << ".align";
5824 if (getContext().getAsmInfo()->getAlignmentIsInBytes())
5825 break;
5827 // Alignment is in log2 form, so print that instead and skip the original
5828 // immediate.
5829 unsigned Val = AR.Val;
5830 OS << ' ' << Val;
5831 assert(Val < 10 && "Expected alignment less then 2^10.");
5832 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
5833 break;
5835 case AOK_EVEN:
5836 OS << ".even";
5837 break;
5838 case AOK_EndOfStatement:
5839 OS << "\n\t";
5840 break;
5843 // Skip the original expression.
5844 AsmStart = Loc + AR.Len + AdditionalSkip;
5847 // Emit the remainder of the asm string.
5848 if (AsmStart != AsmEnd)
5849 OS << StringRef(AsmStart, AsmEnd - AsmStart);
5851 AsmString = OS.str();
5852 return false;
5855 namespace llvm {
5856 namespace MCParserUtils {
5858 /// Returns whether the given symbol is used anywhere in the given expression,
5859 /// or subexpressions.
5860 static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
5861 switch (Value->getKind()) {
5862 case MCExpr::Binary: {
5863 const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
5864 return isSymbolUsedInExpression(Sym, BE->getLHS()) ||
5865 isSymbolUsedInExpression(Sym, BE->getRHS());
5867 case MCExpr::Target:
5868 case MCExpr::Constant:
5869 return false;
5870 case MCExpr::SymbolRef: {
5871 const MCSymbol &S =
5872 static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
5873 if (S.isVariable())
5874 return isSymbolUsedInExpression(Sym, S.getVariableValue());
5875 return &S == Sym;
5877 case MCExpr::Unary:
5878 return isSymbolUsedInExpression(
5879 Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
5882 llvm_unreachable("Unknown expr kind!");
5885 bool parseAssignmentExpression(StringRef Name, bool allow_redef,
5886 MCAsmParser &Parser, MCSymbol *&Sym,
5887 const MCExpr *&Value) {
5889 // FIXME: Use better location, we should use proper tokens.
5890 SMLoc EqualLoc = Parser.getTok().getLoc();
5891 if (Parser.parseExpression(Value))
5892 return Parser.TokError("missing expression");
5894 // Note: we don't count b as used in "a = b". This is to allow
5895 // a = b
5896 // b = c
5898 if (Parser.parseToken(AsmToken::EndOfStatement))
5899 return true;
5901 // Validate that the LHS is allowed to be a variable (either it has not been
5902 // used as a symbol, or it is an absolute symbol).
5903 Sym = Parser.getContext().lookupSymbol(Name);
5904 if (Sym) {
5905 // Diagnose assignment to a label.
5907 // FIXME: Diagnostics. Note the location of the definition as a label.
5908 // FIXME: Diagnose assignment to protected identifier (e.g., register name).
5909 if (isSymbolUsedInExpression(Sym, Value))
5910 return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'");
5911 else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() &&
5912 !Sym->isVariable())
5913 ; // Allow redefinitions of undefined symbols only used in directives.
5914 else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
5915 ; // Allow redefinitions of variables that haven't yet been used.
5916 else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
5917 return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
5918 else if (!Sym->isVariable())
5919 return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'");
5920 else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
5921 return Parser.Error(EqualLoc,
5922 "invalid reassignment of non-absolute variable '" +
5923 Name + "'");
5924 } else if (Name == ".") {
5925 Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
5926 return false;
5927 } else
5928 Sym = Parser.getContext().getOrCreateSymbol(Name);
5930 Sym->setRedefinable(allow_redef);
5932 return false;
5935 } // end namespace MCParserUtils
5936 } // end namespace llvm
5938 /// Create an MCAsmParser instance.
5939 MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
5940 MCStreamer &Out, const MCAsmInfo &MAI,
5941 unsigned CB) {
5942 return new AsmParser(SM, C, Out, MAI, CB);