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