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