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