Bug Summary

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