Bug Summary

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