Bug Summary

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