LLVM 19.0.0git
AsmParser.cpp
Go to the documentation of this file.
1//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This class implements a parser for assembly files similar to gas syntax.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/ADT/APFloat.h"
14#include "llvm/ADT/APInt.h"
15#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/SmallSet.h"
21#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/ADT/Twine.h"
26#include "llvm/MC/MCAsmInfo.h"
27#include "llvm/MC/MCCodeView.h"
28#include "llvm/MC/MCContext.h"
30#include "llvm/MC/MCDwarf.h"
31#include "llvm/MC/MCExpr.h"
33#include "llvm/MC/MCInstrDesc.h"
34#include "llvm/MC/MCInstrInfo.h"
44#include "llvm/MC/MCSection.h"
45#include "llvm/MC/MCStreamer.h"
46#include "llvm/MC/MCSymbol.h"
49#include "llvm/MC/MCValue.h"
53#include "llvm/Support/MD5.h"
56#include "llvm/Support/SMLoc.h"
59#include <algorithm>
60#include <cassert>
61#include <cctype>
62#include <climits>
63#include <cstddef>
64#include <cstdint>
65#include <deque>
66#include <memory>
67#include <optional>
68#include <sstream>
69#include <string>
70#include <tuple>
71#include <utility>
72#include <vector>
73
74using namespace llvm;
75
77
78namespace {
79
80/// Helper types for tracking macro definitions.
81typedef std::vector<AsmToken> MCAsmMacroArgument;
82typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
83
84/// Helper class for storing information about an active macro
85/// instantiation.
86struct MacroInstantiation {
87 /// The location of the instantiation.
88 SMLoc InstantiationLoc;
89
90 /// The buffer where parsing should resume upon instantiation completion.
91 unsigned ExitBuffer;
92
93 /// The location where parsing should resume upon instantiation completion.
94 SMLoc ExitLoc;
95
96 /// The depth of TheCondStack at the start of the instantiation.
97 size_t CondStackDepth;
98};
99
100struct ParseStatementInfo {
101 /// The parsed operands from the last parsed statement.
103
104 /// The opcode from the last parsed instruction.
105 unsigned Opcode = ~0U;
106
107 /// Was there an error parsing the inline assembly?
108 bool ParseError = false;
109
110 SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
111
112 ParseStatementInfo() = delete;
113 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
114 : AsmRewrites(rewrites) {}
115};
116
117/// The concrete assembly parser instance.
118class AsmParser : public MCAsmParser {
119private:
120 AsmLexer Lexer;
121 MCContext &Ctx;
122 MCStreamer &Out;
123 const MCAsmInfo &MAI;
125 SourceMgr::DiagHandlerTy SavedDiagHandler;
126 void *SavedDiagContext;
127 std::unique_ptr<MCAsmParserExtension> PlatformParser;
128 SMLoc StartTokLoc;
129 std::optional<SMLoc> CFIStartProcLoc;
130
131 /// This is the current buffer index we're lexing from as managed by the
132 /// SourceMgr object.
133 unsigned CurBuffer;
134
135 AsmCond TheCondState;
136 std::vector<AsmCond> TheCondStack;
137
138 /// maps directive names to handler methods in parser
139 /// extensions. Extensions register themselves in this map by calling
140 /// addDirectiveHandler.
141 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
142
143 /// Stack of active macro instantiations.
144 std::vector<MacroInstantiation*> ActiveMacros;
145
146 /// List of bodies of anonymous macros.
147 std::deque<MCAsmMacro> MacroLikeBodies;
148
149 /// Boolean tracking whether macro substitution is enabled.
150 unsigned MacrosEnabledFlag : 1;
151
152 /// Keeps track of how many .macro's have been instantiated.
153 unsigned NumOfMacroInstantiations;
154
155 /// The values from the last parsed cpp hash file line comment if any.
156 struct CppHashInfoTy {
158 int64_t LineNumber;
159 SMLoc Loc;
160 unsigned Buf;
161 CppHashInfoTy() : LineNumber(0), Buf(0) {}
162 };
163 CppHashInfoTy CppHashInfo;
164
165 /// The filename from the first cpp hash file line comment, if any.
166 StringRef FirstCppHashFilename;
167
168 /// List of forward directional labels for diagnosis at the end.
170
171 SmallSet<StringRef, 2> LTODiscardSymbols;
172
173 /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
174 unsigned AssemblerDialect = ~0U;
175
176 /// is Darwin compatibility enabled?
177 bool IsDarwin = false;
178
179 /// Are we parsing ms-style inline assembly?
180 bool ParsingMSInlineAsm = false;
181
182 /// Did we already inform the user about inconsistent MD5 usage?
183 bool ReportedInconsistentMD5 = false;
184
185 // Is alt macro mode enabled.
186 bool AltMacroMode = false;
187
188protected:
189 virtual bool parseStatement(ParseStatementInfo &Info,
191
192 /// This routine uses the target specific ParseInstruction function to
193 /// parse an instruction into Operands, and then call the target specific
194 /// MatchAndEmit function to match and emit the instruction.
195 bool parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,
196 StringRef IDVal, AsmToken ID,
197 SMLoc IDLoc);
198
199 /// Should we emit DWARF describing this assembler source? (Returns false if
200 /// the source has .file directives, which means we don't want to generate
201 /// info describing the assembler source itself.)
202 bool enabledGenDwarfForAssembly();
203
204public:
205 AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
206 const MCAsmInfo &MAI, unsigned CB);
207 AsmParser(const AsmParser &) = delete;
208 AsmParser &operator=(const AsmParser &) = delete;
209 ~AsmParser() override;
210
211 bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
212
214 ExtensionDirectiveHandler Handler) override {
215 ExtensionDirectiveMap[Directive] = Handler;
216 }
217
218 void addAliasForDirective(StringRef Directive, StringRef Alias) override {
219 DirectiveKindMap[Directive.lower()] = DirectiveKindMap[Alias.lower()];
220 }
221
222 /// @name MCAsmParser Interface
223 /// {
224
225 SourceMgr &getSourceManager() override { return SrcMgr; }
226 MCAsmLexer &getLexer() override { return Lexer; }
227 MCContext &getContext() override { return Ctx; }
228 MCStreamer &getStreamer() override { return Out; }
229
230 CodeViewContext &getCVContext() { return Ctx.getCVContext(); }
231
232 unsigned getAssemblerDialect() override {
233 if (AssemblerDialect == ~0U)
234 return MAI.getAssemblerDialect();
235 else
236 return AssemblerDialect;
237 }
238 void setAssemblerDialect(unsigned i) override {
239 AssemblerDialect = i;
240 }
241
242 void Note(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) override;
243 bool Warning(SMLoc L, const Twine &Msg,
244 SMRange Range = std::nullopt) override;
245 bool printError(SMLoc L, const Twine &Msg,
246 SMRange Range = std::nullopt) override;
247
248 const AsmToken &Lex() override;
249
250 void setParsingMSInlineAsm(bool V) override {
251 ParsingMSInlineAsm = V;
252 // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
253 // hex integer literals.
254 Lexer.setLexMasmIntegers(V);
255 }
256 bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
257
258 bool discardLTOSymbol(StringRef Name) const override {
259 return LTODiscardSymbols.contains(Name);
260 }
261
262 bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs,
263 unsigned &NumInputs,
264 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
265 SmallVectorImpl<std::string> &Constraints,
267 const MCInstrInfo *MII, const MCInstPrinter *IP,
268 MCAsmParserSemaCallback &SI) override;
269
270 bool parseExpression(const MCExpr *&Res);
271 bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
272 bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
273 AsmTypeInfo *TypeInfo) override;
274 bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
275 bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
276 SMLoc &EndLoc) override;
277 bool parseAbsoluteExpression(int64_t &Res) override;
278
279 /// Parse a floating point expression using the float \p Semantics
280 /// and set \p Res to the value.
281 bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
282
283 /// Parse an identifier or string (as a quoted identifier)
284 /// and set \p Res to the identifier contents.
285 bool parseIdentifier(StringRef &Res) override;
286 void eatToEndOfStatement() override;
287
288 bool checkForValidSection() override;
289
290 /// }
291
292private:
293 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
294 bool parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo = true);
295
296 void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
298 bool expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,
300 ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable);
301
302 /// Are macros enabled in the parser?
303 bool areMacrosEnabled() {return MacrosEnabledFlag;}
304
305 /// Control a flag in the parser that enables or disables macros.
306 void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
307
308 /// Are we inside a macro instantiation?
309 bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
310
311 /// Handle entry to macro instantiation.
312 ///
313 /// \param M The macro.
314 /// \param NameLoc Instantiation location.
315 bool handleMacroEntry(MCAsmMacro *M, SMLoc NameLoc);
316
317 /// Handle exit from macro instantiation.
318 void handleMacroExit();
319
320 /// Extract AsmTokens for a macro argument.
321 bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
322
323 /// Parse all macro arguments for a given macro.
324 bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
325
326 void printMacroInstantiations();
327 void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
328 SMRange Range = std::nullopt) const {
330 SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
331 }
332 static void DiagHandler(const SMDiagnostic &Diag, void *Context);
333
334 /// Enter the specified file. This returns true on failure.
335 bool enterIncludeFile(const std::string &Filename);
336
337 /// Process the specified file for the .incbin directive.
338 /// This returns true on failure.
339 bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,
340 const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());
341
342 /// Reset the current lexer position to that given by \p Loc. The
343 /// current token is not set; clients should ensure Lex() is called
344 /// subsequently.
345 ///
346 /// \param InBuffer If not 0, should be the known buffer id that contains the
347 /// location.
348 void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);
349
350 /// Parse up to the end of statement and a return the contents from the
351 /// current token until the end of the statement; the current token on exit
352 /// will be either the EndOfStatement or EOF.
354
355 /// Parse until the end of a statement or a comma is encountered,
356 /// return the contents from the current token up to the end or comma.
357 StringRef parseStringToComma();
358
359 enum class AssignmentKind {
360 Set,
361 Equiv,
362 Equal,
363 LTOSetConditional,
364 };
365
366 bool parseAssignment(StringRef Name, AssignmentKind Kind);
367
368 unsigned getBinOpPrecedence(AsmToken::TokenKind K,
370
371 bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
372 bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
373 bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
374
375 bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
376
377 bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);
378 bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);
379
380 // Generic (target and platform independent) directive parsing.
381 enum DirectiveKind {
382 DK_NO_DIRECTIVE, // Placeholder
383 DK_SET,
384 DK_EQU,
385 DK_EQUIV,
386 DK_ASCII,
387 DK_ASCIZ,
388 DK_STRING,
389 DK_BYTE,
390 DK_SHORT,
391 DK_RELOC,
392 DK_VALUE,
393 DK_2BYTE,
394 DK_LONG,
395 DK_INT,
396 DK_4BYTE,
397 DK_QUAD,
398 DK_8BYTE,
399 DK_OCTA,
400 DK_DC,
401 DK_DC_A,
402 DK_DC_B,
403 DK_DC_D,
404 DK_DC_L,
405 DK_DC_S,
406 DK_DC_W,
407 DK_DC_X,
408 DK_DCB,
409 DK_DCB_B,
410 DK_DCB_D,
411 DK_DCB_L,
412 DK_DCB_S,
413 DK_DCB_W,
414 DK_DCB_X,
415 DK_DS,
416 DK_DS_B,
417 DK_DS_D,
418 DK_DS_L,
419 DK_DS_P,
420 DK_DS_S,
421 DK_DS_W,
422 DK_DS_X,
423 DK_SINGLE,
424 DK_FLOAT,
425 DK_DOUBLE,
426 DK_ALIGN,
427 DK_ALIGN32,
428 DK_BALIGN,
429 DK_BALIGNW,
430 DK_BALIGNL,
431 DK_P2ALIGN,
432 DK_P2ALIGNW,
433 DK_P2ALIGNL,
434 DK_ORG,
435 DK_FILL,
436 DK_ENDR,
437 DK_BUNDLE_ALIGN_MODE,
438 DK_BUNDLE_LOCK,
439 DK_BUNDLE_UNLOCK,
440 DK_ZERO,
441 DK_EXTERN,
442 DK_GLOBL,
443 DK_GLOBAL,
444 DK_LAZY_REFERENCE,
445 DK_NO_DEAD_STRIP,
446 DK_SYMBOL_RESOLVER,
447 DK_PRIVATE_EXTERN,
448 DK_REFERENCE,
449 DK_WEAK_DEFINITION,
450 DK_WEAK_REFERENCE,
451 DK_WEAK_DEF_CAN_BE_HIDDEN,
452 DK_COLD,
453 DK_COMM,
454 DK_COMMON,
455 DK_LCOMM,
456 DK_ABORT,
457 DK_INCLUDE,
458 DK_INCBIN,
459 DK_CODE16,
460 DK_CODE16GCC,
461 DK_REPT,
462 DK_IRP,
463 DK_IRPC,
464 DK_IF,
465 DK_IFEQ,
466 DK_IFGE,
467 DK_IFGT,
468 DK_IFLE,
469 DK_IFLT,
470 DK_IFNE,
471 DK_IFB,
472 DK_IFNB,
473 DK_IFC,
474 DK_IFEQS,
475 DK_IFNC,
476 DK_IFNES,
477 DK_IFDEF,
478 DK_IFNDEF,
479 DK_IFNOTDEF,
480 DK_ELSEIF,
481 DK_ELSE,
482 DK_ENDIF,
483 DK_SPACE,
484 DK_SKIP,
485 DK_FILE,
486 DK_LINE,
487 DK_LOC,
488 DK_STABS,
489 DK_CV_FILE,
490 DK_CV_FUNC_ID,
491 DK_CV_INLINE_SITE_ID,
492 DK_CV_LOC,
493 DK_CV_LINETABLE,
494 DK_CV_INLINE_LINETABLE,
495 DK_CV_DEF_RANGE,
496 DK_CV_STRINGTABLE,
497 DK_CV_STRING,
498 DK_CV_FILECHECKSUMS,
499 DK_CV_FILECHECKSUM_OFFSET,
500 DK_CV_FPO_DATA,
501 DK_CFI_SECTIONS,
502 DK_CFI_STARTPROC,
503 DK_CFI_ENDPROC,
504 DK_CFI_DEF_CFA,
505 DK_CFI_DEF_CFA_OFFSET,
506 DK_CFI_ADJUST_CFA_OFFSET,
507 DK_CFI_DEF_CFA_REGISTER,
508 DK_CFI_LLVM_DEF_ASPACE_CFA,
509 DK_CFI_OFFSET,
510 DK_CFI_REL_OFFSET,
511 DK_CFI_PERSONALITY,
512 DK_CFI_LSDA,
513 DK_CFI_REMEMBER_STATE,
514 DK_CFI_RESTORE_STATE,
515 DK_CFI_SAME_VALUE,
516 DK_CFI_RESTORE,
517 DK_CFI_ESCAPE,
518 DK_CFI_RETURN_COLUMN,
519 DK_CFI_SIGNAL_FRAME,
520 DK_CFI_UNDEFINED,
521 DK_CFI_REGISTER,
522 DK_CFI_WINDOW_SAVE,
523 DK_CFI_B_KEY_FRAME,
524 DK_MACROS_ON,
525 DK_MACROS_OFF,
526 DK_ALTMACRO,
527 DK_NOALTMACRO,
528 DK_MACRO,
529 DK_EXITM,
530 DK_ENDM,
531 DK_ENDMACRO,
532 DK_PURGEM,
533 DK_SLEB128,
534 DK_ULEB128,
535 DK_ERR,
536 DK_ERROR,
537 DK_WARNING,
538 DK_PRINT,
539 DK_ADDRSIG,
540 DK_ADDRSIG_SYM,
541 DK_PSEUDO_PROBE,
542 DK_LTO_DISCARD,
543 DK_LTO_SET_CONDITIONAL,
544 DK_CFI_MTE_TAGGED_FRAME,
545 DK_MEMTAG,
546 DK_END
547 };
548
549 /// Maps directive name --> DirectiveKind enum, for
550 /// directives parsed by this class.
551 StringMap<DirectiveKind> DirectiveKindMap;
552
553 // Codeview def_range type parsing.
554 enum CVDefRangeType {
555 CVDR_DEFRANGE = 0, // Placeholder
556 CVDR_DEFRANGE_REGISTER,
557 CVDR_DEFRANGE_FRAMEPOINTER_REL,
558 CVDR_DEFRANGE_SUBFIELD_REGISTER,
559 CVDR_DEFRANGE_REGISTER_REL
560 };
561
562 /// Maps Codeview def_range types --> CVDefRangeType enum, for
563 /// Codeview def_range types parsed by this class.
564 StringMap<CVDefRangeType> CVDefRangeTypeMap;
565
566 // ".ascii", ".asciz", ".string"
567 bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
568 bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
569 bool parseDirectiveValue(StringRef IDVal,
570 unsigned Size); // ".byte", ".long", ...
571 bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ...
572 bool parseDirectiveRealValue(StringRef IDVal,
573 const fltSemantics &); // ".single", ...
574 bool parseDirectiveFill(); // ".fill"
575 bool parseDirectiveZero(); // ".zero"
576 // ".set", ".equ", ".equiv", ".lto_set_conditional"
577 bool parseDirectiveSet(StringRef IDVal, AssignmentKind Kind);
578 bool parseDirectiveOrg(); // ".org"
579 // ".align{,32}", ".p2align{,w,l}"
580 bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);
581
582 // ".file", ".line", ".loc", ".stabs"
583 bool parseDirectiveFile(SMLoc DirectiveLoc);
584 bool parseDirectiveLine();
585 bool parseDirectiveLoc();
586 bool parseDirectiveStabs();
587
588 // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
589 // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
590 bool parseDirectiveCVFile();
591 bool parseDirectiveCVFuncId();
592 bool parseDirectiveCVInlineSiteId();
593 bool parseDirectiveCVLoc();
594 bool parseDirectiveCVLinetable();
595 bool parseDirectiveCVInlineLinetable();
596 bool parseDirectiveCVDefRange();
597 bool parseDirectiveCVString();
598 bool parseDirectiveCVStringTable();
599 bool parseDirectiveCVFileChecksums();
600 bool parseDirectiveCVFileChecksumOffset();
601 bool parseDirectiveCVFPOData();
602
603 // .cfi directives
604 bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
605 bool parseDirectiveCFIWindowSave(SMLoc DirectiveLoc);
606 bool parseDirectiveCFISections();
607 bool parseDirectiveCFIStartProc();
608 bool parseDirectiveCFIEndProc();
609 bool parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc);
610 bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
611 bool parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc);
612 bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
613 bool parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc);
614 bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
615 bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
616 bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
617 bool parseDirectiveCFIRememberState(SMLoc DirectiveLoc);
618 bool parseDirectiveCFIRestoreState(SMLoc DirectiveLoc);
619 bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
620 bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
621 bool parseDirectiveCFIEscape(SMLoc DirectiveLoc);
622 bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
623 bool parseDirectiveCFISignalFrame(SMLoc DirectiveLoc);
624 bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
625
626 // macro directives
627 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
628 bool parseDirectiveExitMacro(StringRef Directive);
629 bool parseDirectiveEndMacro(StringRef Directive);
630 bool parseDirectiveMacro(SMLoc DirectiveLoc);
631 bool parseDirectiveMacrosOnOff(StringRef Directive);
632 // alternate macro mode directives
633 bool parseDirectiveAltmacro(StringRef Directive);
634 // ".bundle_align_mode"
635 bool parseDirectiveBundleAlignMode();
636 // ".bundle_lock"
637 bool parseDirectiveBundleLock();
638 // ".bundle_unlock"
639 bool parseDirectiveBundleUnlock();
640
641 // ".space", ".skip"
642 bool parseDirectiveSpace(StringRef IDVal);
643
644 // ".dcb"
645 bool parseDirectiveDCB(StringRef IDVal, unsigned Size);
646 bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &);
647 // ".ds"
648 bool parseDirectiveDS(StringRef IDVal, unsigned Size);
649
650 // .sleb128 (Signed=true) and .uleb128 (Signed=false)
651 bool parseDirectiveLEB128(bool Signed);
652
653 /// Parse a directive like ".globl" which
654 /// accepts a single symbol (which should be a label or an external).
655 bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
656
657 bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
658
659 bool parseDirectiveAbort(); // ".abort"
660 bool parseDirectiveInclude(); // ".include"
661 bool parseDirectiveIncbin(); // ".incbin"
662
663 // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"
664 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
665 // ".ifb" or ".ifnb", depending on ExpectBlank.
666 bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
667 // ".ifc" or ".ifnc", depending on ExpectEqual.
668 bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
669 // ".ifeqs" or ".ifnes", depending on ExpectEqual.
670 bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);
671 // ".ifdef" or ".ifndef", depending on expect_defined
672 bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
673 bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
674 bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
675 bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
676 bool parseEscapedString(std::string &Data) override;
677 bool parseAngleBracketString(std::string &Data) override;
678
679 const MCExpr *applyModifierToExpr(const MCExpr *E,
681
682 // Macro-like directives
683 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
684 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
686 bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);
687 bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
688 bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
689 bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
690
691 // "_emit" or "__emit"
692 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
693 size_t Len);
694
695 // "align"
696 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
697
698 // "end"
699 bool parseDirectiveEnd(SMLoc DirectiveLoc);
700
701 // ".err" or ".error"
702 bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
703
704 // ".warning"
705 bool parseDirectiveWarning(SMLoc DirectiveLoc);
706
707 // .print <double-quotes-string>
708 bool parseDirectivePrint(SMLoc DirectiveLoc);
709
710 // .pseudoprobe
711 bool parseDirectivePseudoProbe();
712
713 // ".lto_discard"
714 bool parseDirectiveLTODiscard();
715
716 // Directives to support address-significance tables.
717 bool parseDirectiveAddrsig();
718 bool parseDirectiveAddrsigSym();
719
720 void initializeDirectiveKindMap();
721 void initializeCVDefRangeTypeMap();
722};
723
724class HLASMAsmParser final : public AsmParser {
725private:
726 MCAsmLexer &Lexer;
727 MCStreamer &Out;
728
729 void lexLeadingSpaces() {
730 while (Lexer.is(AsmToken::Space))
731 Lexer.Lex();
732 }
733
734 bool parseAsHLASMLabel(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI);
735 bool parseAsMachineInstruction(ParseStatementInfo &Info,
737
738public:
739 HLASMAsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
740 const MCAsmInfo &MAI, unsigned CB = 0)
741 : AsmParser(SM, Ctx, Out, MAI, CB), Lexer(getLexer()), Out(Out) {
742 Lexer.setSkipSpace(false);
743 Lexer.setAllowHashInIdentifier(true);
744 Lexer.setLexHLASMIntegers(true);
745 Lexer.setLexHLASMStrings(true);
746 }
747
748 ~HLASMAsmParser() { Lexer.setSkipSpace(true); }
749
750 bool parseStatement(ParseStatementInfo &Info,
751 MCAsmParserSemaCallback *SI) override;
752};
753
754} // end anonymous namespace
755
756namespace llvm {
757
759
766
767} // end namespace llvm
768
769enum { DEFAULT_ADDRSPACE = 0 };
770
771AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
772 const MCAsmInfo &MAI, unsigned CB = 0)
773 : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
774 CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {
775 HadError = false;
776 // Save the old handler.
777 SavedDiagHandler = SrcMgr.getDiagHandler();
778 SavedDiagContext = SrcMgr.getDiagContext();
779 // Set our own handler which calls the saved handler.
781 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
782 // Make MCStreamer aware of the StartTokLoc for locations in diagnostics.
783 Out.setStartTokLocPtr(&StartTokLoc);
784
785 // Initialize the platform / file format parser.
786 switch (Ctx.getObjectFileType()) {
788 PlatformParser.reset(createCOFFAsmParser());
789 break;
791 PlatformParser.reset(createDarwinAsmParser());
792 IsDarwin = true;
793 break;
794 case MCContext::IsELF:
795 PlatformParser.reset(createELFAsmParser());
796 break;
798 PlatformParser.reset(createGOFFAsmParser());
799 break;
802 "Need to implement createSPIRVAsmParser for SPIRV format.");
803 break;
805 PlatformParser.reset(createWasmAsmParser());
806 break;
808 PlatformParser.reset(createXCOFFAsmParser());
809 break;
811 report_fatal_error("DXContainer is not supported yet");
812 break;
813 }
814
815 PlatformParser->Initialize(*this);
816 initializeDirectiveKindMap();
817 initializeCVDefRangeTypeMap();
818
819 NumOfMacroInstantiations = 0;
820}
821
822AsmParser::~AsmParser() {
823 assert((HadError || ActiveMacros.empty()) &&
824 "Unexpected active macro instantiation!");
825
826 // Remove MCStreamer's reference to the parser SMLoc.
827 Out.setStartTokLocPtr(nullptr);
828 // Restore the saved diagnostics handler and context for use during
829 // finalization.
830 SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
831}
832
833void AsmParser::printMacroInstantiations() {
834 // Print the active macro instantiation stack.
835 for (MacroInstantiation *M : reverse(ActiveMacros))
836 printMessage(M->InstantiationLoc, SourceMgr::DK_Note,
837 "while in macro instantiation");
838}
839
840void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
841 printPendingErrors();
842 printMessage(L, SourceMgr::DK_Note, Msg, Range);
843 printMacroInstantiations();
844}
845
846bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
847 if(getTargetParser().getTargetOptions().MCNoWarn)
848 return false;
849 if (getTargetParser().getTargetOptions().MCFatalWarnings)
850 return Error(L, Msg, Range);
851 printMessage(L, SourceMgr::DK_Warning, Msg, Range);
852 printMacroInstantiations();
853 return false;
854}
855
856bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
857 HadError = true;
858 printMessage(L, SourceMgr::DK_Error, Msg, Range);
859 printMacroInstantiations();
860 return true;
861}
862
863bool AsmParser::enterIncludeFile(const std::string &Filename) {
864 std::string IncludedFile;
865 unsigned NewBuf =
866 SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
867 if (!NewBuf)
868 return true;
869
870 CurBuffer = NewBuf;
871 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
872 return false;
873}
874
875/// Process the specified .incbin file by searching for it in the include paths
876/// then just emitting the byte contents of the file to the streamer. This
877/// returns true on failure.
878bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
879 const MCExpr *Count, SMLoc Loc) {
880 std::string IncludedFile;
881 unsigned NewBuf =
882 SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
883 if (!NewBuf)
884 return true;
885
886 // Pick up the bytes from the file and emit them.
887 StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();
888 Bytes = Bytes.drop_front(Skip);
889 if (Count) {
890 int64_t Res;
891 if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
892 return Error(Loc, "expected absolute expression");
893 if (Res < 0)
894 return Warning(Loc, "negative count has no effect");
895 Bytes = Bytes.take_front(Res);
896 }
897 getStreamer().emitBytes(Bytes);
898 return false;
899}
900
901void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
902 CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
903 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
904 Loc.getPointer());
905}
906
907const AsmToken &AsmParser::Lex() {
908 if (Lexer.getTok().is(AsmToken::Error))
909 Error(Lexer.getErrLoc(), Lexer.getErr());
910
911 // if it's a end of statement with a comment in it
912 if (getTok().is(AsmToken::EndOfStatement)) {
913 // if this is a line comment output it.
914 if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
915 getTok().getString().front() != '\r' && MAI.preserveAsmComments())
916 Out.addExplicitComment(Twine(getTok().getString()));
917 }
918
919 const AsmToken *tok = &Lexer.Lex();
920
921 // Parse comments here to be deferred until end of next statement.
922 while (tok->is(AsmToken::Comment)) {
923 if (MAI.preserveAsmComments())
925 tok = &Lexer.Lex();
926 }
927
928 if (tok->is(AsmToken::Eof)) {
929 // If this is the end of an included file, pop the parent file off the
930 // include stack.
931 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
932 if (ParentIncludeLoc != SMLoc()) {
933 jumpToLoc(ParentIncludeLoc);
934 return Lex();
935 }
936 }
937
938 return *tok;
939}
940
941bool AsmParser::enabledGenDwarfForAssembly() {
942 // Check whether the user specified -g.
943 if (!getContext().getGenDwarfForAssembly())
944 return false;
945 // If we haven't encountered any .file directives (which would imply that
946 // the assembler source was produced with debug info already) then emit one
947 // describing the assembler source file itself.
948 if (getContext().getGenDwarfFileNumber() == 0) {
949 // Use the first #line directive for this, if any. It's preprocessed, so
950 // there is no checksum, and of course no source directive.
951 if (!FirstCppHashFilename.empty())
952 getContext().setMCLineTableRootFile(
953 /*CUID=*/0, getContext().getCompilationDir(), FirstCppHashFilename,
954 /*Cksum=*/std::nullopt, /*Source=*/std::nullopt);
955 const MCDwarfFile &RootFile =
956 getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
957 getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
958 /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
959 RootFile.Checksum, RootFile.Source));
960 }
961 return true;
962}
963
964bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
965 LTODiscardSymbols.clear();
966
967 // Create the initial section, if requested.
968 if (!NoInitialTextSection)
969 Out.initSections(false, getTargetParser().getSTI());
970
971 // Prime the lexer.
972 Lex();
973
974 HadError = false;
975 AsmCond StartingCondState = TheCondState;
976 SmallVector<AsmRewrite, 4> AsmStrRewrites;
977
978 // If we are generating dwarf for assembly source files save the initial text
979 // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't
980 // emitting any actual debug info yet and haven't had a chance to parse any
981 // embedded .file directives.)
982 if (getContext().getGenDwarfForAssembly()) {
983 MCSection *Sec = getStreamer().getCurrentSectionOnly();
984 if (!Sec->getBeginSymbol()) {
985 MCSymbol *SectionStartSym = getContext().createTempSymbol();
986 getStreamer().emitLabel(SectionStartSym);
987 Sec->setBeginSymbol(SectionStartSym);
988 }
989 bool InsertResult = getContext().addGenDwarfSection(Sec);
990 assert(InsertResult && ".text section should not have debug info yet");
991 (void)InsertResult;
992 }
993
994 getTargetParser().onBeginOfFile();
995
996 // While we have input, parse each statement.
997 while (Lexer.isNot(AsmToken::Eof)) {
998 ParseStatementInfo Info(&AsmStrRewrites);
999 bool Parsed = parseStatement(Info, nullptr);
1000
1001 // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
1002 // for printing ErrMsg via Lex() only if no (presumably better) parser error
1003 // exists.
1004 if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
1005 Lex();
1006 }
1007
1008 // parseStatement returned true so may need to emit an error.
1009 printPendingErrors();
1010
1011 // Skipping to the next line if needed.
1012 if (Parsed && !getLexer().isAtStartOfStatement())
1013 eatToEndOfStatement();
1014 }
1015
1016 getTargetParser().onEndOfFile();
1017 printPendingErrors();
1018
1019 // All errors should have been emitted.
1020 assert(!hasPendingError() && "unexpected error from parseStatement");
1021
1022 getTargetParser().flushPendingInstructions(getStreamer());
1023
1024 if (TheCondState.TheCond != StartingCondState.TheCond ||
1025 TheCondState.Ignore != StartingCondState.Ignore)
1026 printError(getTok().getLoc(), "unmatched .ifs or .elses");
1027 // Check to see there are no empty DwarfFile slots.
1028 const auto &LineTables = getContext().getMCDwarfLineTables();
1029 if (!LineTables.empty()) {
1030 unsigned Index = 0;
1031 for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {
1032 if (File.Name.empty() && Index != 0)
1033 printError(getTok().getLoc(), "unassigned file number: " +
1034 Twine(Index) +
1035 " for .file directives");
1036 ++Index;
1037 }
1038 }
1039
1040 // Check to see that all assembler local symbols were actually defined.
1041 // Targets that don't do subsections via symbols may not want this, though,
1042 // so conservatively exclude them. Only do this if we're finalizing, though,
1043 // as otherwise we won't necessarilly have seen everything yet.
1044 if (!NoFinalize) {
1045 if (MAI.hasSubsectionsViaSymbols()) {
1046 for (const auto &TableEntry : getContext().getSymbols()) {
1047 MCSymbol *Sym = TableEntry.getValue();
1048 // Variable symbols may not be marked as defined, so check those
1049 // explicitly. If we know it's a variable, we have a definition for
1050 // the purposes of this check.
1051 if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
1052 // FIXME: We would really like to refer back to where the symbol was
1053 // first referenced for a source location. We need to add something
1054 // to track that. Currently, we just point to the end of the file.
1055 printError(getTok().getLoc(), "assembler local symbol '" +
1056 Sym->getName() + "' not defined");
1057 }
1058 }
1059
1060 // Temporary symbols like the ones for directional jumps don't go in the
1061 // symbol table. They also need to be diagnosed in all (final) cases.
1062 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1063 if (std::get<2>(LocSym)->isUndefined()) {
1064 // Reset the state of any "# line file" directives we've seen to the
1065 // context as it was at the diagnostic site.
1066 CppHashInfo = std::get<1>(LocSym);
1067 printError(std::get<0>(LocSym), "directional label undefined");
1068 }
1069 }
1070 }
1071 // Finalize the output stream if there are no errors and if the client wants
1072 // us to.
1073 if (!HadError && !NoFinalize) {
1074 if (auto *TS = Out.getTargetStreamer())
1075 TS->emitConstantPools();
1076
1077 Out.finish(Lexer.getLoc());
1078 }
1079
1080 return HadError || getContext().hadError();
1081}
1082
1083bool AsmParser::checkForValidSection() {
1084 if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
1085 Out.initSections(false, getTargetParser().getSTI());
1086 return Error(getTok().getLoc(),
1087 "expected section directive before assembly directive");
1088 }
1089 return false;
1090}
1091
1092/// Throw away the rest of the line for testing purposes.
1093void AsmParser::eatToEndOfStatement() {
1094 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
1095 Lexer.Lex();
1096
1097 // Eat EOL.
1098 if (Lexer.is(AsmToken::EndOfStatement))
1099 Lexer.Lex();
1100}
1101
1102StringRef AsmParser::parseStringToEndOfStatement() {
1103 const char *Start = getTok().getLoc().getPointer();
1104
1105 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
1106 Lexer.Lex();
1107
1108 const char *End = getTok().getLoc().getPointer();
1109 return StringRef(Start, End - Start);
1110}
1111
1112StringRef AsmParser::parseStringToComma() {
1113 const char *Start = getTok().getLoc().getPointer();
1114
1115 while (Lexer.isNot(AsmToken::EndOfStatement) &&
1116 Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof))
1117 Lexer.Lex();
1118
1119 const char *End = getTok().getLoc().getPointer();
1120 return StringRef(Start, End - Start);
1121}
1122
1123/// Parse a paren expression and return it.
1124/// NOTE: This assumes the leading '(' has already been consumed.
1125///
1126/// parenexpr ::= expr)
1127///
1128bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1129 if (parseExpression(Res))
1130 return true;
1131 EndLoc = Lexer.getTok().getEndLoc();
1132 return parseRParen();
1133}
1134
1135/// Parse a bracket expression and return it.
1136/// NOTE: This assumes the leading '[' has already been consumed.
1137///
1138/// bracketexpr ::= expr]
1139///
1140bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1141 if (parseExpression(Res))
1142 return true;
1143 EndLoc = getTok().getEndLoc();
1144 if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
1145 return true;
1146 return false;
1147}
1148
1149/// Parse a primary expression and return it.
1150/// primaryexpr ::= (parenexpr
1151/// primaryexpr ::= symbol
1152/// primaryexpr ::= number
1153/// primaryexpr ::= '.'
1154/// primaryexpr ::= ~,+,- primaryexpr
1155bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
1156 AsmTypeInfo *TypeInfo) {
1157 SMLoc FirstTokenLoc = getLexer().getLoc();
1158 AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
1159 switch (FirstTokenKind) {
1160 default:
1161 return TokError("unknown token in expression");
1162 // If we have an error assume that we've already handled it.
1163 case AsmToken::Error:
1164 return true;
1165 case AsmToken::Exclaim:
1166 Lex(); // Eat the operator.
1167 if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
1168 return true;
1169 Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
1170 return false;
1171 case AsmToken::Dollar:
1172 case AsmToken::Star:
1173 case AsmToken::At:
1174 case AsmToken::String:
1175 case AsmToken::Identifier: {
1177 if (parseIdentifier(Identifier)) {
1178 // We may have failed but '$'|'*' may be a valid token in context of
1179 // the current PC.
1180 if (getTok().is(AsmToken::Dollar) || getTok().is(AsmToken::Star)) {
1181 bool ShouldGenerateTempSymbol = false;
1182 if ((getTok().is(AsmToken::Dollar) && MAI.getDollarIsPC()) ||
1183 (getTok().is(AsmToken::Star) && MAI.getStarIsPC()))
1184 ShouldGenerateTempSymbol = true;
1185
1186 if (!ShouldGenerateTempSymbol)
1187 return Error(FirstTokenLoc, "invalid token in expression");
1188
1189 // Eat the '$'|'*' token.
1190 Lex();
1191 // This is either a '$'|'*' reference, which references the current PC.
1192 // Emit a temporary label to the streamer and refer to it.
1193 MCSymbol *Sym = Ctx.createTempSymbol();
1194 Out.emitLabel(Sym);
1196 getContext());
1197 EndLoc = FirstTokenLoc;
1198 return false;
1199 }
1200 }
1201 // Parse symbol variant
1202 std::pair<StringRef, StringRef> Split;
1203 if (!MAI.useParensForSymbolVariant()) {
1204 if (FirstTokenKind == AsmToken::String) {
1205 if (Lexer.is(AsmToken::At)) {
1206 Lex(); // eat @
1207 SMLoc AtLoc = getLexer().getLoc();
1208 StringRef VName;
1209 if (parseIdentifier(VName))
1210 return Error(AtLoc, "expected symbol variant after '@'");
1211
1212 Split = std::make_pair(Identifier, VName);
1213 }
1214 } else {
1215 Split = Identifier.split('@');
1216 }
1217 } else if (Lexer.is(AsmToken::LParen)) {
1218 Lex(); // eat '('.
1219 StringRef VName;
1220 parseIdentifier(VName);
1221 if (parseRParen())
1222 return true;
1223 Split = std::make_pair(Identifier, VName);
1224 }
1225
1226 EndLoc = SMLoc::getFromPointer(Identifier.end());
1227
1228 // This is a symbol reference.
1230 if (SymbolName.empty())
1231 return Error(getLexer().getLoc(), "expected a symbol reference");
1232
1234
1235 // Lookup the symbol variant if used.
1236 if (!Split.second.empty()) {
1237 Variant = getTargetParser().getVariantKindForName(Split.second);
1238 if (Variant != MCSymbolRefExpr::VK_Invalid) {
1239 SymbolName = Split.first;
1240 } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
1242 } else {
1243 return Error(SMLoc::getFromPointer(Split.second.begin()),
1244 "invalid variant '" + Split.second + "'");
1245 }
1246 }
1247
1248 MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
1249 if (!Sym)
1250 Sym = getContext().getOrCreateSymbol(
1251 MAI.shouldEmitLabelsInUpperCase() ? SymbolName.upper() : SymbolName);
1252
1253 // If this is an absolute variable reference, substitute it now to preserve
1254 // semantics in the face of reassignment.
1255 if (Sym->isVariable()) {
1256 auto V = Sym->getVariableValue(/*SetUsed*/ false);
1257 bool DoInline = isa<MCConstantExpr>(V) && !Variant;
1258 if (auto TV = dyn_cast<MCTargetExpr>(V))
1259 DoInline = TV->inlineAssignedExpr();
1260 if (DoInline) {
1261 if (Variant)
1262 return Error(EndLoc, "unexpected modifier on variable reference");
1263 Res = Sym->getVariableValue(/*SetUsed*/ false);
1264 return false;
1265 }
1266 }
1267
1268 // Otherwise create a symbol ref.
1269 Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
1270 return false;
1271 }
1272 case AsmToken::BigNum:
1273 return TokError("literal value out of range for directive");
1274 case AsmToken::Integer: {
1275 SMLoc Loc = getTok().getLoc();
1276 int64_t IntVal = getTok().getIntVal();
1277 Res = MCConstantExpr::create(IntVal, getContext());
1278 EndLoc = Lexer.getTok().getEndLoc();
1279 Lex(); // Eat token.
1280 // Look for 'b' or 'f' following an Integer as a directional label
1281 if (Lexer.getKind() == AsmToken::Identifier) {
1282 StringRef IDVal = getTok().getString();
1283 // Lookup the symbol variant if used.
1284 std::pair<StringRef, StringRef> Split = IDVal.split('@');
1286 if (Split.first.size() != IDVal.size()) {
1288 if (Variant == MCSymbolRefExpr::VK_Invalid)
1289 return TokError("invalid variant '" + Split.second + "'");
1290 IDVal = Split.first;
1291 }
1292 if (IDVal == "f" || IDVal == "b") {
1293 MCSymbol *Sym =
1294 Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
1295 Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
1296 if (IDVal == "b" && Sym->isUndefined())
1297 return Error(Loc, "directional label undefined");
1298 DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
1299 EndLoc = Lexer.getTok().getEndLoc();
1300 Lex(); // Eat identifier.
1301 }
1302 }
1303 return false;
1304 }
1305 case AsmToken::Real: {
1306 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1307 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
1308 Res = MCConstantExpr::create(IntVal, getContext());
1309 EndLoc = Lexer.getTok().getEndLoc();
1310 Lex(); // Eat token.
1311 return false;
1312 }
1313 case AsmToken::Dot: {
1314 if (!MAI.getDotIsPC())
1315 return TokError("cannot use . as current PC");
1316
1317 // This is a '.' reference, which references the current PC. Emit a
1318 // temporary label to the streamer and refer to it.
1319 MCSymbol *Sym = Ctx.createTempSymbol();
1320 Out.emitLabel(Sym);
1322 EndLoc = Lexer.getTok().getEndLoc();
1323 Lex(); // Eat identifier.
1324 return false;
1325 }
1326 case AsmToken::LParen:
1327 Lex(); // Eat the '('.
1328 return parseParenExpr(Res, EndLoc);
1329 case AsmToken::LBrac:
1330 if (!PlatformParser->HasBracketExpressions())
1331 return TokError("brackets expression not supported on this target");
1332 Lex(); // Eat the '['.
1333 return parseBracketExpr(Res, EndLoc);
1334 case AsmToken::Minus:
1335 Lex(); // Eat the operator.
1336 if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
1337 return true;
1338 Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
1339 return false;
1340 case AsmToken::Plus:
1341 Lex(); // Eat the operator.
1342 if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
1343 return true;
1344 Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
1345 return false;
1346 case AsmToken::Tilde:
1347 Lex(); // Eat the operator.
1348 if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
1349 return true;
1350 Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
1351 return false;
1352 // MIPS unary expression operators. The lexer won't generate these tokens if
1353 // MCAsmInfo::HasMipsExpressions is false for the target.
1378 Lex(); // Eat the operator.
1379 if (Lexer.isNot(AsmToken::LParen))
1380 return TokError("expected '(' after operator");
1381 Lex(); // Eat the operator.
1382 if (parseExpression(Res, EndLoc))
1383 return true;
1384 if (parseRParen())
1385 return true;
1386 Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
1387 return !Res;
1388 }
1389}
1390
1391bool AsmParser::parseExpression(const MCExpr *&Res) {
1392 SMLoc EndLoc;
1393 return parseExpression(Res, EndLoc);
1394}
1395
1396const MCExpr *
1397AsmParser::applyModifierToExpr(const MCExpr *E,
1399 // Ask the target implementation about this expression first.
1400 const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx);
1401 if (NewE)
1402 return NewE;
1403 // Recurse over the given expression, rebuilding it to apply the given variant
1404 // if there is exactly one symbol.
1405 switch (E->getKind()) {
1406 case MCExpr::Target:
1407 case MCExpr::Constant:
1408 return nullptr;
1409
1410 case MCExpr::SymbolRef: {
1411 const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
1412
1413 if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
1414 TokError("invalid variant on expression '" + getTok().getIdentifier() +
1415 "' (already modified)");
1416 return E;
1417 }
1418
1419 return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext());
1420 }
1421
1422 case MCExpr::Unary: {
1423 const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
1424 const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant);
1425 if (!Sub)
1426 return nullptr;
1427 return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext());
1428 }
1429
1430 case MCExpr::Binary: {
1431 const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
1432 const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant);
1433 const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant);
1434
1435 if (!LHS && !RHS)
1436 return nullptr;
1437
1438 if (!LHS)
1439 LHS = BE->getLHS();
1440 if (!RHS)
1441 RHS = BE->getRHS();
1442
1443 return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext());
1444 }
1445 }
1446
1447 llvm_unreachable("Invalid expression kind!");
1448}
1449
1450/// This function checks if the next token is <string> type or arithmetic.
1451/// string that begin with character '<' must end with character '>'.
1452/// otherwise it is arithmetics.
1453/// If the function returns a 'true' value,
1454/// the End argument will be filled with the last location pointed to the '>'
1455/// character.
1456
1457/// There is a gap between the AltMacro's documentation and the single quote
1458/// implementation. GCC does not fully support this feature and so we will not
1459/// support it.
1460/// TODO: Adding single quote as a string.
1461static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
1462 assert((StrLoc.getPointer() != nullptr) &&
1463 "Argument to the function cannot be a NULL value");
1464 const char *CharPtr = StrLoc.getPointer();
1465 while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
1466 (*CharPtr != '\0')) {
1467 if (*CharPtr == '!')
1468 CharPtr++;
1469 CharPtr++;
1470 }
1471 if (*CharPtr == '>') {
1472 EndLoc = StrLoc.getFromPointer(CharPtr + 1);
1473 return true;
1474 }
1475 return false;
1476}
1477
1478/// creating a string without the escape characters '!'.
1479static std::string angleBracketString(StringRef AltMacroStr) {
1480 std::string Res;
1481 for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
1482 if (AltMacroStr[Pos] == '!')
1483 Pos++;
1484 Res += AltMacroStr[Pos];
1485 }
1486 return Res;
1487}
1488
1489/// Parse an expression and return it.
1490///
1491/// expr ::= expr &&,|| expr -> lowest.
1492/// expr ::= expr |,^,&,! expr
1493/// expr ::= expr ==,!=,<>,<,<=,>,>= expr
1494/// expr ::= expr <<,>> expr
1495/// expr ::= expr +,- expr
1496/// expr ::= expr *,/,% expr -> highest.
1497/// expr ::= primaryexpr
1498///
1499bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
1500 // Parse the expression.
1501 Res = nullptr;
1502 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1503 parseBinOpRHS(1, Res, EndLoc))
1504 return true;
1505
1506 // As a special case, we support 'a op b @ modifier' by rewriting the
1507 // expression to include the modifier. This is inefficient, but in general we
1508 // expect users to use 'a@modifier op b'.
1509 if (parseOptionalToken(AsmToken::At)) {
1510 if (Lexer.isNot(AsmToken::Identifier))
1511 return TokError("unexpected symbol modifier following '@'");
1512
1514 MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
1515 if (Variant == MCSymbolRefExpr::VK_Invalid)
1516 return TokError("invalid variant '" + getTok().getIdentifier() + "'");
1517
1518 const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant);
1519 if (!ModifiedRes) {
1520 return TokError("invalid modifier '" + getTok().getIdentifier() +
1521 "' (no symbols present)");
1522 }
1523
1524 Res = ModifiedRes;
1525 Lex();
1526 }
1527
1528 // Try to constant fold it up front, if possible. Do not exploit
1529 // assembler here.
1530 int64_t Value;
1531 if (Res->evaluateAsAbsolute(Value))
1532 Res = MCConstantExpr::create(Value, getContext());
1533
1534 return false;
1535}
1536
1537bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
1538 Res = nullptr;
1539 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1540}
1541
1542bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
1543 SMLoc &EndLoc) {
1544 if (parseParenExpr(Res, EndLoc))
1545 return true;
1546
1547 for (; ParenDepth > 0; --ParenDepth) {
1548 if (parseBinOpRHS(1, Res, EndLoc))
1549 return true;
1550
1551 // We don't Lex() the last RParen.
1552 // This is the same behavior as parseParenExpression().
1553 if (ParenDepth - 1 > 0) {
1554 EndLoc = getTok().getEndLoc();
1555 if (parseRParen())
1556 return true;
1557 }
1558 }
1559 return false;
1560}
1561
1562bool AsmParser::parseAbsoluteExpression(int64_t &Res) {
1563 const MCExpr *Expr;
1564
1565 SMLoc StartLoc = Lexer.getLoc();
1566 if (parseExpression(Expr))
1567 return true;
1568
1569 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1570 return Error(StartLoc, "expected absolute expression");
1571
1572 return false;
1573}
1574
1577 bool ShouldUseLogicalShr) {
1578 switch (K) {
1579 default:
1580 return 0; // not a binop.
1581
1582 // Lowest Precedence: &&, ||
1583 case AsmToken::AmpAmp:
1584 Kind = MCBinaryExpr::LAnd;
1585 return 1;
1586 case AsmToken::PipePipe:
1587 Kind = MCBinaryExpr::LOr;
1588 return 1;
1589
1590 // Low Precedence: |, &, ^
1591 case AsmToken::Pipe:
1592 Kind = MCBinaryExpr::Or;
1593 return 2;
1594 case AsmToken::Caret:
1595 Kind = MCBinaryExpr::Xor;
1596 return 2;
1597 case AsmToken::Amp:
1598 Kind = MCBinaryExpr::And;
1599 return 2;
1600
1601 // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
1603 Kind = MCBinaryExpr::EQ;
1604 return 3;
1607 Kind = MCBinaryExpr::NE;
1608 return 3;
1609 case AsmToken::Less:
1610 Kind = MCBinaryExpr::LT;
1611 return 3;
1613 Kind = MCBinaryExpr::LTE;
1614 return 3;
1615 case AsmToken::Greater:
1616 Kind = MCBinaryExpr::GT;
1617 return 3;
1619 Kind = MCBinaryExpr::GTE;
1620 return 3;
1621
1622 // Intermediate Precedence: <<, >>
1623 case AsmToken::LessLess:
1624 Kind = MCBinaryExpr::Shl;
1625 return 4;
1627 Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
1628 return 4;
1629
1630 // High Intermediate Precedence: +, -
1631 case AsmToken::Plus:
1632 Kind = MCBinaryExpr::Add;
1633 return 5;
1634 case AsmToken::Minus:
1635 Kind = MCBinaryExpr::Sub;
1636 return 5;
1637
1638 // Highest Precedence: *, /, %
1639 case AsmToken::Star:
1640 Kind = MCBinaryExpr::Mul;
1641 return 6;
1642 case AsmToken::Slash:
1643 Kind = MCBinaryExpr::Div;
1644 return 6;
1645 case AsmToken::Percent:
1646 Kind = MCBinaryExpr::Mod;
1647 return 6;
1648 }
1649}
1650
1651static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI,
1654 bool ShouldUseLogicalShr) {
1655 switch (K) {
1656 default:
1657 return 0; // not a binop.
1658
1659 // Lowest Precedence: &&, ||
1660 case AsmToken::AmpAmp:
1661 Kind = MCBinaryExpr::LAnd;
1662 return 2;
1663 case AsmToken::PipePipe:
1664 Kind = MCBinaryExpr::LOr;
1665 return 1;
1666
1667 // Low Precedence: ==, !=, <>, <, <=, >, >=
1669 Kind = MCBinaryExpr::EQ;
1670 return 3;
1673 Kind = MCBinaryExpr::NE;
1674 return 3;
1675 case AsmToken::Less:
1676 Kind = MCBinaryExpr::LT;
1677 return 3;
1679 Kind = MCBinaryExpr::LTE;
1680 return 3;
1681 case AsmToken::Greater:
1682 Kind = MCBinaryExpr::GT;
1683 return 3;
1685 Kind = MCBinaryExpr::GTE;
1686 return 3;
1687
1688 // Low Intermediate Precedence: +, -
1689 case AsmToken::Plus:
1690 Kind = MCBinaryExpr::Add;
1691 return 4;
1692 case AsmToken::Minus:
1693 Kind = MCBinaryExpr::Sub;
1694 return 4;
1695
1696 // High Intermediate Precedence: |, !, &, ^
1697 //
1698 case AsmToken::Pipe:
1699 Kind = MCBinaryExpr::Or;
1700 return 5;
1701 case AsmToken::Exclaim:
1702 // Hack to support ARM compatible aliases (implied 'sp' operand in 'srs*'
1703 // instructions like 'srsda #31!') and not parse ! as an infix operator.
1704 if (MAI.getCommentString() == "@")
1705 return 0;
1706 Kind = MCBinaryExpr::OrNot;
1707 return 5;
1708 case AsmToken::Caret:
1709 Kind = MCBinaryExpr::Xor;
1710 return 5;
1711 case AsmToken::Amp:
1712 Kind = MCBinaryExpr::And;
1713 return 5;
1714
1715 // Highest Precedence: *, /, %, <<, >>
1716 case AsmToken::Star:
1717 Kind = MCBinaryExpr::Mul;
1718 return 6;
1719 case AsmToken::Slash:
1720 Kind = MCBinaryExpr::Div;
1721 return 6;
1722 case AsmToken::Percent:
1723 Kind = MCBinaryExpr::Mod;
1724 return 6;
1725 case AsmToken::LessLess:
1726 Kind = MCBinaryExpr::Shl;
1727 return 6;
1729 Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
1730 return 6;
1731 }
1732}
1733
1734unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
1735 MCBinaryExpr::Opcode &Kind) {
1736 bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
1737 return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)
1738 : getGNUBinOpPrecedence(MAI, K, Kind, ShouldUseLogicalShr);
1739}
1740
1741/// Parse all binary operators with precedence >= 'Precedence'.
1742/// Res contains the LHS of the expression on input.
1743bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
1744 SMLoc &EndLoc) {
1745 SMLoc StartLoc = Lexer.getLoc();
1746 while (true) {
1748 unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
1749
1750 // If the next token is lower precedence than we are allowed to eat, return
1751 // successfully with what we ate already.
1752 if (TokPrec < Precedence)
1753 return false;
1754
1755 Lex();
1756
1757 // Eat the next primary expression.
1758 const MCExpr *RHS;
1759 if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
1760 return true;
1761
1762 // If BinOp binds less tightly with RHS than the operator after RHS, let
1763 // the pending operator take RHS as its LHS.
1765 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1766 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
1767 return true;
1768
1769 // Merge LHS and RHS according to operator.
1770 Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
1771 }
1772}
1773
1774/// ParseStatement:
1775/// ::= EndOfStatement
1776/// ::= Label* Directive ...Operands... EndOfStatement
1777/// ::= Label* Identifier OperandList* EndOfStatement
1778bool AsmParser::parseStatement(ParseStatementInfo &Info,
1780 assert(!hasPendingError() && "parseStatement started with pending error");
1781 // Eat initial spaces and comments
1782 while (Lexer.is(AsmToken::Space))
1783 Lex();
1784 if (Lexer.is(AsmToken::EndOfStatement)) {
1785 // if this is a line comment we can drop it safely
1786 if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
1787 getTok().getString().front() == '\n')
1788 Out.addBlankLine();
1789 Lex();
1790 return false;
1791 }
1792 // Statements always start with an identifier.
1793 AsmToken ID = getTok();
1794 SMLoc IDLoc = ID.getLoc();
1795 StringRef IDVal;
1796 int64_t LocalLabelVal = -1;
1797 StartTokLoc = ID.getLoc();
1798 if (Lexer.is(AsmToken::HashDirective))
1799 return parseCppHashLineFilenameComment(IDLoc,
1800 !isInsideMacroInstantiation());
1801
1802 // Allow an integer followed by a ':' as a directional local label.
1803 if (Lexer.is(AsmToken::Integer)) {
1804 LocalLabelVal = getTok().getIntVal();
1805 if (LocalLabelVal < 0) {
1806 if (!TheCondState.Ignore) {
1807 Lex(); // always eat a token
1808 return Error(IDLoc, "unexpected token at start of statement");
1809 }
1810 IDVal = "";
1811 } else {
1812 IDVal = getTok().getString();
1813 Lex(); // Consume the integer token to be used as an identifier token.
1814 if (Lexer.getKind() != AsmToken::Colon) {
1815 if (!TheCondState.Ignore) {
1816 Lex(); // always eat a token
1817 return Error(IDLoc, "unexpected token at start of statement");
1818 }
1819 }
1820 }
1821 } else if (Lexer.is(AsmToken::Dot)) {
1822 // Treat '.' as a valid identifier in this context.
1823 Lex();
1824 IDVal = ".";
1825 } else if (Lexer.is(AsmToken::LCurly)) {
1826 // Treat '{' as a valid identifier in this context.
1827 Lex();
1828 IDVal = "{";
1829
1830 } else if (Lexer.is(AsmToken::RCurly)) {
1831 // Treat '}' as a valid identifier in this context.
1832 Lex();
1833 IDVal = "}";
1834 } else if (Lexer.is(AsmToken::Star) &&
1835 getTargetParser().starIsStartOfStatement()) {
1836 // Accept '*' as a valid start of statement.
1837 Lex();
1838 IDVal = "*";
1839 } else if (parseIdentifier(IDVal)) {
1840 if (!TheCondState.Ignore) {
1841 Lex(); // always eat a token
1842 return Error(IDLoc, "unexpected token at start of statement");
1843 }
1844 IDVal = "";
1845 }
1846
1847 // Handle conditional assembly here before checking for skipping. We
1848 // have to do this so that .endif isn't skipped in a ".if 0" block for
1849 // example.
1851 DirectiveKindMap.find(IDVal.lower());
1852 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1853 ? DK_NO_DIRECTIVE
1854 : DirKindIt->getValue();
1855 switch (DirKind) {
1856 default:
1857 break;
1858 case DK_IF:
1859 case DK_IFEQ:
1860 case DK_IFGE:
1861 case DK_IFGT:
1862 case DK_IFLE:
1863 case DK_IFLT:
1864 case DK_IFNE:
1865 return parseDirectiveIf(IDLoc, DirKind);
1866 case DK_IFB:
1867 return parseDirectiveIfb(IDLoc, true);
1868 case DK_IFNB:
1869 return parseDirectiveIfb(IDLoc, false);
1870 case DK_IFC:
1871 return parseDirectiveIfc(IDLoc, true);
1872 case DK_IFEQS:
1873 return parseDirectiveIfeqs(IDLoc, true);
1874 case DK_IFNC:
1875 return parseDirectiveIfc(IDLoc, false);
1876 case DK_IFNES:
1877 return parseDirectiveIfeqs(IDLoc, false);
1878 case DK_IFDEF:
1879 return parseDirectiveIfdef(IDLoc, true);
1880 case DK_IFNDEF:
1881 case DK_IFNOTDEF:
1882 return parseDirectiveIfdef(IDLoc, false);
1883 case DK_ELSEIF:
1884 return parseDirectiveElseIf(IDLoc);
1885 case DK_ELSE:
1886 return parseDirectiveElse(IDLoc);
1887 case DK_ENDIF:
1888 return parseDirectiveEndIf(IDLoc);
1889 }
1890
1891 // Ignore the statement if in the middle of inactive conditional
1892 // (e.g. ".if 0").
1893 if (TheCondState.Ignore) {
1894 eatToEndOfStatement();
1895 return false;
1896 }
1897
1898 // FIXME: Recurse on local labels?
1899
1900 // Check for a label.
1901 // ::= identifier ':'
1902 // ::= number ':'
1903 if (Lexer.is(AsmToken::Colon) && getTargetParser().isLabel(ID)) {
1904 if (checkForValidSection())
1905 return true;
1906
1907 Lex(); // Consume the ':'.
1908
1909 // Diagnose attempt to use '.' as a label.
1910 if (IDVal == ".")
1911 return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
1912
1913 // Diagnose attempt to use a variable as a label.
1914 //
1915 // FIXME: Diagnostics. Note the location of the definition as a label.
1916 // FIXME: This doesn't diagnose assignment to a symbol which has been
1917 // implicitly marked as external.
1918 MCSymbol *Sym;
1919 if (LocalLabelVal == -1) {
1920 if (ParsingMSInlineAsm && SI) {
1921 StringRef RewrittenLabel =
1922 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
1923 assert(!RewrittenLabel.empty() &&
1924 "We should have an internal name here.");
1925 Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
1926 RewrittenLabel);
1927 IDVal = RewrittenLabel;
1928 }
1929 Sym = getContext().getOrCreateSymbol(IDVal);
1930 } else
1931 Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
1932 // End of Labels should be treated as end of line for lexing
1933 // purposes but that information is not available to the Lexer who
1934 // does not understand Labels. This may cause us to see a Hash
1935 // here instead of a preprocessor line comment.
1936 if (getTok().is(AsmToken::Hash)) {
1937 StringRef CommentStr = parseStringToEndOfStatement();
1938 Lexer.Lex();
1939 Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
1940 }
1941
1942 // Consume any end of statement token, if present, to avoid spurious
1943 // addBlankLine calls().
1944 if (getTok().is(AsmToken::EndOfStatement)) {
1945 Lex();
1946 }
1947
1948 if (MAI.hasSubsectionsViaSymbols() && CFIStartProcLoc &&
1949 Sym->isExternal() && !cast<MCSymbolMachO>(Sym)->isAltEntry())
1950 return Error(StartTokLoc, "non-private labels cannot appear between "
1951 ".cfi_startproc / .cfi_endproc pairs") &&
1952 Error(*CFIStartProcLoc, "previous .cfi_startproc was here");
1953
1954 if (discardLTOSymbol(IDVal))
1955 return false;
1956
1957 getTargetParser().doBeforeLabelEmit(Sym, IDLoc);
1958
1959 // Emit the label.
1960 if (!getTargetParser().isParsingMSInlineAsm())
1961 Out.emitLabel(Sym, IDLoc);
1962
1963 // If we are generating dwarf for assembly source files then gather the
1964 // info to make a dwarf label entry for this label if needed.
1965 if (enabledGenDwarfForAssembly())
1966 MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
1967 IDLoc);
1968
1969 getTargetParser().onLabelParsed(Sym);
1970
1971 return false;
1972 }
1973
1974 // Check for an assignment statement.
1975 // ::= identifier '='
1976 if (Lexer.is(AsmToken::Equal) && getTargetParser().equalIsAsmAssignment()) {
1977 Lex();
1978 return parseAssignment(IDVal, AssignmentKind::Equal);
1979 }
1980
1981 // If macros are enabled, check to see if this is a macro instantiation.
1982 if (areMacrosEnabled())
1983 if (MCAsmMacro *M = getContext().lookupMacro(IDVal))
1984 return handleMacroEntry(M, IDLoc);
1985
1986 // Otherwise, we have a normal instruction or directive.
1987
1988 // Directives start with "."
1989 if (IDVal.starts_with(".") && IDVal != ".") {
1990 // There are several entities interested in parsing directives:
1991 //
1992 // 1. The target-specific assembly parser. Some directives are target
1993 // specific or may potentially behave differently on certain targets.
1994 // 2. Asm parser extensions. For example, platform-specific parsers
1995 // (like the ELF parser) register themselves as extensions.
1996 // 3. The generic directive parser implemented by this class. These are
1997 // all the directives that behave in a target and platform independent
1998 // manner, or at least have a default behavior that's shared between
1999 // all targets and platforms.
2000
2001 getTargetParser().flushPendingInstructions(getStreamer());
2002
2003 ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);
2004 assert(TPDirectiveReturn.isFailure() == hasPendingError() &&
2005 "Should only return Failure iff there was an error");
2006 if (TPDirectiveReturn.isFailure())
2007 return true;
2008 if (TPDirectiveReturn.isSuccess())
2009 return false;
2010
2011 // Next, check the extension directive map to see if any extension has
2012 // registered itself to parse this directive.
2013 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2014 ExtensionDirectiveMap.lookup(IDVal);
2015 if (Handler.first)
2016 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2017
2018 // Finally, if no one else is interested in this directive, it must be
2019 // generic and familiar to this class.
2020 switch (DirKind) {
2021 default:
2022 break;
2023 case DK_SET:
2024 case DK_EQU:
2025 return parseDirectiveSet(IDVal, AssignmentKind::Set);
2026 case DK_EQUIV:
2027 return parseDirectiveSet(IDVal, AssignmentKind::Equiv);
2028 case DK_LTO_SET_CONDITIONAL:
2029 return parseDirectiveSet(IDVal, AssignmentKind::LTOSetConditional);
2030 case DK_ASCII:
2031 return parseDirectiveAscii(IDVal, false);
2032 case DK_ASCIZ:
2033 case DK_STRING:
2034 return parseDirectiveAscii(IDVal, true);
2035 case DK_BYTE:
2036 case DK_DC_B:
2037 return parseDirectiveValue(IDVal, 1);
2038 case DK_DC:
2039 case DK_DC_W:
2040 case DK_SHORT:
2041 case DK_VALUE:
2042 case DK_2BYTE:
2043 return parseDirectiveValue(IDVal, 2);
2044 case DK_LONG:
2045 case DK_INT:
2046 case DK_4BYTE:
2047 case DK_DC_L:
2048 return parseDirectiveValue(IDVal, 4);
2049 case DK_QUAD:
2050 case DK_8BYTE:
2051 return parseDirectiveValue(IDVal, 8);
2052 case DK_DC_A:
2053 return parseDirectiveValue(
2054 IDVal, getContext().getAsmInfo()->getCodePointerSize());
2055 case DK_OCTA:
2056 return parseDirectiveOctaValue(IDVal);
2057 case DK_SINGLE:
2058 case DK_FLOAT:
2059 case DK_DC_S:
2060 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());
2061 case DK_DOUBLE:
2062 case DK_DC_D:
2063 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());
2064 case DK_ALIGN: {
2065 bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
2066 return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);
2067 }
2068 case DK_ALIGN32: {
2069 bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
2070 return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);
2071 }
2072 case DK_BALIGN:
2073 return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
2074 case DK_BALIGNW:
2075 return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
2076 case DK_BALIGNL:
2077 return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
2078 case DK_P2ALIGN:
2079 return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
2080 case DK_P2ALIGNW:
2081 return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
2082 case DK_P2ALIGNL:
2083 return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
2084 case DK_ORG:
2085 return parseDirectiveOrg();
2086 case DK_FILL:
2087 return parseDirectiveFill();
2088 case DK_ZERO:
2089 return parseDirectiveZero();
2090 case DK_EXTERN:
2091 eatToEndOfStatement(); // .extern is the default, ignore it.
2092 return false;
2093 case DK_GLOBL:
2094 case DK_GLOBAL:
2095 return parseDirectiveSymbolAttribute(MCSA_Global);
2096 case DK_LAZY_REFERENCE:
2097 return parseDirectiveSymbolAttribute(MCSA_LazyReference);
2098 case DK_NO_DEAD_STRIP:
2099 return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
2100 case DK_SYMBOL_RESOLVER:
2101 return parseDirectiveSymbolAttribute(MCSA_SymbolResolver);
2102 case DK_PRIVATE_EXTERN:
2103 return parseDirectiveSymbolAttribute(MCSA_PrivateExtern);
2104 case DK_REFERENCE:
2105 return parseDirectiveSymbolAttribute(MCSA_Reference);
2106 case DK_WEAK_DEFINITION:
2107 return parseDirectiveSymbolAttribute(MCSA_WeakDefinition);
2108 case DK_WEAK_REFERENCE:
2109 return parseDirectiveSymbolAttribute(MCSA_WeakReference);
2110 case DK_WEAK_DEF_CAN_BE_HIDDEN:
2111 return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
2112 case DK_COLD:
2113 return parseDirectiveSymbolAttribute(MCSA_Cold);
2114 case DK_COMM:
2115 case DK_COMMON:
2116 return parseDirectiveComm(/*IsLocal=*/false);
2117 case DK_LCOMM:
2118 return parseDirectiveComm(/*IsLocal=*/true);
2119 case DK_ABORT:
2120 return parseDirectiveAbort();
2121 case DK_INCLUDE:
2122 return parseDirectiveInclude();
2123 case DK_INCBIN:
2124 return parseDirectiveIncbin();
2125 case DK_CODE16:
2126 case DK_CODE16GCC:
2127 return TokError(Twine(IDVal) +
2128 " not currently supported for this target");
2129 case DK_REPT:
2130 return parseDirectiveRept(IDLoc, IDVal);
2131 case DK_IRP:
2132 return parseDirectiveIrp(IDLoc);
2133 case DK_IRPC:
2134 return parseDirectiveIrpc(IDLoc);
2135 case DK_ENDR:
2136 return parseDirectiveEndr(IDLoc);
2137 case DK_BUNDLE_ALIGN_MODE:
2138 return parseDirectiveBundleAlignMode();
2139 case DK_BUNDLE_LOCK:
2140 return parseDirectiveBundleLock();
2141 case DK_BUNDLE_UNLOCK:
2142 return parseDirectiveBundleUnlock();
2143 case DK_SLEB128:
2144 return parseDirectiveLEB128(true);
2145 case DK_ULEB128:
2146 return parseDirectiveLEB128(false);
2147 case DK_SPACE:
2148 case DK_SKIP:
2149 return parseDirectiveSpace(IDVal);
2150 case DK_FILE:
2151 return parseDirectiveFile(IDLoc);
2152 case DK_LINE:
2153 return parseDirectiveLine();
2154 case DK_LOC:
2155 return parseDirectiveLoc();
2156 case DK_STABS:
2157 return parseDirectiveStabs();
2158 case DK_CV_FILE:
2159 return parseDirectiveCVFile();
2160 case DK_CV_FUNC_ID:
2161 return parseDirectiveCVFuncId();
2162 case DK_CV_INLINE_SITE_ID:
2163 return parseDirectiveCVInlineSiteId();
2164 case DK_CV_LOC:
2165 return parseDirectiveCVLoc();
2166 case DK_CV_LINETABLE:
2167 return parseDirectiveCVLinetable();
2168 case DK_CV_INLINE_LINETABLE:
2169 return parseDirectiveCVInlineLinetable();
2170 case DK_CV_DEF_RANGE:
2171 return parseDirectiveCVDefRange();
2172 case DK_CV_STRING:
2173 return parseDirectiveCVString();
2174 case DK_CV_STRINGTABLE:
2175 return parseDirectiveCVStringTable();
2176 case DK_CV_FILECHECKSUMS:
2177 return parseDirectiveCVFileChecksums();
2178 case DK_CV_FILECHECKSUM_OFFSET:
2179 return parseDirectiveCVFileChecksumOffset();
2180 case DK_CV_FPO_DATA:
2181 return parseDirectiveCVFPOData();
2182 case DK_CFI_SECTIONS:
2183 return parseDirectiveCFISections();
2184 case DK_CFI_STARTPROC:
2185 return parseDirectiveCFIStartProc();
2186 case DK_CFI_ENDPROC:
2187 return parseDirectiveCFIEndProc();
2188 case DK_CFI_DEF_CFA:
2189 return parseDirectiveCFIDefCfa(IDLoc);
2190 case DK_CFI_DEF_CFA_OFFSET:
2191 return parseDirectiveCFIDefCfaOffset(IDLoc);
2192 case DK_CFI_ADJUST_CFA_OFFSET:
2193 return parseDirectiveCFIAdjustCfaOffset(IDLoc);
2194 case DK_CFI_DEF_CFA_REGISTER:
2195 return parseDirectiveCFIDefCfaRegister(IDLoc);
2196 case DK_CFI_LLVM_DEF_ASPACE_CFA:
2197 return parseDirectiveCFILLVMDefAspaceCfa(IDLoc);
2198 case DK_CFI_OFFSET:
2199 return parseDirectiveCFIOffset(IDLoc);
2200 case DK_CFI_REL_OFFSET:
2201 return parseDirectiveCFIRelOffset(IDLoc);
2202 case DK_CFI_PERSONALITY:
2203 return parseDirectiveCFIPersonalityOrLsda(true);
2204 case DK_CFI_LSDA:
2205 return parseDirectiveCFIPersonalityOrLsda(false);
2206 case DK_CFI_REMEMBER_STATE:
2207 return parseDirectiveCFIRememberState(IDLoc);
2208 case DK_CFI_RESTORE_STATE:
2209 return parseDirectiveCFIRestoreState(IDLoc);
2210 case DK_CFI_SAME_VALUE:
2211 return parseDirectiveCFISameValue(IDLoc);
2212 case DK_CFI_RESTORE:
2213 return parseDirectiveCFIRestore(IDLoc);
2214 case DK_CFI_ESCAPE:
2215 return parseDirectiveCFIEscape(IDLoc);
2216 case DK_CFI_RETURN_COLUMN:
2217 return parseDirectiveCFIReturnColumn(IDLoc);
2218 case DK_CFI_SIGNAL_FRAME:
2219 return parseDirectiveCFISignalFrame(IDLoc);
2220 case DK_CFI_UNDEFINED:
2221 return parseDirectiveCFIUndefined(IDLoc);
2222 case DK_CFI_REGISTER:
2223 return parseDirectiveCFIRegister(IDLoc);
2224 case DK_CFI_WINDOW_SAVE:
2225 return parseDirectiveCFIWindowSave(IDLoc);
2226 case DK_MACROS_ON:
2227 case DK_MACROS_OFF:
2228 return parseDirectiveMacrosOnOff(IDVal);
2229 case DK_MACRO:
2230 return parseDirectiveMacro(IDLoc);
2231 case DK_ALTMACRO:
2232 case DK_NOALTMACRO:
2233 return parseDirectiveAltmacro(IDVal);
2234 case DK_EXITM:
2235 return parseDirectiveExitMacro(IDVal);
2236 case DK_ENDM:
2237 case DK_ENDMACRO:
2238 return parseDirectiveEndMacro(IDVal);
2239 case DK_PURGEM:
2240 return parseDirectivePurgeMacro(IDLoc);
2241 case DK_END:
2242 return parseDirectiveEnd(IDLoc);
2243 case DK_ERR:
2244 return parseDirectiveError(IDLoc, false);
2245 case DK_ERROR:
2246 return parseDirectiveError(IDLoc, true);
2247 case DK_WARNING:
2248 return parseDirectiveWarning(IDLoc);
2249 case DK_RELOC:
2250 return parseDirectiveReloc(IDLoc);
2251 case DK_DCB:
2252 case DK_DCB_W:
2253 return parseDirectiveDCB(IDVal, 2);
2254 case DK_DCB_B:
2255 return parseDirectiveDCB(IDVal, 1);
2256 case DK_DCB_D:
2257 return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble());
2258 case DK_DCB_L:
2259 return parseDirectiveDCB(IDVal, 4);
2260 case DK_DCB_S:
2261 return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle());
2262 case DK_DC_X:
2263 case DK_DCB_X:
2264 return TokError(Twine(IDVal) +
2265 " not currently supported for this target");
2266 case DK_DS:
2267 case DK_DS_W:
2268 return parseDirectiveDS(IDVal, 2);
2269 case DK_DS_B:
2270 return parseDirectiveDS(IDVal, 1);
2271 case DK_DS_D:
2272 return parseDirectiveDS(IDVal, 8);
2273 case DK_DS_L:
2274 case DK_DS_S:
2275 return parseDirectiveDS(IDVal, 4);
2276 case DK_DS_P:
2277 case DK_DS_X:
2278 return parseDirectiveDS(IDVal, 12);
2279 case DK_PRINT:
2280 return parseDirectivePrint(IDLoc);
2281 case DK_ADDRSIG:
2282 return parseDirectiveAddrsig();
2283 case DK_ADDRSIG_SYM:
2284 return parseDirectiveAddrsigSym();
2285 case DK_PSEUDO_PROBE:
2286 return parseDirectivePseudoProbe();
2287 case DK_LTO_DISCARD:
2288 return parseDirectiveLTODiscard();
2289 case DK_MEMTAG:
2290 return parseDirectiveSymbolAttribute(MCSA_Memtag);
2291 }
2292
2293 return Error(IDLoc, "unknown directive");
2294 }
2295
2296 // __asm _emit or __asm __emit
2297 if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
2298 IDVal == "_EMIT" || IDVal == "__EMIT"))
2299 return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
2300
2301 // __asm align
2302 if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
2303 return parseDirectiveMSAlign(IDLoc, Info);
2304
2305 if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
2306 Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
2307 if (checkForValidSection())
2308 return true;
2309
2310 return parseAndMatchAndEmitTargetInstruction(Info, IDVal, ID, IDLoc);
2311}
2312
2313bool AsmParser::parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,
2314 StringRef IDVal,
2315 AsmToken ID,
2316 SMLoc IDLoc) {
2317 // Canonicalize the opcode to lower case.
2318 std::string OpcodeStr = IDVal.lower();
2319 ParseInstructionInfo IInfo(Info.AsmRewrites);
2320 bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
2321 Info.ParsedOperands);
2322 Info.ParseError = ParseHadError;
2323
2324 // Dump the parsed representation, if requested.
2325 if (getShowParsedOperands()) {
2326 SmallString<256> Str;
2328 OS << "parsed instruction: [";
2329 for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
2330 if (i != 0)
2331 OS << ", ";
2332 Info.ParsedOperands[i]->print(OS);
2333 }
2334 OS << "]";
2335
2336 printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
2337 }
2338
2339 // Fail even if ParseInstruction erroneously returns false.
2340 if (hasPendingError() || ParseHadError)
2341 return true;
2342
2343 // If we are generating dwarf for the current section then generate a .loc
2344 // directive for the instruction.
2345 if (!ParseHadError && enabledGenDwarfForAssembly() &&
2346 getContext().getGenDwarfSectionSyms().count(
2347 getStreamer().getCurrentSectionOnly())) {
2348 unsigned Line;
2349 if (ActiveMacros.empty())
2350 Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
2351 else
2352 Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
2353 ActiveMacros.front()->ExitBuffer);
2354
2355 // If we previously parsed a cpp hash file line comment then make sure the
2356 // current Dwarf File is for the CppHashFilename if not then emit the
2357 // Dwarf File table for it and adjust the line number for the .loc.
2358 if (!CppHashInfo.Filename.empty()) {
2359 unsigned FileNumber = getStreamer().emitDwarfFileDirective(
2360 0, StringRef(), CppHashInfo.Filename);
2361 getContext().setGenDwarfFileNumber(FileNumber);
2362
2363 unsigned CppHashLocLineNo =
2364 SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
2365 Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
2366 }
2367
2368 getStreamer().emitDwarfLocDirective(
2369 getContext().getGenDwarfFileNumber(), Line, 0,
2371 StringRef());
2372 }
2373
2374 // If parsing succeeded, match the instruction.
2375 if (!ParseHadError) {
2377 if (getTargetParser().MatchAndEmitInstruction(
2378 IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
2379 getTargetParser().isParsingMSInlineAsm()))
2380 return true;
2381 }
2382 return false;
2383}
2384
2385// Parse and erase curly braces marking block start/end
2386bool
2387AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2388 // Identify curly brace marking block start/end
2389 if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
2390 return false;
2391
2392 SMLoc StartLoc = Lexer.getLoc();
2393 Lex(); // Eat the brace
2394 if (Lexer.is(AsmToken::EndOfStatement))
2395 Lex(); // Eat EndOfStatement following the brace
2396
2397 // Erase the block start/end brace from the output asm string
2398 AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
2399 StartLoc.getPointer());
2400 return true;
2401}
2402
2403/// parseCppHashLineFilenameComment as this:
2404/// ::= # number "filename"
2405bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) {
2406 Lex(); // Eat the hash token.
2407 // Lexer only ever emits HashDirective if it fully formed if it's
2408 // done the checking already so this is an internal error.
2409 assert(getTok().is(AsmToken::Integer) &&
2410 "Lexing Cpp line comment: Expected Integer");
2411 int64_t LineNumber = getTok().getIntVal();
2412 Lex();
2413 assert(getTok().is(AsmToken::String) &&
2414 "Lexing Cpp line comment: Expected String");
2415 StringRef Filename = getTok().getString();
2416 Lex();
2417
2418 if (!SaveLocInfo)
2419 return false;
2420
2421 // Get rid of the enclosing quotes.
2422 Filename = Filename.substr(1, Filename.size() - 2);
2423
2424 // Save the SMLoc, Filename and LineNumber for later use by diagnostics
2425 // and possibly DWARF file info.
2426 CppHashInfo.Loc = L;
2427 CppHashInfo.Filename = Filename;
2428 CppHashInfo.LineNumber = LineNumber;
2429 CppHashInfo.Buf = CurBuffer;
2430 if (FirstCppHashFilename.empty())
2431 FirstCppHashFilename = Filename;
2432 return false;
2433}
2434
2435/// will use the last parsed cpp hash line filename comment
2436/// for the Filename and LineNo if any in the diagnostic.
2437void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
2438 auto *Parser = static_cast<AsmParser *>(Context);
2439 raw_ostream &OS = errs();
2440
2441 const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
2442 SMLoc DiagLoc = Diag.getLoc();
2443 unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
2444 unsigned CppHashBuf =
2445 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2446
2447 // Like SourceMgr::printMessage() we need to print the include stack if any
2448 // before printing the message.
2449 unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
2450 if (!Parser->SavedDiagHandler && DiagCurBuffer &&
2451 DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
2452 SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
2453 DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
2454 }
2455
2456 // If we have not parsed a cpp hash line filename comment or the source
2457 // manager changed or buffer changed (like in a nested include) then just
2458 // print the normal diagnostic using its Filename and LineNo.
2459 if (!Parser->CppHashInfo.LineNumber || DiagBuf != CppHashBuf) {
2460 if (Parser->SavedDiagHandler)
2461 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2462 else
2463 Parser->getContext().diagnose(Diag);
2464 return;
2465 }
2466
2467 // Use the CppHashFilename and calculate a line number based on the
2468 // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
2469 // for the diagnostic.
2470 const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
2471
2472 int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
2473 int CppHashLocLineNo =
2474 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2475 int LineNo =
2476 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2477
2478 SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
2479 Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
2480 Diag.getLineContents(), Diag.getRanges());
2481
2482 if (Parser->SavedDiagHandler)
2483 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2484 else
2485 Parser->getContext().diagnose(NewDiag);
2486}
2487
2488// FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The
2489// difference being that that function accepts '@' as part of identifiers and
2490// we can't do that. AsmLexer.cpp should probably be changed to handle
2491// '@' as a special case when needed.
2492static bool isIdentifierChar(char c) {
2493 return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||
2494 c == '.';
2495}
2496
2497bool AsmParser::expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,
2500 bool EnableAtPseudoVariable) {
2501 unsigned NParameters = Parameters.size();
2502 bool HasVararg = NParameters ? Parameters.back().Vararg : false;
2503
2504 // A macro without parameters is handled differently on Darwin:
2505 // gas accepts no arguments and does no substitutions
2506 StringRef Body = Macro.Body;
2507 while (!Body.empty()) {
2508 // Scan for the next substitution.
2509 std::size_t End = Body.size(), Pos = 0;
2510 for (; Pos != End; ++Pos) {
2511 // Check for a substitution or escape.
2512 if (IsDarwin && !NParameters) {
2513 // This macro has no parameters, look for $0, $1, etc.
2514 if (Body[Pos] != '$' || Pos + 1 == End)
2515 continue;
2516
2517 char Next = Body[Pos + 1];
2518 if (Next == '$' || Next == 'n' ||
2519 isdigit(static_cast<unsigned char>(Next)))
2520 break;
2521 } else {
2522 // This macro has parameters, look for \foo, \bar, etc.
2523 if (Body[Pos] == '\\' && Pos + 1 != End)
2524 break;
2525 }
2526 }
2527
2528 // Add the prefix.
2529 OS << Body.slice(0, Pos);
2530
2531 // Check if we reached the end.
2532 if (Pos == End)
2533 break;
2534
2535 if (IsDarwin && !NParameters) {
2536 switch (Body[Pos + 1]) {
2537 // $$ => $
2538 case '$':
2539 OS << '$';
2540 break;
2541
2542 // $n => number of arguments
2543 case 'n':
2544 OS << A.size();
2545 break;
2546
2547 // $[0-9] => argument
2548 default: {
2549 // Missing arguments are ignored.
2550 unsigned Index = Body[Pos + 1] - '0';
2551 if (Index >= A.size())
2552 break;
2553
2554 // Otherwise substitute with the token values, with spaces eliminated.
2555 for (const AsmToken &Token : A[Index])
2556 OS << Token.getString();
2557 break;
2558 }
2559 }
2560 Pos += 2;
2561 } else {
2562 // Check for \@ and \+ pseudo variables.
2563 unsigned I = Pos + 1;
2564 if (I + 1 != End) {
2565 if (EnableAtPseudoVariable && Body[I] == '@') {
2566 ++I;
2567 } else if (Body[I] == '+') {
2568 ++I;
2569 } else {
2570 while (isIdentifierChar(Body[I]) && I + 1 != End)
2571 ++I;
2572 }
2573 }
2574
2575 const char *Begin = Body.data() + Pos + 1;
2576 StringRef Argument(Begin, I - (Pos + 1));
2577 unsigned Index = 0;
2578
2579 if (Argument == "@") {
2580 OS << NumOfMacroInstantiations;
2581 Pos += 2;
2582 } else if (Argument == "+") {
2583 OS << Macro.Count++;
2584 Pos += 2;
2585 } else {
2586 for (; Index < NParameters; ++Index)
2587 if (Parameters[Index].Name == Argument)
2588 break;
2589
2590 if (Index == NParameters) {
2591 if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
2592 Pos += 3;
2593 else {
2594 OS << '\\' << Argument;
2595 Pos = I;
2596 }
2597 } else {
2598 bool VarargParameter = HasVararg && Index == (NParameters - 1);
2599 for (const AsmToken &Token : A[Index])
2600 // For altmacro mode, you can write '%expr'.
2601 // The prefix '%' evaluates the expression 'expr'
2602 // and uses the result as a string (e.g. replace %(1+2) with the
2603 // string "3").
2604 // Here, we identify the integer token which is the result of the
2605 // absolute expression evaluation and replace it with its string
2606 // representation.
2607 if (AltMacroMode && Token.getString().front() == '%' &&
2608 Token.is(AsmToken::Integer))
2609 // Emit an integer value to the buffer.
2610 OS << Token.getIntVal();
2611 // Only Token that was validated as a string and begins with '<'
2612 // is considered altMacroString!!!
2613 else if (AltMacroMode && Token.getString().front() == '<' &&
2614 Token.is(AsmToken::String)) {
2615 OS << angleBracketString(Token.getStringContents());
2616 }
2617 // We expect no quotes around the string's contents when
2618 // parsing for varargs.
2619 else if (Token.isNot(AsmToken::String) || VarargParameter)
2620 OS << Token.getString();
2621 else
2622 OS << Token.getStringContents();
2623
2624 Pos += 1 + Argument.size();
2625 }
2626 }
2627 }
2628 // Update the scan point.
2629 Body = Body.substr(Pos);
2630 }
2631
2632 return false;
2633}
2634
2636 switch (kind) {
2637 default:
2638 return false;
2639 case AsmToken::Plus:
2640 case AsmToken::Minus:
2641 case AsmToken::Tilde:
2642 case AsmToken::Slash:
2643 case AsmToken::Star:
2644 case AsmToken::Dot:
2645 case AsmToken::Equal:
2647 case AsmToken::Pipe:
2648 case AsmToken::PipePipe:
2649 case AsmToken::Caret:
2650 case AsmToken::Amp:
2651 case AsmToken::AmpAmp:
2652 case AsmToken::Exclaim:
2654 case AsmToken::Less:
2656 case AsmToken::LessLess:
2658 case AsmToken::Greater:
2661 return true;
2662 }
2663}
2664
2665namespace {
2666
2667class AsmLexerSkipSpaceRAII {
2668public:
2669 AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
2670 Lexer.setSkipSpace(SkipSpace);
2671 }
2672
2673 ~AsmLexerSkipSpaceRAII() {
2674 Lexer.setSkipSpace(true);
2675 }
2676
2677private:
2678 AsmLexer &Lexer;
2679};
2680
2681} // end anonymous namespace
2682
2683bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
2684
2685 if (Vararg) {
2686 if (Lexer.isNot(AsmToken::EndOfStatement)) {
2687 StringRef Str = parseStringToEndOfStatement();
2688 MA.emplace_back(AsmToken::String, Str);
2689 }
2690 return false;
2691 }
2692
2693 unsigned ParenLevel = 0;
2694
2695 // Darwin doesn't use spaces to delmit arguments.
2696 AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
2697
2698 bool SpaceEaten;
2699
2700 while (true) {
2701 SpaceEaten = false;
2702 if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
2703 return TokError("unexpected token in macro instantiation");
2704
2705 if (ParenLevel == 0) {
2706
2707 if (Lexer.is(AsmToken::Comma))
2708 break;
2709
2710 if (parseOptionalToken(AsmToken::Space))
2711 SpaceEaten = true;
2712
2713 // Spaces can delimit parameters, but could also be part an expression.
2714 // If the token after a space is an operator, add the token and the next
2715 // one into this argument
2716 if (!IsDarwin) {
2717 if (isOperator(Lexer.getKind())) {
2718 MA.push_back(getTok());
2719 Lexer.Lex();
2720
2721 // Whitespace after an operator can be ignored.
2722 parseOptionalToken(AsmToken::Space);
2723 continue;
2724 }
2725 }
2726 if (SpaceEaten)
2727 break;
2728 }
2729
2730 // handleMacroEntry relies on not advancing the lexer here
2731 // to be able to fill in the remaining default parameter values
2732 if (Lexer.is(AsmToken::EndOfStatement))
2733 break;
2734
2735 // Adjust the current parentheses level.
2736 if (Lexer.is(AsmToken::LParen))
2737 ++ParenLevel;
2738 else if (Lexer.is(AsmToken::RParen) && ParenLevel)
2739 --ParenLevel;
2740
2741 // Append the token to the current argument list.
2742 MA.push_back(getTok());
2743 Lexer.Lex();
2744 }
2745
2746 if (ParenLevel != 0)
2747 return TokError("unbalanced parentheses in macro argument");
2748 return false;
2749}
2750
2751// Parse the macro instantiation arguments.
2752bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
2753 MCAsmMacroArguments &A) {
2754 const unsigned NParameters = M ? M->Parameters.size() : 0;
2755 bool NamedParametersFound = false;
2756 SmallVector<SMLoc, 4> FALocs;
2757
2758 A.resize(NParameters);
2759 FALocs.resize(NParameters);
2760
2761 // Parse two kinds of macro invocations:
2762 // - macros defined without any parameters accept an arbitrary number of them
2763 // - macros defined with parameters accept at most that many of them
2764 bool HasVararg = NParameters ? M->Parameters.back().Vararg : false;
2765 for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
2766 ++Parameter) {
2767 SMLoc IDLoc = Lexer.getLoc();
2769
2770 if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
2771 if (parseIdentifier(FA.Name))
2772 return Error(IDLoc, "invalid argument identifier for formal argument");
2773
2774 if (Lexer.isNot(AsmToken::Equal))
2775 return TokError("expected '=' after formal parameter identifier");
2776
2777 Lex();
2778
2779 NamedParametersFound = true;
2780 }
2781 bool Vararg = HasVararg && Parameter == (NParameters - 1);
2782
2783 if (NamedParametersFound && FA.Name.empty())
2784 return Error(IDLoc, "cannot mix positional and keyword arguments");
2785
2786 SMLoc StrLoc = Lexer.getLoc();
2787 SMLoc EndLoc;
2788 if (AltMacroMode && Lexer.is(AsmToken::Percent)) {
2789 const MCExpr *AbsoluteExp;
2790 int64_t Value;
2791 /// Eat '%'
2792 Lex();
2793 if (parseExpression(AbsoluteExp, EndLoc))
2794 return false;
2795 if (!AbsoluteExp->evaluateAsAbsolute(Value,
2796 getStreamer().getAssemblerPtr()))
2797 return Error(StrLoc, "expected absolute expression");
2798 const char *StrChar = StrLoc.getPointer();
2799 const char *EndChar = EndLoc.getPointer();
2800 AsmToken newToken(AsmToken::Integer,
2801 StringRef(StrChar, EndChar - StrChar), Value);
2802 FA.Value.push_back(newToken);
2803 } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
2804 isAngleBracketString(StrLoc, EndLoc)) {
2805 const char *StrChar = StrLoc.getPointer();
2806 const char *EndChar = EndLoc.getPointer();
2807 jumpToLoc(EndLoc, CurBuffer);
2808 /// Eat from '<' to '>'
2809 Lex();
2810 AsmToken newToken(AsmToken::String,
2811 StringRef(StrChar, EndChar - StrChar));
2812 FA.Value.push_back(newToken);
2813 } else if(parseMacroArgument(FA.Value, Vararg))
2814 return true;
2815
2816 unsigned PI = Parameter;
2817 if (!FA.Name.empty()) {
2818 unsigned FAI = 0;
2819 for (FAI = 0; FAI < NParameters; ++FAI)
2820 if (M->Parameters[FAI].Name == FA.Name)
2821 break;
2822
2823 if (FAI >= NParameters) {
2824 assert(M && "expected macro to be defined");
2825 return Error(IDLoc, "parameter named '" + FA.Name +
2826 "' does not exist for macro '" + M->Name + "'");
2827 }
2828 PI = FAI;
2829 }
2830
2831 if (!FA.Value.empty()) {
2832 if (A.size() <= PI)
2833 A.resize(PI + 1);
2834 A[PI] = FA.Value;
2835
2836 if (FALocs.size() <= PI)
2837 FALocs.resize(PI + 1);
2838
2839 FALocs[PI] = Lexer.getLoc();
2840 }
2841
2842 // At the end of the statement, fill in remaining arguments that have
2843 // default values. If there aren't any, then the next argument is
2844 // required but missing
2845 if (Lexer.is(AsmToken::EndOfStatement)) {
2846 bool Failure = false;
2847 for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
2848 if (A[FAI].empty()) {
2849 if (M->Parameters[FAI].Required) {
2850 Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
2851 "missing value for required parameter "
2852 "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
2853 Failure = true;
2854 }
2855
2856 if (!M->Parameters[FAI].Value.empty())
2857 A[FAI] = M->Parameters[FAI].Value;
2858 }
2859 }
2860 return Failure;
2861 }
2862
2863 parseOptionalToken(AsmToken::Comma);
2864 }
2865
2866 return TokError("too many positional arguments");
2867}
2868
2869bool AsmParser::handleMacroEntry(MCAsmMacro *M, SMLoc NameLoc) {
2870 // Arbitrarily limit macro nesting depth (default matches 'as'). We can
2871 // eliminate this, although we should protect against infinite loops.
2872 unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
2873 if (ActiveMacros.size() == MaxNestingDepth) {
2874 std::ostringstream MaxNestingDepthError;
2875 MaxNestingDepthError << "macros cannot be nested more than "
2876 << MaxNestingDepth << " levels deep."
2877 << " Use -asm-macro-max-nesting-depth to increase "
2878 "this limit.";
2879 return TokError(MaxNestingDepthError.str());
2880 }
2881
2882 MCAsmMacroArguments A;
2883 if (parseMacroArguments(M, A))
2884 return true;
2885
2886 // Macro instantiation is lexical, unfortunately. We construct a new buffer
2887 // to hold the macro body with substitutions.
2888 SmallString<256> Buf;
2890
2891 if ((!IsDarwin || M->Parameters.size()) && M->Parameters.size() != A.size())
2892 return Error(getTok().getLoc(), "Wrong number of arguments");
2893 if (expandMacro(OS, *M, M->Parameters, A, true))
2894 return true;
2895
2896 // We include the .endmacro in the buffer as our cue to exit the macro
2897 // instantiation.
2898 OS << ".endmacro\n";
2899
2900 std::unique_ptr<MemoryBuffer> Instantiation =
2901 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
2902
2903 // Create the macro instantiation object and add to the current macro
2904 // instantiation stack.
2905 MacroInstantiation *MI = new MacroInstantiation{
2906 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2907 ActiveMacros.push_back(MI);
2908
2909 ++NumOfMacroInstantiations;
2910
2911 // Jump to the macro instantiation and prime the lexer.
2912 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
2913 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
2914 Lex();
2915
2916 return false;
2917}
2918
2919void AsmParser::handleMacroExit() {
2920 // Jump to the EndOfStatement we should return to, and consume it.
2921 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
2922 Lex();
2923
2924 // Pop the instantiation entry.
2925 delete ActiveMacros.back();
2926 ActiveMacros.pop_back();
2927}
2928
2929bool AsmParser::parseAssignment(StringRef Name, AssignmentKind Kind) {
2930 MCSymbol *Sym;
2931 const MCExpr *Value;
2932 SMLoc ExprLoc = getTok().getLoc();
2933 bool AllowRedef =
2934 Kind == AssignmentKind::Set || Kind == AssignmentKind::Equal;
2935 if (MCParserUtils::parseAssignmentExpression(Name, AllowRedef, *this, Sym,
2936 Value))
2937 return true;
2938
2939 if (!Sym) {
2940 // In the case where we parse an expression starting with a '.', we will
2941 // not generate an error, nor will we create a symbol. In this case we
2942 // should just return out.
2943 return false;
2944 }
2945
2946 if (discardLTOSymbol(Name))
2947 return false;
2948
2949 // Do the assignment.
2950 switch (Kind) {
2951 case AssignmentKind::Equal:
2952 Out.emitAssignment(Sym, Value);
2953 break;
2954 case AssignmentKind::Set:
2955 case AssignmentKind::Equiv:
2956 Out.emitAssignment(Sym, Value);
2958 break;
2959 case AssignmentKind::LTOSetConditional:
2960 if (Value->getKind() != MCExpr::SymbolRef)
2961 return Error(ExprLoc, "expected identifier");
2962
2964 break;
2965 }
2966
2967 return false;
2968}
2969
2970/// parseIdentifier:
2971/// ::= identifier
2972/// ::= string
2973bool AsmParser::parseIdentifier(StringRef &Res) {
2974 // The assembler has relaxed rules for accepting identifiers, in particular we
2975 // allow things like '.globl $foo' and '.def @feat.00', which would normally be
2976 // separate tokens. At this level, we have already lexed so we cannot (currently)
2977 // handle this as a context dependent token, instead we detect adjacent tokens
2978 // and return the combined identifier.
2979 if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
2980 SMLoc PrefixLoc = getLexer().getLoc();
2981
2982 // Consume the prefix character, and check for a following identifier.
2983
2984 AsmToken Buf[1];
2985 Lexer.peekTokens(Buf, false);
2986
2987 if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer))
2988 return true;
2989
2990 // We have a '$' or '@' followed by an identifier or integer token, make
2991 // sure they are adjacent.
2992 if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())
2993 return true;
2994
2995 // eat $ or @
2996 Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
2997 // Construct the joined identifier and consume the token.
2998 Res = StringRef(PrefixLoc.getPointer(), getTok().getString().size() + 1);
2999 Lex(); // Parser Lex to maintain invariants.
3000 return false;
3001 }
3002
3003 if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
3004 return true;
3005
3006 Res = getTok().getIdentifier();
3007
3008 Lex(); // Consume the identifier token.
3009
3010 return false;
3011}
3012
3013/// parseDirectiveSet:
3014/// ::= .equ identifier ',' expression
3015/// ::= .equiv identifier ',' expression
3016/// ::= .set identifier ',' expression
3017/// ::= .lto_set_conditional identifier ',' expression
3018bool AsmParser::parseDirectiveSet(StringRef IDVal, AssignmentKind Kind) {
3020 if (check(parseIdentifier(Name), "expected identifier") || parseComma() ||
3021 parseAssignment(Name, Kind))
3022 return true;
3023 return false;
3024}
3025
3026bool AsmParser::parseEscapedString(std::string &Data) {
3027 if (check(getTok().isNot(AsmToken::String), "expected string"))
3028 return true;
3029
3030 Data = "";
3031 StringRef Str = getTok().getStringContents();
3032 for (unsigned i = 0, e = Str.size(); i != e; ++i) {
3033 if (Str[i] != '\\') {
3034 Data += Str[i];
3035 continue;
3036 }
3037
3038 // Recognize escaped characters. Note that this escape semantics currently
3039 // loosely follows Darwin 'as'.
3040 ++i;
3041 if (i == e)
3042 return TokError("unexpected backslash at end of string");
3043
3044 // Recognize hex sequences similarly to GNU 'as'.
3045 if (Str[i] == 'x' || Str[i] == 'X') {
3046 size_t length = Str.size();
3047 if (i + 1 >= length || !isHexDigit(Str[i + 1]))
3048 return TokError("invalid hexadecimal escape sequence");
3049
3050 // Consume hex characters. GNU 'as' reads all hexadecimal characters and
3051 // then truncates to the lower 16 bits. Seems reasonable.
3052 unsigned Value = 0;
3053 while (i + 1 < length && isHexDigit(Str[i + 1]))
3054 Value = Value * 16 + hexDigitValue(Str[++i]);
3055
3056 Data += (unsigned char)(Value & 0xFF);
3057 continue;
3058 }
3059
3060 // Recognize octal sequences.
3061 if ((unsigned)(Str[i] - '0') <= 7) {
3062 // Consume up to three octal characters.
3063 unsigned Value = Str[i] - '0';
3064
3065 if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
3066 ++i;
3067 Value = Value * 8 + (Str[i] - '0');
3068
3069 if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
3070 ++i;
3071 Value = Value * 8 + (Str[i] - '0');
3072 }
3073 }
3074
3075 if (Value > 255)
3076 return TokError("invalid octal escape sequence (out of range)");
3077
3078 Data += (unsigned char)Value;
3079 continue;
3080 }
3081
3082 // Otherwise recognize individual escapes.
3083 switch (Str[i]) {
3084 default:
3085 // Just reject invalid escape sequences for now.
3086 return TokError("invalid escape sequence (unrecognized character)");
3087
3088 case 'b': Data += '\b'; break;
3089 case 'f': Data += '\f'; break;
3090 case 'n': Data += '\n'; break;
3091 case 'r': Data += '\r'; break;
3092 case 't': Data += '\t'; break;
3093 case '"': Data += '"'; break;
3094 case '\\': Data += '\\'; break;
3095 }
3096 }
3097
3098 Lex();
3099 return false;
3100}
3101
3102bool AsmParser::parseAngleBracketString(std::string &Data) {
3103 SMLoc EndLoc, StartLoc = getTok().getLoc();
3104 if (isAngleBracketString(StartLoc, EndLoc)) {
3105 const char *StartChar = StartLoc.getPointer() + 1;
3106 const char *EndChar = EndLoc.getPointer() - 1;
3107 jumpToLoc(EndLoc, CurBuffer);
3108 /// Eat from '<' to '>'
3109 Lex();
3110
3111 Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
3112 return false;
3113 }
3114 return true;
3115}
3116
3117/// parseDirectiveAscii:
3118// ::= .ascii [ "string"+ ( , "string"+ )* ]
3119/// ::= ( .asciz | .string ) [ "string" ( , "string" )* ]
3120bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
3121 auto parseOp = [&]() -> bool {
3122 std::string Data;
3123 if (checkForValidSection())
3124 return true;
3125 // Only support spaces as separators for .ascii directive for now. See the
3126 // discusssion at https://reviews.llvm.org/D91460 for more details.
3127 do {
3128 if (parseEscapedString(Data))
3129 return true;
3130 getStreamer().emitBytes(Data);
3131 } while (!ZeroTerminated && getTok().is(AsmToken::String));
3132 if (ZeroTerminated)
3133 getStreamer().emitBytes(StringRef("\0", 1));
3134 return false;
3135 };
3136
3137 return parseMany(parseOp);
3138}
3139
3140/// parseDirectiveReloc
3141/// ::= .reloc expression , identifier [ , expression ]
3142bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
3143 const MCExpr *Offset;
3144 const MCExpr *Expr = nullptr;
3145 SMLoc OffsetLoc = Lexer.getTok().getLoc();
3146
3147 if (parseExpression(Offset))
3148 return true;
3149 if (parseComma() ||
3150 check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
3151 return true;
3152
3153 SMLoc NameLoc = Lexer.getTok().getLoc();
3154 StringRef Name = Lexer.getTok().getIdentifier();
3155 Lex();
3156
3157 if (Lexer.is(AsmToken::Comma)) {
3158 Lex();
3159 SMLoc ExprLoc = Lexer.getLoc();
3160 if (parseExpression(Expr))
3161 return true;
3162
3163 MCValue Value;
3164 if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr))
3165 return Error(ExprLoc, "expression must be relocatable");
3166 }
3167
3168 if (parseEOL())
3169 return true;
3170
3171 const MCTargetAsmParser &MCT = getTargetParser();
3172 const MCSubtargetInfo &STI = MCT.getSTI();
3173 if (std::optional<std::pair<bool, std::string>> Err =
3174 getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc,
3175 STI))
3176 return Error(Err->first ? NameLoc : OffsetLoc, Err->second);
3177
3178 return false;
3179}
3180
3181/// parseDirectiveValue
3182/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
3183bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
3184 auto parseOp = [&]() -> bool {
3185 const MCExpr *Value;
3186 SMLoc ExprLoc = getLexer().getLoc();
3187 if (checkForValidSection() || parseExpression(Value))
3188 return true;
3189 // Special case constant expressions to match code generator.
3190 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3191 assert(Size <= 8 && "Invalid size");
3192 uint64_t IntValue = MCE->getValue();
3193 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
3194 return Error(ExprLoc, "out of range literal value");
3195 getStreamer().emitIntValue(IntValue, Size);
3196 } else
3197 getStreamer().emitValue(Value, Size, ExprLoc);
3198 return false;
3199 };
3200
3201 return parseMany(parseOp);
3202}
3203
3204static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {
3205 if (Asm.getTok().isNot(AsmToken::Integer) &&
3206 Asm.getTok().isNot(AsmToken::BigNum))
3207 return Asm.TokError("unknown token in expression");
3208 SMLoc ExprLoc = Asm.getTok().getLoc();
3209 APInt IntValue = Asm.getTok().getAPIntVal();
3210 Asm.Lex();
3211 if (!IntValue.isIntN(128))
3212 return Asm.Error(ExprLoc, "out of range literal value");
3213 if (!IntValue.isIntN(64)) {
3214 hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
3215 lo = IntValue.getLoBits(64).getZExtValue();
3216 } else {
3217 hi = 0;
3218 lo = IntValue.getZExtValue();
3219 }
3220 return false;
3221}
3222
3223/// ParseDirectiveOctaValue
3224/// ::= .octa [ hexconstant (, hexconstant)* ]
3225
3226bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
3227 auto parseOp = [&]() -> bool {
3228 if (checkForValidSection())
3229 return true;
3230 uint64_t hi, lo;
3231 if (parseHexOcta(*this, hi, lo))
3232 return true;
3233 if (MAI.isLittleEndian()) {
3234 getStreamer().emitInt64(lo);
3235 getStreamer().emitInt64(hi);
3236 } else {
3237 getStreamer().emitInt64(hi);
3238 getStreamer().emitInt64(lo);
3239 }
3240 return false;
3241 };
3242
3243 return parseMany(parseOp);
3244}
3245
3246bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
3247 // We don't truly support arithmetic on floating point expressions, so we
3248 // have to manually parse unary prefixes.
3249 bool IsNeg = false;
3250 if (getLexer().is(AsmToken::Minus)) {
3251 Lexer.Lex();
3252 IsNeg = true;
3253 } else if (getLexer().is(AsmToken::Plus))
3254 Lexer.Lex();
3255
3256 if (Lexer.is(AsmToken::Error))
3257 return TokError(Lexer.getErr());
3258 if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
3260 return TokError("unexpected token in directive");
3261
3262 // Convert to an APFloat.
3263 APFloat Value(Semantics);
3264 StringRef IDVal = getTok().getString();
3265 if (getLexer().is(AsmToken::Identifier)) {
3266 if (!IDVal.compare_insensitive("infinity") ||
3267 !IDVal.compare_insensitive("inf"))
3268 Value = APFloat::getInf(Semantics);
3269 else if (!IDVal.compare_insensitive("nan"))
3270 Value = APFloat::getNaN(Semantics, false, ~0);
3271 else
3272 return TokError("invalid floating point literal");
3273 } else if (errorToBool(
3274 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3275 .takeError()))
3276 return TokError("invalid floating point literal");
3277 if (IsNeg)
3278 Value.changeSign();
3279
3280 // Consume the numeric token.
3281 Lex();
3282
3283 Res = Value.bitcastToAPInt();
3284
3285 return false;
3286}
3287
3288/// parseDirectiveRealValue
3289/// ::= (.single | .double) [ expression (, expression)* ]
3290bool AsmParser::parseDirectiveRealValue(StringRef IDVal,
3291 const fltSemantics &Semantics) {
3292 auto parseOp = [&]() -> bool {
3293 APInt AsInt;
3294 if (checkForValidSection() || parseRealValue(Semantics, AsInt))
3295 return true;
3296 getStreamer().emitIntValue(AsInt.getLimitedValue(),
3297 AsInt.getBitWidth() / 8);
3298 return false;
3299 };
3300
3301 return parseMany(parseOp);
3302}
3303
3304/// parseDirectiveZero
3305/// ::= .zero expression
3306bool AsmParser::parseDirectiveZero() {
3307 SMLoc NumBytesLoc = Lexer.getLoc();
3308 const MCExpr *NumBytes;
3309 if (checkForValidSection() || parseExpression(NumBytes))
3310 return true;
3311
3312 int64_t Val = 0;
3313 if (getLexer().is(AsmToken::Comma)) {
3314 Lex();
3315 if (parseAbsoluteExpression(Val))
3316 return true;
3317 }
3318
3319 if (parseEOL())
3320 return true;
3321 getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);
3322
3323 return false;
3324}
3325
3326/// parseDirectiveFill
3327/// ::= .fill expression [ , expression [ , expression ] ]
3328bool AsmParser::parseDirectiveFill() {
3329 SMLoc NumValuesLoc = Lexer.getLoc();
3330 const MCExpr *NumValues;
3331 if (checkForValidSection() || parseExpression(NumValues))
3332 return true;
3333
3334 int64_t FillSize = 1;
3335 int64_t FillExpr = 0;
3336
3337 SMLoc SizeLoc, ExprLoc;
3338
3339 if (parseOptionalToken(AsmToken::Comma)) {
3340 SizeLoc = getTok().getLoc();
3341 if (parseAbsoluteExpression(FillSize))
3342 return true;
3343 if (parseOptionalToken(AsmToken::Comma)) {
3344 ExprLoc = getTok().getLoc();
3345 if (parseAbsoluteExpression(FillExpr))
3346 return true;
3347 }
3348 }
3349 if (parseEOL())
3350 return true;
3351
3352 if (FillSize < 0) {
3353 Warning(SizeLoc, "'.fill' directive with negative size has no effect");
3354 return false;
3355 }
3356 if (FillSize > 8) {
3357 Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
3358 FillSize = 8;
3359 }
3360
3361 if (!isUInt<32>(FillExpr) && FillSize > 4)
3362 Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
3363
3364 getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);
3365
3366 return false;
3367}
3368
3369/// parseDirectiveOrg
3370/// ::= .org expression [ , expression ]
3371bool AsmParser::parseDirectiveOrg() {
3372 const MCExpr *Offset;
3373 SMLoc OffsetLoc = Lexer.getLoc();
3374 if (checkForValidSection() || parseExpression(Offset))
3375 return true;
3376
3377 // Parse optional fill expression.
3378 int64_t FillExpr = 0;
3379 if (parseOptionalToken(AsmToken::Comma))
3380 if (parseAbsoluteExpression(FillExpr))
3381 return true;
3382 if (parseEOL())
3383 return true;
3384
3385 getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
3386 return false;
3387}
3388
3389/// parseDirectiveAlign
3390/// ::= {.align, ...} expression [ , expression [ , expression ]]
3391bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
3392 SMLoc AlignmentLoc = getLexer().getLoc();
3393 int64_t Alignment;
3394 SMLoc MaxBytesLoc;
3395 bool HasFillExpr = false;
3396 int64_t FillExpr = 0;
3397 int64_t MaxBytesToFill = 0;
3398 SMLoc FillExprLoc;
3399
3400 auto parseAlign = [&]() -> bool {
3401 if (parseAbsoluteExpression(Alignment))
3402 return true;
3403 if (parseOptionalToken(AsmToken::Comma)) {
3404 // The fill expression can be omitted while specifying a maximum number of
3405 // alignment bytes, e.g:
3406 // .align 3,,4
3407 if (getTok().isNot(AsmToken::Comma)) {
3408 HasFillExpr = true;
3409 if (parseTokenLoc(FillExprLoc) || parseAbsoluteExpression(FillExpr))
3410 return true;
3411 }
3412 if (parseOptionalToken(AsmToken::Comma))
3413 if (parseTokenLoc(MaxBytesLoc) ||
3414 parseAbsoluteExpression(MaxBytesToFill))
3415 return true;
3416 }
3417 return parseEOL();
3418 };
3419
3420 if (checkForValidSection())
3421 return true;
3422 // Ignore empty '.p2align' directives for GNU-as compatibility
3423 if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
3424 Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
3425 return parseEOL();
3426 }
3427 if (parseAlign())
3428 return true;
3429
3430 // Always emit an alignment here even if we thrown an error.
3431 bool ReturnVal = false;
3432
3433 // Compute alignment in bytes.
3434 if (IsPow2) {
3435 // FIXME: Diagnose overflow.
3436 if (Alignment >= 32) {
3437 ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
3438 Alignment = 31;
3439 }
3440
3441 Alignment = 1ULL << Alignment;
3442 } else {
3443 // Reject alignments that aren't either a power of two or zero,
3444 // for gas compatibility. Alignment of zero is silently rounded
3445 // up to one.
3446 if (Alignment == 0)
3447 Alignment = 1;
3448 else if (!isPowerOf2_64(Alignment)) {
3449 ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
3450 Alignment = llvm::bit_floor<uint64_t>(Alignment);
3451 }
3452 if (!isUInt<32>(Alignment)) {
3453 ReturnVal |= Error(AlignmentLoc, "alignment must be smaller than 2**32");
3454 Alignment = 1u << 31;
3455 }
3456 }
3457
3458 if (HasFillExpr && FillExpr != 0) {
3459 MCSection *Sec = getStreamer().getCurrentSectionOnly();
3460 if (Sec && Sec->isVirtualSection()) {
3461 ReturnVal |=
3462 Warning(FillExprLoc, "ignoring non-zero fill value in " +
3463 Sec->getVirtualSectionKind() + " section '" +
3464 Sec->getName() + "'");
3465 FillExpr = 0;
3466 }
3467 }
3468
3469 // Diagnose non-sensical max bytes to align.
3470 if (MaxBytesLoc.isValid()) {
3471 if (MaxBytesToFill < 1) {
3472 ReturnVal |= Error(MaxBytesLoc,
3473 "alignment directive can never be satisfied in this "
3474 "many bytes, ignoring maximum bytes expression");
3475 MaxBytesToFill = 0;
3476 }
3477
3478 if (MaxBytesToFill >= Alignment) {
3479 Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
3480 "has no effect");
3481 MaxBytesToFill = 0;
3482 }
3483 }
3484
3485 // Check whether we should use optimal code alignment for this .align
3486 // directive.
3487 const MCSection *Section = getStreamer().getCurrentSectionOnly();
3488 assert(Section && "must have section to emit alignment");
3489 bool useCodeAlign = Section->useCodeAlign();
3490 if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
3491 ValueSize == 1 && useCodeAlign) {
3492 getStreamer().emitCodeAlignment(
3493 Align(Alignment), &getTargetParser().getSTI(), MaxBytesToFill);
3494 } else {
3495 // FIXME: Target specific behavior about how the "extra" bytes are filled.
3496 getStreamer().emitValueToAlignment(Align(Alignment), FillExpr, ValueSize,
3497 MaxBytesToFill);
3498 }
3499
3500 return ReturnVal;
3501}
3502
3503/// parseDirectiveFile
3504/// ::= .file filename
3505/// ::= .file number [directory] filename [md5 checksum] [source source-text]
3506bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
3507 // FIXME: I'm not sure what this is.
3508 int64_t FileNumber = -1;
3509 if (getLexer().is(AsmToken::Integer)) {
3510 FileNumber = getTok().getIntVal();
3511 Lex();
3512
3513 if (FileNumber < 0)
3514 return TokError("negative file number");
3515 }
3516
3517 std::string Path;
3518
3519 // Usually the directory and filename together, otherwise just the directory.
3520 // Allow the strings to have escaped octal character sequence.
3521 if (parseEscapedString(Path))
3522 return true;
3523
3524 StringRef Directory;
3526 std::string FilenameData;
3527 if (getLexer().is(AsmToken::String)) {
3528 if (check(FileNumber == -1,
3529 "explicit path specified, but no file number") ||
3530 parseEscapedString(FilenameData))
3531 return true;
3532 Filename = FilenameData;
3533 Directory = Path;
3534 } else {
3535 Filename = Path;
3536 }
3537
3538 uint64_t MD5Hi, MD5Lo;
3539 bool HasMD5 = false;
3540
3541 std::optional<StringRef> Source;
3542 bool HasSource = false;
3543 std::string SourceString;
3544
3545 while (!parseOptionalToken(AsmToken::EndOfStatement)) {
3547 if (check(getTok().isNot(AsmToken::Identifier),
3548 "unexpected token in '.file' directive") ||
3549 parseIdentifier(Keyword))
3550 return true;
3551 if (Keyword == "md5") {
3552 HasMD5 = true;
3553 if (check(FileNumber == -1,
3554 "MD5 checksum specified, but no file number") ||
3555 parseHexOcta(*this, MD5Hi, MD5Lo))
3556 return true;
3557 } else if (Keyword == "source") {
3558 HasSource = true;
3559 if (check(FileNumber == -1,
3560 "source specified, but no file number") ||
3561 check(getTok().isNot(AsmToken::String),
3562 "unexpected token in '.file' directive") ||
3563 parseEscapedString(SourceString))
3564 return true;
3565 } else {
3566 return TokError("unexpected token in '.file' directive");
3567 }
3568 }
3569
3570 if (FileNumber == -1) {
3571 // Ignore the directive if there is no number and the target doesn't support
3572 // numberless .file directives. This allows some portability of assembler
3573 // between different object file formats.
3574 if (getContext().getAsmInfo()->hasSingleParameterDotFile())
3575 getStreamer().emitFileDirective(Filename);
3576 } else {
3577 // In case there is a -g option as well as debug info from directive .file,
3578 // we turn off the -g option, directly use the existing debug info instead.
3579 // Throw away any implicit file table for the assembler source.
3580 if (Ctx.getGenDwarfForAssembly()) {
3582 Ctx.setGenDwarfForAssembly(false);
3583 }
3584
3585 std::optional<MD5::MD5Result> CKMem;
3586 if (HasMD5) {
3587 MD5::MD5Result Sum;
3588 for (unsigned i = 0; i != 8; ++i) {
3589 Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
3590 Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
3591 }
3592 CKMem = Sum;
3593 }
3594 if (HasSource) {
3595 char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
3596 memcpy(SourceBuf, SourceString.data(), SourceString.size());
3597 Source = StringRef(SourceBuf, SourceString.size());
3598 }
3599 if (FileNumber == 0) {
3600 // Upgrade to Version 5 for assembly actions like clang -c a.s.
3601 if (Ctx.getDwarfVersion() < 5)
3602 Ctx.setDwarfVersion(5);
3603 getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
3604 } else {
3605 Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
3606 FileNumber, Directory, Filename, CKMem, Source);
3607 if (!FileNumOrErr)
3608 return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
3609 }
3610 // Alert the user if there are some .file directives with MD5 and some not.
3611 // But only do that once.
3612 if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
3613 ReportedInconsistentMD5 = true;
3614 return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
3615 }
3616 }
3617
3618 return false;
3619}
3620
3621/// parseDirectiveLine
3622/// ::= .line [number]
3623bool AsmParser::parseDirectiveLine() {
3624 int64_t LineNumber;
3625 if (getLexer().is(AsmToken::Integer)) {
3626 if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
3627 return true;
3628 (void)LineNumber;
3629 // FIXME: Do something with the .line.
3630 }
3631 return parseEOL();
3632}
3633
3634/// parseDirectiveLoc
3635/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
3636/// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
3637/// The first number is a file number, must have been previously assigned with
3638/// a .file directive, the second number is the line number and optionally the
3639/// third number is a column position (zero if not specified). The remaining
3640/// optional items are .loc sub-directives.
3641bool AsmParser::parseDirectiveLoc() {
3642 int64_t FileNumber = 0, LineNumber = 0;
3643 SMLoc Loc = getTok().getLoc();
3644 if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
3645 check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
3646 "file number less than one in '.loc' directive") ||
3647 check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
3648 "unassigned file number in '.loc' directive"))
3649 return true;
3650
3651 // optional
3652 if (getLexer().is(AsmToken::Integer)) {
3653 LineNumber = getTok().getIntVal();
3654 if (LineNumber < 0)
3655 return TokError("line number less than zero in '.loc' directive");
3656 Lex();
3657 }
3658
3659 int64_t ColumnPos = 0;
3660 if (getLexer().is(AsmToken::Integer)) {
3661 ColumnPos = getTok().getIntVal();
3662 if (ColumnPos < 0)
3663 return TokError("column position less than zero in '.loc' directive");
3664 Lex();
3665 }
3666
3667 auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
3668 unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
3669 unsigned Isa = 0;
3670 int64_t Discriminator = 0;
3671
3672 auto parseLocOp = [&]() -> bool {
3674 SMLoc Loc = getTok().getLoc();
3675 if (parseIdentifier(Name))
3676 return TokError("unexpected token in '.loc' directive");
3677
3678 if (Name == "basic_block")
3680 else if (Name == "prologue_end")
3682 else if (Name == "epilogue_begin")
3684 else if (Name == "is_stmt") {
3685 Loc = getTok().getLoc();
3686 const MCExpr *Value;
3687 if (parseExpression(Value))
3688 return true;
3689 // The expression must be the constant 0 or 1.
3690 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3691 int Value = MCE->getValue();
3692 if (Value == 0)
3693 Flags &= ~DWARF2_FLAG_IS_STMT;
3694 else if (Value == 1)
3696 else
3697 return Error(Loc, "is_stmt value not 0 or 1");
3698 } else {
3699 return Error(Loc, "is_stmt value not the constant value of 0 or 1");
3700 }
3701 } else if (Name == "isa") {
3702 Loc = getTok().getLoc();
3703 const MCExpr *Value;
3704 if (parseExpression(Value))
3705 return true;
3706 // The expression must be a constant greater or equal to 0.
3707 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3708 int Value = MCE->getValue();
3709 if (Value < 0)
3710 return Error(Loc, "isa number less than zero");
3711 Isa = Value;
3712 } else {
3713 return Error(Loc, "isa number not a constant value");
3714 }
3715 } else if (Name == "discriminator") {
3716 if (parseAbsoluteExpression(Discriminator))
3717 return true;
3718 } else {
3719 return Error(Loc, "unknown sub-directive in '.loc' directive");
3720 }
3721 return false;
3722 };
3723
3724 if (parseMany(parseLocOp, false /*hasComma*/))
3725 return true;
3726
3727 getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
3728 Isa, Discriminator, StringRef());
3729
3730 return false;
3731}
3732
3733/// parseDirectiveStabs
3734/// ::= .stabs string, number, number, number
3735bool AsmParser::parseDirectiveStabs() {
3736 return TokError("unsupported directive '.stabs'");
3737}
3738
3739/// parseDirectiveCVFile
3740/// ::= .cv_file number filename [checksum] [checksumkind]
3741bool AsmParser::parseDirectiveCVFile() {
3742 SMLoc FileNumberLoc = getTok().getLoc();
3743 int64_t FileNumber;
3744 std::string Filename;
3745 std::string Checksum;
3746 int64_t ChecksumKind = 0;
3747
3748 if (parseIntToken(FileNumber,
3749 "expected file number in '.cv_file' directive") ||
3750 check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
3751 check(getTok().isNot(AsmToken::String),
3752 "unexpected token in '.cv_file' directive") ||
3753 parseEscapedString(Filename))
3754 return true;
3755 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
3756 if (check(getTok().isNot(AsmToken::String),
3757 "unexpected token in '.cv_file' directive") ||
3758 parseEscapedString(Checksum) ||
3759 parseIntToken(ChecksumKind,
3760 "expected checksum kind in '.cv_file' directive") ||
3761 parseEOL())
3762 return true;
3763 }
3764
3765 Checksum = fromHex(Checksum);
3766 void *CKMem = Ctx.allocate(Checksum.size(), 1);
3767 memcpy(CKMem, Checksum.data(), Checksum.size());
3768 ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
3769 Checksum.size());
3770
3771 if (!getStreamer().emitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
3772 static_cast<uint8_t>(ChecksumKind)))
3773 return Error(FileNumberLoc, "file number already allocated");
3774
3775 return false;
3776}
3777
3778bool AsmParser::parseCVFunctionId(int64_t &FunctionId,
3779 StringRef DirectiveName) {
3780 SMLoc Loc;
3781 return parseTokenLoc(Loc) ||
3782 parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
3783 "' directive") ||
3784 check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
3785 "expected function id within range [0, UINT_MAX)");
3786}
3787
3788bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
3789 SMLoc Loc;
3790 return parseTokenLoc(Loc) ||
3791 parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
3792 "' directive") ||
3793 check(FileNumber < 1, Loc, "file number less than one in '" +
3794 DirectiveName + "' directive") ||
3795 check(!getCVContext().isValidFileNumber(FileNumber), Loc,
3796 "unassigned file number in '" + DirectiveName + "' directive");
3797}
3798
3799/// parseDirectiveCVFuncId
3800/// ::= .cv_func_id FunctionId
3801///
3802/// Introduces a function ID that can be used with .cv_loc.
3803bool AsmParser::parseDirectiveCVFuncId() {
3804 SMLoc FunctionIdLoc = getTok().getLoc();
3805 int64_t FunctionId;
3806
3807 if (parseCVFunctionId(FunctionId, ".cv_func_id") || parseEOL())
3808 return true;
3809
3810 if (!getStreamer().emitCVFuncIdDirective(FunctionId))
3811 return Error(FunctionIdLoc, "function id already allocated");
3812
3813 return false;
3814}
3815
3816/// parseDirectiveCVInlineSiteId
3817/// ::= .cv_inline_site_id FunctionId
3818/// "within" IAFunc
3819/// "inlined_at" IAFile IALine [IACol]
3820///
3821/// Introduces a function ID that can be used with .cv_loc. Includes "inlined
3822/// at" source location information for use in the line table of the caller,
3823/// whether the caller is a real function or another inlined call site.
3824bool AsmParser::parseDirectiveCVInlineSiteId() {
3825 SMLoc FunctionIdLoc = getTok().getLoc();
3826 int64_t FunctionId;
3827 int64_t IAFunc;
3828 int64_t IAFile;
3829 int64_t IALine;
3830 int64_t IACol = 0;
3831
3832 // FunctionId
3833 if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
3834 return true;
3835
3836 // "within"
3837 if (check((getLexer().isNot(AsmToken::Identifier) ||
3838 getTok().getIdentifier() != "within"),
3839 "expected 'within' identifier in '.cv_inline_site_id' directive"))
3840 return true;
3841 Lex();
3842
3843 // IAFunc
3844 if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
3845 return true;
3846
3847 // "inlined_at"
3848 if (check((getLexer().isNot(AsmToken::Identifier) ||
3849 getTok().getIdentifier() != "inlined_at"),
3850 "expected 'inlined_at' identifier in '.cv_inline_site_id' "
3851 "directive") )
3852 return true;
3853 Lex();
3854
3855 // IAFile IALine
3856 if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
3857 parseIntToken(IALine, "expected line number after 'inlined_at'"))
3858 return true;
3859
3860 // [IACol]
3861 if (getLexer().is(AsmToken::Integer)) {
3862 IACol = getTok().getIntVal();
3863 Lex();
3864 }
3865
3866 if (parseEOL())
3867 return true;
3868
3869 if (!getStreamer().emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
3870 IALine, IACol, FunctionIdLoc))
3871 return Error(FunctionIdLoc, "function id already allocated");
3872
3873 return false;
3874}
3875
3876/// parseDirectiveCVLoc
3877/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
3878/// [is_stmt VALUE]
3879/// The first number is a file number, must have been previously assigned with
3880/// a .file directive, the second number is the line number and optionally the
3881/// third number is a column position (zero if not specified). The remaining
3882/// optional items are .loc sub-directives.
3883bool AsmParser::parseDirectiveCVLoc() {
3884 SMLoc DirectiveLoc = getTok().getLoc();
3885 int64_t FunctionId, FileNumber;
3886 if (parseCVFunctionId(FunctionId, ".cv_loc") ||
3887 parseCVFileId(FileNumber, ".cv_loc"))
3888 return true;
3889
3890 int64_t LineNumber = 0;
3891 if (getLexer().is(AsmToken::Integer)) {
3892 LineNumber = getTok().getIntVal();
3893 if (LineNumber < 0)
3894 return TokError("line number less than zero in '.cv_loc' directive");
3895 Lex();
3896 }
3897
3898 int64_t ColumnPos = 0;
3899 if (getLexer().is(AsmToken::Integer)) {
3900 ColumnPos = getTok().getIntVal();
3901 if (ColumnPos < 0)
3902 return TokError("column position less than zero in '.cv_loc' directive");
3903 Lex();
3904 }
3905
3906 bool PrologueEnd = false;
3907 uint64_t IsStmt = 0;
3908
3909 auto parseOp = [&]() -> bool {
3911 SMLoc Loc = getTok().getLoc();
3912 if (parseIdentifier(Name))
3913 return TokError("unexpected token in '.cv_loc' directive");
3914 if (Name == "prologue_end")
3915 PrologueEnd = true;
3916 else if (Name == "is_stmt") {
3917 Loc = getTok().getLoc();
3918 const MCExpr *Value;
3919 if (parseExpression(Value))
3920 return true;
3921 // The expression must be the constant 0 or 1.
3922 IsStmt = ~0ULL;
3923 if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
3924 IsStmt = MCE->getValue();
3925
3926 if (IsStmt > 1)
3927 return Error(Loc, "is_stmt value not 0 or 1");
3928 } else {
3929 return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
3930 }
3931 return false;
3932 };
3933
3934 if (parseMany(parseOp, false /*hasComma*/))
3935 return true;
3936
3937 getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
3938 ColumnPos, PrologueEnd, IsStmt, StringRef(),
3939 DirectiveLoc);
3940 return false;
3941}
3942
3943/// parseDirectiveCVLinetable
3944/// ::= .cv_linetable FunctionId, FnStart, FnEnd
3945bool AsmParser::parseDirectiveCVLinetable() {
3946 int64_t FunctionId;
3947 StringRef FnStartName, FnEndName;
3948 SMLoc Loc = getTok().getLoc();
3949 if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() ||
3950 parseTokenLoc(Loc) ||
3951 check(parseIdentifier(FnStartName), Loc,
3952 "expected identifier in directive") ||
3953 parseComma() || parseTokenLoc(Loc) ||
3954 check(parseIdentifier(FnEndName), Loc,
3955 "expected identifier in directive"))
3956 return true;
3957
3958 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
3959 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
3960
3961 getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
3962 return false;
3963}
3964
3965/// parseDirectiveCVInlineLinetable
3966/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
3967bool AsmParser::parseDirectiveCVInlineLinetable() {
3968 int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
3969 StringRef FnStartName, FnEndName;
3970 SMLoc Loc = getTok().getLoc();
3971 if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
3972 parseTokenLoc(Loc) ||
3973 parseIntToken(
3974 SourceFileId,
3975 "expected SourceField in '.cv_inline_linetable' directive") ||
3976 check(SourceFileId <= 0, Loc,
3977 "File id less than zero in '.cv_inline_linetable' directive") ||
3978 parseTokenLoc(Loc) ||
3979 parseIntToken(
3980 SourceLineNum,
3981 "expected SourceLineNum in '.cv_inline_linetable' directive") ||
3982 check(SourceLineNum < 0, Loc,
3983 "Line number less than zero in '.cv_inline_linetable' directive") ||
3984 parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
3985 "expected identifier in directive") ||
3986 parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
3987 "expected identifier in directive"))
3988 return true;
3989
3990 if (parseEOL())
3991 return true;
3992
3993 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
3994 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
3995 getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
3996 SourceLineNum, FnStartSym,
3997 FnEndSym);
3998 return false;
3999}
4000
4001void AsmParser::initializeCVDefRangeTypeMap() {
4002 CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
4003 CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
4004 CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
4005 CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
4006}
4007
4008/// parseDirectiveCVDefRange
4009/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
4010bool AsmParser::parseDirectiveCVDefRange() {
4011 SMLoc Loc;
4012 std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
4013 while (getLexer().is(AsmToken::Identifier)) {
4014 Loc = getLexer().getLoc();
4015 StringRef GapStartName;
4016 if (parseIdentifier(GapStartName))
4017 return Error(Loc, "expected identifier in directive");
4018 MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
4019
4020 Loc = getLexer().getLoc();
4021 StringRef GapEndName;
4022 if (parseIdentifier(GapEndName))
4023 return Error(Loc, "expected identifier in directive");
4024 MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
4025
4026 Ranges.push_back({GapStartSym, GapEndSym});
4027 }
4028
4029 StringRef CVDefRangeTypeStr;
4030 if (parseToken(
4032 "expected comma before def_range type in .cv_def_range directive") ||
4033 parseIdentifier(CVDefRangeTypeStr))
4034 return Error(Loc, "expected def_range type in directive");
4035
4037 CVDefRangeTypeMap.find(CVDefRangeTypeStr);
4038 CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
4039 ? CVDR_DEFRANGE
4040 : CVTypeIt->getValue();
4041 switch (CVDRType) {
4042 case CVDR_DEFRANGE_REGISTER: {
4043 int64_t DRRegister;
4044 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4045 ".cv_def_range directive") ||
4046 parseAbsoluteExpression(DRRegister))
4047 return Error(Loc, "expected register number");
4048
4050 DRHdr.Register = DRRegister;
4051 DRHdr.MayHaveNoName = 0;
4052 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4053 break;
4054 }
4055 case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
4056 int64_t DROffset;
4057 if (parseToken(AsmToken::Comma,
4058 "expected comma before offset in .cv_def_range directive") ||
4059 parseAbsoluteExpression(DROffset))
4060 return Error(Loc, "expected offset value");
4061
4063 DRHdr.Offset = DROffset;
4064 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4065 break;
4066 }
4067 case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
4068 int64_t DRRegister;
4069 int64_t DROffsetInParent;
4070 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4071 ".cv_def_range directive") ||
4072 parseAbsoluteExpression(DRRegister))
4073 return Error(Loc, "expected register number");
4074 if (parseToken(AsmToken::Comma,
4075 "expected comma before offset in .cv_def_range directive") ||
4076 parseAbsoluteExpression(DROffsetInParent))
4077 return Error(Loc, "expected offset value");
4078
4080 DRHdr.Register = DRRegister;
4081 DRHdr.MayHaveNoName = 0;
4082 DRHdr.OffsetInParent = DROffsetInParent;
4083 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4084 break;
4085 }
4086 case CVDR_DEFRANGE_REGISTER_REL: {
4087 int64_t DRRegister;
4088 int64_t DRFlags;
4089 int64_t DRBasePointerOffset;
4090 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4091 ".cv_def_range directive") ||
4092 parseAbsoluteExpression(DRRegister))
4093 return Error(Loc, "expected register value");
4094 if (parseToken(
4096 "expected comma before flag value in .cv_def_range directive") ||
4097 parseAbsoluteExpression(DRFlags))
4098 return Error(Loc, "expected flag value");
4099 if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
4100 "in .cv_def_range directive") ||
4101 parseAbsoluteExpression(DRBasePointerOffset))
4102 return Error(Loc, "expected base pointer offset value");
4103
4105 DRHdr.Register = DRRegister;
4106 DRHdr.Flags = DRFlags;
4107 DRHdr.BasePointerOffset = DRBasePointerOffset;
4108 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4109 break;
4110 }
4111 default:
4112 return Error(Loc, "unexpected def_range type in .cv_def_range directive");
4113 }
4114 return true;
4115}
4116
4117/// parseDirectiveCVString
4118/// ::= .cv_stringtable "string"
4119bool AsmParser::parseDirectiveCVString() {
4120 std::string Data;
4121 if (checkForValidSection() || parseEscapedString(Data))
4122 return true;
4123
4124 // Put the string in the table and emit the offset.
4125 std::pair<StringRef, unsigned> Insertion =
4126 getCVContext().addToStringTable(Data);
4127 getStreamer().emitInt32(Insertion.second);
4128 return false;
4129}
4130
4131/// parseDirectiveCVStringTable
4132/// ::= .cv_stringtable
4133bool AsmParser::parseDirectiveCVStringTable() {
4134 getStreamer().emitCVStringTableDirective();
4135 return false;
4136}
4137
4138/// parseDirectiveCVFileChecksums
4139/// ::= .cv_filechecksums
4140bool AsmParser::parseDirectiveCVFileChecksums() {
4141 getStreamer().emitCVFileChecksumsDirective();
4142 return false;
4143}
4144
4145/// parseDirectiveCVFileChecksumOffset
4146/// ::= .cv_filechecksumoffset fileno
4147bool AsmParser::parseDirectiveCVFileChecksumOffset() {
4148 int64_t FileNo;
4149 if (parseIntToken(FileNo, "expected identifier in directive"))
4150 return true;
4151 if (parseEOL())
4152 return true;
4153 getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
4154 return false;
4155}
4156
4157/// parseDirectiveCVFPOData
4158/// ::= .cv_fpo_data procsym
4159bool AsmParser::parseDirectiveCVFPOData() {
4160 SMLoc DirLoc = getLexer().getLoc();
4161 StringRef ProcName;
4162 if (parseIdentifier(ProcName))
4163 return TokError("expected symbol name");
4164 if (parseEOL())
4165 return true;
4166 MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
4167 getStreamer().emitCVFPOData(ProcSym, DirLoc);
4168 return false;
4169}
4170
4171/// parseDirectiveCFISections
4172/// ::= .cfi_sections section [, section]
4173bool AsmParser::parseDirectiveCFISections() {
4175 bool EH = false;
4176 bool Debug = false;
4177
4178 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4179 for (;;) {
4180 if (parseIdentifier(Name))
4181 return TokError("expected .eh_frame or .debug_frame");
4182 if (Name == ".eh_frame")
4183 EH = true;
4184 else if (Name == ".debug_frame")
4185 Debug = true;
4186 if (parseOptionalToken(AsmToken::EndOfStatement))
4187 break;
4188 if (parseComma())
4189 return true;
4190 }
4191 }
4192 getStreamer().emitCFISections(EH, Debug);
4193 return false;
4194}
4195
4196/// parseDirectiveCFIStartProc
4197/// ::= .cfi_startproc [simple]
4198bool AsmParser::parseDirectiveCFIStartProc() {
4199 CFIStartProcLoc = StartTokLoc;
4200
4202 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4203 if (check(parseIdentifier(Simple) || Simple != "simple",
4204 "unexpected token") ||
4205 parseEOL())
4206 return true;
4207 }
4208
4209 // TODO(kristina): Deal with a corner case of incorrect diagnostic context
4210 // being produced if this directive is emitted as part of preprocessor macro
4211 // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
4212 // Tools like llvm-mc on the other hand are not affected by it, and report
4213 // correct context information.
4214 getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
4215 return false;
4216}
4217
4218/// parseDirectiveCFIEndProc
4219/// ::= .cfi_endproc
4220bool AsmParser::parseDirectiveCFIEndProc() {
4221 CFIStartProcLoc = std::nullopt;
4222
4223 if (parseEOL())
4224 return true;
4225
4226 getStreamer().emitCFIEndProc();
4227 return false;
4228}
4229
4230/// parse register name or number.
4231bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
4232 SMLoc DirectiveLoc) {
4233 MCRegister RegNo;
4234
4235 if (getLexer().isNot(AsmToken::Integer)) {
4236 if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc))
4237 return true;
4238 Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
4239 } else
4240 return parseAbsoluteExpression(Register);
4241
4242 return false;
4243}
4244
4245/// parseDirectiveCFIDefCfa
4246/// ::= .cfi_def_cfa register, offset
4247bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
4248 int64_t Register = 0, Offset = 0;
4249 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4250 parseAbsoluteExpression(Offset) || parseEOL())
4251 return true;
4252
4253 getStreamer().emitCFIDefCfa(Register, Offset, DirectiveLoc);
4254 return false;
4255}
4256
4257/// parseDirectiveCFIDefCfaOffset
4258/// ::= .cfi_def_cfa_offset offset
4259bool AsmParser::parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc) {
4260 int64_t Offset = 0;
4261 if (parseAbsoluteExpression(Offset) || parseEOL())
4262 return true;
4263
4264 getStreamer().emitCFIDefCfaOffset(Offset, DirectiveLoc);
4265 return false;
4266}
4267
4268/// parseDirectiveCFIRegister
4269/// ::= .cfi_register register, register
4270bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
4271 int64_t Register1 = 0, Register2 = 0;
4272 if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || parseComma() ||
4273 parseRegisterOrRegisterNumber(Register2, DirectiveLoc) || parseEOL())
4274 return true;
4275
4276 getStreamer().emitCFIRegister(Register1, Register2, DirectiveLoc);
4277 return false;
4278}
4279
4280/// parseDirectiveCFIWindowSave
4281/// ::= .cfi_window_save
4282bool AsmParser::parseDirectiveCFIWindowSave(SMLoc DirectiveLoc) {
4283 if (parseEOL())
4284 return true;
4285 getStreamer().emitCFIWindowSave(DirectiveLoc);
4286 return false;
4287}
4288
4289/// parseDirectiveCFIAdjustCfaOffset
4290/// ::= .cfi_adjust_cfa_offset adjustment
4291bool AsmParser::parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc) {
4292 int64_t Adjustment = 0;
4293 if (parseAbsoluteExpression(Adjustment) || parseEOL())
4294 return true;
4295
4296 getStreamer().emitCFIAdjustCfaOffset(Adjustment, DirectiveLoc);
4297 return false;
4298}
4299
4300/// parseDirectiveCFIDefCfaRegister
4301/// ::= .cfi_def_cfa_register register
4302bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
4303 int64_t Register = 0;
4304 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4305 return true;
4306
4307 getStreamer().emitCFIDefCfaRegister(Register, DirectiveLoc);
4308 return false;
4309}
4310
4311/// parseDirectiveCFILLVMDefAspaceCfa
4312/// ::= .cfi_llvm_def_aspace_cfa register, offset, address_space
4313bool AsmParser::parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc) {
4314 int64_t Register = 0, Offset = 0, AddressSpace = 0;
4315 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4316 parseAbsoluteExpression(Offset) || parseComma() ||
4317 parseAbsoluteExpression(AddressSpace) || parseEOL())
4318 return true;
4319
4320 getStreamer().emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace,
4321 DirectiveLoc);
4322 return false;
4323}
4324
4325/// parseDirectiveCFIOffset
4326/// ::= .cfi_offset register, offset
4327bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
4328 int64_t Register = 0;
4329 int64_t Offset = 0;
4330
4331 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4332 parseAbsoluteExpression(Offset) || parseEOL())
4333 return true;
4334
4335 getStreamer().emitCFIOffset(Register, Offset, DirectiveLoc);
4336 return false;
4337}
4338
4339/// parseDirectiveCFIRelOffset
4340/// ::= .cfi_rel_offset register, offset
4341bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
4342 int64_t Register = 0, Offset = 0;
4343
4344 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4345 parseAbsoluteExpression(Offset) || parseEOL())
4346 return true;
4347
4348 getStreamer().emitCFIRelOffset(Register, Offset, DirectiveLoc);
4349 return false;
4350}
4351
4352static bool isValidEncoding(int64_t Encoding) {
4353 if (Encoding & ~0xff)
4354 return false;
4355
4356 if (Encoding == dwarf::DW_EH_PE_omit)
4357 return true;
4358
4359 const unsigned Format = Encoding & 0xf;
4360 if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
4361 Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
4362 Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
4363 Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
4364 return false;
4365
4366 const unsigned Application = Encoding & 0x70;
4367 if (Application != dwarf::DW_EH_PE_absptr &&
4368 Application != dwarf::DW_EH_PE_pcrel)
4369 return false;
4370
4371 return true;
4372}
4373
4374/// parseDirectiveCFIPersonalityOrLsda
4375/// IsPersonality true for cfi_personality, false for cfi_lsda
4376/// ::= .cfi_personality encoding, [symbol_name]
4377/// ::= .cfi_lsda encoding, [symbol_name]
4378bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
4379 int64_t Encoding = 0;
4380 if (parseAbsoluteExpression(Encoding))
4381 return true;
4382 if (Encoding == dwarf::DW_EH_PE_omit)
4383 return false;
4384
4386 if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
4387 parseComma() ||
4388 check(parseIdentifier(Name), "expected identifier in directive") ||
4389 parseEOL())
4390 return true;
4391
4392 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4393
4394 if (IsPersonality)
4395 getStreamer().emitCFIPersonality(Sym, Encoding);
4396 else
4397 getStreamer().emitCFILsda(Sym, Encoding);
4398 return false;
4399}
4400
4401/// parseDirectiveCFIRememberState
4402/// ::= .cfi_remember_state
4403bool AsmParser::parseDirectiveCFIRememberState(SMLoc DirectiveLoc) {
4404 if (parseEOL())
4405 return true;
4406 getStreamer().emitCFIRememberState(DirectiveLoc);
4407 return false;
4408}
4409
4410/// parseDirectiveCFIRestoreState
4411/// ::= .cfi_remember_state
4412bool AsmParser::parseDirectiveCFIRestoreState(SMLoc DirectiveLoc) {
4413 if (parseEOL())
4414 return true;
4415 getStreamer().emitCFIRestoreState(DirectiveLoc);
4416 return false;
4417}
4418
4419/// parseDirectiveCFISameValue
4420/// ::= .cfi_same_value register
4421bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
4422 int64_t Register = 0;
4423
4424 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4425 return true;
4426
4427 getStreamer().emitCFISameValue(Register, DirectiveLoc);
4428 return false;
4429}
4430
4431/// parseDirectiveCFIRestore
4432/// ::= .cfi_restore register
4433bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
4434 int64_t Register = 0;
4435 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4436 return true;
4437
4438 getStreamer().emitCFIRestore(Register, DirectiveLoc);
4439 return false;
4440}
4441
4442/// parseDirectiveCFIEscape
4443/// ::= .cfi_escape expression[,...]
4444bool AsmParser::parseDirectiveCFIEscape(SMLoc DirectiveLoc) {
4445 std::string Values;
4446 int64_t CurrValue;
4447 if (parseAbsoluteExpression(CurrValue))
4448 return true;
4449
4450 Values.push_back((uint8_t)CurrValue);
4451
4452 while (getLexer().is(AsmToken::Comma)) {
4453 Lex();
4454
4455 if (parseAbsoluteExpression(CurrValue))
4456 return true;
4457
4458 Values.push_back((uint8_t)CurrValue);
4459 }
4460
4461 getStreamer().emitCFIEscape(Values, DirectiveLoc);
4462 return false;
4463}
4464
4465/// parseDirectiveCFIReturnColumn
4466/// ::= .cfi_return_column register
4467bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
4468 int64_t Register = 0;
4469 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4470 return true;
4471 getStreamer().emitCFIReturnColumn(Register);
4472 return false;
4473}
4474
4475/// parseDirectiveCFISignalFrame
4476/// ::= .cfi_signal_frame
4477bool AsmParser::parseDirectiveCFISignalFrame(SMLoc DirectiveLoc) {
4478 if (parseEOL())
4479 return true;
4480
4481 getStreamer().emitCFISignalFrame();
4482 return false;
4483}
4484
4485/// parseDirectiveCFIUndefined
4486/// ::= .cfi_undefined register
4487bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
4488 int64_t Register = 0;
4489
4490 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4491 return true;
4492
4493 getStreamer().emitCFIUndefined(Register, DirectiveLoc);
4494 return false;
4495}
4496
4497/// parseDirectiveAltmacro
4498/// ::= .altmacro
4499/// ::= .noaltmacro
4500bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
4501 if (parseEOL())
4502 return true;
4503 AltMacroMode = (Directive == ".altmacro");
4504 return false;
4505}
4506
4507/// parseDirectiveMacrosOnOff
4508/// ::= .macros_on
4509/// ::= .macros_off
4510bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
4511 if (parseEOL())
4512 return true;
4513 setMacrosEnabled(Directive == ".macros_on");
4514 return false;
4515}
4516
4517/// parseDirectiveMacro
4518/// ::= .macro name[,] [parameters]
4519bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
4521 if (parseIdentifier(Name))
4522 return TokError("expected identifier in '.macro' directive");
4523
4524 if (getLexer().is(AsmToken::Comma))
4525 Lex();
4526
4528 while (getLexer().isNot(AsmToken::EndOfStatement)) {
4529
4530 if (!Parameters.empty() && Parameters.back().Vararg)
4531 return Error(Lexer.getLoc(), "vararg parameter '" +
4532 Parameters.back().Name +
4533 "' should be the last parameter");
4534
4535 MCAsmMacroParameter Parameter;
4536 if (parseIdentifier(Parameter.Name))
4537 return TokError("expected identifier in '.macro' directive");
4538
4539 // Emit an error if two (or more) named parameters share the same name
4540 for (const MCAsmMacroParameter& CurrParam : Parameters)
4541 if (CurrParam.Name == Parameter.Name)
4542 return TokError("macro '" + Name + "' has multiple parameters"
4543 " named '" + Parameter.Name + "'");
4544
4545 if (Lexer.is(AsmToken::Colon)) {
4546 Lex(); // consume ':'
4547
4548 SMLoc QualLoc;
4550
4551 QualLoc = Lexer.getLoc();
4552 if (parseIdentifier(Qualifier))
4553 return Error(QualLoc, "missing parameter qualifier for "
4554 "'" + Parameter.Name + "' in macro '" + Name + "'");
4555
4556 if (Qualifier == "req")
4557 Parameter.Required = true;
4558 else if (Qualifier == "vararg")
4559 Parameter.Vararg = true;
4560 else
4561 return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
4562 "for '" + Parameter.Name + "' in macro '" + Name + "'");
4563 }
4564
4565 if (getLexer().is(AsmToken::Equal)) {
4566 Lex();
4567
4568 SMLoc ParamLoc;
4569
4570 ParamLoc = Lexer.getLoc();
4571 if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
4572 return true;
4573
4574 if (Parameter.Required)
4575 Warning(ParamLoc, "pointless default value for required parameter "
4576 "'" + Parameter.Name + "' in macro '" + Name + "'");
4577 }
4578
4579 Parameters.push_back(std::move(Parameter));
4580
4581 if (getLexer().is(AsmToken::Comma))
4582 Lex();
4583 }
4584
4585 // Eat just the end of statement.
4586 Lexer.Lex();
4587
4588 // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors
4589 AsmToken EndToken, StartToken = getTok();
4590 unsigned MacroDepth = 0;
4591 // Lex the macro definition.
4592 while (true) {
4593 // Ignore Lexing errors in macros.
4594 while (Lexer.is(AsmToken::Error)) {
4595 Lexer.Lex();
4596 }
4597
4598 // Check whether we have reached the end of the file.
4599 if (getLexer().is(AsmToken::Eof))
4600 return Error(DirectiveLoc, "no matching '.endmacro' in definition");
4601
4602 // Otherwise, check whether we have reach the .endmacro or the start of a
4603 // preprocessor line marker.
4604 if (getLexer().is(AsmToken::Identifier)) {
4605 if (getTok().getIdentifier() == ".endm" ||
4606 getTok().getIdentifier() == ".endmacro") {
4607 if (MacroDepth == 0) { // Outermost macro.
4608 EndToken = getTok();
4609 Lexer.Lex();
4610 if (getLexer().isNot(AsmToken::EndOfStatement))
4611 return TokError("unexpected token in '" + EndToken.getIdentifier() +
4612 "' directive");
4613 break;
4614 } else {
4615 // Otherwise we just found the end of an inner macro.
4616 --MacroDepth;
4617 }
4618 } else if (getTok().getIdentifier() == ".macro") {
4619 // We allow nested macros. Those aren't instantiated until the outermost
4620 // macro is expanded so just ignore them for now.
4621 ++MacroDepth;
4622 }
4623 } else if (Lexer.is(AsmToken::HashDirective)) {
4624 (void)parseCppHashLineFilenameComment(getLexer().getLoc());
4625 }
4626
4627 // Otherwise, scan til the end of the statement.
4628 eatToEndOfStatement();
4629 }
4630
4631 if (getContext().lookupMacro(Name)) {
4632 return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
4633 }
4634
4635 const char *BodyStart = StartToken.getLoc().getPointer();
4636 const char *BodyEnd = EndToken.getLoc().getPointer();
4637 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4638 checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
4639 MCAsmMacro Macro(Name, Body, std::move(Parameters));
4640 DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
4641 Macro.dump());
4642 getContext().defineMacro(Name, std::move(Macro));
4643 return false;
4644}
4645
4646/// checkForBadMacro
4647///
4648/// With the support added for named parameters there may be code out there that
4649/// is transitioning from positional parameters. In versions of gas that did
4650/// not support named parameters they would be ignored on the macro definition.
4651/// But to support both styles of parameters this is not possible so if a macro
4652/// definition has named parameters but does not use them and has what appears
4653/// to be positional parameters, strings like $1, $2, ... and $n, then issue a
4654/// warning that the positional parameter found in body which have no effect.
4655/// Hoping the developer will either remove the named parameters from the macro
4656/// definition so the positional parameters get used if that was what was
4657/// intended or change the macro to use the named parameters. It is possible
4658/// this warning will trigger when the none of the named parameters are used
4659/// and the strings like $1 are infact to simply to be passed trough unchanged.
4660void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
4661 StringRef Body,
4662 ArrayRef<MCAsmMacroParameter> Parameters) {
4663 // If this macro is not defined with named parameters the warning we are
4664 // checking for here doesn't apply.
4665 unsigned NParameters = Parameters.size();
4666 if (NParameters == 0)
4667 return;
4668
4669 bool NamedParametersFound = false;
4670 bool PositionalParametersFound = false;
4671
4672 // Look at the body of the macro for use of both the named parameters and what
4673 // are likely to be positional parameters. This is what expandMacro() is
4674 // doing when it finds the parameters in the body.
4675 while (!Body.empty()) {
4676 // Scan for the next possible parameter.
4677 std::size_t End = Body.size(), Pos = 0;
4678 for (; Pos != End; ++Pos) {
4679 // Check for a substitution or escape.
4680 // This macro is defined with parameters, look for \foo, \bar, etc.
4681 if (Body[Pos] == '\\' && Pos + 1 != End)
4682 break;
4683
4684 // This macro should have parameters, but look for $0, $1, ..., $n too.
4685 if (Body[Pos] != '$' || Pos + 1 == End)
4686 continue;
4687 char Next = Body[Pos + 1];
4688 if (Next == '$' || Next == 'n' ||
4689 isdigit(static_cast<unsigned char>(Next)))
4690 break;
4691 }
4692
4693 // Check if we reached the end.
4694 if (Pos == End)
4695 break;
4696
4697 if (Body[Pos] == '$') {
4698 switch (Body[Pos + 1]) {
4699 // $$ => $
4700 case '$':
4701 break;
4702
4703 // $n => number of arguments
4704 case 'n':
4705 PositionalParametersFound = true;
4706 break;
4707
4708 // $[0-9] => argument
4709 default: {
4710 PositionalParametersFound = true;
4711 break;
4712 }
4713 }
4714 Pos += 2;
4715 } else {
4716 unsigned I = Pos + 1;
4717 while (isIdentifierChar(Body[I]) && I + 1 != End)
4718 ++I;
4719
4720 const char *Begin = Body.data() + Pos + 1;
4721 StringRef Argument(Begin, I - (Pos + 1));
4722 unsigned Index = 0;
4723 for (; Index < NParameters; ++Index)
4724 if (Parameters[Index].Name == Argument)
4725 break;
4726
4727 if (Index == NParameters) {
4728 if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
4729 Pos += 3;
4730 else {
4731 Pos = I;
4732 }
4733 } else {
4734 NamedParametersFound = true;
4735 Pos += 1 + Argument.size();
4736 }
4737 }
4738 // Update the scan point.
4739 Body = Body.substr(Pos);
4740 }
4741
4742 if (!NamedParametersFound && PositionalParametersFound)
4743 Warning(DirectiveLoc, "macro defined with named parameters which are not "
4744 "used in macro body, possible positional parameter "
4745 "found in body which will have no effect");
4746}
4747
4748/// parseDirectiveExitMacro
4749/// ::= .exitm
4750bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
4751 if (parseEOL())
4752 return true;
4753
4754 if (!isInsideMacroInstantiation())
4755 return TokError("unexpected '" + Directive + "' in file, "
4756 "no current macro definition");
4757
4758 // Exit all conditionals that are active in the current macro.
4759 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4760 TheCondState = TheCondStack.back();
4761 TheCondStack.pop_back();
4762 }
4763
4764 handleMacroExit();
4765 return false;
4766}
4767
4768/// parseDirectiveEndMacro
4769/// ::= .endm
4770/// ::= .endmacro
4771bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
4772 if (getLexer().isNot(AsmToken::EndOfStatement))
4773 return TokError("unexpected token in '" + Directive + "' directive");
4774
4775 // If we are inside a macro instantiation, terminate the current
4776 // instantiation.
4777 if (isInsideMacroInstantiation()) {
4778 handleMacroExit();
4779 return false;
4780 }
4781
4782 // Otherwise, this .endmacro is a stray entry in the file; well formed
4783 // .endmacro directives are handled during the macro definition parsing.
4784 return TokError("unexpected '" + Directive + "' in file, "
4785 "no current macro definition");
4786}
4787
4788/// parseDirectivePurgeMacro
4789/// ::= .purgem name
4790bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4792 SMLoc Loc;
4793 if (parseTokenLoc(Loc) ||
4794 check(parseIdentifier(Name), Loc,
4795 "expected identifier in '.purgem' directive") ||
4796 parseEOL())
4797 return true;
4798
4799 if (!getContext().lookupMacro(Name))
4800 return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
4801
4802 getContext().undefineMacro(Name);
4803 DEBUG_WITH_TYPE("asm-macros", dbgs()
4804 << "Un-defining macro: " << Name << "\n");
4805 return false;
4806}
4807
4808/// parseDirectiveBundleAlignMode
4809/// ::= {.bundle_align_mode} expression
4810bool AsmParser::parseDirectiveBundleAlignMode() {
4811 // Expect a single argument: an expression that evaluates to a constant
4812 // in the inclusive range 0-30.
4813 SMLoc ExprLoc = getLexer().getLoc();
4814 int64_t AlignSizePow2;
4815 if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||
4816 parseEOL() ||
4817 check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc,
4818 "invalid bundle alignment size (expected between 0 and 30)"))
4819 return true;
4820
4821 getStreamer().emitBundleAlignMode(Align(1ULL << AlignSizePow2));
4822 return false;
4823}
4824
4825/// parseDirectiveBundleLock
4826/// ::= {.bundle_lock} [align_to_end]
4827bool AsmParser::parseDirectiveBundleLock() {
4828 if (checkForValidSection())
4829 return true;
4830 bool AlignToEnd = false;
4831
4833 SMLoc Loc = getTok().getLoc();
4834 const char *kInvalidOptionError =
4835 "invalid option for '.bundle_lock' directive";
4836
4837 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4838 if (check(parseIdentifier(Option), Loc, kInvalidOptionError) ||
4839 check(Option != "align_to_end", Loc, kInvalidOptionError) || parseEOL())
4840 return true;
4841 AlignToEnd = true;
4842 }
4843
4844 getStreamer().emitBundleLock(AlignToEnd);
4845 return false;
4846}
4847
4848/// parseDirectiveBundleLock
4849/// ::= {.bundle_lock}
4850bool AsmParser::parseDirectiveBundleUnlock() {
4851 if (checkForValidSection() || parseEOL())
4852 return true;
4853
4854 getStreamer().emitBundleUnlock();
4855 return false;
4856}
4857
4858/// parseDirectiveSpace
4859/// ::= (.skip | .space) expression [ , expression ]
4860bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
4861 SMLoc NumBytesLoc = Lexer.getLoc();
4862 const MCExpr *NumBytes;
4863 if (checkForValidSection() || parseExpression(NumBytes))
4864 return true;
4865
4866 int64_t FillExpr = 0;
4867 if (parseOptionalToken(AsmToken::Comma))
4868 if (parseAbsoluteExpression(FillExpr))
4869 return true;
4870 if (parseEOL())
4871 return true;
4872
4873 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
4874 getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
4875
4876 return false;
4877}
4878
4879/// parseDirectiveDCB
4880/// ::= .dcb.{b, l, w} expression, expression
4881bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
4882 SMLoc NumValuesLoc = Lexer.getLoc();
4883 int64_t NumValues;
4884 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4885 return true;
4886
4887 if (NumValues < 0) {
4888 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4889 return false;
4890 }
4891
4892 if (parseComma())
4893 return true;
4894
4895 const MCExpr *Value;
4896 SMLoc ExprLoc = getLexer().getLoc();
4897 if (parseExpression(Value))
4898 return true;
4899
4900 // Special case constant expressions to match code generator.
4901 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
4902 assert(Size <= 8 && "Invalid size");
4903 uint64_t IntValue = MCE->getValue();
4904 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
4905 return Error(ExprLoc, "literal value out of range for directive");
4906 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4907 getStreamer().emitIntValue(IntValue, Size);
4908 } else {
4909 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4910 getStreamer().emitValue(Value, Size, ExprLoc);
4911 }
4912
4913 return parseEOL();
4914}
4915
4916/// parseDirectiveRealDCB
4917/// ::= .dcb.{d, s} expression, expression
4918bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {
4919 SMLoc NumValuesLoc = Lexer.getLoc();
4920 int64_t NumValues;
4921 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4922 return true;
4923
4924 if (NumValues < 0) {
4925 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4926 return false;
4927 }
4928
4929 if (parseComma())
4930 return true;
4931
4932 APInt AsInt;
4933 if (parseRealValue(Semantics, AsInt) || parseEOL())
4934 return true;
4935
4936 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4937 getStreamer().emitIntValue(AsInt.getLimitedValue(),
4938 AsInt.getBitWidth() / 8);
4939
4940 return false;
4941}
4942
4943/// parseDirectiveDS
4944/// ::= .ds.{b, d, l, p, s, w, x} expression
4945bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {
4946 SMLoc NumValuesLoc = Lexer.getLoc();
4947 int64_t NumValues;
4948 if (checkForValidSection() || parseAbsoluteExpression(NumValues) ||
4949 parseEOL())
4950 return true;
4951
4952 if (NumValues < 0) {
4953 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4954 return false;
4955 }
4956
4957 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4958 getStreamer().emitFill(Size, 0);
4959
4960 return false;
4961}
4962
4963/// parseDirectiveLEB128
4964/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
4965bool AsmParser::parseDirectiveLEB128(bool Signed) {
4966 if (checkForValidSection())
4967 return true;
4968
4969 auto parseOp = [&]() -> bool {
4970 const MCExpr *Value;
4971 if (parseExpression(Value))
4972 return true;
4973 if (Signed)
4974 getStreamer().emitSLEB128Value(Value);
4975 else
4976 getStreamer().emitULEB128Value(Value);
4977 return false;
4978 };
4979
4980 return parseMany(parseOp);
4981}
4982
4983/// parseDirectiveSymbolAttribute
4984/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
4985bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
4986 auto parseOp = [&]() -> bool {
4988 SMLoc Loc = getTok().getLoc();
4989 if (parseIdentifier(Name))
4990 return Error(Loc, "expected identifier");
4991
4992 if (discardLTOSymbol(Name))
4993 return false;
4994
4995 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4996
4997 // Assembler local symbols don't make any sense here, except for directives
4998 // that the symbol should be tagged.
4999 if (Sym->isTemporary() && Attr != MCSA_Memtag)
5000 return Error(Loc, "non-local symbol required");
5001
5002 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
5003 return Error(Loc, "unable to emit symbol attribute");
5004 return false;
5005 };
5006
5007 return parseMany(parseOp);
5008}
5009
5010/// parseDirectiveComm
5011/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
5012bool AsmParser::parseDirectiveComm(bool IsLocal) {
5013 if (checkForValidSection())
5014 return true;
5015
5016 SMLoc IDLoc = getLexer().getLoc();
5018 if (parseIdentifier(Name))
5019 return TokError("expected identifier in directive");
5020
5021 // Handle the identifier as the key symbol.
5022 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5023
5024 if (parseComma())
5025 return true;
5026
5027 int64_t Size;
5028 SMLoc SizeLoc = getLexer().getLoc();
5029 if (parseAbsoluteExpression(Size))
5030 return true;
5031
5032 int64_t Pow2Alignment = 0;
5033 SMLoc Pow2AlignmentLoc;
5034 if (getLexer().is(AsmToken::Comma)) {
5035 Lex();
5036 Pow2AlignmentLoc = getLexer().getLoc();
5037 if (parseAbsoluteExpression(Pow2Alignment))
5038 return true;
5039
5040 LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
5041 if (IsLocal && LCOMM == LCOMM::NoAlignment)
5042 return Error(Pow2AlignmentLoc, "alignment not supported on this target");
5043
5044 // If this target takes alignments in bytes (not log) validate and convert.
5045 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
5046 (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
5047 if (!isPowerOf2_64(Pow2Alignment))
5048 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
5049 Pow2Alignment = Log2_64(Pow2Alignment);
5050 }
5051 }
5052
5053 if (parseEOL())
5054 return true;
5055
5056 // NOTE: a size of zero for a .comm should create a undefined symbol
5057 // but a size of .lcomm creates a bss symbol of size zero.
5058 if (Size < 0)
5059 return Error(SizeLoc, "size must be non-negative");
5060
5061 Sym->redefineIfPossible();
5062 if (!Sym->isUndefined())
5063 return Error(IDLoc, "invalid symbol redefinition");
5064
5065 // Create the Symbol as a common or local common with Size and Pow2Alignment
5066 if (IsLocal) {
5067 getStreamer().emitLocalCommonSymbol(Sym, Size,
5068 Align(1ULL << Pow2Alignment));
5069 return false;
5070 }
5071
5072 getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));
5073 return false;
5074}
5075
5076/// parseDirectiveAbort
5077/// ::= .abort [... message ...]
5078bool AsmParser::parseDirectiveAbort() {
5079 // FIXME: Use loc from directive.
5080 SMLoc Loc = getLexer().getLoc();
5081
5082 StringRef Str = parseStringToEndOfStatement();
5083 if (parseEOL())
5084 return true;
5085
5086 if (Str.empty())
5087 return Error(Loc, ".abort detected. Assembly stopping.");
5088 else
5089 return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
5090 // FIXME: Actually abort assembly here.
5091
5092 return false;
5093}
5094
5095/// parseDirectiveInclude
5096/// ::= .include "filename"
5097bool AsmParser::parseDirectiveInclude() {
5098 // Allow the strings to have escaped octal character sequence.
5099 std::string Filename;
5100 SMLoc IncludeLoc = getTok().getLoc();
5101
5102 if (check(getTok().isNot(AsmToken::String),
5103 "expected string in '.include' directive") ||
5104 parseEscapedString(Filename) ||
5106 "unexpected token in '.include' directive") ||
5107 // Attempt to switch the lexer to the included file before consuming the
5108 // end of statement to avoid losing it when we switch.
5109 check(enterIncludeFile(Filename), IncludeLoc,
5110 "Could not find include file '" + Filename + "'"))
5111 return true;
5112
5113 return false;
5114}
5115
5116/// parseDirectiveIncbin
5117/// ::= .incbin "filename" [ , skip [ , count ] ]
5118bool AsmParser::parseDirectiveIncbin() {
5119 // Allow the strings to have escaped octal character sequence.
5120 std::string Filename;
5121 SMLoc IncbinLoc = getTok().getLoc();
5122 if (check(getTok().isNot(AsmToken::String),
5123 "expected string in '.incbin' directive") ||
5124 parseEscapedString(Filename))
5125 return true;
5126
5127 int64_t Skip = 0;
5128 const MCExpr *Count = nullptr;
5129 SMLoc SkipLoc, CountLoc;
5130 if (parseOptionalToken(AsmToken::Comma)) {
5131 // The skip expression can be omitted while specifying the count, e.g:
5132 // .incbin "filename",,4
5133 if (getTok().isNot(AsmToken::Comma)) {
5134 if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))
5135 return true;
5136 }
5137 if (parseOptionalToken(AsmToken::Comma)) {
5138 CountLoc = getTok().getLoc();
5139 if (parseExpression(Count))
5140 return true;
5141 }
5142 }
5143
5144 if (parseEOL())
5145 return true;
5146
5147 if (check(Skip < 0, SkipLoc, "skip is negative"))
5148 return true;
5149
5150 // Attempt to process the included file.
5151 if (processIncbinFile(Filename, Skip, Count, CountLoc))
5152 return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
5153 return false;
5154}
5155
5156/// parseDirectiveIf
5157/// ::= .if{,eq,ge,gt,le,lt,ne} expression
5158bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
5159 TheCondStack.push_back(TheCondState);
5160 TheCondState.TheCond = AsmCond::IfCond;
5161 if (TheCondState.Ignore) {
5162 eatToEndOfStatement();
5163 } else {
5164 int64_t ExprValue;
5165 if (parseAbsoluteExpression(ExprValue) || parseEOL())
5166 return true;
5167
5168 switch (DirKind) {
5169 default:
5170 llvm_unreachable("unsupported directive");
5171 case DK_IF:
5172 case DK_IFNE:
5173 break;
5174 case DK_IFEQ:
5175 ExprValue = ExprValue == 0;
5176 break;
5177 case DK_IFGE:
5178 ExprValue = ExprValue >= 0;
5179 break;
5180 case DK_IFGT:
5181 ExprValue = ExprValue > 0;
5182 break;
5183 case DK_IFLE:
5184 ExprValue = ExprValue <= 0;
5185 break;
5186 case DK_IFLT:
5187 ExprValue = ExprValue < 0;
5188 break;
5189 }
5190
5191 TheCondState.CondMet = ExprValue;
5192 TheCondState.Ignore = !TheCondState.CondMet;
5193 }
5194
5195 return false;
5196}
5197
5198/// parseDirectiveIfb
5199/// ::= .ifb string
5200bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
5201 TheCondStack.push_back(TheCondState);
5202 TheCondState.TheCond = AsmCond::IfCond;
5203
5204 if (TheCondState.Ignore) {
5205 eatToEndOfStatement();
5206 } else {
5207 StringRef Str = parseStringToEndOfStatement();
5208
5209 if (parseEOL())
5210 return true;
5211
5212 TheCondState.CondMet = ExpectBlank == Str.empty();
5213 TheCondState.Ignore = !TheCondState.CondMet;
5214 }
5215
5216 return false;
5217}
5218
5219/// parseDirectiveIfc
5220/// ::= .ifc string1, string2
5221/// ::= .ifnc string1, string2
5222bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
5223 TheCondStack.push_back(TheCondState);
5224 TheCondState.TheCond = AsmCond::IfCond;
5225
5226 if (TheCondState.Ignore) {
5227 eatToEndOfStatement();
5228 } else {
5229 StringRef Str1 = parseStringToComma();
5230
5231 if (parseComma())
5232 return true;
5233
5234 StringRef Str2 = parseStringToEndOfStatement();
5235
5236 if (parseEOL())
5237 return true;
5238
5239 TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
5240 TheCondState.Ignore = !TheCondState.CondMet;
5241 }
5242
5243 return false;
5244}
5245
5246/// parseDirectiveIfeqs
5247/// ::= .ifeqs string1, string2
5248bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
5249 if (Lexer.isNot(AsmToken::String)) {
5250 if (ExpectEqual)
5251 return TokError("expected string parameter for '.ifeqs' directive");
5252 return TokError("expected string parameter for '.ifnes' directive");
5253 }
5254
5255 StringRef String1 = getTok().getStringContents();
5256 Lex();
5257
5258 if (Lexer.isNot(AsmToken::Comma)) {
5259 if (ExpectEqual)
5260 return TokError(
5261 "expected comma after first string for '.ifeqs' directive");
5262 return TokError("expected comma after first string for '.ifnes' directive");
5263 }
5264
5265 Lex();
5266
5267 if (Lexer.isNot(AsmToken::String)) {
5268 if (ExpectEqual)
5269 return TokError("expected string parameter for '.ifeqs' directive");
5270 return TokError("expected string parameter for '.ifnes' directive");
5271 }
5272
5273 StringRef String2 = getTok().getStringContents();
5274 Lex();
5275
5276 TheCondStack.push_back(TheCondState);
5277 TheCondState.TheCond = AsmCond::IfCond;
5278 TheCondState.CondMet = ExpectEqual == (String1 == String2);
5279 TheCondState.Ignore = !TheCondState.CondMet;
5280
5281 return false;
5282}
5283
5284/// parseDirectiveIfdef
5285/// ::= .ifdef symbol
5286bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
5288 TheCondStack.push_back(TheCondState);
5289 TheCondState.TheCond = AsmCond::IfCond;
5290
5291 if (TheCondState.Ignore) {
5292 eatToEndOfStatement();
5293 } else {
5294 if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
5295 parseEOL())
5296 return true;
5297
5298 MCSymbol *Sym = getContext().lookupSymbol(Name);
5299
5300 if (expect_defined)
5301 TheCondState.CondMet = (Sym && !Sym->isUndefined(false));
5302 else
5303 TheCondState.CondMet = (!Sym || Sym->isUndefined(false));
5304 TheCondState.Ignore = !TheCondState.CondMet;
5305 }
5306
5307 return false;
5308}
5309
5310/// parseDirectiveElseIf
5311/// ::= .elseif expression
5312bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
5313 if (TheCondState.TheCond != AsmCond::IfCond &&
5314 TheCondState.TheCond != AsmCond::ElseIfCond)
5315 return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
5316 " .if or an .elseif");
5317 TheCondState.TheCond = AsmCond::ElseIfCond;
5318
5319 bool LastIgnoreState = false;
5320 if (!TheCondStack.empty())
5321 LastIgnoreState = TheCondStack.back().Ignore;
5322 if (LastIgnoreState || TheCondState.CondMet) {
5323 TheCondState.Ignore = true;
5324 eatToEndOfStatement();
5325 } else {
5326 int64_t ExprValue;
5327 if (parseAbsoluteExpression(ExprValue))
5328 return true;
5329
5330 if (parseEOL())
5331 return true;
5332
5333 TheCondState.CondMet = ExprValue;
5334 TheCondState.Ignore = !TheCondState.CondMet;
5335 }
5336
5337 return false;
5338}
5339
5340/// parseDirectiveElse
5341/// ::= .else
5342bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
5343 if (parseEOL())
5344 return true;
5345
5346 if (TheCondState.TheCond != AsmCond::IfCond &&
5347 TheCondState.TheCond != AsmCond::ElseIfCond)
5348 return Error(DirectiveLoc, "Encountered a .else that doesn't follow "
5349 " an .if or an .elseif");
5350 TheCondState.TheCond = AsmCond::ElseCond;
5351 bool LastIgnoreState = false;
5352 if (!TheCondStack.empty())
5353 LastIgnoreState = TheCondStack.back().Ignore;
5354 if (LastIgnoreState || TheCondState.CondMet)
5355 TheCondState.Ignore = true;
5356 else
5357 TheCondState.Ignore = false;
5358
5359 return false;
5360}
5361
5362/// parseDirectiveEnd
5363/// ::= .end
5364bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5365 if (parseEOL())
5366 return true;
5367
5368 while (Lexer.isNot(AsmToken::Eof))
5369 Lexer.Lex();
5370
5371 return false;
5372}
5373
5374/// parseDirectiveError
5375/// ::= .err
5376/// ::= .error [string]
5377bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
5378 if (!TheCondStack.empty()) {
5379 if (TheCondStack.back().Ignore) {
5380 eatToEndOfStatement();
5381 return false;
5382 }
5383 }
5384
5385 if (!WithMessage)
5386 return Error(L, ".err encountered");
5387
5388 StringRef Message = ".error directive invoked in source file";
5389 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5390 if (Lexer.isNot(AsmToken::String))
5391 return TokError(".error argument must be a string");
5392
5393 Message = getTok().getStringContents();
5394 Lex();
5395 }
5396
5397 return Error(L, Message);
5398}
5399
5400/// parseDirectiveWarning
5401/// ::= .warning [string]
5402bool AsmParser::parseDirectiveWarning(SMLoc L) {
5403 if (!TheCondStack.empty()) {
5404 if (TheCondStack.back().Ignore) {
5405 eatToEndOfStatement();
5406 return false;
5407 }
5408 }
5409
5410 StringRef Message = ".warning directive invoked in source file";
5411
5412 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
5413 if (Lexer.isNot(AsmToken::String))
5414 return TokError(".warning argument must be a string");
5415
5416 Message = getTok().getStringContents();
5417 Lex();
5418 if (parseEOL())
5419 return true;
5420 }
5421
5422 return Warning(L, Message);
5423}
5424
5425/// parseDirectiveEndIf
5426/// ::= .endif
5427bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5428 if (parseEOL())
5429 return true;
5430
5431 if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
5432 return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
5433 "an .if or .else");
5434 if (!TheCondStack.empty()) {
5435 TheCondState = TheCondStack.back();
5436 TheCondStack.pop_back();
5437 }
5438
5439 return false;
5440}
5441
5442void AsmParser::initializeDirectiveKindMap() {
5443 /* Lookup will be done with the directive
5444 * converted to lower case, so all these
5445 * keys should be lower case.
5446 * (target specific directives are handled
5447 * elsewhere)
5448 */
5449 DirectiveKindMap[".set"] = DK_SET;
5450 DirectiveKindMap[".equ"] = DK_EQU;
5451 DirectiveKindMap[".equiv"] = DK_EQUIV;
5452 DirectiveKindMap[".ascii"] = DK_ASCII;
5453 DirectiveKindMap[".asciz"] = DK_ASCIZ;
5454 DirectiveKindMap[".string"] = DK_STRING;
5455 DirectiveKindMap[".byte"] = DK_BYTE;
5456 DirectiveKindMap[".short"] = DK_SHORT;
5457 DirectiveKindMap[".value"] = DK_VALUE;
5458 DirectiveKindMap[".2byte"] = DK_2BYTE;
5459 DirectiveKindMap[".long"] = DK_LONG;
5460 DirectiveKindMap[".int"] = DK_INT;
5461 DirectiveKindMap[".4byte"] = DK_4BYTE;
5462 DirectiveKindMap[".quad"] = DK_QUAD;
5463 DirectiveKindMap[".8byte"] = DK_8BYTE;
5464 DirectiveKindMap[".octa"] = DK_OCTA;
5465 DirectiveKindMap[".single"] = DK_SINGLE;
5466 DirectiveKindMap[".float"] = DK_FLOAT;
5467 DirectiveKindMap[".double"] = DK_DOUBLE;
5468 DirectiveKindMap[".align"] = DK_ALIGN;
5469 DirectiveKindMap[".align32"] = DK_ALIGN32;
5470 DirectiveKindMap[".balign"] = DK_BALIGN;
5471 DirectiveKindMap[".balignw"] = DK_BALIGNW;
5472 DirectiveKindMap[".balignl"] = DK_BALIGNL;
5473 DirectiveKindMap[".p2align"] = DK_P2ALIGN;
5474 DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
5475 DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
5476 DirectiveKindMap[".org"] = DK_ORG;
5477 DirectiveKindMap[".fill"] = DK_FILL;
5478 DirectiveKindMap[".zero"] = DK_ZERO;
5479 DirectiveKindMap[".extern"] = DK_EXTERN;
5480 DirectiveKindMap[".globl"] = DK_GLOBL;
5481 DirectiveKindMap[".global"] = DK_GLOBAL;
5482 DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
5483 DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
5484 DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
5485 DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
5486 DirectiveKindMap[".reference"] = DK_REFERENCE;
5487 DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
5488 DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
5489 DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
5490 DirectiveKindMap[".cold"] = DK_COLD;
5491 DirectiveKindMap[".comm"] = DK_COMM;
5492 DirectiveKindMap[".common"] = DK_COMMON;
5493 DirectiveKindMap[".lcomm"] = DK_LCOMM;
5494 DirectiveKindMap[".abort"] = DK_ABORT;
5495 DirectiveKindMap[".include"] = DK_INCLUDE;
5496 DirectiveKindMap[".incbin"] = DK_INCBIN;
5497 DirectiveKindMap[".code16"] = DK_CODE16;
5498 DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
5499 DirectiveKindMap[".rept"] = DK_REPT;
5500 DirectiveKindMap[".rep"] = DK_REPT;
5501 DirectiveKindMap[".irp"] = DK_IRP;
5502 DirectiveKindMap[".irpc"] = DK_IRPC;
5503 DirectiveKindMap[".endr"] = DK_ENDR;
5504 DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE;
5505 DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK;
5506 DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK;
5507 DirectiveKindMap[".if"] = DK_IF;
5508 DirectiveKindMap[".ifeq"] = DK_IFEQ;
5509 DirectiveKindMap[".ifge"] = DK_IFGE;
5510 DirectiveKindMap[".ifgt"] = DK_IFGT;
5511 DirectiveKindMap[".ifle"] = DK_IFLE;
5512 DirectiveKindMap[".iflt"] = DK_IFLT;
5513 DirectiveKindMap[".ifne"] = DK_IFNE;
5514 DirectiveKindMap[".ifb"] = DK_IFB;
5515 DirectiveKindMap[".ifnb"] = DK_IFNB;
5516 DirectiveKindMap[".ifc"] = DK_IFC;
5517 DirectiveKindMap[".ifeqs"] = DK_IFEQS;
5518 DirectiveKindMap[".ifnc"] = DK_IFNC;
5519 DirectiveKindMap[".ifnes"] = DK_IFNES;
5520 DirectiveKindMap[".ifdef"] = DK_IFDEF;
5521 DirectiveKindMap[".ifndef"] = DK_IFNDEF;
5522 DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
5523 DirectiveKindMap[".elseif"] = DK_ELSEIF;
5524 DirectiveKindMap[".else"] = DK_ELSE;
5525 DirectiveKindMap[".end"] = DK_END;
5526 DirectiveKindMap[".endif"] = DK_ENDIF;
5527 DirectiveKindMap[".skip"] = DK_SKIP;
5528 DirectiveKindMap[".space"] = DK_SPACE;
5529 DirectiveKindMap[".file"] = DK_FILE;
5530 DirectiveKindMap[".line"] = DK_LINE;
5531 DirectiveKindMap[".loc"] = DK_LOC;
5532 DirectiveKindMap[".stabs"] = DK_STABS;
5533 DirectiveKindMap[".cv_file"] = DK_CV_FILE;
5534 DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
5535 DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
5536 DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
5537 DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
5538 DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
5539 DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
5540 DirectiveKindMap[".cv_string"] = DK_CV_STRING;
5541 DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
5542 DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
5543 DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
5544 DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
5545 DirectiveKindMap[".sleb128"] = DK_SLEB128;
5546 DirectiveKindMap[".uleb128"] = DK_ULEB128;
5547 DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
5548 DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
5549 DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
5550 DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
5551 DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
5552 DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
5553 DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
5554 DirectiveKindMap[".cfi_llvm_def_aspace_cfa"] = DK_CFI_LLVM_DEF_ASPACE_CFA;
5555 DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
5556 DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
5557 DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
5558 DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
5559 DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
5560 DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
5561 DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
5562 DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
5563 DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
5564 DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
5565 DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
5566 DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
5567 DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
5568 DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
5569 DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
5570 DirectiveKindMap[".cfi_mte_tagged_frame"] = DK_CFI_MTE_TAGGED_FRAME;
5571 DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
5572 DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
5573 DirectiveKindMap[".macro"] = DK_MACRO;
5574 DirectiveKindMap[".exitm"] = DK_EXITM;
5575 DirectiveKindMap[".endm"] = DK_ENDM;
5576 DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
5577 DirectiveKindMap[".purgem"] = DK_PURGEM;
5578 DirectiveKindMap[".err"] = DK_ERR;
5579 DirectiveKindMap[".error"] = DK_ERROR;
5580 DirectiveKindMap[".warning"] = DK_WARNING;
5581 DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
5582 DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
5583 DirectiveKindMap[".reloc"] = DK_RELOC;
5584 DirectiveKindMap[".dc"] = DK_DC;
5585 DirectiveKindMap[".dc.a"] = DK_DC_A;
5586 DirectiveKindMap[".dc.b"] = DK_DC_B;
5587 DirectiveKindMap[".dc.d"] = DK_DC_D;
5588 DirectiveKindMap[".dc.l"] = DK_DC_L;
5589 DirectiveKindMap[".dc.s"] = DK_DC_S;
5590 DirectiveKindMap[".dc.w"] = DK_DC_W;
5591 DirectiveKindMap[".dc.x"] = DK_DC_X;
5592 DirectiveKindMap[".dcb"] = DK_DCB;
5593 DirectiveKindMap[".dcb.b"] = DK_DCB_B;
5594 DirectiveKindMap[".dcb.d"] = DK_DCB_D;
5595 DirectiveKindMap[".dcb.l"] = DK_DCB_L;
5596 DirectiveKindMap[".dcb.s"] = DK_DCB_S;
5597 DirectiveKindMap[".dcb.w"] = DK_DCB_W;
5598 DirectiveKindMap[".dcb.x"] = DK_DCB_X;
5599 DirectiveKindMap[".ds"] = DK_DS;
5600 DirectiveKindMap[".ds.b"] = DK_DS_B;
5601 DirectiveKindMap[".ds.d"] = DK_DS_D;
5602 DirectiveKindMap[".ds.l"] = DK_DS_L;
5603 DirectiveKindMap[".ds.p"] = DK_DS_P;
5604 DirectiveKindMap[".ds.s"] = DK_DS_S;
5605 DirectiveKindMap[".ds.w"] = DK_DS_W;
5606 DirectiveKindMap[".ds.x"] = DK_DS_X;
5607 DirectiveKindMap[".print"] = DK_PRINT;
5608 DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
5609 DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
5610 DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE;
5611 DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD;
5612 DirectiveKindMap[".lto_set_conditional"] = DK_LTO_SET_CONDITIONAL;
5613 DirectiveKindMap[".memtag"] = DK_MEMTAG;
5614}
5615
5616MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5617 AsmToken EndToken, StartToken = getTok();
5618
5619 unsigned NestLevel = 0;
5620 while (true) {
5621 // Check whether we have reached the end of the file.
5622 if (getLexer().is(AsmToken::Eof)) {
5623 printError(DirectiveLoc, "no matching '.endr' in definition");
5624 return nullptr;
5625 }
5626
5627 if (Lexer.is(AsmToken::Identifier) &&
5628 (getTok().getIdentifier() == ".rep" ||
5629 getTok().getIdentifier() == ".rept" ||
5630 getTok().getIdentifier() == ".irp" ||
5631 getTok().getIdentifier() == ".irpc")) {
5632 ++NestLevel;
5633 }
5634
5635 // Otherwise, check whether we have reached the .endr.
5636 if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") {
5637 if (NestLevel == 0) {
5638 EndToken = getTok();
5639 Lex();
5640 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5641 printError(getTok().getLoc(),
5642 "unexpected token in '.endr' directive");
5643 return nullptr;
5644 }
5645 break;
5646 }
5647 --NestLevel;
5648 }
5649
5650 // Otherwise, scan till the end of the statement.
5651 eatToEndOfStatement();
5652 }
5653
5654 const char *BodyStart = StartToken.getLoc().getPointer();
5655 const char *BodyEnd = EndToken.getLoc().getPointer();
5656 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5657
5658 // We Are Anonymous.
5659 MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
5660 return &MacroLikeBodies.back();
5661}
5662
5663void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5665 OS << ".endr\n";
5666
5667 std::unique_ptr<MemoryBuffer> Instantiation =
5668 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
5669
5670 // Create the macro instantiation object and add to the current macro
5671 // instantiation stack.
5672 MacroInstantiation *MI = new MacroInstantiation{
5673 DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
5674 ActiveMacros.push_back(MI);
5675
5676 // Jump to the macro instantiation and prime the lexer.
5677 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
5678 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
5679 Lex();
5680}
5681
5682/// parseDirectiveRept
5683/// ::= .rep | .rept count
5684bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
5685 const MCExpr *CountExpr;
5686 SMLoc CountLoc = getTok().getLoc();
5687 if (parseExpression(CountExpr))
5688 return true;
5689
5690 int64_t Count;
5691 if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
5692 return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
5693 }
5694
5695 if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())
5696 return true;
5697
5698 // Lex the rept definition.
5699 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5700 if (!M)
5701 return true;
5702
5703 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5704 // to hold the macro body with substitutions.
5705 SmallString<256> Buf;
5707 while (Count--) {
5708 // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
5709 if (expandMacro(OS, *M, std::nullopt, std::nullopt, false))
5710 return true;
5711 }
5712 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5713
5714 return false;
5715}
5716
5717/// parseDirectiveIrp
5718/// ::= .irp symbol,values
5719bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
5720 MCAsmMacroParameter Parameter;
5721 MCAsmMacroArguments A;
5722 if (check(parseIdentifier(Parameter.Name),
5723 "expected identifier in '.irp' directive") ||
5724 parseComma() || parseMacroArguments(nullptr, A) || parseEOL())
5725 return true;
5726
5727 // Lex the irp definition.
5728 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5729 if (!M)
5730 return true;
5731
5732 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5733 // to hold the macro body with substitutions.
5734 SmallString<256> Buf;
5736
5737 for (const MCAsmMacroArgument &Arg : A) {
5738 // Note that the AtPseudoVariable is enabled for instantiations of .irp.
5739 // This is undocumented, but GAS seems to support it.
5740 if (expandMacro(OS, *M, Parameter, Arg, true))
5741 return true;
5742 }
5743
5744 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5745
5746 return false;
5747}
5748
5749/// parseDirectiveIrpc
5750/// ::= .irpc symbol,values
5751bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
5752 MCAsmMacroParameter Parameter;
5753 MCAsmMacroArguments A;
5754
5755 if (check(parseIdentifier(Parameter.Name),
5756 "expected identifier in '.irpc' directive") ||
5757 parseComma() || parseMacroArguments(nullptr, A))
5758 return true;
5759
5760 if (A.size() != 1 || A.front().size() != 1)
5761 return TokError("unexpected token in '.irpc' directive");
5762 if (parseEOL())
5763 return true;
5764
5765 // Lex the irpc definition.
5766 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5767 if (!M)
5768 return true;
5769
5770 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5771 // to hold the macro body with substitutions.
5772 SmallString<256> Buf;
5774
5775 StringRef Values = A.front().front().getString();
5776 for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
5777 MCAsmMacroArgument Arg;
5778 Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
5779
5780 // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
5781 // This is undocumented, but GAS seems to support it.
5782 if (expandMacro(OS, *M, Parameter, Arg, true))
5783 return true;
5784 }
5785
5786 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5787
5788 return false;
5789}
5790
5791bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
5792 if (ActiveMacros.empty())
5793 return TokError("unmatched '.endr' directive");
5794
5795 // The only .repl that should get here are the ones created by
5796 // instantiateMacroLikeBody.
5797 assert(getLexer().is(AsmToken::EndOfStatement));
5798
5799 handleMacroExit();
5800 return false;
5801}
5802
5803bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5804 size_t Len) {
5805 const MCExpr *Value;
5806 SMLoc ExprLoc = getLexer().getLoc();
5807 if (parseExpression(Value))
5808 return true;
5809 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5810 if (!MCE)
5811 return Error(ExprLoc, "unexpected expression in _emit");
5812 uint64_t IntValue = MCE->getValue();
5813 if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
5814 return Error(ExprLoc, "literal value out of range for directive");
5815
5816 Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
5817 return false;
5818}
5819
5820bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5821 const MCExpr *Value;
5822 SMLoc ExprLoc = getLexer().getLoc();
5823 if (parseExpression(Value))
5824 return true;
5825 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5826 if (!MCE)
5827 return Error(ExprLoc, "unexpected expression in align");
5828 uint64_t IntValue = MCE->getValue();
5829 if (!isPowerOf2_64(IntValue))
5830 return Error(ExprLoc, "literal value not a power of two greater then zero");
5831
5832 Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
5833 return false;
5834}
5835
5836bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
5837 const AsmToken StrTok = getTok();
5838 Lex();
5839 if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
5840 return Error(DirectiveLoc, "expected double quoted string after .print");
5841 if (parseEOL())
5842 return true;
5843 llvm::outs() << StrTok.getStringContents() << '\n';
5844 return false;
5845}
5846
5847bool AsmParser::parseDirectiveAddrsig() {
5848 if (parseEOL())
5849 return true;
5850 getStreamer().emitAddrsig();
5851 return false;
5852}
5853
5854bool AsmParser::parseDirectiveAddrsigSym() {
5856 if (check(parseIdentifier(Name), "expected identifier") || parseEOL())
5857 return true;
5858 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5859 getStreamer().emitAddrsigSym(Sym);
5860 return false;
5861}
5862
5863bool AsmParser::parseDirectivePseudoProbe() {
5864 int64_t Guid;
5865 int64_t Index;
5866 int64_t Type;
5867 int64_t Attr;
5868 int64_t Discriminator = 0;
5869
5870 if (parseIntToken(Guid, "unexpected token in '.pseudoprobe' directive"))
5871 return true;
5872
5873 if (parseIntToken(Index, "unexpected token in '.pseudoprobe' directive"))
5874 return true;
5875
5876 if (parseIntToken(Type, "unexpected token in '.pseudoprobe' directive"))
5877 return true;
5878
5879 if (parseIntToken(Attr, "unexpected token in '.pseudoprobe' directive"))
5880 return true;
5881
5882 if (hasDiscriminator(Attr)) {
5883 if (parseIntToken(Discriminator,
5884 "unexpected token in '.pseudoprobe' directive"))
5885 return true;
5886 }
5887
5888 // Parse inline stack like @ GUID:11:12 @ GUID:1:11 @ GUID:3:21
5889 MCPseudoProbeInlineStack InlineStack;
5890
5891 while (getLexer().is(AsmToken::At)) {
5892 // eat @
5893 Lex();
5894
5895 int64_t CallerGuid = 0;
5896 if (getLexer().is(AsmToken::Integer)) {
5897 if (parseIntToken(CallerGuid,
5898 "unexpected token in '.pseudoprobe' directive"))
5899 return true;
5900 }
5901
5902 // eat colon
5903 if (getLexer().is(AsmToken::Colon))
5904 Lex();
5905
5906 int64_t CallerProbeId = 0;
5907 if (getLexer().is(AsmToken::Integer)) {
5908 if (parseIntToken(CallerProbeId,
5909 "unexpected token in '.pseudoprobe' directive"))
5910 return true;
5911 }
5912
5913 InlineSite Site(CallerGuid, CallerProbeId);
5914 InlineStack.push_back(Site);
5915 }
5916
5917 // Parse function entry name
5918 StringRef FnName;
5919 if (parseIdentifier(FnName))
5920 return Error(getLexer().getLoc(), "unexpected token in '.pseudoprobe' directive");
5921 MCSymbol *FnSym = getContext().lookupSymbol(FnName);
5922
5923 if (parseEOL())
5924 return true;
5925
5926 getStreamer().emitPseudoProbe(Guid, Index, Type, Attr, Discriminator,
5927 InlineStack, FnSym);
5928 return false;
5929}
5930
5931/// parseDirectiveLTODiscard
5932/// ::= ".lto_discard" [ identifier ( , identifier )* ]
5933/// The LTO library emits this directive to discard non-prevailing symbols.
5934/// We ignore symbol assignments and attribute changes for the specified
5935/// symbols.
5936bool AsmParser::parseDirectiveLTODiscard() {
5937 auto ParseOp = [&]() -> bool {
5939 SMLoc Loc = getTok().getLoc();
5940 if (parseIdentifier(Name))
5941 return Error(Loc, "expected identifier");
5942 LTODiscardSymbols.insert(Name);
5943 return false;
5944 };
5945
5946 LTODiscardSymbols.clear();
5947 return parseMany(ParseOp);
5948}
5949
5950// We are comparing pointers, but the pointers are relative to a single string.
5951// Thus, this should always be deterministic.
5952static int rewritesSort(const AsmRewrite *AsmRewriteA,
5953 const AsmRewrite *AsmRewriteB) {
5954 if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
5955 return -1;
5956 if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
5957 return 1;
5958
5959 // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
5960 // rewrite to the same location. Make sure the SizeDirective rewrite is
5961 // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
5962 // ensures the sort algorithm is stable.
5963 if (AsmRewritePrecedence[AsmRewriteA->Kind] >
5964 AsmRewritePrecedence[AsmRewriteB->Kind])
5965 return -1;
5966
5967 if (AsmRewritePrecedence[AsmRewriteA->Kind] <
5968 AsmRewritePrecedence[AsmRewriteB->Kind])
5969 return 1;
5970 llvm_unreachable("Unstable rewrite sort.");
5971}
5972
5973bool AsmParser::parseMSInlineAsm(
5974 std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,
5975 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5976 SmallVectorImpl<std::string> &Constraints,
5977 SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
5978 const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5979 SmallVector<void *, 4> InputDecls;
5980 SmallVector<void *, 4> OutputDecls;
5981 SmallVector<bool, 4> InputDeclsAddressOf;
5982 SmallVector<bool, 4> OutputDeclsAddressOf;
5983 SmallVector<std::string, 4> InputConstraints;
5984 SmallVector<std::string, 4> OutputConstraints;
5985 SmallVector<unsigned, 4> ClobberRegs;
5986
5987 SmallVector<AsmRewrite, 4> AsmStrRewrites;
5988
5989 // Prime the lexer.
5990 Lex();
5991
5992 // While we have input, parse each statement.
5993 unsigned InputIdx = 0;
5994 unsigned OutputIdx = 0;
5995 while (getLexer().isNot(AsmToken::Eof)) {
5996 // Parse curly braces marking block start/end
5997 if (parseCurlyBlockScope(AsmStrRewrites))
5998 continue;
5999
6000 ParseStatementInfo Info(&AsmStrRewrites);
6001 bool StatementErr = parseStatement(Info, &SI);
6002
6003 if (StatementErr || Info.ParseError) {
6004 // Emit pending errors if any exist.
6005 printPendingErrors();
6006 return true;
6007 }
6008
6009 // No pending error should exist here.
6010 assert(!hasPendingError() && "unexpected error from parseStatement");
6011
6012 if (Info.Opcode == ~0U)
6013 continue;
6014
6015 const MCInstrDesc &Desc = MII->get(Info.Opcode);
6016
6017 // Build the list of clobbers, outputs and inputs.
6018 for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
6019 MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
6020
6021 // Register operand.
6022 if (Operand.isReg() && !Operand.needAddressOf() &&
6023 !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
6024 unsigned NumDefs = Desc.getNumDefs();
6025 // Clobber.
6026 if (NumDefs && Operand.getMCOperandNum() < NumDefs)
6027 ClobberRegs.push_back(Operand.getReg());
6028 continue;
6029 }
6030
6031 // Expr/Input or Output.
6032 StringRef SymName = Operand.getSymName();
6033 if (SymName.empty())
6034 continue;
6035
6036 void *OpDecl = Operand.getOpDecl();
6037 if (!OpDecl)
6038 continue;
6039
6040 StringRef Constraint = Operand.getConstraint();
6041 if (Operand.isImm()) {
6042 // Offset as immediate
6043 if (Operand.isOffsetOfLocal())
6044 Constraint = "r";
6045 else
6046 Constraint = "i";
6047 }
6048
6049 bool isOutput = (i == 1) && Desc.mayStore();
6050 bool Restricted = Operand.isMemUseUpRegs();
6051 SMLoc Start = SMLoc::getFromPointer(SymName.data());
6052 if (isOutput) {
6053 ++InputIdx;
6054 OutputDecls.push_back(OpDecl);
6055 OutputDeclsAddressOf.push_back(Operand.needAddressOf());
6056 OutputConstraints.push_back(("=" + Constraint).str());
6057 AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size(), 0,
6058 Restricted);
6059 } else {
6060 InputDecls.push_back(OpDecl);
6061 InputDeclsAddressOf.push_back(Operand.needAddressOf());
6062 InputConstraints.push_back(Constraint.str());
6063 if (Desc.operands()[i - 1].isBranchTarget())
6064 AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size(), 0,
6065 Restricted);
6066 else
6067 AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size(), 0,
6068 Restricted);
6069 }
6070 }
6071
6072 // Consider implicit defs to be clobbers. Think of cpuid and push.
6073 llvm::append_range(ClobberRegs, Desc.implicit_defs());
6074 }
6075
6076 // Set the number of Outputs and Inputs.
6077 NumOutputs = OutputDecls.size();
6078 NumInputs = InputDecls.size();
6079
6080 // Set the unique clobbers.
6081 array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
6082 ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
6083 ClobberRegs.end());
6084 Clobbers.assign(ClobberRegs.size(), std::string());
6085 for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
6086 raw_string_ostream OS(Clobbers[I]);
6087 IP->printRegName(OS, ClobberRegs[I]);
6088 }
6089
6090 // Merge the various outputs and inputs. Output are expected first.
6091 if (NumOutputs || NumInputs) {
6092 unsigned NumExprs = NumOutputs + NumInputs;
6093 OpDecls.resize(NumExprs);
6094 Constraints.resize(NumExprs);
6095 for (unsigned i = 0; i < NumOutputs; ++i) {
6096 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
6097 Constraints[i] = OutputConstraints[i];
6098 }
6099 for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
6100 OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6101 Constraints[j] = InputConstraints[i];
6102 }
6103 }
6104
6105 // Build the IR assembly string.
6106 std::string AsmStringIR;
6107 raw_string_ostream OS(AsmStringIR);
6108 StringRef ASMString =
6110 const char *AsmStart = ASMString.begin();
6111 const char *AsmEnd = ASMString.end();
6112 array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
6113 for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) {
6114 const AsmRewrite &AR = *it;
6115 // Check if this has already been covered by another rewrite...
6116 if (AR.Done)
6117 continue;
6119
6120 const char *Loc = AR.Loc.getPointer();
6121 assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
6122
6123 // Emit everything up to the immediate/expression.
6124 if (unsigned Len = Loc - AsmStart)
6125 OS << StringRef(AsmStart, Len);
6126
6127 // Skip the original expression.
6128 if (Kind == AOK_Skip) {
6129 AsmStart = Loc + AR.Len;
6130 continue;
6131 }
6132
6133 unsigned AdditionalSkip = 0;
6134 // Rewrite expressions in $N notation.
6135 switch (Kind) {
6136 default:
6137 break;
6138 case AOK_IntelExpr:
6139 assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
6140 if (AR.IntelExp.NeedBracs)
6141 OS << "[";
6142 if (AR.IntelExp.hasBaseReg())
6143 OS << AR.IntelExp.BaseReg;
6144 if (AR.IntelExp.hasIndexReg())
6145 OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
6146 << AR.IntelExp.IndexReg;
6147 if (AR.IntelExp.Scale > 1)
6148 OS << " * $$" << AR.IntelExp.Scale;
6149 if (AR.IntelExp.hasOffset()) {
6150 if (AR.IntelExp.hasRegs())
6151 OS << " + ";
6152 // Fuse this rewrite with a rewrite of the offset name, if present.
6153 StringRef OffsetName = AR.IntelExp.OffsetName;
6155 size_t OffsetLen = OffsetName.size();
6156 auto rewrite_it = std::find_if(
6157 it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
6158 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6159 (FusingAR.Kind == AOK_Input ||
6160 FusingAR.Kind == AOK_CallInput);
6161 });
6162 if (rewrite_it == AsmStrRewrites.end()) {
6163 OS << "offset " << OffsetName;
6164 } else if (rewrite_it->Kind == AOK_CallInput) {
6165 OS << "${" << InputIdx++ << ":P}";
6166 rewrite_it->Done = true;
6167 } else {
6168 OS << '$' << InputIdx++;
6169 rewrite_it->Done = true;
6170 }
6171 }
6172 if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
6173 OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
6174 if (AR.IntelExp.NeedBracs)
6175 OS << "]";
6176 break;
6177 case AOK_Label:
6178 OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
6179 break;
6180 case AOK_Input:
6181 if (AR.IntelExpRestricted)
6182 OS << "${" << InputIdx++ << ":P}";
6183 else
6184 OS << '$' << InputIdx++;
6185 break;
6186 case AOK_CallInput:
6187 OS << "${" << InputIdx++ << ":P}";
6188 break;
6189 case AOK_Output:
6190 if (AR.IntelExpRestricted)
6191 OS << "${" << OutputIdx++ << ":P}";
6192 else
6193 OS << '$' << OutputIdx++;
6194 break;
6195 case AOK_SizeDirective:
6196 switch (AR.Val) {
6197 default: break;
6198 case 8: OS << "byte ptr "; break;
6199 case 16: OS << "word ptr "; break;
6200 case 32: OS << "dword ptr "; break;
6201 case 64: OS << "qword ptr "; break;
6202 case 80: OS << "xword ptr "; break;
6203 case 128: OS << "xmmword ptr "; break;
6204 case 256: OS << "ymmword ptr "; break;
6205 }
6206 break;
6207 case AOK_Emit:
6208 OS << ".byte";
6209 break;
6210 case AOK_Align: {
6211 // MS alignment directives are measured in bytes. If the native assembler
6212 // measures alignment in bytes, we can pass it straight through.
6213 OS << ".align";
6214 if (getContext().getAsmInfo()->getAlignmentIsInBytes())
6215 break;
6216
6217 // Alignment is in log2 form, so print that instead and skip the original
6218 // immediate.
6219 unsigned Val = AR.Val;
6220 OS << ' ' << Val;
6221 assert(Val < 10 && "Expected alignment less then 2^10.");
6222 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6223 break;
6224 }
6225 case AOK_EVEN:
6226 OS << ".even";
6227 break;
6228 case AOK_EndOfStatement:
6229 OS << "\n\t";
6230 break;
6231 }
6232
6233 // Skip the original expression.
6234 AsmStart = Loc + AR.Len + AdditionalSkip;
6235 }
6236
6237 // Emit the remainder of the asm string.
6238 if (AsmStart != AsmEnd)
6239 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6240
6241 AsmString = OS.str();
6242 return false;
6243}
6244
6245bool HLASMAsmParser::parseAsHLASMLabel(ParseStatementInfo &Info,
6247 AsmToken LabelTok = getTok();
6248 SMLoc LabelLoc = LabelTok.getLoc();
6249 StringRef LabelVal;
6250
6251 if (parseIdentifier(LabelVal))
6252 return Error(LabelLoc, "The HLASM Label has to be an Identifier");
6253
6254 // We have validated whether the token is an Identifier.
6255 // Now we have to validate whether the token is a
6256 // valid HLASM Label.
6257 if (!getTargetParser().isLabel(LabelTok) || checkForValidSection())
6258 return true;
6259
6260 // Lex leading spaces to get to the next operand.
6261 lexLeadingSpaces();
6262
6263 // We shouldn't emit the label if there is nothing else after the label.
6264 // i.e asm("<token>\n")
6265 if (getTok().is(AsmToken::EndOfStatement))
6266 return Error(LabelLoc,
6267 "Cannot have just a label for an HLASM inline asm statement");
6268
6269 MCSymbol *Sym = getContext().getOrCreateSymbol(
6270 getContext().getAsmInfo()->shouldEmitLabelsInUpperCase()
6271 ? LabelVal.upper()
6272 : LabelVal);
6273
6274 getTargetParser().doBeforeLabelEmit(Sym, LabelLoc);
6275
6276 // Emit the label.
6277 Out.emitLabel(Sym, LabelLoc);
6278
6279 // If we are generating dwarf for assembly source files then gather the
6280 // info to make a dwarf label entry for this label if needed.
6281 if (enabledGenDwarfForAssembly())
6282 MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
6283 LabelLoc);
6284
6285 getTargetParser().onLabelParsed(Sym);
6286
6287 return false;
6288}
6289
6290bool HLASMAsmParser::parseAsMachineInstruction(ParseStatementInfo &Info,
6292 AsmToken OperationEntryTok = Lexer.getTok();
6293 SMLoc OperationEntryLoc = OperationEntryTok.getLoc();
6294 StringRef OperationEntryVal;
6295
6296 // Attempt to parse the first token as an Identifier
6297 if (parseIdentifier(OperationEntryVal))
6298 return Error(OperationEntryLoc, "unexpected token at start of statement");
6299
6300 // Once we've parsed the operation entry successfully, lex
6301 // any spaces to get to the OperandEntries.
6302 lexLeadingSpaces();
6303
6304 return parseAndMatchAndEmitTargetInstruction(
6305 Info, OperationEntryVal, OperationEntryTok, OperationEntryLoc);
6306}
6307
6308bool HLASMAsmParser::parseStatement(ParseStatementInfo &Info,
6310 assert(!hasPendingError() && "parseStatement started with pending error");
6311
6312 // Should the first token be interpreted as a HLASM Label.
6313 bool ShouldParseAsHLASMLabel = false;
6314
6315 // If a Name Entry exists, it should occur at the very
6316 // start of the string. In this case, we should parse the
6317 // first non-space token as a Label.
6318 // If the Name entry is missing (i.e. there's some other
6319 // token), then we attempt to parse the first non-space
6320 // token as a Machine Instruction.
6321 if (getTok().isNot(AsmToken::Space))
6322 ShouldParseAsHLASMLabel = true;
6323
6324 // If we have an EndOfStatement (which includes the target's comment
6325 // string) we can appropriately lex it early on)
6326 if (Lexer.is(AsmToken::EndOfStatement)) {
6327 // if this is a line comment we can drop it safely
6328 if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
6329 getTok().getString().front() == '\n')
6330 Out.addBlankLine();
6331 Lex();
6332 return false;
6333 }
6334
6335 // We have established how to parse the inline asm statement.
6336 // Now we can safely lex any leading spaces to get to the
6337 // first token.
6338 lexLeadingSpaces();
6339
6340 // If we see a new line or carriage return as the first operand,
6341 // after lexing leading spaces, emit the new line and lex the
6342 // EndOfStatement token.
6343 if (Lexer.is(AsmToken::EndOfStatement)) {
6344 if (getTok().getString().front() == '\n' ||
6345 getTok().getString().front() == '\r') {
6346 Out.addBlankLine();
6347 Lex();
6348 return false;
6349 }
6350 }
6351
6352 // Handle the label first if we have to before processing the rest
6353 // of the tokens as a machine instruction.
6354 if (ShouldParseAsHLASMLabel) {
6355 // If there were any errors while handling and emitting the label,
6356 // early return.
6357 if (parseAsHLASMLabel(Info, SI)) {
6358 // If we know we've failed in parsing, simply eat until end of the
6359 // statement. This ensures that we don't process any other statements.
6360 eatToEndOfStatement();
6361 return true;
6362 }
6363 }
6364
6365 return parseAsMachineInstruction(Info, SI);
6366}
6367
6368namespace llvm {
6369namespace MCParserUtils {
6370
6371/// Returns whether the given symbol is used anywhere in the given expression,
6372/// or subexpressions.
6373static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
6374 switch (Value->getKind()) {
6375 case MCExpr::Binary: {
6376 const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
6377 return isSymbolUsedInExpression(Sym, BE->getLHS()) ||
6379 }
6380 case MCExpr::Target:
6381 case MCExpr::Constant:
6382 return false;
6383 case MCExpr::SymbolRef: {
6384 const MCSymbol &S =
6385 static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
6386 if (S.isVariable() && !S.isWeakExternal())
6388 return &S == Sym;
6389 }
6390 case MCExpr::Unary:
6392 Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
6393 }
6394
6395 llvm_unreachable("Unknown expr kind!");
6396}
6397
6399 MCAsmParser &Parser, MCSymbol *&Sym,
6400 const MCExpr *&Value) {
6401
6402 // FIXME: Use better location, we should use proper tokens.
6403 SMLoc EqualLoc = Parser.getTok().getLoc();
6404 if (Parser.parseExpression(Value))
6405 return Parser.TokError("missing expression");
6406
6407 // Note: we don't count b as used in "a = b". This is to allow
6408 // a = b
6409 // b = c
6410
6411 if (Parser.parseEOL())
6412 return true;
6413
6414 // Validate that the LHS is allowed to be a variable (either it has not been
6415 // used as a symbol, or it is an absolute symbol).
6416 Sym = Parser.getContext().lookupSymbol(Name);
6417 if (Sym) {
6418 // Diagnose assignment to a label.
6419 //
6420 // FIXME: Diagnostics. Note the location of the definition as a label.
6421 // FIXME: Diagnose assignment to protected identifier (e.g., register name).
6423 return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'");
6424 else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() &&
6425 !Sym->isVariable())
6426 ; // Allow redefinitions of undefined symbols only used in directives.
6427 else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
6428 ; // Allow redefinitions of variables that haven't yet been used.
6429 else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
6430 return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
6431 else if (!Sym->isVariable())
6432 return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'");
6433 else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
6434 return Parser.Error(EqualLoc,
6435 "invalid reassignment of non-absolute variable '" +
6436 Name + "'");
6437 } else if (Name == ".") {
6438 Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
6439 return false;
6440 } else
6442
6443 Sym->setRedefinable(allow_redef);
6444
6445 return false;
6446}
6447
6448} // end namespace MCParserUtils
6449} // end namespace llvm
6450
6451/// Create an MCAsmParser instance.
6453 MCStreamer &Out, const MCAsmInfo &MAI,
6454 unsigned CB) {
6455 if (C.getTargetTriple().isSystemZ() && C.getTargetTriple().isOSzOS())
6456 return new HLASMAsmParser(SM, C, Out, MAI, CB);
6457
6458 return new AsmParser(SM, C, Out, MAI, CB);
6459}
This file defines the StringMap class.
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static Expected< std::vector< unsigned > > getSymbols(SymbolicFile *Obj, uint16_t Index, raw_ostream &SymNames, SymMap *SymMap)
@ DEFAULT_ADDRSPACE
Definition: AsmParser.cpp:769
static bool isValidEncoding(int64_t Encoding)
Definition: AsmParser.cpp:4352
static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc)
This function checks if the next token is <string> type or arithmetic.
Definition: AsmParser.cpp:1461
static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K, MCBinaryExpr::Opcode &Kind, bool ShouldUseLogicalShr)
Definition: AsmParser.cpp:1575
static bool isIdentifierChar(char c)
Definition: AsmParser.cpp:2492
static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI, AsmToken::TokenKind K, MCBinaryExpr::Opcode &Kind, bool ShouldUseLogicalShr)
Definition: AsmParser.cpp:1651
static std::string angleBracketString(StringRef AltMacroStr)
creating a string without the escape characters '!'.
Definition: AsmParser.cpp:1479
static int rewritesSort(const AsmRewrite *AsmRewriteA, const AsmRewrite *AsmRewriteB)
Definition: AsmParser.cpp:5952
static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo)
Definition: AsmParser.cpp:3204
static bool isOperator(AsmToken::TokenKind kind)
Definition: AsmParser.cpp:2635
basic Basic Alias true
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Definition: Debug.h:64
This file contains constants used for implementing Dwarf debug support.
std::string Name
uint64_t Size
bool End
Definition: ELF_riscv.cpp:480
Symbol * Sym
Definition: ELF_riscv.cpp:479
#define check(cond)
IRTranslator LLVM IR MI
#define DWARF2_FLAG_IS_STMT
Definition: MCDwarf.h:117
#define DWARF2_FLAG_BASIC_BLOCK
Definition: MCDwarf.h:118
#define DWARF2_LINE_DEFAULT_IS_STMT
Definition: MCDwarf.h:115
#define DWARF2_FLAG_PROLOGUE_END
Definition: MCDwarf.h:119
#define DWARF2_FLAG_EPILOGUE_BEGIN
Definition: MCDwarf.h:120
#define I(x, y, z)
Definition: MD5.cpp:58
LLVMContext & Context
if(VerifyEach)
bool Debug
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
static bool isHexDigit(const char C)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
This file defines the SmallSet class.
This file defines the SmallString class.
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
Definition: TextStub.cpp:1060
Value * RHS
Value * LHS
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Definition: APFloat.h:966
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Definition: APFloat.h:977
Class for arbitrary precision integers.
Definition: APInt.h:76
APInt getLoBits(unsigned numBits) const
Compute an APInt containing numBits lowbits from this APInt.
Definition: APInt.cpp:613
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1498
APInt getHiBits(unsigned numBits) const
Compute an APInt containing numBits highbits from this APInt.
Definition: APInt.cpp:608
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1446
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
Definition: APInt.h:453
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
Definition: APInt.h:410
This class represents an incoming formal argument to a Function.
Definition: Argument.h:31
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
AsmCond - Class to support conditional assembly.
Definition: AsmCond.h:21
ConditionalAssemblyType TheCond
Definition: AsmCond.h:30
bool Ignore
Definition: AsmCond.h:32
bool CondMet
Definition: AsmCond.h:31
AsmLexer - Lexer class for assembly files.
Definition: AsmLexer.h:25
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:26
bool isNot(TokenKind K) const
Definition: MCAsmMacro.h:83
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmMacro.h:110
StringRef getStringContents() const
Get the contents of a string token (without quotes).
Definition: MCAsmMacro.h:90
bool is(TokenKind K) const
Definition: MCAsmMacro.h:82
SMLoc getEndLoc() const
Definition: MCAsmLexer.cpp:30
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition: MCAsmMacro.h:99
Holds state from .cv_file and .cv_loc directives for later emission.
Definition: MCCodeView.h:144
Base class for user error types.
Definition: Error.h:352
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
Tagged union holding either a T or a Error.
Definition: Error.h:474
Error takeError()
Take ownership of the stored error.
Definition: Error.h:601
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:56
bool useParensForSymbolVariant() const
Definition: MCAsmInfo.h:811
bool preserveAsmComments() const
Return true if assembly (inline or otherwise) should be parsed.
Definition: MCAsmInfo.h:864
bool isLittleEndian() const
True if the target is little endian.
Definition: MCAsmInfo.h:555
unsigned getAssemblerDialect() const
Definition: MCAsmInfo.h:682
bool doesAllowAtInName() const
Definition: MCAsmInfo.h:683
StringRef getPrivateLabelPrefix() const
Definition: MCAsmInfo.h:665
bool shouldEmitLabelsInUpperCase() const
Definition: MCAsmInfo.h:660
bool getStarIsPC() const
Definition: MCAsmInfo.h:644
bool shouldUseLogicalShr() const
Definition: MCAsmInfo.h:872
StringRef getCommentString() const
Definition: MCAsmInfo.h:651
bool getDotIsPC() const
Definition: MCAsmInfo.h:643
bool hasSubsectionsViaSymbols() const
Definition: MCAsmInfo.h:560
bool getDollarIsPC() const
Definition: MCAsmInfo.h:642
Generic assembler lexer interface, for use by target specific assembly lexers.
Definition: MCAsmLexer.h:37
void UnLex(AsmToken const &Token)
Definition: MCAsmLexer.h:93
void setAllowHashInIdentifier(bool V)
Definition: MCAsmLexer.h:152
const AsmToken peekTok(bool ShouldSkipSpace=true)
Look ahead at the next token to be lexed.
Definition: MCAsmLexer.h:111
void setLexHLASMIntegers(bool V)
Set whether to lex HLASM-flavour integers. For now this is only [0-9]*.
Definition: MCAsmLexer.h:181
bool isNot(AsmToken::TokenKind K) const
Check if the current token has kind K.
Definition: MCAsmLexer.h:144
SMLoc getLoc() const
Get the current source location.
Definition: MCAsmLexer.cpp:22
SMLoc getErrLoc()
Get the current error location.
Definition: MCAsmLexer.h:128
void setLexMasmIntegers(bool V)
Set whether to lex masm-style binary (e.g., 0b1101) and radix-specified literals (e....
Definition: MCAsmLexer.h:160
const AsmToken & getTok() const
Get the current (last) lexed token.
Definition: MCAsmLexer.h:106
AsmToken::TokenKind getKind() const
Get the kind of current token.
Definition: MCAsmLexer.h:138
void setLexHLASMStrings(bool V)
Set whether to "lex" HLASM-flavour character and string literals.
Definition: MCAsmLexer.h:186
void setSkipSpace(bool val)
Set whether spaces should be ignored by the lexer.
Definition: MCAsmLexer.h:147
const AsmToken & Lex()
Consume the next token from the input stream and return it.
Definition: MCAsmLexer.h:79
bool is(AsmToken::TokenKind K) const
Check if the current token has kind K.
Definition: MCAsmLexer.h:141
virtual size_t peekTokens(MutableArrayRef< AsmToken > Buf, bool ShouldSkipSpace=true)=0
Look ahead an arbitrary number of tokens.
const std::string & getErr()
Get the current error string.
Definition: MCAsmLexer.h:133
Generic interface for extending the MCAsmParser, which is implemented by target and object file assem...
Generic Sema callback for assembly parser.
Definition: MCAsmParser.h:108
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:123
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
virtual bool printError(SMLoc L, const Twine &Msg, SMRange Range=std::nullopt)=0
Emit an error at the location L, with the message Msg.
virtual bool parseEscapedString(std::string &Data)=0
Parse the current token as a string which may include escaped characters and return the string conten...
virtual MCStreamer & getStreamer()=0
Return the output streamer for the assembler.
virtual StringRef parseStringToEndOfStatement()=0
Parse up to the end of statement and return the contents from the current token until the end of the ...
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
virtual SourceMgr & getSourceManager()=0
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, AsmTypeInfo *TypeInfo)=0
Parse a primary expression.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
Definition: MCAsmParser.cpp:40
virtual bool checkForValidSection()=0
Ensure that we have a valid section set in the streamer.
virtual bool parseIdentifier(StringRef &Res)=0
Parse an identifier or string (as a quoted identifier) and set Res to the identifier contents.
virtual bool discardLTOSymbol(StringRef) const
Definition: MCAsmParser.h:185
MCAsmParser & operator=(const MCAsmParser &)=delete
virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression, assuming that an initial '(' has already been consumed.
virtual bool isParsingMSInlineAsm()=0
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
virtual bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression of a specified parenthesis depth, assuming that the initial '(' charact...
virtual unsigned getAssemblerDialect()
Definition: MCAsmParser.h:173
virtual MCAsmLexer & getLexer()=0
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
virtual bool parseAngleBracketString(std::string &Data)=0
Parse an angle-bracket delimited string at the current position if one is present,...
bool TokError(const Twine &Msg, SMRange Range=std::nullopt)
Report an error at the current lexer location.
Definition: MCAsmParser.cpp:97
virtual bool parseAbsoluteExpression(int64_t &Res)=0
Parse an expression which must evaluate to an absolute value.
virtual bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, SmallVectorImpl< std::pair< void *, bool > > &OpDecls, SmallVectorImpl< std::string > &Constraints, SmallVectorImpl< std::string > &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, MCAsmParserSemaCallback &SI)=0
Parse MS-style inline assembly.
virtual void setAssemblerDialect(unsigned i)
Definition: MCAsmParser.h:174
virtual MCContext & getContext()=0
virtual void setParsingMSInlineAsm(bool V)=0
virtual void addDirectiveHandler(StringRef Directive, ExtensionDirectiveHandler Handler)=0
bool Error(SMLoc L, const Twine &Msg, SMRange Range=std::nullopt)
Return an error at the location L, with the message Msg.
Binary assembler expressions.
Definition: MCExpr.h:492
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
Definition: MCExpr.h:639
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Definition: MCExpr.h:642
Opcode getOpcode() const
Get the kind of this binary expression.
Definition: MCExpr.h:636
static const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:183
@ Div
Signed division.
Definition: MCExpr.h:497
@ Shl
Shift left.
Definition: MCExpr.h:514
@ AShr
Arithmetic shift right.
Definition: MCExpr.h:515
@ LShr
Logical shift right.
Definition: MCExpr.h:516
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
Definition: MCExpr.h:501
@ EQ
Equality comparison.
Definition: MCExpr.h:498
@ Sub
Subtraction.
Definition: MCExpr.h:517
@ Mul
Multiplication.
Definition: MCExpr.h:510
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
Definition: MCExpr.h:499
@ Mod
Signed remainder.
Definition: MCExpr.h:509
@ And
Bitwise and.
Definition: MCExpr.h:496
@ Or
Bitwise or.
Definition: MCExpr.h:512
@ Xor
Bitwise exclusive or.
Definition: MCExpr.h:518
@ OrNot
Bitwise or not.
Definition: MCExpr.h:513
@ LAnd
Logical and.
Definition: MCExpr.h:503
@ LOr
Logical or.
Definition: MCExpr.h:504
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
Definition: MCExpr.h:505
@ Add
Addition.
Definition: MCExpr.h:495
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
Definition: MCExpr.h:507
@ NE
Inequality comparison.
Definition: MCExpr.h:511
int64_t getValue() const
Definition: MCExpr.h:173
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:81
void * allocate(unsigned Size, unsigned Align=8)
Definition: MCContext.h:842
Environment getObjectFileType() const
Definition: MCContext.h:420
bool isDwarfMD5UsageConsistent(unsigned CUID) const
Reports whether MD5 checksum usage is consistent (all-or-none).
Definition: MCContext.h:761
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:322
bool getGenDwarfForAssembly()
Definition: MCContext.h:786
void setGenDwarfForAssembly(bool Value)
Definition: MCContext.h:787
void setDwarfVersion(uint16_t v)
Definition: MCContext.h:827
MCDwarfLineTable & getMCDwarfLineTable(unsigned CUID)
Definition: MCContext.h:728
MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
Definition: MCContext.cpp:363
CodeViewContext & getCVContext()
Definition: MCContext.cpp:1018
MCSymbol * createDirectionalLocalSymbol(unsigned LocalLabelVal)
Create the definition of a directional local symbol for numbered label (used for "1:" definitions).
Definition: MCContext.cpp:350
uint16_t getDwarfVersion() const
Definition: MCContext.h:828
const MCAsmInfo * getAsmInfo() const
Definition: MCContext.h:437
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:201
MCSymbol * getDirectionalLocalSymbol(unsigned LocalLabelVal, bool Before)
Create and return a directional local symbol for numbered label (used for "1b" or 1f" references).
Definition: MCContext.cpp:355
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
@ Unary
Unary expressions.
Definition: MCExpr.h:41
@ Constant
Constant expressions.
Definition: MCExpr.h:39
@ SymbolRef
References to labels and assigned expressions.
Definition: MCExpr.h:40
@ Target
Target specific expression.
Definition: MCExpr.h:42
@ Binary
Binary expressions.
Definition: MCExpr.h:38
bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const
Try to evaluate the expression to a relocatable value, i.e.
Definition: MCExpr.cpp:814
ExprKind getKind() const
Definition: MCExpr.h:81
static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, SMLoc &Loc)
Definition: MCDwarf.cpp:1205
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
Definition: MCInstPrinter.h:45
virtual void printRegName(raw_ostream &OS, MCRegister Reg) const
Print the assembler register name.
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
virtual bool isMemUseUpRegs() const
isMemUseUpRegs - Is memory operand use up regs, for example, intel MS inline asm may use ARR[baseReg ...
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool needAddressOf() const
needAddressOf - Do we need to emit code to get the address of the variable/label? Only valid when par...
virtual MCRegister getReg() const =0
virtual bool isOffsetOfLocal() const
isOffsetOfLocal - Do we need to emit code to get the offset of the local variable,...
virtual StringRef getSymName()
virtual bool isImm() const =0
isImm - Is this an immediate operand?
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:39
virtual StringRef getVirtualSectionKind() const
Definition: MCSection.cpp:89
void setBeginSymbol(MCSymbol *Sym)
Definition: MCSection.h:133
virtual bool isVirtualSection() const =0
Check whether this section is "virtual", that is has no actual object file contents.
StringRef getName() const
Definition: MCSection.h:124
MCSymbol * getBeginSymbol()
Definition: MCSection.h:129
Streaming machine code generation interface.
Definition: MCStreamer.h:212
virtual void emitAssignment(MCSymbol *Symbol, const MCExpr *Value)
Emit an assignment of Value to Symbol.
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
Definition: MCStreamer.h:380
virtual void initSections(bool NoExecStack, const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
Definition: MCStreamer.cpp:411
void setStartTokLocPtr(const SMLoc *Loc)
Definition: MCStreamer.h:288
virtual bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute)=0
Add the given Attribute to Symbol.
virtual void addExplicitComment(const Twine &T)
Add explicit comment T.
Definition: MCStreamer.cpp:123
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:424
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:304
virtual void emitValueToOffset(const MCExpr *Offset, unsigned char Value, SMLoc Loc)
Emit some number of copies of Value until the byte offset Offset is reached.
virtual void emitConditionalAssignment(MCSymbol *Symbol, const MCExpr *Value)
Emit an assignment of Value to Symbol, but only if Value is also emitted.
Definition: MCStreamer.cpp:443
void finish(SMLoc EndLoc=SMLoc())
Finish emission of machine code.
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
const MCSymbol & getSymbol() const
Definition: MCExpr.h:410
static VariantKind getVariantKindForName(StringRef Name)
Definition: MCExpr.cpp:406
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:397
VariantKind getKind() const
Definition: MCExpr.h:412
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:40
const MCExpr * getVariableValue(bool SetUsed=true) const
getVariableValue - Get the value for variable symbols.
Definition: MCSymbol.h:305
bool isWeakExternal() const
Definition: MCSymbol.h:412
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition: MCSymbol.h:300
MCTargetAsmParser - Generic interface to target specific assembly parsers.
const MCSubtargetInfo & getSTI() const
Unary assembler expressions.
Definition: MCExpr.h:436
Opcode getOpcode() const
Get the kind of this unary expression.
Definition: MCExpr.h:479
static const MCUnaryExpr * create(Opcode Op, const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:189
static const MCUnaryExpr * createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:458
const MCExpr * getSubExpr() const
Get the child of this unary expression.
Definition: MCExpr.h:482
static const MCUnaryExpr * createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:470
static const MCUnaryExpr * createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:466
static const MCUnaryExpr * createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:462
This represents an "assembler immediate".
Definition: MCValue.h:36
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
StringRef getBuffer() const
Definition: MemoryBuffer.h:70
Ternary parse status returned by various parse* methods.
constexpr bool isFailure() const
constexpr bool isSuccess() const
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...
Definition: SourceMgr.h:281
SourceMgr::DiagKind getKind() const
Definition: SourceMgr.h:310
StringRef getLineContents() const
Definition: SourceMgr.h:312
SMLoc getLoc() const
Definition: SourceMgr.h:306
StringRef getMessage() const
Definition: SourceMgr.h:311
ArrayRef< std::pair< unsigned, unsigned > > getRanges() const
Definition: SourceMgr.h:313
const SourceMgr * getSourceMgr() const
Definition: SourceMgr.h:305
int getColumnNo() const
Definition: SourceMgr.h:309
Represents a location in source code.
Definition: SMLoc.h:23
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:36
constexpr const char * getPointer() const
Definition: SMLoc.h:34
constexpr bool isValid() const
Definition: SMLoc.h:29
Represents a range in source code.
Definition: SMLoc.h:48
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:135
void clear()
Definition: SmallSet.h:218
bool contains(const T &V) const
Check if the SmallSet contains the given element.
Definition: SmallSet.h:236
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:179
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void assign(size_type NumElts, ValueParamT Elt)
Definition: SmallVector.h:717
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:950
iterator erase(const_iterator CI)
Definition: SmallVector.h:750
void resize(size_type N)
Definition: SmallVector.h:651
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
Definition: SourceMgr.h:31
void * getDiagContext() const
Definition: SourceMgr.h:118
unsigned getMainFileID() const
Definition: SourceMgr.h:132
DiagHandlerTy getDiagHandler() const
Definition: SourceMgr.h:117
const MemoryBuffer * getMemoryBuffer(unsigned i) const
Definition: SourceMgr.h:125
void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
Definition: SourceMgr.cpp:352
SMLoc getParentIncludeLoc(unsigned i) const
Definition: SourceMgr.h:137
void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const
Prints the names of included files and the line of the file they were included from.
Definition: SourceMgr.cpp:261
unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
Definition: SourceMgr.cpp:73
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
Definition: SourceMgr.h:43
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
Definition: SourceMgr.h:112
unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, std::string &IncludedFile)
Search for a file with the specified name in the current directory or in one of the IncludeDirs.
Definition: SourceMgr.cpp:41
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
Definition: SourceMgr.h:196
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
Definition: SourceMgr.h:144
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:128
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition: StringMap.h:253
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:693
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:223
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:564
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:258
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:602
iterator begin() const
Definition: StringRef.h:111
std::string upper() const
Convert the given ASCII string to uppercase.
Definition: StringRef.cpp:116
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition: StringRef.h:677
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
char front() const
front - Get the first character in the string.
Definition: StringRef.h:140
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
iterator end() const
Definition: StringRef.h:113
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Definition: StringRef.h:573
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
Definition: StringRef.h:808
std::string lower() const
Definition: StringRef.cpp:111
int compare_insensitive(StringRef RHS) const
Compare two strings, ignoring case.
Definition: StringRef.cpp:37
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:660
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:690
This class represents a function that is read from a sample profile.
Definition: FunctionId.h:36
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ ByteAlignment
Definition: MCAsmInfo.h:50
std::variant< std::monostate, Loc::Single, Loc::Multi, Loc::MMI, Loc::EntryValue > Variant
Alias for the std::variant specialization base class of DbgVariable.
Definition: DwarfDebug.h:190
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:148
bool parseAssignmentExpression(StringRef Name, bool allow_redef, MCAsmParser &Parser, MCSymbol *&Symbol, const MCExpr *&Value)
Parse a value expression and return whether it can be assigned to a symbol with the given name.
Definition: AsmParser.cpp:6398
static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value)
Returns whether the given symbol is used anywhere in the given expression, or subexpressions.
Definition: AsmParser.cpp:6373
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
Definition: MCDCTypes.h:56
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
@ DW_EH_PE_pcrel
Definition: Dwarf.h:848
@ DW_EH_PE_signed
Definition: Dwarf.h:847
@ DW_EH_PE_sdata4
Definition: Dwarf.h:845
@ DW_EH_PE_udata2
Definition: Dwarf.h:840
@ DW_EH_PE_sdata8
Definition: Dwarf.h:846
@ DW_EH_PE_absptr
Definition: Dwarf.h:837
@ DW_EH_PE_sdata2
Definition: Dwarf.h:844
@ DW_EH_PE_udata4
Definition: Dwarf.h:841
@ DW_EH_PE_udata8
Definition: Dwarf.h:842
@ DW_EH_PE_omit
Definition: Dwarf.h:838
@ ChecksumKind
Definition: LLToken.h:486
constexpr double e
Definition: MathExtras.h:31
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition: Error.h:1071
@ Offset
Definition: DWP.cpp:456
MCAsmParserExtension * createCOFFAsmParser()
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1680
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:239
@ AOK_EndOfStatement
@ AOK_SizeDirective
AddressSpace
Definition: NVPTXBaseInfo.h:21
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
std::tuple< uint64_t, uint32_t > InlineSite
Definition: MCPseudoProbe.h:99
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2073
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition: MathExtras.h:280
std::vector< MCAsmMacroParameter > MCAsmMacroParameters
Definition: MCAsmMacro.h:141
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:330
MCAsmParserExtension * createXCOFFAsmParser()
SourceMgr SrcMgr
Definition: Error.cpp:24
MCAsmParserExtension * createGOFFAsmParser()
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:419
cl::opt< unsigned > AsmMacroMaxNestingDepth
const char AsmRewritePrecedence[]
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:156
static bool hasDiscriminator(uint32_t Flags)
Definition: PseudoProbe.h:107
MCAsmParserExtension * createWasmAsmParser()
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
MCAsmParser * createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &, const MCAsmInfo &, unsigned CB=0)
Create an MCAsmParser instance for parsing assembly similar to gas syntax.
Definition: AsmParser.cpp:6452
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:244
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition: STLExtras.h:1914
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
Definition: STLExtras.h:1607
MCAsmParserExtension * createELFAsmParser()
MCAsmParserExtension * createDarwinAsmParser()
MCSymbolAttr
Definition: MCDirectives.h:18
@ MCSA_WeakDefAutoPrivate
.weak_def_can_be_hidden (MachO)
Definition: MCDirectives.h:48
@ MCSA_Memtag
.memtag (ELF)
Definition: MCDirectives.h:50
@ MCSA_PrivateExtern
.private_extern (MachO)
Definition: MCDirectives.h:42
@ MCSA_WeakReference
.weak_reference (MachO)
Definition: MCDirectives.h:47
@ MCSA_LazyReference
.lazy_reference (MachO)
Definition: MCDirectives.h:37
@ MCSA_Reference
.reference (MachO)
Definition: MCDirectives.h:44
@ MCSA_SymbolResolver
.symbol_resolver (MachO)
Definition: MCDirectives.h:40
@ MCSA_WeakDefinition
.weak_definition (MachO)
Definition: MCDirectives.h:46
@ MCSA_Global
.type _foo, @gnu_unique_object
Definition: MCDirectives.h:30
@ MCSA_Cold
.cold (MachO)
Definition: MCDirectives.h:22
@ MCSA_NoDeadStrip
.no_dead_strip (MachO)
Definition: MCDirectives.h:39
ArrayRef< int > hi(ArrayRef< int > Vuu)
ArrayRef< int > lo(ArrayRef< int > Vuu)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
AsmRewriteKind Kind
Description of the encoding of one expression Op.
bool hasIndexReg() const
bool hasRegs() const
bool hasOffset() const
bool hasBaseReg() const
bool emitImm() const
bool isValid() const
std::vector< AsmToken > Value
Definition: MCAsmMacro.h:131
Instances of this class represent the name of the dwarf .file directive and its associated dwarf file...
Definition: MCDwarf.h:87
std::optional< MD5::MD5Result > Checksum
The MD5 checksum, if there is one.
Definition: MCDwarf.h:96
std::string Name
Definition: MCDwarf.h:89
std::optional< StringRef > Source
The source code of the file.
Definition: MCDwarf.h:100