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