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