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