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