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