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