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