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