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