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