Bug Summary

File:llvm/lib/MC/MCParser/MasmParser.cpp
Warning:line 2777, column 7
Value stored to 'IdentifierPos' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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