Bug Summary

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