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