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 StringRef FnStartName, FnEndName;
3880 SMLoc Loc = getTok().getLoc();
3881 if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() ||
3882 parseTokenLoc(Loc) ||
3883 check(parseIdentifier(FnStartName), Loc,
3884 "expected identifier in directive") ||
3885 parseComma() || parseTokenLoc(Loc) ||
3886 check(parseIdentifier(FnEndName), Loc,
3887 "expected identifier in directive"))
3888 return true;
3889
3890 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
3891 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
3892
3893 getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
3894 return false;
3895}
3896
3897/// parseDirectiveCVInlineLinetable
3898/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
3899bool AsmParser::parseDirectiveCVInlineLinetable() {
3900 int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
3901 StringRef FnStartName, FnEndName;
3902 SMLoc Loc = getTok().getLoc();
3903 if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
3904 parseTokenLoc(Loc) ||
3905 parseIntToken(SourceFileId, "expected SourceField") ||
3906 check(SourceFileId <= 0, Loc, "File id less than zero") ||
3907 parseTokenLoc(Loc) ||
3908 parseIntToken(SourceLineNum, "expected SourceLineNum") ||
3909 check(SourceLineNum < 0, Loc, "Line number less than zero") ||
3910 parseTokenLoc(Loc) ||
3911 check(parseIdentifier(FnStartName), Loc, "expected identifier") ||
3912 parseTokenLoc(Loc) ||
3913 check(parseIdentifier(FnEndName), Loc, "expected identifier"))
3914 return true;
3915
3916 if (parseEOL())
3917 return true;
3918
3919 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
3920 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
3921 getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
3922 SourceLineNum, FnStartSym,
3923 FnEndSym);
3924 return false;
3925}
3926
3927void AsmParser::initializeCVDefRangeTypeMap() {
3928 CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
3929 CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
3930 CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
3931 CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
3932}
3933
3934/// parseDirectiveCVDefRange
3935/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
3936bool AsmParser::parseDirectiveCVDefRange() {
3937 SMLoc Loc;
3938 std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
3939 while (getLexer().is(AsmToken::Identifier)) {
3940 Loc = getLexer().getLoc();
3941 StringRef GapStartName;
3942 if (parseIdentifier(GapStartName))
3943 return Error(Loc, "expected identifier in directive");
3944 MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
3945
3946 Loc = getLexer().getLoc();
3947 StringRef GapEndName;
3948 if (parseIdentifier(GapEndName))
3949 return Error(Loc, "expected identifier in directive");
3950 MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
3951
3952 Ranges.push_back({GapStartSym, GapEndSym});
3953 }
3954
3955 StringRef CVDefRangeTypeStr;
3956 if (parseToken(
3958 "expected comma before def_range type in .cv_def_range directive") ||
3959 parseIdentifier(CVDefRangeTypeStr))
3960 return Error(Loc, "expected def_range type in directive");
3961
3963 CVDefRangeTypeMap.find(CVDefRangeTypeStr);
3964 CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
3965 ? CVDR_DEFRANGE
3966 : CVTypeIt->getValue();
3967 switch (CVDRType) {
3968 case CVDR_DEFRANGE_REGISTER: {
3969 int64_t DRRegister;
3970 if (parseToken(AsmToken::Comma, "expected comma before register number in "
3971 ".cv_def_range directive") ||
3972 parseAbsoluteExpression(DRRegister))
3973 return Error(Loc, "expected register number");
3974
3975 codeview::DefRangeRegisterHeader DRHdr;
3976 DRHdr.Register = DRRegister;
3977 DRHdr.MayHaveNoName = 0;
3978 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
3979 break;
3980 }
3981 case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
3982 int64_t DROffset;
3983 if (parseToken(AsmToken::Comma,
3984 "expected comma before offset in .cv_def_range directive") ||
3985 parseAbsoluteExpression(DROffset))
3986 return Error(Loc, "expected offset value");
3987
3988 codeview::DefRangeFramePointerRelHeader DRHdr;
3989 DRHdr.Offset = DROffset;
3990 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
3991 break;
3992 }
3993 case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
3994 int64_t DRRegister;
3995 int64_t DROffsetInParent;
3996 if (parseToken(AsmToken::Comma, "expected comma before register number in "
3997 ".cv_def_range directive") ||
3998 parseAbsoluteExpression(DRRegister))
3999 return Error(Loc, "expected register number");
4000 if (parseToken(AsmToken::Comma,
4001 "expected comma before offset in .cv_def_range directive") ||
4002 parseAbsoluteExpression(DROffsetInParent))
4003 return Error(Loc, "expected offset value");
4004
4005 codeview::DefRangeSubfieldRegisterHeader DRHdr;
4006 DRHdr.Register = DRRegister;
4007 DRHdr.MayHaveNoName = 0;
4008 DRHdr.OffsetInParent = DROffsetInParent;
4009 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4010 break;
4011 }
4012 case CVDR_DEFRANGE_REGISTER_REL: {
4013 int64_t DRRegister;
4014 int64_t DRFlags;
4015 int64_t DRBasePointerOffset;
4016 if (parseToken(AsmToken::Comma, "expected comma before register number in "
4017 ".cv_def_range directive") ||
4018 parseAbsoluteExpression(DRRegister))
4019 return Error(Loc, "expected register value");
4020 if (parseToken(
4022 "expected comma before flag value in .cv_def_range directive") ||
4023 parseAbsoluteExpression(DRFlags))
4024 return Error(Loc, "expected flag value");
4025 if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
4026 "in .cv_def_range directive") ||
4027 parseAbsoluteExpression(DRBasePointerOffset))
4028 return Error(Loc, "expected base pointer offset value");
4029
4030 codeview::DefRangeRegisterRelHeader DRHdr;
4031 DRHdr.Register = DRRegister;
4032 DRHdr.Flags = DRFlags;
4033 DRHdr.BasePointerOffset = DRBasePointerOffset;
4034 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
4035 break;
4036 }
4037 default:
4038 return Error(Loc, "unexpected def_range type in .cv_def_range directive");
4039 }
4040 return true;
4041}
4042
4043/// parseDirectiveCVString
4044/// ::= .cv_stringtable "string"
4045bool AsmParser::parseDirectiveCVString() {
4046 std::string Data;
4047 if (checkForValidSection() || parseEscapedString(Data))
4048 return true;
4049
4050 // Put the string in the table and emit the offset.
4051 std::pair<StringRef, unsigned> Insertion =
4052 getCVContext().addToStringTable(Data);
4053 getStreamer().emitInt32(Insertion.second);
4054 return false;
4055}
4056
4057/// parseDirectiveCVStringTable
4058/// ::= .cv_stringtable
4059bool AsmParser::parseDirectiveCVStringTable() {
4060 getStreamer().emitCVStringTableDirective();
4061 return false;
4062}
4063
4064/// parseDirectiveCVFileChecksums
4065/// ::= .cv_filechecksums
4066bool AsmParser::parseDirectiveCVFileChecksums() {
4067 getStreamer().emitCVFileChecksumsDirective();
4068 return false;
4069}
4070
4071/// parseDirectiveCVFileChecksumOffset
4072/// ::= .cv_filechecksumoffset fileno
4073bool AsmParser::parseDirectiveCVFileChecksumOffset() {
4074 int64_t FileNo;
4075 if (parseIntToken(FileNo))
4076 return true;
4077 if (parseEOL())
4078 return true;
4079 getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
4080 return false;
4081}
4082
4083/// parseDirectiveCVFPOData
4084/// ::= .cv_fpo_data procsym
4085bool AsmParser::parseDirectiveCVFPOData() {
4086 SMLoc DirLoc = getLexer().getLoc();
4087 StringRef ProcName;
4088 if (parseIdentifier(ProcName))
4089 return TokError("expected symbol name");
4090 if (parseEOL())
4091 return true;
4092 MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
4093 getStreamer().emitCVFPOData(ProcSym, DirLoc);
4094 return false;
4095}
4096
4097/// parseDirectiveCFISections
4098/// ::= .cfi_sections section [, section][, section]
4099bool AsmParser::parseDirectiveCFISections() {
4100 StringRef Name;
4101 bool EH = false;
4102 bool Debug = false;
4103 bool SFrame = false;
4104
4105 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4106 for (;;) {
4107 if (parseIdentifier(Name))
4108 return TokError("expected .eh_frame, .debug_frame, or .sframe");
4109 if (Name == ".eh_frame")
4110 EH = true;
4111 else if (Name == ".debug_frame")
4112 Debug = true;
4113 else if (Name == ".sframe")
4114 SFrame = true;
4115 if (parseOptionalToken(AsmToken::EndOfStatement))
4116 break;
4117 if (parseComma())
4118 return true;
4119 }
4120 }
4121 getStreamer().emitCFISections(EH, Debug, SFrame);
4122 return false;
4123}
4124
4125/// parseDirectiveCFIStartProc
4126/// ::= .cfi_startproc [simple]
4127bool AsmParser::parseDirectiveCFIStartProc() {
4128 CFIStartProcLoc = StartTokLoc;
4129
4130 StringRef Simple;
4131 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
4132 if (check(parseIdentifier(Simple) || Simple != "simple",
4133 "unexpected token") ||
4134 parseEOL())
4135 return true;
4136 }
4137
4138 // TODO(kristina): Deal with a corner case of incorrect diagnostic context
4139 // being produced if this directive is emitted as part of preprocessor macro
4140 // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
4141 // Tools like llvm-mc on the other hand are not affected by it, and report
4142 // correct context information.
4143 getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
4144 return false;
4145}
4146
4147/// parseDirectiveCFIEndProc
4148/// ::= .cfi_endproc
4149bool AsmParser::parseDirectiveCFIEndProc() {
4150 CFIStartProcLoc = std::nullopt;
4151
4152 if (parseEOL())
4153 return true;
4154
4155 getStreamer().emitCFIEndProc();
4156 return false;
4157}
4158
4159/// parse register name or number.
4160bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
4161 SMLoc DirectiveLoc) {
4162 MCRegister RegNo;
4163
4164 if (getLexer().isNot(AsmToken::Integer)) {
4165 if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc))
4166 return true;
4167 Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
4168 } else
4169 return parseAbsoluteExpression(Register);
4170
4171 return false;
4172}
4173
4174/// parseDirectiveCFIDefCfa
4175/// ::= .cfi_def_cfa register, offset
4176bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
4177 int64_t Register = 0, Offset = 0;
4178 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4179 parseAbsoluteExpression(Offset) || parseEOL())
4180 return true;
4181
4182 getStreamer().emitCFIDefCfa(Register, Offset, DirectiveLoc);
4183 return false;
4184}
4185
4186/// parseDirectiveCFIDefCfaOffset
4187/// ::= .cfi_def_cfa_offset offset
4188bool AsmParser::parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc) {
4189 int64_t Offset = 0;
4190 if (parseAbsoluteExpression(Offset) || parseEOL())
4191 return true;
4192
4193 getStreamer().emitCFIDefCfaOffset(Offset, DirectiveLoc);
4194 return false;
4195}
4196
4197/// parseDirectiveCFIRegister
4198/// ::= .cfi_register register, register
4199bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
4200 int64_t Register1 = 0, Register2 = 0;
4201 if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || parseComma() ||
4202 parseRegisterOrRegisterNumber(Register2, DirectiveLoc) || parseEOL())
4203 return true;
4204
4205 getStreamer().emitCFIRegister(Register1, Register2, DirectiveLoc);
4206 return false;
4207}
4208
4209/// parseDirectiveCFIWindowSave
4210/// ::= .cfi_window_save
4211bool AsmParser::parseDirectiveCFIWindowSave(SMLoc DirectiveLoc) {
4212 if (parseEOL())
4213 return true;
4214 getStreamer().emitCFIWindowSave(DirectiveLoc);
4215 return false;
4216}
4217
4218/// parseDirectiveCFIAdjustCfaOffset
4219/// ::= .cfi_adjust_cfa_offset adjustment
4220bool AsmParser::parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc) {
4221 int64_t Adjustment = 0;
4222 if (parseAbsoluteExpression(Adjustment) || parseEOL())
4223 return true;
4224
4225 getStreamer().emitCFIAdjustCfaOffset(Adjustment, DirectiveLoc);
4226 return false;
4227}
4228
4229/// parseDirectiveCFIDefCfaRegister
4230/// ::= .cfi_def_cfa_register register
4231bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
4232 int64_t Register = 0;
4233 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4234 return true;
4235
4236 getStreamer().emitCFIDefCfaRegister(Register, DirectiveLoc);
4237 return false;
4238}
4239
4240/// parseDirectiveCFILLVMDefAspaceCfa
4241/// ::= .cfi_llvm_def_aspace_cfa register, offset, address_space
4242bool AsmParser::parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc) {
4243 int64_t Register = 0, Offset = 0, AddressSpace = 0;
4244 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4245 parseAbsoluteExpression(Offset) || parseComma() ||
4246 parseAbsoluteExpression(AddressSpace) || parseEOL())
4247 return true;
4248
4249 getStreamer().emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace,
4250 DirectiveLoc);
4251 return false;
4252}
4253
4254/// parseDirectiveCFIOffset
4255/// ::= .cfi_offset register, offset
4256bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
4257 int64_t Register = 0;
4258 int64_t Offset = 0;
4259
4260 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4261 parseAbsoluteExpression(Offset) || parseEOL())
4262 return true;
4263
4264 getStreamer().emitCFIOffset(Register, Offset, DirectiveLoc);
4265 return false;
4266}
4267
4268/// parseDirectiveCFIRelOffset
4269/// ::= .cfi_rel_offset register, offset
4270bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
4271 int64_t Register = 0, Offset = 0;
4272
4273 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4274 parseAbsoluteExpression(Offset) || parseEOL())
4275 return true;
4276
4277 getStreamer().emitCFIRelOffset(Register, Offset, DirectiveLoc);
4278 return false;
4279}
4280
4281static bool isValidEncoding(int64_t Encoding) {
4282 if (Encoding & ~0xff)
4283 return false;
4284
4285 if (Encoding == dwarf::DW_EH_PE_omit)
4286 return true;
4287
4288 const unsigned Format = Encoding & 0xf;
4289 if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
4290 Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
4291 Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
4292 Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
4293 return false;
4294
4295 const unsigned Application = Encoding & 0x70;
4296 if (Application != dwarf::DW_EH_PE_absptr &&
4297 Application != dwarf::DW_EH_PE_pcrel)
4298 return false;
4299
4300 return true;
4301}
4302
4303/// parseDirectiveCFIPersonalityOrLsda
4304/// IsPersonality true for cfi_personality, false for cfi_lsda
4305/// ::= .cfi_personality encoding, [symbol_name]
4306/// ::= .cfi_lsda encoding, [symbol_name]
4307bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
4308 int64_t Encoding = 0;
4309 if (parseAbsoluteExpression(Encoding))
4310 return true;
4311 if (Encoding == dwarf::DW_EH_PE_omit)
4312 return false;
4313
4314 StringRef Name;
4315 if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
4316 parseComma() ||
4317 check(parseIdentifier(Name), "expected identifier in directive") ||
4318 parseEOL())
4319 return true;
4320
4321 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4322
4323 if (IsPersonality)
4324 getStreamer().emitCFIPersonality(Sym, Encoding);
4325 else
4326 getStreamer().emitCFILsda(Sym, Encoding);
4327 return false;
4328}
4329
4330/// parseDirectiveCFIRememberState
4331/// ::= .cfi_remember_state
4332bool AsmParser::parseDirectiveCFIRememberState(SMLoc DirectiveLoc) {
4333 if (parseEOL())
4334 return true;
4335 getStreamer().emitCFIRememberState(DirectiveLoc);
4336 return false;
4337}
4338
4339/// parseDirectiveCFIRestoreState
4340/// ::= .cfi_remember_state
4341bool AsmParser::parseDirectiveCFIRestoreState(SMLoc DirectiveLoc) {
4342 if (parseEOL())
4343 return true;
4344 getStreamer().emitCFIRestoreState(DirectiveLoc);
4345 return false;
4346}
4347
4348/// parseDirectiveCFISameValue
4349/// ::= .cfi_same_value register
4350bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
4351 int64_t Register = 0;
4352
4353 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4354 return true;
4355
4356 getStreamer().emitCFISameValue(Register, DirectiveLoc);
4357 return false;
4358}
4359
4360/// parseDirectiveCFIRestore
4361/// ::= .cfi_restore register
4362bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
4363 int64_t Register = 0;
4364 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4365 return true;
4366
4367 getStreamer().emitCFIRestore(Register, DirectiveLoc);
4368 return false;
4369}
4370
4371/// parseDirectiveCFIEscape
4372/// ::= .cfi_escape expression[,...]
4373bool AsmParser::parseDirectiveCFIEscape(SMLoc DirectiveLoc) {
4374 std::string Values;
4375 int64_t CurrValue;
4376 if (parseAbsoluteExpression(CurrValue))
4377 return true;
4378
4379 Values.push_back((uint8_t)CurrValue);
4380
4381 while (getLexer().is(AsmToken::Comma)) {
4382 Lex();
4383
4384 if (parseAbsoluteExpression(CurrValue))
4385 return true;
4386
4387 Values.push_back((uint8_t)CurrValue);
4388 }
4389
4390 getStreamer().emitCFIEscape(Values, DirectiveLoc);
4391 return false;
4392}
4393
4394/// parseDirectiveCFIReturnColumn
4395/// ::= .cfi_return_column register
4396bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
4397 int64_t Register = 0;
4398 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4399 return true;
4400 getStreamer().emitCFIReturnColumn(Register);
4401 return false;
4402}
4403
4404/// parseDirectiveCFISignalFrame
4405/// ::= .cfi_signal_frame
4406bool AsmParser::parseDirectiveCFISignalFrame(SMLoc DirectiveLoc) {
4407 if (parseEOL())
4408 return true;
4409
4410 getStreamer().emitCFISignalFrame();
4411 return false;
4412}
4413
4414/// parseDirectiveCFIUndefined
4415/// ::= .cfi_undefined register
4416bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
4417 int64_t Register = 0;
4418
4419 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())
4420 return true;
4421
4422 getStreamer().emitCFIUndefined(Register, DirectiveLoc);
4423 return false;
4424}
4425
4426/// parseDirectiveCFILabel
4427/// ::= .cfi_label label
4428bool AsmParser::parseDirectiveCFILabel(SMLoc Loc) {
4429 StringRef Name;
4430 Loc = Lexer.getLoc();
4431 if (parseIdentifier(Name))
4432 return TokError("expected identifier");
4433 if (parseEOL())
4434 return true;
4435 getStreamer().emitCFILabelDirective(Loc, Name);
4436 return false;
4437}
4438
4439/// parseDirectiveCFIValOffset
4440/// ::= .cfi_val_offset register, offset
4441bool AsmParser::parseDirectiveCFIValOffset(SMLoc DirectiveLoc) {
4442 int64_t Register = 0;
4443 int64_t Offset = 0;
4444
4445 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||
4446 parseAbsoluteExpression(Offset) || parseEOL())
4447 return true;
4448
4449 getStreamer().emitCFIValOffset(Register, Offset, DirectiveLoc);
4450 return false;
4451}
4452
4453/// parseDirectiveAltmacro
4454/// ::= .altmacro
4455/// ::= .noaltmacro
4456bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
4457 if (parseEOL())
4458 return true;
4459 AltMacroMode = (Directive == ".altmacro");
4460 return false;
4461}
4462
4463/// parseDirectiveMacrosOnOff
4464/// ::= .macros_on
4465/// ::= .macros_off
4466bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
4467 if (parseEOL())
4468 return true;
4469 setMacrosEnabled(Directive == ".macros_on");
4470 return false;
4471}
4472
4473/// parseDirectiveMacro
4474/// ::= .macro name[,] [parameters]
4475bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
4476 StringRef Name;
4477 if (parseIdentifier(Name))
4478 return TokError("expected identifier in '.macro' directive");
4479
4480 if (getLexer().is(AsmToken::Comma))
4481 Lex();
4482
4484 while (getLexer().isNot(AsmToken::EndOfStatement)) {
4485
4486 if (!Parameters.empty() && Parameters.back().Vararg)
4487 return Error(Lexer.getLoc(), "vararg parameter '" +
4488 Parameters.back().Name +
4489 "' should be the last parameter");
4490
4491 MCAsmMacroParameter Parameter;
4492 if (parseIdentifier(Parameter.Name))
4493 return TokError("expected identifier in '.macro' directive");
4494
4495 // Emit an error if two (or more) named parameters share the same name
4496 for (const MCAsmMacroParameter& CurrParam : Parameters)
4497 if (CurrParam.Name == Parameter.Name)
4498 return TokError("macro '" + Name + "' has multiple parameters"
4499 " named '" + Parameter.Name + "'");
4500
4501 if (Lexer.is(AsmToken::Colon)) {
4502 Lex(); // consume ':'
4503
4504 SMLoc QualLoc;
4505 StringRef Qualifier;
4506
4507 QualLoc = Lexer.getLoc();
4508 if (parseIdentifier(Qualifier))
4509 return Error(QualLoc, "missing parameter qualifier for "
4510 "'" + Parameter.Name + "' in macro '" + Name + "'");
4511
4512 if (Qualifier == "req")
4513 Parameter.Required = true;
4514 else if (Qualifier == "vararg")
4515 Parameter.Vararg = true;
4516 else
4517 return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
4518 "for '" + Parameter.Name + "' in macro '" + Name + "'");
4519 }
4520
4521 if (getLexer().is(AsmToken::Equal)) {
4522 Lex();
4523
4524 SMLoc ParamLoc;
4525
4526 ParamLoc = Lexer.getLoc();
4527 if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
4528 return true;
4529
4530 if (Parameter.Required)
4531 Warning(ParamLoc, "pointless default value for required parameter "
4532 "'" + Parameter.Name + "' in macro '" + Name + "'");
4533 }
4534
4535 Parameters.push_back(std::move(Parameter));
4536
4537 if (getLexer().is(AsmToken::Comma))
4538 Lex();
4539 }
4540
4541 // Eat just the end of statement.
4542 Lexer.Lex();
4543
4544 // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors
4545 AsmToken EndToken, StartToken = getTok();
4546 unsigned MacroDepth = 0;
4547 // Lex the macro definition.
4548 while (true) {
4549 // Ignore Lexing errors in macros.
4550 while (Lexer.is(AsmToken::Error)) {
4551 Lexer.Lex();
4552 }
4553
4554 // Check whether we have reached the end of the file.
4555 if (getLexer().is(AsmToken::Eof))
4556 return Error(DirectiveLoc, "no matching '.endmacro' in definition");
4557
4558 // Otherwise, check whether we have reach the .endmacro or the start of a
4559 // preprocessor line marker.
4560 if (getLexer().is(AsmToken::Identifier)) {
4561 if (getTok().getIdentifier() == ".endm" ||
4562 getTok().getIdentifier() == ".endmacro") {
4563 if (MacroDepth == 0) { // Outermost macro.
4564 EndToken = getTok();
4565 Lexer.Lex();
4566 if (getLexer().isNot(AsmToken::EndOfStatement))
4567 return TokError("unexpected token in '" + EndToken.getIdentifier() +
4568 "' directive");
4569 break;
4570 } else {
4571 // Otherwise we just found the end of an inner macro.
4572 --MacroDepth;
4573 }
4574 } else if (getTok().getIdentifier() == ".macro") {
4575 // We allow nested macros. Those aren't instantiated until the outermost
4576 // macro is expanded so just ignore them for now.
4577 ++MacroDepth;
4578 }
4579 } else if (Lexer.is(AsmToken::HashDirective)) {
4580 (void)parseCppHashLineFilenameComment(getLexer().getLoc());
4581 }
4582
4583 // Otherwise, scan til the end of the statement.
4584 eatToEndOfStatement();
4585 }
4586
4587 if (getContext().lookupMacro(Name)) {
4588 return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
4589 }
4590
4591 const char *BodyStart = StartToken.getLoc().getPointer();
4592 const char *BodyEnd = EndToken.getLoc().getPointer();
4593 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4594 checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
4595 MCAsmMacro Macro(Name, Body, std::move(Parameters));
4596 DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
4597 Macro.dump());
4598 getContext().defineMacro(Name, std::move(Macro));
4599 return false;
4600}
4601
4602/// checkForBadMacro
4603///
4604/// With the support added for named parameters there may be code out there that
4605/// is transitioning from positional parameters. In versions of gas that did
4606/// not support named parameters they would be ignored on the macro definition.
4607/// But to support both styles of parameters this is not possible so if a macro
4608/// definition has named parameters but does not use them and has what appears
4609/// to be positional parameters, strings like $1, $2, ... and $n, then issue a
4610/// warning that the positional parameter found in body which have no effect.
4611/// Hoping the developer will either remove the named parameters from the macro
4612/// definition so the positional parameters get used if that was what was
4613/// intended or change the macro to use the named parameters. It is possible
4614/// this warning will trigger when the none of the named parameters are used
4615/// and the strings like $1 are infact to simply to be passed trough unchanged.
4616void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
4617 StringRef Body,
4618 ArrayRef<MCAsmMacroParameter> Parameters) {
4619 // If this macro is not defined with named parameters the warning we are
4620 // checking for here doesn't apply.
4621 unsigned NParameters = Parameters.size();
4622 if (NParameters == 0)
4623 return;
4624
4625 bool NamedParametersFound = false;
4626 bool PositionalParametersFound = false;
4627
4628 // Look at the body of the macro for use of both the named parameters and what
4629 // are likely to be positional parameters. This is what expandMacro() is
4630 // doing when it finds the parameters in the body.
4631 while (!Body.empty()) {
4632 // Scan for the next possible parameter.
4633 std::size_t End = Body.size(), Pos = 0;
4634 for (; Pos != End; ++Pos) {
4635 // Check for a substitution or escape.
4636 // This macro is defined with parameters, look for \foo, \bar, etc.
4637 if (Body[Pos] == '\\' && Pos + 1 != End)
4638 break;
4639
4640 // This macro should have parameters, but look for $0, $1, ..., $n too.
4641 if (Body[Pos] != '$' || Pos + 1 == End)
4642 continue;
4643 char Next = Body[Pos + 1];
4644 if (Next == '$' || Next == 'n' ||
4645 isdigit(static_cast<unsigned char>(Next)))
4646 break;
4647 }
4648
4649 // Check if we reached the end.
4650 if (Pos == End)
4651 break;
4652
4653 if (Body[Pos] == '$') {
4654 switch (Body[Pos + 1]) {
4655 // $$ => $
4656 case '$':
4657 break;
4658
4659 // $n => number of arguments
4660 case 'n':
4661 PositionalParametersFound = true;
4662 break;
4663
4664 // $[0-9] => argument
4665 default: {
4666 PositionalParametersFound = true;
4667 break;
4668 }
4669 }
4670 Pos += 2;
4671 } else {
4672 unsigned I = Pos + 1;
4673 while (isIdentifierChar(Body[I]) && I + 1 != End)
4674 ++I;
4675
4676 const char *Begin = Body.data() + Pos + 1;
4677 StringRef Argument(Begin, I - (Pos + 1));
4678 unsigned Index = 0;
4679 for (; Index < NParameters; ++Index)
4680 if (Parameters[Index].Name == Argument)
4681 break;
4682
4683 if (Index == NParameters) {
4684 if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
4685 Pos += 3;
4686 else {
4687 Pos = I;
4688 }
4689 } else {
4690 NamedParametersFound = true;
4691 Pos += 1 + Argument.size();
4692 }
4693 }
4694 // Update the scan point.
4695 Body = Body.substr(Pos);
4696 }
4697
4698 if (!NamedParametersFound && PositionalParametersFound)
4699 Warning(DirectiveLoc, "macro defined with named parameters which are not "
4700 "used in macro body, possible positional parameter "
4701 "found in body which will have no effect");
4702}
4703
4704/// parseDirectiveExitMacro
4705/// ::= .exitm
4706bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
4707 if (parseEOL())
4708 return true;
4709
4710 if (!isInsideMacroInstantiation())
4711 return TokError("unexpected '" + Directive + "' in file, "
4712 "no current macro definition");
4713
4714 // Exit all conditionals that are active in the current macro.
4715 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4716 TheCondState = TheCondStack.back();
4717 TheCondStack.pop_back();
4718 }
4719
4720 handleMacroExit();
4721 return false;
4722}
4723
4724/// parseDirectiveEndMacro
4725/// ::= .endm
4726/// ::= .endmacro
4727bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
4728 if (getLexer().isNot(AsmToken::EndOfStatement))
4729 return TokError("unexpected token in '" + Directive + "' directive");
4730
4731 // If we are inside a macro instantiation, terminate the current
4732 // instantiation.
4733 if (isInsideMacroInstantiation()) {
4734 handleMacroExit();
4735 return false;
4736 }
4737
4738 // Otherwise, this .endmacro is a stray entry in the file; well formed
4739 // .endmacro directives are handled during the macro definition parsing.
4740 return TokError("unexpected '" + Directive + "' in file, "
4741 "no current macro definition");
4742}
4743
4744/// parseDirectivePurgeMacro
4745/// ::= .purgem name
4746bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4747 StringRef Name;
4748 SMLoc Loc;
4749 if (parseTokenLoc(Loc) ||
4750 check(parseIdentifier(Name), Loc,
4751 "expected identifier in '.purgem' directive") ||
4752 parseEOL())
4753 return true;
4754
4755 if (!getContext().lookupMacro(Name))
4756 return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
4757
4758 getContext().undefineMacro(Name);
4759 DEBUG_WITH_TYPE("asm-macros", dbgs()
4760 << "Un-defining macro: " << Name << "\n");
4761 return false;
4762}
4763
4764/// parseDirectiveSpace
4765/// ::= (.skip | .space) expression [ , expression ]
4766bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
4767 SMLoc NumBytesLoc = Lexer.getLoc();
4768 const MCExpr *NumBytes;
4769 if (checkForValidSection() || parseExpression(NumBytes))
4770 return true;
4771
4772 int64_t FillExpr = 0;
4773 if (parseOptionalToken(AsmToken::Comma))
4774 if (parseAbsoluteExpression(FillExpr))
4775 return true;
4776 if (parseEOL())
4777 return true;
4778
4779 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
4780 getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
4781
4782 return false;
4783}
4784
4785/// parseDirectiveDCB
4786/// ::= .dcb.{b, l, w} expression, expression
4787bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
4788 SMLoc NumValuesLoc = Lexer.getLoc();
4789 int64_t NumValues;
4790 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4791 return true;
4792
4793 if (NumValues < 0) {
4794 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4795 return false;
4796 }
4797
4798 if (parseComma())
4799 return true;
4800
4801 const MCExpr *Value;
4802 SMLoc ExprLoc = getLexer().getLoc();
4803 if (parseExpression(Value))
4804 return true;
4805
4806 // Special case constant expressions to match code generator.
4807 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
4808 assert(Size <= 8 && "Invalid size");
4809 uint64_t IntValue = MCE->getValue();
4810 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
4811 return Error(ExprLoc, "literal value out of range for directive");
4812 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4813 getStreamer().emitIntValue(IntValue, Size);
4814 } else {
4815 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4816 getStreamer().emitValue(Value, Size, ExprLoc);
4817 }
4818
4819 return parseEOL();
4820}
4821
4822/// parseDirectiveRealDCB
4823/// ::= .dcb.{d, s} expression, expression
4824bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {
4825 SMLoc NumValuesLoc = Lexer.getLoc();
4826 int64_t NumValues;
4827 if (checkForValidSection() || parseAbsoluteExpression(NumValues))
4828 return true;
4829
4830 if (NumValues < 0) {
4831 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4832 return false;
4833 }
4834
4835 if (parseComma())
4836 return true;
4837
4838 APInt AsInt;
4839 if (parseRealValue(Semantics, AsInt) || parseEOL())
4840 return true;
4841
4842 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4843 getStreamer().emitIntValue(AsInt.getLimitedValue(),
4844 AsInt.getBitWidth() / 8);
4845
4846 return false;
4847}
4848
4849/// parseDirectiveDS
4850/// ::= .ds.{b, d, l, p, s, w, x} expression
4851bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {
4852 SMLoc NumValuesLoc = Lexer.getLoc();
4853 int64_t NumValues;
4854 if (checkForValidSection() || parseAbsoluteExpression(NumValues) ||
4855 parseEOL())
4856 return true;
4857
4858 if (NumValues < 0) {
4859 Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
4860 return false;
4861 }
4862
4863 for (uint64_t i = 0, e = NumValues; i != e; ++i)
4864 getStreamer().emitFill(Size, 0);
4865
4866 return false;
4867}
4868
4869/// parseDirectiveLEB128
4870/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
4871bool AsmParser::parseDirectiveLEB128(bool Signed) {
4872 if (checkForValidSection())
4873 return true;
4874
4875 auto parseOp = [&]() -> bool {
4876 const MCExpr *Value;
4877 if (parseExpression(Value))
4878 return true;
4879 if (Signed)
4880 getStreamer().emitSLEB128Value(Value);
4881 else
4882 getStreamer().emitULEB128Value(Value);
4883 return false;
4884 };
4885
4886 return parseMany(parseOp);
4887}
4888
4889/// parseDirectiveSymbolAttribute
4890/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
4891bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
4892 auto parseOp = [&]() -> bool {
4893 StringRef Name;
4894 SMLoc Loc = getTok().getLoc();
4895 if (parseIdentifier(Name))
4896 return Error(Loc, "expected identifier");
4897
4898 if (discardLTOSymbol(Name))
4899 return false;
4900
4901 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4902
4903 // Assembler local symbols don't make any sense here, except for directives
4904 // that the symbol should be tagged.
4905 if (Sym->isTemporary() && Attr != MCSA_Memtag)
4906 return Error(Loc, "non-local symbol required");
4907
4908 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4909 return Error(Loc, "unable to emit symbol attribute");
4910 return false;
4911 };
4912
4913 return parseMany(parseOp);
4914}
4915
4916/// parseDirectiveComm
4917/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
4918bool AsmParser::parseDirectiveComm(bool IsLocal) {
4919 if (checkForValidSection())
4920 return true;
4921
4922 SMLoc IDLoc = getLexer().getLoc();
4923 StringRef Name;
4924 if (parseIdentifier(Name))
4925 return TokError("expected identifier in directive");
4926
4927 // Handle the identifier as the key symbol.
4928 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4929
4930 if (parseComma())
4931 return true;
4932
4933 int64_t Size;
4934 SMLoc SizeLoc = getLexer().getLoc();
4935 if (parseAbsoluteExpression(Size))
4936 return true;
4937
4938 int64_t Pow2Alignment = 0;
4939 SMLoc Pow2AlignmentLoc;
4940 if (getLexer().is(AsmToken::Comma)) {
4941 Lex();
4942 Pow2AlignmentLoc = getLexer().getLoc();
4943 if (parseAbsoluteExpression(Pow2Alignment))
4944 return true;
4945
4947 if (IsLocal && LCOMM == LCOMM::NoAlignment)
4948 return Error(Pow2AlignmentLoc, "alignment not supported on this target");
4949
4950 // If this target takes alignments in bytes (not log) validate and convert.
4951 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4952 (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
4953 if (!isPowerOf2_64(Pow2Alignment))
4954 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
4955 Pow2Alignment = Log2_64(Pow2Alignment);
4956 }
4957 }
4958
4959 if (parseEOL())
4960 return true;
4961
4962 // NOTE: a size of zero for a .comm should create a undefined symbol
4963 // but a size of .lcomm creates a bss symbol of size zero.
4964 if (Size < 0)
4965 return Error(SizeLoc, "size must be non-negative");
4966
4967 Sym->redefineIfPossible();
4968 if (!Sym->isUndefined())
4969 return Error(IDLoc, "invalid symbol redefinition");
4970
4971 // Create the Symbol as a common or local common with Size and Pow2Alignment
4972 if (IsLocal) {
4973 getStreamer().emitLocalCommonSymbol(Sym, Size,
4974 Align(1ULL << Pow2Alignment));
4975 return false;
4976 }
4977
4978 getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));
4979 return false;
4980}
4981
4982/// parseDirectiveAbort
4983/// ::= .abort [... message ...]
4984bool AsmParser::parseDirectiveAbort(SMLoc DirectiveLoc) {
4985 StringRef Str = parseStringToEndOfStatement();
4986 if (parseEOL())
4987 return true;
4988
4989 if (Str.empty())
4990 return Error(DirectiveLoc, ".abort detected. Assembly stopping");
4991
4992 // FIXME: Actually abort assembly here.
4993 return Error(DirectiveLoc,
4994 ".abort '" + Str + "' detected. Assembly stopping");
4995}
4996
4997/// parseDirectiveInclude
4998/// ::= .include "filename"
4999bool AsmParser::parseDirectiveInclude() {
5000 // Allow the strings to have escaped octal character sequence.
5001 std::string Filename;
5002 SMLoc IncludeLoc = getTok().getLoc();
5003
5004 if (check(getTok().isNot(AsmToken::String),
5005 "expected string in '.include' directive") ||
5006 parseEscapedString(Filename) ||
5007 check(getTok().isNot(AsmToken::EndOfStatement),
5008 "unexpected token in '.include' directive") ||
5009 // Attempt to switch the lexer to the included file before consuming the
5010 // end of statement to avoid losing it when we switch.
5011 check(enterIncludeFile(Filename), IncludeLoc,
5012 "Could not find include file '" + Filename + "'"))
5013 return true;
5014
5015 return false;
5016}
5017
5018/// parseDirectiveIncbin
5019/// ::= .incbin "filename" [ , skip [ , count ] ]
5020bool AsmParser::parseDirectiveIncbin() {
5021 // Allow the strings to have escaped octal character sequence.
5022 std::string Filename;
5023 SMLoc IncbinLoc = getTok().getLoc();
5024 if (check(getTok().isNot(AsmToken::String),
5025 "expected string in '.incbin' directive") ||
5026 parseEscapedString(Filename))
5027 return true;
5028
5029 int64_t Skip = 0;
5030 const MCExpr *Count = nullptr;
5031 SMLoc SkipLoc, CountLoc;
5032 if (parseOptionalToken(AsmToken::Comma)) {
5033 // The skip expression can be omitted while specifying the count, e.g:
5034 // .incbin "filename",,4
5035 if (getTok().isNot(AsmToken::Comma)) {
5036 if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))
5037 return true;
5038 }
5039 if (parseOptionalToken(AsmToken::Comma)) {
5040 CountLoc = getTok().getLoc();
5041 if (parseExpression(Count))
5042 return true;
5043 }
5044 }
5045
5046 if (parseEOL())
5047 return true;
5048
5049 if (check(Skip < 0, SkipLoc, "skip is negative"))
5050 return true;
5051
5052 // Attempt to process the included file.
5053 if (processIncbinFile(Filename, Skip, Count, CountLoc))
5054 return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
5055 return false;
5056}
5057
5058/// parseDirectiveIf
5059/// ::= .if{,eq,ge,gt,le,lt,ne} expression
5060bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
5061 TheCondStack.push_back(TheCondState);
5062 TheCondState.TheCond = AsmCond::IfCond;
5063 if (TheCondState.Ignore) {
5064 eatToEndOfStatement();
5065 } else {
5066 int64_t ExprValue;
5067 if (parseAbsoluteExpression(ExprValue) || parseEOL())
5068 return true;
5069
5070 switch (DirKind) {
5071 default:
5072 llvm_unreachable("unsupported directive");
5073 case DK_IF:
5074 case DK_IFNE:
5075 break;
5076 case DK_IFEQ:
5077 ExprValue = ExprValue == 0;
5078 break;
5079 case DK_IFGE:
5080 ExprValue = ExprValue >= 0;
5081 break;
5082 case DK_IFGT:
5083 ExprValue = ExprValue > 0;
5084 break;
5085 case DK_IFLE:
5086 ExprValue = ExprValue <= 0;
5087 break;
5088 case DK_IFLT:
5089 ExprValue = ExprValue < 0;
5090 break;
5091 }
5092
5093 TheCondState.CondMet = ExprValue;
5094 TheCondState.Ignore = !TheCondState.CondMet;
5095 }
5096
5097 return false;
5098}
5099
5100/// parseDirectiveIfb
5101/// ::= .ifb string
5102bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
5103 TheCondStack.push_back(TheCondState);
5104 TheCondState.TheCond = AsmCond::IfCond;
5105
5106 if (TheCondState.Ignore) {
5107 eatToEndOfStatement();
5108 } else {
5109 StringRef Str = parseStringToEndOfStatement();
5110
5111 if (parseEOL())
5112 return true;
5113
5114 TheCondState.CondMet = ExpectBlank == Str.empty();
5115 TheCondState.Ignore = !TheCondState.CondMet;
5116 }
5117
5118 return false;
5119}
5120
5121/// parseDirectiveIfc
5122/// ::= .ifc string1, string2
5123/// ::= .ifnc string1, string2
5124bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
5125 TheCondStack.push_back(TheCondState);
5126 TheCondState.TheCond = AsmCond::IfCond;
5127
5128 if (TheCondState.Ignore) {
5129 eatToEndOfStatement();
5130 } else {
5131 StringRef Str1 = parseStringToComma();
5132
5133 if (parseComma())
5134 return true;
5135
5136 StringRef Str2 = parseStringToEndOfStatement();
5137
5138 if (parseEOL())
5139 return true;
5140
5141 TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
5142 TheCondState.Ignore = !TheCondState.CondMet;
5143 }
5144
5145 return false;
5146}
5147
5148/// parseDirectiveIfeqs
5149/// ::= .ifeqs string1, string2
5150bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
5151 TheCondStack.push_back(TheCondState);
5152 TheCondState.TheCond = AsmCond::IfCond;
5153
5154 if (TheCondState.Ignore) {
5155 eatToEndOfStatement();
5156 } else {
5157 if (Lexer.isNot(AsmToken::String)) {
5158 if (ExpectEqual)
5159 return TokError("expected string parameter for '.ifeqs' directive");
5160 return TokError("expected string parameter for '.ifnes' directive");
5161 }
5162
5163 StringRef String1 = getTok().getStringContents();
5164 Lex();
5165
5166 if (Lexer.isNot(AsmToken::Comma)) {
5167 if (ExpectEqual)
5168 return TokError(
5169 "expected comma after first string for '.ifeqs' directive");
5170 return TokError(
5171 "expected comma after first string for '.ifnes' directive");
5172 }
5173
5174 Lex();
5175
5176 if (Lexer.isNot(AsmToken::String)) {
5177 if (ExpectEqual)
5178 return TokError("expected string parameter for '.ifeqs' directive");
5179 return TokError("expected string parameter for '.ifnes' directive");
5180 }
5181
5182 StringRef String2 = getTok().getStringContents();
5183 Lex();
5184
5185 TheCondState.CondMet = ExpectEqual == (String1 == String2);
5186 TheCondState.Ignore = !TheCondState.CondMet;
5187 }
5188
5189 return false;
5190}
5191
5192/// parseDirectiveIfdef
5193/// ::= .ifdef symbol
5194bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
5195 StringRef Name;
5196 TheCondStack.push_back(TheCondState);
5197 TheCondState.TheCond = AsmCond::IfCond;
5198
5199 if (TheCondState.Ignore) {
5200 eatToEndOfStatement();
5201 } else {
5202 if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
5203 parseEOL())
5204 return true;
5205
5206 MCSymbol *Sym = getContext().lookupSymbol(Name);
5207
5208 if (expect_defined)
5209 TheCondState.CondMet = (Sym && !Sym->isUndefined());
5210 else
5211 TheCondState.CondMet = (!Sym || Sym->isUndefined());
5212 TheCondState.Ignore = !TheCondState.CondMet;
5213 }
5214
5215 return false;
5216}
5217
5218/// parseDirectiveElseIf
5219/// ::= .elseif expression
5220bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
5221 if (TheCondState.TheCond != AsmCond::IfCond &&
5222 TheCondState.TheCond != AsmCond::ElseIfCond)
5223 return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
5224 " .if or an .elseif");
5225 TheCondState.TheCond = AsmCond::ElseIfCond;
5226
5227 bool LastIgnoreState = false;
5228 if (!TheCondStack.empty())
5229 LastIgnoreState = TheCondStack.back().Ignore;
5230 if (LastIgnoreState || TheCondState.CondMet) {
5231 TheCondState.Ignore = true;
5232 eatToEndOfStatement();
5233 } else {
5234 int64_t ExprValue;
5235 if (parseAbsoluteExpression(ExprValue))
5236 return true;
5237
5238 if (parseEOL())
5239 return true;
5240
5241 TheCondState.CondMet = ExprValue;
5242 TheCondState.Ignore = !TheCondState.CondMet;
5243 }
5244
5245 return false;
5246}
5247
5248/// parseDirectiveElse
5249/// ::= .else
5250bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
5251 if (parseEOL())
5252 return true;
5253
5254 if (TheCondState.TheCond != AsmCond::IfCond &&
5255 TheCondState.TheCond != AsmCond::ElseIfCond)
5256 return Error(DirectiveLoc, "Encountered a .else that doesn't follow "
5257 " an .if or an .elseif");
5258 TheCondState.TheCond = AsmCond::ElseCond;
5259 bool LastIgnoreState = false;
5260 if (!TheCondStack.empty())
5261 LastIgnoreState = TheCondStack.back().Ignore;
5262 if (LastIgnoreState || TheCondState.CondMet)
5263 TheCondState.Ignore = true;
5264 else
5265 TheCondState.Ignore = false;
5266
5267 return false;
5268}
5269
5270/// parseDirectiveEnd
5271/// ::= .end
5272bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5273 if (parseEOL())
5274 return true;
5275
5276 while (Lexer.isNot(AsmToken::Eof))
5277 Lexer.Lex();
5278
5279 return false;
5280}
5281
5282/// parseDirectiveError
5283/// ::= .err
5284/// ::= .error [string]
5285bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
5286 if (!TheCondStack.empty()) {
5287 if (TheCondStack.back().Ignore) {
5288 eatToEndOfStatement();
5289 return false;
5290 }
5291 }
5292
5293 if (!WithMessage)
5294 return Error(L, ".err encountered");
5295
5296 StringRef Message = ".error directive invoked in source file";
5297 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5298 if (Lexer.isNot(AsmToken::String))
5299 return TokError(".error argument must be a string");
5300
5301 Message = getTok().getStringContents();
5302 Lex();
5303 }
5304
5305 return Error(L, Message);
5306}
5307
5308/// parseDirectiveWarning
5309/// ::= .warning [string]
5310bool AsmParser::parseDirectiveWarning(SMLoc L) {
5311 if (!TheCondStack.empty()) {
5312 if (TheCondStack.back().Ignore) {
5313 eatToEndOfStatement();
5314 return false;
5315 }
5316 }
5317
5318 StringRef Message = ".warning directive invoked in source file";
5319
5320 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
5321 if (Lexer.isNot(AsmToken::String))
5322 return TokError(".warning argument must be a string");
5323
5324 Message = getTok().getStringContents();
5325 Lex();
5326 if (parseEOL())
5327 return true;
5328 }
5329
5330 return Warning(L, Message);
5331}
5332
5333/// parseDirectiveEndIf
5334/// ::= .endif
5335bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5336 if (parseEOL())
5337 return true;
5338
5339 if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
5340 return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
5341 "an .if or .else");
5342 if (!TheCondStack.empty()) {
5343 TheCondState = TheCondStack.back();
5344 TheCondStack.pop_back();
5345 }
5346
5347 return false;
5348}
5349
5350void AsmParser::initializeDirectiveKindMap() {
5351 /* Lookup will be done with the directive
5352 * converted to lower case, so all these
5353 * keys should be lower case.
5354 * (target specific directives are handled
5355 * elsewhere)
5356 */
5357 DirectiveKindMap[".set"] = DK_SET;
5358 DirectiveKindMap[".equ"] = DK_EQU;
5359 DirectiveKindMap[".equiv"] = DK_EQUIV;
5360 DirectiveKindMap[".ascii"] = DK_ASCII;
5361 DirectiveKindMap[".asciz"] = DK_ASCIZ;
5362 DirectiveKindMap[".string"] = DK_STRING;
5363 DirectiveKindMap[".byte"] = DK_BYTE;
5364 DirectiveKindMap[".short"] = DK_SHORT;
5365 DirectiveKindMap[".value"] = DK_VALUE;
5366 DirectiveKindMap[".2byte"] = DK_2BYTE;
5367 DirectiveKindMap[".long"] = DK_LONG;
5368 DirectiveKindMap[".int"] = DK_INT;
5369 DirectiveKindMap[".4byte"] = DK_4BYTE;
5370 DirectiveKindMap[".quad"] = DK_QUAD;
5371 DirectiveKindMap[".8byte"] = DK_8BYTE;
5372 DirectiveKindMap[".octa"] = DK_OCTA;
5373 DirectiveKindMap[".single"] = DK_SINGLE;
5374 DirectiveKindMap[".float"] = DK_FLOAT;
5375 DirectiveKindMap[".double"] = DK_DOUBLE;
5376 DirectiveKindMap[".align"] = DK_ALIGN;
5377 DirectiveKindMap[".align32"] = DK_ALIGN32;
5378 DirectiveKindMap[".balign"] = DK_BALIGN;
5379 DirectiveKindMap[".balignw"] = DK_BALIGNW;
5380 DirectiveKindMap[".balignl"] = DK_BALIGNL;
5381 DirectiveKindMap[".p2align"] = DK_P2ALIGN;
5382 DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
5383 DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
5384 DirectiveKindMap[".org"] = DK_ORG;
5385 DirectiveKindMap[".fill"] = DK_FILL;
5386 DirectiveKindMap[".zero"] = DK_ZERO;
5387 DirectiveKindMap[".extern"] = DK_EXTERN;
5388 DirectiveKindMap[".globl"] = DK_GLOBL;
5389 DirectiveKindMap[".global"] = DK_GLOBAL;
5390 DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
5391 DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
5392 DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
5393 DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
5394 DirectiveKindMap[".reference"] = DK_REFERENCE;
5395 DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
5396 DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
5397 DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
5398 DirectiveKindMap[".cold"] = DK_COLD;
5399 DirectiveKindMap[".comm"] = DK_COMM;
5400 DirectiveKindMap[".common"] = DK_COMMON;
5401 DirectiveKindMap[".lcomm"] = DK_LCOMM;
5402 DirectiveKindMap[".abort"] = DK_ABORT;
5403 DirectiveKindMap[".include"] = DK_INCLUDE;
5404 DirectiveKindMap[".incbin"] = DK_INCBIN;
5405 DirectiveKindMap[".code16"] = DK_CODE16;
5406 DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
5407 DirectiveKindMap[".rept"] = DK_REPT;
5408 DirectiveKindMap[".rep"] = DK_REPT;
5409 DirectiveKindMap[".irp"] = DK_IRP;
5410 DirectiveKindMap[".irpc"] = DK_IRPC;
5411 DirectiveKindMap[".endr"] = DK_ENDR;
5412 DirectiveKindMap[".if"] = DK_IF;
5413 DirectiveKindMap[".ifeq"] = DK_IFEQ;
5414 DirectiveKindMap[".ifge"] = DK_IFGE;
5415 DirectiveKindMap[".ifgt"] = DK_IFGT;
5416 DirectiveKindMap[".ifle"] = DK_IFLE;
5417 DirectiveKindMap[".iflt"] = DK_IFLT;
5418 DirectiveKindMap[".ifne"] = DK_IFNE;
5419 DirectiveKindMap[".ifb"] = DK_IFB;
5420 DirectiveKindMap[".ifnb"] = DK_IFNB;
5421 DirectiveKindMap[".ifc"] = DK_IFC;
5422 DirectiveKindMap[".ifeqs"] = DK_IFEQS;
5423 DirectiveKindMap[".ifnc"] = DK_IFNC;
5424 DirectiveKindMap[".ifnes"] = DK_IFNES;
5425 DirectiveKindMap[".ifdef"] = DK_IFDEF;
5426 DirectiveKindMap[".ifndef"] = DK_IFNDEF;
5427 DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
5428 DirectiveKindMap[".elseif"] = DK_ELSEIF;
5429 DirectiveKindMap[".else"] = DK_ELSE;
5430 DirectiveKindMap[".end"] = DK_END;
5431 DirectiveKindMap[".endif"] = DK_ENDIF;
5432 DirectiveKindMap[".skip"] = DK_SKIP;
5433 DirectiveKindMap[".space"] = DK_SPACE;
5434 DirectiveKindMap[".file"] = DK_FILE;
5435 DirectiveKindMap[".line"] = DK_LINE;
5436 DirectiveKindMap[".loc"] = DK_LOC;
5437 DirectiveKindMap[".loc_label"] = DK_LOC_LABEL;
5438 DirectiveKindMap[".stabs"] = DK_STABS;
5439 DirectiveKindMap[".cv_file"] = DK_CV_FILE;
5440 DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
5441 DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
5442 DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
5443 DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
5444 DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
5445 DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
5446 DirectiveKindMap[".cv_string"] = DK_CV_STRING;
5447 DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
5448 DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
5449 DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
5450 DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
5451 DirectiveKindMap[".sleb128"] = DK_SLEB128;
5452 DirectiveKindMap[".uleb128"] = DK_ULEB128;
5453 DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
5454 DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
5455 DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
5456 DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
5457 DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
5458 DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
5459 DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
5460 DirectiveKindMap[".cfi_llvm_def_aspace_cfa"] = DK_CFI_LLVM_DEF_ASPACE_CFA;
5461 DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
5462 DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
5463 DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
5464 DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
5465 DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
5466 DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
5467 DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
5468 DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
5469 DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
5470 DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
5471 DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
5472 DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
5473 DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
5474 DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
5475 DirectiveKindMap[".cfi_label"] = DK_CFI_LABEL;
5476 DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
5477 DirectiveKindMap[".cfi_mte_tagged_frame"] = DK_CFI_MTE_TAGGED_FRAME;
5478 DirectiveKindMap[".cfi_val_offset"] = DK_CFI_VAL_OFFSET;
5479 DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
5480 DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
5481 DirectiveKindMap[".macro"] = DK_MACRO;
5482 DirectiveKindMap[".exitm"] = DK_EXITM;
5483 DirectiveKindMap[".endm"] = DK_ENDM;
5484 DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
5485 DirectiveKindMap[".purgem"] = DK_PURGEM;
5486 DirectiveKindMap[".err"] = DK_ERR;
5487 DirectiveKindMap[".error"] = DK_ERROR;
5488 DirectiveKindMap[".warning"] = DK_WARNING;
5489 DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
5490 DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
5491 DirectiveKindMap[".reloc"] = DK_RELOC;
5492 DirectiveKindMap[".dc"] = DK_DC;
5493 DirectiveKindMap[".dc.a"] = DK_DC_A;
5494 DirectiveKindMap[".dc.b"] = DK_DC_B;
5495 DirectiveKindMap[".dc.d"] = DK_DC_D;
5496 DirectiveKindMap[".dc.l"] = DK_DC_L;
5497 DirectiveKindMap[".dc.s"] = DK_DC_S;
5498 DirectiveKindMap[".dc.w"] = DK_DC_W;
5499 DirectiveKindMap[".dc.x"] = DK_DC_X;
5500 DirectiveKindMap[".dcb"] = DK_DCB;
5501 DirectiveKindMap[".dcb.b"] = DK_DCB_B;
5502 DirectiveKindMap[".dcb.d"] = DK_DCB_D;
5503 DirectiveKindMap[".dcb.l"] = DK_DCB_L;
5504 DirectiveKindMap[".dcb.s"] = DK_DCB_S;
5505 DirectiveKindMap[".dcb.w"] = DK_DCB_W;
5506 DirectiveKindMap[".dcb.x"] = DK_DCB_X;
5507 DirectiveKindMap[".ds"] = DK_DS;
5508 DirectiveKindMap[".ds.b"] = DK_DS_B;
5509 DirectiveKindMap[".ds.d"] = DK_DS_D;
5510 DirectiveKindMap[".ds.l"] = DK_DS_L;
5511 DirectiveKindMap[".ds.p"] = DK_DS_P;
5512 DirectiveKindMap[".ds.s"] = DK_DS_S;
5513 DirectiveKindMap[".ds.w"] = DK_DS_W;
5514 DirectiveKindMap[".ds.x"] = DK_DS_X;
5515 DirectiveKindMap[".print"] = DK_PRINT;
5516 DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
5517 DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
5518 DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE;
5519 DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD;
5520 DirectiveKindMap[".lto_set_conditional"] = DK_LTO_SET_CONDITIONAL;
5521 DirectiveKindMap[".memtag"] = DK_MEMTAG;
5522}
5523
5524MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5525 AsmToken EndToken, StartToken = getTok();
5526
5527 unsigned NestLevel = 0;
5528 while (true) {
5529 // Check whether we have reached the end of the file.
5530 if (getLexer().is(AsmToken::Eof)) {
5531 printError(DirectiveLoc, "no matching '.endr' in definition");
5532 return nullptr;
5533 }
5534
5535 if (Lexer.is(AsmToken::Identifier)) {
5536 StringRef Ident = getTok().getIdentifier();
5537 if (Ident == ".rep" || Ident == ".rept" || Ident == ".irp" ||
5538 Ident == ".irpc") {
5539 ++NestLevel;
5540 } else if (Ident == ".endr") {
5541 if (NestLevel == 0) {
5542 EndToken = getTok();
5543 Lex();
5544 if (Lexer.is(AsmToken::EndOfStatement))
5545 break;
5546 printError(getTok().getLoc(), "expected newline");
5547 return nullptr;
5548 }
5549 --NestLevel;
5550 }
5551 }
5552
5553 // Otherwise, scan till the end of the statement.
5554 eatToEndOfStatement();
5555 }
5556
5557 const char *BodyStart = StartToken.getLoc().getPointer();
5558 const char *BodyEnd = EndToken.getLoc().getPointer();
5559 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5560
5561 // We Are Anonymous.
5562 MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
5563 return &MacroLikeBodies.back();
5564}
5565
5566void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5567 raw_svector_ostream &OS) {
5568 OS << ".endr\n";
5569
5570 std::unique_ptr<MemoryBuffer> Instantiation =
5571 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
5572
5573 // Create the macro instantiation object and add to the current macro
5574 // instantiation stack.
5575 MacroInstantiation *MI = new MacroInstantiation{
5576 DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
5577 ActiveMacros.push_back(MI);
5578
5579 // Jump to the macro instantiation and prime the lexer.
5580 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
5581 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
5582 Lex();
5583}
5584
5585/// parseDirectiveRept
5586/// ::= .rep | .rept count
5587bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
5588 const MCExpr *CountExpr;
5589 SMLoc CountLoc = getTok().getLoc();
5590 if (parseExpression(CountExpr))
5591 return true;
5592
5593 int64_t Count;
5594 if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
5595 return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
5596 }
5597
5598 if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())
5599 return true;
5600
5601 // Lex the rept definition.
5602 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5603 if (!M)
5604 return true;
5605
5606 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5607 // to hold the macro body with substitutions.
5608 SmallString<256> Buf;
5609 raw_svector_ostream OS(Buf);
5610 while (Count--) {
5611 // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
5612 if (expandMacro(OS, *M, {}, {}, false))
5613 return true;
5614 }
5615 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5616
5617 return false;
5618}
5619
5620/// parseDirectiveIrp
5621/// ::= .irp symbol,values
5622bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
5623 MCAsmMacroParameter Parameter;
5624 MCAsmMacroArguments A;
5625 if (check(parseIdentifier(Parameter.Name),
5626 "expected identifier in '.irp' directive") ||
5627 parseComma() || parseMacroArguments(nullptr, A) || parseEOL())
5628 return true;
5629
5630 // Lex the irp definition.
5631 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5632 if (!M)
5633 return true;
5634
5635 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5636 // to hold the macro body with substitutions.
5637 SmallString<256> Buf;
5638 raw_svector_ostream OS(Buf);
5639
5640 for (const MCAsmMacroArgument &Arg : A) {
5641 // Note that the AtPseudoVariable is enabled for instantiations of .irp.
5642 // This is undocumented, but GAS seems to support it.
5643 if (expandMacro(OS, *M, Parameter, Arg, true))
5644 return true;
5645 }
5646
5647 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5648
5649 return false;
5650}
5651
5652/// parseDirectiveIrpc
5653/// ::= .irpc symbol,values
5654bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
5655 MCAsmMacroParameter Parameter;
5656 MCAsmMacroArguments A;
5657
5658 if (check(parseIdentifier(Parameter.Name),
5659 "expected identifier in '.irpc' directive") ||
5660 parseComma() || parseMacroArguments(nullptr, A))
5661 return true;
5662
5663 if (A.size() != 1 || A.front().size() != 1)
5664 return TokError("unexpected token in '.irpc' directive");
5665 if (parseEOL())
5666 return true;
5667
5668 // Lex the irpc definition.
5669 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5670 if (!M)
5671 return true;
5672
5673 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5674 // to hold the macro body with substitutions.
5675 SmallString<256> Buf;
5676 raw_svector_ostream OS(Buf);
5677
5678 StringRef Values = A[0][0].is(AsmToken::String) ? A[0][0].getStringContents()
5679 : A[0][0].getString();
5680 for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
5681 MCAsmMacroArgument Arg;
5682 Arg.emplace_back(AsmToken::Identifier, Values.substr(I, 1));
5683
5684 // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
5685 // This is undocumented, but GAS seems to support it.
5686 if (expandMacro(OS, *M, Parameter, Arg, true))
5687 return true;
5688 }
5689
5690 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5691
5692 return false;
5693}
5694
5695bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
5696 if (ActiveMacros.empty())
5697 return TokError("unmatched '.endr' directive");
5698
5699 // The only .repl that should get here are the ones created by
5700 // instantiateMacroLikeBody.
5701 assert(getLexer().is(AsmToken::EndOfStatement));
5702
5703 handleMacroExit();
5704 return false;
5705}
5706
5707bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5708 size_t Len) {
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 _emit");
5716 uint64_t IntValue = MCE->getValue();
5717 if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
5718 return Error(ExprLoc, "literal value out of range for directive");
5719
5720 Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
5721 return false;
5722}
5723
5724bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5725 const MCExpr *Value;
5726 SMLoc ExprLoc = getLexer().getLoc();
5727 if (parseExpression(Value))
5728 return true;
5729 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5730 if (!MCE)
5731 return Error(ExprLoc, "unexpected expression in align");
5732 uint64_t IntValue = MCE->getValue();
5733 if (!isPowerOf2_64(IntValue))
5734 return Error(ExprLoc, "literal value not a power of two greater then zero");
5735
5736 Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
5737 return false;
5738}
5739
5740bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
5741 const AsmToken StrTok = getTok();
5742 Lex();
5743 if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
5744 return Error(DirectiveLoc, "expected double quoted string after .print");
5745 if (parseEOL())
5746 return true;
5747 llvm::outs() << StrTok.getStringContents() << '\n';
5748 return false;
5749}
5750
5751bool AsmParser::parseDirectiveAddrsig() {
5752 if (parseEOL())
5753 return true;
5754 getStreamer().emitAddrsig();
5755 return false;
5756}
5757
5758bool AsmParser::parseDirectiveAddrsigSym() {
5759 StringRef Name;
5760 if (check(parseIdentifier(Name), "expected identifier") || parseEOL())
5761 return true;
5762 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5763 getStreamer().emitAddrsigSym(Sym);
5764 return false;
5765}
5766
5767bool AsmParser::parseDirectivePseudoProbe() {
5768 int64_t Guid;
5769 int64_t Index;
5770 int64_t Type;
5771 int64_t Attr;
5772 int64_t Discriminator = 0;
5773 if (parseIntToken(Guid))
5774 return true;
5775 if (parseIntToken(Index))
5776 return true;
5777 if (parseIntToken(Type))
5778 return true;
5779 if (parseIntToken(Attr))
5780 return true;
5781 if (hasDiscriminator(Attr) && parseIntToken(Discriminator))
5782 return true;
5783
5784 // Parse inline stack like @ GUID:11:12 @ GUID:1:11 @ GUID:3:21
5785 MCPseudoProbeInlineStack InlineStack;
5786
5787 while (getLexer().is(AsmToken::At)) {
5788 // eat @
5789 Lex();
5790
5791 int64_t CallerGuid = 0;
5792 if (getLexer().is(AsmToken::Integer)) {
5793 CallerGuid = getTok().getIntVal();
5794 Lex();
5795 }
5796
5797 // eat colon
5798 if (getLexer().is(AsmToken::Colon))
5799 Lex();
5800
5801 int64_t CallerProbeId = 0;
5802 if (getLexer().is(AsmToken::Integer)) {
5803 CallerProbeId = getTok().getIntVal();
5804 Lex();
5805 }
5806
5807 InlineSite Site(CallerGuid, CallerProbeId);
5808 InlineStack.push_back(Site);
5809 }
5810
5811 // Parse function entry name
5812 StringRef FnName;
5813 if (parseIdentifier(FnName))
5814 return Error(getLexer().getLoc(), "expected identifier");
5815 MCSymbol *FnSym = getContext().lookupSymbol(FnName);
5816
5817 if (parseEOL())
5818 return true;
5819
5820 getStreamer().emitPseudoProbe(Guid, Index, Type, Attr, Discriminator,
5821 InlineStack, FnSym);
5822 return false;
5823}
5824
5825/// parseDirectiveLTODiscard
5826/// ::= ".lto_discard" [ identifier ( , identifier )* ]
5827/// The LTO library emits this directive to discard non-prevailing symbols.
5828/// We ignore symbol assignments and attribute changes for the specified
5829/// symbols.
5830bool AsmParser::parseDirectiveLTODiscard() {
5831 auto ParseOp = [&]() -> bool {
5832 StringRef Name;
5833 SMLoc Loc = getTok().getLoc();
5834 if (parseIdentifier(Name))
5835 return Error(Loc, "expected identifier");
5836 LTODiscardSymbols.insert(Name);
5837 return false;
5838 };
5839
5840 LTODiscardSymbols.clear();
5841 return parseMany(ParseOp);
5842}
5843
5844// We are comparing pointers, but the pointers are relative to a single string.
5845// Thus, this should always be deterministic.
5846static int rewritesSort(const AsmRewrite *AsmRewriteA,
5847 const AsmRewrite *AsmRewriteB) {
5848 if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
5849 return -1;
5850 if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
5851 return 1;
5852
5853 // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
5854 // rewrite to the same location. Make sure the SizeDirective rewrite is
5855 // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
5856 // ensures the sort algorithm is stable.
5857 if (AsmRewritePrecedence[AsmRewriteA->Kind] >
5858 AsmRewritePrecedence[AsmRewriteB->Kind])
5859 return -1;
5860
5861 if (AsmRewritePrecedence[AsmRewriteA->Kind] <
5862 AsmRewritePrecedence[AsmRewriteB->Kind])
5863 return 1;
5864 llvm_unreachable("Unstable rewrite sort.");
5865}
5866
5867bool AsmParser::parseMSInlineAsm(
5868 std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,
5869 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5870 SmallVectorImpl<std::string> &Constraints,
5871 SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
5872 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5873 SmallVector<void *, 4> InputDecls;
5874 SmallVector<void *, 4> OutputDecls;
5875 SmallVector<bool, 4> InputDeclsAddressOf;
5876 SmallVector<bool, 4> OutputDeclsAddressOf;
5877 SmallVector<std::string, 4> InputConstraints;
5878 SmallVector<std::string, 4> OutputConstraints;
5879 SmallVector<MCRegister, 4> ClobberRegs;
5880
5881 SmallVector<AsmRewrite, 4> AsmStrRewrites;
5882
5883 // Prime the lexer.
5884 Lex();
5885
5886 // While we have input, parse each statement.
5887 unsigned InputIdx = 0;
5888 unsigned OutputIdx = 0;
5889 while (getLexer().isNot(AsmToken::Eof)) {
5890 // Parse curly braces marking block start/end
5891 if (parseCurlyBlockScope(AsmStrRewrites))
5892 continue;
5893
5894 ParseStatementInfo Info(&AsmStrRewrites);
5895 bool StatementErr = parseStatement(Info, &SI);
5896
5897 if (StatementErr || Info.ParseError) {
5898 // Emit pending errors if any exist.
5899 printPendingErrors();
5900 return true;
5901 }
5902
5903 // No pending error should exist here.
5904 assert(!hasPendingError() && "unexpected error from parseStatement");
5905
5906 if (Info.Opcode == ~0U)
5907 continue;
5908
5909 const MCInstrDesc &Desc = MII->get(Info.Opcode);
5910
5911 // Build the list of clobbers, outputs and inputs.
5912 for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
5913 MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
5914
5915 // Register operand.
5916 if (Operand.isReg() && !Operand.needAddressOf() &&
5917 !getTargetParser().omitRegisterFromClobberLists(Operand.getReg())) {
5918 unsigned NumDefs = Desc.getNumDefs();
5919 // Clobber.
5920 if (NumDefs && Operand.getMCOperandNum() < NumDefs)
5921 ClobberRegs.push_back(Operand.getReg());
5922 continue;
5923 }
5924
5925 // Expr/Input or Output.
5926 StringRef SymName = Operand.getSymName();
5927 if (SymName.empty())
5928 continue;
5929
5930 void *OpDecl = Operand.getOpDecl();
5931 if (!OpDecl)
5932 continue;
5933
5934 StringRef Constraint = Operand.getConstraint();
5935 if (Operand.isImm()) {
5936 // Offset as immediate
5937 if (Operand.isOffsetOfLocal())
5938 Constraint = "r";
5939 else
5940 Constraint = "i";
5941 }
5942
5943 bool isOutput = (i == 1) && Desc.mayStore();
5944 bool Restricted = Operand.isMemUseUpRegs();
5945 SMLoc Start = SMLoc::getFromPointer(SymName.data());
5946 if (isOutput) {
5947 ++InputIdx;
5948 OutputDecls.push_back(OpDecl);
5949 OutputDeclsAddressOf.push_back(Operand.needAddressOf());
5950 OutputConstraints.push_back(("=" + Constraint).str());
5951 AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size(), 0,
5952 Restricted);
5953 } else {
5954 InputDecls.push_back(OpDecl);
5955 InputDeclsAddressOf.push_back(Operand.needAddressOf());
5956 InputConstraints.push_back(Constraint.str());
5957 if (Desc.operands()[i - 1].isBranchTarget())
5958 AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size(), 0,
5959 Restricted);
5960 else
5961 AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size(), 0,
5962 Restricted);
5963 }
5964 }
5965
5966 // Consider implicit defs to be clobbers. Think of cpuid and push.
5967 llvm::append_range(ClobberRegs, Desc.implicit_defs());
5968 }
5969
5970 // Set the number of Outputs and Inputs.
5971 NumOutputs = OutputDecls.size();
5972 NumInputs = InputDecls.size();
5973
5974 // Set the unique clobbers.
5975 array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
5976 ClobberRegs.erase(llvm::unique(ClobberRegs), ClobberRegs.end());
5977 Clobbers.assign(ClobberRegs.size(), std::string());
5978 for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
5979 raw_string_ostream OS(Clobbers[I]);
5980 IP->printRegName(OS, ClobberRegs[I]);
5981 }
5982
5983 // Merge the various outputs and inputs. Output are expected first.
5984 if (NumOutputs || NumInputs) {
5985 unsigned NumExprs = NumOutputs + NumInputs;
5986 OpDecls.resize(NumExprs);
5987 Constraints.resize(NumExprs);
5988 for (unsigned i = 0; i < NumOutputs; ++i) {
5989 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
5990 Constraints[i] = OutputConstraints[i];
5991 }
5992 for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
5993 OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
5994 Constraints[j] = InputConstraints[i];
5995 }
5996 }
5997
5998 // Build the IR assembly string.
5999 std::string AsmStringIR;
6000 raw_string_ostream OS(AsmStringIR);
6001 StringRef ASMString =
6003 const char *AsmStart = ASMString.begin();
6004 const char *AsmEnd = ASMString.end();
6005 array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
6006 for (auto I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {
6007 const AsmRewrite &AR = *I;
6008 // Check if this has already been covered by another rewrite...
6009 if (AR.Done)
6010 continue;
6012
6013 const char *Loc = AR.Loc.getPointer();
6014 assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
6015
6016 // Emit everything up to the immediate/expression.
6017 if (unsigned Len = Loc - AsmStart)
6018 OS << StringRef(AsmStart, Len);
6019
6020 // Skip the original expression.
6021 if (Kind == AOK_Skip) {
6022 AsmStart = Loc + AR.Len;
6023 continue;
6024 }
6025
6026 unsigned AdditionalSkip = 0;
6027 // Rewrite expressions in $N notation.
6028 switch (Kind) {
6029 default:
6030 break;
6031 case AOK_IntelExpr:
6032 assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
6033 if (AR.IntelExp.NeedBracs)
6034 OS << "[";
6035 if (AR.IntelExp.hasBaseReg())
6036 OS << AR.IntelExp.BaseReg;
6037 if (AR.IntelExp.hasIndexReg())
6038 OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
6039 << AR.IntelExp.IndexReg;
6040 if (AR.IntelExp.Scale > 1)
6041 OS << " * $$" << AR.IntelExp.Scale;
6042 if (AR.IntelExp.hasOffset()) {
6043 if (AR.IntelExp.hasRegs())
6044 OS << " + ";
6045 // Fuse this rewrite with a rewrite of the offset name, if present.
6046 StringRef OffsetName = AR.IntelExp.OffsetName;
6047 SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
6048 size_t OffsetLen = OffsetName.size();
6049 auto rewrite_it = std::find_if(
6050 I, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
6051 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6052 (FusingAR.Kind == AOK_Input ||
6053 FusingAR.Kind == AOK_CallInput);
6054 });
6055 if (rewrite_it == AsmStrRewrites.end()) {
6056 OS << "offset " << OffsetName;
6057 } else if (rewrite_it->Kind == AOK_CallInput) {
6058 OS << "${" << InputIdx++ << ":P}";
6059 rewrite_it->Done = true;
6060 } else {
6061 OS << '$' << InputIdx++;
6062 rewrite_it->Done = true;
6063 }
6064 }
6065 if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
6066 OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
6067 if (AR.IntelExp.NeedBracs)
6068 OS << "]";
6069 break;
6070 case AOK_Label:
6071 OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
6072 break;
6073 case AOK_Input:
6074 if (AR.IntelExpRestricted)
6075 OS << "${" << InputIdx++ << ":P}";
6076 else
6077 OS << '$' << InputIdx++;
6078 break;
6079 case AOK_CallInput:
6080 OS << "${" << InputIdx++ << ":P}";
6081 break;
6082 case AOK_Output:
6083 if (AR.IntelExpRestricted)
6084 OS << "${" << OutputIdx++ << ":P}";
6085 else
6086 OS << '$' << OutputIdx++;
6087 break;
6088 case AOK_SizeDirective:
6089 switch (AR.Val) {
6090 default: break;
6091 case 8: OS << "byte ptr "; break;
6092 case 16: OS << "word ptr "; break;
6093 case 32: OS << "dword ptr "; break;
6094 case 64: OS << "qword ptr "; break;
6095 case 80: OS << "xword ptr "; break;
6096 case 128: OS << "xmmword ptr "; break;
6097 case 256: OS << "ymmword ptr "; break;
6098 }
6099 break;
6100 case AOK_Emit:
6101 OS << ".byte";
6102 break;
6103 case AOK_Align: {
6104 // MS alignment directives are measured in bytes. If the native assembler
6105 // measures alignment in bytes, we can pass it straight through.
6106 OS << ".align";
6107 if (getContext().getAsmInfo()->getAlignmentIsInBytes())
6108 break;
6109
6110 // Alignment is in log2 form, so print that instead and skip the original
6111 // immediate.
6112 unsigned Val = AR.Val;
6113 OS << ' ' << Val;
6114 assert(Val < 10 && "Expected alignment less then 2^10.");
6115 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6116 break;
6117 }
6118 case AOK_EVEN:
6119 OS << ".even";
6120 break;
6121 case AOK_EndOfStatement:
6122 OS << "\n\t";
6123 break;
6124 }
6125
6126 // Skip the original expression.
6127 AsmStart = Loc + AR.Len + AdditionalSkip;
6128 }
6129
6130 // Emit the remainder of the asm string.
6131 if (AsmStart != AsmEnd)
6132 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6133
6134 AsmString = std::move(AsmStringIR);
6135 return false;
6136}
6137
6138bool HLASMAsmParser::parseAsHLASMLabel(ParseStatementInfo &Info,
6139 MCAsmParserSemaCallback *SI) {
6140 AsmToken LabelTok = getTok();
6141 SMLoc LabelLoc = LabelTok.getLoc();
6142 StringRef LabelVal;
6143
6144 if (parseIdentifier(LabelVal))
6145 return Error(LabelLoc, "The HLASM Label has to be an Identifier");
6146
6147 // We have validated whether the token is an Identifier.
6148 // Now we have to validate whether the token is a
6149 // valid HLASM Label.
6150 if (!getTargetParser().isLabel(LabelTok) || checkForValidSection())
6151 return true;
6152
6153 // Lex leading spaces to get to the next operand.
6154 lexLeadingSpaces();
6155
6156 // We shouldn't emit the label if there is nothing else after the label.
6157 // i.e asm("<token>\n")
6158 if (getTok().is(AsmToken::EndOfStatement))
6159 return Error(LabelLoc,
6160 "Cannot have just a label for an HLASM inline asm statement");
6161
6162 MCSymbol *Sym = getContext().getOrCreateSymbol(
6163 getContext().getAsmInfo()->isHLASM() ? LabelVal.upper() : LabelVal);
6164
6165 // Emit the label.
6166 Out.emitLabel(Sym, LabelLoc);
6167
6168 // If we are generating dwarf for assembly source files then gather the
6169 // info to make a dwarf label entry for this label if needed.
6170 if (enabledGenDwarfForAssembly())
6171 MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
6172 LabelLoc);
6173
6174 return false;
6175}
6176
6177bool HLASMAsmParser::parseAsMachineInstruction(ParseStatementInfo &Info,
6178 MCAsmParserSemaCallback *SI) {
6179 AsmToken OperationEntryTok = Lexer.getTok();
6180 SMLoc OperationEntryLoc = OperationEntryTok.getLoc();
6181 StringRef OperationEntryVal;
6182
6183 // Attempt to parse the first token as an Identifier
6184 if (parseIdentifier(OperationEntryVal))
6185 return Error(OperationEntryLoc, "unexpected token at start of statement");
6186
6187 // Once we've parsed the operation entry successfully, lex
6188 // any spaces to get to the OperandEntries.
6189 lexLeadingSpaces();
6190
6191 return parseAndMatchAndEmitTargetInstruction(
6192 Info, OperationEntryVal, OperationEntryTok, OperationEntryLoc);
6193}
6194
6195bool HLASMAsmParser::parseStatement(ParseStatementInfo &Info,
6196 MCAsmParserSemaCallback *SI) {
6197 assert(!hasPendingError() && "parseStatement started with pending error");
6198
6199 // Should the first token be interpreted as a HLASM Label.
6200 bool ShouldParseAsHLASMLabel = false;
6201
6202 // If a Name Entry exists, it should occur at the very
6203 // start of the string. In this case, we should parse the
6204 // first non-space token as a Label.
6205 // If the Name entry is missing (i.e. there's some other
6206 // token), then we attempt to parse the first non-space
6207 // token as a Machine Instruction.
6208 if (getTok().isNot(AsmToken::Space))
6209 ShouldParseAsHLASMLabel = true;
6210
6211 // If we have an EndOfStatement (which includes the target's comment
6212 // string) we can appropriately lex it early on)
6213 if (Lexer.is(AsmToken::EndOfStatement)) {
6214 // if this is a line comment we can drop it safely
6215 if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
6216 getTok().getString().front() == '\n')
6217 Out.addBlankLine();
6218 Lex();
6219 return false;
6220 }
6221
6222 // We have established how to parse the inline asm statement.
6223 // Now we can safely lex any leading spaces to get to the
6224 // first token.
6225 lexLeadingSpaces();
6226
6227 // If we see a new line or carriage return as the first operand,
6228 // after lexing leading spaces, emit the new line and lex the
6229 // EndOfStatement token.
6230 if (Lexer.is(AsmToken::EndOfStatement)) {
6231 if (getTok().getString().front() == '\n' ||
6232 getTok().getString().front() == '\r') {
6233 Out.addBlankLine();
6234 Lex();
6235 return false;
6236 }
6237 }
6238
6239 // Handle the label first if we have to before processing the rest
6240 // of the tokens as a machine instruction.
6241 if (ShouldParseAsHLASMLabel) {
6242 // If there were any errors while handling and emitting the label,
6243 // early return.
6244 if (parseAsHLASMLabel(Info, SI)) {
6245 // If we know we've failed in parsing, simply eat until end of the
6246 // statement. This ensures that we don't process any other statements.
6247 eatToEndOfStatement();
6248 return true;
6249 }
6250 }
6251
6252 return parseAsMachineInstruction(Info, SI);
6253}
6254
6255namespace llvm {
6256namespace MCParserUtils {
6257
6258bool parseAssignmentExpression(StringRef Name, bool allow_redef,
6259 MCAsmParser &Parser, MCSymbol *&Sym,
6260 const MCExpr *&Value) {
6261
6262 // FIXME: Use better location, we should use proper tokens.
6263 SMLoc EqualLoc = Parser.getTok().getLoc();
6264 if (Parser.parseExpression(Value))
6265 return Parser.TokError("missing expression");
6266 if (Parser.parseEOL())
6267 return true;
6268 // Relocation specifiers are not permitted. For now, handle just
6269 // MCSymbolRefExpr.
6270 if (auto *S = dyn_cast<MCSymbolRefExpr>(Value); S && S->getSpecifier())
6271 return Parser.Error(
6272 EqualLoc, "relocation specifier not permitted in symbol equating");
6273
6274 // Validate that the LHS is allowed to be a variable (either it has not been
6275 // used as a symbol, or it is an absolute symbol).
6276 Sym = Parser.getContext().lookupSymbol(Name);
6277 if (Sym) {
6278 if ((Sym->isVariable() || Sym->isDefined()) &&
6279 (!allow_redef || !Sym->isRedefinable()))
6280 return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
6281 // If the symbol is redefinable, clone it and update the symbol table
6282 // to the new symbol. Existing references to the original symbol remain
6283 // unchanged.
6284 if (Sym->isRedefinable())
6285 Sym = Parser.getContext().cloneSymbol(*Sym);
6286 } else if (Name == ".") {
6287 Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
6288 return false;
6289 } else
6290 Sym = Parser.getContext().getOrCreateSymbol(Name);
6291
6292 Sym->setRedefinable(allow_redef);
6293
6294 return false;
6295}
6296
6297} // end namespace MCParserUtils
6298} // end namespace llvm
6299
6300/// Create an MCAsmParser instance.
6302 MCStreamer &Out, const MCAsmInfo &MAI,
6303 unsigned CB) {
6304 if (C.getTargetTriple().isSystemZ() && C.getTargetTriple().isOSzOS())
6305 return new HLASMAsmParser(SM, C, Out, MAI, CB);
6306
6307 return new AsmParser(SM, C, Out, MAI, CB);
6308}
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:77
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.
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
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:1685
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:2138
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:2078
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:342
MCAsmParserExtension * createXCOFFAsmParser()
SourceMgr SrcMgr
Definition Error.cpp:24
MCAsmParserExtension * createGOFFAsmParser()
auto reverse(ContainerTy &&C)
Definition STLExtras.h:420
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:1956
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:1612
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