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