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