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 MCSymbol *Sym;
2890 const MCExpr *Value;
2891 SMLoc ExprLoc = getTok().getLoc();
2892 bool AllowRedef =
2893 Kind == AssignmentKind::Set || Kind == AssignmentKind::Equal;
2894 if (MCParserUtils::parseAssignmentExpression(Name, AllowRedef, *this, Sym,
2895 Value))
2896 return true;
2897
2898 if (!Sym) {
2899 // In the case where we parse an expression starting with a '.', we will
2900 // not generate an error, nor will we create a symbol. In this case we
2901 // should just return out.
2902 return false;
2903 }
2904
2905 if (discardLTOSymbol(Name))
2906 return false;
2907
2908 // Do the assignment.
2909 switch (Kind) {
2910 case AssignmentKind::Equal:
2911 Out.emitAssignment(Sym, Value);
2912 break;
2913 case AssignmentKind::Set:
2914 case AssignmentKind::Equiv:
2915 Out.emitAssignment(Sym, Value);
2917 break;
2918 case AssignmentKind::LTOSetConditional:
2919 if (Value->getKind() != MCExpr::SymbolRef)
2920 return Error(ExprLoc, "expected identifier");
2921
2923 break;
2924 }
2925
2926 return false;
2927}
2928
2929/// parseIdentifier:
2930/// ::= identifier
2931/// ::= string
2932bool AsmParser::parseIdentifier(StringRef &Res) {
2933 // The assembler has relaxed rules for accepting identifiers, in particular we
2934 // allow things like '.globl $foo' and '.def @feat.00', which would normally be
2935 // separate tokens. At this level, we have already lexed so we cannot (currently)
2936 // handle this as a context dependent token, instead we detect adjacent tokens
2937 // and return the combined identifier.
2938 if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
2939 SMLoc PrefixLoc = getLexer().getLoc();
2940
2941 // Consume the prefix character, and check for a following identifier.
2942
2943 AsmToken Buf[1];
2944 Lexer.peekTokens(Buf, false);
2945
2946 if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer))
2947 return true;
2948
2949 // We have a '$' or '@' followed by an identifier or integer token, make
2950 // sure they are adjacent.
2951 if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())
2952 return true;
2953
2954 // eat $ or @
2955 Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
2956 // Construct the joined identifier and consume the token.
2957 Res = StringRef(PrefixLoc.getPointer(), getTok().getString().size() + 1);
2958 Lex(); // Parser Lex to maintain invariants.
2959 return false;
2960 }
2961
2962 if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
2963 return true;
2964
2965 Res = getTok().getIdentifier();
2966
2967 Lex(); // Consume the identifier token.
2968
2969 return false;
2970}
2971
2972/// parseDirectiveSet:
2973/// ::= .equ identifier ',' expression
2974/// ::= .equiv identifier ',' expression
2975/// ::= .set identifier ',' expression
2976/// ::= .lto_set_conditional identifier ',' expression
2977bool AsmParser::parseDirectiveSet(StringRef IDVal, AssignmentKind Kind) {
2978 StringRef Name;
2979 if (check(parseIdentifier(Name), "expected identifier") || parseComma() ||
2980 parseAssignment(Name, Kind))
2981 return true;
2982 return false;
2983}
2984
2985bool AsmParser::parseEscapedString(std::string &Data) {
2986 if (check(getTok().isNot(AsmToken::String), "expected string"))
2987 return true;
2988
2989 Data = "";
2990 StringRef Str = getTok().getStringContents();
2991 for (unsigned i = 0, e = Str.size(); i != e; ++i) {
2992 if (Str[i] != '\\') {
2993 if ((Str[i] == '\n') || (Str[i] == '\r')) {
2994 // Don't double-warn for Windows newlines.
2995 if ((Str[i] == '\n') && (i > 0) && (Str[i - 1] == '\r'))
2996 continue;
2997
2998 SMLoc NewlineLoc = SMLoc::getFromPointer(Str.data() + i);
2999 if (Warning(NewlineLoc, "unterminated string; newline inserted"))
3000 return true;
3001 }
3002 Data += Str[i];
3003 continue;
3004 }
3005
3006 // Recognize escaped characters. Note that this escape semantics currently
3007 // loosely follows Darwin 'as'.
3008 ++i;
3009 if (i == e)
3010 return TokError("unexpected backslash at end of string");
3011
3012 // Recognize hex sequences similarly to GNU 'as'.
3013 if (Str[i] == 'x' || Str[i] == 'X') {
3014 size_t length = Str.size();
3015 if (i + 1 >= length || !isHexDigit(Str[i + 1]))
3016 return TokError("invalid hexadecimal escape sequence");
3017
3018 // Consume hex characters. GNU 'as' reads all hexadecimal characters and
3019 // then truncates to the lower 16 bits. Seems reasonable.
3020 unsigned Value = 0;
3021 while (i + 1 < length && isHexDigit(Str[i + 1]))
3022 Value = Value * 16 + hexDigitValue(Str[++i]);
3023
3024 Data += (unsigned char)(Value & 0xFF);
3025 continue;
3026 }
3027
3028 // Recognize octal sequences.
3029 if ((unsigned)(Str[i] - '0') <= 7) {
3030 // Consume up to three octal characters.
3031 unsigned Value = Str[i] - '0';
3032
3033 if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
3034 ++i;
3035 Value = Value * 8 + (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 }
3042
3043 if (Value > 255)
3044 return TokError("invalid octal escape sequence (out of range)");
3045
3046 Data += (unsigned char)Value;
3047 continue;
3048 }
3049
3050 // Otherwise recognize individual escapes.
3051 switch (Str[i]) {
3052 default:
3053 // Just reject invalid escape sequences for now.
3054 return TokError("invalid escape sequence (unrecognized character)");
3055
3056 case 'b': Data += '\b'; break;
3057 case 'f': Data += '\f'; break;
3058 case 'n': Data += '\n'; break;
3059 case 'r': Data += '\r'; break;
3060 case 't': Data += '\t'; break;
3061 case '"': Data += '"'; break;
3062 case '\\': Data += '\\'; break;
3063 }
3064 }
3065
3066 Lex();
3067 return false;
3068}
3069
3070bool AsmParser::parseAngleBracketString(std::string &Data) {
3071 SMLoc EndLoc, StartLoc = getTok().getLoc();
3072 if (isAngleBracketString(StartLoc, EndLoc)) {
3073 const char *StartChar = StartLoc.getPointer() + 1;
3074 const char *EndChar = EndLoc.getPointer() - 1;
3075 jumpToLoc(EndLoc, CurBuffer);
3076 /// Eat from '<' to '>'
3077 Lex();
3078
3079 Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
3080 return false;
3081 }
3082 return true;
3083}
3084
3085/// parseDirectiveAscii:
3086// ::= .ascii [ "string"+ ( , "string"+ )* ]
3087/// ::= ( .asciz | .string ) [ "string" ( , "string" )* ]
3088bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
3089 auto parseOp = [&]() -> bool {
3090 std::string Data;
3091 if (checkForValidSection())
3092 return true;
3093 // Only support spaces as separators for .ascii directive for now. See the
3094 // discusssion at https://reviews.llvm.org/D91460 for more details.
3095 do {
3096 if (parseEscapedString(Data))
3097 return true;
3098 getStreamer().emitBytes(Data);
3099 } while (!ZeroTerminated && getTok().is(AsmToken::String));
3100 if (ZeroTerminated)
3101 getStreamer().emitBytes(StringRef("\0", 1));
3102 return false;
3103 };
3104
3105 return parseMany(parseOp);
3106}
3107
3108/// parseDirectiveBase64:
3109// ::= .base64 "string" (, "string" )*
3110bool AsmParser::parseDirectiveBase64() {
3111 auto parseOp = [&]() -> bool {
3112 if (checkForValidSection())
3113 return true;
3114
3115 if (getTok().isNot(AsmToken::String)) {
3116 return true;
3117 }
3118
3119 std::vector<char> Decoded;
3120 std::string const str = getTok().getStringContents().str();
3121 if (check(str.empty(), "expected nonempty string")) {
3122 return true;
3123 }
3124
3125 llvm::Error e = decodeBase64(str, Decoded);
3126 if (e) {
3127 consumeError(std::move(e));
3128 return Error(Lexer.getLoc(), "failed to base64 decode string data");
3129 }
3130
3131 getStreamer().emitBytes(std::string(Decoded.begin(), Decoded.end()));
3132 Lex();
3133 return false;
3134 };
3135
3136 return check(parseMany(parseOp), "expected string");
3137}
3138
3139/// parseDirectiveReloc
3140/// ::= .reloc expression , identifier [ , expression ]
3141bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
3142 const MCExpr *Offset;
3143 const MCExpr *Expr = nullptr;
3144
3145 if (parseExpression(Offset))
3146 return true;
3147 if (parseComma() ||
3148 check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
3149 return true;
3150
3151 SMLoc NameLoc = Lexer.getTok().getLoc();
3152 StringRef Name = Lexer.getTok().getIdentifier();
3153 Lex();
3154
3155 if (Lexer.is(AsmToken::Comma)) {
3156 Lex();
3157 SMLoc ExprLoc = Lexer.getLoc();
3158 if (parseExpression(Expr))
3159 return true;
3160
3161 MCValue Value;
3162 if (!Expr->evaluateAsRelocatable(Value, nullptr))
3163 return Error(ExprLoc, "expression must be relocatable");
3164 }
3165
3166 if (parseEOL())
3167 return true;
3168
3169 getStreamer().emitRelocDirective(*Offset, Name, Expr, NameLoc);
3170 return false;
3171}
3172
3173/// parseDirectiveValue
3174/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
3175bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
3176 auto parseOp = [&]() -> bool {
3177 const MCExpr *Value;
3178 SMLoc ExprLoc = getLexer().getLoc();
3179 if (checkForValidSection() || getTargetParser().parseDataExpr(Value))
3180 return true;
3181 // Special case constant expressions to match code generator.
3182 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3183 assert(Size <= 8 && "Invalid size");
3184 uint64_t IntValue = MCE->getValue();
3185 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
3186 return Error(ExprLoc, "out of range literal value");
3187 getStreamer().emitIntValue(IntValue, Size);
3188 } else
3189 getStreamer().emitValue(Value, Size, ExprLoc);
3190 return false;
3191 };
3192
3193 return parseMany(parseOp);
3194}
3195
3196static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {
3197 if (Asm.getTok().isNot(AsmToken::Integer) &&
3198 Asm.getTok().isNot(AsmToken::BigNum))
3199 return Asm.TokError("unknown token in expression");
3200 SMLoc ExprLoc = Asm.getTok().getLoc();
3201 APInt IntValue = Asm.getTok().getAPIntVal();
3202 Asm.Lex();
3203 if (!IntValue.isIntN(128))
3204 return Asm.Error(ExprLoc, "out of range literal value");
3205 if (!IntValue.isIntN(64)) {
3206 hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
3207 lo = IntValue.getLoBits(64).getZExtValue();
3208 } else {
3209 hi = 0;
3210 lo = IntValue.getZExtValue();
3211 }
3212 return false;
3213}
3214
3215/// ParseDirectiveOctaValue
3216/// ::= .octa [ hexconstant (, hexconstant)* ]
3217
3218bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
3219 auto parseOp = [&]() -> bool {
3220 if (checkForValidSection())
3221 return true;
3222 uint64_t hi, lo;
3223 if (parseHexOcta(*this, hi, lo))
3224 return true;
3225 if (MAI.isLittleEndian()) {
3226 getStreamer().emitInt64(lo);
3227 getStreamer().emitInt64(hi);
3228 } else {
3229 getStreamer().emitInt64(hi);
3230 getStreamer().emitInt64(lo);
3231 }
3232 return false;
3233 };
3234
3235 return parseMany(parseOp);
3236}
3237
3238bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
3239 // We don't truly support arithmetic on floating point expressions, so we
3240 // have to manually parse unary prefixes.
3241 bool IsNeg = false;
3242 if (getLexer().is(AsmToken::Minus)) {
3243 Lexer.Lex();
3244 IsNeg = true;
3245 } else if (getLexer().is(AsmToken::Plus))
3246 Lexer.Lex();
3247
3248 if (Lexer.is(AsmToken::Error))
3249 return TokError(Lexer.getErr());
3250 if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
3252 return TokError("unexpected token in directive");
3253
3254 // Convert to an APFloat.
3255 APFloat Value(Semantics);
3256 StringRef IDVal = getTok().getString();
3257 if (getLexer().is(AsmToken::Identifier)) {
3258 if (!IDVal.compare_insensitive("infinity") ||
3259 !IDVal.compare_insensitive("inf"))
3260 Value = APFloat::getInf(Semantics);
3261 else if (!IDVal.compare_insensitive("nan"))
3262 Value = APFloat::getNaN(Semantics, false, ~0);
3263 else
3264 return TokError("invalid floating point literal");
3265 } else if (errorToBool(
3266 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3267 .takeError()))
3268 return TokError("invalid floating point literal");
3269 if (IsNeg)
3270 Value.changeSign();
3271
3272 // Consume the numeric token.
3273 Lex();
3274
3275 Res = Value.bitcastToAPInt();
3276
3277 return false;
3278}
3279
3280/// parseDirectiveRealValue
3281/// ::= (.single | .double) [ expression (, expression)* ]
3282bool AsmParser::parseDirectiveRealValue(StringRef IDVal,
3283 const fltSemantics &Semantics) {
3284 auto parseOp = [&]() -> bool {
3285 APInt AsInt;
3286 if (checkForValidSection() || parseRealValue(Semantics, AsInt))
3287 return true;
3288 getStreamer().emitIntValue(AsInt.getLimitedValue(),
3289 AsInt.getBitWidth() / 8);
3290 return false;
3291 };
3292
3293 return parseMany(parseOp);
3294}
3295
3296/// parseDirectiveZero
3297/// ::= .zero expression
3298bool AsmParser::parseDirectiveZero() {
3299 SMLoc NumBytesLoc = Lexer.getLoc();
3300 const MCExpr *NumBytes;
3301 if (checkForValidSection() || parseExpression(NumBytes))
3302 return true;
3303
3304 int64_t Val = 0;
3305 if (getLexer().is(AsmToken::Comma)) {
3306 Lex();
3307 if (parseAbsoluteExpression(Val))
3308 return true;
3309 }
3310
3311 if (parseEOL())
3312 return true;
3313 getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);
3314
3315 return false;
3316}
3317
3318/// parseDirectiveFill
3319/// ::= .fill expression [ , expression [ , expression ] ]
3320bool AsmParser::parseDirectiveFill() {
3321 SMLoc NumValuesLoc = Lexer.getLoc();
3322 const MCExpr *NumValues;
3323 if (checkForValidSection() || parseExpression(NumValues))
3324 return true;
3325
3326 int64_t FillSize = 1;
3327 int64_t FillExpr = 0;
3328
3329 SMLoc SizeLoc, ExprLoc;
3330
3331 if (parseOptionalToken(AsmToken::Comma)) {
3332 SizeLoc = getTok().getLoc();
3333 if (parseAbsoluteExpression(FillSize))
3334 return true;
3335 if (parseOptionalToken(AsmToken::Comma)) {
3336 ExprLoc = getTok().getLoc();
3337 if (parseAbsoluteExpression(FillExpr))
3338 return true;
3339 }
3340 }
3341 if (parseEOL())
3342 return true;
3343
3344 if (FillSize < 0) {
3345 Warning(SizeLoc, "'.fill' directive with negative size has no effect");
3346 return false;
3347 }
3348 if (FillSize > 8) {
3349 Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
3350 FillSize = 8;
3351 }
3352
3353 if (!isUInt<32>(FillExpr) && FillSize > 4)
3354 Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
3355
3356 getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);
3357
3358 return false;
3359}
3360
3361/// parseDirectiveOrg
3362/// ::= .org expression [ , expression ]
3363bool AsmParser::parseDirectiveOrg() {
3364 const MCExpr *Offset;
3365 SMLoc OffsetLoc = Lexer.getLoc();
3366 if (checkForValidSection() || parseExpression(Offset))
3367 return true;
3368
3369 // Parse optional fill expression.
3370 int64_t FillExpr = 0;
3371 if (parseOptionalToken(AsmToken::Comma))
3372 if (parseAbsoluteExpression(FillExpr))
3373 return true;
3374 if (parseEOL())
3375 return true;
3376
3377 getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
3378 return false;
3379}
3380
3381/// parseDirectiveAlign
3382/// ::= {.align, ...} expression [ , expression [ , expression ]]
3383bool AsmParser::parseDirectiveAlign(bool IsPow2, uint8_t ValueSize) {
3384 SMLoc AlignmentLoc = getLexer().getLoc();
3385 int64_t Alignment;
3386 SMLoc MaxBytesLoc;
3387 bool HasFillExpr = false;
3388 int64_t FillExpr = 0;
3389 int64_t MaxBytesToFill = 0;
3390 SMLoc FillExprLoc;
3391
3392 auto parseAlign = [&]() -> bool {
3393 if (parseAbsoluteExpression(Alignment))
3394 return true;
3395 if (parseOptionalToken(AsmToken::Comma)) {
3396 // The fill expression can be omitted while specifying a maximum number of
3397 // alignment bytes, e.g:
3398 // .align 3,,4
3399 if (getTok().isNot(AsmToken::Comma)) {
3400 HasFillExpr = true;
3401 if (parseTokenLoc(FillExprLoc) || parseAbsoluteExpression(FillExpr))
3402 return true;
3403 }
3404 if (parseOptionalToken(AsmToken::Comma))
3405 if (parseTokenLoc(MaxBytesLoc) ||
3406 parseAbsoluteExpression(MaxBytesToFill))
3407 return true;
3408 }
3409 return parseEOL();
3410 };
3411
3412 if (checkForValidSection())
3413 return true;
3414 // Ignore empty '.p2align' directives for GNU-as compatibility
3415 if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
3416 Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
3417 return parseEOL();
3418 }
3419 if (parseAlign())
3420 return true;
3421
3422 // Always emit an alignment here even if we thrown an error.
3423 bool ReturnVal = false;
3424
3425 // Compute alignment in bytes.
3426 if (IsPow2) {
3427 // FIXME: Diagnose overflow.
3428 if (Alignment >= 32) {
3429 ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
3430 Alignment = 31;
3431 }
3432
3433 Alignment = 1ULL << Alignment;
3434 } else {
3435 // Reject alignments that aren't either a power of two or zero,
3436 // for gas compatibility. Alignment of zero is silently rounded
3437 // up to one.
3438 if (Alignment == 0)
3439 Alignment = 1;
3440 else if (!isPowerOf2_64(Alignment)) {
3441 ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
3442 Alignment = llvm::bit_floor<uint64_t>(Alignment);
3443 }
3444 if (!isUInt<32>(Alignment)) {
3445 ReturnVal |= Error(AlignmentLoc, "alignment must be smaller than 2**32");
3446 Alignment = 1u << 31;
3447 }
3448 }
3449
3450 // Diagnose non-sensical max bytes to align.
3451 if (MaxBytesLoc.isValid()) {
3452 if (MaxBytesToFill < 1) {
3453 ReturnVal |= Error(MaxBytesLoc,
3454 "alignment directive can never be satisfied in this "
3455 "many bytes, ignoring maximum bytes expression");
3456 MaxBytesToFill = 0;
3457 }
3458
3459 if (MaxBytesToFill >= Alignment) {
3460 Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
3461 "has no effect");
3462 MaxBytesToFill = 0;
3463 }
3464 }
3465
3466 const MCSection *Section = getStreamer().getCurrentSectionOnly();
3467 assert(Section && "must have section to emit alignment");
3468
3469 if (HasFillExpr && FillExpr != 0 && Section->isBssSection()) {
3470 ReturnVal |=
3471 Warning(FillExprLoc, "ignoring non-zero fill value in BSS section '" +
3472 Section->getName() + "'");
3473 FillExpr = 0;
3474 }
3475
3476 // Check whether we should use optimal code alignment for this .align
3477 // directive.
3478 if (MAI.useCodeAlign(*Section) && !HasFillExpr) {
3479 getStreamer().emitCodeAlignment(
3480 Align(Alignment), &getTargetParser().getSTI(), MaxBytesToFill);
3481 } else {
3482 // FIXME: Target specific behavior about how the "extra" bytes are filled.
3483 getStreamer().emitValueToAlignment(Align(Alignment), FillExpr, ValueSize,
3484 MaxBytesToFill);
3485 }
3486
3487 return ReturnVal;
3488}
3489
3490bool AsmParser::parseDirectivePrefAlign() {
3491 SMLoc AlignmentLoc = getLexer().getLoc();
3492 int64_t Log2Alignment;
3493 if (checkForValidSection() || parseAbsoluteExpression(Log2Alignment))
3494 return true;
3495
3496 if (Log2Alignment < 0 || Log2Alignment > 63)
3497 return Error(AlignmentLoc, "log2 alignment must be in the range [0, 63]");
3498
3499 // Parse end symbol: .prefalign N, sym
3500 SMLoc SymLoc = getLexer().getLoc();
3501 if (parseComma())
3502 return true;
3503 StringRef Name;
3504 SymLoc = getLexer().getLoc();
3505 if (parseIdentifier(Name))
3506 return Error(SymLoc, "expected symbol name");
3507 MCSymbol *End = getContext().getOrCreateSymbol(Name);
3508
3509 // Parse fill operand: integer byte [0, 255] or "nop".
3510 SMLoc FillLoc = getLexer().getLoc();
3511 if (parseComma())
3512 return true;
3513
3514 bool EmitNops = false;
3515 uint8_t Fill = 0;
3516 SMLoc FillLoc2 = getLexer().getLoc();
3517 if (getLexer().is(AsmToken::Identifier) &&
3518 getLexer().getTok().getIdentifier() == "nop") {
3519 EmitNops = true;
3520 Lex();
3521 } else {
3522 int64_t FillVal;
3523 if (parseAbsoluteExpression(FillVal))
3524 return true;
3525 if (FillVal < 0 || FillVal > 255)
3526 return Error(FillLoc2, "fill value must be in range [0, 255]");
3527 Fill = static_cast<uint8_t>(FillVal);
3528 }
3529
3530 if (parseEOL())
3531 return true;
3532 if ((EmitNops || Fill != 0) &&
3533 getStreamer().getCurrentSectionOnly()->isBssSection())
3534 return Error(FillLoc, "non-zero fill in BSS section '" +
3535 getStreamer().getCurrentSectionOnly()->getName() +
3536 "'");
3537
3538 getStreamer().emitPrefAlign(Align(1ULL << Log2Alignment), *End, EmitNops,
3539 Fill, getTargetParser().getSTI());
3540 return false;
3541}
3542
3543/// parseDirectiveFile
3544/// ::= .file filename
3545/// ::= .file number [directory] filename [md5 checksum] [source source-text]
3546bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
3547 // FIXME: I'm not sure what this is.
3548 int64_t FileNumber = -1;
3549 if (getLexer().is(AsmToken::Integer)) {
3550 FileNumber = getTok().getIntVal();
3551 Lex();
3552
3553 if (FileNumber < 0)
3554 return TokError("negative file number");
3555 }
3556
3557 std::string Path;
3558
3559 // Usually the directory and filename together, otherwise just the directory.
3560 // Allow the strings to have escaped octal character sequence.
3561 if (parseEscapedString(Path))
3562 return true;
3563
3564 StringRef Directory;
3565 StringRef Filename;
3566 std::string FilenameData;
3567 if (getLexer().is(AsmToken::String)) {
3568 if (check(FileNumber == -1,
3569 "explicit path specified, but no file number") ||
3570 parseEscapedString(FilenameData))
3571 return true;
3572 Filename = FilenameData;
3573 Directory = Path;
3574 } else {
3575 Filename = Path;
3576 }
3577
3578 uint64_t MD5Hi, MD5Lo;
3579 bool HasMD5 = false;
3580
3581 std::optional<StringRef> Source;
3582 bool HasSource = false;
3583 std::string SourceString;
3584
3585 while (!parseOptionalToken(AsmToken::EndOfStatement)) {
3586 StringRef Keyword;
3587 if (check(getTok().isNot(AsmToken::Identifier),
3588 "unexpected token in '.file' directive") ||
3589 parseIdentifier(Keyword))
3590 return true;
3591 if (Keyword == "md5") {
3592 HasMD5 = true;
3593 if (check(FileNumber == -1,
3594 "MD5 checksum specified, but no file number") ||
3595 parseHexOcta(*this, MD5Hi, MD5Lo))
3596 return true;
3597 } else if (Keyword == "source") {
3598 HasSource = true;
3599 if (check(FileNumber == -1,
3600 "source specified, but no file number") ||
3601 check(getTok().isNot(AsmToken::String),
3602 "unexpected token in '.file' directive") ||
3603 parseEscapedString(SourceString))
3604 return true;
3605 } else {
3606 return TokError("unexpected token in '.file' directive");
3607 }
3608 }
3609
3610 if (FileNumber == -1) {
3611 // Ignore the directive if there is no number and the target doesn't support
3612 // numberless .file directives. This allows some portability of assembler
3613 // between different object file formats.
3614 if (getContext().getAsmInfo().hasSingleParameterDotFile())
3615 getStreamer().emitFileDirective(Filename);
3616 } else {
3617 // In case there is a -g option as well as debug info from directive .file,
3618 // we turn off the -g option, directly use the existing debug info instead.
3619 // Throw away any implicit file table for the assembler source.
3620 if (Ctx.getGenDwarfForAssembly()) {
3622 Ctx.setGenDwarfForAssembly(false);
3623 }
3624
3625 std::optional<MD5::MD5Result> CKMem;
3626 if (HasMD5) {
3627 MD5::MD5Result Sum;
3628 for (unsigned i = 0; i != 8; ++i) {
3629 Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
3630 Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
3631 }
3632 CKMem = Sum;
3633 }
3634 if (HasSource) {
3635 char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
3636 memcpy(SourceBuf, SourceString.data(), SourceString.size());
3637 Source = StringRef(SourceBuf, SourceString.size());
3638 }
3639 if (FileNumber == 0) {
3640 // Upgrade to Version 5 for assembly actions like clang -c a.s.
3641 if (Ctx.getDwarfVersion() < 5)
3642 Ctx.setDwarfVersion(5);
3643 getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
3644 } else {
3645 Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
3646 FileNumber, Directory, Filename, CKMem, Source);
3647 if (!FileNumOrErr)
3648 return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
3649 }
3650 // Alert the user if there are some .file directives with MD5 and some not.
3651 // But only do that once.
3652 if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
3653 ReportedInconsistentMD5 = true;
3654 return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
3655 }
3656 }
3657
3658 return false;
3659}
3660
3661/// parseDirectiveLine
3662/// ::= .line [number]
3663bool AsmParser::parseDirectiveLine() {
3664 parseOptionalToken(AsmToken::Integer);
3665 return parseEOL();
3666}
3667
3668/// parseDirectiveLoc
3669/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
3670/// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
3671/// The first number is a file number, must have been previously assigned with
3672/// a .file directive, the second number is the line number and optionally the
3673/// third number is a column position (zero if not specified). The remaining
3674/// optional items are .loc sub-directives.
3675bool AsmParser::parseDirectiveLoc() {
3676 int64_t FileNumber = 0, LineNumber = 0;
3677 SMLoc Loc = getTok().getLoc();
3678 if (parseIntToken(FileNumber) ||
3679 check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
3680 "file number less than one in '.loc' directive") ||
3681 check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
3682 "unassigned file number in '.loc' directive"))
3683 return true;
3684
3685 // optional
3686 if (getLexer().is(AsmToken::Integer)) {
3687 LineNumber = getTok().getIntVal();
3688 if (LineNumber < 0)
3689 return TokError("line number less than zero in '.loc' directive");
3690 Lex();
3691 }
3692
3693 int64_t ColumnPos = 0;
3694 if (getLexer().is(AsmToken::Integer)) {
3695 ColumnPos = getTok().getIntVal();
3696 if (ColumnPos < 0)
3697 return TokError("column position less than zero in '.loc' directive");
3698 Lex();
3699 }
3700
3701 auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
3702 unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
3703 unsigned Isa = 0;
3704 int64_t Discriminator = 0;
3705
3706 auto parseLocOp = [&]() -> bool {
3707 StringRef Name;
3708 SMLoc Loc = getTok().getLoc();
3709 if (parseIdentifier(Name))
3710 return TokError("unexpected token in '.loc' directive");
3711
3712 if (Name == "basic_block")
3714 else if (Name == "prologue_end")
3716 else if (Name == "epilogue_begin")
3718 else if (Name == "is_stmt") {
3719 Loc = getTok().getLoc();
3720 const MCExpr *Value;
3721 if (parseExpression(Value))
3722 return true;
3723 // The expression must be the constant 0 or 1.
3724 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3725 int Value = MCE->getValue();
3726 if (Value == 0)
3727 Flags &= ~DWARF2_FLAG_IS_STMT;
3728 else if (Value == 1)
3730 else
3731 return Error(Loc, "is_stmt value not 0 or 1");
3732 } else {
3733 return Error(Loc, "is_stmt value not the constant value of 0 or 1");
3734 }
3735 } else if (Name == "isa") {
3736 Loc = getTok().getLoc();
3737 const MCExpr *Value;
3738 if (parseExpression(Value))
3739 return true;
3740 // The expression must be a constant greater or equal to 0.
3741 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3742 int Value = MCE->getValue();
3743 if (Value < 0)
3744 return Error(Loc, "isa number less than zero");
3745 Isa = Value;
3746 } else {
3747 return Error(Loc, "isa number not a constant value");
3748 }
3749 } else if (Name == "discriminator") {
3750 if (parseAbsoluteExpression(Discriminator))
3751 return true;
3752 } else {
3753 return Error(Loc, "unknown sub-directive in '.loc' directive");
3754 }
3755 return false;
3756 };
3757
3758 if (parseMany(parseLocOp, false /*hasComma*/))
3759 return true;
3760
3761 getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
3762 Isa, Discriminator, StringRef());
3763
3764 return false;
3765}
3766
3767/// parseDirectiveLoc
3768/// ::= .loc_label label
3769bool AsmParser::parseDirectiveLocLabel(SMLoc DirectiveLoc) {
3770 StringRef Name;
3771 DirectiveLoc = Lexer.getLoc();
3772 if (parseIdentifier(Name))
3773 return TokError("expected identifier");
3774 if (parseEOL())
3775 return true;
3776 getStreamer().emitDwarfLocLabelDirective(DirectiveLoc, Name);
3777 return false;
3778}
3779
3780/// parseDirectiveStabs
3781/// ::= .stabs string, number, number, number
3782bool AsmParser::parseDirectiveStabs() {
3783 return TokError("unsupported directive '.stabs'");
3784}
3785
3786/// parseDirectiveCVFile
3787/// ::= .cv_file number filename [checksum] [checksumkind]
3788bool AsmParser::parseDirectiveCVFile() {
3789 SMLoc FileNumberLoc = getTok().getLoc();
3790 int64_t FileNumber;
3791 std::string Filename;
3792 std::string Checksum;
3793 int64_t ChecksumKind = 0;
3794
3795 if (parseIntToken(FileNumber, "expected file number") ||
3796 check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
3797 check(getTok().isNot(AsmToken::String),
3798 "unexpected token in '.cv_file' directive") ||
3799 parseEscapedString(Filename))
3800 return true;
3801 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
3802 if (check(getTok().isNot(AsmToken::String),
3803 "unexpected token in '.cv_file' directive") ||
3804 parseEscapedString(Checksum) ||
3805 parseIntToken(ChecksumKind,
3806 "expected checksum kind in '.cv_file' directive") ||
3807 parseEOL())
3808 return true;
3809 }
3810
3811 Checksum = fromHex(Checksum);
3812 void *CKMem = Ctx.allocate(Checksum.size(), 1);
3813 memcpy(CKMem, Checksum.data(), Checksum.size());
3814 ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
3815 Checksum.size());
3816
3817 if (!getStreamer().emitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
3818 static_cast<uint8_t>(ChecksumKind)))
3819 return Error(FileNumberLoc, "file number already allocated");
3820
3821 return false;
3822}
3823
3824bool AsmParser::parseCVFunctionId(int64_t &FunctionId,
3825 StringRef DirectiveName) {
3826 SMLoc Loc;
3827 return parseTokenLoc(Loc) ||
3828 parseIntToken(FunctionId, "expected function id") ||
3829 check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
3830 "expected function id within range [0, UINT_MAX)");
3831}
3832
3833bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
3834 SMLoc Loc;
3835 return parseTokenLoc(Loc) ||
3836 parseIntToken(FileNumber, "expected file number") ||
3837 check(FileNumber < 1, Loc,
3838 "file number less than one in '" + DirectiveName +
3839 "' directive") ||
3840 check(!getCVContext().isValidFileNumber(FileNumber), Loc,
3841 "unassigned file number in '" + DirectiveName + "' directive");
3842}
3843
3844/// parseDirectiveCVFuncId
3845/// ::= .cv_func_id FunctionId
3846///
3847/// Introduces a function ID that can be used with .cv_loc.
3848bool AsmParser::parseDirectiveCVFuncId() {
3849 SMLoc FunctionIdLoc = getTok().getLoc();
3850 int64_t FunctionId;
3851
3852 if (parseCVFunctionId(FunctionId, ".cv_func_id") || parseEOL())
3853 return true;
3854
3855 if (!getStreamer().emitCVFuncIdDirective(FunctionId))
3856 return Error(FunctionIdLoc, "function id already allocated");
3857
3858 return false;
3859}
3860
3861/// parseDirectiveCVInlineSiteId
3862/// ::= .cv_inline_site_id FunctionId
3863/// "within" IAFunc
3864/// "inlined_at" IAFile IALine [IACol]
3865///
3866/// Introduces a function ID that can be used with .cv_loc. Includes "inlined
3867/// at" source location information for use in the line table of the caller,
3868/// whether the caller is a real function or another inlined call site.
3869bool AsmParser::parseDirectiveCVInlineSiteId() {
3870 SMLoc FunctionIdLoc = getTok().getLoc();
3871 int64_t FunctionId;
3872 int64_t IAFunc;
3873 int64_t IAFile;
3874 int64_t IALine;
3875 int64_t IACol = 0;
3876
3877 // FunctionId
3878 if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
3879 return true;
3880
3881 // "within"
3882 if (check((getLexer().isNot(AsmToken::Identifier) ||
3883 getTok().getIdentifier() != "within"),
3884 "expected 'within' identifier in '.cv_inline_site_id' directive"))
3885 return true;
3886 Lex();
3887
3888 // IAFunc
3889 if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
3890 return true;
3891
3892 // "inlined_at"
3893 if (check((getLexer().isNot(AsmToken::Identifier) ||
3894 getTok().getIdentifier() != "inlined_at"),
3895 "expected 'inlined_at' identifier in '.cv_inline_site_id' "
3896 "directive") )
3897 return true;
3898 Lex();
3899
3900 // IAFile IALine
3901 if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
3902 parseIntToken(IALine, "expected line number after 'inlined_at'"))
3903 return true;
3904
3905 // [IACol]
3906 if (getLexer().is(AsmToken::Integer)) {
3907 IACol = getTok().getIntVal();
3908 Lex();
3909 }
3910
3911 if (parseEOL())
3912 return true;
3913
3914 if (!getStreamer().emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
3915 IALine, IACol, FunctionIdLoc))
3916 return Error(FunctionIdLoc, "function id already allocated");
3917
3918 return false;
3919}
3920
3921/// parseDirectiveCVLoc
3922/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
3923/// [is_stmt VALUE]
3924/// The first number is a file number, must have been previously assigned with
3925/// a .file directive, the second number is the line number and optionally the
3926/// third number is a column position (zero if not specified). The remaining
3927/// optional items are .loc sub-directives.
3928bool AsmParser::parseDirectiveCVLoc() {
3929 SMLoc DirectiveLoc = getTok().getLoc();
3930 int64_t FunctionId, FileNumber;
3931 if (parseCVFunctionId(FunctionId, ".cv_loc") ||
3932 parseCVFileId(FileNumber, ".cv_loc"))
3933 return true;
3934
3935 int64_t LineNumber = 0;
3936 if (getLexer().is(AsmToken::Integer)) {
3937 LineNumber = getTok().getIntVal();
3938 if (LineNumber < 0)
3939 return TokError("line number less than zero in '.cv_loc' directive");
3940 Lex();
3941 }
3942
3943 int64_t ColumnPos = 0;
3944 if (getLexer().is(AsmToken::Integer)) {
3945 ColumnPos = getTok().getIntVal();
3946 if (ColumnPos < 0)
3947 return TokError("column position less than zero in '.cv_loc' directive");
3948 Lex();
3949 }
3950
3951 bool PrologueEnd = false;
3952 uint64_t IsStmt = 0;
3953
3954 auto parseOp = [&]() -> bool {
3955 StringRef Name;
3956 SMLoc Loc = getTok().getLoc();
3957 if (parseIdentifier(Name))
3958 return TokError("unexpected token in '.cv_loc' directive");
3959 if (Name == "prologue_end")
3960 PrologueEnd = true;
3961 else if (Name == "is_stmt") {
3962 Loc = getTok().getLoc();
3963 const MCExpr *Value;
3964 if (parseExpression(Value))
3965 return true;
3966 // The expression must be the constant 0 or 1.
3967 IsStmt = ~0ULL;
3968 if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
3969 IsStmt = MCE->getValue();
3970
3971 if (IsStmt > 1)
3972 return Error(Loc, "is_stmt value not 0 or 1");
3973 } else {
3974 return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
3975 }
3976 return false;
3977 };
3978
3979 if (parseMany(parseOp, false /*hasComma*/))
3980 return true;
3981
3982 getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
3983 ColumnPos, PrologueEnd, IsStmt, StringRef(),
3984 DirectiveLoc);
3985 return false;
3986}
3987
3988/// parseDirectiveCVLinetable
3989/// ::= .cv_linetable FunctionId, FnStart, FnEnd
3990bool AsmParser::parseDirectiveCVLinetable() {
3991 int64_t FunctionId;
3992 MCSymbol *FnStartSym, *FnEndSym;
3993 SMLoc Loc = getTok().getLoc();
3994 if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() ||
3995 parseTokenLoc(Loc) ||
3996 check(parseSymbol(FnStartSym), Loc, "expected identifier in directive") ||
3997 parseComma() || parseTokenLoc(Loc) ||
3998 check(parseSymbol(FnEndSym), Loc, "expected identifier in directive"))
3999 return true;
4000
4001 getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
4002 return false;
4003}
4004
4005/// parseDirectiveCVInlineLinetable
4006/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
4007bool AsmParser::parseDirectiveCVInlineLinetable() {
4008 int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
4009 MCSymbol *FnStartSym, *FnEndSym;
4010 SMLoc Loc = getTok().getLoc();
4011 if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
4012 parseTokenLoc(Loc) ||
4013 parseIntToken(SourceFileId, "expected SourceField") ||
4014 check(SourceFileId <= 0, Loc, "File id less than zero") ||
4015 parseTokenLoc(Loc) ||
4016 parseIntToken(SourceLineNum, "expected SourceLineNum") ||
4017 check(SourceLineNum < 0, Loc, "Line number less than zero") ||
4018 parseTokenLoc(Loc) ||
4019 check(parseSymbol(FnStartSym), Loc, "expected identifier") ||
4020 parseTokenLoc(Loc) ||
4021 check(parseSymbol(FnEndSym), Loc, "expected identifier"))
4022 return true;
4023
4024 if (parseEOL())
4025 return true;
4026
4027 getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
4028 SourceLineNum, FnStartSym,
4029 FnEndSym);
4030 return false;
4031}
4032
4033void AsmParser::initializeCVDefRangeTypeMap() {
4034 CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
4035 CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
4036 CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
4037 CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
4038 CVDefRangeTypeMap["reg_rel_indir"] = CVDR_DEFRANGE_REGISTER_REL_INDIR;
4039}
4040
4041/// parseDirectiveCVDefRange
4042/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
4043bool AsmParser::parseDirectiveCVDefRange() {
4044 SMLoc Loc;
4045 std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
4046 while (getLexer().is(AsmToken::Identifier)) {
4047 Loc = getLexer().getLoc();
4048 MCSymbol *GapStartSym;
4049 if (parseSymbol(GapStartSym))
4050 return Error(Loc, "expected identifier in directive");
4051
4052 Loc = getLexer().getLoc();
4053 MCSymbol *GapEndSym;
4054 if (parseSymbol(GapEndSym))
4055 return Error(Loc, "expected identifier in directive");
4056
4057 Ranges.push_back({GapStartSym, GapEndSym});
4058 }
4059
4060 StringRef CVDefRangeTypeStr;
4061 if (parseToken(
4063 "expected comma before def_range type in .cv_def_range directive") ||
4064 parseIdentifier(CVDefRangeTypeStr))
4065 return Error(Loc, "expected def_range type in directive");
4066
4068 CVDefRangeTypeMap.find(CVDefRangeTypeStr);
4069 CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
4070 ? CVDR_DEFRANGE
4071 : CVTypeIt->getValue();
4072 switch (CVDRType) {
4073 case CVDR_DEFRANGE_REGISTER: {
4074 int64_t DRRegister;
4075 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4076 ".cv_def_range directive") ||
4077 parseAbsoluteExpression(DRRegister))
4078 return Error(Loc, "expected register number");
4079
4080 codeview::DefRangeRegisterHeader DRHdr;
4081 DRHdr.Register = DRRegister;
4082 DRHdr.MayHaveNoName = 0;
4083 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4084 break;
4085 }
4086 case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
4087 int64_t DROffset;
4088 if (parseToken(AsmToken::Comma,
4089 "expected comma before offset in .cv_def_range directive") ||
4090 parseAbsoluteExpression(DROffset))
4091 return Error(Loc, "expected offset value");
4092
4093 codeview::DefRangeFramePointerRelHeader DRHdr;
4094 DRHdr.Offset = DROffset;
4095 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4096 break;
4097 }
4098 case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
4099 int64_t DRRegister;
4100 int64_t DROffsetInParent;
4101 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4102 ".cv_def_range directive") ||
4103 parseAbsoluteExpression(DRRegister))
4104 return Error(Loc, "expected register number");
4105 if (parseToken(AsmToken::Comma,
4106 "expected comma before offset in .cv_def_range directive") ||
4107 parseAbsoluteExpression(DROffsetInParent))
4108 return Error(Loc, "expected offset value");
4109
4110 codeview::DefRangeSubfieldRegisterHeader DRHdr;
4111 DRHdr.Register = DRRegister;
4112 DRHdr.MayHaveNoName = 0;
4113 DRHdr.OffsetInParent = DROffsetInParent;
4114 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4115 break;
4116 }
4117 case CVDR_DEFRANGE_REGISTER_REL: {
4118 int64_t DRRegister;
4119 int64_t DRFlags;
4120 int64_t DRBasePointerOffset;
4121 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4122 ".cv_def_range directive") ||
4123 parseAbsoluteExpression(DRRegister))
4124 return Error(Loc, "expected register value");
4125 if (parseToken(
4127 "expected comma before flag value in .cv_def_range directive") ||
4128 parseAbsoluteExpression(DRFlags))
4129 return Error(Loc, "expected flag value");
4130 if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
4131 "in .cv_def_range directive") ||
4132 parseAbsoluteExpression(DRBasePointerOffset))
4133 return Error(Loc, "expected base pointer offset value");
4134
4135 codeview::DefRangeRegisterRelHeader DRHdr;
4136 DRHdr.Register = DRRegister;
4137 DRHdr.Flags = DRFlags;
4138 DRHdr.BasePointerOffset = DRBasePointerOffset;
4139 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4140 break;
4141 }
4142 case CVDR_DEFRANGE_REGISTER_REL_INDIR: {
4143 int64_t DRRegister;
4144 int64_t DRFlags;
4145 int64_t DRBasePointerOffset;
4146 int64_t DROffsetInUdt;
4147 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4148 ".cv_def_range directive") ||
4149 parseAbsoluteExpression(DRRegister))
4150 return Error(Loc, "expected register value");
4151 if (parseToken(
4153 "expected comma before flag value in .cv_def_range directive") ||
4154 parseAbsoluteExpression(DRFlags))
4155 return Error(Loc, "expected flag value");
4156 if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
4157 "in .cv_def_range directive") ||
4158 parseAbsoluteExpression(DRBasePointerOffset))
4159 return Error(Loc, "expected base pointer offset value");
4160 if (parseToken(AsmToken::Comma, "expected comma before offset in UDT "
4161 "in .cv_def_range directive") ||
4162 parseAbsoluteExpression(DROffsetInUdt))
4163 return Error(Loc, "expected offset in UDT value");
4164
4165 codeview::DefRangeRegisterRelIndirHeader DRHdr;
4166 DRHdr.Register = DRRegister;
4167 DRHdr.Flags = DRFlags;
4168 DRHdr.BasePointerOffset = DRBasePointerOffset;
4169 DRHdr.OffsetInUdt = DROffsetInUdt;
4170 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4171 break;
4172 }
4173 default:
4174 return Error(Loc, "unexpected def_range type in .cv_def_range directive");
4175 }
4176 return true;
4177}
4178
4179/// parseDirectiveCVString
4180/// ::= .cv_stringtable "string"
4181bool AsmParser::parseDirectiveCVString() {
4182 std::string Data;
4183 if (checkForValidSection() || parseEscapedString(Data))
4184 return true;
4185
4186 // Put the string in the table and emit the offset.
4187 std::pair<StringRef, unsigned> Insertion =
4188 getCVContext().addToStringTable(Data);
4189 getStreamer().emitInt32(Insertion.second);
4190 return false;
4191}
4192
4193/// parseDirectiveCVStringTable
4194/// ::= .cv_stringtable
4195bool AsmParser::parseDirectiveCVStringTable() {
4196 getStreamer().emitCVStringTableDirective();
4197 return false;
4198}
4199
4200/// parseDirectiveCVFileChecksums
4201/// ::= .cv_filechecksums
4202bool AsmParser::parseDirectiveCVFileChecksums() {
4203 getStreamer().emitCVFileChecksumsDirective();
4204 return false;
4205}
4206
4207/// parseDirectiveCVFileChecksumOffset
4208/// ::= .cv_filechecksumoffset fileno
4209bool AsmParser::parseDirectiveCVFileChecksumOffset() {
4210 int64_t FileNo;
4211 if (parseIntToken(FileNo))
4212 return true;
4213 if (parseEOL())
4214 return true;
4215 getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
4216 return false;
4217}
4218
4219/// parseDirectiveCVFPOData
4220/// ::= .cv_fpo_data procsym
4221bool AsmParser::parseDirectiveCVFPOData() {
4222 SMLoc DirLoc = getLexer().getLoc();
4223 MCSymbol *ProcSym;
4224 if (parseSymbol(ProcSym))
4225 return TokError("expected symbol name");
4226 if (parseEOL())
4227 return true;
4228 getStreamer().emitCVFPOData(ProcSym, DirLoc);
4229 return false;
4230}
4231
4232/// parseDirectiveCFISections
4233/// ::= .cfi_sections section [, section][, section]
4234bool AsmParser::parseDirectiveCFISections() {
4235 StringRef Name;
4236 bool EH = false;
4237 bool Debug = false;
4238 bool SFrame = false;
4239
4240 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4241 for (;;) {
4242 if (parseIdentifier(Name))
4243 return TokError("expected .eh_frame, .debug_frame, or .sframe");
4244 if (Name == ".eh_frame")
4245 EH = true;
4246 else if (Name == ".debug_frame")
4247 Debug = true;
4248 else if (Name == ".sframe")
4249 SFrame = true;
4250 if (parseOptionalToken(AsmToken::EndOfStatement))
4251 break;
4252 if (parseComma())
4253 return true;
4254 }
4255 }
4256 getStreamer().emitCFISections(EH, Debug, SFrame);
4257 return false;
4258}
4259
4260/// parseDirectiveCFIStartProc
4261/// ::= .cfi_startproc [simple]
4262bool AsmParser::parseDirectiveCFIStartProc() {
4263 CFIStartProcLoc = StartTokLoc;
4264
4265 StringRef Simple;
4266 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4267 if (check(parseIdentifier(Simple) || Simple != "simple",
4268 "unexpected token") ||
4269 parseEOL())
4270 return true;
4271 }
4272
4273 // TODO(kristina): Deal with a corner case of incorrect diagnostic context
4274 // being produced if this directive is emitted as part of preprocessor macro
4275 // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
4276 // Tools like llvm-mc on the other hand are not affected by it, and report
4277 // correct context information.
4278 getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
4279 return false;
4280}
4281
4282/// parseDirectiveCFIEndProc
4283/// ::= .cfi_endproc
4284bool AsmParser::parseDirectiveCFIEndProc() {
4285 CFIStartProcLoc = std::nullopt;
4286
4287 if (parseEOL())
4288 return true;
4289
4290 getStreamer().emitCFIEndProc();
4291 return false;
4292}
4293
4294/// parse register name or number.
4295bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
4296 SMLoc DirectiveLoc) {
4297 MCRegister RegNo;
4298
4299 if (getLexer().isNot(AsmToken::Integer)) {
4300 if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc))
4301 return true;
4302 Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
4303 } else
4304 return parseAbsoluteExpression(Register);
4305
4306 return false;
4307}
4308
4309/// parseDirectiveCFIDefCfa
4310/// ::= .cfi_def_cfa register, offset
4311bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
4312 int64_t Register = 0, Offset = 0;
4313 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4314 parseAbsoluteExpression(Offset) || parseEOL())
4315 return true;
4316
4317 getStreamer().emitCFIDefCfa(Register, Offset, DirectiveLoc);
4318 return false;
4319}
4320
4321/// parseDirectiveCFIDefCfaOffset
4322/// ::= .cfi_def_cfa_offset offset
4323bool AsmParser::parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc) {
4324 int64_t Offset = 0;
4325 if (parseAbsoluteExpression(Offset) || parseEOL())
4326 return true;
4327
4328 getStreamer().emitCFIDefCfaOffset(Offset, DirectiveLoc);
4329 return false;
4330}
4331
4332/// parseDirectiveCFIRegister
4333/// ::= .cfi_register register, register
4334bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
4335 int64_t Register1 = 0, Register2 = 0;
4336 if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || parseComma() ||
4337 parseRegisterOrRegisterNumber(Register2, DirectiveLoc) || parseEOL())
4338 return true;
4339
4340 getStreamer().emitCFIRegister(Register1, Register2, DirectiveLoc);
4341 return false;
4342}
4343
4344/// parseDirectiveCFIWindowSave
4345/// ::= .cfi_window_save
4346bool AsmParser::parseDirectiveCFIWindowSave(SMLoc DirectiveLoc) {
4347 if (parseEOL())
4348 return true;
4349 getStreamer().emitCFIWindowSave(DirectiveLoc);
4350 return false;
4351}
4352
4353/// parseDirectiveCFIAdjustCfaOffset
4354/// ::= .cfi_adjust_cfa_offset adjustment
4355bool AsmParser::parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc) {
4356 int64_t Adjustment = 0;
4357 if (parseAbsoluteExpression(Adjustment) || parseEOL())
4358 return true;
4359
4360 getStreamer().emitCFIAdjustCfaOffset(Adjustment, DirectiveLoc);
4361 return false;
4362}
4363
4364/// parseDirectiveCFIDefCfaRegister
4365/// ::= .cfi_def_cfa_register register
4366bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
4367 int64_t Register = 0;
4368 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4369 return true;
4370
4371 getStreamer().emitCFIDefCfaRegister(Register, DirectiveLoc);
4372 return false;
4373}
4374
4375/// parseDirectiveCFILLVMDefAspaceCfa
4376/// ::= .cfi_llvm_def_aspace_cfa register, offset, address_space
4377bool AsmParser::parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc) {
4378 int64_t Register = 0, Offset = 0, AddressSpace = 0;
4379 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4380 parseAbsoluteExpression(Offset) || parseComma() ||
4381 parseAbsoluteExpression(AddressSpace) || parseEOL())
4382 return true;
4383
4384 getStreamer().emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace,
4385 DirectiveLoc);
4386 return false;
4387}
4388
4389/// parseDirectiveCFIOffset
4390/// ::= .cfi_offset register, offset
4391bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
4392 int64_t Register = 0;
4393 int64_t Offset = 0;
4394
4395 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4396 parseAbsoluteExpression(Offset) || parseEOL())
4397 return true;
4398
4399 getStreamer().emitCFIOffset(Register, Offset, DirectiveLoc);
4400 return false;
4401}
4402
4403/// parseDirectiveCFIRelOffset
4404/// ::= .cfi_rel_offset register, offset
4405bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
4406 int64_t Register = 0, Offset = 0;
4407
4408 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4409 parseAbsoluteExpression(Offset) || parseEOL())
4410 return true;
4411
4412 getStreamer().emitCFIRelOffset(Register, Offset, DirectiveLoc);
4413 return false;
4414}
4415
4416static bool isValidEncoding(int64_t Encoding) {
4417 if (Encoding & ~0xff)
4418 return false;
4419
4420 if (Encoding == dwarf::DW_EH_PE_omit)
4421 return true;
4422
4423 const unsigned Format = Encoding & 0xf;
4424 if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
4425 Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
4426 Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
4427 Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
4428 return false;
4429
4430 const unsigned Application = Encoding & 0x70;
4431 if (Application != dwarf::DW_EH_PE_absptr &&
4432 Application != dwarf::DW_EH_PE_pcrel)
4433 return false;
4434
4435 return true;
4436}
4437
4438/// parseDirectiveCFIPersonalityOrLsda
4439/// IsPersonality true for cfi_personality, false for cfi_lsda
4440/// ::= .cfi_personality encoding, [symbol_name]
4441/// ::= .cfi_lsda encoding, [symbol_name]
4442bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
4443 int64_t Encoding = 0;
4444 if (parseAbsoluteExpression(Encoding))
4445 return true;
4446 if (Encoding == dwarf::DW_EH_PE_omit)
4447 return false;
4448
4449 MCSymbol *Sym;
4450 if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
4451 parseComma() ||
4452 check(parseSymbol(Sym), "expected identifier in directive") || parseEOL())
4453 return true;
4454
4455 if (IsPersonality)
4456 getStreamer().emitCFIPersonality(Sym, Encoding);
4457 else
4458 getStreamer().emitCFILsda(Sym, Encoding);
4459 return false;
4460}
4461
4462/// parseDirectiveCFIRememberState
4463/// ::= .cfi_remember_state
4464bool AsmParser::parseDirectiveCFIRememberState(SMLoc DirectiveLoc) {
4465 if (parseEOL())
4466 return true;
4467 getStreamer().emitCFIRememberState(DirectiveLoc);
4468 return false;
4469}
4470
4471/// parseDirectiveCFIRestoreState
4472/// ::= .cfi_remember_state
4473bool AsmParser::parseDirectiveCFIRestoreState(SMLoc DirectiveLoc) {
4474 if (parseEOL())
4475 return true;
4476 getStreamer().emitCFIRestoreState(DirectiveLoc);
4477 return false;
4478}
4479
4480/// parseDirectiveCFISameValue
4481/// ::= .cfi_same_value register
4482bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
4483 int64_t Register = 0;
4484
4485 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4486 return true;
4487
4488 getStreamer().emitCFISameValue(Register, DirectiveLoc);
4489 return false;
4490}
4491
4492/// parseDirectiveCFIRestore
4493/// ::= .cfi_restore register
4494bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
4495 int64_t Register = 0;
4496 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4497 return true;
4498
4499 getStreamer().emitCFIRestore(Register, DirectiveLoc);
4500 return false;
4501}
4502
4503/// parseDirectiveCFIEscape
4504/// ::= .cfi_escape expression[,...]
4505bool AsmParser::parseDirectiveCFIEscape(SMLoc DirectiveLoc) {
4506 std::string Values;
4507 int64_t CurrValue;
4508 if (parseAbsoluteExpression(CurrValue))
4509 return true;
4510
4511 Values.push_back((uint8_t)CurrValue);
4512
4513 while (getLexer().is(AsmToken::Comma)) {
4514 Lex();
4515
4516 if (parseAbsoluteExpression(CurrValue))
4517 return true;
4518
4519 Values.push_back((uint8_t)CurrValue);
4520 }
4521
4522 getStreamer().emitCFIEscape(Values, DirectiveLoc);
4523 return false;
4524}
4525
4526/// parseDirectiveCFIReturnColumn
4527/// ::= .cfi_return_column register
4528bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
4529 int64_t Register = 0;
4530 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4531 return true;
4532 getStreamer().emitCFIReturnColumn(Register);
4533 return false;
4534}
4535
4536/// parseDirectiveCFISignalFrame
4537/// ::= .cfi_signal_frame
4538bool AsmParser::parseDirectiveCFISignalFrame(SMLoc DirectiveLoc) {
4539 if (parseEOL())
4540 return true;
4541
4542 getStreamer().emitCFISignalFrame();
4543 return false;
4544}
4545
4546/// parseDirectiveCFIUndefined
4547/// ::= .cfi_undefined register
4548bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
4549 int64_t Register = 0;
4550
4551 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4552 return true;
4553
4554 getStreamer().emitCFIUndefined(Register, DirectiveLoc);
4555 return false;
4556}
4557
4558/// parseDirectiveCFILLVMRegisterPair
4559/// ::= .cfi_llvm_register_pair reg, r1, r1size, r2, r2size
4560bool AsmParser::parseDirectiveCFILLVMRegisterPair(SMLoc DirectiveLoc) {
4561 int64_t Register = 0;
4562 int64_t R1 = 0, R2 = 0;
4563 int64_t R1Size = 0, R2Size = 0;
4564
4565 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4566 parseRegisterOrRegisterNumber(R1, DirectiveLoc) || parseComma() ||
4567 parseAbsoluteExpression(R1Size) || parseComma() ||
4568 parseRegisterOrRegisterNumber(R2, DirectiveLoc) || parseComma() ||
4569 parseAbsoluteExpression(R2Size) || parseEOL())
4570 return true;
4571
4572 getStreamer().emitCFILLVMRegisterPair(Register, R1, R1Size, R2, R2Size,
4573 DirectiveLoc);
4574 return false;
4575}
4576
4577/// parseDirectiveCFILLVMVectorRegisters
4578/// ::= .cfi_llvm_vector_registers reg, vreg0, vlane0, vreg0size,
4579bool AsmParser::parseDirectiveCFILLVMVectorRegisters(SMLoc DirectiveLoc) {
4580 int64_t Register = 0;
4581 std::vector<MCCFIInstruction::VectorRegisterWithLane> VRs;
4582
4583 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma())
4584 return true;
4585
4586 do {
4587 int64_t VectorRegister = 0;
4588 int64_t Lane = 0;
4589 int64_t Size = 0;
4590 if (parseRegisterOrRegisterNumber(VectorRegister, DirectiveLoc) ||
4591 parseComma() || parseIntToken(Lane, "expected a lane number") ||
4592 parseComma() || parseAbsoluteExpression(Size))
4593 return true;
4594 VRs.push_back({unsigned(VectorRegister), unsigned(Lane), unsigned(Size)});
4595 } while (parseOptionalToken(AsmToken::Comma));
4596
4597 if (parseEOL())
4598 return true;
4599
4600 getStreamer().emitCFILLVMVectorRegisters(Register, std::move(VRs),
4601 DirectiveLoc);
4602 return false;
4603}
4604
4605/// parseDirectiveCFILLVMVectorOffset
4606/// ::= .cfi_llvm_vector_offset register, register-size, mask, mask-size, offset
4607bool AsmParser::parseDirectiveCFILLVMVectorOffset(SMLoc DirectiveLoc) {
4608 int64_t Register = 0, MaskRegister = 0;
4609 int64_t RegisterSize = 0, MaskRegisterSize = 0;
4610 int64_t Offset = 0;
4611
4612 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4613 parseAbsoluteExpression(RegisterSize) || parseComma() ||
4614 parseRegisterOrRegisterNumber(MaskRegister, DirectiveLoc) ||
4615 parseComma() || parseAbsoluteExpression(MaskRegisterSize) ||
4616 parseComma() || parseAbsoluteExpression(Offset) || parseEOL())
4617 return true;
4618
4619 getStreamer().emitCFILLVMVectorOffset(Register, RegisterSize, MaskRegister,
4620 MaskRegisterSize, Offset, DirectiveLoc);
4621 return false;
4622}
4623
4624/// parseDirectiveCFILLVMVectorOffset
4625/// ::= .cfi_llvm_vector_register_mask register, spill-reg, spill-reg-lane-size,
4626/// mask-reg, mask-reg-size
4627bool AsmParser::parseDirectiveCFILLVMVectorRegisterMask(SMLoc DirectiveLoc) {
4628 int64_t Register = 0, SpillReg = 0, MaskReg = 0;
4629 int64_t SpillRegLaneSize = 0, MaskRegSize = 0;
4630
4631 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4632 parseRegisterOrRegisterNumber(SpillReg, DirectiveLoc) || parseComma() ||
4633 parseAbsoluteExpression(SpillRegLaneSize) || parseComma() ||
4634 parseRegisterOrRegisterNumber(MaskReg, DirectiveLoc) || parseComma() ||
4635 parseAbsoluteExpression(MaskRegSize) || parseEOL())
4636 return true;
4637
4638 getStreamer().emitCFILLVMVectorRegisterMask(
4639 Register, SpillReg, SpillRegLaneSize, MaskReg, MaskRegSize, DirectiveLoc);
4640 return false;
4641}
4642
4643/// parseDirectiveCFILabel
4644/// ::= .cfi_label label
4645bool AsmParser::parseDirectiveCFILabel(SMLoc Loc) {
4646 StringRef Name;
4647 Loc = Lexer.getLoc();
4648 if (parseIdentifier(Name))
4649 return TokError("expected identifier");
4650 if (parseEOL())
4651 return true;
4652 getStreamer().emitCFILabelDirective(Loc, Name);
4653 return false;
4654}
4655
4656/// parseDirectiveCFIValOffset
4657/// ::= .cfi_val_offset register, offset
4658bool AsmParser::parseDirectiveCFIValOffset(SMLoc DirectiveLoc) {
4659 int64_t Register = 0;
4660 int64_t Offset = 0;
4661
4662 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4663 parseAbsoluteExpression(Offset) || parseEOL())
4664 return true;
4665
4666 getStreamer().emitCFIValOffset(Register, Offset, DirectiveLoc);
4667 return false;
4668}
4669
4670/// parseDirectiveAltmacro
4671/// ::= .altmacro
4672/// ::= .noaltmacro
4673bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
4674 if (parseEOL())
4675 return true;
4676 AltMacroMode = (Directive == ".altmacro");
4677 return false;
4678}
4679
4680/// parseDirectiveMacrosOnOff
4681/// ::= .macros_on
4682/// ::= .macros_off
4683bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
4684 if (parseEOL())
4685 return true;
4686 setMacrosEnabled(Directive == ".macros_on");
4687 return false;
4688}
4689
4690/// parseDirectiveMacro
4691/// ::= .macro name[,] [parameters]
4692bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
4693 StringRef Name;
4694 if (parseIdentifier(Name))
4695 return TokError("expected identifier in '.macro' directive");
4696
4697 if (getLexer().is(AsmToken::Comma))
4698 Lex();
4699
4701 while (getLexer().isNot(AsmToken::EndOfStatement)) {
4702
4703 if (!Parameters.empty() && Parameters.back().Vararg)
4704 return Error(Lexer.getLoc(), "vararg parameter '" +
4705 Parameters.back().Name +
4706 "' should be the last parameter");
4707
4708 MCAsmMacroParameter Parameter;
4709 if (parseIdentifier(Parameter.Name))
4710 return TokError("expected identifier in '.macro' directive");
4711
4712 // Emit an error if two (or more) named parameters share the same name
4713 for (const MCAsmMacroParameter& CurrParam : Parameters)
4714 if (CurrParam.Name == Parameter.Name)
4715 return TokError("macro '" + Name + "' has multiple parameters"
4716 " named '" + Parameter.Name + "'");
4717
4718 if (Lexer.is(AsmToken::Colon)) {
4719 Lex(); // consume ':'
4720
4721 SMLoc QualLoc;
4722 StringRef Qualifier;
4723
4724 QualLoc = Lexer.getLoc();
4725 if (parseIdentifier(Qualifier))
4726 return Error(QualLoc, "missing parameter qualifier for "
4727 "'" + Parameter.Name + "' in macro '" + Name + "'");
4728
4729 if (Qualifier == "req")
4730 Parameter.Required = true;
4731 else if (Qualifier == "vararg")
4732 Parameter.Vararg = true;
4733 else
4734 return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
4735 "for '" + Parameter.Name + "' in macro '" + Name + "'");
4736 }
4737
4738 if (getLexer().is(AsmToken::Equal)) {
4739 Lex();
4740
4741 SMLoc ParamLoc;
4742
4743 ParamLoc = Lexer.getLoc();
4744 if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
4745 return true;
4746
4747 if (Parameter.Required)
4748 Warning(ParamLoc, "pointless default value for required parameter "
4749 "'" + Parameter.Name + "' in macro '" + Name + "'");
4750 }
4751
4752 Parameters.push_back(std::move(Parameter));
4753
4754 if (getLexer().is(AsmToken::Comma))
4755 Lex();
4756 }
4757
4758 // Eat just the end of statement.
4759 Lexer.Lex();
4760
4761 // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors
4762 AsmToken EndToken, StartToken = getTok();
4763 unsigned MacroDepth = 0;
4764 // Lex the macro definition.
4765 while (true) {
4766 // Ignore Lexing errors in macros.
4767 while (Lexer.is(AsmToken::Error)) {
4768 Lexer.Lex();
4769 }
4770
4771 // Check whether we have reached the end of the file.
4772 if (getLexer().is(AsmToken::Eof))
4773 return Error(DirectiveLoc, "no matching '.endmacro' in definition");
4774
4775 // Otherwise, check whether we have reach the .endmacro or the start of a
4776 // preprocessor line marker.
4777 if (getLexer().is(AsmToken::Identifier)) {
4778 if (getTok().getIdentifier() == ".endm" ||
4779 getTok().getIdentifier() == ".endmacro") {
4780 if (MacroDepth == 0) { // Outermost macro.
4781 EndToken = getTok();
4782 Lexer.Lex();
4783 if (getLexer().isNot(AsmToken::EndOfStatement))
4784 return TokError("unexpected token in '" + EndToken.getIdentifier() +
4785 "' directive");
4786 break;
4787 } else {
4788 // Otherwise we just found the end of an inner macro.
4789 --MacroDepth;
4790 }
4791 } else if (getTok().getIdentifier() == ".macro") {
4792 // We allow nested macros. Those aren't instantiated until the outermost
4793 // macro is expanded so just ignore them for now.
4794 ++MacroDepth;
4795 }
4796 } else if (Lexer.is(AsmToken::HashDirective)) {
4797 (void)parseCppHashLineFilenameComment(getLexer().getLoc());
4798 }
4799
4800 // Otherwise, scan til the end of the statement.
4801 eatToEndOfStatement();
4802 }
4803
4804 if (getContext().lookupMacro(Name)) {
4805 return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
4806 }
4807
4808 const char *BodyStart = StartToken.getLoc().getPointer();
4809 const char *BodyEnd = EndToken.getLoc().getPointer();
4810 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4811 checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
4812 MCAsmMacro Macro(Name, Body, std::move(Parameters));
4813 DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
4814 Macro.dump());
4815 getContext().defineMacro(Name, std::move(Macro));
4816 return false;
4817}
4818
4819/// checkForBadMacro
4820///
4821/// With the support added for named parameters there may be code out there that
4822/// is transitioning from positional parameters. In versions of gas that did
4823/// not support named parameters they would be ignored on the macro definition.
4824/// But to support both styles of parameters this is not possible so if a macro
4825/// definition has named parameters but does not use them and has what appears
4826/// to be positional parameters, strings like $1, $2, ... and $n, then issue a
4827/// warning that the positional parameter found in body which have no effect.
4828/// Hoping the developer will either remove the named parameters from the macro
4829/// definition so the positional parameters get used if that was what was
4830/// intended or change the macro to use the named parameters. It is possible
4831/// this warning will trigger when the none of the named parameters are used
4832/// and the strings like $1 are infact to simply to be passed trough unchanged.
4833void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
4834 StringRef Body,
4835 ArrayRef<MCAsmMacroParameter> Parameters) {
4836 // If this macro is not defined with named parameters the warning we are
4837 // checking for here doesn't apply.
4838 unsigned NParameters = Parameters.size();
4839 if (NParameters == 0)
4840 return;
4841
4842 bool NamedParametersFound = false;
4843 bool PositionalParametersFound = false;
4844
4845 // Look at the body of the macro for use of both the named parameters and what
4846 // are likely to be positional parameters. This is what expandMacro() is
4847 // doing when it finds the parameters in the body.
4848 while (!Body.empty()) {
4849 // Scan for the next possible parameter.
4850 std::size_t End = Body.size(), Pos = 0;
4851 for (; Pos != End; ++Pos) {
4852 // Check for a substitution or escape.
4853 // This macro is defined with parameters, look for \foo, \bar, etc.
4854 if (Body[Pos] == '\\' && Pos + 1 != End)
4855 break;
4856
4857 // This macro should have parameters, but look for $0, $1, ..., $n too.
4858 if (Body[Pos] != '$' || Pos + 1 == End)
4859 continue;
4860 char Next = Body[Pos + 1];
4861 if (Next == '$' || Next == 'n' ||
4862 isdigit(static_cast<unsigned char>(Next)))
4863 break;
4864 }
4865
4866 // Check if we reached the end.
4867 if (Pos == End)
4868 break;
4869
4870 if (Body[Pos] == '$') {
4871 switch (Body[Pos + 1]) {
4872 // $$ => $
4873 case '$':
4874 break;
4875
4876 // $n => number of arguments
4877 case 'n':
4878 PositionalParametersFound = true;
4879 break;
4880
4881 // $[0-9] => argument
4882 default: {
4883 PositionalParametersFound = true;
4884 break;
4885 }
4886 }
4887 Pos += 2;
4888 } else {
4889 unsigned I = Pos + 1;
4890 while (isIdentifierChar(Body[I]) && I + 1 != End)
4891 ++I;
4892
4893 const char *Begin = Body.data() + Pos + 1;
4894 StringRef Argument(Begin, I - (Pos + 1));
4895 unsigned Index = 0;
4896 for (; Index < NParameters; ++Index)
4897 if (Parameters[Index].Name == Argument)
4898 break;
4899
4900 if (Index == NParameters) {
4901 if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
4902 Pos += 3;
4903 else {
4904 Pos = I;
4905 }
4906 } else {
4907 NamedParametersFound = true;
4908 Pos += 1 + Argument.size();
4909 }
4910 }
4911 // Update the scan point.
4912 Body = Body.substr(Pos);
4913 }
4914
4915 if (!NamedParametersFound && PositionalParametersFound)
4916 Warning(DirectiveLoc, "macro defined with named parameters which are not "
4917 "used in macro body, possible positional parameter "
4918 "found in body which will have no effect");
4919}
4920
4921/// parseDirectiveExitMacro
4922/// ::= .exitm
4923bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
4924 if (parseEOL())
4925 return true;
4926
4927 if (!isInsideMacroInstantiation())
4928 return TokError("unexpected '" + Directive + "' in file, "
4929 "no current macro definition");
4930
4931 // Exit all conditionals that are active in the current macro.
4932 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4933 TheCondState = TheCondStack.back();
4934 TheCondStack.pop_back();
4935 }
4936
4937 handleMacroExit();
4938 return false;
4939}
4940
4941/// parseDirectiveEndMacro
4942/// ::= .endm
4943/// ::= .endmacro
4944bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
4945 if (getLexer().isNot(AsmToken::EndOfStatement))
4946 return TokError("unexpected token in '" + Directive + "' directive");
4947
4948 // If we are inside a macro instantiation, terminate the current
4949 // instantiation.
4950 if (isInsideMacroInstantiation()) {
4951 handleMacroExit();
4952 return false;
4953 }
4954
4955 // Otherwise, this .endmacro is a stray entry in the file; well formed
4956 // .endmacro directives are handled during the macro definition parsing.
4957 return TokError("unexpected '" + Directive + "' in file, "
4958 "no current macro definition");
4959}
4960
4961/// parseDirectivePurgeMacro
4962/// ::= .purgem name
4963bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4964 StringRef Name;
4965 SMLoc Loc;
4966 if (parseTokenLoc(Loc) ||
4967 check(parseIdentifier(Name), Loc,
4968 "expected identifier in '.purgem' directive") ||
4969 parseEOL())
4970 return true;
4971
4972 if (!getContext().lookupMacro(Name))
4973 return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
4974
4975 getContext().undefineMacro(Name);
4976 DEBUG_WITH_TYPE("asm-macros", dbgs()
4977 << "Un-defining macro: " << Name << "\n");
4978 return false;
4979}
4980
4981/// parseDirectiveSpace
4982/// ::= (.skip | .space) expression [ , expression ]
4983bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
4984 SMLoc NumBytesLoc = Lexer.getLoc();
4985 const MCExpr *NumBytes;
4986 if (checkForValidSection() || parseExpression(NumBytes))
4987 return true;
4988
4989 int64_t FillExpr = 0;
4990 if (parseOptionalToken(AsmToken::Comma))
4991 if (parseAbsoluteExpression(FillExpr))
4992 return true;
4993 if (parseEOL())
4994 return true;
4995
4996 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
4997 getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
4998
4999 return false;
5000}
5001
5002/// parseDirectiveDCB
5003/// ::= .dcb.{b, l, w} expression, expression
5004bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
5005 SMLoc NumValuesLoc = Lexer.getLoc();
5006 int64_t NumValues;
5007 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
5008 return true;
5009
5010 if (NumValues < 0) {
5011 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
5012 return false;
5013 }
5014
5015 if (parseComma())
5016 return true;
5017
5018 const MCExpr *Value;
5019 SMLoc ExprLoc = getLexer().getLoc();
5020 if (parseExpression(Value))
5021 return true;
5022
5023 // Special case constant expressions to match code generator.
5024 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
5025 assert(Size <= 8 && "Invalid size");
5026 uint64_t IntValue = MCE->getValue();
5027 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
5028 return Error(ExprLoc, "literal value out of range for directive");
5029 for (uint64_t i = 0, e = NumValues; i != e; ++i)
5030 getStreamer().emitIntValue(IntValue, Size);
5031 } else {
5032 for (uint64_t i = 0, e = NumValues; i != e; ++i)
5033 getStreamer().emitValue(Value, Size, ExprLoc);
5034 }
5035
5036 return parseEOL();
5037}
5038
5039/// parseDirectiveRealDCB
5040/// ::= .dcb.{d, s} expression, expression
5041bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {
5042 SMLoc NumValuesLoc = Lexer.getLoc();
5043 int64_t NumValues;
5044 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
5045 return true;
5046
5047 if (NumValues < 0) {
5048 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
5049 return false;
5050 }
5051
5052 if (parseComma())
5053 return true;
5054
5055 APInt AsInt;
5056 if (parseRealValue(Semantics, AsInt) || parseEOL())
5057 return true;
5058
5059 for (uint64_t i = 0, e = NumValues; i != e; ++i)
5060 getStreamer().emitIntValue(AsInt.getLimitedValue(),
5061 AsInt.getBitWidth() / 8);
5062
5063 return false;
5064}
5065
5066/// parseDirectiveDS
5067/// ::= .ds.{b, d, l, p, s, w, x} expression
5068bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {
5069 SMLoc NumValuesLoc = Lexer.getLoc();
5070 int64_t NumValues;
5071 if (checkForValidSection() || parseAbsoluteExpression(NumValues) ||
5072 parseEOL())
5073 return true;
5074
5075 if (NumValues < 0) {
5076 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
5077 return false;
5078 }
5079
5080 for (uint64_t i = 0, e = NumValues; i != e; ++i)
5081 getStreamer().emitFill(Size, 0);
5082
5083 return false;
5084}
5085
5086/// parseDirectiveLEB128
5087/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
5088bool AsmParser::parseDirectiveLEB128(bool Signed) {
5089 if (checkForValidSection())
5090 return true;
5091
5092 auto parseOp = [&]() -> bool {
5093 const MCExpr *Value;
5094 if (parseExpression(Value))
5095 return true;
5096 if (Signed)
5097 getStreamer().emitSLEB128Value(Value);
5098 else
5099 getStreamer().emitULEB128Value(Value);
5100 return false;
5101 };
5102
5103 return parseMany(parseOp);
5104}
5105
5106/// parseDirectiveSymbolAttribute
5107/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
5108bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
5109 auto parseOp = [&]() -> bool {
5110 StringRef Name;
5111 SMLoc Loc = getTok().getLoc();
5112 if (parseIdentifier(Name))
5113 return Error(Loc, "expected identifier");
5114
5115 if (discardLTOSymbol(Name))
5116 return false;
5117
5118 MCSymbol *Sym = getContext().parseSymbol(Name);
5119
5120 // Assembler local symbols don't make any sense here, except for directives
5121 // that the symbol should be tagged.
5122 if (Sym->isTemporary() && Attr != MCSA_Memtag)
5123 return Error(Loc, "non-local symbol required");
5124
5125 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
5126 return Error(Loc, "unable to emit symbol attribute");
5127 return false;
5128 };
5129
5130 return parseMany(parseOp);
5131}
5132
5133/// parseDirectiveComm
5134/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
5135bool AsmParser::parseDirectiveComm(bool IsLocal) {
5136 if (checkForValidSection())
5137 return true;
5138
5139 SMLoc IDLoc = getLexer().getLoc();
5140 MCSymbol *Sym;
5141 if (parseSymbol(Sym))
5142 return TokError("expected identifier in directive");
5143
5144 if (parseComma())
5145 return true;
5146
5147 int64_t Size;
5148 SMLoc SizeLoc = getLexer().getLoc();
5149 if (parseAbsoluteExpression(Size))
5150 return true;
5151
5152 int64_t Pow2Alignment = 0;
5153 SMLoc Pow2AlignmentLoc;
5154 if (getLexer().is(AsmToken::Comma)) {
5155 Lex();
5156 Pow2AlignmentLoc = getLexer().getLoc();
5157 if (parseAbsoluteExpression(Pow2Alignment))
5158 return true;
5159
5161 if (IsLocal && LCOMM == LCOMM::NoAlignment)
5162 return Error(Pow2AlignmentLoc, "alignment not supported on this target");
5163
5164 // If this target takes alignments in bytes (not log) validate and convert.
5165 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
5166 (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
5167 if (!isPowerOf2_64(Pow2Alignment))
5168 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
5169 Pow2Alignment = Log2_64(Pow2Alignment);
5170 }
5171 }
5172
5173 if (parseEOL())
5174 return true;
5175
5176 // NOTE: a size of zero for a .comm should create a undefined symbol
5177 // but a size of .lcomm creates a bss symbol of size zero.
5178 if (Size < 0)
5179 return Error(SizeLoc, "size must be non-negative");
5180
5181 Sym->redefineIfPossible();
5182 if (!Sym->isUndefined())
5183 return Error(IDLoc, "invalid symbol redefinition");
5184
5185 // Create the Symbol as a common or local common with Size and Pow2Alignment
5186 if (IsLocal) {
5187 getStreamer().emitLocalCommonSymbol(Sym, Size,
5188 Align(1ULL << Pow2Alignment));
5189 return false;
5190 }
5191
5192 getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));
5193 return false;
5194}
5195
5196/// parseDirectiveAbort
5197/// ::= .abort [... message ...]
5198bool AsmParser::parseDirectiveAbort(SMLoc DirectiveLoc) {
5199 StringRef Str = parseStringToEndOfStatement();
5200 if (parseEOL())
5201 return true;
5202
5203 if (Str.empty())
5204 return Error(DirectiveLoc, ".abort detected. Assembly stopping");
5205
5206 // FIXME: Actually abort assembly here.
5207 return Error(DirectiveLoc,
5208 ".abort '" + Str + "' detected. Assembly stopping");
5209}
5210
5211/// parseDirectiveInclude
5212/// ::= .include "filename"
5213bool AsmParser::parseDirectiveInclude() {
5214 // Allow the strings to have escaped octal character sequence.
5215 std::string Filename;
5216 SMLoc IncludeLoc = getTok().getLoc();
5217
5218 if (check(getTok().isNot(AsmToken::String),
5219 "expected string in '.include' directive") ||
5220 parseEscapedString(Filename) ||
5221 check(getTok().isNot(AsmToken::EndOfStatement),
5222 "unexpected token in '.include' directive") ||
5223 // Attempt to switch the lexer to the included file before consuming the
5224 // end of statement to avoid losing it when we switch.
5225 check(enterIncludeFile(Filename), IncludeLoc,
5226 "Could not find include file '" + Filename + "'"))
5227 return true;
5228
5229 return false;
5230}
5231
5232/// parseDirectiveIncbin
5233/// ::= .incbin "filename" [ , skip [ , count ] ]
5234bool AsmParser::parseDirectiveIncbin() {
5235 // Allow the strings to have escaped octal character sequence.
5236 std::string Filename;
5237 SMLoc IncbinLoc = getTok().getLoc();
5238 if (check(getTok().isNot(AsmToken::String),
5239 "expected string in '.incbin' directive") ||
5240 parseEscapedString(Filename))
5241 return true;
5242
5243 int64_t Skip = 0;
5244 const MCExpr *Count = nullptr;
5245 SMLoc SkipLoc, CountLoc;
5246 if (parseOptionalToken(AsmToken::Comma)) {
5247 // The skip expression can be omitted while specifying the count, e.g:
5248 // .incbin "filename",,4
5249 if (getTok().isNot(AsmToken::Comma)) {
5250 if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))
5251 return true;
5252 }
5253 if (parseOptionalToken(AsmToken::Comma)) {
5254 CountLoc = getTok().getLoc();
5255 if (parseExpression(Count))
5256 return true;
5257 }
5258 }
5259
5260 if (parseEOL())
5261 return true;
5262
5263 if (check(Skip < 0, SkipLoc, "skip is negative"))
5264 return true;
5265
5266 // Attempt to process the included file.
5267 if (processIncbinFile(Filename, Skip, Count, CountLoc))
5268 return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
5269 return false;
5270}
5271
5272/// parseDirectiveIf
5273/// ::= .if{,eq,ge,gt,le,lt,ne} expression
5274bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
5275 TheCondStack.push_back(TheCondState);
5276 TheCondState.TheCond = AsmCond::IfCond;
5277 if (TheCondState.Ignore) {
5278 eatToEndOfStatement();
5279 } else {
5280 int64_t ExprValue;
5281 if (parseAbsoluteExpression(ExprValue) || parseEOL())
5282 return true;
5283
5284 switch (DirKind) {
5285 default:
5286 llvm_unreachable("unsupported directive");
5287 case DK_IF:
5288 case DK_IFNE:
5289 break;
5290 case DK_IFEQ:
5291 ExprValue = ExprValue == 0;
5292 break;
5293 case DK_IFGE:
5294 ExprValue = ExprValue >= 0;
5295 break;
5296 case DK_IFGT:
5297 ExprValue = ExprValue > 0;
5298 break;
5299 case DK_IFLE:
5300 ExprValue = ExprValue <= 0;
5301 break;
5302 case DK_IFLT:
5303 ExprValue = ExprValue < 0;
5304 break;
5305 }
5306
5307 TheCondState.CondMet = ExprValue;
5308 TheCondState.Ignore = !TheCondState.CondMet;
5309 }
5310
5311 return false;
5312}
5313
5314/// parseDirectiveIfb
5315/// ::= .ifb string
5316bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
5317 TheCondStack.push_back(TheCondState);
5318 TheCondState.TheCond = AsmCond::IfCond;
5319
5320 if (TheCondState.Ignore) {
5321 eatToEndOfStatement();
5322 } else {
5323 StringRef Str = parseStringToEndOfStatement();
5324
5325 if (parseEOL())
5326 return true;
5327
5328 TheCondState.CondMet = ExpectBlank == Str.empty();
5329 TheCondState.Ignore = !TheCondState.CondMet;
5330 }
5331
5332 return false;
5333}
5334
5335/// parseDirectiveIfc
5336/// ::= .ifc string1, string2
5337/// ::= .ifnc string1, string2
5338bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
5339 TheCondStack.push_back(TheCondState);
5340 TheCondState.TheCond = AsmCond::IfCond;
5341
5342 if (TheCondState.Ignore) {
5343 eatToEndOfStatement();
5344 } else {
5345 StringRef Str1 = parseStringToComma();
5346
5347 if (parseComma())
5348 return true;
5349
5350 StringRef Str2 = parseStringToEndOfStatement();
5351
5352 if (parseEOL())
5353 return true;
5354
5355 TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
5356 TheCondState.Ignore = !TheCondState.CondMet;
5357 }
5358
5359 return false;
5360}
5361
5362/// parseDirectiveIfeqs
5363/// ::= .ifeqs string1, string2
5364bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
5365 TheCondStack.push_back(TheCondState);
5366 TheCondState.TheCond = AsmCond::IfCond;
5367
5368 if (TheCondState.Ignore) {
5369 eatToEndOfStatement();
5370 } else {
5371 if (Lexer.isNot(AsmToken::String)) {
5372 if (ExpectEqual)
5373 return TokError("expected string parameter for '.ifeqs' directive");
5374 return TokError("expected string parameter for '.ifnes' directive");
5375 }
5376
5377 StringRef String1 = getTok().getStringContents();
5378 Lex();
5379
5380 if (Lexer.isNot(AsmToken::Comma)) {
5381 if (ExpectEqual)
5382 return TokError(
5383 "expected comma after first string for '.ifeqs' directive");
5384 return TokError(
5385 "expected comma after first string for '.ifnes' directive");
5386 }
5387
5388 Lex();
5389
5390 if (Lexer.isNot(AsmToken::String)) {
5391 if (ExpectEqual)
5392 return TokError("expected string parameter for '.ifeqs' directive");
5393 return TokError("expected string parameter for '.ifnes' directive");
5394 }
5395
5396 StringRef String2 = getTok().getStringContents();
5397 Lex();
5398
5399 TheCondState.CondMet = ExpectEqual == (String1 == String2);
5400 TheCondState.Ignore = !TheCondState.CondMet;
5401 }
5402
5403 return false;
5404}
5405
5406/// parseDirectiveIfdef
5407/// ::= .ifdef symbol
5408bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
5409 StringRef Name;
5410 TheCondStack.push_back(TheCondState);
5411 TheCondState.TheCond = AsmCond::IfCond;
5412
5413 if (TheCondState.Ignore) {
5414 eatToEndOfStatement();
5415 } else {
5416 if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
5417 parseEOL())
5418 return true;
5419
5420 MCSymbol *Sym = getContext().lookupSymbol(Name);
5421
5422 if (expect_defined)
5423 TheCondState.CondMet = (Sym && !Sym->isUndefined());
5424 else
5425 TheCondState.CondMet = (!Sym || Sym->isUndefined());
5426 TheCondState.Ignore = !TheCondState.CondMet;
5427 }
5428
5429 return false;
5430}
5431
5432/// parseDirectiveElseIf
5433/// ::= .elseif expression
5434bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
5435 if (TheCondState.TheCond != AsmCond::IfCond &&
5436 TheCondState.TheCond != AsmCond::ElseIfCond)
5437 return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
5438 " .if or an .elseif");
5439 TheCondState.TheCond = AsmCond::ElseIfCond;
5440
5441 bool LastIgnoreState = false;
5442 if (!TheCondStack.empty())
5443 LastIgnoreState = TheCondStack.back().Ignore;
5444 if (LastIgnoreState || TheCondState.CondMet) {
5445 TheCondState.Ignore = true;
5446 eatToEndOfStatement();
5447 } else {
5448 int64_t ExprValue;
5449 if (parseAbsoluteExpression(ExprValue))
5450 return true;
5451
5452 if (parseEOL())
5453 return true;
5454
5455 TheCondState.CondMet = ExprValue;
5456 TheCondState.Ignore = !TheCondState.CondMet;
5457 }
5458
5459 return false;
5460}
5461
5462/// parseDirectiveElse
5463/// ::= .else
5464bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
5465 if (parseEOL())
5466 return true;
5467
5468 if (TheCondState.TheCond != AsmCond::IfCond &&
5469 TheCondState.TheCond != AsmCond::ElseIfCond)
5470 return Error(DirectiveLoc, "Encountered a .else that doesn't follow "
5471 " an .if or an .elseif");
5472 TheCondState.TheCond = AsmCond::ElseCond;
5473 bool LastIgnoreState = false;
5474 if (!TheCondStack.empty())
5475 LastIgnoreState = TheCondStack.back().Ignore;
5476 if (LastIgnoreState || TheCondState.CondMet)
5477 TheCondState.Ignore = true;
5478 else
5479 TheCondState.Ignore = false;
5480
5481 return false;
5482}
5483
5484/// parseDirectiveEnd
5485/// ::= .end
5486bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5487 if (parseEOL())
5488 return true;
5489
5490 while (Lexer.isNot(AsmToken::Eof))
5491 Lexer.Lex();
5492
5493 return false;
5494}
5495
5496/// parseDirectiveError
5497/// ::= .err
5498/// ::= .error [string]
5499bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
5500 if (!TheCondStack.empty()) {
5501 if (TheCondStack.back().Ignore) {
5502 eatToEndOfStatement();
5503 return false;
5504 }
5505 }
5506
5507 if (!WithMessage)
5508 return Error(L, ".err encountered");
5509
5510 StringRef Message = ".error directive invoked in source file";
5511 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5512 if (Lexer.isNot(AsmToken::String))
5513 return TokError(".error argument must be a string");
5514
5515 Message = getTok().getStringContents();
5516 Lex();
5517 }
5518
5519 return Error(L, Message);
5520}
5521
5522/// parseDirectiveWarning
5523/// ::= .warning [string]
5524bool AsmParser::parseDirectiveWarning(SMLoc L) {
5525 if (!TheCondStack.empty()) {
5526 if (TheCondStack.back().Ignore) {
5527 eatToEndOfStatement();
5528 return false;
5529 }
5530 }
5531
5532 StringRef Message = ".warning directive invoked in source file";
5533
5534 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
5535 if (Lexer.isNot(AsmToken::String))
5536 return TokError(".warning argument must be a string");
5537
5538 Message = getTok().getStringContents();
5539 Lex();
5540 if (parseEOL())
5541 return true;
5542 }
5543
5544 return Warning(L, Message);
5545}
5546
5547/// parseDirectiveEndIf
5548/// ::= .endif
5549bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5550 if (parseEOL())
5551 return true;
5552
5553 if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
5554 return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
5555 "an .if or .else");
5556 if (!TheCondStack.empty()) {
5557 TheCondState = TheCondStack.back();
5558 TheCondStack.pop_back();
5559 }
5560
5561 return false;
5562}
5563
5564void AsmParser::initializeDirectiveKindMap() {
5565 /* Lookup will be done with the directive
5566 * converted to lower case, so all these
5567 * keys should be lower case.
5568 * (target specific directives are handled
5569 * elsewhere)
5570 */
5571 DirectiveKindMap[".set"] = DK_SET;
5572 DirectiveKindMap[".equ"] = DK_EQU;
5573 DirectiveKindMap[".equiv"] = DK_EQUIV;
5574 DirectiveKindMap[".ascii"] = DK_ASCII;
5575 DirectiveKindMap[".asciz"] = DK_ASCIZ;
5576 DirectiveKindMap[".string"] = DK_STRING;
5577 DirectiveKindMap[".byte"] = DK_BYTE;
5578 DirectiveKindMap[".base64"] = DK_BASE64;
5579 DirectiveKindMap[".short"] = DK_SHORT;
5580 DirectiveKindMap[".value"] = DK_VALUE;
5581 DirectiveKindMap[".2byte"] = DK_2BYTE;
5582 DirectiveKindMap[".long"] = DK_LONG;
5583 DirectiveKindMap[".int"] = DK_INT;
5584 DirectiveKindMap[".4byte"] = DK_4BYTE;
5585 DirectiveKindMap[".quad"] = DK_QUAD;
5586 DirectiveKindMap[".8byte"] = DK_8BYTE;
5587 DirectiveKindMap[".octa"] = DK_OCTA;
5588 DirectiveKindMap[".single"] = DK_SINGLE;
5589 DirectiveKindMap[".float"] = DK_FLOAT;
5590 DirectiveKindMap[".double"] = DK_DOUBLE;
5591 DirectiveKindMap[".align"] = DK_ALIGN;
5592 DirectiveKindMap[".align32"] = DK_ALIGN32;
5593 DirectiveKindMap[".balign"] = DK_BALIGN;
5594 DirectiveKindMap[".balignw"] = DK_BALIGNW;
5595 DirectiveKindMap[".balignl"] = DK_BALIGNL;
5596 DirectiveKindMap[".p2align"] = DK_P2ALIGN;
5597 DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
5598 DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
5599 DirectiveKindMap[".prefalign"] = DK_PREFALIGN;
5600 DirectiveKindMap[".org"] = DK_ORG;
5601 DirectiveKindMap[".fill"] = DK_FILL;
5602 DirectiveKindMap[".zero"] = DK_ZERO;
5603 DirectiveKindMap[".extern"] = DK_EXTERN;
5604 DirectiveKindMap[".globl"] = DK_GLOBL;
5605 DirectiveKindMap[".global"] = DK_GLOBAL;
5606 DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
5607 DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
5608 DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
5609 DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
5610 DirectiveKindMap[".reference"] = DK_REFERENCE;
5611 DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
5612 DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
5613 DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
5614 DirectiveKindMap[".cold"] = DK_COLD;
5615 DirectiveKindMap[".comm"] = DK_COMM;
5616 DirectiveKindMap[".common"] = DK_COMMON;
5617 DirectiveKindMap[".lcomm"] = DK_LCOMM;
5618 DirectiveKindMap[".abort"] = DK_ABORT;
5619 DirectiveKindMap[".include"] = DK_INCLUDE;
5620 DirectiveKindMap[".incbin"] = DK_INCBIN;
5621 DirectiveKindMap[".code16"] = DK_CODE16;
5622 DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
5623 DirectiveKindMap[".rept"] = DK_REPT;
5624 DirectiveKindMap[".rep"] = DK_REPT;
5625 DirectiveKindMap[".irp"] = DK_IRP;
5626 DirectiveKindMap[".irpc"] = DK_IRPC;
5627 DirectiveKindMap[".endr"] = DK_ENDR;
5628 DirectiveKindMap[".if"] = DK_IF;
5629 DirectiveKindMap[".ifeq"] = DK_IFEQ;
5630 DirectiveKindMap[".ifge"] = DK_IFGE;
5631 DirectiveKindMap[".ifgt"] = DK_IFGT;
5632 DirectiveKindMap[".ifle"] = DK_IFLE;
5633 DirectiveKindMap[".iflt"] = DK_IFLT;
5634 DirectiveKindMap[".ifne"] = DK_IFNE;
5635 DirectiveKindMap[".ifb"] = DK_IFB;
5636 DirectiveKindMap[".ifnb"] = DK_IFNB;
5637 DirectiveKindMap[".ifc"] = DK_IFC;
5638 DirectiveKindMap[".ifeqs"] = DK_IFEQS;
5639 DirectiveKindMap[".ifnc"] = DK_IFNC;
5640 DirectiveKindMap[".ifnes"] = DK_IFNES;
5641 DirectiveKindMap[".ifdef"] = DK_IFDEF;
5642 DirectiveKindMap[".ifndef"] = DK_IFNDEF;
5643 DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
5644 DirectiveKindMap[".elseif"] = DK_ELSEIF;
5645 DirectiveKindMap[".else"] = DK_ELSE;
5646 DirectiveKindMap[".end"] = DK_END;
5647 DirectiveKindMap[".endif"] = DK_ENDIF;
5648 DirectiveKindMap[".skip"] = DK_SKIP;
5649 DirectiveKindMap[".space"] = DK_SPACE;
5650 DirectiveKindMap[".file"] = DK_FILE;
5651 DirectiveKindMap[".line"] = DK_LINE;
5652 DirectiveKindMap[".loc"] = DK_LOC;
5653 DirectiveKindMap[".loc_label"] = DK_LOC_LABEL;
5654 DirectiveKindMap[".stabs"] = DK_STABS;
5655 DirectiveKindMap[".cv_file"] = DK_CV_FILE;
5656 DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
5657 DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
5658 DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
5659 DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
5660 DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
5661 DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
5662 DirectiveKindMap[".cv_string"] = DK_CV_STRING;
5663 DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
5664 DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
5665 DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
5666 DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
5667 DirectiveKindMap[".sleb128"] = DK_SLEB128;
5668 DirectiveKindMap[".uleb128"] = DK_ULEB128;
5669 DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
5670 DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
5671 DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
5672 DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
5673 DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
5674 DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
5675 DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
5676 DirectiveKindMap[".cfi_llvm_def_aspace_cfa"] = DK_CFI_LLVM_DEF_ASPACE_CFA;
5677 DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
5678 DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
5679 DirectiveKindMap[".cfi_llvm_register_pair"] = DK_CFI_LLVM_REGISTER_PAIR;
5680 DirectiveKindMap[".cfi_llvm_vector_registers"] = DK_CFI_LLVM_VECTOR_REGISTERS;
5681 DirectiveKindMap[".cfi_llvm_vector_offset"] = DK_CFI_LLVM_VECTOR_OFFSET;
5682 DirectiveKindMap[".cfi_llvm_vector_register_mask"] =
5683 DK_CFI_LLVM_VECTOR_REGISTER_MASK;
5684 DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
5685 DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
5686 DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
5687 DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
5688 DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
5689 DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
5690 DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
5691 DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
5692 DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
5693 DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
5694 DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
5695 DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
5696 DirectiveKindMap[".cfi_label"] = DK_CFI_LABEL;
5697 DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
5698 DirectiveKindMap[".cfi_mte_tagged_frame"] = DK_CFI_MTE_TAGGED_FRAME;
5699 DirectiveKindMap[".cfi_val_offset"] = DK_CFI_VAL_OFFSET;
5700 DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
5701 DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
5702 DirectiveKindMap[".macro"] = DK_MACRO;
5703 DirectiveKindMap[".exitm"] = DK_EXITM;
5704 DirectiveKindMap[".endm"] = DK_ENDM;
5705 DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
5706 DirectiveKindMap[".purgem"] = DK_PURGEM;
5707 DirectiveKindMap[".err"] = DK_ERR;
5708 DirectiveKindMap[".error"] = DK_ERROR;
5709 DirectiveKindMap[".warning"] = DK_WARNING;
5710 DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
5711 DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
5712 DirectiveKindMap[".reloc"] = DK_RELOC;
5713 DirectiveKindMap[".dc"] = DK_DC;
5714 DirectiveKindMap[".dc.a"] = DK_DC_A;
5715 DirectiveKindMap[".dc.b"] = DK_DC_B;
5716 DirectiveKindMap[".dc.d"] = DK_DC_D;
5717 DirectiveKindMap[".dc.l"] = DK_DC_L;
5718 DirectiveKindMap[".dc.s"] = DK_DC_S;
5719 DirectiveKindMap[".dc.w"] = DK_DC_W;
5720 DirectiveKindMap[".dc.x"] = DK_DC_X;
5721 DirectiveKindMap[".dcb"] = DK_DCB;
5722 DirectiveKindMap[".dcb.b"] = DK_DCB_B;
5723 DirectiveKindMap[".dcb.d"] = DK_DCB_D;
5724 DirectiveKindMap[".dcb.l"] = DK_DCB_L;
5725 DirectiveKindMap[".dcb.s"] = DK_DCB_S;
5726 DirectiveKindMap[".dcb.w"] = DK_DCB_W;
5727 DirectiveKindMap[".dcb.x"] = DK_DCB_X;
5728 DirectiveKindMap[".ds"] = DK_DS;
5729 DirectiveKindMap[".ds.b"] = DK_DS_B;
5730 DirectiveKindMap[".ds.d"] = DK_DS_D;
5731 DirectiveKindMap[".ds.l"] = DK_DS_L;
5732 DirectiveKindMap[".ds.p"] = DK_DS_P;
5733 DirectiveKindMap[".ds.s"] = DK_DS_S;
5734 DirectiveKindMap[".ds.w"] = DK_DS_W;
5735 DirectiveKindMap[".ds.x"] = DK_DS_X;
5736 DirectiveKindMap[".print"] = DK_PRINT;
5737 DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
5738 DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
5739 DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE;
5740 DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD;
5741 DirectiveKindMap[".lto_set_conditional"] = DK_LTO_SET_CONDITIONAL;
5742 DirectiveKindMap[".memtag"] = DK_MEMTAG;
5743}
5744
5745MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5746 AsmToken EndToken, StartToken = getTok();
5747
5748 unsigned NestLevel = 0;
5749 while (true) {
5750 // Check whether we have reached the end of the file.
5751 if (getLexer().is(AsmToken::Eof)) {
5752 printError(DirectiveLoc, "no matching '.endr' in definition");
5753 return nullptr;
5754 }
5755
5756 if (Lexer.is(AsmToken::Identifier)) {
5757 StringRef Ident = getTok().getIdentifier();
5758 if (Ident == ".rep" || Ident == ".rept" || Ident == ".irp" ||
5759 Ident == ".irpc") {
5760 ++NestLevel;
5761 } else if (Ident == ".endr") {
5762 if (NestLevel == 0) {
5763 EndToken = getTok();
5764 Lex();
5765 if (Lexer.is(AsmToken::EndOfStatement))
5766 break;
5767 printError(getTok().getLoc(), "expected newline");
5768 return nullptr;
5769 }
5770 --NestLevel;
5771 }
5772 }
5773
5774 // Otherwise, scan till the end of the statement.
5775 eatToEndOfStatement();
5776 }
5777
5778 const char *BodyStart = StartToken.getLoc().getPointer();
5779 const char *BodyEnd = EndToken.getLoc().getPointer();
5780 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5781
5782 // We Are Anonymous.
5783 MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
5784 return &MacroLikeBodies.back();
5785}
5786
5787void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5788 raw_svector_ostream &OS) {
5789 OS << ".endr\n";
5790
5791 std::unique_ptr<MemoryBuffer> Instantiation =
5792 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
5793
5794 // Create the macro instantiation object and add to the current macro
5795 // instantiation stack.
5796 MacroInstantiation *MI = new MacroInstantiation{
5797 DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
5798 ActiveMacros.push_back(MI);
5799
5800 // Jump to the macro instantiation and prime the lexer.
5801 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
5802 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
5803 Lex();
5804}
5805
5806/// parseDirectiveRept
5807/// ::= .rep | .rept count
5808bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
5809 const MCExpr *CountExpr;
5810 SMLoc CountLoc = getTok().getLoc();
5811 if (parseExpression(CountExpr))
5812 return true;
5813
5814 int64_t Count;
5815 if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
5816 return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
5817 }
5818
5819 if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())
5820 return true;
5821
5822 // Lex the rept definition.
5823 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5824 if (!M)
5825 return true;
5826
5827 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5828 // to hold the macro body with substitutions.
5829 SmallString<256> Buf;
5830 raw_svector_ostream OS(Buf);
5831 while (Count--) {
5832 // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
5833 if (expandMacro(OS, *M, {}, {}, false))
5834 return true;
5835 }
5836 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5837
5838 return false;
5839}
5840
5841/// parseDirectiveIrp
5842/// ::= .irp symbol,values
5843bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
5844 MCAsmMacroParameter Parameter;
5845 MCAsmMacroArguments A;
5846 if (check(parseIdentifier(Parameter.Name),
5847 "expected identifier in '.irp' directive") ||
5848 parseComma() || parseMacroArguments(nullptr, A) || parseEOL())
5849 return true;
5850
5851 // Lex the irp definition.
5852 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5853 if (!M)
5854 return true;
5855
5856 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5857 // to hold the macro body with substitutions.
5858 SmallString<256> Buf;
5859 raw_svector_ostream OS(Buf);
5860
5861 for (const MCAsmMacroArgument &Arg : A) {
5862 // Note that the AtPseudoVariable is enabled for instantiations of .irp.
5863 // This is undocumented, but GAS seems to support it.
5864 if (expandMacro(OS, *M, Parameter, Arg, true))
5865 return true;
5866 }
5867
5868 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5869
5870 return false;
5871}
5872
5873/// parseDirectiveIrpc
5874/// ::= .irpc symbol,values
5875bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
5876 MCAsmMacroParameter Parameter;
5877 MCAsmMacroArguments A;
5878
5879 if (check(parseIdentifier(Parameter.Name),
5880 "expected identifier in '.irpc' directive") ||
5881 parseComma() || parseMacroArguments(nullptr, A))
5882 return true;
5883
5884 if (A.size() != 1 || A.front().size() != 1)
5885 return TokError("unexpected token in '.irpc' directive");
5886 if (parseEOL())
5887 return true;
5888
5889 // Lex the irpc definition.
5890 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5891 if (!M)
5892 return true;
5893
5894 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5895 // to hold the macro body with substitutions.
5896 SmallString<256> Buf;
5897 raw_svector_ostream OS(Buf);
5898
5899 StringRef Values = A[0][0].is(AsmToken::String) ? A[0][0].getStringContents()
5900 : A[0][0].getString();
5901 for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
5902 MCAsmMacroArgument Arg;
5903 Arg.emplace_back(AsmToken::Identifier, Values.substr(I, 1));
5904
5905 // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
5906 // This is undocumented, but GAS seems to support it.
5907 if (expandMacro(OS, *M, Parameter, Arg, true))
5908 return true;
5909 }
5910
5911 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5912
5913 return false;
5914}
5915
5916bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
5917 if (ActiveMacros.empty())
5918 return TokError("unmatched '.endr' directive");
5919
5920 // The only .repl that should get here are the ones created by
5921 // instantiateMacroLikeBody.
5922 assert(getLexer().is(AsmToken::EndOfStatement));
5923
5924 handleMacroExit();
5925 return false;
5926}
5927
5928bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5929 size_t Len) {
5930 const MCExpr *Value;
5931 SMLoc ExprLoc = getLexer().getLoc();
5932 if (parseExpression(Value))
5933 return true;
5934 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5935 if (!MCE)
5936 return Error(ExprLoc, "unexpected expression in _emit");
5937 uint64_t IntValue = MCE->getValue();
5938 if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
5939 return Error(ExprLoc, "literal value out of range for directive");
5940
5941 Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
5942 return false;
5943}
5944
5945bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5946 const MCExpr *Value;
5947 SMLoc ExprLoc = getLexer().getLoc();
5948 if (parseExpression(Value))
5949 return true;
5950 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5951 if (!MCE)
5952 return Error(ExprLoc, "unexpected expression in align");
5953 uint64_t IntValue = MCE->getValue();
5954 if (!isPowerOf2_64(IntValue))
5955 return Error(ExprLoc, "literal value not a power of two greater then zero");
5956
5957 Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
5958 return false;
5959}
5960
5961bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
5962 const AsmToken StrTok = getTok();
5963 Lex();
5964 if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
5965 return Error(DirectiveLoc, "expected double quoted string after .print");
5966 if (parseEOL())
5967 return true;
5968 llvm::outs() << StrTok.getStringContents() << '\n';
5969 return false;
5970}
5971
5972bool AsmParser::parseDirectiveAddrsig() {
5973 if (parseEOL())
5974 return true;
5975 getStreamer().emitAddrsig();
5976 return false;
5977}
5978
5979bool AsmParser::parseDirectiveAddrsigSym() {
5980 MCSymbol *Sym;
5981 if (check(parseSymbol(Sym), "expected identifier") || parseEOL())
5982 return true;
5983 getStreamer().emitAddrsigSym(Sym);
5984 return false;
5985}
5986
5987bool AsmParser::parseDirectivePseudoProbe() {
5988 int64_t Guid;
5989 int64_t Index;
5990 int64_t Type;
5991 int64_t Attr;
5992 int64_t Discriminator = 0;
5993 if (parseIntToken(Guid))
5994 return true;
5995 if (parseIntToken(Index))
5996 return true;
5997 if (parseIntToken(Type))
5998 return true;
5999 if (parseIntToken(Attr))
6000 return true;
6001 if (hasDiscriminator(Attr) && parseIntToken(Discriminator))
6002 return true;
6003
6004 // Parse inline stack like @ GUID:11:12 @ GUID:1:11 @ GUID:3:21
6005 MCPseudoProbeInlineStack InlineStack;
6006
6007 while (getLexer().is(AsmToken::At)) {
6008 // eat @
6009 Lex();
6010
6011 int64_t CallerGuid = 0;
6012 if (getLexer().is(AsmToken::Integer)) {
6013 CallerGuid = getTok().getIntVal();
6014 Lex();
6015 }
6016
6017 // eat colon
6018 if (getLexer().is(AsmToken::Colon))
6019 Lex();
6020
6021 int64_t CallerProbeId = 0;
6022 if (getLexer().is(AsmToken::Integer)) {
6023 CallerProbeId = getTok().getIntVal();
6024 Lex();
6025 }
6026
6027 InlineSite Site(CallerGuid, CallerProbeId);
6028 InlineStack.push_back(Site);
6029 }
6030
6031 // Parse function entry name
6032 StringRef FnName;
6033 if (parseIdentifier(FnName))
6034 return Error(getLexer().getLoc(), "expected identifier");
6035 MCSymbol *FnSym = getContext().lookupSymbol(FnName);
6036
6037 if (parseEOL())
6038 return true;
6039
6040 getStreamer().emitPseudoProbe(Guid, Index, Type, Attr, Discriminator,
6041 InlineStack, FnSym);
6042 return false;
6043}
6044
6045/// parseDirectiveLTODiscard
6046/// ::= ".lto_discard" [ identifier ( , identifier )* ]
6047/// The LTO library emits this directive to discard non-prevailing symbols.
6048/// We ignore symbol assignments and attribute changes for the specified
6049/// symbols.
6050bool AsmParser::parseDirectiveLTODiscard() {
6051 auto ParseOp = [&]() -> bool {
6052 StringRef Name;
6053 SMLoc Loc = getTok().getLoc();
6054 if (parseIdentifier(Name))
6055 return Error(Loc, "expected identifier");
6056 LTODiscardSymbols.insert(Name);
6057 return false;
6058 };
6059
6060 LTODiscardSymbols.clear();
6061 return parseMany(ParseOp);
6062}
6063
6064// We are comparing pointers, but the pointers are relative to a single string.
6065// Thus, this should always be deterministic.
6066static int rewritesSort(const AsmRewrite *AsmRewriteA,
6067 const AsmRewrite *AsmRewriteB) {
6068 if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
6069 return -1;
6070 if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
6071 return 1;
6072
6073 // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
6074 // rewrite to the same location. Make sure the SizeDirective rewrite is
6075 // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
6076 // ensures the sort algorithm is stable.
6077 if (AsmRewritePrecedence[AsmRewriteA->Kind] >
6078 AsmRewritePrecedence[AsmRewriteB->Kind])
6079 return -1;
6080
6081 if (AsmRewritePrecedence[AsmRewriteA->Kind] <
6082 AsmRewritePrecedence[AsmRewriteB->Kind])
6083 return 1;
6084 llvm_unreachable("Unstable rewrite sort.");
6085}
6086
6087bool AsmParser::parseMSInlineAsm(
6088 std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,
6089 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
6090 SmallVectorImpl<std::string> &Constraints,
6091 SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
6092 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
6093 SmallVector<void *, 4> InputDecls;
6094 SmallVector<void *, 4> OutputDecls;
6095 SmallVector<bool, 4> InputDeclsAddressOf;
6096 SmallVector<bool, 4> OutputDeclsAddressOf;
6097 SmallVector<std::string, 4> InputConstraints;
6098 SmallVector<std::string, 4> OutputConstraints;
6099 SmallVector<MCRegister, 4> ClobberRegs;
6100
6101 SmallVector<AsmRewrite, 4> AsmStrRewrites;
6102
6103 // Prime the lexer.
6104 Lex();
6105
6106 // While we have input, parse each statement.
6107 unsigned InputIdx = 0;
6108 unsigned OutputIdx = 0;
6109 while (getLexer().isNot(AsmToken::Eof)) {
6110 // Parse curly braces marking block start/end
6111 if (parseCurlyBlockScope(AsmStrRewrites))
6112 continue;
6113
6114 ParseStatementInfo Info(&AsmStrRewrites);
6115 bool StatementErr = parseStatement(Info, &SI);
6116
6117 if (StatementErr || Info.ParseError) {
6118 // Emit pending errors if any exist.
6119 printPendingErrors();
6120 return true;
6121 }
6122
6123 // No pending error should exist here.
6124 assert(!hasPendingError() && "unexpected error from parseStatement");
6125
6126 if (Info.Opcode == ~0U)
6127 continue;
6128
6129 const MCInstrDesc &Desc = MII->get(Info.Opcode);
6130
6131 // Build the list of clobbers, outputs and inputs.
6132 for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
6133 MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
6134
6135 // Register operand.
6136 if (Operand.isReg() && !Operand.needAddressOf() &&
6137 !getTargetParser().omitRegisterFromClobberLists(Operand.getReg())) {
6138 unsigned NumDefs = Desc.getNumDefs();
6139 // Clobber.
6140 if (NumDefs && Operand.getMCOperandNum() < NumDefs)
6141 ClobberRegs.push_back(Operand.getReg());
6142 continue;
6143 }
6144
6145 // Expr/Input or Output.
6146 StringRef SymName = Operand.getSymName();
6147 if (SymName.empty())
6148 continue;
6149
6150 void *OpDecl = Operand.getOpDecl();
6151 if (!OpDecl)
6152 continue;
6153
6154 StringRef Constraint = Operand.getConstraint();
6155 if (Operand.isImm()) {
6156 // Offset as immediate
6157 if (Operand.isOffsetOfLocal())
6158 Constraint = "r";
6159 else
6160 Constraint = "i";
6161 }
6162
6163 bool isOutput = (i == 1) && Desc.mayStore();
6164 bool Restricted = Operand.isMemUseUpRegs();
6165 SMLoc Start = SMLoc::getFromPointer(SymName.data());
6166 if (isOutput) {
6167 ++InputIdx;
6168 OutputDecls.push_back(OpDecl);
6169 OutputDeclsAddressOf.push_back(Operand.needAddressOf());
6170 OutputConstraints.push_back(("=" + Constraint).str());
6171 AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size(), 0,
6172 Restricted);
6173 } else {
6174 InputDecls.push_back(OpDecl);
6175 InputDeclsAddressOf.push_back(Operand.needAddressOf());
6176 InputConstraints.push_back(Constraint.str());
6177 if (Desc.operands()[i - 1].isBranchTarget())
6178 AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size(), 0,
6179 Restricted);
6180 else
6181 AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size(), 0,
6182 Restricted);
6183 }
6184 }
6185
6186 // Consider implicit defs to be clobbers. Think of cpuid and push.
6187 llvm::append_range(ClobberRegs, Desc.implicit_defs());
6188 }
6189
6190 // Set the number of Outputs and Inputs.
6191 NumOutputs = OutputDecls.size();
6192 NumInputs = InputDecls.size();
6193
6194 // Set the unique clobbers.
6195 array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
6196 ClobberRegs.erase(llvm::unique(ClobberRegs), ClobberRegs.end());
6197 Clobbers.assign(ClobberRegs.size(), std::string());
6198 for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
6199 raw_string_ostream OS(Clobbers[I]);
6200 IP->printRegName(OS, ClobberRegs[I]);
6201 }
6202
6203 // Merge the various outputs and inputs. Output are expected first.
6204 if (NumOutputs || NumInputs) {
6205 unsigned NumExprs = NumOutputs + NumInputs;
6206 OpDecls.resize(NumExprs);
6207 Constraints.resize(NumExprs);
6208 for (unsigned i = 0; i < NumOutputs; ++i) {
6209 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
6210 Constraints[i] = OutputConstraints[i];
6211 }
6212 for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
6213 OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6214 Constraints[j] = InputConstraints[i];
6215 }
6216 }
6217
6218 // Build the IR assembly string.
6219 std::string AsmStringIR;
6220 raw_string_ostream OS(AsmStringIR);
6221 StringRef ASMString =
6223 const char *AsmStart = ASMString.begin();
6224 const char *AsmEnd = ASMString.end();
6225 array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
6226 for (auto I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {
6227 const AsmRewrite &AR = *I;
6228 // Check if this has already been covered by another rewrite...
6229 if (AR.Done)
6230 continue;
6232
6233 const char *Loc = AR.Loc.getPointer();
6234 assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
6235
6236 // Emit everything up to the immediate/expression.
6237 if (unsigned Len = Loc - AsmStart)
6238 OS << StringRef(AsmStart, Len);
6239
6240 // Skip the original expression.
6241 if (Kind == AOK_Skip) {
6242 AsmStart = Loc + AR.Len;
6243 continue;
6244 }
6245
6246 unsigned AdditionalSkip = 0;
6247 // Rewrite expressions in $N notation.
6248 switch (Kind) {
6249 default:
6250 break;
6251 case AOK_IntelExpr:
6252 assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
6253 if (AR.IntelExp.NeedBracs)
6254 OS << "[";
6255 if (AR.IntelExp.hasBaseReg())
6256 OS << AR.IntelExp.BaseReg;
6257 if (AR.IntelExp.hasIndexReg())
6258 OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
6259 << AR.IntelExp.IndexReg;
6260 if (AR.IntelExp.Scale > 1)
6261 OS << " * $$" << AR.IntelExp.Scale;
6262 if (AR.IntelExp.hasOffset()) {
6263 if (AR.IntelExp.hasRegs())
6264 OS << " + ";
6265 // Fuse this rewrite with a rewrite of the offset name, if present.
6266 StringRef OffsetName = AR.IntelExp.OffsetName;
6267 SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
6268 size_t OffsetLen = OffsetName.size();
6269 auto rewrite_it = std::find_if(
6270 I, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
6271 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6272 (FusingAR.Kind == AOK_Input ||
6273 FusingAR.Kind == AOK_CallInput);
6274 });
6275 if (rewrite_it == AsmStrRewrites.end()) {
6276 OS << "offset " << OffsetName;
6277 } else if (rewrite_it->Kind == AOK_CallInput) {
6278 OS << "${" << InputIdx++ << ":P}";
6279 rewrite_it->Done = true;
6280 } else {
6281 OS << '$' << InputIdx++;
6282 rewrite_it->Done = true;
6283 }
6284 }
6285 if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
6286 OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
6287 if (AR.IntelExp.NeedBracs)
6288 OS << "]";
6289 break;
6290 case AOK_Label:
6291 OS << Ctx.getAsmInfo().getPrivateLabelPrefix() << AR.Label;
6292 break;
6293 case AOK_Input:
6294 if (AR.IntelExpRestricted)
6295 OS << "${" << InputIdx++ << ":P}";
6296 else
6297 OS << '$' << InputIdx++;
6298 break;
6299 case AOK_CallInput:
6300 OS << "${" << InputIdx++ << ":P}";
6301 break;
6302 case AOK_Output:
6303 if (AR.IntelExpRestricted)
6304 OS << "${" << OutputIdx++ << ":P}";
6305 else
6306 OS << '$' << OutputIdx++;
6307 break;
6308 case AOK_SizeDirective:
6309 switch (AR.Val) {
6310 default: break;
6311 case 8: OS << "byte ptr "; break;
6312 case 16: OS << "word ptr "; break;
6313 case 32: OS << "dword ptr "; break;
6314 case 64: OS << "qword ptr "; break;
6315 case 80: OS << "xword ptr "; break;
6316 case 128: OS << "xmmword ptr "; break;
6317 case 256: OS << "ymmword ptr "; break;
6318 }
6319 break;
6320 case AOK_Emit:
6321 OS << ".byte";
6322 break;
6323 case AOK_Align: {
6324 // MS alignment directives are measured in bytes. If the native assembler
6325 // measures alignment in bytes, we can pass it straight through.
6326 OS << ".align";
6327 if (getContext().getAsmInfo().getAlignmentIsInBytes())
6328 break;
6329
6330 // Alignment is in log2 form, so print that instead and skip the original
6331 // immediate.
6332 unsigned Val = AR.Val;
6333 OS << ' ' << Val;
6334 assert(Val < 10 && "Expected alignment less then 2^10.");
6335 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6336 break;
6337 }
6338 case AOK_EVEN:
6339 OS << ".even";
6340 break;
6341 case AOK_EndOfStatement:
6342 OS << "\n\t";
6343 break;
6344 }
6345
6346 // Skip the original expression.
6347 AsmStart = Loc + AR.Len + AdditionalSkip;
6348 }
6349
6350 // Emit the remainder of the asm string.
6351 if (AsmStart != AsmEnd)
6352 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6353
6354 AsmString = std::move(AsmStringIR);
6355 return false;
6356}
6357
6358bool HLASMAsmParser::parseAsHLASMLabel(ParseStatementInfo &Info,
6359 MCAsmParserSemaCallback *SI) {
6360 AsmToken LabelTok = getTok();
6361 SMLoc LabelLoc = LabelTok.getLoc();
6362 StringRef LabelVal;
6363
6364 if (parseIdentifier(LabelVal))
6365 return Error(LabelLoc, "The HLASM Label has to be an Identifier");
6366
6367 // We have validated whether the token is an Identifier.
6368 // Now we have to validate whether the token is a
6369 // valid HLASM Label.
6370 if (!getTargetParser().isLabel(LabelTok) || checkForValidSection())
6371 return true;
6372
6373 // Lex leading spaces to get to the next operand.
6374 lexLeadingSpaces();
6375
6376 // We shouldn't emit the label if there is nothing else after the label.
6377 // i.e asm("<token>\n")
6378 if (getTok().is(AsmToken::EndOfStatement))
6379 return Error(LabelLoc,
6380 "Cannot have just a label for an HLASM inline asm statement");
6381
6382 MCSymbol *Sym = getContext().parseSymbol(
6383 getContext().getAsmInfo().isHLASM() ? LabelVal.upper() : LabelVal);
6384
6385 // Emit the label.
6386 Out.emitLabel(Sym, LabelLoc);
6387
6388 // If we are generating dwarf for assembly source files then gather the
6389 // info to make a dwarf label entry for this label if needed.
6390 if (enabledGenDwarfForAssembly())
6391 MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
6392 LabelLoc);
6393
6394 return false;
6395}
6396
6397bool HLASMAsmParser::parseAsMachineInstruction(ParseStatementInfo &Info,
6398 MCAsmParserSemaCallback *SI) {
6399 AsmToken OperationEntryTok = Lexer.getTok();
6400 SMLoc OperationEntryLoc = OperationEntryTok.getLoc();
6401 StringRef OperationEntryVal;
6402
6403 // Attempt to parse the first token as an Identifier
6404 if (parseIdentifier(OperationEntryVal))
6405 return Error(OperationEntryLoc, "unexpected token at start of statement");
6406
6407 // Once we've parsed the operation entry successfully, lex
6408 // any spaces to get to the OperandEntries.
6409 lexLeadingSpaces();
6410
6411 return parseAndMatchAndEmitTargetInstruction(
6412 Info, OperationEntryVal, OperationEntryTok, OperationEntryLoc);
6413}
6414
6415bool HLASMAsmParser::parseStatement(ParseStatementInfo &Info,
6416 MCAsmParserSemaCallback *SI) {
6417 assert(!hasPendingError() && "parseStatement started with pending error");
6418
6419 // Should the first token be interpreted as a HLASM Label.
6420 bool ShouldParseAsHLASMLabel = false;
6421
6422 // If a Name Entry exists, it should occur at the very
6423 // start of the string. In this case, we should parse the
6424 // first non-space token as a Label.
6425 // If the Name entry is missing (i.e. there's some other
6426 // token), then we attempt to parse the first non-space
6427 // token as a Machine Instruction.
6428 if (getTok().isNot(AsmToken::Space))
6429 ShouldParseAsHLASMLabel = true;
6430
6431 // If we have an EndOfStatement (which includes the target's comment
6432 // string) we can appropriately lex it early on)
6433 if (Lexer.is(AsmToken::EndOfStatement)) {
6434 // if this is a line comment we can drop it safely
6435 if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
6436 getTok().getString().front() == '\n')
6437 Out.addBlankLine();
6438 Lex();
6439 return false;
6440 }
6441
6442 // We have established how to parse the inline asm statement.
6443 // Now we can safely lex any leading spaces to get to the
6444 // first token.
6445 lexLeadingSpaces();
6446
6447 // If we see a new line or carriage return as the first operand,
6448 // after lexing leading spaces, emit the new line and lex the
6449 // EndOfStatement token.
6450 if (Lexer.is(AsmToken::EndOfStatement)) {
6451 if (getTok().getString().front() == '\n' ||
6452 getTok().getString().front() == '\r') {
6453 Out.addBlankLine();
6454 Lex();
6455 return false;
6456 }
6457 }
6458
6459 // Handle the label first if we have to before processing the rest
6460 // of the tokens as a machine instruction.
6461 if (ShouldParseAsHLASMLabel) {
6462 // If there were any errors while handling and emitting the label,
6463 // early return.
6464 if (parseAsHLASMLabel(Info, SI)) {
6465 // If we know we've failed in parsing, simply eat until end of the
6466 // statement. This ensures that we don't process any other statements.
6467 eatToEndOfStatement();
6468 return true;
6469 }
6470 }
6471
6472 return parseAsMachineInstruction(Info, SI);
6473}
6474
6476 bool allow_redef,
6477 MCAsmParser &Parser,
6478 MCSymbol *&Sym,
6479 const MCExpr *&Value) {
6480
6481 // FIXME: Use better location, we should use proper tokens.
6482 SMLoc EqualLoc = Parser.getTok().getLoc();
6483 if (Parser.parseExpression(Value))
6484 return Parser.TokError("missing expression");
6485 if (Parser.parseEOL())
6486 return true;
6487 // Relocation specifiers are not permitted. For now, handle just
6488 // MCSymbolRefExpr.
6489 if (auto *S = dyn_cast<MCSymbolRefExpr>(Value); S && S->getSpecifier())
6490 return Parser.Error(
6491 EqualLoc, "relocation specifier not permitted in symbol equating");
6492
6493 // Validate that the LHS is allowed to be a variable (either it has not been
6494 // used as a symbol, or it is an absolute symbol).
6495 Sym = Parser.getContext().lookupSymbol(Name);
6496 if (Sym) {
6497 if ((Sym->isVariable() || Sym->isDefined()) &&
6498 (!allow_redef || !Sym->isRedefinable()))
6499 return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
6500 // If the symbol is redefinable, clone it and update the symbol table
6501 // to the new symbol. Existing references to the original symbol remain
6502 // unchanged.
6503 if (Sym->isRedefinable())
6504 Sym = Parser.getContext().cloneSymbol(*Sym);
6505 } else if (Name == ".") {
6506 Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
6507 return false;
6508 } else
6509 Sym = Parser.getContext().parseSymbol(Name);
6510
6511 Sym->setRedefinable(allow_redef);
6512
6513 return false;
6514}
6515
6516/// Create an MCAsmParser instance.
6518 MCStreamer &Out, const MCAsmInfo &MAI,
6519 unsigned CB) {
6520 if (C.getTargetTriple().isSystemZ() && C.getTargetTriple().isOSzOS())
6521 return new HLASMAsmParser(SM, C, Out, MAI, CB);
6522
6523 return new AsmParser(SM, C, Out, MAI, CB);
6524}
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:1157
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Definition APFloat.h:1168
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:735
bool isHLASM() const
Definition MCAsmInfo.h:540
bool isLittleEndian() const
True if the target is little endian.
Definition MCAsmInfo.h:464
bool useAtForSpecifier() const
Definition MCAsmInfo.h:690
bool doesAllowAtInName() const
Definition MCAsmInfo.h:586
StringRef getPrivateLabelPrefix() const
Definition MCAsmInfo.h:566
std::optional< uint32_t > getSpecifierForName(StringRef Name) const
LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const
Definition MCAsmInfo.h:626
bool shouldUseLogicalShr() const
Definition MCAsmInfo.h:743
StringRef getCommentString() const
Definition MCAsmInfo.h:558
bool hasSubsectionsViaSymbols() const
Definition MCAsmInfo.h:469
bool getCOMMDirectiveAlignmentIsInBytes() const
Definition MCAsmInfo.h:622
virtual bool useCodeAlign(const MCSection &Sec) const
Definition MCAsmInfo.h:523
bool useParensForSpecifier() const
Definition MCAsmInfo.h:691
bool isMachO() const
Definition MCAsmInfo.h:541
bool getDollarIsPC() const
Definition MCAsmInfo.h:552
Generic assembler parser interface, for use by target specific assembly parsers.
bool Error(SMLoc L, const Twine &Msg, SMRange Range={})
Return an error at the location L, with the message Msg.
MCContext & getContext()
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
AsmLexer & getLexer()
bool parseAtSpecifier(const MCExpr *&Res, SMLoc &EndLoc)
const AsmToken & getTok() const
Get the current AsmToken from the stream.
const MCExpr * applySpecifier(const MCExpr *E, uint32_t Variant)
bool parseOptionalToken(AsmToken::TokenKind T)
Attempt to parse and consume token, returning true on success.
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
bool TokError(const Twine &Msg, SMRange Range={})
Report an error at the current lexer location.
MCContext & Ctx
const MCAsmInfo & MAI
MCStreamer & getStreamer()
MCTargetAsmParser & getTargetParser() const
Binary assembler expressions.
Definition MCExpr.h:299
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
Definition MCExpr.h:446
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Definition MCExpr.h:449
Opcode getOpcode() const
Get the kind of this binary expression.
Definition MCExpr.h:443
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:201
@ Div
Signed division.
Definition MCExpr.h:304
@ Shl
Shift left.
Definition MCExpr.h:321
@ AShr
Arithmetic shift right.
Definition MCExpr.h:322
@ LShr
Logical shift right.
Definition MCExpr.h:323
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
Definition MCExpr.h:308
@ EQ
Equality comparison.
Definition MCExpr.h:305
@ Sub
Subtraction.
Definition MCExpr.h:324
@ Mul
Multiplication.
Definition MCExpr.h:317
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
Definition MCExpr.h:306
@ Mod
Signed remainder.
Definition MCExpr.h:316
@ And
Bitwise and.
Definition MCExpr.h:303
@ Or
Bitwise or.
Definition MCExpr.h:319
@ Xor
Bitwise exclusive or.
Definition MCExpr.h:325
@ OrNot
Bitwise or not.
Definition MCExpr.h:320
@ LAnd
Logical and.
Definition MCExpr.h:310
@ LOr
Logical or.
Definition MCExpr.h:311
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
Definition MCExpr.h:312
@ Add
Addition.
Definition MCExpr.h:302
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
Definition MCExpr.h:314
@ NE
Inequality comparison.
Definition MCExpr.h:318
int64_t getValue() const
Definition MCExpr.h:171
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
void * allocate(unsigned Size, unsigned Align=8)
Definition MCContext.h:828
bool isDwarfMD5UsageConsistent(unsigned CUID) const
Reports whether MD5 checksum usage is consistent (all-or-none).
Definition MCContext.h:747
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
bool getGenDwarfForAssembly()
Definition MCContext.h:772
void setGenDwarfForAssembly(bool Value)
Definition MCContext.h:773
void setDwarfVersion(uint16_t v)
Definition MCContext.h:813
MCDwarfLineTable & getMCDwarfLineTable(unsigned CUID)
Definition MCContext.h:714
LLVM_ABI MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
LLVM_ABI MCSymbol * createDirectionalLocalSymbol(unsigned LocalLabelVal)
Create the definition of a directional local symbol for numbered label (used for "1:" definitions).
uint16_t getDwarfVersion() const
Definition MCContext.h:814
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:1268
virtual void printRegName(raw_ostream &OS, MCRegister Reg)
Print the assembler register name.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:90
virtual bool isMemUseUpRegs() const
isMemUseUpRegs - Is memory operand use up regs, for example, intel MS inline asm may use ARR[baseReg ...
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool needAddressOf() const
needAddressOf - Do we need to emit code to get the address of the variable/label?
virtual MCRegister getReg() const =0
virtual bool isOffsetOfLocal() const
isOffsetOfLocal - Do we need to emit code to get the offset of the local variable,...
virtual StringRef getSymName()
virtual bool isImm() const =0
isImm - Is this an immediate operand?
void setBeginSymbol(MCSymbol *Sym)
Definition MCSection.h: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:415
void setStartTokLocPtr(const SMLoc *Loc)
Definition MCStreamer.h:310
virtual bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute)=0
Add the given Attribute to Symbol.
virtual void addExplicitComment(const Twine &T)
Add explicit comment T.
virtual void initSections(const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
MCTargetStreamer * getTargetStreamer()
Definition MCStreamer.h:333
MCLFIRewriter * getLFIRewriter()
Definition MCStreamer.h:317
virtual void emitValueToOffset(const MCExpr *Offset, unsigned char Value, SMLoc Loc)
Emit some number of copies of Value until the byte offset Offset is reached.
virtual void emitConditionalAssignment(MCSymbol *Symbol, const MCExpr *Value)
Emit an assignment of Value to Symbol, but only if Value is also emitted.
void finish(SMLoc EndLoc=SMLoc())
Finish emission of machine code.
Represent a reference to a symbol from inside an expression.
Definition MCExpr.h:190
const MCSymbol & getSymbol() const
Definition MCExpr.h:227
uint16_t getSpecifier() const
Definition MCExpr.h:233
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
bool isDefined() const
isDefined - Check if this symbol is defined (i.e., it has an address).
Definition MCSymbol.h:233
bool isUndefined() const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).
Definition MCSymbol.h:243
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition MCSymbol.h:267
bool isRedefinable() const
Check if this symbol is redefinable.
Definition MCSymbol.h:208
void setRedefinable(bool Value)
Mark this symbol as redefinable.
Definition MCSymbol.h:210
void redefineIfPossible()
Prepare this symbol to be redefined.
Definition MCSymbol.h:212
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
Definition MCSymbol.h:270
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
Definition MCSymbol.h:205
Unary assembler expressions.
Definition MCExpr.h:243
Opcode getOpcode() const
Get the kind of this unary expression.
Definition MCExpr.h:286
static LLVM_ABI const MCUnaryExpr * create(Opcode Op, const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:207
static const MCUnaryExpr * createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:265
const MCExpr * getSubExpr() const
Get the child of this unary expression.
Definition MCExpr.h:289
static const MCUnaryExpr * createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:277
static const MCUnaryExpr * createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:273
static const MCUnaryExpr * createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:269
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
StringRef getBuffer() const
constexpr bool isFailure() const
constexpr bool isSuccess() const
SourceMgr::DiagKind getKind() const
Definition SourceMgr.h: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:260
StringMapIterBase< ValueTy, true > const_iterator
Definition StringMap.h:220
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.
bool parseAssignmentExpression(StringRef Name, bool allow_redef, MCAsmParser &Parser, MCSymbol *&Symbol, const MCExpr *&Value)
Parse a value expression and return whether it can be assigned to a symbol with the given name.
LLVM_ABI SimpleSymbol parseSymbol(StringRef SymName)
Get symbol classification by parsing the name of a symbol.
Definition Symbol.cpp:75
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
Definition MCDCTypes.h:56
@ DW_EH_PE_pcrel
Definition Dwarf.h:879
@ DW_EH_PE_signed
Definition Dwarf.h:878
@ DW_EH_PE_sdata4
Definition Dwarf.h:876
@ DW_EH_PE_udata2
Definition Dwarf.h:871
@ DW_EH_PE_sdata8
Definition Dwarf.h:877
@ DW_EH_PE_absptr
Definition Dwarf.h:868
@ DW_EH_PE_sdata2
Definition Dwarf.h:875
@ DW_EH_PE_udata4
Definition Dwarf.h:872
@ DW_EH_PE_udata8
Definition Dwarf.h:873
@ DW_EH_PE_omit
Definition Dwarf.h:869
@ Parameter
An inlay hint that is for a parameter.
Definition Protocol.h:1147
constexpr double e
bool empty() const
Definition BasicBlock.h:101
Context & getContext() const
Definition BasicBlock.h:99
LLVM_ABI Instruction & front() const
This is an optimization pass for GlobalISel generic memory operations.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition Error.h:1129
@ Offset
Definition DWP.cpp:557
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
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.