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