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