LLVM 20.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 /// Have we seen any file line comment.
166 bool HadCppHashFilename = false;
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, 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_LOC_LABEL,
489 DK_STABS,
490 DK_CV_FILE,
491 DK_CV_FUNC_ID,
492 DK_CV_INLINE_SITE_ID,
493 DK_CV_LOC,
494 DK_CV_LINETABLE,
495 DK_CV_INLINE_LINETABLE,
496 DK_CV_DEF_RANGE,
497 DK_CV_STRINGTABLE,
498 DK_CV_STRING,
499 DK_CV_FILECHECKSUMS,
500 DK_CV_FILECHECKSUM_OFFSET,
501 DK_CV_FPO_DATA,
502 DK_CFI_SECTIONS,
503 DK_CFI_STARTPROC,
504 DK_CFI_ENDPROC,
505 DK_CFI_DEF_CFA,
506 DK_CFI_DEF_CFA_OFFSET,
507 DK_CFI_ADJUST_CFA_OFFSET,
508 DK_CFI_DEF_CFA_REGISTER,
509 DK_CFI_LLVM_DEF_ASPACE_CFA,
510 DK_CFI_OFFSET,
511 DK_CFI_REL_OFFSET,
512 DK_CFI_PERSONALITY,
513 DK_CFI_LSDA,
514 DK_CFI_REMEMBER_STATE,
515 DK_CFI_RESTORE_STATE,
516 DK_CFI_SAME_VALUE,
517 DK_CFI_RESTORE,
518 DK_CFI_ESCAPE,
519 DK_CFI_RETURN_COLUMN,
520 DK_CFI_SIGNAL_FRAME,
521 DK_CFI_UNDEFINED,
522 DK_CFI_REGISTER,
523 DK_CFI_WINDOW_SAVE,
524 DK_CFI_LABEL,
525 DK_CFI_B_KEY_FRAME,
526 DK_CFI_VAL_OFFSET,
527 DK_MACROS_ON,
528 DK_MACROS_OFF,
529 DK_ALTMACRO,
530 DK_NOALTMACRO,
531 DK_MACRO,
532 DK_EXITM,
533 DK_ENDM,
534 DK_ENDMACRO,
535 DK_PURGEM,
536 DK_SLEB128,
537 DK_ULEB128,
538 DK_ERR,
539 DK_ERROR,
540 DK_WARNING,
541 DK_PRINT,
542 DK_ADDRSIG,
543 DK_ADDRSIG_SYM,
544 DK_PSEUDO_PROBE,
545 DK_LTO_DISCARD,
546 DK_LTO_SET_CONDITIONAL,
547 DK_CFI_MTE_TAGGED_FRAME,
548 DK_MEMTAG,
549 DK_END
550 };
551
552 /// Maps directive name --> DirectiveKind enum, for
553 /// directives parsed by this class.
554 StringMap<DirectiveKind> DirectiveKindMap;
555
556 // Codeview def_range type parsing.
557 enum CVDefRangeType {
558 CVDR_DEFRANGE = 0, // Placeholder
559 CVDR_DEFRANGE_REGISTER,
560 CVDR_DEFRANGE_FRAMEPOINTER_REL,
561 CVDR_DEFRANGE_SUBFIELD_REGISTER,
562 CVDR_DEFRANGE_REGISTER_REL
563 };
564
565 /// Maps Codeview def_range types --> CVDefRangeType enum, for
566 /// Codeview def_range types parsed by this class.
567 StringMap<CVDefRangeType> CVDefRangeTypeMap;
568
569 // ".ascii", ".asciz", ".string"
570 bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
571 bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
572 bool parseDirectiveValue(StringRef IDVal,
573 unsigned Size); // ".byte", ".long", ...
574 bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ...
575 bool parseDirectiveRealValue(StringRef IDVal,
576 const fltSemantics &); // ".single", ...
577 bool parseDirectiveFill(); // ".fill"
578 bool parseDirectiveZero(); // ".zero"
579 // ".set", ".equ", ".equiv", ".lto_set_conditional"
580 bool parseDirectiveSet(StringRef IDVal, AssignmentKind Kind);
581 bool parseDirectiveOrg(); // ".org"
582 // ".align{,32}", ".p2align{,w,l}"
583 bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);
584
585 // ".file", ".line", ".loc", ".loc_label", ".stabs"
586 bool parseDirectiveFile(SMLoc DirectiveLoc);
587 bool parseDirectiveLine();
588 bool parseDirectiveLoc();
589 bool parseDirectiveLocLabel(SMLoc DirectiveLoc);
590 bool parseDirectiveStabs();
591
592 // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
593 // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
594 bool parseDirectiveCVFile();
595 bool parseDirectiveCVFuncId();
596 bool parseDirectiveCVInlineSiteId();
597 bool parseDirectiveCVLoc();
598 bool parseDirectiveCVLinetable();
599 bool parseDirectiveCVInlineLinetable();
600 bool parseDirectiveCVDefRange();
601 bool parseDirectiveCVString();
602 bool parseDirectiveCVStringTable();
603 bool parseDirectiveCVFileChecksums();
604 bool parseDirectiveCVFileChecksumOffset();
605 bool parseDirectiveCVFPOData();
606
607 // .cfi directives
608 bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
609 bool parseDirectiveCFIWindowSave(SMLoc DirectiveLoc);
610 bool parseDirectiveCFISections();
611 bool parseDirectiveCFIStartProc();
612 bool parseDirectiveCFIEndProc();
613 bool parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc);
614 bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
615 bool parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc);
616 bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
617 bool parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc);
618 bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
619 bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
620 bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
621 bool parseDirectiveCFIRememberState(SMLoc DirectiveLoc);
622 bool parseDirectiveCFIRestoreState(SMLoc DirectiveLoc);
623 bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
624 bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
625 bool parseDirectiveCFIEscape(SMLoc DirectiveLoc);
626 bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
627 bool parseDirectiveCFISignalFrame(SMLoc DirectiveLoc);
628 bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
629 bool parseDirectiveCFILabel(SMLoc DirectiveLoc);
630 bool parseDirectiveCFIValOffset(SMLoc DirectiveLoc);
631
632 // macro directives
633 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
634 bool parseDirectiveExitMacro(StringRef Directive);
635 bool parseDirectiveEndMacro(StringRef Directive);
636 bool parseDirectiveMacro(SMLoc DirectiveLoc);
637 bool parseDirectiveMacrosOnOff(StringRef Directive);
638 // alternate macro mode directives
639 bool parseDirectiveAltmacro(StringRef Directive);
640 // ".bundle_align_mode"
641 bool parseDirectiveBundleAlignMode();
642 // ".bundle_lock"
643 bool parseDirectiveBundleLock();
644 // ".bundle_unlock"
645 bool parseDirectiveBundleUnlock();
646
647 // ".space", ".skip"
648 bool parseDirectiveSpace(StringRef IDVal);
649
650 // ".dcb"
651 bool parseDirectiveDCB(StringRef IDVal, unsigned Size);
652 bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &);
653 // ".ds"
654 bool parseDirectiveDS(StringRef IDVal, unsigned Size);
655
656 // .sleb128 (Signed=true) and .uleb128 (Signed=false)
657 bool parseDirectiveLEB128(bool Signed);
658
659 /// Parse a directive like ".globl" which
660 /// accepts a single symbol (which should be a label or an external).
661 bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
662
663 bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
664
665 bool parseDirectiveAbort(SMLoc DirectiveLoc); // ".abort"
666 bool parseDirectiveInclude(); // ".include"
667 bool parseDirectiveIncbin(); // ".incbin"
668
669 // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"
670 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
671 // ".ifb" or ".ifnb", depending on ExpectBlank.
672 bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
673 // ".ifc" or ".ifnc", depending on ExpectEqual.
674 bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
675 // ".ifeqs" or ".ifnes", depending on ExpectEqual.
676 bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);
677 // ".ifdef" or ".ifndef", depending on expect_defined
678 bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
679 bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
680 bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
681 bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
682 bool parseEscapedString(std::string &Data) override;
683 bool parseAngleBracketString(std::string &Data) override;
684
685 const MCExpr *applyModifierToExpr(const MCExpr *E,
687
688 // Macro-like directives
689 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
690 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
692 bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);
693 bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
694 bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
695 bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
696
697 // "_emit" or "__emit"
698 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
699 size_t Len);
700
701 // "align"
702 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
703
704 // "end"
705 bool parseDirectiveEnd(SMLoc DirectiveLoc);
706
707 // ".err" or ".error"
708 bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
709
710 // ".warning"
711 bool parseDirectiveWarning(SMLoc DirectiveLoc);
712
713 // .print <double-quotes-string>
714 bool parseDirectivePrint(SMLoc DirectiveLoc);
715
716 // .pseudoprobe
717 bool parseDirectivePseudoProbe();
718
719 // ".lto_discard"
720 bool parseDirectiveLTODiscard();
721
722 // Directives to support address-significance tables.
723 bool parseDirectiveAddrsig();
724 bool parseDirectiveAddrsigSym();
725
726 void initializeDirectiveKindMap();
727 void initializeCVDefRangeTypeMap();
728};
729
730class HLASMAsmParser final : public AsmParser {
731private:
732 MCAsmLexer &Lexer;
733 MCStreamer &Out;
734
735 void lexLeadingSpaces() {
736 while (Lexer.is(AsmToken::Space))
737 Lexer.Lex();
738 }
739
740 bool parseAsHLASMLabel(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI);
741 bool parseAsMachineInstruction(ParseStatementInfo &Info,
743
744public:
745 HLASMAsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
746 const MCAsmInfo &MAI, unsigned CB = 0)
747 : AsmParser(SM, Ctx, Out, MAI, CB), Lexer(getLexer()), Out(Out) {
748 Lexer.setSkipSpace(false);
749 Lexer.setAllowHashInIdentifier(true);
750 Lexer.setLexHLASMIntegers(true);
751 Lexer.setLexHLASMStrings(true);
752 }
753
754 ~HLASMAsmParser() { Lexer.setSkipSpace(true); }
755
756 bool parseStatement(ParseStatementInfo &Info,
757 MCAsmParserSemaCallback *SI) override;
758};
759
760} // end anonymous namespace
761
762namespace llvm {
763
765
772
773} // end namespace llvm
774
775enum { DEFAULT_ADDRSPACE = 0 };
776
777AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
778 const MCAsmInfo &MAI, unsigned CB = 0)
779 : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
780 CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {
781 HadError = false;
782 // Save the old handler.
783 SavedDiagHandler = SrcMgr.getDiagHandler();
784 SavedDiagContext = SrcMgr.getDiagContext();
785 // Set our own handler which calls the saved handler.
787 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
788 // Make MCStreamer aware of the StartTokLoc for locations in diagnostics.
789 Out.setStartTokLocPtr(&StartTokLoc);
790
791 // Initialize the platform / file format parser.
792 switch (Ctx.getObjectFileType()) {
794 PlatformParser.reset(createCOFFAsmParser());
795 break;
797 PlatformParser.reset(createDarwinAsmParser());
798 IsDarwin = true;
799 break;
800 case MCContext::IsELF:
801 PlatformParser.reset(createELFAsmParser());
802 break;
804 PlatformParser.reset(createGOFFAsmParser());
805 break;
808 "Need to implement createSPIRVAsmParser for SPIRV format.");
809 break;
811 PlatformParser.reset(createWasmAsmParser());
812 break;
814 PlatformParser.reset(createXCOFFAsmParser());
815 break;
817 report_fatal_error("DXContainer is not supported yet");
818 break;
819 }
820
821 PlatformParser->Initialize(*this);
822 initializeDirectiveKindMap();
823 initializeCVDefRangeTypeMap();
824
825 NumOfMacroInstantiations = 0;
826}
827
828AsmParser::~AsmParser() {
829 assert((HadError || ActiveMacros.empty()) &&
830 "Unexpected active macro instantiation!");
831
832 // Remove MCStreamer's reference to the parser SMLoc.
833 Out.setStartTokLocPtr(nullptr);
834 // Restore the saved diagnostics handler and context for use during
835 // finalization.
836 SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
837}
838
839void AsmParser::printMacroInstantiations() {
840 // Print the active macro instantiation stack.
841 for (MacroInstantiation *M : reverse(ActiveMacros))
842 printMessage(M->InstantiationLoc, SourceMgr::DK_Note,
843 "while in macro instantiation");
844}
845
846void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
847 printPendingErrors();
848 printMessage(L, SourceMgr::DK_Note, Msg, Range);
849 printMacroInstantiations();
850}
851
852bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
853 if(getTargetParser().getTargetOptions().MCNoWarn)
854 return false;
855 if (getTargetParser().getTargetOptions().MCFatalWarnings)
856 return Error(L, Msg, Range);
857 printMessage(L, SourceMgr::DK_Warning, Msg, Range);
858 printMacroInstantiations();
859 return false;
860}
861
862bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
863 HadError = true;
864 printMessage(L, SourceMgr::DK_Error, Msg, Range);
865 printMacroInstantiations();
866 return true;
867}
868
869bool AsmParser::enterIncludeFile(const std::string &Filename) {
870 std::string IncludedFile;
871 unsigned NewBuf =
872 SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
873 if (!NewBuf)
874 return true;
875
876 CurBuffer = NewBuf;
877 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
878 return false;
879}
880
881/// Process the specified .incbin file by searching for it in the include paths
882/// then just emitting the byte contents of the file to the streamer. This
883/// returns true on failure.
884bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
885 const MCExpr *Count, SMLoc Loc) {
886 std::string IncludedFile;
887 unsigned NewBuf =
888 SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
889 if (!NewBuf)
890 return true;
891
892 // Pick up the bytes from the file and emit them.
893 StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();
894 Bytes = Bytes.drop_front(Skip);
895 if (Count) {
896 int64_t Res;
897 if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
898 return Error(Loc, "expected absolute expression");
899 if (Res < 0)
900 return Warning(Loc, "negative count has no effect");
901 Bytes = Bytes.take_front(Res);
902 }
903 getStreamer().emitBytes(Bytes);
904 return false;
905}
906
907void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
908 CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
909 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
910 Loc.getPointer());
911}
912
913const AsmToken &AsmParser::Lex() {
914 if (Lexer.getTok().is(AsmToken::Error))
915 Error(Lexer.getErrLoc(), Lexer.getErr());
916
917 // if it's a end of statement with a comment in it
918 if (getTok().is(AsmToken::EndOfStatement)) {
919 // if this is a line comment output it.
920 if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
921 getTok().getString().front() != '\r' && MAI.preserveAsmComments())
922 Out.addExplicitComment(Twine(getTok().getString()));
923 }
924
925 const AsmToken *tok = &Lexer.Lex();
926
927 // Parse comments here to be deferred until end of next statement.
928 while (tok->is(AsmToken::Comment)) {
929 if (MAI.preserveAsmComments())
931 tok = &Lexer.Lex();
932 }
933
934 if (tok->is(AsmToken::Eof)) {
935 // If this is the end of an included file, pop the parent file off the
936 // include stack.
937 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
938 if (ParentIncludeLoc != SMLoc()) {
939 jumpToLoc(ParentIncludeLoc);
940 return Lex();
941 }
942 }
943
944 return *tok;
945}
946
947bool AsmParser::enabledGenDwarfForAssembly() {
948 // Check whether the user specified -g.
949 if (!getContext().getGenDwarfForAssembly())
950 return false;
951 // If we haven't encountered any .file directives (which would imply that
952 // the assembler source was produced with debug info already) then emit one
953 // describing the assembler source file itself.
954 if (getContext().getGenDwarfFileNumber() == 0) {
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 necessarily 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(IDLoc);
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_LOC_LABEL:
2158 return parseDirectiveLocLabel(IDLoc);
2159 case DK_STABS:
2160 return parseDirectiveStabs();
2161 case DK_CV_FILE:
2162 return parseDirectiveCVFile();
2163 case DK_CV_FUNC_ID:
2164 return parseDirectiveCVFuncId();
2165 case DK_CV_INLINE_SITE_ID:
2166 return parseDirectiveCVInlineSiteId();
2167 case DK_CV_LOC:
2168 return parseDirectiveCVLoc();
2169 case DK_CV_LINETABLE:
2170 return parseDirectiveCVLinetable();
2171 case DK_CV_INLINE_LINETABLE:
2172 return parseDirectiveCVInlineLinetable();
2173 case DK_CV_DEF_RANGE:
2174 return parseDirectiveCVDefRange();
2175 case DK_CV_STRING:
2176 return parseDirectiveCVString();
2177 case DK_CV_STRINGTABLE:
2178 return parseDirectiveCVStringTable();
2179 case DK_CV_FILECHECKSUMS:
2180 return parseDirectiveCVFileChecksums();
2181 case DK_CV_FILECHECKSUM_OFFSET:
2182 return parseDirectiveCVFileChecksumOffset();
2183 case DK_CV_FPO_DATA:
2184 return parseDirectiveCVFPOData();
2185 case DK_CFI_SECTIONS:
2186 return parseDirectiveCFISections();
2187 case DK_CFI_STARTPROC:
2188 return parseDirectiveCFIStartProc();
2189 case DK_CFI_ENDPROC:
2190 return parseDirectiveCFIEndProc();
2191 case DK_CFI_DEF_CFA:
2192 return parseDirectiveCFIDefCfa(IDLoc);
2193 case DK_CFI_DEF_CFA_OFFSET:
2194 return parseDirectiveCFIDefCfaOffset(IDLoc);
2195 case DK_CFI_ADJUST_CFA_OFFSET:
2196 return parseDirectiveCFIAdjustCfaOffset(IDLoc);
2197 case DK_CFI_DEF_CFA_REGISTER:
2198 return parseDirectiveCFIDefCfaRegister(IDLoc);
2199 case DK_CFI_LLVM_DEF_ASPACE_CFA:
2200 return parseDirectiveCFILLVMDefAspaceCfa(IDLoc);
2201 case DK_CFI_OFFSET:
2202 return parseDirectiveCFIOffset(IDLoc);
2203 case DK_CFI_REL_OFFSET:
2204 return parseDirectiveCFIRelOffset(IDLoc);
2205 case DK_CFI_PERSONALITY:
2206 return parseDirectiveCFIPersonalityOrLsda(true);
2207 case DK_CFI_LSDA:
2208 return parseDirectiveCFIPersonalityOrLsda(false);
2209 case DK_CFI_REMEMBER_STATE:
2210 return parseDirectiveCFIRememberState(IDLoc);
2211 case DK_CFI_RESTORE_STATE:
2212 return parseDirectiveCFIRestoreState(IDLoc);
2213 case DK_CFI_SAME_VALUE:
2214 return parseDirectiveCFISameValue(IDLoc);
2215 case DK_CFI_RESTORE:
2216 return parseDirectiveCFIRestore(IDLoc);
2217 case DK_CFI_ESCAPE:
2218 return parseDirectiveCFIEscape(IDLoc);
2219 case DK_CFI_RETURN_COLUMN:
2220 return parseDirectiveCFIReturnColumn(IDLoc);
2221 case DK_CFI_SIGNAL_FRAME:
2222 return parseDirectiveCFISignalFrame(IDLoc);
2223 case DK_CFI_UNDEFINED:
2224 return parseDirectiveCFIUndefined(IDLoc);
2225 case DK_CFI_REGISTER:
2226 return parseDirectiveCFIRegister(IDLoc);
2227 case DK_CFI_WINDOW_SAVE:
2228 return parseDirectiveCFIWindowSave(IDLoc);
2229 case DK_CFI_LABEL:
2230 return parseDirectiveCFILabel(IDLoc);
2231 case DK_CFI_VAL_OFFSET:
2232 return parseDirectiveCFIValOffset(IDLoc);
2233 case DK_MACROS_ON:
2234 case DK_MACROS_OFF:
2235 return parseDirectiveMacrosOnOff(IDVal);
2236 case DK_MACRO:
2237 return parseDirectiveMacro(IDLoc);
2238 case DK_ALTMACRO:
2239 case DK_NOALTMACRO:
2240 return parseDirectiveAltmacro(IDVal);
2241 case DK_EXITM:
2242 return parseDirectiveExitMacro(IDVal);
2243 case DK_ENDM:
2244 case DK_ENDMACRO:
2245 return parseDirectiveEndMacro(IDVal);
2246 case DK_PURGEM:
2247 return parseDirectivePurgeMacro(IDLoc);
2248 case DK_END:
2249 return parseDirectiveEnd(IDLoc);
2250 case DK_ERR:
2251 return parseDirectiveError(IDLoc, false);
2252 case DK_ERROR:
2253 return parseDirectiveError(IDLoc, true);
2254 case DK_WARNING:
2255 return parseDirectiveWarning(IDLoc);
2256 case DK_RELOC:
2257 return parseDirectiveReloc(IDLoc);
2258 case DK_DCB:
2259 case DK_DCB_W:
2260 return parseDirectiveDCB(IDVal, 2);
2261 case DK_DCB_B:
2262 return parseDirectiveDCB(IDVal, 1);
2263 case DK_DCB_D:
2264 return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble());
2265 case DK_DCB_L:
2266 return parseDirectiveDCB(IDVal, 4);
2267 case DK_DCB_S:
2268 return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle());
2269 case DK_DC_X:
2270 case DK_DCB_X:
2271 return TokError(Twine(IDVal) +
2272 " not currently supported for this target");
2273 case DK_DS:
2274 case DK_DS_W:
2275 return parseDirectiveDS(IDVal, 2);
2276 case DK_DS_B:
2277 return parseDirectiveDS(IDVal, 1);
2278 case DK_DS_D:
2279 return parseDirectiveDS(IDVal, 8);
2280 case DK_DS_L:
2281 case DK_DS_S:
2282 return parseDirectiveDS(IDVal, 4);
2283 case DK_DS_P:
2284 case DK_DS_X:
2285 return parseDirectiveDS(IDVal, 12);
2286 case DK_PRINT:
2287 return parseDirectivePrint(IDLoc);
2288 case DK_ADDRSIG:
2289 return parseDirectiveAddrsig();
2290 case DK_ADDRSIG_SYM:
2291 return parseDirectiveAddrsigSym();
2292 case DK_PSEUDO_PROBE:
2293 return parseDirectivePseudoProbe();
2294 case DK_LTO_DISCARD:
2295 return parseDirectiveLTODiscard();
2296 case DK_MEMTAG:
2297 return parseDirectiveSymbolAttribute(MCSA_Memtag);
2298 }
2299
2300 return Error(IDLoc, "unknown directive");
2301 }
2302
2303 // __asm _emit or __asm __emit
2304 if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
2305 IDVal == "_EMIT" || IDVal == "__EMIT"))
2306 return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
2307
2308 // __asm align
2309 if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
2310 return parseDirectiveMSAlign(IDLoc, Info);
2311
2312 if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
2313 Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
2314 if (checkForValidSection())
2315 return true;
2316
2317 return parseAndMatchAndEmitTargetInstruction(Info, IDVal, ID, IDLoc);
2318}
2319
2320bool AsmParser::parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,
2321 StringRef IDVal,
2322 AsmToken ID,
2323 SMLoc IDLoc) {
2324 // Canonicalize the opcode to lower case.
2325 std::string OpcodeStr = IDVal.lower();
2326 ParseInstructionInfo IInfo(Info.AsmRewrites);
2327 bool ParseHadError = getTargetParser().parseInstruction(IInfo, OpcodeStr, ID,
2328 Info.ParsedOperands);
2329 Info.ParseError = ParseHadError;
2330
2331 // Dump the parsed representation, if requested.
2332 if (getShowParsedOperands()) {
2333 SmallString<256> Str;
2335 OS << "parsed instruction: [";
2336 for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
2337 if (i != 0)
2338 OS << ", ";
2339 Info.ParsedOperands[i]->print(OS);
2340 }
2341 OS << "]";
2342
2343 printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
2344 }
2345
2346 // Fail even if ParseInstruction erroneously returns false.
2347 if (hasPendingError() || ParseHadError)
2348 return true;
2349
2350 // If we are generating dwarf for the current section then generate a .loc
2351 // directive for the instruction.
2352 if (!ParseHadError && enabledGenDwarfForAssembly() &&
2353 getContext().getGenDwarfSectionSyms().count(
2354 getStreamer().getCurrentSectionOnly())) {
2355 unsigned Line;
2356 if (ActiveMacros.empty())
2357 Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
2358 else
2359 Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
2360 ActiveMacros.front()->ExitBuffer);
2361
2362 // If we previously parsed a cpp hash file line comment then make sure the
2363 // current Dwarf File is for the CppHashFilename if not then emit the
2364 // Dwarf File table for it and adjust the line number for the .loc.
2365 if (!CppHashInfo.Filename.empty()) {
2366 unsigned FileNumber = getStreamer().emitDwarfFileDirective(
2367 0, StringRef(), CppHashInfo.Filename);
2368 getContext().setGenDwarfFileNumber(FileNumber);
2369
2370 unsigned CppHashLocLineNo =
2371 SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
2372 Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
2373 }
2374
2375 getStreamer().emitDwarfLocDirective(
2376 getContext().getGenDwarfFileNumber(), Line, 0,
2378 StringRef());
2379 }
2380
2381 // If parsing succeeded, match the instruction.
2382 if (!ParseHadError) {
2384 if (getTargetParser().matchAndEmitInstruction(
2385 IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
2386 getTargetParser().isParsingMSInlineAsm()))
2387 return true;
2388 }
2389 return false;
2390}
2391
2392// Parse and erase curly braces marking block start/end
2393bool
2394AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2395 // Identify curly brace marking block start/end
2396 if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
2397 return false;
2398
2399 SMLoc StartLoc = Lexer.getLoc();
2400 Lex(); // Eat the brace
2401 if (Lexer.is(AsmToken::EndOfStatement))
2402 Lex(); // Eat EndOfStatement following the brace
2403
2404 // Erase the block start/end brace from the output asm string
2405 AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
2406 StartLoc.getPointer());
2407 return true;
2408}
2409
2410/// parseCppHashLineFilenameComment as this:
2411/// ::= # number "filename"
2412bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) {
2413 Lex(); // Eat the hash token.
2414 // Lexer only ever emits HashDirective if it fully formed if it's
2415 // done the checking already so this is an internal error.
2416 assert(getTok().is(AsmToken::Integer) &&
2417 "Lexing Cpp line comment: Expected Integer");
2418 int64_t LineNumber = getTok().getIntVal();
2419 Lex();
2420 assert(getTok().is(AsmToken::String) &&
2421 "Lexing Cpp line comment: Expected String");
2422 StringRef Filename = getTok().getString();
2423 Lex();
2424
2425 if (!SaveLocInfo)
2426 return false;
2427
2428 // Get rid of the enclosing quotes.
2429 Filename = Filename.substr(1, Filename.size() - 2);
2430
2431 // Save the SMLoc, Filename and LineNumber for later use by diagnostics
2432 // and possibly DWARF file info.
2433 CppHashInfo.Loc = L;
2434 CppHashInfo.Filename = Filename;
2435 CppHashInfo.LineNumber = LineNumber;
2436 CppHashInfo.Buf = CurBuffer;
2437 if (!HadCppHashFilename) {
2438 HadCppHashFilename = true;
2439 // If we haven't encountered any .file directives, then the first #line
2440 // directive describes the "root" file and directory of the compilation
2441 // unit.
2442 if (getContext().getGenDwarfForAssembly() &&
2443 getContext().getGenDwarfFileNumber() == 0) {
2444 // It's preprocessed, so there is no checksum, and of course no source
2445 // directive.
2446 getContext().setMCLineTableRootFile(
2447 /*CUID=*/0, getContext().getCompilationDir(), Filename,
2448 /*Cksum=*/std::nullopt, /*Source=*/std::nullopt);
2449 }
2450 }
2451 return false;
2452}
2453
2454/// will use the last parsed cpp hash line filename comment
2455/// for the Filename and LineNo if any in the diagnostic.
2456void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
2457 auto *Parser = static_cast<AsmParser *>(Context);
2458 raw_ostream &OS = errs();
2459
2460 const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
2461 SMLoc DiagLoc = Diag.getLoc();
2462 unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
2463 unsigned CppHashBuf =
2464 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2465
2466 // Like SourceMgr::printMessage() we need to print the include stack if any
2467 // before printing the message.
2468 unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
2469 if (!Parser->SavedDiagHandler && DiagCurBuffer &&
2470 DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
2471 SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
2472 DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
2473 }
2474
2475 // If we have not parsed a cpp hash line filename comment or the source
2476 // manager changed or buffer changed (like in a nested include) then just
2477 // print the normal diagnostic using its Filename and LineNo.
2478 if (!Parser->CppHashInfo.LineNumber || DiagBuf != CppHashBuf) {
2479 if (Parser->SavedDiagHandler)
2480 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2481 else
2482 Parser->getContext().diagnose(Diag);
2483 return;
2484 }
2485
2486 // Use the CppHashFilename and calculate a line number based on the
2487 // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
2488 // for the diagnostic.
2489 const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
2490
2491 int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
2492 int CppHashLocLineNo =
2493 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2494 int LineNo =
2495 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2496
2497 SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
2498 Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
2499 Diag.getLineContents(), Diag.getRanges());
2500
2501 if (Parser->SavedDiagHandler)
2502 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2503 else
2504 Parser->getContext().diagnose(NewDiag);
2505}
2506
2507// FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The
2508// difference being that that function accepts '@' as part of identifiers and
2509// we can't do that. AsmLexer.cpp should probably be changed to handle
2510// '@' as a special case when needed.
2511static bool isIdentifierChar(char c) {
2512 return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||
2513 c == '.';
2514}
2515
2516bool AsmParser::expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,
2519 bool EnableAtPseudoVariable) {
2520 unsigned NParameters = Parameters.size();
2521 auto expandArg = [&](unsigned Index) {
2522 bool HasVararg = NParameters ? Parameters.back().Vararg : false;
2523 bool VarargParameter = HasVararg && Index == (NParameters - 1);
2524 for (const AsmToken &Token : A[Index])
2525 // For altmacro mode, you can write '%expr'.
2526 // The prefix '%' evaluates the expression 'expr'
2527 // and uses the result as a string (e.g. replace %(1+2) with the
2528 // string "3").
2529 // Here, we identify the integer token which is the result of the
2530 // absolute expression evaluation and replace it with its string
2531 // representation.
2532 if (AltMacroMode && Token.getString().front() == '%' &&
2533 Token.is(AsmToken::Integer))
2534 // Emit an integer value to the buffer.
2535 OS << Token.getIntVal();
2536 // Only Token that was validated as a string and begins with '<'
2537 // is considered altMacroString!!!
2538 else if (AltMacroMode && Token.getString().front() == '<' &&
2539 Token.is(AsmToken::String)) {
2540 OS << angleBracketString(Token.getStringContents());
2541 }
2542 // We expect no quotes around the string's contents when
2543 // parsing for varargs.
2544 else if (Token.isNot(AsmToken::String) || VarargParameter)
2545 OS << Token.getString();
2546 else
2547 OS << Token.getStringContents();
2548 };
2549
2550 // A macro without parameters is handled differently on Darwin:
2551 // gas accepts no arguments and does no substitutions
2552 StringRef Body = Macro.Body;
2553 size_t I = 0, End = Body.size();
2554 while (I != End) {
2555 if (Body[I] == '\\' && I + 1 != End) {
2556 // Check for \@ and \+ pseudo variables.
2557 if (EnableAtPseudoVariable && Body[I + 1] == '@') {
2558 OS << NumOfMacroInstantiations;
2559 I += 2;
2560 continue;
2561 }
2562 if (Body[I + 1] == '+') {
2563 OS << Macro.Count;
2564 I += 2;
2565 continue;
2566 }
2567 if (Body[I + 1] == '(' && Body[I + 2] == ')') {
2568 I += 3;
2569 continue;
2570 }
2571
2572 size_t Pos = ++I;
2573 while (I != End && isIdentifierChar(Body[I]))
2574 ++I;
2575 StringRef Argument(Body.data() + Pos, I - Pos);
2576 if (AltMacroMode && I != End && Body[I] == '&')
2577 ++I;
2578 unsigned Index = 0;
2579 for (; Index < NParameters; ++Index)
2580 if (Parameters[Index].Name == Argument)
2581 break;
2582 if (Index == NParameters)
2583 OS << '\\' << Argument;
2584 else
2585 expandArg(Index);
2586 continue;
2587 }
2588
2589 // In Darwin mode, $ is used for macro expansion, not considered an
2590 // identifier char.
2591 if (Body[I] == '$' && I + 1 != End && IsDarwin && !NParameters) {
2592 // This macro has no parameters, look for $0, $1, etc.
2593 switch (Body[I + 1]) {
2594 // $$ => $
2595 case '$':
2596 OS << '$';
2597 I += 2;
2598 continue;
2599 // $n => number of arguments
2600 case 'n':
2601 OS << A.size();
2602 I += 2;
2603 continue;
2604 default: {
2605 if (!isDigit(Body[I + 1]))
2606 break;
2607 // $[0-9] => argument
2608 // Missing arguments are ignored.
2609 unsigned Index = Body[I + 1] - '0';
2610 if (Index < A.size())
2611 for (const AsmToken &Token : A[Index])
2612 OS << Token.getString();
2613 I += 2;
2614 continue;
2615 }
2616 }
2617 }
2618
2619 if (!isIdentifierChar(Body[I]) || IsDarwin) {
2620 OS << Body[I++];
2621 continue;
2622 }
2623
2624 const size_t Start = I;
2625 while (++I && isIdentifierChar(Body[I])) {
2626 }
2627 StringRef Token(Body.data() + Start, I - Start);
2628 if (AltMacroMode) {
2629 unsigned Index = 0;
2630 for (; Index != NParameters; ++Index)
2631 if (Parameters[Index].Name == Token)
2632 break;
2633 if (Index != NParameters) {
2634 expandArg(Index);
2635 if (I != End && Body[I] == '&')
2636 ++I;
2637 continue;
2638 }
2639 }
2640 OS << Token;
2641 }
2642
2643 ++Macro.Count;
2644 return false;
2645}
2646
2648 switch (kind) {
2649 default:
2650 return false;
2651 case AsmToken::Plus:
2652 case AsmToken::Minus:
2653 case AsmToken::Tilde:
2654 case AsmToken::Slash:
2655 case AsmToken::Star:
2656 case AsmToken::Dot:
2657 case AsmToken::Equal:
2659 case AsmToken::Pipe:
2660 case AsmToken::PipePipe:
2661 case AsmToken::Caret:
2662 case AsmToken::Amp:
2663 case AsmToken::AmpAmp:
2664 case AsmToken::Exclaim:
2666 case AsmToken::Less:
2668 case AsmToken::LessLess:
2670 case AsmToken::Greater:
2673 return true;
2674 }
2675}
2676
2677namespace {
2678
2679class AsmLexerSkipSpaceRAII {
2680public:
2681 AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
2682 Lexer.setSkipSpace(SkipSpace);
2683 }
2684
2685 ~AsmLexerSkipSpaceRAII() {
2686 Lexer.setSkipSpace(true);
2687 }
2688
2689private:
2690 AsmLexer &Lexer;
2691};
2692
2693} // end anonymous namespace
2694
2695bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
2696
2697 if (Vararg) {
2698 if (Lexer.isNot(AsmToken::EndOfStatement)) {
2699 StringRef Str = parseStringToEndOfStatement();
2700 MA.emplace_back(AsmToken::String, Str);
2701 }
2702 return false;
2703 }
2704
2705 unsigned ParenLevel = 0;
2706
2707 // Darwin doesn't use spaces to delmit arguments.
2708 AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
2709
2710 bool SpaceEaten;
2711
2712 while (true) {
2713 SpaceEaten = false;
2714 if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
2715 return TokError("unexpected token in macro instantiation");
2716
2717 if (ParenLevel == 0) {
2718
2719 if (Lexer.is(AsmToken::Comma))
2720 break;
2721
2722 if (parseOptionalToken(AsmToken::Space))
2723 SpaceEaten = true;
2724
2725 // Spaces can delimit parameters, but could also be part an expression.
2726 // If the token after a space is an operator, add the token and the next
2727 // one into this argument
2728 if (!IsDarwin) {
2729 if (isOperator(Lexer.getKind())) {
2730 MA.push_back(getTok());
2731 Lexer.Lex();
2732
2733 // Whitespace after an operator can be ignored.
2734 parseOptionalToken(AsmToken::Space);
2735 continue;
2736 }
2737 }
2738 if (SpaceEaten)
2739 break;
2740 }
2741
2742 // handleMacroEntry relies on not advancing the lexer here
2743 // to be able to fill in the remaining default parameter values
2744 if (Lexer.is(AsmToken::EndOfStatement))
2745 break;
2746
2747 // Adjust the current parentheses level.
2748 if (Lexer.is(AsmToken::LParen))
2749 ++ParenLevel;
2750 else if (Lexer.is(AsmToken::RParen) && ParenLevel)
2751 --ParenLevel;
2752
2753 // Append the token to the current argument list.
2754 MA.push_back(getTok());
2755 Lexer.Lex();
2756 }
2757
2758 if (ParenLevel != 0)
2759 return TokError("unbalanced parentheses in macro argument");
2760 return false;
2761}
2762
2763// Parse the macro instantiation arguments.
2764bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
2765 MCAsmMacroArguments &A) {
2766 const unsigned NParameters = M ? M->Parameters.size() : 0;
2767 bool NamedParametersFound = false;
2768 SmallVector<SMLoc, 4> FALocs;
2769
2770 A.resize(NParameters);
2771 FALocs.resize(NParameters);
2772
2773 // Parse two kinds of macro invocations:
2774 // - macros defined without any parameters accept an arbitrary number of them
2775 // - macros defined with parameters accept at most that many of them
2776 bool HasVararg = NParameters ? M->Parameters.back().Vararg : false;
2777 for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
2778 ++Parameter) {
2779 SMLoc IDLoc = Lexer.getLoc();
2781
2782 if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
2783 if (parseIdentifier(FA.Name))
2784 return Error(IDLoc, "invalid argument identifier for formal argument");
2785
2786 if (Lexer.isNot(AsmToken::Equal))
2787 return TokError("expected '=' after formal parameter identifier");
2788
2789 Lex();
2790
2791 NamedParametersFound = true;
2792 }
2793 bool Vararg = HasVararg && Parameter == (NParameters - 1);
2794
2795 if (NamedParametersFound && FA.Name.empty())
2796 return Error(IDLoc, "cannot mix positional and keyword arguments");
2797
2798 SMLoc StrLoc = Lexer.getLoc();
2799 SMLoc EndLoc;
2800 if (AltMacroMode && Lexer.is(AsmToken::Percent)) {
2801 const MCExpr *AbsoluteExp;
2802 int64_t Value;
2803 /// Eat '%'
2804 Lex();
2805 if (parseExpression(AbsoluteExp, EndLoc))
2806 return false;
2807 if (!AbsoluteExp->evaluateAsAbsolute(Value,
2808 getStreamer().getAssemblerPtr()))
2809 return Error(StrLoc, "expected absolute expression");
2810 const char *StrChar = StrLoc.getPointer();
2811 const char *EndChar = EndLoc.getPointer();
2812 AsmToken newToken(AsmToken::Integer,
2813 StringRef(StrChar, EndChar - StrChar), Value);
2814 FA.Value.push_back(newToken);
2815 } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
2816 isAngleBracketString(StrLoc, EndLoc)) {
2817 const char *StrChar = StrLoc.getPointer();
2818 const char *EndChar = EndLoc.getPointer();
2819 jumpToLoc(EndLoc, CurBuffer);
2820 /// Eat from '<' to '>'
2821 Lex();
2822 AsmToken newToken(AsmToken::String,
2823 StringRef(StrChar, EndChar - StrChar));
2824 FA.Value.push_back(newToken);
2825 } else if(parseMacroArgument(FA.Value, Vararg))
2826 return true;
2827
2828 unsigned PI = Parameter;
2829 if (!FA.Name.empty()) {
2830 unsigned FAI = 0;
2831 for (FAI = 0; FAI < NParameters; ++FAI)
2832 if (M->Parameters[FAI].Name == FA.Name)
2833 break;
2834
2835 if (FAI >= NParameters) {
2836 assert(M && "expected macro to be defined");
2837 return Error(IDLoc, "parameter named '" + FA.Name +
2838 "' does not exist for macro '" + M->Name + "'");
2839 }
2840 PI = FAI;
2841 }
2842
2843 if (!FA.Value.empty()) {
2844 if (A.size() <= PI)
2845 A.resize(PI + 1);
2846 A[PI] = FA.Value;
2847
2848 if (FALocs.size() <= PI)
2849 FALocs.resize(PI + 1);
2850
2851 FALocs[PI] = Lexer.getLoc();
2852 }
2853
2854 // At the end of the statement, fill in remaining arguments that have
2855 // default values. If there aren't any, then the next argument is
2856 // required but missing
2857 if (Lexer.is(AsmToken::EndOfStatement)) {
2858 bool Failure = false;
2859 for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
2860 if (A[FAI].empty()) {
2861 if (M->Parameters[FAI].Required) {
2862 Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
2863 "missing value for required parameter "
2864 "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
2865 Failure = true;
2866 }
2867
2868 if (!M->Parameters[FAI].Value.empty())
2869 A[FAI] = M->Parameters[FAI].Value;
2870 }
2871 }
2872 return Failure;
2873 }
2874
2875 parseOptionalToken(AsmToken::Comma);
2876 }
2877
2878 return TokError("too many positional arguments");
2879}
2880
2881bool AsmParser::handleMacroEntry(MCAsmMacro *M, SMLoc NameLoc) {
2882 // Arbitrarily limit macro nesting depth (default matches 'as'). We can
2883 // eliminate this, although we should protect against infinite loops.
2884 unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
2885 if (ActiveMacros.size() == MaxNestingDepth) {
2886 std::ostringstream MaxNestingDepthError;
2887 MaxNestingDepthError << "macros cannot be nested more than "
2888 << MaxNestingDepth << " levels deep."
2889 << " Use -asm-macro-max-nesting-depth to increase "
2890 "this limit.";
2891 return TokError(MaxNestingDepthError.str());
2892 }
2893
2894 MCAsmMacroArguments A;
2895 if (parseMacroArguments(M, A))
2896 return true;
2897
2898 // Macro instantiation is lexical, unfortunately. We construct a new buffer
2899 // to hold the macro body with substitutions.
2900 SmallString<256> Buf;
2902
2903 if ((!IsDarwin || M->Parameters.size()) && M->Parameters.size() != A.size())
2904 return Error(getTok().getLoc(), "Wrong number of arguments");
2905 if (expandMacro(OS, *M, M->Parameters, A, true))
2906 return true;
2907
2908 // We include the .endmacro in the buffer as our cue to exit the macro
2909 // instantiation.
2910 OS << ".endmacro\n";
2911
2912 std::unique_ptr<MemoryBuffer> Instantiation =
2913 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
2914
2915 // Create the macro instantiation object and add to the current macro
2916 // instantiation stack.
2917 MacroInstantiation *MI = new MacroInstantiation{
2918 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2919 ActiveMacros.push_back(MI);
2920
2921 ++NumOfMacroInstantiations;
2922
2923 // Jump to the macro instantiation and prime the lexer.
2924 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
2925 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
2926 Lex();
2927
2928 return false;
2929}
2930
2931void AsmParser::handleMacroExit() {
2932 // Jump to the EndOfStatement we should return to, and consume it.
2933 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
2934 Lex();
2935 // If .endm/.endr is followed by \n instead of a comment, consume it so that
2936 // we don't print an excess \n.
2937 if (getTok().is(AsmToken::EndOfStatement))
2938 Lex();
2939
2940 // Pop the instantiation entry.
2941 delete ActiveMacros.back();
2942 ActiveMacros.pop_back();
2943}
2944
2945bool AsmParser::parseAssignment(StringRef Name, AssignmentKind Kind) {
2946 MCSymbol *Sym;
2947 const MCExpr *Value;
2948 SMLoc ExprLoc = getTok().getLoc();
2949 bool AllowRedef =
2950 Kind == AssignmentKind::Set || Kind == AssignmentKind::Equal;
2951 if (MCParserUtils::parseAssignmentExpression(Name, AllowRedef, *this, Sym,
2952 Value))
2953 return true;
2954
2955 if (!Sym) {
2956 // In the case where we parse an expression starting with a '.', we will
2957 // not generate an error, nor will we create a symbol. In this case we
2958 // should just return out.
2959 return false;
2960 }
2961
2962 if (discardLTOSymbol(Name))
2963 return false;
2964
2965 // Do the assignment.
2966 switch (Kind) {
2967 case AssignmentKind::Equal:
2968 Out.emitAssignment(Sym, Value);
2969 break;
2970 case AssignmentKind::Set:
2971 case AssignmentKind::Equiv:
2972 Out.emitAssignment(Sym, Value);
2974 break;
2975 case AssignmentKind::LTOSetConditional:
2976 if (Value->getKind() != MCExpr::SymbolRef)
2977 return Error(ExprLoc, "expected identifier");
2978
2980 break;
2981 }
2982
2983 return false;
2984}
2985
2986/// parseIdentifier:
2987/// ::= identifier
2988/// ::= string
2989bool AsmParser::parseIdentifier(StringRef &Res) {
2990 // The assembler has relaxed rules for accepting identifiers, in particular we
2991 // allow things like '.globl $foo' and '.def @feat.00', which would normally be
2992 // separate tokens. At this level, we have already lexed so we cannot (currently)
2993 // handle this as a context dependent token, instead we detect adjacent tokens
2994 // and return the combined identifier.
2995 if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
2996 SMLoc PrefixLoc = getLexer().getLoc();
2997
2998 // Consume the prefix character, and check for a following identifier.
2999
3000 AsmToken Buf[1];
3001 Lexer.peekTokens(Buf, false);
3002
3003 if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer))
3004 return true;
3005
3006 // We have a '$' or '@' followed by an identifier or integer token, make
3007 // sure they are adjacent.
3008 if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())
3009 return true;
3010
3011 // eat $ or @
3012 Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
3013 // Construct the joined identifier and consume the token.
3014 Res = StringRef(PrefixLoc.getPointer(), getTok().getString().size() + 1);
3015 Lex(); // Parser Lex to maintain invariants.
3016 return false;
3017 }
3018
3019 if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
3020 return true;
3021
3022 Res = getTok().getIdentifier();
3023
3024 Lex(); // Consume the identifier token.
3025
3026 return false;
3027}
3028
3029/// parseDirectiveSet:
3030/// ::= .equ identifier ',' expression
3031/// ::= .equiv identifier ',' expression
3032/// ::= .set identifier ',' expression
3033/// ::= .lto_set_conditional identifier ',' expression
3034bool AsmParser::parseDirectiveSet(StringRef IDVal, AssignmentKind Kind) {
3036 if (check(parseIdentifier(Name), "expected identifier") || parseComma() ||
3037 parseAssignment(Name, Kind))
3038 return true;
3039 return false;
3040}
3041
3042bool AsmParser::parseEscapedString(std::string &Data) {
3043 if (check(getTok().isNot(AsmToken::String), "expected string"))
3044 return true;
3045
3046 Data = "";
3047 StringRef Str = getTok().getStringContents();
3048 for (unsigned i = 0, e = Str.size(); i != e; ++i) {
3049 if (Str[i] != '\\') {
3050 if ((Str[i] == '\n') || (Str[i] == '\r')) {
3051 // Don't double-warn for Windows newlines.
3052 if ((Str[i] == '\n') && (i > 0) && (Str[i - 1] == '\r'))
3053 continue;
3054
3055 SMLoc NewlineLoc = SMLoc::getFromPointer(Str.data() + i);
3056 if (Warning(NewlineLoc, "unterminated string; newline inserted"))
3057 return true;
3058 }
3059 Data += Str[i];
3060 continue;
3061 }
3062
3063 // Recognize escaped characters. Note that this escape semantics currently
3064 // loosely follows Darwin 'as'.
3065 ++i;
3066 if (i == e)
3067 return TokError("unexpected backslash at end of string");
3068
3069 // Recognize hex sequences similarly to GNU 'as'.
3070 if (Str[i] == 'x' || Str[i] == 'X') {
3071 size_t length = Str.size();
3072 if (i + 1 >= length || !isHexDigit(Str[i + 1]))
3073 return TokError("invalid hexadecimal escape sequence");
3074
3075 // Consume hex characters. GNU 'as' reads all hexadecimal characters and
3076 // then truncates to the lower 16 bits. Seems reasonable.
3077 unsigned Value = 0;
3078 while (i + 1 < length && isHexDigit(Str[i + 1]))
3079 Value = Value * 16 + hexDigitValue(Str[++i]);
3080
3081 Data += (unsigned char)(Value & 0xFF);
3082 continue;
3083 }
3084
3085 // Recognize octal sequences.
3086 if ((unsigned)(Str[i] - '0') <= 7) {
3087 // Consume up to three octal characters.
3088 unsigned Value = Str[i] - '0';
3089
3090 if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
3091 ++i;
3092 Value = Value * 8 + (Str[i] - '0');
3093
3094 if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
3095 ++i;
3096 Value = Value * 8 + (Str[i] - '0');
3097 }
3098 }
3099
3100 if (Value > 255)
3101 return TokError("invalid octal escape sequence (out of range)");
3102
3103 Data += (unsigned char)Value;
3104 continue;
3105 }
3106
3107 // Otherwise recognize individual escapes.
3108 switch (Str[i]) {
3109 default:
3110 // Just reject invalid escape sequences for now.
3111 return TokError("invalid escape sequence (unrecognized character)");
3112
3113 case 'b': Data += '\b'; break;
3114 case 'f': Data += '\f'; break;
3115 case 'n': Data += '\n'; break;
3116 case 'r': Data += '\r'; break;
3117 case 't': Data += '\t'; break;
3118 case '"': Data += '"'; break;
3119 case '\\': Data += '\\'; break;
3120 }
3121 }
3122
3123 Lex();
3124 return false;
3125}
3126
3127bool AsmParser::parseAngleBracketString(std::string &Data) {
3128 SMLoc EndLoc, StartLoc = getTok().getLoc();
3129 if (isAngleBracketString(StartLoc, EndLoc)) {
3130 const char *StartChar = StartLoc.getPointer() + 1;
3131 const char *EndChar = EndLoc.getPointer() - 1;
3132 jumpToLoc(EndLoc, CurBuffer);
3133 /// Eat from '<' to '>'
3134 Lex();
3135
3136 Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
3137 return false;
3138 }
3139 return true;
3140}
3141
3142/// parseDirectiveAscii:
3143// ::= .ascii [ "string"+ ( , "string"+ )* ]
3144/// ::= ( .asciz | .string ) [ "string" ( , "string" )* ]
3145bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
3146 auto parseOp = [&]() -> bool {
3147 std::string Data;
3148 if (checkForValidSection())
3149 return true;
3150 // Only support spaces as separators for .ascii directive for now. See the
3151 // discusssion at https://reviews.llvm.org/D91460 for more details.
3152 do {
3153 if (parseEscapedString(Data))
3154 return true;
3155 getStreamer().emitBytes(Data);
3156 } while (!ZeroTerminated && getTok().is(AsmToken::String));
3157 if (ZeroTerminated)
3158 getStreamer().emitBytes(StringRef("\0", 1));
3159 return false;
3160 };
3161
3162 return parseMany(parseOp);
3163}
3164
3165/// parseDirectiveReloc
3166/// ::= .reloc expression , identifier [ , expression ]
3167bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
3168 const MCExpr *Offset;
3169 const MCExpr *Expr = nullptr;
3170 SMLoc OffsetLoc = Lexer.getTok().getLoc();
3171
3172 if (parseExpression(Offset))
3173 return true;
3174 if (parseComma() ||
3175 check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
3176 return true;
3177
3178 SMLoc NameLoc = Lexer.getTok().getLoc();
3179 StringRef Name = Lexer.getTok().getIdentifier();
3180 Lex();
3181
3182 if (Lexer.is(AsmToken::Comma)) {
3183 Lex();
3184 SMLoc ExprLoc = Lexer.getLoc();
3185 if (parseExpression(Expr))
3186 return true;
3187
3188 MCValue Value;
3189 if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr))
3190 return Error(ExprLoc, "expression must be relocatable");
3191 }
3192
3193 if (parseEOL())
3194 return true;
3195
3196 const MCTargetAsmParser &MCT = getTargetParser();
3197 const MCSubtargetInfo &STI = MCT.getSTI();
3198 if (std::optional<std::pair<bool, std::string>> Err =
3199 getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc,
3200 STI))
3201 return Error(Err->first ? NameLoc : OffsetLoc, Err->second);
3202
3203 return false;
3204}
3205
3206/// parseDirectiveValue
3207/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
3208bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
3209 auto parseOp = [&]() -> bool {
3210 const MCExpr *Value;
3211 SMLoc ExprLoc = getLexer().getLoc();
3212 if (checkForValidSection() || parseExpression(Value))
3213 return true;
3214 // Special case constant expressions to match code generator.
3215 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3216 assert(Size <= 8 && "Invalid size");
3217 uint64_t IntValue = MCE->getValue();
3218 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
3219 return Error(ExprLoc, "out of range literal value");
3220 getStreamer().emitIntValue(IntValue, Size);
3221 } else
3222 getStreamer().emitValue(Value, Size, ExprLoc);
3223 return false;
3224 };
3225
3226 return parseMany(parseOp);
3227}
3228
3229static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {
3230 if (Asm.getTok().isNot(AsmToken::Integer) &&
3231 Asm.getTok().isNot(AsmToken::BigNum))
3232 return Asm.TokError("unknown token in expression");
3233 SMLoc ExprLoc = Asm.getTok().getLoc();
3234 APInt IntValue = Asm.getTok().getAPIntVal();
3235 Asm.Lex();
3236 if (!IntValue.isIntN(128))
3237 return Asm.Error(ExprLoc, "out of range literal value");
3238 if (!IntValue.isIntN(64)) {
3239 hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
3240 lo = IntValue.getLoBits(64).getZExtValue();
3241 } else {
3242 hi = 0;
3243 lo = IntValue.getZExtValue();
3244 }
3245 return false;
3246}
3247
3248/// ParseDirectiveOctaValue
3249/// ::= .octa [ hexconstant (, hexconstant)* ]
3250
3251bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
3252 auto parseOp = [&]() -> bool {
3253 if (checkForValidSection())
3254 return true;
3255 uint64_t hi, lo;
3256 if (parseHexOcta(*this, hi, lo))
3257 return true;
3258 if (MAI.isLittleEndian()) {
3259 getStreamer().emitInt64(lo);
3260 getStreamer().emitInt64(hi);
3261 } else {
3262 getStreamer().emitInt64(hi);
3263 getStreamer().emitInt64(lo);
3264 }
3265 return false;
3266 };
3267
3268 return parseMany(parseOp);
3269}
3270
3271bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
3272 // We don't truly support arithmetic on floating point expressions, so we
3273 // have to manually parse unary prefixes.
3274 bool IsNeg = false;
3275 if (getLexer().is(AsmToken::Minus)) {
3276 Lexer.Lex();
3277 IsNeg = true;
3278 } else if (getLexer().is(AsmToken::Plus))
3279 Lexer.Lex();
3280
3281 if (Lexer.is(AsmToken::Error))
3282 return TokError(Lexer.getErr());
3283 if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
3285 return TokError("unexpected token in directive");
3286
3287 // Convert to an APFloat.
3288 APFloat Value(Semantics);
3289 StringRef IDVal = getTok().getString();
3290 if (getLexer().is(AsmToken::Identifier)) {
3291 if (!IDVal.compare_insensitive("infinity") ||
3292 !IDVal.compare_insensitive("inf"))
3293 Value = APFloat::getInf(Semantics);
3294 else if (!IDVal.compare_insensitive("nan"))
3295 Value = APFloat::getNaN(Semantics, false, ~0);
3296 else
3297 return TokError("invalid floating point literal");
3298 } else if (errorToBool(
3299 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3300 .takeError()))
3301 return TokError("invalid floating point literal");
3302 if (IsNeg)
3303 Value.changeSign();
3304
3305 // Consume the numeric token.
3306 Lex();
3307
3308 Res = Value.bitcastToAPInt();
3309
3310 return false;
3311}
3312
3313/// parseDirectiveRealValue
3314/// ::= (.single | .double) [ expression (, expression)* ]
3315bool AsmParser::parseDirectiveRealValue(StringRef IDVal,
3316 const fltSemantics &Semantics) {
3317 auto parseOp = [&]() -> bool {
3318 APInt AsInt;
3319 if (checkForValidSection() || parseRealValue(Semantics, AsInt))
3320 return true;
3321 getStreamer().emitIntValue(AsInt.getLimitedValue(),
3322 AsInt.getBitWidth() / 8);
3323 return false;
3324 };
3325
3326 return parseMany(parseOp);
3327}
3328
3329/// parseDirectiveZero
3330/// ::= .zero expression
3331bool AsmParser::parseDirectiveZero() {
3332 SMLoc NumBytesLoc = Lexer.getLoc();
3333 const MCExpr *NumBytes;
3334 if (checkForValidSection() || parseExpression(NumBytes))
3335 return true;
3336
3337 int64_t Val = 0;
3338 if (getLexer().is(AsmToken::Comma)) {
3339 Lex();
3340 if (parseAbsoluteExpression(Val))
3341 return true;
3342 }
3343
3344 if (parseEOL())
3345 return true;
3346 getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);
3347
3348 return false;
3349}
3350
3351/// parseDirectiveFill
3352/// ::= .fill expression [ , expression [ , expression ] ]
3353bool AsmParser::parseDirectiveFill() {
3354 SMLoc NumValuesLoc = Lexer.getLoc();
3355 const MCExpr *NumValues;
3356 if (checkForValidSection() || parseExpression(NumValues))
3357 return true;
3358
3359 int64_t FillSize = 1;
3360 int64_t FillExpr = 0;
3361
3362 SMLoc SizeLoc, ExprLoc;
3363
3364 if (parseOptionalToken(AsmToken::Comma)) {
3365 SizeLoc = getTok().getLoc();
3366 if (parseAbsoluteExpression(FillSize))
3367 return true;
3368 if (parseOptionalToken(AsmToken::Comma)) {
3369 ExprLoc = getTok().getLoc();
3370 if (parseAbsoluteExpression(FillExpr))
3371 return true;
3372 }
3373 }
3374 if (parseEOL())
3375 return true;
3376
3377 if (FillSize < 0) {
3378 Warning(SizeLoc, "'.fill' directive with negative size has no effect");
3379 return false;
3380 }
3381 if (FillSize > 8) {
3382 Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
3383 FillSize = 8;
3384 }
3385
3386 if (!isUInt<32>(FillExpr) && FillSize > 4)
3387 Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
3388
3389 getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);
3390
3391 return false;
3392}
3393
3394/// parseDirectiveOrg
3395/// ::= .org expression [ , expression ]
3396bool AsmParser::parseDirectiveOrg() {
3397 const MCExpr *Offset;
3398 SMLoc OffsetLoc = Lexer.getLoc();
3399 if (checkForValidSection() || parseExpression(Offset))
3400 return true;
3401
3402 // Parse optional fill expression.
3403 int64_t FillExpr = 0;
3404 if (parseOptionalToken(AsmToken::Comma))
3405 if (parseAbsoluteExpression(FillExpr))
3406 return true;
3407 if (parseEOL())
3408 return true;
3409
3410 getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
3411 return false;
3412}
3413
3414/// parseDirectiveAlign
3415/// ::= {.align, ...} expression [ , expression [ , expression ]]
3416bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
3417 SMLoc AlignmentLoc = getLexer().getLoc();
3418 int64_t Alignment;
3419 SMLoc MaxBytesLoc;
3420 bool HasFillExpr = false;
3421 int64_t FillExpr = 0;
3422 int64_t MaxBytesToFill = 0;
3423 SMLoc FillExprLoc;
3424
3425 auto parseAlign = [&]() -> bool {
3426 if (parseAbsoluteExpression(Alignment))
3427 return true;
3428 if (parseOptionalToken(AsmToken::Comma)) {
3429 // The fill expression can be omitted while specifying a maximum number of
3430 // alignment bytes, e.g:
3431 // .align 3,,4
3432 if (getTok().isNot(AsmToken::Comma)) {
3433 HasFillExpr = true;
3434 if (parseTokenLoc(FillExprLoc) || parseAbsoluteExpression(FillExpr))
3435 return true;
3436 }
3437 if (parseOptionalToken(AsmToken::Comma))
3438 if (parseTokenLoc(MaxBytesLoc) ||
3439 parseAbsoluteExpression(MaxBytesToFill))
3440 return true;
3441 }
3442 return parseEOL();
3443 };
3444
3445 if (checkForValidSection())
3446 return true;
3447 // Ignore empty '.p2align' directives for GNU-as compatibility
3448 if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
3449 Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
3450 return parseEOL();
3451 }
3452 if (parseAlign())
3453 return true;
3454
3455 // Always emit an alignment here even if we thrown an error.
3456 bool ReturnVal = false;
3457
3458 // Compute alignment in bytes.
3459 if (IsPow2) {
3460 // FIXME: Diagnose overflow.
3461 if (Alignment >= 32) {
3462 ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
3463 Alignment = 31;
3464 }
3465
3466 Alignment = 1ULL << Alignment;
3467 } else {
3468 // Reject alignments that aren't either a power of two or zero,
3469 // for gas compatibility. Alignment of zero is silently rounded
3470 // up to one.
3471 if (Alignment == 0)
3472 Alignment = 1;
3473 else if (!isPowerOf2_64(Alignment)) {
3474 ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
3475 Alignment = llvm::bit_floor<uint64_t>(Alignment);
3476 }
3477 if (!isUInt<32>(Alignment)) {
3478 ReturnVal |= Error(AlignmentLoc, "alignment must be smaller than 2**32");
3479 Alignment = 1u << 31;
3480 }
3481 }
3482
3483 // Diagnose non-sensical max bytes to align.
3484 if (MaxBytesLoc.isValid()) {
3485 if (MaxBytesToFill < 1) {
3486 ReturnVal |= Error(MaxBytesLoc,
3487 "alignment directive can never be satisfied in this "
3488 "many bytes, ignoring maximum bytes expression");
3489 MaxBytesToFill = 0;
3490 }
3491
3492 if (MaxBytesToFill >= Alignment) {
3493 Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
3494 "has no effect");
3495 MaxBytesToFill = 0;
3496 }
3497 }
3498
3499 const MCSection *Section = getStreamer().getCurrentSectionOnly();
3500 assert(Section && "must have section to emit alignment");
3501
3502 if (HasFillExpr && FillExpr != 0 && Section->isVirtualSection()) {
3503 ReturnVal |=
3504 Warning(FillExprLoc, "ignoring non-zero fill value in " +
3505 Section->getVirtualSectionKind() +
3506 " section '" + Section->getName() + "'");
3507 FillExpr = 0;
3508 }
3509
3510 // Check whether we should use optimal code alignment for this .align
3511 // directive.
3512 if (Section->useCodeAlign() && !HasFillExpr) {
3513 getStreamer().emitCodeAlignment(
3514 Align(Alignment), &getTargetParser().getSTI(), MaxBytesToFill);
3515 } else {
3516 // FIXME: Target specific behavior about how the "extra" bytes are filled.
3517 getStreamer().emitValueToAlignment(Align(Alignment), FillExpr, ValueSize,
3518 MaxBytesToFill);
3519 }
3520
3521 return ReturnVal;
3522}
3523
3524/// parseDirectiveFile
3525/// ::= .file filename
3526/// ::= .file number [directory] filename [md5 checksum] [source source-text]
3527bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
3528 // FIXME: I'm not sure what this is.
3529 int64_t FileNumber = -1;
3530 if (getLexer().is(AsmToken::Integer)) {
3531 FileNumber = getTok().getIntVal();
3532 Lex();
3533
3534 if (FileNumber < 0)
3535 return TokError("negative file number");
3536 }
3537
3538 std::string Path;
3539
3540 // Usually the directory and filename together, otherwise just the directory.
3541 // Allow the strings to have escaped octal character sequence.
3542 if (parseEscapedString(Path))
3543 return true;
3544
3545 StringRef Directory;
3547 std::string FilenameData;
3548 if (getLexer().is(AsmToken::String)) {
3549 if (check(FileNumber == -1,
3550 "explicit path specified, but no file number") ||
3551 parseEscapedString(FilenameData))
3552 return true;
3553 Filename = FilenameData;
3554 Directory = Path;
3555 } else {
3556 Filename = Path;
3557 }
3558
3559 uint64_t MD5Hi, MD5Lo;
3560 bool HasMD5 = false;
3561
3562 std::optional<StringRef> Source;
3563 bool HasSource = false;
3564 std::string SourceString;
3565
3566 while (!parseOptionalToken(AsmToken::EndOfStatement)) {
3568 if (check(getTok().isNot(AsmToken::Identifier),
3569 "unexpected token in '.file' directive") ||
3570 parseIdentifier(Keyword))
3571 return true;
3572 if (Keyword == "md5") {
3573 HasMD5 = true;
3574 if (check(FileNumber == -1,
3575 "MD5 checksum specified, but no file number") ||
3576 parseHexOcta(*this, MD5Hi, MD5Lo))
3577 return true;
3578 } else if (Keyword == "source") {
3579 HasSource = true;
3580 if (check(FileNumber == -1,
3581 "source specified, but no file number") ||
3582 check(getTok().isNot(AsmToken::String),
3583 "unexpected token in '.file' directive") ||
3584 parseEscapedString(SourceString))
3585 return true;
3586 } else {
3587 return TokError("unexpected token in '.file' directive");
3588 }
3589 }
3590
3591 if (FileNumber == -1) {
3592 // Ignore the directive if there is no number and the target doesn't support
3593 // numberless .file directives. This allows some portability of assembler
3594 // between different object file formats.
3595 if (getContext().getAsmInfo()->hasSingleParameterDotFile())
3596 getStreamer().emitFileDirective(Filename);
3597 } else {
3598 // In case there is a -g option as well as debug info from directive .file,
3599 // we turn off the -g option, directly use the existing debug info instead.
3600 // Throw away any implicit file table for the assembler source.
3601 if (Ctx.getGenDwarfForAssembly()) {
3603 Ctx.setGenDwarfForAssembly(false);
3604 }
3605
3606 std::optional<MD5::MD5Result> CKMem;
3607 if (HasMD5) {
3608 MD5::MD5Result Sum;
3609 for (unsigned i = 0; i != 8; ++i) {
3610 Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
3611 Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
3612 }
3613 CKMem = Sum;
3614 }
3615 if (HasSource) {
3616 char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
3617 memcpy(SourceBuf, SourceString.data(), SourceString.size());
3618 Source = StringRef(SourceBuf, SourceString.size());
3619 }
3620 if (FileNumber == 0) {
3621 // Upgrade to Version 5 for assembly actions like clang -c a.s.
3622 if (Ctx.getDwarfVersion() < 5)
3623 Ctx.setDwarfVersion(5);
3624 getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
3625 } else {
3626 Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
3627 FileNumber, Directory, Filename, CKMem, Source);
3628 if (!FileNumOrErr)
3629 return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
3630 }
3631 // Alert the user if there are some .file directives with MD5 and some not.
3632 // But only do that once.
3633 if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
3634 ReportedInconsistentMD5 = true;
3635 return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
3636 }
3637 }
3638
3639 return false;
3640}
3641
3642/// parseDirectiveLine
3643/// ::= .line [number]
3644bool AsmParser::parseDirectiveLine() {
3645 int64_t LineNumber;
3646 if (getLexer().is(AsmToken::Integer)) {
3647 if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
3648 return true;
3649 (void)LineNumber;
3650 // FIXME: Do something with the .line.
3651 }
3652 return parseEOL();
3653}
3654
3655/// parseDirectiveLoc
3656/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
3657/// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
3658/// The first number is a file number, must have been previously assigned with
3659/// a .file directive, the second number is the line number and optionally the
3660/// third number is a column position (zero if not specified). The remaining
3661/// optional items are .loc sub-directives.
3662bool AsmParser::parseDirectiveLoc() {
3663 int64_t FileNumber = 0, LineNumber = 0;
3664 SMLoc Loc = getTok().getLoc();
3665 if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
3666 check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
3667 "file number less than one in '.loc' directive") ||
3668 check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
3669 "unassigned file number in '.loc' directive"))
3670 return true;
3671
3672 // optional
3673 if (getLexer().is(AsmToken::Integer)) {
3674 LineNumber = getTok().getIntVal();
3675 if (LineNumber < 0)
3676 return TokError("line number less than zero in '.loc' directive");
3677 Lex();
3678 }
3679
3680 int64_t ColumnPos = 0;
3681 if (getLexer().is(AsmToken::Integer)) {
3682 ColumnPos = getTok().getIntVal();
3683 if (ColumnPos < 0)
3684 return TokError("column position less than zero in '.loc' directive");
3685 Lex();
3686 }
3687
3688 auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
3689 unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
3690 unsigned Isa = 0;
3691 int64_t Discriminator = 0;
3692
3693 auto parseLocOp = [&]() -> bool {
3695 SMLoc Loc = getTok().getLoc();
3696 if (parseIdentifier(Name))
3697 return TokError("unexpected token in '.loc' directive");
3698
3699 if (Name == "basic_block")
3701 else if (Name == "prologue_end")
3703 else if (Name == "epilogue_begin")
3705 else if (Name == "is_stmt") {
3706 Loc = getTok().getLoc();
3707 const MCExpr *Value;
3708 if (parseExpression(Value))
3709 return true;
3710 // The expression must be the constant 0 or 1.
3711 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3712 int Value = MCE->getValue();
3713 if (Value == 0)
3714 Flags &= ~DWARF2_FLAG_IS_STMT;
3715 else if (Value == 1)
3717 else
3718 return Error(Loc, "is_stmt value not 0 or 1");
3719 } else {
3720 return Error(Loc, "is_stmt value not the constant value of 0 or 1");
3721 }
3722 } else if (Name == "isa") {
3723 Loc = getTok().getLoc();
3724 const MCExpr *Value;
3725 if (parseExpression(Value))
3726 return true;
3727 // The expression must be a constant greater or equal to 0.
3728 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3729 int Value = MCE->getValue();
3730 if (Value < 0)
3731 return Error(Loc, "isa number less than zero");
3732 Isa = Value;
3733 } else {
3734 return Error(Loc, "isa number not a constant value");
3735 }
3736 } else if (Name == "discriminator") {
3737 if (parseAbsoluteExpression(Discriminator))
3738 return true;
3739 } else {
3740 return Error(Loc, "unknown sub-directive in '.loc' directive");
3741 }
3742 return false;
3743 };
3744
3745 if (parseMany(parseLocOp, false /*hasComma*/))
3746 return true;
3747
3748 getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
3749 Isa, Discriminator, StringRef());
3750
3751 return false;
3752}
3753
3754/// parseDirectiveLoc
3755/// ::= .loc_label label
3756bool AsmParser::parseDirectiveLocLabel(SMLoc DirectiveLoc) {
3758 DirectiveLoc = Lexer.getLoc();
3759 if (parseIdentifier(Name))
3760 return TokError("expected identifier");
3761 if (parseEOL())
3762 return true;
3763 getStreamer().emitDwarfLocLabelDirective(DirectiveLoc, Name);
3764 return false;
3765}
3766
3767/// parseDirectiveStabs
3768/// ::= .stabs string, number, number, number
3769bool AsmParser::parseDirectiveStabs() {
3770 return TokError("unsupported directive '.stabs'");
3771}
3772
3773/// parseDirectiveCVFile
3774/// ::= .cv_file number filename [checksum] [checksumkind]
3775bool AsmParser::parseDirectiveCVFile() {
3776 SMLoc FileNumberLoc = getTok().getLoc();
3777 int64_t FileNumber;
3778 std::string Filename;
3779 std::string Checksum;
3780 int64_t ChecksumKind = 0;
3781
3782 if (parseIntToken(FileNumber,
3783 "expected file number in '.cv_file' directive") ||
3784 check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
3785 check(getTok().isNot(AsmToken::String),
3786 "unexpected token in '.cv_file' directive") ||
3787 parseEscapedString(Filename))
3788 return true;
3789 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
3790 if (check(getTok().isNot(AsmToken::String),
3791 "unexpected token in '.cv_file' directive") ||
3792 parseEscapedString(Checksum) ||
3793 parseIntToken(ChecksumKind,
3794 "expected checksum kind in '.cv_file' directive") ||
3795 parseEOL())
3796 return true;
3797 }
3798
3799 Checksum = fromHex(Checksum);
3800 void *CKMem = Ctx.allocate(Checksum.size(), 1);
3801 memcpy(CKMem, Checksum.data(), Checksum.size());
3802 ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
3803 Checksum.size());
3804
3805 if (!getStreamer().emitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
3806 static_cast<uint8_t>(ChecksumKind)))
3807 return Error(FileNumberLoc, "file number already allocated");
3808
3809 return false;
3810}
3811
3812bool AsmParser::parseCVFunctionId(int64_t &FunctionId,
3813 StringRef DirectiveName) {
3814 SMLoc Loc;
3815 return parseTokenLoc(Loc) ||
3816 parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
3817 "' directive") ||
3818 check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
3819 "expected function id within range [0, UINT_MAX)");
3820}
3821
3822bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
3823 SMLoc Loc;
3824 return parseTokenLoc(Loc) ||
3825 parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
3826 "' directive") ||
3827 check(FileNumber < 1, Loc, "file number less than one in '" +
3828 DirectiveName + "' directive") ||
3829 check(!getCVContext().isValidFileNumber(FileNumber), Loc,
3830 "unassigned file number in '" + DirectiveName + "' directive");
3831}
3832
3833/// parseDirectiveCVFuncId
3834/// ::= .cv_func_id FunctionId
3835///
3836/// Introduces a function ID that can be used with .cv_loc.
3837bool AsmParser::parseDirectiveCVFuncId() {
3838 SMLoc FunctionIdLoc = getTok().getLoc();
3839 int64_t FunctionId;
3840
3841 if (parseCVFunctionId(FunctionId, ".cv_func_id") || parseEOL())
3842 return true;
3843
3844 if (!getStreamer().emitCVFuncIdDirective(FunctionId))
3845 return Error(FunctionIdLoc, "function id already allocated");
3846
3847 return false;
3848}
3849
3850/// parseDirectiveCVInlineSiteId
3851/// ::= .cv_inline_site_id FunctionId
3852/// "within" IAFunc
3853/// "inlined_at" IAFile IALine [IACol]
3854///
3855/// Introduces a function ID that can be used with .cv_loc. Includes "inlined
3856/// at" source location information for use in the line table of the caller,
3857/// whether the caller is a real function or another inlined call site.
3858bool AsmParser::parseDirectiveCVInlineSiteId() {
3859 SMLoc FunctionIdLoc = getTok().getLoc();
3860 int64_t FunctionId;
3861 int64_t IAFunc;
3862 int64_t IAFile;
3863 int64_t IALine;
3864 int64_t IACol = 0;
3865
3866 // FunctionId
3867 if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
3868 return true;
3869
3870 // "within"
3871 if (check((getLexer().isNot(AsmToken::Identifier) ||
3872 getTok().getIdentifier() != "within"),
3873 "expected 'within' identifier in '.cv_inline_site_id' directive"))
3874 return true;
3875 Lex();
3876
3877 // IAFunc
3878 if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
3879 return true;
3880
3881 // "inlined_at"
3882 if (check((getLexer().isNot(AsmToken::Identifier) ||
3883 getTok().getIdentifier() != "inlined_at"),
3884 "expected 'inlined_at' identifier in '.cv_inline_site_id' "
3885 "directive") )
3886 return true;
3887 Lex();
3888
3889 // IAFile IALine
3890 if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
3891 parseIntToken(IALine, "expected line number after 'inlined_at'"))
3892 return true;
3893
3894 // [IACol]
3895 if (getLexer().is(AsmToken::Integer)) {
3896 IACol = getTok().getIntVal();
3897 Lex();
3898 }
3899
3900 if (parseEOL())
3901 return true;
3902
3903 if (!getStreamer().emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
3904 IALine, IACol, FunctionIdLoc))
3905 return Error(FunctionIdLoc, "function id already allocated");
3906
3907 return false;
3908}
3909
3910/// parseDirectiveCVLoc
3911/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
3912/// [is_stmt VALUE]
3913/// The first number is a file number, must have been previously assigned with
3914/// a .file directive, the second number is the line number and optionally the
3915/// third number is a column position (zero if not specified). The remaining
3916/// optional items are .loc sub-directives.
3917bool AsmParser::parseDirectiveCVLoc() {
3918 SMLoc DirectiveLoc = getTok().getLoc();
3919 int64_t FunctionId, FileNumber;
3920 if (parseCVFunctionId(FunctionId, ".cv_loc") ||
3921 parseCVFileId(FileNumber, ".cv_loc"))
3922 return true;
3923
3924 int64_t LineNumber = 0;
3925 if (getLexer().is(AsmToken::Integer)) {
3926 LineNumber = getTok().getIntVal();
3927 if (LineNumber < 0)
3928 return TokError("line number less than zero in '.cv_loc' directive");
3929 Lex();
3930 }
3931
3932 int64_t ColumnPos = 0;
3933 if (getLexer().is(AsmToken::Integer)) {
3934 ColumnPos = getTok().getIntVal();
3935 if (ColumnPos < 0)
3936 return TokError("column position less than zero in '.cv_loc' directive");
3937 Lex();
3938 }
3939
3940 bool PrologueEnd = false;
3941 uint64_t IsStmt = 0;
3942
3943 auto parseOp = [&]() -> bool {
3945 SMLoc Loc = getTok().getLoc();
3946 if (parseIdentifier(Name))
3947 return TokError("unexpected token in '.cv_loc' directive");
3948 if (Name == "prologue_end")
3949 PrologueEnd = true;
3950 else if (Name == "is_stmt") {
3951 Loc = getTok().getLoc();
3952 const MCExpr *Value;
3953 if (parseExpression(Value))
3954 return true;
3955 // The expression must be the constant 0 or 1.
3956 IsStmt = ~0ULL;
3957 if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
3958 IsStmt = MCE->getValue();
3959
3960 if (IsStmt > 1)
3961 return Error(Loc, "is_stmt value not 0 or 1");
3962 } else {
3963 return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
3964 }
3965 return false;
3966 };
3967
3968 if (parseMany(parseOp, false /*hasComma*/))
3969 return true;
3970
3971 getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
3972 ColumnPos, PrologueEnd, IsStmt, StringRef(),
3973 DirectiveLoc);
3974 return false;
3975}
3976
3977/// parseDirectiveCVLinetable
3978/// ::= .cv_linetable FunctionId, FnStart, FnEnd
3979bool AsmParser::parseDirectiveCVLinetable() {
3980 int64_t FunctionId;
3981 StringRef FnStartName, FnEndName;
3982 SMLoc Loc = getTok().getLoc();
3983 if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() ||
3984 parseTokenLoc(Loc) ||
3985 check(parseIdentifier(FnStartName), Loc,
3986 "expected identifier in directive") ||
3987 parseComma() || parseTokenLoc(Loc) ||
3988 check(parseIdentifier(FnEndName), Loc,
3989 "expected identifier in directive"))
3990 return true;
3991
3992 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
3993 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
3994
3995 getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
3996 return false;
3997}
3998
3999/// parseDirectiveCVInlineLinetable
4000/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
4001bool AsmParser::parseDirectiveCVInlineLinetable() {
4002 int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
4003 StringRef FnStartName, FnEndName;
4004 SMLoc Loc = getTok().getLoc();
4005 if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
4006 parseTokenLoc(Loc) ||
4007 parseIntToken(
4008 SourceFileId,
4009 "expected SourceField in '.cv_inline_linetable' directive") ||
4010 check(SourceFileId <= 0, Loc,
4011 "File id less than zero in '.cv_inline_linetable' directive") ||
4012 parseTokenLoc(Loc) ||
4013 parseIntToken(
4014 SourceLineNum,
4015 "expected SourceLineNum in '.cv_inline_linetable' directive") ||
4016 check(SourceLineNum < 0, Loc,
4017 "Line number less than zero in '.cv_inline_linetable' directive") ||
4018 parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
4019 "expected identifier in directive") ||
4020 parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
4021 "expected identifier in directive"))
4022 return true;
4023
4024 if (parseEOL())
4025 return true;
4026
4027 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
4028 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
4029 getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
4030 SourceLineNum, FnStartSym,
4031 FnEndSym);
4032 return false;
4033}
4034
4035void AsmParser::initializeCVDefRangeTypeMap() {
4036 CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
4037 CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
4038 CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
4039 CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
4040}
4041
4042/// parseDirectiveCVDefRange
4043/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
4044bool AsmParser::parseDirectiveCVDefRange() {
4045 SMLoc Loc;
4046 std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
4047 while (getLexer().is(AsmToken::Identifier)) {
4048 Loc = getLexer().getLoc();
4049 StringRef GapStartName;
4050 if (parseIdentifier(GapStartName))
4051 return Error(Loc, "expected identifier in directive");
4052 MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
4053
4054 Loc = getLexer().getLoc();
4055 StringRef GapEndName;
4056 if (parseIdentifier(GapEndName))
4057 return Error(Loc, "expected identifier in directive");
4058 MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
4059
4060 Ranges.push_back({GapStartSym, GapEndSym});
4061 }
4062
4063 StringRef CVDefRangeTypeStr;
4064 if (parseToken(
4066 "expected comma before def_range type in .cv_def_range directive") ||
4067 parseIdentifier(CVDefRangeTypeStr))
4068 return Error(Loc, "expected def_range type in directive");
4069
4071 CVDefRangeTypeMap.find(CVDefRangeTypeStr);
4072 CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
4073 ? CVDR_DEFRANGE
4074 : CVTypeIt->getValue();
4075 switch (CVDRType) {
4076 case CVDR_DEFRANGE_REGISTER: {
4077 int64_t DRRegister;
4078 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4079 ".cv_def_range directive") ||
4080 parseAbsoluteExpression(DRRegister))
4081 return Error(Loc, "expected register number");
4082
4084 DRHdr.Register = DRRegister;
4085 DRHdr.MayHaveNoName = 0;
4086 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4087 break;
4088 }
4089 case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
4090 int64_t DROffset;
4091 if (parseToken(AsmToken::Comma,
4092 "expected comma before offset in .cv_def_range directive") ||
4093 parseAbsoluteExpression(DROffset))
4094 return Error(Loc, "expected offset value");
4095
4097 DRHdr.Offset = DROffset;
4098 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4099 break;
4100 }
4101 case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
4102 int64_t DRRegister;
4103 int64_t DROffsetInParent;
4104 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4105 ".cv_def_range directive") ||
4106 parseAbsoluteExpression(DRRegister))
4107 return Error(Loc, "expected register number");
4108 if (parseToken(AsmToken::Comma,
4109 "expected comma before offset in .cv_def_range directive") ||
4110 parseAbsoluteExpression(DROffsetInParent))
4111 return Error(Loc, "expected offset value");
4112
4114 DRHdr.Register = DRRegister;
4115 DRHdr.MayHaveNoName = 0;
4116 DRHdr.OffsetInParent = DROffsetInParent;
4117 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4118 break;
4119 }
4120 case CVDR_DEFRANGE_REGISTER_REL: {
4121 int64_t DRRegister;
4122 int64_t DRFlags;
4123 int64_t DRBasePointerOffset;
4124 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4125 ".cv_def_range directive") ||
4126 parseAbsoluteExpression(DRRegister))
4127 return Error(Loc, "expected register value");
4128 if (parseToken(
4130 "expected comma before flag value in .cv_def_range directive") ||
4131 parseAbsoluteExpression(DRFlags))
4132 return Error(Loc, "expected flag value");
4133 if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
4134 "in .cv_def_range directive") ||
4135 parseAbsoluteExpression(DRBasePointerOffset))
4136 return Error(Loc, "expected base pointer offset value");
4137
4139 DRHdr.Register = DRRegister;
4140 DRHdr.Flags = DRFlags;
4141 DRHdr.BasePointerOffset = DRBasePointerOffset;
4142 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4143 break;
4144 }
4145 default:
4146 return Error(Loc, "unexpected def_range type in .cv_def_range directive");
4147 }
4148 return true;
4149}
4150
4151/// parseDirectiveCVString
4152/// ::= .cv_stringtable "string"
4153bool AsmParser::parseDirectiveCVString() {
4154 std::string Data;
4155 if (checkForValidSection() || parseEscapedString(Data))
4156 return true;
4157
4158 // Put the string in the table and emit the offset.
4159 std::pair<StringRef, unsigned> Insertion =
4160 getCVContext().addToStringTable(Data);
4161 getStreamer().emitInt32(Insertion.second);
4162 return false;
4163}
4164
4165/// parseDirectiveCVStringTable
4166/// ::= .cv_stringtable
4167bool AsmParser::parseDirectiveCVStringTable() {
4168 getStreamer().emitCVStringTableDirective();
4169 return false;
4170}
4171
4172/// parseDirectiveCVFileChecksums
4173/// ::= .cv_filechecksums
4174bool AsmParser::parseDirectiveCVFileChecksums() {
4175 getStreamer().emitCVFileChecksumsDirective();
4176 return false;
4177}
4178
4179/// parseDirectiveCVFileChecksumOffset
4180/// ::= .cv_filechecksumoffset fileno
4181bool AsmParser::parseDirectiveCVFileChecksumOffset() {
4182 int64_t FileNo;
4183 if (parseIntToken(FileNo, "expected identifier in directive"))
4184 return true;
4185 if (parseEOL())
4186 return true;
4187 getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
4188 return false;
4189}
4190
4191/// parseDirectiveCVFPOData
4192/// ::= .cv_fpo_data procsym
4193bool AsmParser::parseDirectiveCVFPOData() {
4194 SMLoc DirLoc = getLexer().getLoc();
4195 StringRef ProcName;
4196 if (parseIdentifier(ProcName))
4197 return TokError("expected symbol name");
4198 if (parseEOL())
4199 return true;
4200 MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
4201 getStreamer().emitCVFPOData(ProcSym, DirLoc);
4202 return false;
4203}
4204
4205/// parseDirectiveCFISections
4206/// ::= .cfi_sections section [, section]
4207bool AsmParser::parseDirectiveCFISections() {
4209 bool EH = false;
4210 bool Debug = false;
4211
4212 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4213 for (;;) {
4214 if (parseIdentifier(Name))
4215 return TokError("expected .eh_frame or .debug_frame");
4216 if (Name == ".eh_frame")
4217 EH = true;
4218 else if (Name == ".debug_frame")
4219 Debug = true;
4220 if (parseOptionalToken(AsmToken::EndOfStatement))
4221 break;
4222 if (parseComma())
4223 return true;
4224 }
4225 }
4226 getStreamer().emitCFISections(EH, Debug);
4227 return false;
4228}
4229
4230/// parseDirectiveCFIStartProc
4231/// ::= .cfi_startproc [simple]
4232bool AsmParser::parseDirectiveCFIStartProc() {
4233 CFIStartProcLoc = StartTokLoc;
4234
4236 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4237 if (check(parseIdentifier(Simple) || Simple != "simple",
4238 "unexpected token") ||
4239 parseEOL())
4240 return true;
4241 }
4242
4243 // TODO(kristina): Deal with a corner case of incorrect diagnostic context
4244 // being produced if this directive is emitted as part of preprocessor macro
4245 // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
4246 // Tools like llvm-mc on the other hand are not affected by it, and report
4247 // correct context information.
4248 getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
4249 return false;
4250}
4251
4252/// parseDirectiveCFIEndProc
4253/// ::= .cfi_endproc
4254bool AsmParser::parseDirectiveCFIEndProc() {
4255 CFIStartProcLoc = std::nullopt;
4256
4257 if (parseEOL())
4258 return true;
4259
4260 getStreamer().emitCFIEndProc();
4261 return false;
4262}
4263
4264/// parse register name or number.
4265bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
4266 SMLoc DirectiveLoc) {
4267 MCRegister RegNo;
4268
4269 if (getLexer().isNot(AsmToken::Integer)) {
4270 if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc))
4271 return true;
4272 Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
4273 } else
4274 return parseAbsoluteExpression(Register);
4275
4276 return false;
4277}
4278
4279/// parseDirectiveCFIDefCfa
4280/// ::= .cfi_def_cfa register, offset
4281bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
4282 int64_t Register = 0, Offset = 0;
4283 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4284 parseAbsoluteExpression(Offset) || parseEOL())
4285 return true;
4286
4287 getStreamer().emitCFIDefCfa(Register, Offset, DirectiveLoc);
4288 return false;
4289}
4290
4291/// parseDirectiveCFIDefCfaOffset
4292/// ::= .cfi_def_cfa_offset offset
4293bool AsmParser::parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc) {
4294 int64_t Offset = 0;
4295 if (parseAbsoluteExpression(Offset) || parseEOL())
4296 return true;
4297
4298 getStreamer().emitCFIDefCfaOffset(Offset, DirectiveLoc);
4299 return false;
4300}
4301
4302/// parseDirectiveCFIRegister
4303/// ::= .cfi_register register, register
4304bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
4305 int64_t Register1 = 0, Register2 = 0;
4306 if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || parseComma() ||
4307 parseRegisterOrRegisterNumber(Register2, DirectiveLoc) || parseEOL())
4308 return true;
4309
4310 getStreamer().emitCFIRegister(Register1, Register2, DirectiveLoc);
4311 return false;
4312}
4313
4314/// parseDirectiveCFIWindowSave
4315/// ::= .cfi_window_save
4316bool AsmParser::parseDirectiveCFIWindowSave(SMLoc DirectiveLoc) {
4317 if (parseEOL())
4318 return true;
4319 getStreamer().emitCFIWindowSave(DirectiveLoc);
4320 return false;
4321}
4322
4323/// parseDirectiveCFIAdjustCfaOffset
4324/// ::= .cfi_adjust_cfa_offset adjustment
4325bool AsmParser::parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc) {
4326 int64_t Adjustment = 0;
4327 if (parseAbsoluteExpression(Adjustment) || parseEOL())
4328 return true;
4329
4330 getStreamer().emitCFIAdjustCfaOffset(Adjustment, DirectiveLoc);
4331 return false;
4332}
4333
4334/// parseDirectiveCFIDefCfaRegister
4335/// ::= .cfi_def_cfa_register register
4336bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
4337 int64_t Register = 0;
4338 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4339 return true;
4340
4341 getStreamer().emitCFIDefCfaRegister(Register, DirectiveLoc);
4342 return false;
4343}
4344
4345/// parseDirectiveCFILLVMDefAspaceCfa
4346/// ::= .cfi_llvm_def_aspace_cfa register, offset, address_space
4347bool AsmParser::parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc) {
4348 int64_t Register = 0, Offset = 0, AddressSpace = 0;
4349 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4350 parseAbsoluteExpression(Offset) || parseComma() ||
4351 parseAbsoluteExpression(AddressSpace) || parseEOL())
4352 return true;
4353
4354 getStreamer().emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace,
4355 DirectiveLoc);
4356 return false;
4357}
4358
4359/// parseDirectiveCFIOffset
4360/// ::= .cfi_offset register, offset
4361bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
4362 int64_t Register = 0;
4363 int64_t Offset = 0;
4364
4365 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4366 parseAbsoluteExpression(Offset) || parseEOL())
4367 return true;
4368
4369 getStreamer().emitCFIOffset(Register, Offset, DirectiveLoc);
4370 return false;
4371}
4372
4373/// parseDirectiveCFIRelOffset
4374/// ::= .cfi_rel_offset register, offset
4375bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
4376 int64_t Register = 0, Offset = 0;
4377
4378 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4379 parseAbsoluteExpression(Offset) || parseEOL())
4380 return true;
4381
4382 getStreamer().emitCFIRelOffset(Register, Offset, DirectiveLoc);
4383 return false;
4384}
4385
4386static bool isValidEncoding(int64_t Encoding) {
4387 if (Encoding & ~0xff)
4388 return false;
4389
4390 if (Encoding == dwarf::DW_EH_PE_omit)
4391 return true;
4392
4393 const unsigned Format = Encoding & 0xf;
4394 if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
4395 Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
4396 Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
4397 Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
4398 return false;
4399
4400 const unsigned Application = Encoding & 0x70;
4401 if (Application != dwarf::DW_EH_PE_absptr &&
4402 Application != dwarf::DW_EH_PE_pcrel)
4403 return false;
4404
4405 return true;
4406}
4407
4408/// parseDirectiveCFIPersonalityOrLsda
4409/// IsPersonality true for cfi_personality, false for cfi_lsda
4410/// ::= .cfi_personality encoding, [symbol_name]
4411/// ::= .cfi_lsda encoding, [symbol_name]
4412bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
4413 int64_t Encoding = 0;
4414 if (parseAbsoluteExpression(Encoding))
4415 return true;
4416 if (Encoding == dwarf::DW_EH_PE_omit)
4417 return false;
4418
4420 if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
4421 parseComma() ||
4422 check(parseIdentifier(Name), "expected identifier in directive") ||
4423 parseEOL())
4424 return true;
4425
4426 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4427
4428 if (IsPersonality)
4429 getStreamer().emitCFIPersonality(Sym, Encoding);
4430 else
4431 getStreamer().emitCFILsda(Sym, Encoding);
4432 return false;
4433}
4434
4435/// parseDirectiveCFIRememberState
4436/// ::= .cfi_remember_state
4437bool AsmParser::parseDirectiveCFIRememberState(SMLoc DirectiveLoc) {
4438 if (parseEOL())
4439 return true;
4440 getStreamer().emitCFIRememberState(DirectiveLoc);
4441 return false;
4442}
4443
4444/// parseDirectiveCFIRestoreState
4445/// ::= .cfi_remember_state
4446bool AsmParser::parseDirectiveCFIRestoreState(SMLoc DirectiveLoc) {
4447 if (parseEOL())
4448 return true;
4449 getStreamer().emitCFIRestoreState(DirectiveLoc);
4450 return false;
4451}
4452
4453/// parseDirectiveCFISameValue
4454/// ::= .cfi_same_value register
4455bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
4456 int64_t Register = 0;
4457
4458 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4459 return true;
4460
4461 getStreamer().emitCFISameValue(Register, DirectiveLoc);
4462 return false;
4463}
4464
4465/// parseDirectiveCFIRestore
4466/// ::= .cfi_restore register
4467bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
4468 int64_t Register = 0;
4469 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4470 return true;
4471
4472 getStreamer().emitCFIRestore(Register, DirectiveLoc);
4473 return false;
4474}
4475
4476/// parseDirectiveCFIEscape
4477/// ::= .cfi_escape expression[,...]
4478bool AsmParser::parseDirectiveCFIEscape(SMLoc DirectiveLoc) {
4479 std::string Values;
4480 int64_t CurrValue;
4481 if (parseAbsoluteExpression(CurrValue))
4482 return true;
4483
4484 Values.push_back((uint8_t)CurrValue);
4485
4486 while (getLexer().is(AsmToken::Comma)) {
4487 Lex();
4488
4489 if (parseAbsoluteExpression(CurrValue))
4490 return true;
4491
4492 Values.push_back((uint8_t)CurrValue);
4493 }
4494
4495 getStreamer().emitCFIEscape(Values, DirectiveLoc);
4496 return false;
4497}
4498
4499/// parseDirectiveCFIReturnColumn
4500/// ::= .cfi_return_column register
4501bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
4502 int64_t Register = 0;
4503 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4504 return true;
4505 getStreamer().emitCFIReturnColumn(Register);
4506 return false;
4507}
4508
4509/// parseDirectiveCFISignalFrame
4510/// ::= .cfi_signal_frame
4511bool AsmParser::parseDirectiveCFISignalFrame(SMLoc DirectiveLoc) {
4512 if (parseEOL())
4513 return true;
4514
4515 getStreamer().emitCFISignalFrame();
4516 return false;
4517}
4518
4519/// parseDirectiveCFIUndefined
4520/// ::= .cfi_undefined register
4521bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
4522 int64_t Register = 0;
4523
4524 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4525 return true;
4526
4527 getStreamer().emitCFIUndefined(Register, DirectiveLoc);
4528 return false;
4529}
4530
4531/// parseDirectiveCFILabel
4532/// ::= .cfi_label label
4533bool AsmParser::parseDirectiveCFILabel(SMLoc Loc) {
4535 Loc = Lexer.getLoc();
4536 if (parseIdentifier(Name))
4537 return TokError("expected identifier");
4538 if (parseEOL())
4539 return true;
4540 getStreamer().emitCFILabelDirective(Loc, Name);
4541 return false;
4542}
4543
4544/// parseDirectiveCFIValOffset
4545/// ::= .cfi_val_offset register, offset
4546bool AsmParser::parseDirectiveCFIValOffset(SMLoc DirectiveLoc) {
4547 int64_t Register = 0;
4548 int64_t Offset = 0;
4549
4550 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4551 parseAbsoluteExpression(Offset) || parseEOL())
4552 return true;
4553
4554 getStreamer().emitCFIValOffset(Register, Offset, DirectiveLoc);
4555 return false;
4556}
4557
4558/// parseDirectiveAltmacro
4559/// ::= .altmacro
4560/// ::= .noaltmacro
4561bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
4562 if (parseEOL())
4563 return true;
4564 AltMacroMode = (Directive == ".altmacro");
4565 return false;
4566}
4567
4568/// parseDirectiveMacrosOnOff
4569/// ::= .macros_on
4570/// ::= .macros_off
4571bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
4572 if (parseEOL())
4573 return true;
4574 setMacrosEnabled(Directive == ".macros_on");
4575 return false;
4576}
4577
4578/// parseDirectiveMacro
4579/// ::= .macro name[,] [parameters]
4580bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
4582 if (parseIdentifier(Name))
4583 return TokError("expected identifier in '.macro' directive");
4584
4585 if (getLexer().is(AsmToken::Comma))
4586 Lex();
4587
4589 while (getLexer().isNot(AsmToken::EndOfStatement)) {
4590
4591 if (!Parameters.empty() && Parameters.back().Vararg)
4592 return Error(Lexer.getLoc(), "vararg parameter '" +
4593 Parameters.back().Name +
4594 "' should be the last parameter");
4595
4596 MCAsmMacroParameter Parameter;
4597 if (parseIdentifier(Parameter.Name))
4598 return TokError("expected identifier in '.macro' directive");
4599
4600 // Emit an error if two (or more) named parameters share the same name
4601 for (const MCAsmMacroParameter& CurrParam : Parameters)
4602 if (CurrParam.Name == Parameter.Name)
4603 return TokError("macro '" + Name + "' has multiple parameters"
4604 " named '" + Parameter.Name + "'");
4605
4606 if (Lexer.is(AsmToken::Colon)) {
4607 Lex(); // consume ':'
4608
4609 SMLoc QualLoc;
4611
4612 QualLoc = Lexer.getLoc();
4613 if (parseIdentifier(Qualifier))
4614 return Error(QualLoc, "missing parameter qualifier for "
4615 "'" + Parameter.Name + "' in macro '" + Name + "'");
4616
4617 if (Qualifier == "req")
4618 Parameter.Required = true;
4619 else if (Qualifier == "vararg")
4620 Parameter.Vararg = true;
4621 else
4622 return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
4623 "for '" + Parameter.Name + "' in macro '" + Name + "'");
4624 }
4625
4626 if (getLexer().is(AsmToken::Equal)) {
4627 Lex();
4628
4629 SMLoc ParamLoc;
4630
4631 ParamLoc = Lexer.getLoc();
4632 if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
4633 return true;
4634
4635 if (Parameter.Required)
4636 Warning(ParamLoc, "pointless default value for required parameter "
4637 "'" + Parameter.Name + "' in macro '" + Name + "'");
4638 }
4639
4640 Parameters.push_back(std::move(Parameter));
4641
4642 if (getLexer().is(AsmToken::Comma))
4643 Lex();
4644 }
4645
4646 // Eat just the end of statement.
4647 Lexer.Lex();
4648
4649 // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors
4650 AsmToken EndToken, StartToken = getTok();
4651 unsigned MacroDepth = 0;
4652 // Lex the macro definition.
4653 while (true) {
4654 // Ignore Lexing errors in macros.
4655 while (Lexer.is(AsmToken::Error)) {
4656 Lexer.Lex();
4657 }
4658
4659 // Check whether we have reached the end of the file.
4660 if (getLexer().is(AsmToken::Eof))
4661 return Error(DirectiveLoc, "no matching '.endmacro' in definition");
4662
4663 // Otherwise, check whether we have reach the .endmacro or the start of a
4664 // preprocessor line marker.
4665 if (getLexer().is(AsmToken::Identifier)) {
4666 if (getTok().getIdentifier() == ".endm" ||
4667 getTok().getIdentifier() == ".endmacro") {
4668 if (MacroDepth == 0) { // Outermost macro.
4669 EndToken = getTok();
4670 Lexer.Lex();
4671 if (getLexer().isNot(AsmToken::EndOfStatement))
4672 return TokError("unexpected token in '" + EndToken.getIdentifier() +
4673 "' directive");
4674 break;
4675 } else {
4676 // Otherwise we just found the end of an inner macro.
4677 --MacroDepth;
4678 }
4679 } else if (getTok().getIdentifier() == ".macro") {
4680 // We allow nested macros. Those aren't instantiated until the outermost
4681 // macro is expanded so just ignore them for now.
4682 ++MacroDepth;
4683 }
4684 } else if (Lexer.is(AsmToken::HashDirective)) {
4685 (void)parseCppHashLineFilenameComment(getLexer().getLoc());
4686 }
4687
4688 // Otherwise, scan til the end of the statement.
4689 eatToEndOfStatement();
4690 }
4691
4692 if (getContext().lookupMacro(Name)) {
4693 return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
4694 }
4695
4696 const char *BodyStart = StartToken.getLoc().getPointer();
4697 const char *BodyEnd = EndToken.getLoc().getPointer();
4698 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4699 checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
4700 MCAsmMacro Macro(Name, Body, std::move(Parameters));
4701 DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
4702 Macro.dump());
4703 getContext().defineMacro(Name, std::move(Macro));
4704 return false;
4705}
4706
4707/// checkForBadMacro
4708///
4709/// With the support added for named parameters there may be code out there that
4710/// is transitioning from positional parameters. In versions of gas that did
4711/// not support named parameters they would be ignored on the macro definition.
4712/// But to support both styles of parameters this is not possible so if a macro
4713/// definition has named parameters but does not use them and has what appears
4714/// to be positional parameters, strings like $1, $2, ... and $n, then issue a
4715/// warning that the positional parameter found in body which have no effect.
4716/// Hoping the developer will either remove the named parameters from the macro
4717/// definition so the positional parameters get used if that was what was
4718/// intended or change the macro to use the named parameters. It is possible
4719/// this warning will trigger when the none of the named parameters are used
4720/// and the strings like $1 are infact to simply to be passed trough unchanged.
4721void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
4722 StringRef Body,
4723 ArrayRef<MCAsmMacroParameter> Parameters) {
4724 // If this macro is not defined with named parameters the warning we are
4725 // checking for here doesn't apply.
4726 unsigned NParameters = Parameters.size();
4727 if (NParameters == 0)
4728 return;
4729
4730 bool NamedParametersFound = false;
4731 bool PositionalParametersFound = false;
4732
4733 // Look at the body of the macro for use of both the named parameters and what
4734 // are likely to be positional parameters. This is what expandMacro() is
4735 // doing when it finds the parameters in the body.
4736 while (!Body.empty()) {
4737 // Scan for the next possible parameter.
4738 std::size_t End = Body.size(), Pos = 0;
4739 for (; Pos != End; ++Pos) {
4740 // Check for a substitution or escape.
4741 // This macro is defined with parameters, look for \foo, \bar, etc.
4742 if (Body[Pos] == '\\' && Pos + 1 != End)
4743 break;
4744
4745 // This macro should have parameters, but look for $0, $1, ..., $n too.
4746 if (Body[Pos] != '$' || Pos + 1 == End)
4747 continue;
4748 char Next = Body[Pos + 1];
4749 if (Next == '$' || Next == 'n' ||
4750 isdigit(static_cast<unsigned char>(Next)))
4751 break;
4752 }
4753
4754 // Check if we reached the end.
4755 if (Pos == End)
4756 break;
4757
4758 if (Body[Pos] == '$') {
4759 switch (Body[Pos + 1]) {
4760 // $$ => $
4761 case '$':
4762 break;
4763
4764 // $n => number of arguments
4765 case 'n':
4766 PositionalParametersFound = true;
4767 break;
4768
4769 // $[0-9] => argument
4770 default: {
4771 PositionalParametersFound = true;
4772 break;
4773 }
4774 }
4775 Pos += 2;
4776 } else {
4777 unsigned I = Pos + 1;
4778 while (isIdentifierChar(Body[I]) && I + 1 != End)
4779 ++I;
4780
4781 const char *Begin = Body.data() + Pos + 1;
4782 StringRef Argument(Begin, I - (Pos + 1));
4783 unsigned Index = 0;
4784 for (; Index < NParameters; ++Index)
4785 if (Parameters[Index].Name == Argument)
4786 break;
4787
4788 if (Index == NParameters) {
4789 if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
4790 Pos += 3;
4791 else {
4792 Pos = I;
4793 }
4794 } else {
4795 NamedParametersFound = true;
4796 Pos += 1 + Argument.size();
4797 }
4798 }
4799 // Update the scan point.
4800 Body = Body.substr(Pos);
4801 }
4802
4803 if (!NamedParametersFound && PositionalParametersFound)
4804 Warning(DirectiveLoc, "macro defined with named parameters which are not "
4805 "used in macro body, possible positional parameter "
4806 "found in body which will have no effect");
4807}
4808
4809/// parseDirectiveExitMacro
4810/// ::= .exitm
4811bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
4812 if (parseEOL())
4813 return true;
4814
4815 if (!isInsideMacroInstantiation())
4816 return TokError("unexpected '" + Directive + "' in file, "
4817 "no current macro definition");
4818
4819 // Exit all conditionals that are active in the current macro.
4820 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4821 TheCondState = TheCondStack.back();
4822 TheCondStack.pop_back();
4823 }
4824
4825 handleMacroExit();
4826 return false;
4827}
4828
4829/// parseDirectiveEndMacro
4830/// ::= .endm
4831/// ::= .endmacro
4832bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
4833 if (getLexer().isNot(AsmToken::EndOfStatement))
4834 return TokError("unexpected token in '" + Directive + "' directive");
4835
4836 // If we are inside a macro instantiation, terminate the current
4837 // instantiation.
4838 if (isInsideMacroInstantiation()) {
4839 handleMacroExit();
4840 return false;
4841 }
4842
4843 // Otherwise, this .endmacro is a stray entry in the file; well formed
4844 // .endmacro directives are handled during the macro definition parsing.
4845 return TokError("unexpected '" + Directive + "' in file, "
4846 "no current macro definition");
4847}
4848
4849/// parseDirectivePurgeMacro
4850/// ::= .purgem name
4851bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4853 SMLoc Loc;
4854 if (parseTokenLoc(Loc) ||
4855 check(parseIdentifier(Name), Loc,
4856 "expected identifier in '.purgem' directive") ||
4857 parseEOL())
4858 return true;
4859
4860 if (!getContext().lookupMacro(Name))
4861 return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
4862
4863 getContext().undefineMacro(Name);
4864 DEBUG_WITH_TYPE("asm-macros", dbgs()
4865 << "Un-defining macro: " << Name << "\n");
4866 return false;
4867}
4868
4869/// parseDirectiveBundleAlignMode
4870/// ::= {.bundle_align_mode} expression
4871bool AsmParser::parseDirectiveBundleAlignMode() {
4872 // Expect a single argument: an expression that evaluates to a constant
4873 // in the inclusive range 0-30.
4874 SMLoc ExprLoc = getLexer().getLoc();
4875 int64_t AlignSizePow2;
4876 if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||
4877 parseEOL() ||
4878 check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc,
4879 "invalid bundle alignment size (expected between 0 and 30)"))
4880 return true;
4881
4882 getStreamer().emitBundleAlignMode(Align(1ULL << AlignSizePow2));
4883 return false;
4884}
4885
4886/// parseDirectiveBundleLock
4887/// ::= {.bundle_lock} [align_to_end]
4888bool AsmParser::parseDirectiveBundleLock() {
4889 if (checkForValidSection())
4890 return true;
4891 bool AlignToEnd = false;
4892
4894 SMLoc Loc = getTok().getLoc();
4895 const char *kInvalidOptionError =
4896 "invalid option for '.bundle_lock' directive";
4897
4898 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4899 if (check(parseIdentifier(Option), Loc, kInvalidOptionError) ||
4900 check(Option != "align_to_end", Loc, kInvalidOptionError) || parseEOL())
4901 return true;
4902 AlignToEnd = true;
4903 }
4904
4905 getStreamer().emitBundleLock(AlignToEnd);
4906 return false;
4907}
4908
4909/// parseDirectiveBundleLock
4910/// ::= {.bundle_lock}
4911bool AsmParser::parseDirectiveBundleUnlock() {
4912 if (checkForValidSection() || parseEOL())
4913 return true;
4914
4915 getStreamer().emitBundleUnlock();
4916 return false;
4917}
4918
4919/// parseDirectiveSpace
4920/// ::= (.skip | .space) expression [ , expression ]
4921bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
4922 SMLoc NumBytesLoc = Lexer.getLoc();
4923 const MCExpr *NumBytes;
4924 if (checkForValidSection() || parseExpression(NumBytes))
4925 return true;
4926
4927 int64_t FillExpr = 0;
4928 if (parseOptionalToken(AsmToken::Comma))
4929 if (parseAbsoluteExpression(FillExpr))
4930 return true;
4931 if (parseEOL())
4932 return true;
4933
4934 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
4935 getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
4936
4937 return false;
4938}
4939
4940/// parseDirectiveDCB
4941/// ::= .dcb.{b, l, w} expression, expression
4942bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
4943 SMLoc NumValuesLoc = Lexer.getLoc();
4944 int64_t NumValues;
4945 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4946 return true;
4947
4948 if (NumValues < 0) {
4949 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4950 return false;
4951 }
4952
4953 if (parseComma())
4954 return true;
4955
4956 const MCExpr *Value;
4957 SMLoc ExprLoc = getLexer().getLoc();
4958 if (parseExpression(Value))
4959 return true;
4960
4961 // Special case constant expressions to match code generator.
4962 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
4963 assert(Size <= 8 && "Invalid size");
4964 uint64_t IntValue = MCE->getValue();
4965 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
4966 return Error(ExprLoc, "literal value out of range for directive");
4967 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4968 getStreamer().emitIntValue(IntValue, Size);
4969 } else {
4970 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4971 getStreamer().emitValue(Value, Size, ExprLoc);
4972 }
4973
4974 return parseEOL();
4975}
4976
4977/// parseDirectiveRealDCB
4978/// ::= .dcb.{d, s} expression, expression
4979bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {
4980 SMLoc NumValuesLoc = Lexer.getLoc();
4981 int64_t NumValues;
4982 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4983 return true;
4984
4985 if (NumValues < 0) {
4986 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4987 return false;
4988 }
4989
4990 if (parseComma())
4991 return true;
4992
4993 APInt AsInt;
4994 if (parseRealValue(Semantics, AsInt) || parseEOL())
4995 return true;
4996
4997 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4998 getStreamer().emitIntValue(AsInt.getLimitedValue(),
4999 AsInt.getBitWidth() / 8);
5000
5001 return false;
5002}
5003
5004/// parseDirectiveDS
5005/// ::= .ds.{b, d, l, p, s, w, x} expression
5006bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {
5007 SMLoc NumValuesLoc = Lexer.getLoc();
5008 int64_t NumValues;
5009 if (checkForValidSection() || parseAbsoluteExpression(NumValues) ||
5010 parseEOL())
5011 return true;
5012
5013 if (NumValues < 0) {
5014 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
5015 return false;
5016 }
5017
5018 for (uint64_t i = 0, e = NumValues; i != e; ++i)
5019 getStreamer().emitFill(Size, 0);
5020
5021 return false;
5022}
5023
5024/// parseDirectiveLEB128
5025/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
5026bool AsmParser::parseDirectiveLEB128(bool Signed) {
5027 if (checkForValidSection())
5028 return true;
5029
5030 auto parseOp = [&]() -> bool {
5031 const MCExpr *Value;
5032 if (parseExpression(Value))
5033 return true;
5034 if (Signed)
5035 getStreamer().emitSLEB128Value(Value);
5036 else
5037 getStreamer().emitULEB128Value(Value);
5038 return false;
5039 };
5040
5041 return parseMany(parseOp);
5042}
5043
5044/// parseDirectiveSymbolAttribute
5045/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
5046bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
5047 auto parseOp = [&]() -> bool {
5049 SMLoc Loc = getTok().getLoc();
5050 if (parseIdentifier(Name))
5051 return Error(Loc, "expected identifier");
5052
5053 if (discardLTOSymbol(Name))
5054 return false;
5055
5056 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5057
5058 // Assembler local symbols don't make any sense here, except for directives
5059 // that the symbol should be tagged.
5060 if (Sym->isTemporary() && Attr != MCSA_Memtag)
5061 return Error(Loc, "non-local symbol required");
5062
5063 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
5064 return Error(Loc, "unable to emit symbol attribute");
5065 return false;
5066 };
5067
5068 return parseMany(parseOp);
5069}
5070
5071/// parseDirectiveComm
5072/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
5073bool AsmParser::parseDirectiveComm(bool IsLocal) {
5074 if (checkForValidSection())
5075 return true;
5076
5077 SMLoc IDLoc = getLexer().getLoc();
5079 if (parseIdentifier(Name))
5080 return TokError("expected identifier in directive");
5081
5082 // Handle the identifier as the key symbol.
5083 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5084
5085 if (parseComma())
5086 return true;
5087
5088 int64_t Size;
5089 SMLoc SizeLoc = getLexer().getLoc();
5090 if (parseAbsoluteExpression(Size))
5091 return true;
5092
5093 int64_t Pow2Alignment = 0;
5094 SMLoc Pow2AlignmentLoc;
5095 if (getLexer().is(AsmToken::Comma)) {
5096 Lex();
5097 Pow2AlignmentLoc = getLexer().getLoc();
5098 if (parseAbsoluteExpression(Pow2Alignment))
5099 return true;
5100
5101 LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
5102 if (IsLocal && LCOMM == LCOMM::NoAlignment)
5103 return Error(Pow2AlignmentLoc, "alignment not supported on this target");
5104
5105 // If this target takes alignments in bytes (not log) validate and convert.
5106 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
5107 (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
5108 if (!isPowerOf2_64(Pow2Alignment))
5109 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
5110 Pow2Alignment = Log2_64(Pow2Alignment);
5111 }
5112 }
5113
5114 if (parseEOL())
5115 return true;
5116
5117 // NOTE: a size of zero for a .comm should create a undefined symbol
5118 // but a size of .lcomm creates a bss symbol of size zero.
5119 if (Size < 0)
5120 return Error(SizeLoc, "size must be non-negative");
5121
5122 Sym->redefineIfPossible();
5123 if (!Sym->isUndefined())
5124 return Error(IDLoc, "invalid symbol redefinition");
5125
5126 // Create the Symbol as a common or local common with Size and Pow2Alignment
5127 if (IsLocal) {
5128 getStreamer().emitLocalCommonSymbol(Sym, Size,
5129 Align(1ULL << Pow2Alignment));
5130 return false;
5131 }
5132
5133 getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));
5134 return false;
5135}
5136
5137/// parseDirectiveAbort
5138/// ::= .abort [... message ...]
5139bool AsmParser::parseDirectiveAbort(SMLoc DirectiveLoc) {
5140 StringRef Str = parseStringToEndOfStatement();
5141 if (parseEOL())
5142 return true;
5143
5144 if (Str.empty())
5145 return Error(DirectiveLoc, ".abort detected. Assembly stopping");
5146
5147 // FIXME: Actually abort assembly here.
5148 return Error(DirectiveLoc,
5149 ".abort '" + Str + "' detected. Assembly stopping");
5150}
5151
5152/// parseDirectiveInclude
5153/// ::= .include "filename"
5154bool AsmParser::parseDirectiveInclude() {
5155 // Allow the strings to have escaped octal character sequence.
5156 std::string Filename;
5157 SMLoc IncludeLoc = getTok().getLoc();
5158
5159 if (check(getTok().isNot(AsmToken::String),
5160 "expected string in '.include' directive") ||
5161 parseEscapedString(Filename) ||
5162 check(getTok().isNot(AsmToken::EndOfStatement),
5163 "unexpected token in '.include' directive") ||
5164 // Attempt to switch the lexer to the included file before consuming the
5165 // end of statement to avoid losing it when we switch.
5166 check(enterIncludeFile(Filename), IncludeLoc,
5167 "Could not find include file '" + Filename + "'"))
5168 return true;
5169
5170 return false;
5171}
5172
5173/// parseDirectiveIncbin
5174/// ::= .incbin "filename" [ , skip [ , count ] ]
5175bool AsmParser::parseDirectiveIncbin() {
5176 // Allow the strings to have escaped octal character sequence.
5177 std::string Filename;
5178 SMLoc IncbinLoc = getTok().getLoc();
5179 if (check(getTok().isNot(AsmToken::String),
5180 "expected string in '.incbin' directive") ||
5181 parseEscapedString(Filename))
5182 return true;
5183
5184 int64_t Skip = 0;
5185 const MCExpr *Count = nullptr;
5186 SMLoc SkipLoc, CountLoc;
5187 if (parseOptionalToken(AsmToken::Comma)) {
5188 // The skip expression can be omitted while specifying the count, e.g:
5189 // .incbin "filename",,4
5190 if (getTok().isNot(AsmToken::Comma)) {
5191 if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))
5192 return true;
5193 }
5194 if (parseOptionalToken(AsmToken::Comma)) {
5195 CountLoc = getTok().getLoc();
5196 if (parseExpression(Count))
5197 return true;
5198 }
5199 }
5200
5201 if (parseEOL())
5202 return true;
5203
5204 if (check(Skip < 0, SkipLoc, "skip is negative"))
5205 return true;
5206
5207 // Attempt to process the included file.
5208 if (processIncbinFile(Filename, Skip, Count, CountLoc))
5209 return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
5210 return false;
5211}
5212
5213/// parseDirectiveIf
5214/// ::= .if{,eq,ge,gt,le,lt,ne} expression
5215bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
5216 TheCondStack.push_back(TheCondState);
5217 TheCondState.TheCond = AsmCond::IfCond;
5218 if (TheCondState.Ignore) {
5219 eatToEndOfStatement();
5220 } else {
5221 int64_t ExprValue;
5222 if (parseAbsoluteExpression(ExprValue) || parseEOL())
5223 return true;
5224
5225 switch (DirKind) {
5226 default:
5227 llvm_unreachable("unsupported directive");
5228 case DK_IF:
5229 case DK_IFNE:
5230 break;
5231 case DK_IFEQ:
5232 ExprValue = ExprValue == 0;
5233 break;
5234 case DK_IFGE:
5235 ExprValue = ExprValue >= 0;
5236 break;
5237 case DK_IFGT:
5238 ExprValue = ExprValue > 0;
5239 break;
5240 case DK_IFLE:
5241 ExprValue = ExprValue <= 0;
5242 break;
5243 case DK_IFLT:
5244 ExprValue = ExprValue < 0;
5245 break;
5246 }
5247
5248 TheCondState.CondMet = ExprValue;
5249 TheCondState.Ignore = !TheCondState.CondMet;
5250 }
5251
5252 return false;
5253}
5254
5255/// parseDirectiveIfb
5256/// ::= .ifb string
5257bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
5258 TheCondStack.push_back(TheCondState);
5259 TheCondState.TheCond = AsmCond::IfCond;
5260
5261 if (TheCondState.Ignore) {
5262 eatToEndOfStatement();
5263 } else {
5264 StringRef Str = parseStringToEndOfStatement();
5265
5266 if (parseEOL())
5267 return true;
5268
5269 TheCondState.CondMet = ExpectBlank == Str.empty();
5270 TheCondState.Ignore = !TheCondState.CondMet;
5271 }
5272
5273 return false;
5274}
5275
5276/// parseDirectiveIfc
5277/// ::= .ifc string1, string2
5278/// ::= .ifnc string1, string2
5279bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
5280 TheCondStack.push_back(TheCondState);
5281 TheCondState.TheCond = AsmCond::IfCond;
5282
5283 if (TheCondState.Ignore) {
5284 eatToEndOfStatement();
5285 } else {
5286 StringRef Str1 = parseStringToComma();
5287
5288 if (parseComma())
5289 return true;
5290
5291 StringRef Str2 = parseStringToEndOfStatement();
5292
5293 if (parseEOL())
5294 return true;
5295
5296 TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
5297 TheCondState.Ignore = !TheCondState.CondMet;
5298 }
5299
5300 return false;
5301}
5302
5303/// parseDirectiveIfeqs
5304/// ::= .ifeqs string1, string2
5305bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
5306 if (Lexer.isNot(AsmToken::String)) {
5307 if (ExpectEqual)
5308 return TokError("expected string parameter for '.ifeqs' directive");
5309 return TokError("expected string parameter for '.ifnes' directive");
5310 }
5311
5312 StringRef String1 = getTok().getStringContents();
5313 Lex();
5314
5315 if (Lexer.isNot(AsmToken::Comma)) {
5316 if (ExpectEqual)
5317 return TokError(
5318 "expected comma after first string for '.ifeqs' directive");
5319 return TokError("expected comma after first string for '.ifnes' directive");
5320 }
5321
5322 Lex();
5323
5324 if (Lexer.isNot(AsmToken::String)) {
5325 if (ExpectEqual)
5326 return TokError("expected string parameter for '.ifeqs' directive");
5327 return TokError("expected string parameter for '.ifnes' directive");
5328 }
5329
5330 StringRef String2 = getTok().getStringContents();
5331 Lex();
5332
5333 TheCondStack.push_back(TheCondState);
5334 TheCondState.TheCond = AsmCond::IfCond;
5335 TheCondState.CondMet = ExpectEqual == (String1 == String2);
5336 TheCondState.Ignore = !TheCondState.CondMet;
5337
5338 return false;
5339}
5340
5341/// parseDirectiveIfdef
5342/// ::= .ifdef symbol
5343bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
5345 TheCondStack.push_back(TheCondState);
5346 TheCondState.TheCond = AsmCond::IfCond;
5347
5348 if (TheCondState.Ignore) {
5349 eatToEndOfStatement();
5350 } else {
5351 if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
5352 parseEOL())
5353 return true;
5354
5355 MCSymbol *Sym = getContext().lookupSymbol(Name);
5356
5357 if (expect_defined)
5358 TheCondState.CondMet = (Sym && !Sym->isUndefined(false));
5359 else
5360 TheCondState.CondMet = (!Sym || Sym->isUndefined(false));
5361 TheCondState.Ignore = !TheCondState.CondMet;
5362 }
5363
5364 return false;
5365}
5366
5367/// parseDirectiveElseIf
5368/// ::= .elseif expression
5369bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
5370 if (TheCondState.TheCond != AsmCond::IfCond &&
5371 TheCondState.TheCond != AsmCond::ElseIfCond)
5372 return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
5373 " .if or an .elseif");
5374 TheCondState.TheCond = AsmCond::ElseIfCond;
5375
5376 bool LastIgnoreState = false;
5377 if (!TheCondStack.empty())
5378 LastIgnoreState = TheCondStack.back().Ignore;
5379 if (LastIgnoreState || TheCondState.CondMet) {
5380 TheCondState.Ignore = true;
5381 eatToEndOfStatement();
5382 } else {
5383 int64_t ExprValue;
5384 if (parseAbsoluteExpression(ExprValue))
5385 return true;
5386
5387 if (parseEOL())
5388 return true;
5389
5390 TheCondState.CondMet = ExprValue;
5391 TheCondState.Ignore = !TheCondState.CondMet;
5392 }
5393
5394 return false;
5395}
5396
5397/// parseDirectiveElse
5398/// ::= .else
5399bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
5400 if (parseEOL())
5401 return true;
5402
5403 if (TheCondState.TheCond != AsmCond::IfCond &&
5404 TheCondState.TheCond != AsmCond::ElseIfCond)
5405 return Error(DirectiveLoc, "Encountered a .else that doesn't follow "
5406 " an .if or an .elseif");
5407 TheCondState.TheCond = AsmCond::ElseCond;
5408 bool LastIgnoreState = false;
5409 if (!TheCondStack.empty())
5410 LastIgnoreState = TheCondStack.back().Ignore;
5411 if (LastIgnoreState || TheCondState.CondMet)
5412 TheCondState.Ignore = true;
5413 else
5414 TheCondState.Ignore = false;
5415
5416 return false;
5417}
5418
5419/// parseDirectiveEnd
5420/// ::= .end
5421bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5422 if (parseEOL())
5423 return true;
5424
5425 while (Lexer.isNot(AsmToken::Eof))
5426 Lexer.Lex();
5427
5428 return false;
5429}
5430
5431/// parseDirectiveError
5432/// ::= .err
5433/// ::= .error [string]
5434bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
5435 if (!TheCondStack.empty()) {
5436 if (TheCondStack.back().Ignore) {
5437 eatToEndOfStatement();
5438 return false;
5439 }
5440 }
5441
5442 if (!WithMessage)
5443 return Error(L, ".err encountered");
5444
5445 StringRef Message = ".error directive invoked in source file";
5446 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5447 if (Lexer.isNot(AsmToken::String))
5448 return TokError(".error argument must be a string");
5449
5450 Message = getTok().getStringContents();
5451 Lex();
5452 }
5453
5454 return Error(L, Message);
5455}
5456
5457/// parseDirectiveWarning
5458/// ::= .warning [string]
5459bool AsmParser::parseDirectiveWarning(SMLoc L) {
5460 if (!TheCondStack.empty()) {
5461 if (TheCondStack.back().Ignore) {
5462 eatToEndOfStatement();
5463 return false;
5464 }
5465 }
5466
5467 StringRef Message = ".warning directive invoked in source file";
5468
5469 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
5470 if (Lexer.isNot(AsmToken::String))
5471 return TokError(".warning argument must be a string");
5472
5473 Message = getTok().getStringContents();
5474 Lex();
5475 if (parseEOL())
5476 return true;
5477 }
5478
5479 return Warning(L, Message);
5480}
5481
5482/// parseDirectiveEndIf
5483/// ::= .endif
5484bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5485 if (parseEOL())
5486 return true;
5487
5488 if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
5489 return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
5490 "an .if or .else");
5491 if (!TheCondStack.empty()) {
5492 TheCondState = TheCondStack.back();
5493 TheCondStack.pop_back();
5494 }
5495
5496 return false;
5497}
5498
5499void AsmParser::initializeDirectiveKindMap() {
5500 /* Lookup will be done with the directive
5501 * converted to lower case, so all these
5502 * keys should be lower case.
5503 * (target specific directives are handled
5504 * elsewhere)
5505 */
5506 DirectiveKindMap[".set"] = DK_SET;
5507 DirectiveKindMap[".equ"] = DK_EQU;
5508 DirectiveKindMap[".equiv"] = DK_EQUIV;
5509 DirectiveKindMap[".ascii"] = DK_ASCII;
5510 DirectiveKindMap[".asciz"] = DK_ASCIZ;
5511 DirectiveKindMap[".string"] = DK_STRING;
5512 DirectiveKindMap[".byte"] = DK_BYTE;
5513 DirectiveKindMap[".short"] = DK_SHORT;
5514 DirectiveKindMap[".value"] = DK_VALUE;
5515 DirectiveKindMap[".2byte"] = DK_2BYTE;
5516 DirectiveKindMap[".long"] = DK_LONG;
5517 DirectiveKindMap[".int"] = DK_INT;
5518 DirectiveKindMap[".4byte"] = DK_4BYTE;
5519 DirectiveKindMap[".quad"] = DK_QUAD;
5520 DirectiveKindMap[".8byte"] = DK_8BYTE;
5521 DirectiveKindMap[".octa"] = DK_OCTA;
5522 DirectiveKindMap[".single"] = DK_SINGLE;
5523 DirectiveKindMap[".float"] = DK_FLOAT;
5524 DirectiveKindMap[".double"] = DK_DOUBLE;
5525 DirectiveKindMap[".align"] = DK_ALIGN;
5526 DirectiveKindMap[".align32"] = DK_ALIGN32;
5527 DirectiveKindMap[".balign"] = DK_BALIGN;
5528 DirectiveKindMap[".balignw"] = DK_BALIGNW;
5529 DirectiveKindMap[".balignl"] = DK_BALIGNL;
5530 DirectiveKindMap[".p2align"] = DK_P2ALIGN;
5531 DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
5532 DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
5533 DirectiveKindMap[".org"] = DK_ORG;
5534 DirectiveKindMap[".fill"] = DK_FILL;
5535 DirectiveKindMap[".zero"] = DK_ZERO;
5536 DirectiveKindMap[".extern"] = DK_EXTERN;
5537 DirectiveKindMap[".globl"] = DK_GLOBL;
5538 DirectiveKindMap[".global"] = DK_GLOBAL;
5539 DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
5540 DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
5541 DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
5542 DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
5543 DirectiveKindMap[".reference"] = DK_REFERENCE;
5544 DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
5545 DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
5546 DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
5547 DirectiveKindMap[".cold"] = DK_COLD;
5548 DirectiveKindMap[".comm"] = DK_COMM;
5549 DirectiveKindMap[".common"] = DK_COMMON;
5550 DirectiveKindMap[".lcomm"] = DK_LCOMM;
5551 DirectiveKindMap[".abort"] = DK_ABORT;
5552 DirectiveKindMap[".include"] = DK_INCLUDE;
5553 DirectiveKindMap[".incbin"] = DK_INCBIN;
5554 DirectiveKindMap[".code16"] = DK_CODE16;
5555 DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
5556 DirectiveKindMap[".rept"] = DK_REPT;
5557 DirectiveKindMap[".rep"] = DK_REPT;
5558 DirectiveKindMap[".irp"] = DK_IRP;
5559 DirectiveKindMap[".irpc"] = DK_IRPC;
5560 DirectiveKindMap[".endr"] = DK_ENDR;
5561 DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE;
5562 DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK;
5563 DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK;
5564 DirectiveKindMap[".if"] = DK_IF;
5565 DirectiveKindMap[".ifeq"] = DK_IFEQ;
5566 DirectiveKindMap[".ifge"] = DK_IFGE;
5567 DirectiveKindMap[".ifgt"] = DK_IFGT;
5568 DirectiveKindMap[".ifle"] = DK_IFLE;
5569 DirectiveKindMap[".iflt"] = DK_IFLT;
5570 DirectiveKindMap[".ifne"] = DK_IFNE;
5571 DirectiveKindMap[".ifb"] = DK_IFB;
5572 DirectiveKindMap[".ifnb"] = DK_IFNB;
5573 DirectiveKindMap[".ifc"] = DK_IFC;
5574 DirectiveKindMap[".ifeqs"] = DK_IFEQS;
5575 DirectiveKindMap[".ifnc"] = DK_IFNC;
5576 DirectiveKindMap[".ifnes"] = DK_IFNES;
5577 DirectiveKindMap[".ifdef"] = DK_IFDEF;
5578 DirectiveKindMap[".ifndef"] = DK_IFNDEF;
5579 DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
5580 DirectiveKindMap[".elseif"] = DK_ELSEIF;
5581 DirectiveKindMap[".else"] = DK_ELSE;
5582 DirectiveKindMap[".end"] = DK_END;
5583 DirectiveKindMap[".endif"] = DK_ENDIF;
5584 DirectiveKindMap[".skip"] = DK_SKIP;
5585 DirectiveKindMap[".space"] = DK_SPACE;
5586 DirectiveKindMap[".file"] = DK_FILE;
5587 DirectiveKindMap[".line"] = DK_LINE;
5588 DirectiveKindMap[".loc"] = DK_LOC;
5589 DirectiveKindMap[".loc_label"] = DK_LOC_LABEL;
5590 DirectiveKindMap[".stabs"] = DK_STABS;
5591 DirectiveKindMap[".cv_file"] = DK_CV_FILE;
5592 DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
5593 DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
5594 DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
5595 DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
5596 DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
5597 DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
5598 DirectiveKindMap[".cv_string"] = DK_CV_STRING;
5599 DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
5600 DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
5601 DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
5602 DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
5603 DirectiveKindMap[".sleb128"] = DK_SLEB128;
5604 DirectiveKindMap[".uleb128"] = DK_ULEB128;
5605 DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
5606 DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
5607 DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
5608 DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
5609 DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
5610 DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
5611 DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
5612 DirectiveKindMap[".cfi_llvm_def_aspace_cfa"] = DK_CFI_LLVM_DEF_ASPACE_CFA;
5613 DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
5614 DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
5615 DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
5616 DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
5617 DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
5618 DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
5619 DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
5620 DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
5621 DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
5622 DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
5623 DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
5624 DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
5625 DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
5626 DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
5627 DirectiveKindMap[".cfi_label"] = DK_CFI_LABEL;
5628 DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
5629 DirectiveKindMap[".cfi_mte_tagged_frame"] = DK_CFI_MTE_TAGGED_FRAME;
5630 DirectiveKindMap[".cfi_val_offset"] = DK_CFI_VAL_OFFSET;
5631 DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
5632 DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
5633 DirectiveKindMap[".macro"] = DK_MACRO;
5634 DirectiveKindMap[".exitm"] = DK_EXITM;
5635 DirectiveKindMap[".endm"] = DK_ENDM;
5636 DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
5637 DirectiveKindMap[".purgem"] = DK_PURGEM;
5638 DirectiveKindMap[".err"] = DK_ERR;
5639 DirectiveKindMap[".error"] = DK_ERROR;
5640 DirectiveKindMap[".warning"] = DK_WARNING;
5641 DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
5642 DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
5643 DirectiveKindMap[".reloc"] = DK_RELOC;
5644 DirectiveKindMap[".dc"] = DK_DC;
5645 DirectiveKindMap[".dc.a"] = DK_DC_A;
5646 DirectiveKindMap[".dc.b"] = DK_DC_B;
5647 DirectiveKindMap[".dc.d"] = DK_DC_D;
5648 DirectiveKindMap[".dc.l"] = DK_DC_L;
5649 DirectiveKindMap[".dc.s"] = DK_DC_S;
5650 DirectiveKindMap[".dc.w"] = DK_DC_W;
5651 DirectiveKindMap[".dc.x"] = DK_DC_X;
5652 DirectiveKindMap[".dcb"] = DK_DCB;
5653 DirectiveKindMap[".dcb.b"] = DK_DCB_B;
5654 DirectiveKindMap[".dcb.d"] = DK_DCB_D;
5655 DirectiveKindMap[".dcb.l"] = DK_DCB_L;
5656 DirectiveKindMap[".dcb.s"] = DK_DCB_S;
5657 DirectiveKindMap[".dcb.w"] = DK_DCB_W;
5658 DirectiveKindMap[".dcb.x"] = DK_DCB_X;
5659 DirectiveKindMap[".ds"] = DK_DS;
5660 DirectiveKindMap[".ds.b"] = DK_DS_B;
5661 DirectiveKindMap[".ds.d"] = DK_DS_D;
5662 DirectiveKindMap[".ds.l"] = DK_DS_L;
5663 DirectiveKindMap[".ds.p"] = DK_DS_P;
5664 DirectiveKindMap[".ds.s"] = DK_DS_S;
5665 DirectiveKindMap[".ds.w"] = DK_DS_W;
5666 DirectiveKindMap[".ds.x"] = DK_DS_X;
5667 DirectiveKindMap[".print"] = DK_PRINT;
5668 DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
5669 DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
5670 DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE;
5671 DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD;
5672 DirectiveKindMap[".lto_set_conditional"] = DK_LTO_SET_CONDITIONAL;
5673 DirectiveKindMap[".memtag"] = DK_MEMTAG;
5674}
5675
5676MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5677 AsmToken EndToken, StartToken = getTok();
5678
5679 unsigned NestLevel = 0;
5680 while (true) {
5681 // Check whether we have reached the end of the file.
5682 if (getLexer().is(AsmToken::Eof)) {
5683 printError(DirectiveLoc, "no matching '.endr' in definition");
5684 return nullptr;
5685 }
5686
5687 if (Lexer.is(AsmToken::Identifier)) {
5688 StringRef Ident = getTok().getIdentifier();
5689 if (Ident == ".rep" || Ident == ".rept" || Ident == ".irp" ||
5690 Ident == ".irpc") {
5691 ++NestLevel;
5692 } else if (Ident == ".endr") {
5693 if (NestLevel == 0) {
5694 EndToken = getTok();
5695 Lex();
5696 if (Lexer.is(AsmToken::EndOfStatement))
5697 break;
5698 printError(getTok().getLoc(), "expected newline");
5699 return nullptr;
5700 }
5701 --NestLevel;
5702 }
5703 }
5704
5705 // Otherwise, scan till the end of the statement.
5706 eatToEndOfStatement();
5707 }
5708
5709 const char *BodyStart = StartToken.getLoc().getPointer();
5710 const char *BodyEnd = EndToken.getLoc().getPointer();
5711 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5712
5713 // We Are Anonymous.
5714 MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
5715 return &MacroLikeBodies.back();
5716}
5717
5718void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5720 OS << ".endr\n";
5721
5722 std::unique_ptr<MemoryBuffer> Instantiation =
5723 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
5724
5725 // Create the macro instantiation object and add to the current macro
5726 // instantiation stack.
5727 MacroInstantiation *MI = new MacroInstantiation{
5728 DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
5729 ActiveMacros.push_back(MI);
5730
5731 // Jump to the macro instantiation and prime the lexer.
5732 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
5733 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
5734 Lex();
5735}
5736
5737/// parseDirectiveRept
5738/// ::= .rep | .rept count
5739bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
5740 const MCExpr *CountExpr;
5741 SMLoc CountLoc = getTok().getLoc();
5742 if (parseExpression(CountExpr))
5743 return true;
5744
5745 int64_t Count;
5746 if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
5747 return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
5748 }
5749
5750 if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())
5751 return true;
5752
5753 // Lex the rept definition.
5754 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5755 if (!M)
5756 return true;
5757
5758 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5759 // to hold the macro body with substitutions.
5760 SmallString<256> Buf;
5762 while (Count--) {
5763 // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
5764 if (expandMacro(OS, *M, {}, {}, false))
5765 return true;
5766 }
5767 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5768
5769 return false;
5770}
5771
5772/// parseDirectiveIrp
5773/// ::= .irp symbol,values
5774bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
5775 MCAsmMacroParameter Parameter;
5776 MCAsmMacroArguments A;
5777 if (check(parseIdentifier(Parameter.Name),
5778 "expected identifier in '.irp' directive") ||
5779 parseComma() || parseMacroArguments(nullptr, A) || parseEOL())
5780 return true;
5781
5782 // Lex the irp definition.
5783 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5784 if (!M)
5785 return true;
5786
5787 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5788 // to hold the macro body with substitutions.
5789 SmallString<256> Buf;
5791
5792 for (const MCAsmMacroArgument &Arg : A) {
5793 // Note that the AtPseudoVariable is enabled for instantiations of .irp.
5794 // This is undocumented, but GAS seems to support it.
5795 if (expandMacro(OS, *M, Parameter, Arg, true))
5796 return true;
5797 }
5798
5799 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5800
5801 return false;
5802}
5803
5804/// parseDirectiveIrpc
5805/// ::= .irpc symbol,values
5806bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
5807 MCAsmMacroParameter Parameter;
5808 MCAsmMacroArguments A;
5809
5810 if (check(parseIdentifier(Parameter.Name),
5811 "expected identifier in '.irpc' directive") ||
5812 parseComma() || parseMacroArguments(nullptr, A))
5813 return true;
5814
5815 if (A.size() != 1 || A.front().size() != 1)
5816 return TokError("unexpected token in '.irpc' directive");
5817 if (parseEOL())
5818 return true;
5819
5820 // Lex the irpc definition.
5821 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5822 if (!M)
5823 return true;
5824
5825 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5826 // to hold the macro body with substitutions.
5827 SmallString<256> Buf;
5829
5830 StringRef Values = A[0][0].is(AsmToken::String) ? A[0][0].getStringContents()
5831 : A[0][0].getString();
5832 for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
5833 MCAsmMacroArgument Arg;
5834 Arg.emplace_back(AsmToken::Identifier, Values.substr(I, 1));
5835
5836 // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
5837 // This is undocumented, but GAS seems to support it.
5838 if (expandMacro(OS, *M, Parameter, Arg, true))
5839 return true;
5840 }
5841
5842 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5843
5844 return false;
5845}
5846
5847bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
5848 if (ActiveMacros.empty())
5849 return TokError("unmatched '.endr' directive");
5850
5851 // The only .repl that should get here are the ones created by
5852 // instantiateMacroLikeBody.
5853 assert(getLexer().is(AsmToken::EndOfStatement));
5854
5855 handleMacroExit();
5856 return false;
5857}
5858
5859bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5860 size_t Len) {
5861 const MCExpr *Value;
5862 SMLoc ExprLoc = getLexer().getLoc();
5863 if (parseExpression(Value))
5864 return true;
5865 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5866 if (!MCE)
5867 return Error(ExprLoc, "unexpected expression in _emit");
5868 uint64_t IntValue = MCE->getValue();
5869 if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
5870 return Error(ExprLoc, "literal value out of range for directive");
5871
5872 Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
5873 return false;
5874}
5875
5876bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5877 const MCExpr *Value;
5878 SMLoc ExprLoc = getLexer().getLoc();
5879 if (parseExpression(Value))
5880 return true;
5881 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5882 if (!MCE)
5883 return Error(ExprLoc, "unexpected expression in align");
5884 uint64_t IntValue = MCE->getValue();
5885 if (!isPowerOf2_64(IntValue))
5886 return Error(ExprLoc, "literal value not a power of two greater then zero");
5887
5888 Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
5889 return false;
5890}
5891
5892bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
5893 const AsmToken StrTok = getTok();
5894 Lex();
5895 if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
5896 return Error(DirectiveLoc, "expected double quoted string after .print");
5897 if (parseEOL())
5898 return true;
5899 llvm::outs() << StrTok.getStringContents() << '\n';
5900 return false;
5901}
5902
5903bool AsmParser::parseDirectiveAddrsig() {
5904 if (parseEOL())
5905 return true;
5906 getStreamer().emitAddrsig();
5907 return false;
5908}
5909
5910bool AsmParser::parseDirectiveAddrsigSym() {
5912 if (check(parseIdentifier(Name), "expected identifier") || parseEOL())
5913 return true;
5914 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5915 getStreamer().emitAddrsigSym(Sym);
5916 return false;
5917}
5918
5919bool AsmParser::parseDirectivePseudoProbe() {
5920 int64_t Guid;
5921 int64_t Index;
5922 int64_t Type;
5923 int64_t Attr;
5924 int64_t Discriminator = 0;
5925
5926 if (parseIntToken(Guid, "unexpected token in '.pseudoprobe' directive"))
5927 return true;
5928
5929 if (parseIntToken(Index, "unexpected token in '.pseudoprobe' directive"))
5930 return true;
5931
5932 if (parseIntToken(Type, "unexpected token in '.pseudoprobe' directive"))
5933 return true;
5934
5935 if (parseIntToken(Attr, "unexpected token in '.pseudoprobe' directive"))
5936 return true;
5937
5938 if (hasDiscriminator(Attr)) {
5939 if (parseIntToken(Discriminator,
5940 "unexpected token in '.pseudoprobe' directive"))
5941 return true;
5942 }
5943
5944 // Parse inline stack like @ GUID:11:12 @ GUID:1:11 @ GUID:3:21
5945 MCPseudoProbeInlineStack InlineStack;
5946
5947 while (getLexer().is(AsmToken::At)) {
5948 // eat @
5949 Lex();
5950
5951 int64_t CallerGuid = 0;
5952 if (getLexer().is(AsmToken::Integer)) {
5953 if (parseIntToken(CallerGuid,
5954 "unexpected token in '.pseudoprobe' directive"))
5955 return true;
5956 }
5957
5958 // eat colon
5959 if (getLexer().is(AsmToken::Colon))
5960 Lex();
5961
5962 int64_t CallerProbeId = 0;
5963 if (getLexer().is(AsmToken::Integer)) {
5964 if (parseIntToken(CallerProbeId,
5965 "unexpected token in '.pseudoprobe' directive"))
5966 return true;
5967 }
5968
5969 InlineSite Site(CallerGuid, CallerProbeId);
5970 InlineStack.push_back(Site);
5971 }
5972
5973 // Parse function entry name
5974 StringRef FnName;
5975 if (parseIdentifier(FnName))
5976 return Error(getLexer().getLoc(), "unexpected token in '.pseudoprobe' directive");
5977 MCSymbol *FnSym = getContext().lookupSymbol(FnName);
5978
5979 if (parseEOL())
5980 return true;
5981
5982 getStreamer().emitPseudoProbe(Guid, Index, Type, Attr, Discriminator,
5983 InlineStack, FnSym);
5984 return false;
5985}
5986
5987/// parseDirectiveLTODiscard
5988/// ::= ".lto_discard" [ identifier ( , identifier )* ]
5989/// The LTO library emits this directive to discard non-prevailing symbols.
5990/// We ignore symbol assignments and attribute changes for the specified
5991/// symbols.
5992bool AsmParser::parseDirectiveLTODiscard() {
5993 auto ParseOp = [&]() -> bool {
5995 SMLoc Loc = getTok().getLoc();
5996 if (parseIdentifier(Name))
5997 return Error(Loc, "expected identifier");
5998 LTODiscardSymbols.insert(Name);
5999 return false;
6000 };
6001
6002 LTODiscardSymbols.clear();
6003 return parseMany(ParseOp);
6004}
6005
6006// We are comparing pointers, but the pointers are relative to a single string.
6007// Thus, this should always be deterministic.
6008static int rewritesSort(const AsmRewrite *AsmRewriteA,
6009 const AsmRewrite *AsmRewriteB) {
6010 if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
6011 return -1;
6012 if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
6013 return 1;
6014
6015 // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
6016 // rewrite to the same location. Make sure the SizeDirective rewrite is
6017 // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
6018 // ensures the sort algorithm is stable.
6019 if (AsmRewritePrecedence[AsmRewriteA->Kind] >
6020 AsmRewritePrecedence[AsmRewriteB->Kind])
6021 return -1;
6022
6023 if (AsmRewritePrecedence[AsmRewriteA->Kind] <
6024 AsmRewritePrecedence[AsmRewriteB->Kind])
6025 return 1;
6026 llvm_unreachable("Unstable rewrite sort.");
6027}
6028
6029bool AsmParser::parseMSInlineAsm(
6030 std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,
6031 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
6032 SmallVectorImpl<std::string> &Constraints,
6033 SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
6035 SmallVector<void *, 4> InputDecls;
6036 SmallVector<void *, 4> OutputDecls;
6037 SmallVector<bool, 4> InputDeclsAddressOf;
6038 SmallVector<bool, 4> OutputDeclsAddressOf;
6039 SmallVector<std::string, 4> InputConstraints;
6040 SmallVector<std::string, 4> OutputConstraints;
6041 SmallVector<MCRegister, 4> ClobberRegs;
6042
6043 SmallVector<AsmRewrite, 4> AsmStrRewrites;
6044
6045 // Prime the lexer.
6046 Lex();
6047
6048 // While we have input, parse each statement.
6049 unsigned InputIdx = 0;
6050 unsigned OutputIdx = 0;
6051 while (getLexer().isNot(AsmToken::Eof)) {
6052 // Parse curly braces marking block start/end
6053 if (parseCurlyBlockScope(AsmStrRewrites))
6054 continue;
6055
6056 ParseStatementInfo Info(&AsmStrRewrites);
6057 bool StatementErr = parseStatement(Info, &SI);
6058
6059 if (StatementErr || Info.ParseError) {
6060 // Emit pending errors if any exist.
6061 printPendingErrors();
6062 return true;
6063 }
6064
6065 // No pending error should exist here.
6066 assert(!hasPendingError() && "unexpected error from parseStatement");
6067
6068 if (Info.Opcode == ~0U)
6069 continue;
6070
6071 const MCInstrDesc &Desc = MII->get(Info.Opcode);
6072
6073 // Build the list of clobbers, outputs and inputs.
6074 for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
6075 MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
6076
6077 // Register operand.
6078 if (Operand.isReg() && !Operand.needAddressOf() &&
6079 !getTargetParser().omitRegisterFromClobberLists(Operand.getReg())) {
6080 unsigned NumDefs = Desc.getNumDefs();
6081 // Clobber.
6082 if (NumDefs && Operand.getMCOperandNum() < NumDefs)
6083 ClobberRegs.push_back(Operand.getReg());
6084 continue;
6085 }
6086
6087 // Expr/Input or Output.
6088 StringRef SymName = Operand.getSymName();
6089 if (SymName.empty())
6090 continue;
6091
6092 void *OpDecl = Operand.getOpDecl();
6093 if (!OpDecl)
6094 continue;
6095
6096 StringRef Constraint = Operand.getConstraint();
6097 if (Operand.isImm()) {
6098 // Offset as immediate
6099 if (Operand.isOffsetOfLocal())
6100 Constraint = "r";
6101 else
6102 Constraint = "i";
6103 }
6104
6105 bool isOutput = (i == 1) && Desc.mayStore();
6106 bool Restricted = Operand.isMemUseUpRegs();
6107 SMLoc Start = SMLoc::getFromPointer(SymName.data());
6108 if (isOutput) {
6109 ++InputIdx;
6110 OutputDecls.push_back(OpDecl);
6111 OutputDeclsAddressOf.push_back(Operand.needAddressOf());
6112 OutputConstraints.push_back(("=" + Constraint).str());
6113 AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size(), 0,
6114 Restricted);
6115 } else {
6116 InputDecls.push_back(OpDecl);
6117 InputDeclsAddressOf.push_back(Operand.needAddressOf());
6118 InputConstraints.push_back(Constraint.str());
6119 if (Desc.operands()[i - 1].isBranchTarget())
6120 AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size(), 0,
6121 Restricted);
6122 else
6123 AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size(), 0,
6124 Restricted);
6125 }
6126 }
6127
6128 // Consider implicit defs to be clobbers. Think of cpuid and push.
6129 llvm::append_range(ClobberRegs, Desc.implicit_defs());
6130 }
6131
6132 // Set the number of Outputs and Inputs.
6133 NumOutputs = OutputDecls.size();
6134 NumInputs = InputDecls.size();
6135
6136 // Set the unique clobbers.
6137 array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
6138 ClobberRegs.erase(llvm::unique(ClobberRegs), ClobberRegs.end());
6139 Clobbers.assign(ClobberRegs.size(), std::string());
6140 for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
6141 raw_string_ostream OS(Clobbers[I]);
6142 IP->printRegName(OS, ClobberRegs[I]);
6143 }
6144
6145 // Merge the various outputs and inputs. Output are expected first.
6146 if (NumOutputs || NumInputs) {
6147 unsigned NumExprs = NumOutputs + NumInputs;
6148 OpDecls.resize(NumExprs);
6149 Constraints.resize(NumExprs);
6150 for (unsigned i = 0; i < NumOutputs; ++i) {
6151 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
6152 Constraints[i] = OutputConstraints[i];
6153 }
6154 for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
6155 OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6156 Constraints[j] = InputConstraints[i];
6157 }
6158 }
6159
6160 // Build the IR assembly string.
6161 std::string AsmStringIR;
6162 raw_string_ostream OS(AsmStringIR);
6163 StringRef ASMString =
6165 const char *AsmStart = ASMString.begin();
6166 const char *AsmEnd = ASMString.end();
6167 array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
6168 for (auto I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {
6169 const AsmRewrite &AR = *I;
6170 // Check if this has already been covered by another rewrite...
6171 if (AR.Done)
6172 continue;
6174
6175 const char *Loc = AR.Loc.getPointer();
6176 assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
6177
6178 // Emit everything up to the immediate/expression.
6179 if (unsigned Len = Loc - AsmStart)
6180 OS << StringRef(AsmStart, Len);
6181
6182 // Skip the original expression.
6183 if (Kind == AOK_Skip) {
6184 AsmStart = Loc + AR.Len;
6185 continue;
6186 }
6187
6188 unsigned AdditionalSkip = 0;
6189 // Rewrite expressions in $N notation.
6190 switch (Kind) {
6191 default:
6192 break;
6193 case AOK_IntelExpr:
6194 assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
6195 if (AR.IntelExp.NeedBracs)
6196 OS << "[";
6197 if (AR.IntelExp.hasBaseReg())
6198 OS << AR.IntelExp.BaseReg;
6199 if (AR.IntelExp.hasIndexReg())
6200 OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
6201 << AR.IntelExp.IndexReg;
6202 if (AR.IntelExp.Scale > 1)
6203 OS << " * $$" << AR.IntelExp.Scale;
6204 if (AR.IntelExp.hasOffset()) {
6205 if (AR.IntelExp.hasRegs())
6206 OS << " + ";
6207 // Fuse this rewrite with a rewrite of the offset name, if present.
6208 StringRef OffsetName = AR.IntelExp.OffsetName;
6210 size_t OffsetLen = OffsetName.size();
6211 auto rewrite_it = std::find_if(
6212 I, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
6213 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6214 (FusingAR.Kind == AOK_Input ||
6215 FusingAR.Kind == AOK_CallInput);
6216 });
6217 if (rewrite_it == AsmStrRewrites.end()) {
6218 OS << "offset " << OffsetName;
6219 } else if (rewrite_it->Kind == AOK_CallInput) {
6220 OS << "${" << InputIdx++ << ":P}";
6221 rewrite_it->Done = true;
6222 } else {
6223 OS << '$' << InputIdx++;
6224 rewrite_it->Done = true;
6225 }
6226 }
6227 if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
6228 OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
6229 if (AR.IntelExp.NeedBracs)
6230 OS << "]";
6231 break;
6232 case AOK_Label:
6233 OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
6234 break;
6235 case AOK_Input:
6236 if (AR.IntelExpRestricted)
6237 OS << "${" << InputIdx++ << ":P}";
6238 else
6239 OS << '$' << InputIdx++;
6240 break;
6241 case AOK_CallInput:
6242 OS << "${" << InputIdx++ << ":P}";
6243 break;
6244 case AOK_Output:
6245 if (AR.IntelExpRestricted)
6246 OS << "${" << OutputIdx++ << ":P}";
6247 else
6248 OS << '$' << OutputIdx++;
6249 break;
6250 case AOK_SizeDirective:
6251 switch (AR.Val) {
6252 default: break;
6253 case 8: OS << "byte ptr "; break;
6254 case 16: OS << "word ptr "; break;
6255 case 32: OS << "dword ptr "; break;
6256 case 64: OS << "qword ptr "; break;
6257 case 80: OS << "xword ptr "; break;
6258 case 128: OS << "xmmword ptr "; break;
6259 case 256: OS << "ymmword ptr "; break;
6260 }
6261 break;
6262 case AOK_Emit:
6263 OS << ".byte";
6264 break;
6265 case AOK_Align: {
6266 // MS alignment directives are measured in bytes. If the native assembler
6267 // measures alignment in bytes, we can pass it straight through.
6268 OS << ".align";
6269 if (getContext().getAsmInfo()->getAlignmentIsInBytes())
6270 break;
6271
6272 // Alignment is in log2 form, so print that instead and skip the original
6273 // immediate.
6274 unsigned Val = AR.Val;
6275 OS << ' ' << Val;
6276 assert(Val < 10 && "Expected alignment less then 2^10.");
6277 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6278 break;
6279 }
6280 case AOK_EVEN:
6281 OS << ".even";
6282 break;
6283 case AOK_EndOfStatement:
6284 OS << "\n\t";
6285 break;
6286 }
6287
6288 // Skip the original expression.
6289 AsmStart = Loc + AR.Len + AdditionalSkip;
6290 }
6291
6292 // Emit the remainder of the asm string.
6293 if (AsmStart != AsmEnd)
6294 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6295
6296 AsmString = std::move(AsmStringIR);
6297 return false;
6298}
6299
6300bool HLASMAsmParser::parseAsHLASMLabel(ParseStatementInfo &Info,
6302 AsmToken LabelTok = getTok();
6303 SMLoc LabelLoc = LabelTok.getLoc();
6304 StringRef LabelVal;
6305
6306 if (parseIdentifier(LabelVal))
6307 return Error(LabelLoc, "The HLASM Label has to be an Identifier");
6308
6309 // We have validated whether the token is an Identifier.
6310 // Now we have to validate whether the token is a
6311 // valid HLASM Label.
6312 if (!getTargetParser().isLabel(LabelTok) || checkForValidSection())
6313 return true;
6314
6315 // Lex leading spaces to get to the next operand.
6316 lexLeadingSpaces();
6317
6318 // We shouldn't emit the label if there is nothing else after the label.
6319 // i.e asm("<token>\n")
6320 if (getTok().is(AsmToken::EndOfStatement))
6321 return Error(LabelLoc,
6322 "Cannot have just a label for an HLASM inline asm statement");
6323
6324 MCSymbol *Sym = getContext().getOrCreateSymbol(
6325 getContext().getAsmInfo()->shouldEmitLabelsInUpperCase()
6326 ? LabelVal.upper()
6327 : LabelVal);
6328
6329 getTargetParser().doBeforeLabelEmit(Sym, LabelLoc);
6330
6331 // Emit the label.
6332 Out.emitLabel(Sym, LabelLoc);
6333
6334 // If we are generating dwarf for assembly source files then gather the
6335 // info to make a dwarf label entry for this label if needed.
6336 if (enabledGenDwarfForAssembly())
6337 MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
6338 LabelLoc);
6339
6340 getTargetParser().onLabelParsed(Sym);
6341
6342 return false;
6343}
6344
6345bool HLASMAsmParser::parseAsMachineInstruction(ParseStatementInfo &Info,
6347 AsmToken OperationEntryTok = Lexer.getTok();
6348 SMLoc OperationEntryLoc = OperationEntryTok.getLoc();
6349 StringRef OperationEntryVal;
6350
6351 // Attempt to parse the first token as an Identifier
6352 if (parseIdentifier(OperationEntryVal))
6353 return Error(OperationEntryLoc, "unexpected token at start of statement");
6354
6355 // Once we've parsed the operation entry successfully, lex
6356 // any spaces to get to the OperandEntries.
6357 lexLeadingSpaces();
6358
6359 return parseAndMatchAndEmitTargetInstruction(
6360 Info, OperationEntryVal, OperationEntryTok, OperationEntryLoc);
6361}
6362
6363bool HLASMAsmParser::parseStatement(ParseStatementInfo &Info,
6365 assert(!hasPendingError() && "parseStatement started with pending error");
6366
6367 // Should the first token be interpreted as a HLASM Label.
6368 bool ShouldParseAsHLASMLabel = false;
6369
6370 // If a Name Entry exists, it should occur at the very
6371 // start of the string. In this case, we should parse the
6372 // first non-space token as a Label.
6373 // If the Name entry is missing (i.e. there's some other
6374 // token), then we attempt to parse the first non-space
6375 // token as a Machine Instruction.
6376 if (getTok().isNot(AsmToken::Space))
6377 ShouldParseAsHLASMLabel = true;
6378
6379 // If we have an EndOfStatement (which includes the target's comment
6380 // string) we can appropriately lex it early on)
6381 if (Lexer.is(AsmToken::EndOfStatement)) {
6382 // if this is a line comment we can drop it safely
6383 if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
6384 getTok().getString().front() == '\n')
6385 Out.addBlankLine();
6386 Lex();
6387 return false;
6388 }
6389
6390 // We have established how to parse the inline asm statement.
6391 // Now we can safely lex any leading spaces to get to the
6392 // first token.
6393 lexLeadingSpaces();
6394
6395 // If we see a new line or carriage return as the first operand,
6396 // after lexing leading spaces, emit the new line and lex the
6397 // EndOfStatement token.
6398 if (Lexer.is(AsmToken::EndOfStatement)) {
6399 if (getTok().getString().front() == '\n' ||
6400 getTok().getString().front() == '\r') {
6401 Out.addBlankLine();
6402 Lex();
6403 return false;
6404 }
6405 }
6406
6407 // Handle the label first if we have to before processing the rest
6408 // of the tokens as a machine instruction.
6409 if (ShouldParseAsHLASMLabel) {
6410 // If there were any errors while handling and emitting the label,
6411 // early return.
6412 if (parseAsHLASMLabel(Info, SI)) {
6413 // If we know we've failed in parsing, simply eat until end of the
6414 // statement. This ensures that we don't process any other statements.
6415 eatToEndOfStatement();
6416 return true;
6417 }
6418 }
6419
6420 return parseAsMachineInstruction(Info, SI);
6421}
6422
6423namespace llvm {
6424namespace MCParserUtils {
6425
6427 MCAsmParser &Parser, MCSymbol *&Sym,
6428 const MCExpr *&Value) {
6429
6430 // FIXME: Use better location, we should use proper tokens.
6431 SMLoc EqualLoc = Parser.getTok().getLoc();
6432 if (Parser.parseExpression(Value))
6433 return Parser.TokError("missing expression");
6434
6435 // Note: we don't count b as used in "a = b". This is to allow
6436 // a = b
6437 // b = c
6438
6439 if (Parser.parseEOL())
6440 return true;
6441
6442 // Validate that the LHS is allowed to be a variable (either it has not been
6443 // used as a symbol, or it is an absolute symbol).
6444 Sym = Parser.getContext().lookupSymbol(Name);
6445 if (Sym) {
6446 // Diagnose assignment to a label.
6447 //
6448 // FIXME: Diagnostics. Note the location of the definition as a label.
6449 // FIXME: Diagnose assignment to protected identifier (e.g., register name).
6450 if (Value->isSymbolUsedInExpression(Sym))
6451 return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'");
6452 else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() &&
6453 !Sym->isVariable())
6454 ; // Allow redefinitions of undefined symbols only used in directives.
6455 else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
6456 ; // Allow redefinitions of variables that haven't yet been used.
6457 else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
6458 return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
6459 else if (!Sym->isVariable())
6460 return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'");
6461 else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
6462 return Parser.Error(EqualLoc,
6463 "invalid reassignment of non-absolute variable '" +
6464 Name + "'");
6465 } else if (Name == ".") {
6466 Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
6467 return false;
6468 } else
6470
6471 Sym->setRedefinable(allow_redef);
6472
6473 return false;
6474}
6475
6476} // end namespace MCParserUtils
6477} // end namespace llvm
6478
6479/// Create an MCAsmParser instance.
6481 MCStreamer &Out, const MCAsmInfo &MAI,
6482 unsigned CB) {
6483 if (C.getTargetTriple().isSystemZ() && C.getTargetTriple().isOSzOS())
6484 return new HLASMAsmParser(SM, C, Out, MAI, CB);
6485
6486 return new AsmParser(SM, C, Out, MAI, CB);
6487}
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:4386
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:2511
@ DEFAULT_ADDRSPACE
Definition: AsmParser.cpp:775
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:6008
static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo)
Definition: AsmParser.cpp:3229
static bool isOperator(AsmToken::TokenKind kind)
Definition: AsmParser.cpp:2647
basic Basic Alias true
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
static ManagedStatic< cl::opt< bool, true >, CreateDebug > Debug
Definition: Debug.cpp:108
#define DEBUG_WITH_TYPE(TYPE,...)
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
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(PassOpts->AAPipeline)
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
static bool isDigit(const char C)
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:1095
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Definition: APFloat.h:1106
Class for arbitrary precision integers.
Definition: APInt.h:78
APInt getLoBits(unsigned numBits) const
Compute an APInt containing numBits lowbits from this APInt.
Definition: APInt.cpp:617
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1520
APInt getHiBits(unsigned numBits) const
Compute an APInt containing numBits highbits from this APInt.
Definition: APInt.cpp:612
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1468
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:475
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
Definition: APInt.h:432
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:771
bool preserveAsmComments() const
Return true if assembly (inline or otherwise) should be parsed.
Definition: MCAsmInfo.h:824
bool isLittleEndian() const
True if the target is little endian.
Definition: MCAsmInfo.h:527
unsigned getAssemblerDialect() const
Definition: MCAsmInfo.h:646
bool doesAllowAtInName() const
Definition: MCAsmInfo.h:647
StringRef getPrivateLabelPrefix() const
Definition: MCAsmInfo.h:629
bool shouldEmitLabelsInUpperCase() const
Definition: MCAsmInfo.h:624
bool getStarIsPC() const
Definition: MCAsmInfo.h:609
bool shouldUseLogicalShr() const
Definition: MCAsmInfo.h:832
StringRef getCommentString() const
Definition: MCAsmInfo.h:615
bool getDotIsPC() const
Definition: MCAsmInfo.h:608
bool hasSubsectionsViaSymbols() const
Definition: MCAsmInfo.h:532
bool getDollarIsPC() const
Definition: MCAsmInfo.h:607
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 void setAssemblerDialect(unsigned i)
Definition: MCAsmParser.h:174
virtual MCContext & getContext()=0
virtual void setParsingMSInlineAsm(bool V)=0
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, MCInstPrinter *IP, MCAsmParserSemaCallback &SI)=0
Parse MS-style inline assembly.
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:493
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
Definition: MCExpr.h:640
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Definition: MCExpr.h:643
Opcode getOpcode() const
Get the kind of this binary expression.
Definition: MCExpr.h:637
static const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:211
@ Div
Signed division.
Definition: MCExpr.h:498
@ Shl
Shift left.
Definition: MCExpr.h:515
@ AShr
Arithmetic shift right.
Definition: MCExpr.h:516
@ LShr
Logical shift right.
Definition: MCExpr.h:517
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
Definition: MCExpr.h:502
@ EQ
Equality comparison.
Definition: MCExpr.h:499
@ Sub
Subtraction.
Definition: MCExpr.h:518
@ Mul
Multiplication.
Definition: MCExpr.h:511
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
Definition: MCExpr.h:500
@ Mod
Signed remainder.
Definition: MCExpr.h:510
@ And
Bitwise and.
Definition: MCExpr.h:497
@ Or
Bitwise or.
Definition: MCExpr.h:513
@ Xor
Bitwise exclusive or.
Definition: MCExpr.h:519
@ OrNot
Bitwise or not.
Definition: MCExpr.h:514
@ LAnd
Logical and.
Definition: MCExpr.h:504
@ LOr
Logical or.
Definition: MCExpr.h:505
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
Definition: MCExpr.h:506
@ Add
Addition.
Definition: MCExpr.h:496
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
Definition: MCExpr.h:508
@ NE
Inequality comparison.
Definition: MCExpr.h:512
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:222
Context object for machine code objects.
Definition: MCContext.h:83
void * allocate(unsigned Size, unsigned Align=8)
Definition: MCContext.h:816
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:735
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:345
bool getGenDwarfForAssembly()
Definition: MCContext.h:760
void setGenDwarfForAssembly(bool Value)
Definition: MCContext.h:761
void setDwarfVersion(uint16_t v)
Definition: MCContext.h:801
MCDwarfLineTable & getMCDwarfLineTable(unsigned CUID)
Definition: MCContext.h:702
MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
Definition: MCContext.cpp:412
CodeViewContext & getCVContext()
Definition: MCContext.cpp:1017
MCSymbol * createDirectionalLocalSymbol(unsigned LocalLabelVal)
Create the definition of a directional local symbol for numbered label (used for "1:" definitions).
Definition: MCContext.cpp:378
uint16_t getDwarfVersion() const
Definition: MCContext.h:802
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:383
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
@ Unary
Unary expressions.
Definition: MCExpr.h:40
@ Constant
Constant expressions.
Definition: MCExpr.h:38
@ SymbolRef
References to labels and assigned expressions.
Definition: MCExpr.h:39
@ Target
Target specific expression.
Definition: MCExpr.h:41
@ Binary
Binary expressions.
Definition: MCExpr.h:37
bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm, const MCFixup *Fixup) const
Try to evaluate the expression to a relocatable value, i.e.
Definition: MCExpr.cpp:819
ExprKind getKind() const
Definition: MCExpr.h:78
static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, SMLoc &Loc)
Definition: MCDwarf.cpp:1233
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
Definition: MCInstPrinter.h:46
virtual void printRegName(raw_ostream &OS, MCRegister Reg)
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
void setBeginSymbol(MCSymbol *Sym)
Definition: MCSection.h:139
MCSymbol * getBeginSymbol()
Definition: MCSection.h:135
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:387
virtual void initSections(bool NoExecStack, const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
Definition: MCStreamer.cpp:416
void setStartTokLocPtr(const SMLoc *Loc)
Definition: MCStreamer.h:291
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:122
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:420
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:309
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:439
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:411
static VariantKind getVariantKindForName(StringRef Name)
Definition: MCExpr.cpp:435
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:398
VariantKind getKind() const
Definition: MCExpr.h:413
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
MCTargetAsmParser - Generic interface to target specific assembly parsers.
const MCSubtargetInfo & getSTI() const
Unary assembler expressions.
Definition: MCExpr.h:437
Opcode getOpcode() const
Get the kind of this unary expression.
Definition: MCExpr.h:480
static const MCUnaryExpr * create(Opcode Op, const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:217
static const MCUnaryExpr * createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:459
const MCExpr * getSubExpr() const
Get the child of this unary expression.
Definition: MCExpr.h:483
static const MCUnaryExpr * createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:471
static const MCUnaryExpr * createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:467
static const MCUnaryExpr * createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:463
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:132
void clear()
Definition: SmallSet.h:204
bool contains(const T &V) const
Check if the SmallSet contains the given element.
Definition: SmallSet.h:222
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:181
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:78
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
void assign(size_type NumElts, ValueParamT Elt)
Definition: SmallVector.h:704
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:937
iterator erase(const_iterator CI)
Definition: SmallVector.h:737
void resize(size_type N)
Definition: SmallVector.h:638
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
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:51
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:700
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:229
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:571
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:265
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:609
iterator begin() const
Definition: StringRef.h:116
std::string upper() const
Convert the given ASCII string to uppercase.
Definition: StringRef.cpp:118
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:150
char front() const
front - Get the first character in the string.
Definition: StringRef.h:153
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:144
iterator end() const
Definition: StringRef.h:118
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:580
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
Definition: StringRef.h:815
std::string lower() const
Definition: StringRef.cpp:113
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:6426
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
Definition: MCDCTypes.h:56
@ DW_EH_PE_pcrel
Definition: Dwarf.h:858
@ DW_EH_PE_signed
Definition: Dwarf.h:857
@ DW_EH_PE_sdata4
Definition: Dwarf.h:855
@ DW_EH_PE_udata2
Definition: Dwarf.h:850
@ DW_EH_PE_sdata8
Definition: Dwarf.h:856
@ DW_EH_PE_absptr
Definition: Dwarf.h:847
@ DW_EH_PE_sdata2
Definition: Dwarf.h:854
@ DW_EH_PE_udata4
Definition: Dwarf.h:851
@ DW_EH_PE_udata8
Definition: Dwarf.h:852
@ DW_EH_PE_omit
Definition: Dwarf.h:848
@ ChecksumKind
Definition: LLToken.h:492
constexpr double e
Definition: MathExtras.h:47
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:1697
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:255
@ AOK_EndOfStatement
@ AOK_SizeDirective
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
std::tuple< uint64_t, uint32_t > InlineSite
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2115
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition: MathExtras.h:296
std::vector< MCAsmMacroParameter > MCAsmMacroParameters
Definition: MCAsmMacro.h:141
auto unique(Range &&R, Predicate P)
Definition: STLExtras.h:2055
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:346
MCAsmParserExtension * createXCOFFAsmParser()
SourceMgr SrcMgr
Definition: Error.cpp:24
MCAsmParserExtension * createGOFFAsmParser()
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:420
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:6480
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:260
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:1938
const char * toString(DWARFSectionKind Kind)
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:1624
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