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