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